diff --git a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/Transactions/Transaction/index.js b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/Transactions/Transaction/index.js index c4f67398..5432a58e 100644 --- a/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/Transactions/Transaction/index.js +++ b/modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/Transactions/Transaction/index.js @@ -24,14 +24,14 @@ $(function () { [ { text: l('Edit'), - visible: abp.auth.isGranted('Stores.Transaction.Update'), + visible: abp.auth.isGranted('EasyAbp.EShop.Stores.Transaction.Update'), action: function (data) { editModal.open({ id: data.record.id }); } }, { text: l('Delete'), - visible: abp.auth.isGranted('Stores.Transaction.Delete'), + visible: abp.auth.isGranted('EasyAbp.EShop.Stores.Transaction.Delete'), confirmMessage: function (data) { return l('TransactionDeletionConfirmationMessage', data.record.id); }, 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 new file mode 100644 index 00000000..5bc1688b --- /dev/null +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs @@ -0,0 +1,77 @@ +using System; +using JetBrains.Annotations; + +namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos; + +[Serializable] +public class ClientSideBasketItemModel : IBasketItem +{ + public Guid Id { get; set; } + + public string BasketName { get; set; } + + public int Quantity { get; set; } + + public Guid StoreId { get; set; } + + public Guid ProductId { get; set; } + + public string ProductUniqueName { get; set; } + + public string ProductDisplayName { get; set; } + + public Guid ProductSkuId { get; set; } + + public string SkuName { get; set; } + + public string SkuDescription { get; set; } + + public string MediaResources { get; set; } + + public string Currency { get; set; } + + public decimal UnitPrice { get; set; } + + public decimal TotalPrice { get; set; } + + public decimal TotalDiscount { get; set; } + + public int Inventory { get; set; } + + public bool IsInvalid { get; set; } + + public ClientSideBasketItemModel( + Guid id, + [NotNull] string basketName, + Guid storeId, + Guid productId, + Guid productSkuId) + { + Id = id; + BasketName = basketName; + StoreId = storeId; + ProductId = productId; + ProductSkuId = productSkuId; + } + + public void SetIsInvalid(bool isInvalid) + { + IsInvalid = isInvalid; + } + + public void UpdateProductData(int quantity, IProductData productData) + { + Quantity = quantity; + + MediaResources = productData.MediaResources; + ProductUniqueName = productData.ProductUniqueName; + ProductDisplayName = productData.ProductDisplayName; + SkuName = productData.SkuName; + SkuDescription = productData.SkuDescription; + Currency = productData.Currency; + UnitPrice = productData.UnitPrice; + TotalPrice = productData.TotalPrice; + TotalDiscount = productData.TotalDiscount; + Inventory = productData.Inventory; + } +} \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/CreateBasketItemDto.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/CreateBasketItemDto.cs index 6267a1ee..e8b8a069 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/CreateBasketItemDto.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/CreateBasketItemDto.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.ComponentModel.DataAnnotations; using Volo.Abp.ObjectExtending; diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataInput.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataInput.cs new file mode 100644 index 00000000..6ff6a523 --- /dev/null +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataInput.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; +using Volo.Abp.ObjectExtending; + +namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos; + +public class GenerateClientSideDataInput : ExtensibleObject +{ + public List Items { get; set; } = new(); +} \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataItemInput.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataItemInput.cs new file mode 100644 index 00000000..98e335fc --- /dev/null +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataItemInput.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.ObjectExtending; + +namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos +{ + [Serializable] + public class GenerateClientSideDataItemInput : ExtensibleObject + { + /// + /// Reuse Id if set. + /// + public Guid? Id { get; set; } + + public string BasketName { get; set; } = BasketsConsts.DefaultBasketName; + + public Guid ProductId { get; set; } + + public Guid ProductSkuId { get; set; } + + public int Quantity { get; set; } + + public override IEnumerable Validate(ValidationContext validationContext) + { + base.Validate(validationContext); + + if (Quantity <= 0) + { + yield return new ValidationResult( + "Quantity should be greater than 0.", + new[] { "Quantity" } + ); + } + + if (BasketName.IsNullOrWhiteSpace()) + { + yield return new ValidationResult( + "BasketName should not be empty.", + new[] { "BasketName" } + ); + } + } + } +} \ No newline at end of file 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 9bdf28e1..a0610631 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,11 +1,10 @@ using System; using System.ComponentModel.DataAnnotations; -using Volo.Abp.Application.Dtos; namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos { [Serializable] - public class GetBasketItemListDto : PagedAndSortedResultRequestDto + public class GetBasketItemListDto { [Required] public string BasketName { get; set; } diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemAppService.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemAppService.cs index 95a7a9b0..61acc79b 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemAppService.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemAppService.cs @@ -15,6 +15,8 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems CreateBasketItemDto, UpdateBasketItemDto> { - Task DeleteInBulkAsync(IEnumerable ids); + Task BatchDeleteAsync(IEnumerable ids); + + Task> GenerateClientSideDataAsync(GenerateClientSideDataInput input); } } \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs similarity index 100% rename from plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs rename to plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissionDefinitionProvider.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissionDefinitionProvider.cs index f6f84c2c..0abbc3ed 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissionDefinitionProvider.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissionDefinitionProvider.cs @@ -12,9 +12,6 @@ namespace EasyAbp.EShop.Plugins.Baskets.Permissions var basketItemPermission = myGroup.AddPermission(BasketsPermissions.BasketItem.Default, L("Permission:BasketItem")); basketItemPermission.AddChild(BasketsPermissions.BasketItem.Manage, L("Permission:Manage")); - basketItemPermission.AddChild(BasketsPermissions.BasketItem.Create, L("Permission:Create")); - basketItemPermission.AddChild(BasketsPermissions.BasketItem.Update, L("Permission:Update")); - basketItemPermission.AddChild(BasketsPermissions.BasketItem.Delete, L("Permission:Delete")); } private static LocalizableString L(string name) diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissions.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissions.cs index 7d80f4d3..db488061 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissions.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissions.cs @@ -15,9 +15,6 @@ namespace EasyAbp.EShop.Plugins.Baskets.Permissions { public const string Default = GroupName + ".BasketItem"; public const string Manage = Default + ".Manage"; - public const string Update = Default + ".Update"; - public const string Create = Default + ".Create"; - public const string Delete = Default + ".Delete"; } } 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 0fbf76da..383fe0e0 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 @@ -5,14 +5,12 @@ using System.Threading.Tasks; using EasyAbp.EShop.Plugins.Baskets.Permissions; using EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos; using EasyAbp.EShop.Plugins.Baskets.ProductUpdates; -using EasyAbp.EShop.Products.ProductInventories; using EasyAbp.EShop.Products.Products; using EasyAbp.EShop.Products.Products.Dtos; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.Authorization; -using Volo.Abp.Domain.Entities; using Volo.Abp.Users; namespace EasyAbp.EShop.Plugins.Baskets.BasketItems @@ -22,9 +20,9 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems { protected override string GetPolicyName { get; set; } = BasketsPermissions.BasketItem.Default; protected override string GetListPolicyName { get; set; } = BasketsPermissions.BasketItem.Default; - protected override string CreatePolicyName { get; set; } = BasketsPermissions.BasketItem.Create; - protected override string UpdatePolicyName { get; set; } = BasketsPermissions.BasketItem.Update; - protected override string DeletePolicyName { get; set; } = BasketsPermissions.BasketItem.Delete; + protected override string CreatePolicyName { get; set; } = BasketsPermissions.BasketItem.Default; + protected override string UpdatePolicyName { get; set; } = BasketsPermissions.BasketItem.Default; + protected override string DeletePolicyName { get; set; } = BasketsPermissions.BasketItem.Default; private readonly IBasketItemRepository _repository; private readonly IProductUpdateRepository _productUpdateRepository; @@ -85,11 +83,6 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems var query = await CreateFilteredQueryAsync(input); - var totalCount = await AsyncExecuter.CountAsync(query); - - query = ApplySorting(query, input); - query = ApplyPaging(query, input); - var items = await AsyncExecuter.ToListAsync(query); var productSkuIds = items.Select(item => item.ProductSkuId).ToList(); @@ -127,12 +120,12 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems } return new PagedResultDto( - totalCount, + items.Count, await MapToGetListOutputDtosAsync(items) ); } - protected virtual async Task UpdateProductDataAsync(int quantity, BasketItem item, ProductDto productDto) + protected virtual async Task UpdateProductDataAsync(int quantity, IBasketItem item, ProductDto productDto) { item.SetIsInvalid(false); @@ -254,7 +247,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems await _repository.DeleteAsync(item, true); } - public virtual async Task DeleteInBulkAsync(IEnumerable ids) + public virtual async Task BatchDeleteAsync(IEnumerable ids) { await CheckDeletePolicyAsync(); @@ -273,6 +266,42 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems } } + public virtual async Task> GenerateClientSideDataAsync( + GenerateClientSideDataInput input) + { + var itemList = new List(); + + var products = new Dictionary(); + + foreach (var dto in input.Items) + { + if (!products.ContainsKey(dto.ProductId)) + { + products[dto.ProductId] = await _productAppService.GetAsync(dto.ProductId); + } + + var productDto = products[dto.ProductId]; + + var productSkuDto = productDto.FindSkuById(dto.ProductSkuId); + + if (productSkuDto == null) + { + throw new ProductSkuNotFoundException(dto.ProductId, dto.ProductSkuId); + } + + var id = dto.Id ?? GuidGenerator.Create(); + + var item = new ClientSideBasketItemModel(id, dto.BasketName, productDto.StoreId, + dto.ProductId, dto.ProductSkuId); + + await UpdateProductDataAsync(dto.Quantity, item, productDto); + + itemList.Add(item); + } + + return new ListResultDto(itemList); + } + protected virtual async Task IsCurrentUserManagerAsync() { return await AuthorizationService.IsGrantedAsync(BasketsPermissions.BasketItem.Manage); 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 new file mode 100644 index 00000000..bd4c67e7 --- /dev/null +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs @@ -0,0 +1,26 @@ +using System; +using JetBrains.Annotations; + +namespace EasyAbp.EShop.Plugins.Baskets.BasketItems; + +public interface IBasketItem : IProductData +{ + Guid Id { get; } + + [NotNull] + string BasketName { get; } + + Guid StoreId { get; } + + Guid ProductId { get; } + + Guid ProductSkuId { get; } + + int Quantity { get; } + + bool IsInvalid { get; } + + void SetIsInvalid(bool isInvalid); + + void UpdateProductData(int quantity, IProductData productData); +} \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs similarity index 100% rename from plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs rename to plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs index e26e5b18..4b567d7f 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs @@ -5,11 +5,10 @@ using Volo.Abp.MultiTenancy; namespace EasyAbp.EShop.Plugins.Baskets.BasketItems { - public class BasketItem : AuditedAggregateRoot, IProductData, IMultiTenant + public class BasketItem : AuditedAggregateRoot, IBasketItem, IMultiTenant { public virtual Guid? TenantId { get; protected set; } - [NotNull] public virtual string BasketName { get; protected set; } public virtual Guid UserId { get; protected set; } @@ -87,9 +86,9 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems Inventory = productData.Inventory; } - public void SetIsInvalid(bool isForSale) + public void SetIsInvalid(bool isInvalid) { - IsInvalid = isForSale; + IsInvalid = isInvalid; } } } diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettingDefinitionProvider.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettingDefinitionProvider.cs index a9eff40f..2408215a 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettingDefinitionProvider.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettingDefinitionProvider.cs @@ -9,6 +9,10 @@ namespace EasyAbp.EShop.Plugins.Baskets.Settings /* Define module settings here. * Use names from BasketsSettings class. */ + context.Add(new SettingDefinition( + BasketsSettings.EnableServerSideBasketsName, + true.ToString(), + isVisibleToClients: true)); } } } \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettings.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettings.cs index c27f0458..e058e574 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettings.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettings.cs @@ -7,5 +7,7 @@ /* Add constants for setting names. Example: * public const string MySettingName = GroupName + ".MySettingName"; */ + + public const string EnableServerSideBasketsName = GroupName + ".EnableServerSideBaskets"; } } \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.HttpApi/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemController.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.HttpApi/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemController.cs index e4db27ff..0dba150a 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.HttpApi/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemController.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.HttpApi/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemController.cs @@ -53,10 +53,17 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems } [HttpDelete] - [Route("in-bulk")] - public Task DeleteInBulkAsync(IEnumerable ids) + [Route("batch")] + public Task BatchDeleteAsync(IEnumerable ids) { - return _service.DeleteInBulkAsync(ids); + return _service.BatchDeleteAsync(ids); + } + + [HttpPost] + [Route("generate-client-side-data")] + public Task> GenerateClientSideDataAsync(GenerateClientSideDataInput input) + { + return _service.GenerateClientSideDataAsync(input); } } } \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/BasketsWebAutoMapperProfile.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/BasketsWebAutoMapperProfile.cs index 77c878ba..1b899f75 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/BasketsWebAutoMapperProfile.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/BasketsWebAutoMapperProfile.cs @@ -1,5 +1,6 @@ using EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos; using AutoMapper; +using EasyAbp.EShop.Plugins.Baskets.BasketItems; using EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.ViewModels; using Volo.Abp.AutoMapper; @@ -12,8 +13,11 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web /* You can configure your AutoMapper mapping configuration here. * Alternatively, you can split your mapping configurations * into multiple profile classes for a better organization. */ - CreateMap(); + CreateMap() + .Ignore(dto => dto.ExtraProperties); + CreateMap(); CreateMap() + .Ignore(dto => dto.UserId) .Ignore(dto => dto.ExtraProperties); CreateMap() .Ignore(dto => dto.ExtraProperties); 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 f796a22b..87e8b5b0 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EShopPluginsBasketsWebModule.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EShopPluginsBasketsWebModule.cs @@ -8,7 +8,6 @@ using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; using Volo.Abp.UI.Navigation; using Volo.Abp.VirtualFileSystem; -using EasyAbp.EShop.Plugins.Baskets.Permissions; namespace EasyAbp.EShop.Plugins.Baskets.Web { @@ -45,6 +44,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web }); context.Services.AddAutoMapperObjectMapper(); + Configure(options => { options.AddMaps(validate: true); diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Menus/BasketsMenuContributor.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Menus/BasketsMenuContributor.cs index 83483b13..fa97a0a5 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Menus/BasketsMenuContributor.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Menus/BasketsMenuContributor.cs @@ -1,7 +1,9 @@ using System.Collections.Generic; +using System.Security.Principal; using System.Threading.Tasks; using EasyAbp.EShop.Plugins.Baskets.Localization; using EasyAbp.EShop.Plugins.Baskets.Permissions; +using Volo.Abp; using Volo.Abp.UI.Navigation; namespace EasyAbp.EShop.Plugins.Baskets.Web.Menus @@ -22,7 +24,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Menus var basketManagementMenuItem = new ApplicationMenuItem(BasketsMenus.Prefix, l["Menu:BasketManagement"]); - if (await context.IsGrantedAsync(BasketsPermissions.BasketItem.Default)) + if (context.GetHttpContext().User.Identity.FindUserId() == null || await context.IsGrantedAsync(BasketsPermissions.BasketItem.Default)) { basketManagementMenuItem.AddItem( new ApplicationMenuItem(BasketsMenus.BasketItem, l["Menu:BasketItem"], $"/EShop/Plugins/Baskets/BasketItems/BasketItem?basketName={BasketsConsts.DefaultBasketName}&userId=") 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 87827e24..2b739e7c 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,12 +1,18 @@ @page @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 +@using Volo.Abp.Settings @inject IHtmlLocalizer L +@inject IAuthorizationService _authorizationService +@inject ISettingProvider _settingProvider @model EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.CreateModalModel @{ Layout = null; } + @@ -15,4 +21,59 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml.cs index c048fd46..d73c5e61 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml.cs @@ -2,14 +2,19 @@ using System.Threading.Tasks; 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.Settings; namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem { public class CreateModalModel : BasketsPageModel { [BindProperty] - public CreateBasketItemViewModel ViewModel { get; set; } = new CreateBasketItemViewModel(); + public CreateBasketItemViewModel ViewModel { get; set; } = new(); + + public bool ServerSide { get; set; } private readonly IBasketItemAppService _service; @@ -18,6 +23,12 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt _service = service; } + public virtual async Task OnGetAsync() + { + ServerSide = await SettingProvider.GetAsync("EasyAbp.EShop.Plugins.Baskets.EnableServerSideBaskets") + && await AuthorizationService.IsGrantedAsync(BasketsPermissions.BasketItem.Default); + } + public virtual async Task OnPostAsync() { var dto = ObjectMapper.Map(ViewModel); 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 bdccd845..2b597b20 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,8 +1,13 @@ @page @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 +@using Volo.Abp.Settings @inject IHtmlLocalizer L +@inject IAuthorizationService _authorizationService +@inject ISettingProvider _settingProvider @model EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.EditModalModel @{ Layout = null; @@ -16,4 +21,49 @@ - \ No newline at end of file + + + \ 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 82934271..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,17 +1,28 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; 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.Settings; namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem { public class EditModalModel : BasketsPageModel { + [Required] + [HiddenInput] + [BindProperty(SupportsGet = true)] + public string BasketName { get; set; } + [HiddenInput] [BindProperty(SupportsGet = true)] public Guid Id { get; set; } + + public bool ServerSide { get; set; } [BindProperty] public EditBasketItemViewModel ViewModel { get; set; } @@ -25,6 +36,14 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt public virtual async Task OnGetAsync() { + ServerSide = await SettingProvider.GetAsync("EasyAbp.EShop.Plugins.Baskets.EnableServerSideBaskets") + && await AuthorizationService.IsGrantedAsync(BasketsPermissions.BasketItem.Default); + + if (!ServerSide) + { + return; + } + var dto = await _service.GetAsync(Id); ViewModel = ObjectMapper.Map(dto); } diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml index 3913cbfd..69247564 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml @@ -1,4 +1,5 @@ @page +@using System.Security.Principal @using EasyAbp.EShop.Plugins.Baskets.Permissions @using EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem @using EasyAbp.EShop.Plugins.Baskets.Localization @@ -36,13 +37,10 @@ @L["BasketItem"] - @if (await Authorization.IsGrantedAsync(BasketsPermissions.BasketItem.Create)) - { - } @@ -52,7 +50,6 @@ @L["Actions"] @L["BasketItemBasketName"] - @L["BasketItemUserId"] @L["BasketItemStoreId"] @L["BasketItemProductId"] @L["BasketItemProductSkuId"] diff --git a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/ViewModels/CreateBasketItemViewModel.cs b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/ViewModels/CreateBasketItemViewModel.cs index 47dc519b..afd93285 100644 --- a/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/ViewModels/CreateBasketItemViewModel.cs +++ b/plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/ViewModels/CreateBasketItemViewModel.cs @@ -8,13 +8,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt { [Display(Name = "BasketItemBasketName")] public string BasketName { get; set; } = BasketsConsts.DefaultBasketName; - - /// - /// Specify the basket item owner user ID. Use current user ID if this property is null. - /// - [Display(Name = "BasketItemUserId")] - public Guid? UserId { get; set; } - + [Display(Name = "BasketItemStoreId")] public Guid StoreId { get; set; } 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 f9160e58..b4b06c59 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 @@ -1,22 +1,23 @@ $(function () { + var localStorageItemKey = "EShopBasket:" + basketName; + var l = abp.localization.getResource('EasyAbpEShopPluginsBaskets'); + + var serverSide = abp.setting.getBoolean('EasyAbp.EShop.Plugins.Baskets.EnableServerSideBaskets') + && abp.auth.isGranted('EasyAbp.EShop.Plugins.Baskets.BasketItem'); var service = easyAbp.eShop.plugins.baskets.basketItems.basketItem; var createModal = new abp.ModalManager(abp.appPath + 'EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal'); var editModal = new abp.ModalManager(abp.appPath + 'EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal'); - var dataTable = $('#BasketItemTable').DataTable(abp.libs.datatables.normalizeConfiguration({ + var configuration = { processing: true, - serverSide: true, paging: true, searching: false, autoWidth: false, scrollCollapse: true, order: [[1, "asc"]], - ajax: abp.libs.datatables.createAjax(service.getList, function () { - return { basketName: basketName, userId: userId } - }), columnDefs: [ { rowAction: { @@ -24,30 +25,34 @@ $(function () { [ { text: l('Edit'), - visible: abp.auth.isGranted('EasyAbp.EShop.Plugins.Baskets.BasketItem.Update'), action: function (data) { - editModal.open({ id: data.record.id }); + editModal.open({ basketName: basketName, id: data.record.id }); } }, { text: l('Delete'), - visible: abp.auth.isGranted('EasyAbp.EShop.Plugins.Baskets.BasketItem.Delete'), confirmMessage: function (data) { return l('BasketItemDeletionConfirmationMessage', data.record.id); }, action: function (data) { + if (serverSide) { service.delete(data.record.id) - .then(function () { - abp.notify.info(l('SuccessfullyDeleted')); - dataTable.ajax.reload(); - }); + .then(function () { + abp.notify.info(l('SuccessfullyDeleted')); + dataTable.ajax.reload(); + }); + } else { + var cachedItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || []; + cachedItems.splice(cachedItems.findIndex(x => x.id === data.record.id), 1); + localStorage.setItem(localStorageItemKey, JSON.stringify(cachedItems)); + location.reload(); + } } } ] } }, { data: "basketName" }, - { data: "userId" }, { data: "storeId" }, { data: "productId" }, { data: "productSkuId" }, @@ -64,15 +69,67 @@ $(function () { { data: "inventory" }, { data: "isInvalid" }, ] - })); + }; + + var dataTable; + + if (serverSide) { + configuration.serverSide = true; + configuration.ajax = abp.libs.datatables.createAjax(service.getList, function () { + return { basketName: basketName, userId: userId } + }); + + var clientSideItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || []; + + // Move client-side basket items to server-side. + if (clientSideItems.length > 0) { + localStorage.setItem(localStorageItemKey, JSON.stringify([])); + createManyServerSideBasketItems(clientSideItems); + } + + dataTable = $('#BasketItemTable').DataTable(abp.libs.datatables.normalizeConfiguration(configuration)); + } else { + configuration.serverSide = false; + var cachedItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || []; + if (cachedItems.length > 0) { + service.generateClientSideData({ items: cachedItems }).then(function (result) { + configuration.data = result.items + dataTable = $('#BasketItemTable').DataTable(abp.libs.datatables.normalizeConfiguration(configuration)); + }); + } else { + configuration.data = []; + dataTable = $('#BasketItemTable').DataTable(abp.libs.datatables.normalizeConfiguration(configuration)); + } + } createModal.onResult(function () { - dataTable.ajax.reload(); + if (serverSide) { + dataTable.ajax.reload(); + } else { + location.reload(); + } }); editModal.onResult(function () { - dataTable.ajax.reload(); + if (serverSide) { + dataTable.ajax.reload(); + } else { + location.reload(); + } }); + + 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(); + } + } + }) + } $('#NewBasketItemButton').click(function (e) { e.preventDefault();