diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/FlashSalesOrderCreationAuthorizationHandler.cs b/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/FlashSalesOrderCreationAuthorizationHandler.cs deleted file mode 100644 index 42505195..00000000 --- a/plugins/FlashSales/src/EasyAbp.EShop.Orders.Plugins.FlashSales.Application/EasyAbp/EShop/Orders/Orders/FlashSalesOrderCreationAuthorizationHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Threading.Tasks; -using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; -using EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; -using EasyAbp.EShop.Plugins.FlashSales.Localization; -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Localization; -using Volo.Abp.DependencyInjection; - -namespace EasyAbp.EShop.Orders.Orders; - -public class FlashSalesOrderCreationAuthorizationHandler : OrderCreationAuthorizationHandler -{ - protected IAbpLazyServiceProvider LazyServiceProvider { get; } - protected IStringLocalizer Localizer { get; } - - public FlashSalesOrderCreationAuthorizationHandler( - IAbpLazyServiceProvider lazyServiceProvider, - IStringLocalizer localizer) - { - LazyServiceProvider = lazyServiceProvider; - Localizer = localizer; - } - - protected override async Task HandleOrderCreationAsync(AuthorizationHandlerContext context, - OrderOperationAuthorizationRequirement requirement, OrderCreationResource resource) - { - if (await IsFlashSalesPlanProductSkuAsync(resource)) - { - context.Fail(new AuthorizationFailureReason(this, Localizer["ExistFlashSalesPlanProduct"])); - return; - } - - context.Succeed(requirement); - } - - protected virtual async Task IsFlashSalesPlanProductSkuAsync(OrderCreationResource resource) - { - var flashSalesPlanAppService = LazyServiceProvider.LazyGetRequiredService(); - foreach (var orderLine in resource.Input.OrderLines) - { - var plans = await flashSalesPlanAppService.GetListAsync(new FlashSalesPlanGetListInput() - { - StoreId = resource.Input.StoreId, - ProductId = orderLine.ProductId, - ProductSkuId = orderLine.ProductSkuId - }); - if (plans.Items.Count > 0) - { - return true; - } - } - - return false; - } -} diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateDto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateDto.cs index 45c740bc..c8848d1d 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateDto.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateDto.cs @@ -1,8 +1,21 @@ using System; +using EasyAbp.EShop.Stores.Stores; +using Volo.Abp.Application.Dtos; namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; [Serializable] -public class FlashSalesPlanCreateDto : FlashSalesPlanCreateOrUpdateDtoBase +public class FlashSalesPlanCreateDto : ExtensibleEntityDto, IMultiStore { + public Guid StoreId { get; set; } + + public DateTime BeginTime { get; set; } + + public DateTime EndTime { get; set; } + + public Guid ProductId { get; set; } + + public Guid ProductSkuId { get; set; } + + public bool IsPublished { get; set; } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateOrUpdateDtoBase.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateOrUpdateDtoBase.cs deleted file mode 100644 index 81f44718..00000000 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanCreateOrUpdateDtoBase.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using EasyAbp.EShop.Stores.Stores; -using Volo.Abp.Application.Dtos; - -namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; - -[Serializable] -public abstract class FlashSalesPlanCreateOrUpdateDtoBase : ExtensibleEntityDto, IMultiStore -{ - public Guid StoreId { get; set; } - - public DateTime BeginTime { get; set; } - - public DateTime EndTime { get; set; } - - public Guid ProductId { get; set; } - - public Guid ProductSkuId { get; set; } - - public bool IsPublished { get; set; } -} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanUpdateDto.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanUpdateDto.cs index 4a02dfa7..269fc645 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanUpdateDto.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application.Contracts/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/Dtos/FlashSalesPlanUpdateDto.cs @@ -1,10 +1,21 @@ using System; +using Volo.Abp.Application.Dtos; using Volo.Abp.Domain.Entities; namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans.Dtos; [Serializable] -public class FlashSalesPlanUpdateDto : FlashSalesPlanCreateOrUpdateDtoBase, IHasConcurrencyStamp +public class FlashSalesPlanUpdateDto : ExtensibleEntityDto, IHasConcurrencyStamp { + public DateTime BeginTime { get; set; } + + public DateTime EndTime { get; set; } + + public Guid ProductId { get; set; } + + public Guid ProductSkuId { get; set; } + + public bool IsPublished { get; set; } + public string ConcurrencyStamp { get; set; } } \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/ExistRelatedFlashSalesResultsException.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/ExistRelatedFlashSalesResultsException.cs new file mode 100644 index 00000000..dcf50d5b --- /dev/null +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/ExistRelatedFlashSalesResultsException.cs @@ -0,0 +1,14 @@ +using System; +using System.Runtime.Serialization; +using Volo.Abp; + +namespace EasyAbp.EShop.Plugins.FlashSales.FlashSalesPlans; + +[Serializable] +public class ExistRelatedFlashSalesResultsException : BusinessException +{ + public ExistRelatedFlashSalesResultsException(Guid planId) : base(FlashSalesErrorCodes.ExistRelatedFlashSalesResults) + { + WithData(nameof(planId), planId); + } +} \ No newline at end of file diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanAppService.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanAppService.cs index 4c0687f6..ac8c24f2 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanAppService.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Application/EasyAbp/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlanAppService.cs @@ -88,12 +88,9 @@ public class FlashSalesPlanAppService : await CheckMultiStorePolicyAsync(input.StoreId, CreatePolicyName); var product = await ProductAppService.GetAsync(input.ProductId); - product.GetSkuById(input.ProductSkuId); + var productSku = product.GetSkuById(input.ProductSkuId); - if (product.StoreId != input.StoreId) - { - throw new ProductIsNotInThisStoreException(input.ProductId, input.StoreId); - } + await ValidateCreateOrUpdateProductAsync(input.ProductId, product, input.ProductSkuId, productSku, input.StoreId); var flashSalesPlan = new FlashSalesPlan( GuidGenerator.Create(), @@ -113,20 +110,21 @@ public class FlashSalesPlanAppService : public override async Task UpdateAsync(Guid id, FlashSalesPlanUpdateDto input) { - await CheckMultiStorePolicyAsync(input.StoreId, UpdatePolicyName); - + var flashSalesPlan = await GetEntityByIdAsync(id); var product = await ProductAppService.GetAsync(input.ProductId); - product.GetSkuById(input.ProductSkuId); + var productSku = product.GetSkuById(input.ProductSkuId); - if (product.StoreId != input.StoreId) + await CheckMultiStorePolicyAsync(product.StoreId, UpdatePolicyName); + + await ValidateCreateOrUpdateProductAsync(input.ProductId, product, input.ProductSkuId, productSku, flashSalesPlan.StoreId); + + if (await ExistRelatedFlashSalesResultsAsync(id) && (input.ProductId != flashSalesPlan.ProductId || input.ProductSkuId != flashSalesPlan.ProductSkuId)) { - throw new ProductIsNotInThisStoreException(input.ProductId, input.StoreId); + throw new ExistRelatedFlashSalesResultsException(id); } - var flashSalesPlan = await GetEntityByIdAsync(id); - flashSalesPlan.SetTimeRange(input.BeginTime, input.EndTime); - flashSalesPlan.SetProductSku(input.StoreId, input.ProductId, input.ProductSkuId); + flashSalesPlan.SetProductSku(flashSalesPlan.StoreId, input.ProductId, input.ProductSkuId); flashSalesPlan.SetPublished(input.IsPublished); flashSalesPlan.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); @@ -142,6 +140,11 @@ public class FlashSalesPlanAppService : await CheckMultiStorePolicyAsync(flashSalesPlan.StoreId, DeletePolicyName); + if (await ExistRelatedFlashSalesResultsAsync(id)) + { + throw new ExistRelatedFlashSalesResultsException(id); + } + await FlashSalesPlanRepository.DeleteAsync(flashSalesPlan); } @@ -167,7 +170,7 @@ public class FlashSalesPlanAppService : var product = await ProductAppService.GetAsync(plan.ProductId); var productSku = product.GetSkuById(plan.ProductSkuId); - await CheckPreOrderAsync(plan, product, productSku); + await ValidatePreOrderAsync(plan, product, productSku); await SetCacheHashTokenAsync(plan, product, productSku); } @@ -190,7 +193,7 @@ public class FlashSalesPlanAppService : throw new BusinessException(FlashSalesErrorCodes.PreOrderExpired); } - await CheckPreOrderAsync(plan, product, productSku); + await ValidatePreOrderAsync(plan, product, productSku); } public virtual async Task CreateOrderAsync(Guid id, CreateOrderInput input) @@ -339,7 +342,7 @@ public class FlashSalesPlanAppService : return await FlashSalesResultRepository.InsertAsync(result, autoSave: true); } - protected virtual Task CheckPreOrderAsync(FlashSalesPlanCacheItem plan, ProductDto product, ProductSkuDto productSku) + protected virtual Task ValidatePreOrderAsync(FlashSalesPlanCacheItem plan, ProductDto product, ProductSkuDto productSku) { if (!product.IsPublished) { @@ -368,4 +371,29 @@ public class FlashSalesPlanAppService : return Task.CompletedTask; } + + protected virtual async Task ExistRelatedFlashSalesResultsAsync(Guid planId) + { + return await FlashSalesResultRepository.AnyAsync(x => x.PlanId == planId); + } + + protected virtual Task ValidateCreateOrUpdateProductAsync(Guid productId, ProductDto product, Guid productSkuId, ProductSkuDto productSku, Guid storeId) + { + if (product.StoreId != storeId) + { + throw new ProductIsNotInThisStoreException(productId, storeId); + } + + if (productSku == null) + { + throw new ProductSkuIsNotFoundException(productSkuId); + } + + if (product.InventoryStrategy != InventoryStrategy.FlashSales) + { + throw new UnexpectedInventoryStrategyException(InventoryStrategy.FlashSales); + } + + return Task.CompletedTask; + } } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesErrorCodes.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesErrorCodes.cs index ec85d72c..ba672872 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesErrorCodes.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/FlashSalesErrorCodes.cs @@ -25,4 +25,6 @@ public static class FlashSalesErrorCodes public const string BusyToCreateFlashSaleOrder = $"{Namespace}:{nameof(BusyToCreateFlashSaleOrder)}"; public const string DuplicateFlashSalesOrder = $"{Namespace}:{nameof(DuplicateFlashSalesOrder)}"; + + public const string ExistRelatedFlashSalesResults = $"{Namespace}:{nameof(ExistRelatedFlashSalesResults)}"; } diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/en.json b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/en.json index ff582ce7..c4a32c55 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/en.json +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/en.json @@ -10,9 +10,9 @@ "EasyAbp.EShop.Plugins.FlashSales:PreOrderExpired": "Pre order expired", "EasyAbp.EShop.Plugins.FlashSales:FlashSaleNotStarted": "Flash-sale not started", "EasyAbp.EShop.Plugins.FlashSales:FlashSaleIsOver": "Flash-sale is over", - "EasyAbp.EShop.Plugins.FlashSales:BusyToCreateFlashSaleOrder": "Busy to create flash-sale Order", + "EasyAbp.EShop.Plugins.FlashSales:BusyToCreateFlashSaleOrder": "Busy to create flash-sale order", "EasyAbp.EShop.Plugins.FlashSales:DuplicateFlashSalesOrder": "Duplicate flash-sales order", - "ExistFlashSalesPlanProduct": "Exist unexpected flash-sales plan product", + "EasyAbp.EShop.Plugins.FlashSales:ExistRelatedFlashSalesResults": "Exist Related flash-sales results", "Menu:FlashSalesManagement": "FlashSales Management", "Permission:FlashSalesPlan": "FlashSales Plan", "Permission:Manage": "Manage", diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hans.json b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hans.json index aef15648..8e7293e2 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hans.json +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hans.json @@ -12,7 +12,7 @@ "EasyAbp.EShop.Plugins.FlashSales:FlashSaleIsOver": "闪购已经结束", "EasyAbp.EShop.Plugins.FlashSales:BusyToCreateFlashSaleOrder": "闪购下单繁忙", "EasyAbp.EShop.Plugins.FlashSales:DuplicateFlashSalesOrder": "重复闪购下单", - "ExistFlashSalesPlanProduct": "清單中不允許存在閃購計畫中的產品", + "EasyAbp.EShop.Plugins.FlashSales:ExistRelatedFlashSalesResults": "已存在关联的闪购结果", "Menu:FlashSalesManagement": "闪购", "Permission:FlashSalesPlan": "闪购计划", "Permission:Manage": "管理", diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hant.json b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hant.json index 81f10e24..14084ab1 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hant.json +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Domain.Shared/EasyAbp/EShop/Plugins/FlashSales/Localization/zh-Hant.json @@ -12,7 +12,7 @@ "EasyAbp.EShop.Plugins.FlashSales:FlashSaleIsOver": "閃購已經結束", "EasyAbp.EShop.Plugins.FlashSales:BusyToCreateFlashSaleOrder": "閃購下單繁忙", "EasyAbp.EShop.Plugins.FlashSales:DuplicateFlashSalesOrder": "重複閃購下單", - "ExistFlashSalesPlanProduct": "清单中不允许存在闪购计划中的产品", + "EasyAbp.EShop.Plugins.FlashSales:ExistRelatedFlashSalesResults": "已存在關聯的閃購結果", "Menu:FlashSalesManagement": "閃購管理", "Permission:FlashSalesPlan": "閃購計畫", "Permission:Manage": "管理", diff --git a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/EditFlashSalesPlanViewModel.cs b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/EditFlashSalesPlanViewModel.cs index 73ca7dfe..972d0980 100644 --- a/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/EditFlashSalesPlanViewModel.cs +++ b/plugins/FlashSales/src/EasyAbp.EShop.Plugins.FlashSales.Web/Pages/EShop/Plugins/FlashSales/FlashSalesPlans/FlashSalesPlan/ViewModels/EditFlashSalesPlanViewModel.cs @@ -8,6 +8,8 @@ namespace EasyAbp.EShop.Plugins.FlashSales.Web.Pages.EShop.Plugins.FlashSales.Fl public class EditFlashSalesPlanViewModel : IHasConcurrencyStamp { + [DisabledInput] + [ReadOnlyInput] [Display(Name = "FlashSalesPlanStoreId")] public Guid StoreId { get; set; }