Skip to content

Commit e56b544

Browse files
Grand.Web.Store - Product attributes/Product specifications per store (#604)
1 parent 00a8dff commit e56b544

37 files changed

+2274
-71
lines changed

src/Business/Grand.Business.Catalog/Services/Products/ProductAttributeService.cs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Grand.Domain.Catalog;
55
using Grand.Infrastructure.Caching;
66
using Grand.Infrastructure.Caching.Constants;
7+
using Grand.Infrastructure.Configuration;
78
using Grand.Infrastructure.Extensions;
89
using MediatR;
910

@@ -42,7 +43,7 @@ public ProductAttributeService(ICacheBase cacheBase,
4243
private readonly IRepository<Product> _productRepository;
4344
private readonly IMediator _mediator;
4445
private readonly ICacheBase _cacheBase;
45-
46+
4647
#endregion
4748

4849
#region Methods
@@ -52,20 +53,31 @@ public ProductAttributeService(ICacheBase cacheBase,
5253
/// <summary>
5354
/// Gets all product attributes
5455
/// </summary>
56+
/// <param name="storeId">Store ident</param>
5557
/// <param name="pageIndex">Page index</param>
5658
/// <param name="pageSize">Page size</param>
5759
/// <returns>Product attributes</returns>
58-
public virtual async Task<IPagedList<ProductAttribute>> GetAllProductAttributes(int pageIndex = 0,
60+
public virtual async Task<IPagedList<ProductAttribute>> GetAllProductAttributes(string storeId = "", int pageIndex = 0,
5961
int pageSize = int.MaxValue)
6062
{
61-
var key = string.Format(CacheKey.PRODUCTATTRIBUTES_ALL_KEY, pageIndex, pageSize);
63+
var key = string.Format(CacheKey.PRODUCTATTRIBUTES_ALL_KEY, storeId, pageIndex, pageSize);
6264
return await _cacheBase.GetAsync(key, () =>
6365
{
6466
var query = from pa in _productAttributeRepository.Table
65-
orderby pa.Name
6667
select pa;
68+
69+
if (!string.IsNullOrEmpty(storeId))
70+
//Limited to stores rules
71+
query = from p in query
72+
where !p.LimitedToStores || p.Stores.Contains(storeId)
73+
select p;
74+
75+
query = query.OrderBy(pa => pa.Name);
76+
6777
return Task.FromResult(new PagedList<ProductAttribute>(query, pageIndex, pageSize));
6878
});
79+
80+
6981
}
7082

7183
/// <summary>

src/Business/Grand.Business.Catalog/Services/Products/ProductService.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ public virtual async Task<IPagedList<Product>> GetProductsByDiscount(string disc
150150
int pageSize = int.MaxValue)
151151
{
152152
var query = from c in _productRepository.Table
153-
where c.AppliedDiscounts.Any(x => x == discountId)
154-
select c;
153+
where c.AppliedDiscounts.Any(x => x == discountId)
154+
select c;
155155

156156
return await PagedList<Product>.Create(query, pageIndex, pageSize);
157157
}
@@ -422,7 +422,7 @@ public virtual int GetCategoryProductNumber(Customer customer, IList<string> cat
422422
categoryIds.Remove("");
423423

424424
var query = from p in _productRepository.Table
425-
select p;
425+
select p;
426426

427427
query = query.Where(p => p.Published && p.VisibleIndividually);
428428

@@ -435,15 +435,15 @@ public virtual int GetCategoryProductNumber(Customer customer, IList<string> cat
435435
//ACL (access control list)
436436
var allowedCustomerGroupsIds = customer.GetCustomerGroupIds();
437437
query = from p in query
438-
where !p.LimitedToGroups || allowedCustomerGroupsIds.Any(x => p.CustomerGroups.Contains(x))
439-
select p;
438+
where !p.LimitedToGroups || allowedCustomerGroupsIds.Any(x => p.CustomerGroups.Contains(x))
439+
select p;
440440
}
441441

442442
if (!string.IsNullOrEmpty(storeId) && !ignoreStore)
443443
//Limited to stores rules
444444
query = from p in query
445-
where !p.LimitedToStores || p.Stores.Contains(storeId)
446-
select p;
445+
where !p.LimitedToStores || p.Stores.Contains(storeId)
446+
select p;
447447

448448
return Convert.ToInt32(query.Count());
449449
}
@@ -561,15 +561,20 @@ public virtual int GetCategoryProductNumber(Customer customer, IList<string> cat
561561
/// Gets products by product attribute
562562
/// </summary>
563563
/// <param name="productAttributeId">Product attribute identifier</param>
564+
/// <param name="storeId">Store ident</param>
564565
/// <param name="pageIndex">Page index</param>
565566
/// <param name="pageSize">Page size</param>
566567
/// <returns>Products</returns>
567-
public virtual async Task<IPagedList<Product>> GetProductsByProductAttributeId(string productAttributeId,
568+
public virtual async Task<IPagedList<Product>> GetProductsByProductAttributeId(string productAttributeId, string storeId = "",
568569
int pageIndex = 0, int pageSize = int.MaxValue)
569570
{
570571
var query = from p in _productRepository.Table
571-
select p;
572+
select p;
572573
query = query.Where(x => x.ProductAttributeMappings.Any(y => y.ProductAttributeId == productAttributeId));
574+
575+
if (!string.IsNullOrEmpty(storeId))
576+
query = query.Where(x => x.LimitedToStores || x.Stores.Contains(storeId));
577+
573578
query = query.OrderBy(x => x.Name);
574579

575580
return await PagedList<Product>.Create(query, pageIndex, pageSize);
@@ -587,7 +592,7 @@ public virtual async Task<IList<Product>> GetAssociatedProducts(string parentGro
587592
string storeId = "", string vendorId = "", bool showHidden = false)
588593
{
589594
var query = from p in _productRepository.Table
590-
select p;
595+
select p;
591596

592597
query = query.Where(p => p.ParentGroupedProductId == parentGroupedProductId);
593598

src/Business/Grand.Business.Catalog/Services/Products/SpecificationAttributeService.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Grand.Domain.Catalog;
55
using Grand.Infrastructure.Caching;
66
using Grand.Infrastructure.Caching.Constants;
7+
using Grand.Infrastructure.Configuration;
78
using Grand.Infrastructure.Extensions;
89
using MediatR;
910

@@ -79,15 +80,24 @@ await Task.FromResult(_specificationAttributeRepository.Table
7980
/// <summary>
8081
/// Gets specification attributes
8182
/// </summary>
83+
/// <param name="storeId">Store ident</param>
8284
/// <param name="pageIndex">Page index</param>
8385
/// <param name="pageSize">Page size</param>
8486
/// <returns>Specification attributes</returns>
85-
public virtual async Task<IPagedList<SpecificationAttribute>> GetSpecificationAttributes(int pageIndex = 0,
87+
public virtual async Task<IPagedList<SpecificationAttribute>> GetSpecificationAttributes(string storeId = "", int pageIndex = 0,
8688
int pageSize = int.MaxValue)
8789
{
8890
var query = from sa in _specificationAttributeRepository.Table
89-
orderby sa.DisplayOrder
90-
select sa;
91+
select sa;
92+
93+
if (!string.IsNullOrEmpty(storeId))
94+
//Limited to stores rules
95+
query = from p in query
96+
where !p.LimitedToStores || p.Stores.Contains(storeId)
97+
select p;
98+
99+
query = query.OrderBy(sa => sa.DisplayOrder).ThenBy(sa => sa.Name);
100+
91101
return await PagedList<SpecificationAttribute>.Create(query, pageIndex, pageSize);
92102
}
93103

src/Business/Grand.Business.Core/Interfaces/Catalog/Products/IProductAttributeService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ public interface IProductAttributeService
1919
/// <summary>
2020
/// Gets all product attributes
2121
/// </summary>
22+
/// <param name="storeId">Store ident</param>
2223
/// <param name="pageIndex">Page index</param>
2324
/// <param name="pageSize">Page size</param>
2425
/// <returns>Product attributes</returns>
25-
Task<IPagedList<ProductAttribute>> GetAllProductAttributes(int pageIndex = 0, int pageSize = int.MaxValue);
26+
Task<IPagedList<ProductAttribute>> GetAllProductAttributes(string storeId = "", int pageIndex = 0, int pageSize = int.MaxValue);
2627

2728
/// <summary>
2829
/// Gets a product attribute

src/Business/Grand.Business.Core/Interfaces/Catalog/Products/IProductService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,11 @@ int GetCategoryProductNumber(Customer customer, IList<string> categoryIds = null
190190
/// Gets products by product attribute
191191
/// </summary>
192192
/// <param name="productAttributeId">Product attribute identifier</param>
193+
/// <param name="storeId">Store ident</param>
193194
/// <param name="pageIndex">Page index</param>
194195
/// <param name="pageSize">Page size</param>
195196
/// <returns>Products</returns>
196-
Task<IPagedList<Product>> GetProductsByProductAttributeId(string productAttributeId,
197+
Task<IPagedList<Product>> GetProductsByProductAttributeId(string productAttributeId, string storeId = "",
197198
int pageIndex = 0, int pageSize = int.MaxValue);
198199

199200
/// <summary>

src/Business/Grand.Business.Core/Interfaces/Catalog/Products/ISpecificationAttributeService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ public interface ISpecificationAttributeService
2727
/// <summary>
2828
/// Gets specification attributes
2929
/// </summary>
30+
/// <param name="storeId">Store ident</param>
3031
/// <param name="pageIndex">Page index</param>
3132
/// <param name="pageSize">Page size</param>
3233
/// <returns>Specification attributes</returns>
33-
Task<IPagedList<SpecificationAttribute>> GetSpecificationAttributes(int pageIndex = 0, int pageSize = int.MaxValue);
34+
Task<IPagedList<SpecificationAttribute>> GetSpecificationAttributes(string storeId = "", int pageIndex = 0, int pageSize = int.MaxValue);
3435

3536
/// <summary>
3637
/// Inserts a specification attribute

src/Core/Grand.Infrastructure/Caching/Constants/ProductAttributeCacheKey.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ public static partial class CacheKey
66
/// Key for caching
77
/// </summary>
88
/// <remarks>
9-
/// {0} : page index
10-
/// {1} : page size
9+
/// {0} : store ID
10+
/// {1} : page index
11+
/// {2} : page size
1112
/// </remarks>
12-
public static string PRODUCTATTRIBUTES_ALL_KEY => "Grand.productattribute.all-{0}-{1}";
13+
public static string PRODUCTATTRIBUTES_ALL_KEY => "Grand.productattribute.all-{0}-{1}-{2}";
1314

1415
/// <summary>
1516
/// Key for caching

src/Modules/Grand.Module.Installer/Extensions/PermissionExtensions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ public static IEnumerable<DefaultPermission> DefaultPermissions()
199199
Permissions = [
200200
StandardPermission.ManageAccessStoreManagerPanel,
201201
StandardPermission.ManageProducts,
202+
StandardPermission.ManageProductAttributes,
203+
StandardPermission.ManageSpecificationAttributes,
202204
StandardPermission.ManageFiles,
203205
StandardPermission.ManagePictures,
204206
StandardPermission.ManageCategories,

src/Web/Grand.Web.Admin/Controllers/ProductAttributeController.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using Grand.Business.Core.Extensions;
22
using Grand.Business.Core.Interfaces.Catalog.Products;
3-
using Grand.Business.Core.Interfaces.Common.Directory;
43
using Grand.Business.Core.Interfaces.Common.Localization;
54
using Grand.Domain.Permissions;
65
using Grand.Domain.Seo;
@@ -25,15 +24,13 @@ public ProductAttributeController(
2524
ILanguageService languageService,
2625
ITranslationService translationService,
2726
IContextAccessor contextAccessor,
28-
IGroupService groupService,
2927
SeoSettings seoSettings)
3028
{
3129
_productService = productService;
3230
_productAttributeService = productAttributeService;
3331
_languageService = languageService;
3432
_translationService = translationService;
3533
_contextAccessor = contextAccessor;
36-
_groupService = groupService;
3734
_seoSettings = seoSettings;
3835
}
3936

@@ -46,7 +43,6 @@ public ProductAttributeController(
4643
private readonly ILanguageService _languageService;
4744
private readonly ITranslationService _translationService;
4845
private readonly IContextAccessor _contextAccessor;
49-
private readonly IGroupService _groupService;
5046
private readonly SeoSettings _seoSettings;
5147

5248
#endregion Fields
@@ -70,8 +66,7 @@ public IActionResult List()
7066
[HttpPost]
7167
public async Task<IActionResult> List(DataSourceRequest command)
7268
{
73-
var productAttributes = await _productAttributeService
74-
.GetAllProductAttributes(command.Page - 1, command.PageSize);
69+
var productAttributes = await _productAttributeService.GetAllProductAttributes(pageIndex: command.Page - 1, pageSize: command.PageSize);
7570
var gridModel = new DataSourceResult {
7671
Data = productAttributes.Select(x => x.ToModel()),
7772
Total = productAttributes.TotalCount
@@ -102,8 +97,6 @@ public async Task<IActionResult> Create(ProductAttributeModel model, bool contin
10297
string.IsNullOrEmpty(productAttribute.SeName) ? productAttribute.Name : productAttribute.SeName,
10398
_seoSettings.ConvertNonWesternChars, _seoSettings.AllowUnicodeCharsInUrls,
10499
_seoSettings.SeoCharConversion);
105-
if (await _groupService.IsStoreManager(_contextAccessor.WorkContext.CurrentCustomer))
106-
model.Stores = [_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId];
107100

108101
await _productAttributeService.InsertProductAttribute(productAttribute);
109102

@@ -154,8 +147,7 @@ public async Task<IActionResult> Edit(ProductAttributeModel model, bool continue
154147
string.IsNullOrEmpty(productAttribute.SeName) ? productAttribute.Name : productAttribute.SeName,
155148
_seoSettings.ConvertNonWesternChars, _seoSettings.AllowUnicodeCharsInUrls,
156149
_seoSettings.SeoCharConversion);
157-
if (await _groupService.IsStoreManager(_contextAccessor.WorkContext.CurrentCustomer))
158-
model.Stores = [_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId];
150+
159151
await _productAttributeService.UpdateProductAttribute(productAttribute);
160152

161153
Success(_translationService.GetResource("Admin.Catalog.Attributes.ProductAttributes.Updated"));
@@ -212,6 +204,7 @@ public async Task<IActionResult> UsedByProducts(DataSourceRequest command, strin
212204
{
213205
var orders = await _productService.GetProductsByProductAttributeId(
214206
productAttributeId,
207+
"",
215208
command.Page - 1,
216209
command.PageSize);
217210
var gridModel = new DataSourceResult {

src/Web/Grand.Web.Admin/Controllers/SpecificationAttributeController.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using Grand.Business.Core.Extensions;
22
using Grand.Business.Core.Interfaces.Catalog.Products;
3-
using Grand.Business.Core.Interfaces.Common.Directory;
43
using Grand.Business.Core.Interfaces.Common.Localization;
54
using Grand.Domain.Permissions;
65
using Grand.Domain.Seo;
@@ -24,15 +23,13 @@ public SpecificationAttributeController(
2423
ILanguageService languageService,
2524
ITranslationService translationService,
2625
IContextAccessor contextAccessor,
27-
IGroupService groupService,
2826
IProductService productService,
2927
SeoSettings seoSettings)
3028
{
3129
_specificationAttributeService = specificationAttributeService;
3230
_languageService = languageService;
3331
_translationService = translationService;
3432
_contextAccessor = contextAccessor;
35-
_groupService = groupService;
3633
_productService = productService;
3734
_seoSettings = seoSettings;
3835
}
@@ -53,10 +50,6 @@ public async Task<IActionResult> UsedByProducts(DataSourceRequest command, strin
5350

5451
var searchStoreId = string.Empty;
5552

56-
//limit for store manager
57-
if (!string.IsNullOrEmpty(_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId))
58-
searchStoreId = _contextAccessor.WorkContext.CurrentCustomer.StaffStoreId;
59-
6053
var specificationProducts = new List<SpecificationAttributeModel.UsedByProductModel>();
6154
var total = 0;
6255

@@ -104,7 +97,6 @@ public async Task<IActionResult> UsedByProducts(DataSourceRequest command, strin
10497
private readonly ILanguageService _languageService;
10598
private readonly ITranslationService _translationService;
10699
private readonly IContextAccessor _contextAccessor;
107-
private readonly IGroupService _groupService;
108100
private readonly SeoSettings _seoSettings;
109101

110102
#endregion Fields
@@ -126,8 +118,7 @@ public IActionResult List()
126118
[PermissionAuthorizeAction(PermissionActionName.List)]
127119
public async Task<IActionResult> List(DataSourceRequest command)
128120
{
129-
var specificationAttributes = await _specificationAttributeService
130-
.GetSpecificationAttributes(command.Page - 1, command.PageSize);
121+
var specificationAttributes = await _specificationAttributeService.GetSpecificationAttributes(pageIndex: command.Page - 1, pageSize: command.PageSize);
131122
var gridModel = new DataSourceResult {
132123
Data = specificationAttributes.Select(x => x.ToModel()),
133124
Total = specificationAttributes.TotalCount
@@ -160,8 +151,7 @@ public async Task<IActionResult> Create(SpecificationAttributeModel model, bool
160151
? specificationAttribute.Name
161152
: specificationAttribute.SeName, _seoSettings.ConvertNonWesternChars,
162153
_seoSettings.AllowUnicodeCharsInUrls, _seoSettings.SeoCharConversion);
163-
if (await _groupService.IsStoreManager(_contextAccessor.WorkContext.CurrentCustomer))
164-
model.Stores = [_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId];
154+
165155
await _specificationAttributeService.InsertSpecificationAttribute(specificationAttribute);
166156

167157
Success(_translationService.GetResource("Admin.Catalog.Attributes.SpecificationAttributes.Added"));
@@ -211,8 +201,7 @@ public async Task<IActionResult> Edit(SpecificationAttributeModel model, bool co
211201
? specificationAttribute.Name
212202
: specificationAttribute.SeName, _seoSettings.ConvertNonWesternChars,
213203
_seoSettings.AllowUnicodeCharsInUrls, _seoSettings.SeoCharConversion);
214-
if (await _groupService.IsStoreManager(_contextAccessor.WorkContext.CurrentCustomer))
215-
model.Stores = [_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId];
204+
216205
await _specificationAttributeService.UpdateSpecificationAttribute(specificationAttribute);
217206

218207
Success(_translationService.GetResource("Admin.Catalog.Attributes.SpecificationAttributes.Updated"));

0 commit comments

Comments
 (0)