Add store-scoped discount management to Grand.Web.Store#706
Conversation
Co-authored-by: KrzysztofPajak <16772986+KrzysztofPajak@users.noreply.github.com>
Co-authored-by: KrzysztofPajak <16772986+KrzysztofPajak@users.noreply.github.com>
This comment was marked as resolved.
This comment was marked as resolved.
…rollers and views Co-authored-by: KrzysztofPajak <16772986+KrzysztofPajak@users.noreply.github.com>
Co-authored-by: KrzysztofPajak <16772986+KrzysztofPajak@users.noreply.github.com>
Fixed. The root cause was that The fix adds Store-area counterparts throughout:
Commit: the changes span commits ending at the latest push. |
This comment was marked as resolved.
This comment was marked as resolved.
Instead of duplicating all DiscountRules.Standard plugin controllers/views into a Store area, this commit takes a DRY approach: - Add optional `area` parameter to IDiscountRule.GetConfigurationUrl - All 5 providers use the area param to build area-aware URLs - Store DiscountController calls GetConfigurationUrl(..., "Store") directly, no more Admin/->Store/ string replacement - New BaseDiscountRulePluginController: bypasses [AuthorizeAdmin] via ignore:true, so store managers can reach the same Admin-area controllers - Existing Admin controllers now handle both Admin/* and Store/* routes via dual [Route] attributes - Store-manager context (CurrentStoreId) scopes product search in HasOneProduct/HasAllProducts when accessed from the Store area - Delete all Store-area plugin controller/view duplicates - Delete BaseStorePluginController (no longer needed) Co-authored-by: KrzysztofPajak <16772986+KrzysztofPajak@users.noreply.github.com>
Addressed in the latest commit. The approach now avoids all code duplication:
|
…ntProvider Co-authored-by: KrzysztofPajak <16772986+KrzysztofPajak@users.noreply.github.com>
Fixed in the latest commit. The root cause was that class-level The fix:
With this, |
…ementUrlInternal - Remove BuildStoreRequirementUrl from Store DiscountController; replace both calls with _discountViewModelService.GetRequirementUrlInternal which produces /Admin/<rule>/Configure URLs — these already work for store managers because BaseDiscountRulePluginController carries [AuthorizeAdmin(ignore: true)] - Remove Store-specific plugin routes from DiscountRules.Standard EndpointProvider; they were shadowed by the storeareas area route (priority 10) before the plugin routes (priority 0) could match, causing 404 for Store/CustomerGroups/Configure Co-authored-by: KrzysztofPajak <16772986+KrzysztofPajak@users.noreply.github.com>
- Removed `area` parameter from `GetConfigurationUrl` method. - Replaced `Admin` area with custom paths in endpoint routes. - Refactored and renamed discount rule controllers. - Updated `BaseDiscountRulePluginController` for store manager access. - Simplified and standardized views for discount rule configurations. - Added new views for handling configurations and product selection. - Updated `_ViewImports.cshtml` for tag helpers and namespaces. - Introduced new controllers for modular discount rule handling. - Improved JavaScript for AJAX requests and product-friendly names. - Added localization support for views using `LocService`.
Store owners had no way to manage discounts from the store area — only admins could via
Grand.Web.Admin. This adds a full discount CRUD surface toGrand.Web.Storewith all operations scoped to the current store owner's store.Controller (
DiscountController.cs)AccessToEntityByStore(CurrentStoreId)guards on all mutating actionsmodel.Stores = [CurrentStoreId]— store owners cannot assign discounts to other storesIsStoreManagercheck needed — all users in the Store area are implicitly store managersGetDiscountRequirementConfigurationUrlcallsIDiscountRule.GetConfigurationUrl(..., area: "Store")directly, producing area-correct URLs without any string replacementViews (
Areas/Store/Views/Discount/)Grand.Web.AdminwithConstants.AreaStorethroughoutTabInfo— assigned server-side automaticallyCurrentStoreIdDiscount requirement plugin support (
DiscountRules.Standard)IDiscountRule.GetConfigurationUrlgains an optionalarea = "Admin"parameter — providers use it to build area-aware URLs without hardcodingAdmin/BaseDiscountRulePluginControllershared base class with[AuthorizeAdmin(ignore: true)],[Area("Admin")],[AuthorizeMenu]— bypasses the admin-only gate so store managers can reach the same controllers; per-action authorization viaIPermissionServiceis preservedCustomerGroups,HadSpentAmount,ShoppingCartAmount,HasOneProduct,HasAllProducts) now carry dual[Route]attributes (Admin/[controller]/[action]andStore/[controller]/[action]), serving both areas without any view duplicationHasOneProductandHasAllProductscheckCurrentStoreIdand scope product search and available stores to the store manager's store when accessed from the Store areaStore scoping
The list query already filters by
StaffStoreIdinsideDiscountViewModelService.PrepareDiscountModel— no service changes needed._ViewImports.cshtml
Added
@using Grand.Web.AdminShared.Models.Discountsto the Store area view imports.