-
Notifications
You must be signed in to change notification settings - Fork 0
/
HasOneProductDiscountRequirementRule.cs
213 lines (186 loc) · 8.84 KB
/
HasOneProductDiscountRequirementRule.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Nop.Core;
using Nop.Core.Domain.Orders;
using Nop.Plugin.Opensoftware.DiscountRules.HasOneProduct.Extensions;
using Nop.Services.Configuration;
using Nop.Services.Discounts;
using Nop.Services.Localization;
using Nop.Services.Orders;
using System;
using System.Linq;
namespace Nop.Plugin.Opensoftware.DiscountRules.HasOneProduct
{
public partial class HasOneProductDiscountRequirementRule : BaseOswPlugin, IDiscountRequirementRule
{
#region Fields
private readonly IActionContextAccessor _actionContextAccessor;
private readonly IDiscountService _discountService;
private readonly ILocalizationService _localizationService;
private readonly ISettingService _settingService;
private readonly IShoppingCartService _shoppingCartService;
private readonly IUrlHelperFactory _urlHelperFactory;
private readonly IWebHelper _webHelper;
#endregion
#region Ctor
public HasOneProductDiscountRequirementRule(IActionContextAccessor actionContextAccessor,
IDiscountService discountService,
ILocalizationService localizationService,
ISettingService settingService,
IShoppingCartService shoppingCartService,
IUrlHelperFactory urlHelperFactory,
IWebHelper webHelper)
{
_actionContextAccessor = actionContextAccessor;
_discountService = discountService;
_localizationService = localizationService;
_settingService = settingService;
_shoppingCartService = shoppingCartService;
_urlHelperFactory = urlHelperFactory;
_webHelper = webHelper;
}
#endregion
#region Methods
/// <summary>
/// Check discount requirement
/// </summary>
/// <param name="request">Object that contains all information required to check the requirement (Current customer, discount, etc)</param>
/// <returns>Result</returns>
public DiscountRequirementValidationResult CheckRequirement(DiscountRequirementValidationRequest request)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
//invalid by default
var result = new DiscountRequirementValidationResult();
//try to get saved restricted product identifiers
var restrictedProductIds = _settingService.GetSettingByKey<string>(SettingExtensions.FormatSettingName(request.DiscountRequirementId));
if (string.IsNullOrWhiteSpace(restrictedProductIds))
{
//valid
result.IsValid = true;
return result;
}
if (request.Customer == null)
return result;
//we support three ways of specifying products:
//1. The comma-separated list of product identifiers (e.g. 77, 123, 156).
//2. The comma-separated list of product identifiers with quantities.
// {Product ID}:{Quantity}. For example, 77:1, 123:2, 156:3
//3. The comma-separated list of product identifiers with quantity range.
// {Product ID}:{Min quantity}-{Max quantity}. For example, 77:1-3, 123:2-5, 156:3-8
var restrictedProducts = restrictedProductIds.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();
if (!restrictedProducts.Any())
return result;
//group products in the cart by product ID
//it could be the same product with distinct product attributes
//that's why we get the total quantity of this product
var cart = _shoppingCartService.GetShoppingCart(customer: request.Customer, shoppingCartType: ShoppingCartType.ShoppingCart, storeId: request.Store.Id)
.GroupBy(sci => sci.ProductId)
.Select(g => new { ProductId = g.Key, TotalQuantity = g.Sum(x => x.Quantity) });
//process
var found = false;
foreach (var restrictedProduct in restrictedProducts)
{
if (string.IsNullOrWhiteSpace(restrictedProduct))
continue;
foreach (var sci in cart)
{
if (restrictedProduct.Contains(":"))
{
if (restrictedProduct.Contains("-"))
{
//the third way (the quantity rage specified)
//{Product ID}:{Min quantity}-{Max quantity}. For example, 77:1-3, 123:2-5, 156:3-8
if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[0], out var restrictedProductId))
//parsing error; exit;
return result;
if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[1].Split(new[] { '-' })[0], out var quantityMin))
//parsing error; exit;
return result;
if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[1].Split(new[] { '-' })[1], out var quantityMax))
//parsing error; exit;
return result;
if (sci.ProductId == restrictedProductId && quantityMin <= sci.TotalQuantity && sci.TotalQuantity <= quantityMax)
{
found = true;
break;
}
}
else
{
//the second way (the quantity specified)
//{Product ID}:{Quantity}. For example, 77:1, 123:2, 156:3
if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[0], out var restrictedProductId))
//parsing error; exit;
return result;
if (!int.TryParse(restrictedProduct.Split(new[] { ':' })[1], out var quantity))
//parsing error; exit;
return result;
if (sci.ProductId == restrictedProductId && sci.TotalQuantity == quantity)
{
found = true;
break;
}
}
}
else
{
//the first way (the quantity is not specified)
if (int.TryParse(restrictedProduct, out var restrictedProductId))
{
if (sci.ProductId == restrictedProductId)
{
found = true;
break;
}
}
}
}
if (found)
{
break;
}
}
if (found)
{
//valid
result.IsValid = true;
return result;
}
return result;
}
/// <summary>
/// Get URL for rule configuration
/// </summary>
/// <param name="discountId">Discount identifier</param>
/// <param name="discountRequirementId">Discount requirement identifier (if editing)</param>
/// <returns>URL</returns>
public string GetConfigurationUrl(int discountId, int? discountRequirementId)
{
var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext);
return urlHelper.Action("Configure", "DiscountRulesHasOneProduct",
new { discountId = discountId, discountRequirementId = discountRequirementId }, _webHelper.CurrentRequestProtocol);
}
/// <summary>
/// Install the plugin
/// </summary>
public override void Install()
{
base.Install();
}
/// <summary>
/// Uninstall the plugin
/// </summary>
public override void Uninstall()
{
//discount requirements
var discountRequirements = _discountService.GetAllDiscountRequirements()
.Where(discountRequirement => discountRequirement.DiscountRequirementRuleSystemName.Equals(this.PluginDescriptor.SystemName));
foreach (var discountRequirement in discountRequirements)
_discountService.DeleteDiscountRequirement(discountRequirement);
base.Uninstall();
}
#endregion
}
}