From d079d89b9fd717e065c766210faa5204bb9f622c Mon Sep 17 00:00:00 2001 From: gdlcf88 Date: Thu, 14 Jul 2022 22:37:39 +0800 Subject: [PATCH] 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