From 210337bb526bc9ab28bdbcb018550c6c684c335d Mon Sep 17 00:00:00 2001 From: "Md. Abul Kalam" Date: Sun, 22 Dec 2024 23:27:26 +0600 Subject: [PATCH] Issue #59: Update login and cart APIs. --- .../Common/Mapping/CartMappingConfig.cs | 3 -- .../Controllers/AuthenticationController.cs | 2 +- src/Shopizy.Api/Controllers/CartController.cs | 17 ------- .../Register/RegisterCommandHandler.cs | 9 +++- .../Queries/login/LoginQueryHandler.cs | 14 +++++- .../AddProductToCartCommand.cs | 9 +++- .../AddProductToCartCommandHandler.cs | 4 +- .../CreateCartWithFirstProductCommand.cs | 10 ---- ...reateCartWithFirstProductCommandHandler.cs | 49 ------------------- .../CreateOrder/CreateOrderCommand.cs | 3 +- .../CreateOrder/CreateOrderCommandHandler.cs | 40 +++++++++------ .../CardNotPresentSaleCommand.cs | 3 +- .../CashOnDeliverySaleCommand.cs | 3 +- .../DeleteProductImageCommandHandler.cs | 4 +- .../Cart/AddProductToCartRequest.cs | 2 +- .../Cart/CreateCartWithFirstProductRequest.cs | 7 ++- src/Shopizy.Domain/Carts/Entities/CartItem.cs | 14 ++++-- 17 files changed, 79 insertions(+), 114 deletions(-) delete mode 100644 src/Shopizy.Application/Carts/Commands/CreateCartWithFirstProduct/CreateCartWithFirstProductCommand.cs delete mode 100644 src/Shopizy.Application/Carts/Commands/CreateCartWithFirstProduct/CreateCartWithFirstProductCommandHandler.cs diff --git a/src/Shopizy.Api/Common/Mapping/CartMappingConfig.cs b/src/Shopizy.Api/Common/Mapping/CartMappingConfig.cs index ca7b68c..4e805a0 100644 --- a/src/Shopizy.Api/Common/Mapping/CartMappingConfig.cs +++ b/src/Shopizy.Api/Common/Mapping/CartMappingConfig.cs @@ -1,7 +1,6 @@ using Ardalis.GuardClauses; using Mapster; using Shopizy.Application.Carts.Commands.AddProductToCart; -using Shopizy.Application.Carts.Commands.CreateCartWithFirstProduct; using Shopizy.Application.Carts.Commands.RemoveProductFromCart; using Shopizy.Application.Carts.Commands.UpdateProductQuantity; using Shopizy.Application.Carts.Queries.GetCart; @@ -17,8 +16,6 @@ public void Register(TypeAdapterConfig config) { Guard.Against.Null(config); - config.NewConfig(); - config .NewConfig<(Guid CartId, AddProductToCartRequest request), AddProductToCartCommand>() .Map(dest => dest.CartId, src => src.CartId) diff --git a/src/Shopizy.Api/Controllers/AuthenticationController.cs b/src/Shopizy.Api/Controllers/AuthenticationController.cs index 56bf72b..9612a71 100644 --- a/src/Shopizy.Api/Controllers/AuthenticationController.cs +++ b/src/Shopizy.Api/Controllers/AuthenticationController.cs @@ -16,7 +16,7 @@ public class AuthenticationController(ISender mediator, IMapper mapper) : ApiCon private readonly IMapper _mapper = mapper; [HttpPost("register")] - [SwaggerResponse(StatusCodes.Status200OK, null, typeof(AuthResponse))] + [SwaggerResponse(StatusCodes.Status200OK, null, typeof(SuccessResult))] [SwaggerResponse(StatusCodes.Status400BadRequest, null, typeof(ErrorResult))] [SwaggerResponse(StatusCodes.Status401Unauthorized, null, typeof(ErrorResult))] [SwaggerResponse(StatusCodes.Status409Conflict, null, typeof(ErrorResult))] diff --git a/src/Shopizy.Api/Controllers/CartController.cs b/src/Shopizy.Api/Controllers/CartController.cs index abb8b08..0e9b98b 100644 --- a/src/Shopizy.Api/Controllers/CartController.cs +++ b/src/Shopizy.Api/Controllers/CartController.cs @@ -2,7 +2,6 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using Shopizy.Application.Carts.Commands.AddProductToCart; -using Shopizy.Application.Carts.Commands.CreateCartWithFirstProduct; using Shopizy.Application.Carts.Commands.RemoveProductFromCart; using Shopizy.Application.Carts.Commands.UpdateProductQuantity; using Shopizy.Application.Carts.Queries.GetCart; @@ -31,22 +30,6 @@ public async Task GetCartAsync(Guid userId) return result.Match(Product => Ok(_mapper.Map(Product)), Problem); } - [HttpPost] - [SwaggerResponse(StatusCodes.Status200OK, null, typeof(CartResponse))] - [SwaggerResponse(StatusCodes.Status400BadRequest, null, typeof(ErrorResult))] - [SwaggerResponse(StatusCodes.Status401Unauthorized, null, typeof(ErrorResult))] - [SwaggerResponse(StatusCodes.Status409Conflict, null, typeof(ErrorResult))] - [SwaggerResponse(StatusCodes.Status500InternalServerError, null, typeof(ErrorResult))] - public async Task CreateCartWithFirstProductAsync( - CreateCartWithFirstProductRequest request - ) - { - var command = _mapper.Map(request); - var result = await _mediator.Send(command); - - return result.Match(product => Ok(_mapper.Map(product)), Problem); - } - [HttpPatch("{cartId:guid}")] [SwaggerResponse(StatusCodes.Status200OK, null, typeof(CartResponse))] [SwaggerResponse(StatusCodes.Status400BadRequest, null, typeof(ErrorResult))] diff --git a/src/Shopizy.Application/Authentication/Commands/Register/RegisterCommandHandler.cs b/src/Shopizy.Application/Authentication/Commands/Register/RegisterCommandHandler.cs index b2ed085..3f6c1a6 100644 --- a/src/Shopizy.Application/Authentication/Commands/Register/RegisterCommandHandler.cs +++ b/src/Shopizy.Application/Authentication/Commands/Register/RegisterCommandHandler.cs @@ -2,6 +2,7 @@ using MediatR; using Shopizy.Application.Common.Interfaces.Authentication; using Shopizy.Application.Common.Interfaces.Persistence; +using Shopizy.Domain.Carts; using Shopizy.Domain.Common.CustomErrors; using Shopizy.Domain.Permissions.ValueObjects; using Shopizy.Domain.Users; @@ -10,11 +11,13 @@ namespace Shopizy.Application.Authentication.Commands.Register; public class RegisterCommandHandler( IUserRepository userRepository, - IPasswordManager passwordManager + IPasswordManager passwordManager, + ICartRepository cartRepository ) : IRequestHandler> { private readonly IUserRepository _userRepository = userRepository; private readonly IPasswordManager _passwordManager = passwordManager; + private readonly ICartRepository _cartRepository = cartRepository; public async Task> Handle( RegisterCommand command, @@ -66,6 +69,10 @@ CancellationToken cancellationToken return CustomErrors.User.UserNotCreated; } + var cart = Cart.Create(user.Id); + await _cartRepository.AddAsync(cart); + await _cartRepository.Commit(cancellationToken); + return Result.Success; } } diff --git a/src/Shopizy.Application/Authentication/Queries/login/LoginQueryHandler.cs b/src/Shopizy.Application/Authentication/Queries/login/LoginQueryHandler.cs index 965a15d..02b1ace 100644 --- a/src/Shopizy.Application/Authentication/Queries/login/LoginQueryHandler.cs +++ b/src/Shopizy.Application/Authentication/Queries/login/LoginQueryHandler.cs @@ -3,6 +3,7 @@ using Shopizy.Application.Authentication.Common; using Shopizy.Application.Common.Interfaces.Authentication; using Shopizy.Application.Common.Interfaces.Persistence; +using Shopizy.Domain.Carts; using Shopizy.Domain.Common.CustomErrors; namespace Shopizy.Application.Authentication.Queries.login; @@ -11,13 +12,15 @@ public class LoginQueryHandler( IUserRepository userRepository, IPermissionRepository permissionRepository, IJwtTokenGenerator jwtTokenGenerator, - IPasswordManager passwordManager + IPasswordManager passwordManager, + ICartRepository cartRepository ) : IRequestHandler> { private readonly IUserRepository _userRepository = userRepository; private readonly IPermissionRepository _permissionRepository = permissionRepository; private readonly IJwtTokenGenerator _jwtTokenGenerator = jwtTokenGenerator; private readonly IPasswordManager _passwordManager = passwordManager; + private readonly ICartRepository _cartRepository = cartRepository; public async Task> Handle( LoginQuery query, @@ -52,6 +55,15 @@ CancellationToken cancellationToken var token = _jwtTokenGenerator.GenerateToken(user.Id, roles, assignedPermissions); + var cart = await _cartRepository.GetCartByUserIdAsync(user.Id); + + if (cart is null) + { + cart = Cart.Create(user.Id); + await _cartRepository.AddAsync(cart); + await _cartRepository.Commit(cancellationToken); + } + return new AuthResult(user.Id.Value, user.FirstName, user.LastName, user.Email, token); } } diff --git a/src/Shopizy.Application/Carts/Commands/AddProductToCart/AddProductToCartCommand.cs b/src/Shopizy.Application/Carts/Commands/AddProductToCart/AddProductToCartCommand.cs index a4fceff..baedab8 100644 --- a/src/Shopizy.Application/Carts/Commands/AddProductToCart/AddProductToCartCommand.cs +++ b/src/Shopizy.Application/Carts/Commands/AddProductToCart/AddProductToCartCommand.cs @@ -6,5 +6,10 @@ namespace Shopizy.Application.Carts.Commands.AddProductToCart; [Authorize(Permissions = Permissions.Cart.Modify)] -public record AddProductToCartCommand(Guid CartId, Guid ProductId, string Color, string Size) - : IAuthorizeableRequest>; +public record AddProductToCartCommand( + Guid CartId, + Guid ProductId, + string Color, + string Size, + int Quantity +) : IAuthorizeableRequest>; diff --git a/src/Shopizy.Application/Carts/Commands/AddProductToCart/AddProductToCartCommandHandler.cs b/src/Shopizy.Application/Carts/Commands/AddProductToCart/AddProductToCartCommandHandler.cs index 9f157a9..cd01c52 100644 --- a/src/Shopizy.Application/Carts/Commands/AddProductToCart/AddProductToCartCommandHandler.cs +++ b/src/Shopizy.Application/Carts/Commands/AddProductToCart/AddProductToCartCommandHandler.cs @@ -54,7 +54,9 @@ CancellationToken cancellationToken return CustomErrors.Product.ProductNotFound; } - cart.AddLineItem(CartItem.Create(ProductId.Create(cmd.ProductId), cmd.Color, cmd.Size)); + cart.AddLineItem( + CartItem.Create(ProductId.Create(cmd.ProductId), cmd.Color, cmd.Size, cmd.Quantity) + ); _cartRepository.Update(cart); diff --git a/src/Shopizy.Application/Carts/Commands/CreateCartWithFirstProduct/CreateCartWithFirstProductCommand.cs b/src/Shopizy.Application/Carts/Commands/CreateCartWithFirstProduct/CreateCartWithFirstProductCommand.cs deleted file mode 100644 index ff6b09d..0000000 --- a/src/Shopizy.Application/Carts/Commands/CreateCartWithFirstProduct/CreateCartWithFirstProductCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -using ErrorOr; -using Shopizy.Application.Common.Security.Permissions; -using Shopizy.Application.Common.Security.Request; -using Shopizy.Domain.Carts; - -namespace Shopizy.Application.Carts.Commands.CreateCartWithFirstProduct; - -[Authorize(Permissions = Permissions.Cart.Create)] -public record CreateCartWithFirstProductCommand(Guid ProductId, string Color, string Size) - : IAuthorizeableRequest>; diff --git a/src/Shopizy.Application/Carts/Commands/CreateCartWithFirstProduct/CreateCartWithFirstProductCommandHandler.cs b/src/Shopizy.Application/Carts/Commands/CreateCartWithFirstProduct/CreateCartWithFirstProductCommandHandler.cs deleted file mode 100644 index fa99a68..0000000 --- a/src/Shopizy.Application/Carts/Commands/CreateCartWithFirstProduct/CreateCartWithFirstProductCommandHandler.cs +++ /dev/null @@ -1,49 +0,0 @@ -using ErrorOr; -using MediatR; -using Shopizy.Application.Common.Interfaces.Persistence; -using Shopizy.Application.Common.Security.CurrentUser; -using Shopizy.Domain.Carts; -using Shopizy.Domain.Carts.Entities; -using Shopizy.Domain.Common.CustomErrors; -using Shopizy.Domain.Products.ValueObjects; -using Shopizy.Domain.Users.ValueObjects; - -namespace Shopizy.Application.Carts.Commands.CreateCartWithFirstProduct; - -public class CreateCartWithFirstProductCommandHandler( - IProductRepository productRepository, - ICartRepository cartRepository, - ICurrentUser currentUser -) : IRequestHandler> -{ - private readonly IProductRepository _productRepository = productRepository; - private readonly ICartRepository _cartRepository = cartRepository; - private readonly ICurrentUser _currentUser = currentUser; - - public async Task> Handle( - CreateCartWithFirstProductCommand cmd, - CancellationToken cancellationToken - ) - { - var product = await _productRepository.IsProductExistAsync(ProductId.Create(cmd.ProductId)); - - if (!product) - { - return CustomErrors.Product.ProductNotFound; - } - - var cart = Cart.Create(UserId.Create(_currentUser.GetCurrentUserId())); - cart.AddLineItem(CartItem.Create(ProductId.Create(cmd.ProductId), cmd.Color, cmd.Size)); - - await _cartRepository.AddAsync(cart); - - if (await _cartRepository.Commit(cancellationToken) <= 0) - { - return CustomErrors.Cart.CartNotCreated; - } - - return await _cartRepository.GetCartByUserIdAsync( - UserId.Create(_currentUser.GetCurrentUserId()) - ); - } -} diff --git a/src/Shopizy.Application/Orders/Commands/CreateOrder/CreateOrderCommand.cs b/src/Shopizy.Application/Orders/Commands/CreateOrder/CreateOrderCommand.cs index 66b06c3..2a97c04 100644 --- a/src/Shopizy.Application/Orders/Commands/CreateOrder/CreateOrderCommand.cs +++ b/src/Shopizy.Application/Orders/Commands/CreateOrder/CreateOrderCommand.cs @@ -1,13 +1,12 @@ using ErrorOr; using Shopizy.Application.Common.Security.Permissions; -using Shopizy.Application.Common.Security.Policies; using Shopizy.Application.Common.Security.Request; using Shopizy.Domain.Common.Enums; using Shopizy.Domain.Orders; namespace Shopizy.Application.Orders.Commands.CreateOrder; -[Authorize(Permissions = Permissions.Order.Create, Policies = Policy.Admin)] +[Authorize(Permissions = Permissions.Order.Create)] public record CreateOrderCommand( string PromoCode, int DeliveryMethod, diff --git a/src/Shopizy.Application/Orders/Commands/CreateOrder/CreateOrderCommandHandler.cs b/src/Shopizy.Application/Orders/Commands/CreateOrder/CreateOrderCommandHandler.cs index ebfb763..8b12406 100644 --- a/src/Shopizy.Application/Orders/Commands/CreateOrder/CreateOrderCommandHandler.cs +++ b/src/Shopizy.Application/Orders/Commands/CreateOrder/CreateOrderCommandHandler.cs @@ -43,6 +43,8 @@ CancellationToken cancellationToken // } // } + + var order = Order.Create( userId: UserId.Create(_currentUser.GetCurrentUserId()), promoCode: request.PromoCode, @@ -58,22 +60,27 @@ CancellationToken cancellationToken country: request.ShippingAddress.Country, zipCode: request.ShippingAddress.ZipCode ), - orderItems: products.ConvertAll(product => - { - var item = request.OrderItems.First(p => p.ProductId == product.Id.Value); - var photoUrl = - product.ProductImages.Count == 0 ? "" : product.ProductImages[0].ImageUrl; + orderItems: request + .OrderItems.ToList() + .ConvertAll(item => + { + var product = products.First(p => p.Id.Value == item.ProductId); + var photoUrl = + product.ProductImages.Count == 0 ? "" : product.ProductImages[0].ImageUrl; - return OrderItem.Create( - name: product.Name, - pictureUrl: photoUrl, - unitPrice: product.UnitPrice, - quantity: item.Quantity, - color: item.Color, - size: item.Size, - discount: product.Discount - ); - }) + return OrderItem.Create( + name: product.Name, + pictureUrl: photoUrl, + unitPrice: Price.CreateNew( + product.UnitPrice.Amount, + product.UnitPrice.Currency + ), + quantity: item.Quantity, + color: item.Color, + size: item.Size, + discount: product.Discount + ); + }) ); await _orderRepository.AddAsync(order); @@ -81,6 +88,9 @@ CancellationToken cancellationToken { return CustomErrors.Order.OrderNotCreated; } + + // remove cart items events + return order; } } diff --git a/src/Shopizy.Application/Payments/Commands/CardNotPresentSale/CardNotPresentSaleCommand.cs b/src/Shopizy.Application/Payments/Commands/CardNotPresentSale/CardNotPresentSaleCommand.cs index 8a884b0..3802431 100644 --- a/src/Shopizy.Application/Payments/Commands/CardNotPresentSale/CardNotPresentSaleCommand.cs +++ b/src/Shopizy.Application/Payments/Commands/CardNotPresentSale/CardNotPresentSaleCommand.cs @@ -1,11 +1,10 @@ using ErrorOr; using Shopizy.Application.Common.Security.Permissions; -using Shopizy.Application.Common.Security.Policies; using Shopizy.Application.Common.Security.Request; namespace Shopizy.Application.Payments.Commands.CardNotPresentSale; -[Authorize(Permissions = Permissions.Order.Get, Policies = Policy.Admin)] +[Authorize(Permissions = Permissions.Order.Create)] public record CardNotPresentSaleCommand( Guid OrderId, decimal Amount, diff --git a/src/Shopizy.Application/Payments/Commands/CashOnDeliverySale/CashOnDeliverySaleCommand.cs b/src/Shopizy.Application/Payments/Commands/CashOnDeliverySale/CashOnDeliverySaleCommand.cs index 91b3860..bce6cd5 100644 --- a/src/Shopizy.Application/Payments/Commands/CashOnDeliverySale/CashOnDeliverySaleCommand.cs +++ b/src/Shopizy.Application/Payments/Commands/CashOnDeliverySale/CashOnDeliverySaleCommand.cs @@ -1,11 +1,10 @@ using ErrorOr; using Shopizy.Application.Common.Security.Permissions; -using Shopizy.Application.Common.Security.Policies; using Shopizy.Application.Common.Security.Request; namespace Shopizy.Application.Payments.Commands.CashOnDeliverySale; -[Authorize(Permissions = Permissions.Order.Get, Policies = Policy.Admin)] +[Authorize(Permissions = Permissions.Order.Create)] public record CashOnDeliverySaleCommand( Guid OrderId, decimal Amount, diff --git a/src/Shopizy.Application/Products/Commands/DeleteProductImage/DeleteProductImageCommandHandler.cs b/src/Shopizy.Application/Products/Commands/DeleteProductImage/DeleteProductImageCommandHandler.cs index 5cbaf0d..9182e3f 100644 --- a/src/Shopizy.Application/Products/Commands/DeleteProductImage/DeleteProductImageCommandHandler.cs +++ b/src/Shopizy.Application/Products/Commands/DeleteProductImage/DeleteProductImageCommandHandler.cs @@ -27,8 +27,8 @@ CancellationToken cancellationToken return CustomErrors.Product.ProductNotFound; } - Domain.Products.Entities.ProductImage? prodImage = product.ProductImages.FirstOrDefault( - pi => pi.Id == ProductImageId.Create(cmd.ImageId) + var prodImage = product.ProductImages.FirstOrDefault(pi => + pi.Id == ProductImageId.Create(cmd.ImageId) ); if (prodImage is null) diff --git a/src/Shopizy.Contracts/Cart/AddProductToCartRequest.cs b/src/Shopizy.Contracts/Cart/AddProductToCartRequest.cs index 09336f5..dde0e5d 100644 --- a/src/Shopizy.Contracts/Cart/AddProductToCartRequest.cs +++ b/src/Shopizy.Contracts/Cart/AddProductToCartRequest.cs @@ -1,3 +1,3 @@ namespace Shopizy.Contracts.Cart; -public record AddProductToCartRequest(Guid ProductId, string Color, string Size); +public record AddProductToCartRequest(Guid ProductId, string Color, string Size, int Quantity); diff --git a/src/Shopizy.Contracts/Cart/CreateCartWithFirstProductRequest.cs b/src/Shopizy.Contracts/Cart/CreateCartWithFirstProductRequest.cs index 9626ab8..d536562 100644 --- a/src/Shopizy.Contracts/Cart/CreateCartWithFirstProductRequest.cs +++ b/src/Shopizy.Contracts/Cart/CreateCartWithFirstProductRequest.cs @@ -1,3 +1,8 @@ namespace Shopizy.Contracts.Cart; -public record CreateCartWithFirstProductRequest(Guid ProductId, string Color, string Size); +public record CreateCartWithFirstProductRequest( + Guid ProductId, + string Color, + string Size, + int Quantity +); diff --git a/src/Shopizy.Domain/Carts/Entities/CartItem.cs b/src/Shopizy.Domain/Carts/Entities/CartItem.cs index cd579d5..c92868b 100644 --- a/src/Shopizy.Domain/Carts/Entities/CartItem.cs +++ b/src/Shopizy.Domain/Carts/Entities/CartItem.cs @@ -13,9 +13,9 @@ public sealed class CartItem : Entity public string Size { get; private set; } public int Quantity { get; private set; } - public static CartItem Create(ProductId productId, string color, string size) + public static CartItem Create(ProductId productId, string color, string size, int quantity) { - return new CartItem(CartItemId.CreateUnique(), productId, color, size); + return new CartItem(CartItemId.CreateUnique(), productId, color, size, quantity); } public void UpdateQuantity(int quantity) @@ -23,13 +23,19 @@ public void UpdateQuantity(int quantity) Quantity = quantity; } - private CartItem(CartItemId CartItemId, ProductId productId, string color, string size) + private CartItem( + CartItemId CartItemId, + ProductId productId, + string color, + string size, + int quantity + ) : base(CartItemId) { ProductId = productId; Color = color; Size = size; - Quantity = 1; + Quantity = quantity; } private CartItem() { }