From d079d89b9fd717e065c766210faa5204bb9f622c Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Thu, 14 Jul 2022 22:37:39 +0800 Subject: [PATCH 01/12] Introduce `IBasketItemProductInfoUpdater` --- EShop.sln | 7 + .../Dtos/ClientSideBasketItemModel.cs | 3 +- .../BasicBasketItemProductInfoUpdater.cs | 52 ++++++++ .../BasketItems/BasketItemAppService.cs | 83 +++++------- .../IBasketItemProductInfoUpdater.cs | 9 ++ .../Baskets/BasketItems/IBasketItem.cs | 3 +- .../BasketItems/IProductUpdateRecorder.cs | 12 -- .../ProductUpdates/IProductUpdateRecorder.cs | 6 + .../ProductUpdateRecorder.cs | 3 +- ...Plugins.Baskets.Booking.Application.csproj | 20 +++ .../BookingBasketItemProductInfoUpdater.cs | 121 ++++++++++++++++++ .../BookingBasketItemUpdatedCacheItem.cs | 6 + ...pPluginsBasketsBookingApplicationModule.cs | 19 +++ .../BookingBasketItemProperties.cs | 20 +++ ...opPluginsBasketsBookingObjectExtensions.cs | 55 ++++++++ .../ObjectExtending/OrderLineExtensions.cs | 97 ++++++++++++++ 16 files changed, 447 insertions(+), 69 deletions(-) create mode 100644 plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs create mode 100644 plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemProductInfoUpdater.cs delete mode 100644 plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductUpdateRecorder.cs create mode 100644 plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/IProductUpdateRecorder.cs rename plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/{BasketItems => ProductUpdates}/ProductUpdateRecorder.cs (95%) create mode 100644 plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp.EShop.Plugins.Baskets.Booking.Application.csproj create mode 100644 plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemProductInfoUpdater.cs create mode 100644 plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemUpdatedCacheItem.cs create mode 100644 plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/EShopPluginsBasketsBookingApplicationModule.cs create mode 100644 plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/BookingBasketItemProperties.cs create mode 100644 plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/EShopPluginsBasketsBookingObjectExtensions.cs create mode 100644 plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/OrderLineExtensions.cs diff --git a/EShop.sln b/EShop.sln index 66339cb1..859398c4 100644 --- a/EShop.sln +++ b/EShop.sln @@ -417,6 +417,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Orders.Bookin EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Payments.Booking.Application", "plugins\Booking\src\EasyAbp.EShop.Payments.Booking.Application\EasyAbp.EShop.Payments.Booking.Application.csproj", "{4480BFAF-C981-4242-A509-EDA6F572E45C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyAbp.EShop.Plugins.Baskets.Booking.Application", "plugins\Booking\src\EasyAbp.EShop.Plugins.Baskets.Booking.Application\EasyAbp.EShop.Plugins.Baskets.Booking.Application.csproj", "{F9FD36E6-0ED0-4649-8E1C-33B2CDE85B14}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1083,6 +1085,10 @@ Global {4480BFAF-C981-4242-A509-EDA6F572E45C}.Debug|Any CPU.Build.0 = Debug|Any CPU {4480BFAF-C981-4242-A509-EDA6F572E45C}.Release|Any CPU.ActiveCfg = Release|Any CPU {4480BFAF-C981-4242-A509-EDA6F572E45C}.Release|Any CPU.Build.0 = Release|Any CPU + {F9FD36E6-0ED0-4649-8E1C-33B2CDE85B14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F9FD36E6-0ED0-4649-8E1C-33B2CDE85B14}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F9FD36E6-0ED0-4649-8E1C-33B2CDE85B14}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F9FD36E6-0ED0-4649-8E1C-33B2CDE85B14}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1291,6 +1297,7 @@ Global {739CAE6A-14E6-44FC-8863-DA905CBD289F} = {7087FDFF-196A-4C9F-8C66-EEBC2C49F2F8} {C0399352-1278-4D91-8D4E-7491FD77C18B} = {A8C4583C-034E-47AF-B7EC-1A34EE288E2F} {4480BFAF-C981-4242-A509-EDA6F572E45C} = {A8C4583C-034E-47AF-B7EC-1A34EE288E2F} + {F9FD36E6-0ED0-4649-8E1C-33B2CDE85B14} = {A8C4583C-034E-47AF-B7EC-1A34EE288E2F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F} diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs index 5bc1688b..2256d63e 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs @@ -1,10 +1,11 @@ using System; using JetBrains.Annotations; +using Volo.Abp.ObjectExtending; namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos; [Serializable] -public class ClientSideBasketItemModel : IBasketItem +public class ClientSideBasketItemModel : ExtensibleObject, IBasketItem { public Guid Id { get; set; } diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs new file mode 100644 index 00000000..d7b619de --- /dev/null +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs @@ -0,0 +1,52 @@ +using System.Threading.Tasks; +using EasyAbp.EShop.Products.Products; +using EasyAbp.EShop.Products.Products.Dtos; +using Volo.Abp.DependencyInjection; + +namespace EasyAbp.EShop.Plugins.Baskets.BasketItems; + +public class BasicBasketItemProductInfoUpdater : IBasketItemProductInfoUpdater, ITransientDependency +{ + protected IProductSkuDescriptionProvider ProductSkuDescriptionProvider { get; } + + public BasicBasketItemProductInfoUpdater(IProductSkuDescriptionProvider productSkuDescriptionProvider) + { + ProductSkuDescriptionProvider = productSkuDescriptionProvider; + } + + public virtual async Task UpdateProductDataAsync(int targetQuantity, IBasketItem item, ProductDto productDto) + { + var productSkuDto = productDto.FindSkuById(item.ProductSkuId); + + if (productSkuDto == null) + { + item.SetIsInvalid(true); + + return; + } + + item.UpdateProductData(targetQuantity, new ProductDataModel + { + MediaResources = productSkuDto.MediaResources ?? productDto.MediaResources, + ProductUniqueName = productDto.UniqueName, + ProductDisplayName = productDto.DisplayName, + SkuName = productSkuDto.Name, + SkuDescription = await ProductSkuDescriptionProvider.GenerateAsync(productDto, productSkuDto), + Currency = productSkuDto.Currency, + UnitPrice = productSkuDto.DiscountedPrice, + TotalPrice = productSkuDto.DiscountedPrice * item.Quantity, + TotalDiscount = (productSkuDto.Price - productSkuDto.DiscountedPrice) * item.Quantity, + Inventory = productSkuDto.Inventory + }); + + if (productDto.InventoryStrategy != InventoryStrategy.NoNeed && targetQuantity > productSkuDto.Inventory) + { + item.SetIsInvalid(true); + } + + if (!productDto.IsPublished) + { + item.SetIsInvalid(true); + } + } +} \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs index 383fe0e0..e8c4420d 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs @@ -11,11 +11,13 @@ using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.Authorization; +using Volo.Abp.ObjectExtending; using Volo.Abp.Users; namespace EasyAbp.EShop.Plugins.Baskets.BasketItems { - public class BasketItemAppService : CrudAppService, + public class BasketItemAppService : CrudAppService, IBasketItemAppService { protected override string GetPolicyName { get; set; } = BasketsPermissions.BasketItem.Default; @@ -27,18 +29,15 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems private readonly IBasketItemRepository _repository; private readonly IProductUpdateRepository _productUpdateRepository; private readonly IProductAppService _productAppService; - private readonly IProductSkuDescriptionProvider _productSkuDescriptionProvider; public BasketItemAppService( IBasketItemRepository repository, IProductUpdateRepository productUpdateRepository, - IProductAppService productAppService, - IProductSkuDescriptionProvider productSkuDescriptionProvider) : base(repository) + IProductAppService productAppService) : base(repository) { _repository = repository; _productUpdateRepository = productUpdateRepository; _productAppService = productAppService; - _productSkuDescriptionProvider = productSkuDescriptionProvider; } public override async Task GetAsync(Guid id) @@ -46,14 +45,14 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems await CheckGetPolicyAsync(); var item = await GetEntityByIdAsync(id); - + if (item.UserId != CurrentUser.GetId() && !await IsCurrentUserManagerAsync()) { throw new AbpAuthorizationException(); } var productUpdate = await _productUpdateRepository.FindAsync(x => x.ProductSkuId == item.ProductSkuId); - + if (productUpdate != null) { var itemUpdateTime = item.LastModificationTime ?? item.CreationTime; @@ -62,9 +61,9 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems if (itemUpdateTime < productUpdateTime) { var productDto = await _productAppService.GetAsync(item.ProductId); - + await UpdateProductDataAsync(item.Quantity, item, productDto); - + await _repository.UpdateAsync(item, true); } } @@ -75,7 +74,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems public override async Task> GetListAsync(GetBasketItemListDto input) { await CheckGetListPolicyAsync(); - + if (input.UserId != CurrentUser.GetId()) { await AuthorizationService.CheckAsync(BasketsPermissions.BasketItem.Manage); @@ -124,49 +123,23 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems await MapToGetListOutputDtosAsync(items) ); } - - protected virtual async Task UpdateProductDataAsync(int quantity, IBasketItem item, ProductDto productDto) + + protected virtual async Task UpdateProductDataAsync(int targetQuantity, IBasketItem item, ProductDto productDto) { item.SetIsInvalid(false); - var productSkuDto = productDto.FindSkuById(item.ProductSkuId); + var updaters = LazyServiceProvider.LazyGetRequiredService>(); - if (productSkuDto == null) + foreach (var updater in updaters) { - item.SetIsInvalid(true); - - return; - } - - if (productDto.InventoryStrategy != InventoryStrategy.NoNeed && quantity > productSkuDto.Inventory) - { - item.SetIsInvalid(true); - } - - item.UpdateProductData(quantity, new ProductDataModel - { - MediaResources = productSkuDto.MediaResources ?? productDto.MediaResources, - ProductUniqueName = productDto.UniqueName, - ProductDisplayName = productDto.DisplayName, - SkuName = productSkuDto.Name, - SkuDescription = await _productSkuDescriptionProvider.GenerateAsync(productDto, productSkuDto), - Currency = productSkuDto.Currency, - UnitPrice = productSkuDto.DiscountedPrice, - TotalPrice = productSkuDto.DiscountedPrice * item.Quantity, - TotalDiscount = (productSkuDto.Price - productSkuDto.DiscountedPrice) * item.Quantity, - Inventory = productSkuDto.Inventory - }); - - if (!productDto.IsPublished) - { - item.SetIsInvalid(true); + await updater.UpdateProductDataAsync(targetQuantity, item, productDto); } } protected override async Task> CreateFilteredQueryAsync(GetBasketItemListDto input) { var userId = input.UserId ?? CurrentUser.GetId(); - + return (await ReadOnlyRepository.GetQueryableAsync()) .Where(item => item.UserId == userId && item.BasketName == input.BasketName); } @@ -190,12 +163,12 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems if (item != null) { await UpdateProductDataAsync(input.Quantity + item.Quantity, item, productDto); - + await Repository.UpdateAsync(item, autoSave: true); return await MapToGetOutputDtoAsync(item); } - + var productSkuDto = productDto.FindSkuById(input.ProductSkuId); if (productSkuDto == null) @@ -205,9 +178,11 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems item = new BasketItem(GuidGenerator.Create(), CurrentTenant.Id, input.BasketName, CurrentUser.GetId(), productDto.StoreId, input.ProductId, input.ProductSkuId); + + input.MapExtraPropertiesTo(item); await UpdateProductDataAsync(input.Quantity, item, productDto); - + await Repository.InsertAsync(item, autoSave: true); return await MapToGetOutputDtoAsync(item); @@ -218,7 +193,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems await CheckUpdatePolicyAsync(); var item = await GetEntityByIdAsync(id); - + if (item.UserId != CurrentUser.GetId() && !await IsCurrentUserManagerAsync()) { throw new AbpAuthorizationException(); @@ -226,8 +201,10 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems var productDto = await _productAppService.GetAsync(item.ProductId); + input.MapExtraPropertiesTo(item); + await UpdateProductDataAsync(input.Quantity, item, productDto); - + await Repository.UpdateAsync(item, autoSave: true); return await MapToGetOutputDtoAsync(item); @@ -243,20 +220,20 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems { throw new AbpAuthorizationException(); } - + await _repository.DeleteAsync(item, true); } public virtual async Task BatchDeleteAsync(IEnumerable ids) { await CheckDeletePolicyAsync(); - + var isCurrentUserManager = await IsCurrentUserManagerAsync(); - + foreach (var id in ids) { var item = await GetEntityByIdAsync(id); - + if (item.UserId != CurrentUser.GetId() && !isCurrentUserManager) { throw new AbpAuthorizationException(); @@ -270,7 +247,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems GenerateClientSideDataInput input) { var itemList = new List(); - + var products = new Dictionary(); foreach (var dto in input.Items) @@ -290,7 +267,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems } var id = dto.Id ?? GuidGenerator.Create(); - + var item = new ClientSideBasketItemModel(id, dto.BasketName, productDto.StoreId, dto.ProductId, dto.ProductSkuId); diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemProductInfoUpdater.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemProductInfoUpdater.cs new file mode 100644 index 00000000..582f6387 --- /dev/null +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemProductInfoUpdater.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; +using EasyAbp.EShop.Products.Products.Dtos; + +namespace EasyAbp.EShop.Plugins.Baskets.BasketItems; + +public interface IBasketItemProductInfoUpdater +{ + Task UpdateProductDataAsync(int targetQuantity, IBasketItem item, ProductDto productDto); +} \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs index bd4c67e7..15d13d5a 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs @@ -1,9 +1,10 @@ using System; using JetBrains.Annotations; +using Volo.Abp.Data; namespace EasyAbp.EShop.Plugins.Baskets.BasketItems; -public interface IBasketItem : IProductData +public interface IBasketItem : IProductData, IHasExtraProperties { Guid Id { get; } diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductUpdateRecorder.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductUpdateRecorder.cs deleted file mode 100644 index 3dfdc29b..00000000 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductUpdateRecorder.cs +++ /dev/null @@ -1,12 +0,0 @@ -using EasyAbp.EShop.Products.ProductInventories; -using EasyAbp.EShop.Products.Products; -using Volo.Abp.Domain.Entities.Events.Distributed; -using Volo.Abp.EventBus.Distributed; - -namespace EasyAbp.EShop.Plugins.Baskets.BasketItems -{ - public interface IProductUpdateRecorder - { - - } -} \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/IProductUpdateRecorder.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/IProductUpdateRecorder.cs new file mode 100644 index 00000000..2ec3e842 --- /dev/null +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/IProductUpdateRecorder.cs @@ -0,0 +1,6 @@ +namespace EasyAbp.EShop.Plugins.Baskets.ProductUpdates; + +public interface IProductUpdateRecorder +{ + +} \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductUpdateRecorder.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/ProductUpdateRecorder.cs similarity index 95% rename from plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductUpdateRecorder.cs rename to plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/ProductUpdateRecorder.cs index 673171ef..c8d577f3 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductUpdateRecorder.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/ProductUpdates/ProductUpdateRecorder.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Threading.Tasks; -using EasyAbp.EShop.Plugins.Baskets.ProductUpdates; using EasyAbp.EShop.Products.ProductInventories; using EasyAbp.EShop.Products.Products; using Volo.Abp.DependencyInjection; @@ -11,7 +10,7 @@ using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; -namespace EasyAbp.EShop.Plugins.Baskets.BasketItems +namespace EasyAbp.EShop.Plugins.Baskets.ProductUpdates { public class ProductUpdateRecorder : IProductUpdateRecorder, diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp.EShop.Plugins.Baskets.Booking.Application.csproj b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp.EShop.Plugins.Baskets.Booking.Application.csproj new file mode 100644 index 00000000..8df05985 --- /dev/null +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp.EShop.Plugins.Baskets.Booking.Application.csproj @@ -0,0 +1,20 @@ + + + + + + net6.0 + + + + + + + + + + + + + + diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemProductInfoUpdater.cs b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemProductInfoUpdater.cs new file mode 100644 index 00000000..b7bd9e6a --- /dev/null +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemProductInfoUpdater.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using EasyAbp.BookingService.AssetOccupancies; +using EasyAbp.BookingService.AssetOccupancies.Dtos; +using EasyAbp.EShop.Plugins.Baskets.BasketItems; +using EasyAbp.EShop.Plugins.Baskets.Booking.ObjectExtending; +using EasyAbp.EShop.Plugins.Booking.BookingProductGroupDefinitions; +using EasyAbp.EShop.Products.Products.Dtos; +using Microsoft.Extensions.Caching.Distributed; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Users; + +namespace EasyAbp.EShop.Plugins.Baskets.Booking.BasketItems; + +public class BookingBasketItemProductInfoUpdater : IBasketItemProductInfoUpdater, ITransientDependency +{ + protected List ProductGroupNames { get; set; } + protected bool? AllowedToUpdate { get; set; } + + protected ICurrentUser CurrentUser { get; } + protected IDistributedCache Cache { get; } + protected IAssetOccupancyAppService AssetOccupancyAppService { get; } + protected IBookingProductGroupDefinitionAppService DefinitionAppService { get; } + + public BookingBasketItemProductInfoUpdater( + ICurrentUser currentUser, + IDistributedCache cache, + IAssetOccupancyAppService assetOccupancyAppService, + IBookingProductGroupDefinitionAppService definitionAppService) + { + CurrentUser = currentUser; + Cache = cache; + AssetOccupancyAppService = assetOccupancyAppService; + DefinitionAppService = definitionAppService; + } + + public virtual async Task UpdateProductDataAsync(int targetQuantity, IBasketItem item, ProductDto productDto) + { + if (!await IsAllowedToUpdateAsync(item, productDto) || + !await IsBookingProductGroupAsync(productDto.ProductGroupName)) + { + return; + } + + var assetId = item.FindBookingAssetId(); + var assetCategoryId = item.FindBookingAssetCategoryId(); + + if (assetId is not null) + { + try + { + await AssetOccupancyAppService.CheckCreateAsync(new CreateAssetOccupancyDto + { + AssetId = assetId.Value, + Volume = item.GetBookingVolume(), + Date = item.GetBookingDate(), + StartingTime = item.GetBookingStartingTime(), + Duration = item.GetBookingDuration() + }); + } + catch + { + item.SetIsInvalid(true); + } + } + else + { + try + { + await AssetOccupancyAppService.CheckCreateByCategoryIdAsync(new CreateAssetOccupancyByCategoryIdDto + { + AssetCategoryId = assetCategoryId!.Value, + Volume = item.GetBookingVolume(), + Date = item.GetBookingDate(), + StartingTime = item.GetBookingStartingTime(), + Duration = item.GetBookingDuration() + }); + } + catch + { + item.SetIsInvalid(true); + } + } + + } + + protected virtual async Task IsAllowedToUpdateAsync(IBasketItem item, ProductDto productDto) + { + if (AllowedToUpdate.HasValue) + { + return AllowedToUpdate.Value; + } + + var key = GetCacheItemKey(item, productDto); + + AllowedToUpdate = await Cache.GetAsync(key) is null; + + await Cache.SetAsync(key, new BookingBasketItemUpdatedCacheItem(), new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(30) + }); + + return AllowedToUpdate.Value; + } + + protected virtual string GetCacheItemKey(IBasketItem item, ProductDto productDto) + { + return CurrentUser.GetId().ToString(); + } + + protected virtual async Task IsBookingProductGroupAsync(string productGroupName) + { + ProductGroupNames ??= + (await DefinitionAppService.GetListAsync()).Items.Select(x => x.ProductGroupName).ToList(); + + return ProductGroupNames.Contains(productGroupName); + } +} \ No newline at end of file diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemUpdatedCacheItem.cs b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemUpdatedCacheItem.cs new file mode 100644 index 00000000..b1edae3c --- /dev/null +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemUpdatedCacheItem.cs @@ -0,0 +1,6 @@ +namespace EasyAbp.EShop.Plugins.Baskets.Booking.BasketItems; + +public class BookingBasketItemUpdatedCacheItem +{ + +} \ No newline at end of file diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/EShopPluginsBasketsBookingApplicationModule.cs b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/EShopPluginsBasketsBookingApplicationModule.cs new file mode 100644 index 00000000..54b7a9f8 --- /dev/null +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/EShopPluginsBasketsBookingApplicationModule.cs @@ -0,0 +1,19 @@ +using EasyAbp.EShop.Orders; +using EasyAbp.EShop.Plugins.Baskets.Booking.ObjectExtending; +using Volo.Abp.Caching; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.Baskets.Booking; + +[DependsOn( + typeof(AbpCachingModule), + typeof(EShopPluginsBasketsApplicationModule), + typeof(EShopOrdersApplicationContractsModule) +)] +public class EShopPluginsBasketsBookingApplicationModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + EShopPluginsBasketsBookingObjectExtensions.Configure(); + } +} \ No newline at end of file diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/BookingBasketItemProperties.cs b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/BookingBasketItemProperties.cs new file mode 100644 index 00000000..80cb958b --- /dev/null +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/BookingBasketItemProperties.cs @@ -0,0 +1,20 @@ +namespace EasyAbp.EShop.Plugins.Baskets.Booking.ObjectExtending; + +public class BookingBasketItemProperties +{ + public const string BasketItemBookingAssetId = "BookingAssetId"; + + public const string BasketItemBookingAssetCategoryId = "BookingAssetCategoryId"; + + public const string BasketItemBookingPeriodSchemeId = "BookingPeriodSchemeId"; + + public const string BasketItemBookingPeriodId = "BookingPeriodId"; + + public const string BasketItemBookingDate = "BookingDate"; + + public const string BasketItemBookingStartingTime = "BookingStartingTime"; + + public const string BasketItemBookingDuration = "BookingDuration"; + + public const string BasketItemBookingAssetOccupancyId = "BookingAssetOccupancyId"; +} \ No newline at end of file diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/EShopPluginsBasketsBookingObjectExtensions.cs b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/EShopPluginsBasketsBookingObjectExtensions.cs new file mode 100644 index 00000000..ae290a1c --- /dev/null +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/EShopPluginsBasketsBookingObjectExtensions.cs @@ -0,0 +1,55 @@ +using System; +using EasyAbp.EShop.Orders; +using EasyAbp.EShop.Plugins.Baskets.BasketItems; +using EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace EasyAbp.EShop.Plugins.Baskets.Booking.ObjectExtending; + +public static class EShopPluginsBasketsBookingObjectExtensions +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure extension properties to entities or other object types + * defined in the depended modules. + * + * If you are using EF Core and want to map the entity extension properties to new + * table fields in the database, then configure them in the EShopSampleEfCoreEntityExtensionMappings + * + * Example: + * + * ObjectExtensionManager.Instance + * .AddOrUpdateProperty("Title"); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Object-Extensions + */ + + ObjectExtensionManager.Instance + .AddOrUpdate( + new[] + { + typeof(BasketItem), + typeof(BasketItemDto), + typeof(CreateBasketItemDto), + typeof(UpdateBasketItemDto) + }, + config => + { + config.AddOrUpdateProperty(BookingBasketItemProperties.BasketItemBookingAssetId); + config.AddOrUpdateProperty(BookingBasketItemProperties.BasketItemBookingAssetCategoryId); + config.AddOrUpdateProperty(BookingBasketItemProperties.BasketItemBookingPeriodSchemeId); + config.AddOrUpdateProperty(BookingBasketItemProperties.BasketItemBookingPeriodId); + config.AddOrUpdateProperty(BookingBasketItemProperties.BasketItemBookingDate); + config.AddOrUpdateProperty(BookingBasketItemProperties.BasketItemBookingStartingTime); + config.AddOrUpdateProperty(BookingBasketItemProperties.BasketItemBookingDuration); + } + ); + }); + } +} \ No newline at end of file diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/OrderLineExtensions.cs b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/OrderLineExtensions.cs new file mode 100644 index 00000000..d76a2cf9 --- /dev/null +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/ObjectExtending/OrderLineExtensions.cs @@ -0,0 +1,97 @@ +using System; +using EasyAbp.EShop.Orders; +using EasyAbp.EShop.Plugins.Baskets.BasketItems; +using Volo.Abp; +using Volo.Abp.Data; + +namespace EasyAbp.EShop.Plugins.Baskets.Booking.ObjectExtending; + +public static class OrderLineExtensions +{ + public static Guid? FindBookingAssetId(this IBasketItem basketItem) + { + return basketItem.GetProperty(BookingOrderProperties.OrderLineBookingAssetId); + } + + public static Guid GetBookingAssetId(this IBasketItem basketItem) + { + return Check.NotNull(FindBookingAssetId(basketItem), + BookingOrderProperties.OrderLineBookingAssetId)!.Value; + } + + public static Guid? FindBookingAssetCategoryId(this IBasketItem basketItem) + { + return basketItem.GetProperty(BookingOrderProperties.OrderLineBookingAssetCategoryId); + } + + public static Guid GetBookingAssetCategoryId(this IBasketItem basketItem) + { + return Check.NotNull(FindBookingAssetCategoryId(basketItem), + BookingOrderProperties.OrderLineBookingAssetCategoryId)!.Value; + } + + public static Guid? FindBookingPeriodSchemeId(this IBasketItem basketItem) + { + return basketItem.GetProperty(BookingOrderProperties.OrderLineBookingPeriodSchemeId); + } + + public static Guid GetBookingPeriodSchemeId(this IBasketItem basketItem) + { + return Check.NotNull(FindBookingPeriodSchemeId(basketItem), + BookingOrderProperties.OrderLineBookingPeriodSchemeId)!.Value; + } + + public static Guid? FindBookingPeriodId(this IBasketItem basketItem) + { + return basketItem.GetProperty(BookingOrderProperties.OrderLineBookingPeriodId); + } + + public static Guid GetBookingPeriodId(this IBasketItem basketItem) + { + return Check.NotNull(FindBookingPeriodId(basketItem), + BookingOrderProperties.OrderLineBookingPeriodId)!.Value; + } + + public static int? FindBookingVolume(this IBasketItem basketItem) + { + return basketItem.Quantity; + } + + public static int GetBookingVolume(this IBasketItem basketItem) + { + return FindBookingVolume(basketItem)!.Value; + } + + public static DateTime? FindBookingDate(this IBasketItem basketItem) + { + return basketItem.FindDateTimeProperty(BookingOrderProperties.OrderLineBookingDate); + } + + public static DateTime GetBookingDate(this IBasketItem basketItem) + { + return Check.NotNull(FindBookingDate(basketItem), + BookingOrderProperties.OrderLineBookingDate)!.Value; + } + + public static TimeSpan? FindBookingStartingTime(this IBasketItem basketItem) + { + return basketItem.FindTimeSpanProperty(BookingOrderProperties.OrderLineBookingStartingTime); + } + + public static TimeSpan GetBookingStartingTime(this IBasketItem basketItem) + { + return Check.NotNull(FindBookingStartingTime(basketItem), + BookingOrderProperties.OrderLineBookingStartingTime)!.Value; + } + + public static TimeSpan? FindBookingDuration(this IBasketItem basketItem) + { + return basketItem.FindTimeSpanProperty(BookingOrderProperties.OrderLineBookingDuration); + } + + public static TimeSpan GetBookingDuration(this IBasketItem basketItem) + { + return Check.NotNull(FindBookingDuration(basketItem), + BookingOrderProperties.OrderLineBookingDuration)!.Value; + } +} \ No newline at end of file From 2033d854d23b024c2732f523d7c9ac57daecd44c Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Thu, 14 Jul 2022 22:40:25 +0800 Subject: [PATCH 02/12] Create fody files --- .../FodyWeavers.xml | 3 ++ .../FodyWeavers.xsd | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/FodyWeavers.xml create mode 100644 plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/FodyWeavers.xsd diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/FodyWeavers.xml b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/FodyWeavers.xsd b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file From 4ec5f404e004df6cc3affd425367b8b76ab21372 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Fri, 15 Jul 2022 15:05:40 +0800 Subject: [PATCH 03/12] Update README.md of the booking module --- docs/plugins/booking/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plugins/booking/README.md b/docs/plugins/booking/README.md index ebf463d6..ed03f48b 100644 --- a/docs/plugins/booking/README.md +++ b/docs/plugins/booking/README.md @@ -16,7 +16,7 @@ A booking-business plugin for EShop. It extends EShop to use the [EasyAbp.Bookin * EasyAbp.EShop.Orders.Booking.Application (install at EasyAbp.EShop.Orders.Application location) * (Optional) EasyAbp.EShop.Payments.Booking.Application (install at EasyAbp.EShop.Payments.Application location) - * EasyAbp.EShop.Plugins.Booking.Application + * (Optional) EasyAbp.EShop.Plugins.Baskets.Booking.Application (install at EasyAbp.EShop.Plugins.Baskets.Application location) * EasyAbp.EShop.Plugins.Booking.Application * EasyAbp.EShop.Plugins.Booking.Application.Contracts * EasyAbp.EShop.Plugins.Booking.Domain From 987820f9c13c25ab647c53a0f00258113c600523 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Mon, 18 Jul 2022 13:55:07 +0800 Subject: [PATCH 04/12] Refactor `IBasketItemProductInfoUpdater` for anonymous --- .../BasketItems/BasicBasketItemProductInfoUpdater.cs | 12 +++++++++++- .../Baskets/BasketItems/BasketItemAppService.cs | 2 +- .../BasketItems/IBasketItemProductInfoUpdater.cs | 4 +++- .../BookingBasketItemProductInfoUpdater.cs | 8 ++++++-- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs index d7b619de..bebfd596 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs @@ -14,7 +14,17 @@ public class BasicBasketItemProductInfoUpdater : IBasketItemProductInfoUpdater, ProductSkuDescriptionProvider = productSkuDescriptionProvider; } - public virtual async Task UpdateProductDataAsync(int targetQuantity, IBasketItem item, ProductDto productDto) + public virtual Task UpdateForAnonymousAsync(int targetQuantity, IBasketItem item, ProductDto productDto) + { + return InternalUpdateAsync(targetQuantity, item, productDto); + } + + public virtual Task UpdateForIdentifiedAsync(int targetQuantity, IBasketItem item, ProductDto productDto) + { + return InternalUpdateAsync(targetQuantity, item, productDto); + } + + protected virtual async Task InternalUpdateAsync(int targetQuantity, IBasketItem item, ProductDto productDto) { var productSkuDto = productDto.FindSkuById(item.ProductSkuId); diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs index e8c4420d..ffb639e8 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs @@ -132,7 +132,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems foreach (var updater in updaters) { - await updater.UpdateProductDataAsync(targetQuantity, item, productDto); + await updater.UpdateForIdentifiedAsync(targetQuantity, item, productDto); } } diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemProductInfoUpdater.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemProductInfoUpdater.cs index 582f6387..5aa940d3 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemProductInfoUpdater.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemProductInfoUpdater.cs @@ -5,5 +5,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems; public interface IBasketItemProductInfoUpdater { - Task UpdateProductDataAsync(int targetQuantity, IBasketItem item, ProductDto productDto); + Task UpdateForAnonymousAsync(int targetQuantity, IBasketItem item, ProductDto productDto); + + Task UpdateForIdentifiedAsync(int targetQuantity, IBasketItem item, ProductDto productDto); } \ No newline at end of file diff --git a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemProductInfoUpdater.cs b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemProductInfoUpdater.cs index b7bd9e6a..8e13bb28 100644 --- a/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemProductInfoUpdater.cs +++ b/plugins/Booking/src/EasyAbp.EShop.Plugins.Baskets.Booking.Application/EasyAbp/EShop/Plugins/Baskets/Booking/BasketItems/BookingBasketItemProductInfoUpdater.cs @@ -37,7 +37,12 @@ public class BookingBasketItemProductInfoUpdater : IBasketItemProductInfoUpdater DefinitionAppService = definitionAppService; } - public virtual async Task UpdateProductDataAsync(int targetQuantity, IBasketItem item, ProductDto productDto) + public virtual Task UpdateForAnonymousAsync(int targetQuantity, IBasketItem item, ProductDto productDto) + { + return Task.CompletedTask; + } + + public virtual async Task UpdateForIdentifiedAsync(int targetQuantity, IBasketItem item, ProductDto productDto) { if (!await IsAllowedToUpdateAsync(item, productDto) || !await IsBookingProductGroupAsync(productDto.ProductGroupName)) @@ -84,7 +89,6 @@ public class BookingBasketItemProductInfoUpdater : IBasketItemProductInfoUpdater item.SetIsInvalid(true); } } - } protected virtual async Task IsAllowedToUpdateAsync(IBasketItem item, ProductDto productDto) From e986808269d5d4e0a52f827212b98c914aece799 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Mon, 18 Jul 2022 15:26:29 +0800 Subject: [PATCH 05/12] Improve `GetBasketItemListDto` to set the BasketName as "Default" --- .../Plugins/Baskets/BasketItems/Dtos/GetBasketItemListDto.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GetBasketItemListDto.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GetBasketItemListDto.cs index a0610631..185fc31e 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GetBasketItemListDto.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GetBasketItemListDto.cs @@ -1,13 +1,11 @@ using System; -using System.ComponentModel.DataAnnotations; namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos { [Serializable] public class GetBasketItemListDto { - [Required] - public string BasketName { get; set; } + public string BasketName { get; set; } = BasketsConsts.DefaultBasketName; /// /// Specify the basket item owner user ID. Use current user ID if this property is null. From 68af8c0fe3ac3f917cac5fc74f9f4c0d130479a4 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Mon, 18 Jul 2022 20:12:58 +0800 Subject: [PATCH 06/12] Use `UpdateForAnonymousAsync` --- .../Baskets/BasketItems/BasketItemAppService.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs index ffb639e8..f58bbea8 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs @@ -130,9 +130,19 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems var updaters = LazyServiceProvider.LazyGetRequiredService>(); - foreach (var updater in updaters) + if (CurrentUser.IsAuthenticated) { - await updater.UpdateForIdentifiedAsync(targetQuantity, item, productDto); + foreach (var updater in updaters) + { + await updater.UpdateForIdentifiedAsync(targetQuantity, item, productDto); + } + } + else + { + foreach (var updater in updaters) + { + await updater.UpdateForAnonymousAsync(targetQuantity, item, productDto); + } } } From 525f1c415d05e75a43702d0c9b0c4002410b3d9b Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Mon, 18 Jul 2022 22:06:22 +0800 Subject: [PATCH 07/12] Introduce `IOrderAppService.CheckCreateAsync` method --- .../Orders/Dtos/CheckCreateOrderInput.cs | 8 ++ .../Orders/Dtos/CheckCreateOrderResultDto.cs | 11 +++ .../EShop/Orders/Orders/IOrderAppService.cs | 2 + .../EShop/Orders/Orders/OrderAppService.cs | 43 ++++++++-- .../EShop/Orders/Orders/OrderController.cs | 7 ++ .../Orders/OrderAppServiceTests.cs | 83 +++++++++++++++++++ 6 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/CheckCreateOrderInput.cs create mode 100644 modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/CheckCreateOrderResultDto.cs diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/CheckCreateOrderInput.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/CheckCreateOrderInput.cs new file mode 100644 index 00000000..c9b83892 --- /dev/null +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/CheckCreateOrderInput.cs @@ -0,0 +1,8 @@ +using System; + +namespace EasyAbp.EShop.Orders.Orders.Dtos; + +[Serializable] +public class CheckCreateOrderInput : CreateOrderDto +{ +} \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/CheckCreateOrderResultDto.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/CheckCreateOrderResultDto.cs new file mode 100644 index 00000000..f6add213 --- /dev/null +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/Dtos/CheckCreateOrderResultDto.cs @@ -0,0 +1,11 @@ +using System; + +namespace EasyAbp.EShop.Orders.Orders.Dtos; + +[Serializable] +public class CheckCreateOrderResultDto +{ + public bool CanCreate { get; set; } + + public string Reason { get; set; } +} \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/IOrderAppService.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/IOrderAppService.cs index 5c6ae2cc..081c7b0b 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/IOrderAppService.cs +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application.Contracts/EasyAbp/EShop/Orders/Orders/IOrderAppService.cs @@ -19,5 +19,7 @@ namespace EasyAbp.EShop.Orders.Orders Task CancelAsync(Guid id, CancelOrderInput input); Task UpdateStaffRemarkAsync(Guid id, UpdateStaffRemarkInput input); + + Task CheckCreateAsync(CheckCreateOrderInput input); } } \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs index f8759d9a..b2317415 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs @@ -12,6 +12,7 @@ using EasyAbp.EShop.Stores.Stores; using Microsoft.AspNetCore.Authorization; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Uow; using Volo.Abp.Users; namespace EasyAbp.EShop.Orders.Orders @@ -91,7 +92,7 @@ namespace EasyAbp.EShop.Orders.Orders var productDict = await GetProductDictionaryAsync(input.OrderLines.Select(dto => dto.ProductId).ToList()); ThrowIfExistFlashSalesProduct(productDict); - + await AuthorizationService.CheckAsync( new OrderCreationResource { @@ -108,11 +109,12 @@ namespace EasyAbp.EShop.Orders.Orders .Where(x => x.HasValue) .Select(x => x.Value) .ToList(); - + var productDetailDict = await GetProductDetailDictionaryAsync(productDetailIds); // Todo: Can we use IProductDataScopedCache/IProductDetailDataScopedCache instead of productDict/productDetailDict? - var order = await _newOrderGenerator.GenerateAsync(CurrentUser.GetId(), input, productDict, productDetailDict); + var order = await _newOrderGenerator.GenerateAsync(CurrentUser.GetId(), input, productDict, + productDetailDict); await DiscountOrderAsync(order, productDict); @@ -203,11 +205,11 @@ namespace EasyAbp.EShop.Orders.Orders return await MapToGetOutputDtoAsync(order); } - + public virtual async Task CancelAsync(Guid id, CancelOrderInput input) { var order = await GetEntityByIdAsync(id); - + await AuthorizationService.CheckAsync( order, new OrderOperationAuthorizationRequirement(OrderOperation.Cancellation) @@ -225,10 +227,39 @@ namespace EasyAbp.EShop.Orders.Orders await CheckMultiStorePolicyAsync(order.StoreId, OrdersPermissions.Orders.Manage); order.SetStaffRemark(input.StaffRemark); - + await Repository.UpdateAsync(order, true); return await MapToGetOutputDtoAsync(order); } + + public virtual async Task CheckCreateAsync(CheckCreateOrderInput input) + { + var requiresNewUow = !UnitOfWorkManager.Current?.Options.IsTransactional ?? false; + using var uow = UnitOfWorkManager.Begin(new AbpUnitOfWorkOptions(true), requiresNewUow); + + try + { + await CreateAsync(input); + + await uow.RollbackAsync(); + } + catch + { + await uow.RollbackAsync(); + + return new CheckCreateOrderResultDto + { + CanCreate = false, + Reason = "Unknown" // Todo: get failure reason + }; + } + + return new CheckCreateOrderResultDto + { + CanCreate = true, + Reason = null, + }; + } } } \ No newline at end of file diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.HttpApi/EasyAbp/EShop/Orders/Orders/OrderController.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.HttpApi/EasyAbp/EShop/Orders/Orders/OrderController.cs index b109f3af..644e636a 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.HttpApi/EasyAbp/EShop/Orders/Orders/OrderController.cs +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.HttpApi/EasyAbp/EShop/Orders/Orders/OrderController.cs @@ -81,5 +81,12 @@ namespace EasyAbp.EShop.Orders.Orders { return _service.UpdateStaffRemarkAsync(id, input); } + + [HttpPost] + [Route("check-create")] + public virtual Task CheckCreateAsync(CheckCreateOrderInput input) + { + return _service.CheckCreateAsync(input); + } } } diff --git a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs index bc99825f..a2f4896b 100644 --- a/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs +++ b/modules/EasyAbp.EShop.Orders/test/EasyAbp.EShop.Orders.Application.Tests/Orders/OrderAppServiceTests.cs @@ -13,6 +13,7 @@ using Microsoft.Extensions.DependencyInjection; using NSubstitute; using Shouldly; using Volo.Abp; +using Volo.Abp.Domain.Repositories; using Volo.Abp.Settings; using Volo.Abp.Timing; using Xunit; @@ -113,6 +114,88 @@ namespace EasyAbp.EShop.Orders.Orders services.AddTransient(_ => productDetailAppService); } + [Fact] + public async Task Check_Create_Order_Should_Succeed() + { + var orderRepository = ServiceProvider.GetRequiredService(); + var orderCount = 0; + await WithUnitOfWorkAsync(async () => + { + orderCount = await orderRepository.CountAsync(); + }); + + // Arrange + var checkCreateOrderInput = new CheckCreateOrderInput + { + CustomerRemark = "customer remark", + StoreId = OrderTestData.Store1Id, + OrderLines = new List + { + new CreateOrderLineDto + { + ProductId = OrderTestData.Product1Id, + ProductSkuId = OrderTestData.ProductSku1Id, + Quantity = 10 + } + } + }; + + CheckCreateOrderResultDto resultDto = null; + // Act + await WithUnitOfWorkAsync(async () => + { + resultDto = await _orderAppService.CheckCreateAsync(checkCreateOrderInput); + }); + + // Assert + resultDto.CanCreate.ShouldBeTrue(); + await WithUnitOfWorkAsync(async () => + { + orderCount.ShouldBeEquivalentTo(await orderRepository.CountAsync()); + }); + } + + [Fact] + public async Task Check_Create_Order_Should_Fail() + { + var orderRepository = ServiceProvider.GetRequiredService(); + var orderCount = 0; + await WithUnitOfWorkAsync(async () => + { + orderCount = await orderRepository.CountAsync(); + }); + + // Arrange + var checkCreateOrderInput = new CheckCreateOrderInput + { + CustomerRemark = "customer remark", + StoreId = OrderTestData.Store1Id, + OrderLines = new List + { + new CreateOrderLineDto + { + ProductId = OrderTestData.Product1Id, + ProductSkuId = OrderTestData.ProductSku1Id, + Quantity = 101 // limited range: 1-100 + } + } + }; + + CheckCreateOrderResultDto resultDto = null; + // Act + await WithUnitOfWorkAsync(async () => + { + resultDto = await _orderAppService.CheckCreateAsync(checkCreateOrderInput); + }); + + // Assert + resultDto.CanCreate.ShouldBeFalse(); + await WithUnitOfWorkAsync(async () => + { + orderCount.ShouldBeEquivalentTo(await orderRepository.CountAsync()); + }); + } + [Fact] public async Task Order_Should_Be_Created() { From 15b799a1112c7171d2fc2193543946c920d92a7a Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Tue, 19 Jul 2022 01:47:16 +0800 Subject: [PATCH 08/12] Force creating new UOW in CheckCreateAsync method --- .../EasyAbp/EShop/Orders/Orders/OrderAppService.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs index b2317415..06c5d04d 100644 --- a/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs +++ b/modules/EasyAbp.EShop.Orders/src/EasyAbp.EShop.Orders.Application/EasyAbp/EShop/Orders/Orders/OrderAppService.cs @@ -235,8 +235,7 @@ namespace EasyAbp.EShop.Orders.Orders public virtual async Task CheckCreateAsync(CheckCreateOrderInput input) { - var requiresNewUow = !UnitOfWorkManager.Current?.Options.IsTransactional ?? false; - using var uow = UnitOfWorkManager.Begin(new AbpUnitOfWorkOptions(true), requiresNewUow); + using var uow = UnitOfWorkManager.Begin(new AbpUnitOfWorkOptions(true), true); try { From 63eda717d29546e0bd852d391951aca583fdad9c Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Tue, 19 Jul 2022 01:48:12 +0800 Subject: [PATCH 09/12] Check quantity in `BasicBasketItemProductInfoUpdater` --- .../BasketItems/BasicBasketItemProductInfoUpdater.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs index bebfd596..83cbaa78 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasicBasketItemProductInfoUpdater.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using EasyAbp.EShop.Products.Products; using EasyAbp.EShop.Products.Products.Dtos; @@ -31,7 +32,6 @@ public class BasicBasketItemProductInfoUpdater : IBasketItemProductInfoUpdater, if (productSkuDto == null) { item.SetIsInvalid(true); - return; } @@ -52,11 +52,19 @@ public class BasicBasketItemProductInfoUpdater : IBasketItemProductInfoUpdater, if (productDto.InventoryStrategy != InventoryStrategy.NoNeed && targetQuantity > productSkuDto.Inventory) { item.SetIsInvalid(true); + return; } if (!productDto.IsPublished) { item.SetIsInvalid(true); + return; + } + + if (!targetQuantity.IsBetween(productSkuDto.OrderMinQuantity, productSkuDto.OrderMaxQuantity)) + { + item.SetIsInvalid(true); + return; } } } \ No newline at end of file From f738f80a65fc6cfc24f81d3acbba1c623b5501f7 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Tue, 19 Jul 2022 01:51:03 +0800 Subject: [PATCH 10/12] Update pages to support "check-create-order" --- .../Plugins/Baskets/BasketsErrorCodes.cs | 1 + .../Plugins/Baskets/Localization/en.json | 1 + .../Plugins/Baskets/Localization/zh-Hans.json | 1 + .../Plugins/Baskets/Localization/zh-Hant.json | 1 + .../EShopPluginsBasketsWebModule.cs | 4 +- .../EasyAbp.EShop.Plugins.Baskets.Web.csproj | 1 + .../BasketItems/BasketItem/CreateModal.cshtml | 41 ++++++++++++--- .../BasketItem/CreateModal.cshtml.cs | 40 ++++++++++++-- .../BasketItems/BasketItem/EditModal.cshtml | 52 ++++++++++++++----- .../BasketItem/EditModal.cshtml.cs | 42 +++++++++++++-- .../Baskets/BasketItems/BasketItem/index.js | 29 ++++++++--- 11 files changed, 175 insertions(+), 38 deletions(-) diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketsErrorCodes.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketsErrorCodes.cs index 6bdd1cc5..d123b535 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketsErrorCodes.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketsErrorCodes.cs @@ -2,6 +2,7 @@ { public static class BasketsErrorCodes { + public const string CheckCreateOrderFailed = "EasyAbp.EShop.Plugins.Baskets:CheckCreateOrderFailed"; public const string ProductSkuNotFound = "EasyAbp.EShop.Plugins.Baskets:ProductSkuNotFound"; } } diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/en.json b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/en.json index dd7ff74c..ba85b081 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/en.json +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/en.json @@ -27,6 +27,7 @@ "EditBasketItem": "Edit", "BasketItemDeletionConfirmationMessage": "Are you sure to delete the basket item {0}?", "SuccessfullyDeleted": "Successfully deleted", + "EasyAbp.EShop.Plugins.Baskets:CheckCreateOrderFailed": "You are not allowed to purchase the specified item. Reason: {reason}", "EasyAbp.EShop.Plugins.Baskets:ProductSkuNotFound": "Product {productId} (SKU: {productSkuId}) not found." } } \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hans.json b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hans.json index 31ebc3d7..9d917b82 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hans.json +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hans.json @@ -27,6 +27,7 @@ "EditBasketItem": "编辑", "BasketItemDeletionConfirmationMessage": "确认删除购物车项 {0}?", "SuccessfullyDeleted": "删除成功", + "EasyAbp.EShop.Plugins.Baskets:CheckCreateOrderFailed": "您无法购买指定商品,原因:{reason}", "EasyAbp.EShop.Plugins.Baskets:ProductSkuNotFound": "商品{productId}(SKU: {productSkuId})未找到" } } \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hant.json b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hant.json index a88995bb..20e509a7 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hant.json +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/Localization/zh-Hant.json @@ -27,6 +27,7 @@ "EditBasketItem": "編輯", "BasketItemDeletionConfirmationMessage": "確認刪除購物車項 {0}?", "SuccessfullyDeleted": "刪除成功", + "EasyAbp.EShop.Plugins.Baskets:CheckCreateOrderFailed": "您無法購買指定商品,原因:{reason}", "EasyAbp.EShop.Plugins.Baskets:ProductSkuNotFound": "商品{productId}(SKU: {productSkuId})未找到" } } \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EShopPluginsBasketsWebModule.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EShopPluginsBasketsWebModule.cs index 87e8b5b0..df6b7ca1 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EShopPluginsBasketsWebModule.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EShopPluginsBasketsWebModule.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; +using EasyAbp.EShop.Orders; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.DependencyInjection; using EasyAbp.EShop.Plugins.Baskets.Localization; using EasyAbp.EShop.Plugins.Baskets.Web.Menus; @@ -12,6 +13,7 @@ using Volo.Abp.VirtualFileSystem; namespace EasyAbp.EShop.Plugins.Baskets.Web { [DependsOn( + typeof(EShopOrdersApplicationContractsModule), typeof(EShopPluginsBasketsApplicationContractsModule), typeof(AbpAspNetCoreMvcUiThemeSharedModule), typeof(AbpAutoMapperModule) diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EasyAbp.EShop.Plugins.Baskets.Web.csproj b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EasyAbp.EShop.Plugins.Baskets.Web.csproj index 26f20ae2..2ac0989a 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EasyAbp.EShop.Plugins.Baskets.Web.csproj +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EasyAbp.EShop.Plugins.Baskets.Web.csproj @@ -17,6 +17,7 @@ + diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml index ac0ede94..fea6d104 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml @@ -1,6 +1,6 @@ @page +@using EasyAbp.EShop.Plugins.Baskets @using EasyAbp.EShop.Plugins.Baskets.Localization -@using EasyAbp.EShop.Plugins.Baskets.Permissions @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @@ -25,16 +25,15 @@ \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs index c6d5a5fc..ff5ebc11 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs @@ -1,12 +1,16 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; +using EasyAbp.EShop.Orders.Orders; +using EasyAbp.EShop.Orders.Orders.Dtos; using Microsoft.AspNetCore.Mvc; using EasyAbp.EShop.Plugins.Baskets.BasketItems; using EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos; using EasyAbp.EShop.Plugins.Baskets.Permissions; using EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.ViewModels; using Microsoft.AspNetCore.Authorization; +using Volo.Abp; using Volo.Abp.Settings; namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem @@ -27,11 +31,15 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt [BindProperty] public EditBasketItemViewModel ViewModel { get; set; } - private readonly IBasketItemAppService _service; + private readonly IOrderAppService _orderAppService; + private readonly IBasketItemAppService _basketItemAppService; - public EditModalModel(IBasketItemAppService service) + public EditModalModel( + IOrderAppService orderAppService, + IBasketItemAppService basketItemAppService) { - _service = service; + _orderAppService = orderAppService; + _basketItemAppService = basketItemAppService; } public virtual async Task OnGetAsync() @@ -44,14 +52,38 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt return; } - var dto = await _service.GetAsync(Id); + var dto = await _basketItemAppService.GetAsync(Id); ViewModel = ObjectMapper.Map(dto); } public virtual async Task OnPostAsync() { + var item = await _basketItemAppService.GetAsync(Id); + var dto = ObjectMapper.Map(ViewModel); - await _service.UpdateAsync(Id, dto); + + var checkCreateOrderResult = await _orderAppService.CheckCreateAsync(new CheckCreateOrderInput + { + StoreId = item.StoreId, + OrderLines = new List + { + new() + { + ProductId = item.ProductId, + ProductSkuId = item.ProductSkuId, + Quantity = ViewModel.Quantity + } + } + }); + + if (!checkCreateOrderResult.CanCreate) + { + throw new BusinessException(BasketsErrorCodes.CheckCreateOrderFailed) + .WithData("reason", checkCreateOrderResult.Reason); + } + + await _basketItemAppService.UpdateAsync(Id, dto); + return NoContent(); } } diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js index b4b06c59..950d55d2 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js @@ -120,15 +120,30 @@ $(function () { function createManyServerSideBasketItems(items, autoReloadDataTable = true) { var item = items.shift(); - service.create(item, { - success: function () { - if (items.length > 0) { - createManyServerSideBasketItems(items); - } else if (autoReloadDataTable) { - dataTable.ajax.reload(); + var orderService = easyAbp.eShop.orders.orders.order; + orderService.checkCreate({ + storeId: item.storeId, + orderLines: [{ + productId: item.productId, + productSkuId: item.productSkuId, + quantity: item.quantity + }] + }, { + success: function (responseText, statusText, xhr, form) { + console.log(responseText); + if (responseText.canCreate) { + service.create(item, { + success: function () { + if (items.length > 0) { + createManyServerSideBasketItems(items); + } else if (autoReloadDataTable) { + dataTable.ajax.reload(); + } + } + }) } } - }) + }); } $('#NewBasketItemButton').click(function (e) { From 3c44b19ab72ab53d69455b330c22f1095336c793 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Tue, 19 Jul 2022 02:04:16 +0800 Subject: [PATCH 11/12] Create README.md for the baskets module --- docs/README.md | 2 +- docs/plugins/baskets/README.md | 72 ++++++++++++++++++++++++++++++++++ plugins/Baskets/README.md | 1 + 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 docs/plugins/baskets/README.md create mode 120000 plugins/Baskets/README.md diff --git a/docs/README.md b/docs/README.md index 56cb754c..29938b6b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -104,7 +104,7 @@ We can customize some features to use EShop in complex application scenarios. * Stores * Plugin modules - * Baskets + * [Baskets](https://github.com/EasyAbp/EShop/tree/dev/plugins/Baskets) * Coupons * Inventories * [DaprActors](https://github.com/EasyAbp/EShop/tree/dev/plugins/Inventories/DaprActors) diff --git a/docs/plugins/baskets/README.md b/docs/plugins/baskets/README.md new file mode 100644 index 00000000..8f525b25 --- /dev/null +++ b/docs/plugins/baskets/README.md @@ -0,0 +1,72 @@ +# EShop.Plugins.Baskets + +[![ABP version](https://img.shields.io/badge/dynamic/xml?style=flat-square&color=yellow&label=abp&query=%2F%2FProject%2FPropertyGroup%2FAbpVersion&url=https%3A%2F%2Fraw.githubusercontent.com%2FEasyAbp%2FEShop%2Fmaster%2FDirectory.Build.props)](https://abp.io) +[![NuGet](https://img.shields.io/nuget/v/EasyAbp.EShop.Plugins.Baskets.Domain.Shared.svg?style=flat-square)](https://www.nuget.org/packages/EasyAbp.EShop.Plugins.Baskets.Domain.Shared) +[![NuGet Download](https://img.shields.io/nuget/dt/EasyAbp.EShop.Plugins.Baskets.Domain.Shared.svg?style=flat-square)](https://www.nuget.org/packages/EasyAbp.EShop.Plugins.Baskets.Domain.Shared) +[![Discord online](https://badgen.net/discord/online-members/S6QaezrCRq?label=Discord)](https://discord.gg/S6QaezrCRq) +[![GitHub stars](https://img.shields.io/github/stars/EasyAbp/EShop?style=social)](https://www.github.com/EasyAbp/EShop) + +🛒 A baskets (cart) plugin for EShop. It supports both the server-side pattern and the client-side pattern. + +## Installation + +1. Install the following NuGet packages. ([see how](https://github.com/EasyAbp/EasyAbpGuide/blob/master/docs/How-To.md#add-nuget-packages)) + + * EasyAbp.EShop.Plugins.Baskets.Application + * EasyAbp.EShop.Plugins.Baskets.Application.Contracts + * EasyAbp.EShop.Plugins.Baskets.Domain + * EasyAbp.EShop.Plugins.Baskets.Domain.Shared + * EasyAbp.EShop.Plugins.Baskets.EntityFrameworkCore + * EasyAbp.EShop.Plugins.Baskets.HttpApi + * EasyAbp.EShop.Plugins.Baskets.HttpApi.Client + * (Optional) EasyAbp.EShop.Plugins.Baskets.MongoDB + * (Optional) EasyAbp.EShop.Plugins.Baskets.Web + +1. Add `DependsOn(typeof(EShopXxxModule))` attribute to configure the module dependencies. ([see how](https://github.com/EasyAbp/EasyAbpGuide/blob/master/docs/How-To.md#add-module-dependencies)) + +1. Add `builder.ConfigureEShopPluginsBaskets();` to the `OnModelCreating()` method in **MyProjectMigrationsDbContext.cs**. + +1. Add EF Core migrations and update your database. See: [ABP document](https://docs.abp.io/en/abp/latest/Tutorials/Part-1?UI=MVC&DB=EF#add-database-migration). + +## Server-side Baskets Pattern + +The server-side basket is for identified(logon) users. It requests the basket [backend service APIs](https://github.com/EasyAbp/EShop/blob/dev/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.HttpApi/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemController.cs) are available. + +1. Before you create a basket item, use `/api/e-shop/orders/order/check-create` (POST) to check whether the current user is allowed to create an order with it. +1. Use `/api/e-shop/plugins/baskets/basket-item` (POST) to create basket items on the server side. Extra properties are allowed. +1. Use `/api/e-shop/plugins/baskets/basket-item` (GET) to get basket the item list. The returned "IsInvalid" property shows whether you can use the item to create an order. +1. Use `/api/e-shop/plugins/baskets/basket-item/{id}` (PUT) or `/api/e-shop/plugins/baskets/basket-item/{id}` (DELETE) to change an item's quantity or remove an item. + +## Client-side Baskets Pattern + +You should store the basket items in the client(browser) cache as a collection of [IBasketItem](https://github.com/EasyAbp/EShop/blob/dev/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs). The client-side doesn't depend on the baskets module backend service APIs. + +### With Backend + +If you install the backend, it provides APIs to help refresh your client-side basket items. + +1. Before you create a basket item, use `/api/e-shop/orders/order/check-create` (POST) to check whether the current user is allowed to create an order with it. +1. Use `/api/e-shop/plugins/baskets/basket-item/generate-client-side-data` (POST) to refresh your client-side basket items anytime. + +### Without Backend + +If you don't install the backend, you can still create and store the basket items locally, but the client-side basket items will not validate and never update. + +## How To Determine a Basket Pattern + +The server-side baskets pattern will take effect if all the following conditions are met: +1. The baskets module backend has been installed and is available. +1. The `EasyAbp.EShop.Plugins.Baskets.EnableServerSideBaskets` setting value is "True". +1. The current user has the `EasyAbp.EShop.Plugins.Baskets.BasketItem` permission. + +## What if Anonymous Users Add Basket Items and Then Log In? + +The client(browser) should try to add the existing items to the server-side and remove them from the client-side. You can implement it by referring to the [index.js](https://github.com/EasyAbp/EShop/blob/dev/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js). + +## Use Basket Items To Create an Order + +We don't provide a built-in way to convert basket items to an order creation DTO. + +Create an order manually by the front end, and remember to map the basket item's extra properties to the order creation DTO since some special product may need them. + +After creating the order, the front end should clear the unused basket items. \ No newline at end of file diff --git a/plugins/Baskets/README.md b/plugins/Baskets/README.md new file mode 120000 index 00000000..559ea800 --- /dev/null +++ b/plugins/Baskets/README.md @@ -0,0 +1 @@ +../../docs/plugins/baskets/README.md \ No newline at end of file From 91eda09c3e8a4f6cebbb196c3beae701a11a0108 Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Tue, 19 Jul 2022 02:15:27 +0800 Subject: [PATCH 12/12] Revert the Edit modal --- .../BasketItems/BasketItem/EditModal.cshtml | 52 +++++-------------- .../BasketItem/EditModal.cshtml.cs | 42 ++------------- 2 files changed, 18 insertions(+), 76 deletions(-) diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml index 7227efc4..051be9b3 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml @@ -1,9 +1,8 @@ @page -@using EasyAbp.EShop.Plugins.Baskets @using EasyAbp.EShop.Plugins.Baskets.Localization +@using EasyAbp.EShop.Plugins.Baskets.Permissions @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Mvc.Localization -@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @using Volo.Abp.Settings @inject IHtmlLocalizer L @@ -29,11 +28,19 @@ $(document).ready(function() { if (@(Model.ServerSide ? "true" : "false")) return; + + var basketItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || []; + var index = basketItems.findIndex(x => x.id === '@Model.Id'); - function generateClientSideData(basketItems) { - var basketItemService = easyAbp.eShop.plugins.baskets.basketItems.basketItem; - - basketItemService.generateClientSideData({ items: [ basketItems[index] ] }, { + $('#ViewModel_Quantity').val(basketItems[index].quantity); + + var $form = $("form"); + $form.off('submit'); + $form.on('submit', function(e){ + e.preventDefault(); + var service = easyAbp.eShop.plugins.baskets.basketItems.basketItem; + basketItems[index].quantity = parseInt($form.serializeFormToObject().viewModel.quantity); + service.generateClientSideData({ items: [ basketItems[index] ] }, { success: function (responseText, statusText, xhr, form) { localStorage.setItem(localStorageItemKey, JSON.stringify(basketItems)); $form.trigger('abp-ajax-success', @@ -45,39 +52,6 @@ }) } }); - } - - var basketItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || []; - var index = basketItems.findIndex(x => x.id === '@Model.Id'); - - $('#ViewModel_Quantity').val(basketItems[index].quantity); - - var $form = $("form"); - $form.off('submit'); - $form.on('submit', function(e){ - e.preventDefault(); - var orderService = easyAbp.eShop.orders.orders.order; - basketItems[index].quantity = parseInt($form.serializeFormToObject().viewModel.quantity); - if (abp.currentUser.isAuthenticated) { - orderService.checkCreate({ - storeId: basketItems[index].storeId, - orderLines: [{ - productId: basketItems[index].productId, - productSkuId: basketItems[index].productSkuId, - quantity: basketItems[index].quantity - }] - }, { - success: function (responseText, statusText, xhr, form) { - if (responseText.canCreate) { - generateClientSideData(basketItems); - } else { - abp.message.error(l('@BasketsErrorCodes.CheckCreateOrderFailed', responseText.reason)); - } - } - }); - } else { - generateClientSideData(basketItems); - } }); }); \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs index ff5ebc11..c6d5a5fc 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs @@ -1,16 +1,12 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; -using EasyAbp.EShop.Orders.Orders; -using EasyAbp.EShop.Orders.Orders.Dtos; using Microsoft.AspNetCore.Mvc; using EasyAbp.EShop.Plugins.Baskets.BasketItems; using EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos; using EasyAbp.EShop.Plugins.Baskets.Permissions; using EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.ViewModels; using Microsoft.AspNetCore.Authorization; -using Volo.Abp; using Volo.Abp.Settings; namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem @@ -31,15 +27,11 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt [BindProperty] public EditBasketItemViewModel ViewModel { get; set; } - private readonly IOrderAppService _orderAppService; - private readonly IBasketItemAppService _basketItemAppService; + private readonly IBasketItemAppService _service; - public EditModalModel( - IOrderAppService orderAppService, - IBasketItemAppService basketItemAppService) + public EditModalModel(IBasketItemAppService service) { - _orderAppService = orderAppService; - _basketItemAppService = basketItemAppService; + _service = service; } public virtual async Task OnGetAsync() @@ -52,38 +44,14 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt return; } - var dto = await _basketItemAppService.GetAsync(Id); + var dto = await _service.GetAsync(Id); ViewModel = ObjectMapper.Map(dto); } public virtual async Task OnPostAsync() { - var item = await _basketItemAppService.GetAsync(Id); - var dto = ObjectMapper.Map(ViewModel); - - var checkCreateOrderResult = await _orderAppService.CheckCreateAsync(new CheckCreateOrderInput - { - StoreId = item.StoreId, - OrderLines = new List - { - new() - { - ProductId = item.ProductId, - ProductSkuId = item.ProductSkuId, - Quantity = ViewModel.Quantity - } - } - }); - - if (!checkCreateOrderResult.CanCreate) - { - throw new BusinessException(BasketsErrorCodes.CheckCreateOrderFailed) - .WithData("reason", checkCreateOrderResult.Reason); - } - - await _basketItemAppService.UpdateAsync(Id, dto); - + await _service.UpdateAsync(Id, dto); return NoContent(); } }