From a8ea4b41ee411d4d428981669a7e2be52f6852f2 Mon Sep 17 00:00:00 2001 From: lumijiez <59575049+lumijiez@users.noreply.github.com> Date: Thu, 26 Jun 2025 01:30:25 +0300 Subject: [PATCH] Holy moly...... --- ...eateAddressHandler.cs => CreateAddress.cs} | 2 +- ...erIdHandler.cs => GetAddressesByUserId.cs} | 2 +- ...yAddressesHandler.cs => GetMyAddresses.cs} | 2 +- ...teCategoryHandler.cs => CreateCategory.cs} | 2 +- ...teCategoryHandler.cs => DeleteCategory.cs} | 2 +- ...tCategoriesHandler.cs => GetCategories.cs} | 2 +- ...teCategoryHandler.cs => UpdateCategory.cs} | 2 +- .../{CreateOrderHandler.cs => CreateOrder.cs} | 5 +- ...GetOrderByIdHandler.cs => GetOrderById.cs} | 2 +- ...tIdHandler.cs => GetOrdersByMerchantId.cs} | 2 +- ...yUserIdHandler.cs => GetOrdersByUserId.cs} | 2 +- ...iantHandler.cs => CreateProductVariant.cs} | 2 +- ...iantHandler.cs => DeleteProductVariant.cs} | 2 +- ...riantsHandler.cs => GetProductVariants.cs} | 2 +- ...iantHandler.cs => UpdateProductVariant.cs} | 2 +- ...eateProductHandler.cs => CreateProduct.cs} | 2 +- ...leteProductHandler.cs => DeleteProduct.cs} | 2 +- .../Commands/Products/GetProductById.cs | 6 + .../{GetProductsHandler.cs => GetProducts.cs} | 2 +- ...dateProductCommand.cs => UpdateProduct.cs} | 6 +- ...teUserRoleHandler.cs => DeleteUserRole.cs} | 2 +- .../{GetAllRolesHandler.cs => GetAllRoles.cs} | 2 +- ...GetUserRolesHandler.cs => GetUserRoles.cs} | 2 +- ...rFullNameHandler.cs => SetUserFullName.cs} | 2 +- ...SetUserPhoneHandler.cs => SetUserPhone.cs} | 2 +- .../{SetUserRoleHandler.cs => SetUserRole.cs} | 2 +- .../Users/{SyncUserHandler.cs => SyncUser.cs} | 2 +- .../CreateAddressCommandValidator.cs | 117 ++++++++++++++++++ .../Orders/CreateOrderCommandValidator.cs | 76 ++++++++++++ .../Products/UpdateProductCommandValidator.cs | 2 +- .../Controllers/ProductsController.cs | 2 +- src/Imprink.WebApi/Startup.cs | 2 +- .../CreateCategoryHandlerIntegrationTest.cs | 8 +- .../UpdateCategoryHandlerUnitTest.cs | 8 +- 34 files changed, 238 insertions(+), 42 deletions(-) rename src/Imprink.Application/Commands/Addresses/{CreateAddressHandler.cs => CreateAddress.cs} (98%) rename src/Imprink.Application/Commands/Addresses/{GetAddressesByUserIdHandler.cs => GetAddressesByUserId.cs} (96%) rename src/Imprink.Application/Commands/Addresses/{GetMyAddressesHandler.cs => GetMyAddresses.cs} (95%) rename src/Imprink.Application/Commands/Categories/{CreateCategoryHandler.cs => CreateCategory.cs} (98%) rename src/Imprink.Application/Commands/Categories/{DeleteCategoryHandler.cs => DeleteCategory.cs} (96%) rename src/Imprink.Application/Commands/Categories/{GetCategoriesHandler.cs => GetCategories.cs} (97%) rename src/Imprink.Application/Commands/Categories/{UpdateCategoryHandler.cs => UpdateCategory.cs} (98%) rename src/Imprink.Application/Commands/Orders/{CreateOrderHandler.cs => CreateOrder.cs} (96%) rename src/Imprink.Application/Commands/Orders/{GetOrderByIdHandler.cs => GetOrderById.cs} (96%) rename src/Imprink.Application/Commands/Orders/{GetOrdersByMerchantIdHandler.cs => GetOrdersByMerchantId.cs} (96%) rename src/Imprink.Application/Commands/Orders/{GetOrdersByUserIdHandler.cs => GetOrdersByUserId.cs} (96%) rename src/Imprink.Application/Commands/ProductVariants/{CreateProductVariantHandler.cs => CreateProductVariant.cs} (97%) rename src/Imprink.Application/Commands/ProductVariants/{DeleteProductVariantHandler.cs => DeleteProductVariant.cs} (96%) rename src/Imprink.Application/Commands/ProductVariants/{GetProductVariantsHandler.cs => GetProductVariants.cs} (97%) rename src/Imprink.Application/Commands/ProductVariants/{UpdateProductVariantHandler.cs => UpdateProductVariant.cs} (97%) rename src/Imprink.Application/Commands/Products/{CreateProductHandler.cs => CreateProduct.cs} (97%) rename src/Imprink.Application/Commands/Products/{DeleteProductHandler.cs => DeleteProduct.cs} (95%) create mode 100644 src/Imprink.Application/Commands/Products/GetProductById.cs rename src/Imprink.Application/Commands/Products/{GetProductsHandler.cs => GetProducts.cs} (98%) rename src/Imprink.Application/Commands/Products/{UpdateProductCommand.cs => UpdateProduct.cs} (95%) rename src/Imprink.Application/Commands/Users/{DeleteUserRoleHandler.cs => DeleteUserRole.cs} (97%) rename src/Imprink.Application/Commands/Users/{GetAllRolesHandler.cs => GetAllRoles.cs} (94%) rename src/Imprink.Application/Commands/Users/{GetUserRolesHandler.cs => GetUserRoles.cs} (96%) rename src/Imprink.Application/Commands/Users/{SetUserFullNameHandler.cs => SetUserFullName.cs} (97%) rename src/Imprink.Application/Commands/Users/{SetUserPhoneHandler.cs => SetUserPhone.cs} (97%) rename src/Imprink.Application/Commands/Users/{SetUserRoleHandler.cs => SetUserRole.cs} (97%) rename src/Imprink.Application/Commands/Users/{SyncUserHandler.cs => SyncUser.cs} (97%) create mode 100644 src/Imprink.Application/Validation/Addresses/CreateAddressCommandValidator.cs create mode 100644 src/Imprink.Application/Validation/Orders/CreateOrderCommandValidator.cs diff --git a/src/Imprink.Application/Commands/Addresses/CreateAddressHandler.cs b/src/Imprink.Application/Commands/Addresses/CreateAddress.cs similarity index 98% rename from src/Imprink.Application/Commands/Addresses/CreateAddressHandler.cs rename to src/Imprink.Application/Commands/Addresses/CreateAddress.cs index 9e9a94c..96b8be8 100644 --- a/src/Imprink.Application/Commands/Addresses/CreateAddressHandler.cs +++ b/src/Imprink.Application/Commands/Addresses/CreateAddress.cs @@ -27,7 +27,7 @@ public class CreateAddressCommand : IRequest public bool IsActive { get; set; } = true; } -public class CreateAddressHandler( +public class CreateAddress( IUnitOfWork uw, IMapper mapper, ICurrentUserService userService) diff --git a/src/Imprink.Application/Commands/Addresses/GetAddressesByUserIdHandler.cs b/src/Imprink.Application/Commands/Addresses/GetAddressesByUserId.cs similarity index 96% rename from src/Imprink.Application/Commands/Addresses/GetAddressesByUserIdHandler.cs rename to src/Imprink.Application/Commands/Addresses/GetAddressesByUserId.cs index 5816518..ab5a66e 100644 --- a/src/Imprink.Application/Commands/Addresses/GetAddressesByUserIdHandler.cs +++ b/src/Imprink.Application/Commands/Addresses/GetAddressesByUserId.cs @@ -12,7 +12,7 @@ public class GetAddressesByUserIdQuery : IRequest> public string? AddressType { get; set; } } -public class GetAddressesByUserIdHandler( +public class GetAddressesByUserId( IUnitOfWork uw, IMapper mapper) : IRequestHandler> diff --git a/src/Imprink.Application/Commands/Addresses/GetMyAddressesHandler.cs b/src/Imprink.Application/Commands/Addresses/GetMyAddresses.cs similarity index 95% rename from src/Imprink.Application/Commands/Addresses/GetMyAddressesHandler.cs rename to src/Imprink.Application/Commands/Addresses/GetMyAddresses.cs index 3f7a565..1915d04 100644 --- a/src/Imprink.Application/Commands/Addresses/GetMyAddressesHandler.cs +++ b/src/Imprink.Application/Commands/Addresses/GetMyAddresses.cs @@ -8,7 +8,7 @@ namespace Imprink.Application.Commands.Addresses; public class GetMyAddressesQuery : IRequest>; -public class GetMyAddressesHandler( +public class GetMyAddresses( IUnitOfWork uw, IMapper mapper, ICurrentUserService userService) diff --git a/src/Imprink.Application/Commands/Categories/CreateCategoryHandler.cs b/src/Imprink.Application/Commands/Categories/CreateCategory.cs similarity index 98% rename from src/Imprink.Application/Commands/Categories/CreateCategoryHandler.cs rename to src/Imprink.Application/Commands/Categories/CreateCategory.cs index d690cc4..44a95c1 100644 --- a/src/Imprink.Application/Commands/Categories/CreateCategoryHandler.cs +++ b/src/Imprink.Application/Commands/Categories/CreateCategory.cs @@ -14,7 +14,7 @@ public class CreateCategoryCommand : IRequest public Guid? ParentCategoryId { get; set; } } -public class CreateCategoryHandler( +public class CreateCategory( IUnitOfWork unitOfWork) : IRequestHandler { diff --git a/src/Imprink.Application/Commands/Categories/DeleteCategoryHandler.cs b/src/Imprink.Application/Commands/Categories/DeleteCategory.cs similarity index 96% rename from src/Imprink.Application/Commands/Categories/DeleteCategoryHandler.cs rename to src/Imprink.Application/Commands/Categories/DeleteCategory.cs index 3becc84..172b46b 100644 --- a/src/Imprink.Application/Commands/Categories/DeleteCategoryHandler.cs +++ b/src/Imprink.Application/Commands/Categories/DeleteCategory.cs @@ -7,7 +7,7 @@ public class DeleteCategoryCommand : IRequest public Guid Id { get; init; } } -public class DeleteCategoryHandler( +public class DeleteCategory( IUnitOfWork unitOfWork) : IRequestHandler { diff --git a/src/Imprink.Application/Commands/Categories/GetCategoriesHandler.cs b/src/Imprink.Application/Commands/Categories/GetCategories.cs similarity index 97% rename from src/Imprink.Application/Commands/Categories/GetCategoriesHandler.cs rename to src/Imprink.Application/Commands/Categories/GetCategories.cs index 1e5fcbd..0a28126 100644 --- a/src/Imprink.Application/Commands/Categories/GetCategoriesHandler.cs +++ b/src/Imprink.Application/Commands/Categories/GetCategories.cs @@ -10,7 +10,7 @@ public class GetCategoriesQuery : IRequest> public bool RootCategoriesOnly { get; set; } = false; } -public class GetCategoriesHandler( +public class GetCategories( IUnitOfWork unitOfWork) : IRequestHandler> { diff --git a/src/Imprink.Application/Commands/Categories/UpdateCategoryHandler.cs b/src/Imprink.Application/Commands/Categories/UpdateCategory.cs similarity index 98% rename from src/Imprink.Application/Commands/Categories/UpdateCategoryHandler.cs rename to src/Imprink.Application/Commands/Categories/UpdateCategory.cs index 975d3c5..aa2db76 100644 --- a/src/Imprink.Application/Commands/Categories/UpdateCategoryHandler.cs +++ b/src/Imprink.Application/Commands/Categories/UpdateCategory.cs @@ -15,7 +15,7 @@ public class UpdateCategoryCommand : IRequest public Guid? ParentCategoryId { get; set; } } -public class UpdateCategoryHandler( +public class UpdateCategory( IUnitOfWork unitOfWork) : IRequestHandler { diff --git a/src/Imprink.Application/Commands/Orders/CreateOrderHandler.cs b/src/Imprink.Application/Commands/Orders/CreateOrder.cs similarity index 96% rename from src/Imprink.Application/Commands/Orders/CreateOrderHandler.cs rename to src/Imprink.Application/Commands/Orders/CreateOrder.cs index 3784708..024a32e 100644 --- a/src/Imprink.Application/Commands/Orders/CreateOrderHandler.cs +++ b/src/Imprink.Application/Commands/Orders/CreateOrder.cs @@ -12,17 +12,14 @@ public class CreateOrderCommand : IRequest public int Quantity { get; set; } public Guid ProductId { get; set; } public Guid ProductVariantId { get; set; } - public string? Notes { get; set; } - public string? MerchantId { get; set; } public string? ComposingImageUrl { get; set; } public string[]? OriginalImageUrls { get; set; } = []; public string? CustomizationImageUrl { get; set; } = null!; public string? CustomizationDescription { get; set; } = null!; - public Guid AddressId { get; set; } } -public class CreateOrderHandler( +public class CreateOrder( IUnitOfWork uw, IMapper mapper, ICurrentUserService userService) diff --git a/src/Imprink.Application/Commands/Orders/GetOrderByIdHandler.cs b/src/Imprink.Application/Commands/Orders/GetOrderById.cs similarity index 96% rename from src/Imprink.Application/Commands/Orders/GetOrderByIdHandler.cs rename to src/Imprink.Application/Commands/Orders/GetOrderById.cs index f9d0770..8749cb3 100644 --- a/src/Imprink.Application/Commands/Orders/GetOrderByIdHandler.cs +++ b/src/Imprink.Application/Commands/Orders/GetOrderById.cs @@ -11,7 +11,7 @@ public class GetOrderByIdQuery : IRequest public bool IncludeDetails { get; set; } } -public class GetOrderByIdHandler( +public class GetOrderById( IUnitOfWork uw, IMapper mapper) : IRequestHandler diff --git a/src/Imprink.Application/Commands/Orders/GetOrdersByMerchantIdHandler.cs b/src/Imprink.Application/Commands/Orders/GetOrdersByMerchantId.cs similarity index 96% rename from src/Imprink.Application/Commands/Orders/GetOrdersByMerchantIdHandler.cs rename to src/Imprink.Application/Commands/Orders/GetOrdersByMerchantId.cs index 93b30ac..10b8080 100644 --- a/src/Imprink.Application/Commands/Orders/GetOrdersByMerchantIdHandler.cs +++ b/src/Imprink.Application/Commands/Orders/GetOrdersByMerchantId.cs @@ -11,7 +11,7 @@ public class GetOrdersByMerchantIdQuery : IRequest> public bool IncludeDetails { get; set; } } -public class GetOrdersByMerchantIdHandler( +public class GetOrdersByMerchantId( IUnitOfWork uw, IMapper mapper) : IRequestHandler> diff --git a/src/Imprink.Application/Commands/Orders/GetOrdersByUserIdHandler.cs b/src/Imprink.Application/Commands/Orders/GetOrdersByUserId.cs similarity index 96% rename from src/Imprink.Application/Commands/Orders/GetOrdersByUserIdHandler.cs rename to src/Imprink.Application/Commands/Orders/GetOrdersByUserId.cs index 41dd354..7889877 100644 --- a/src/Imprink.Application/Commands/Orders/GetOrdersByUserIdHandler.cs +++ b/src/Imprink.Application/Commands/Orders/GetOrdersByUserId.cs @@ -11,7 +11,7 @@ public class GetOrdersByUserIdQuery : IRequest> public bool IncludeDetails { get; set; } } -public class GetOrdersByUserIdHandler( +public class GetOrdersByUserId( IUnitOfWork uw, IMapper mapper) : IRequestHandler> diff --git a/src/Imprink.Application/Commands/ProductVariants/CreateProductVariantHandler.cs b/src/Imprink.Application/Commands/ProductVariants/CreateProductVariant.cs similarity index 97% rename from src/Imprink.Application/Commands/ProductVariants/CreateProductVariantHandler.cs rename to src/Imprink.Application/Commands/ProductVariants/CreateProductVariant.cs index 1444882..ba0db6f 100644 --- a/src/Imprink.Application/Commands/ProductVariants/CreateProductVariantHandler.cs +++ b/src/Imprink.Application/Commands/ProductVariants/CreateProductVariant.cs @@ -17,7 +17,7 @@ public class CreateProductVariantCommand : IRequest public bool IsActive { get; set; } = true; } -public class CreateProductVariantHandler( +public class CreateProductVariant( IUnitOfWork unitOfWork, IMapper mapper) : IRequestHandler diff --git a/src/Imprink.Application/Commands/ProductVariants/DeleteProductVariantHandler.cs b/src/Imprink.Application/Commands/ProductVariants/DeleteProductVariant.cs similarity index 96% rename from src/Imprink.Application/Commands/ProductVariants/DeleteProductVariantHandler.cs rename to src/Imprink.Application/Commands/ProductVariants/DeleteProductVariant.cs index d461975..3fda9f1 100644 --- a/src/Imprink.Application/Commands/ProductVariants/DeleteProductVariantHandler.cs +++ b/src/Imprink.Application/Commands/ProductVariants/DeleteProductVariant.cs @@ -7,7 +7,7 @@ public class DeleteProductVariantCommand : IRequest public Guid Id { get; set; } } -public class DeleteProductVariantHandler( +public class DeleteProductVariant( IUnitOfWork unitOfWork) : IRequestHandler { diff --git a/src/Imprink.Application/Commands/ProductVariants/GetProductVariantsHandler.cs b/src/Imprink.Application/Commands/ProductVariants/GetProductVariants.cs similarity index 97% rename from src/Imprink.Application/Commands/ProductVariants/GetProductVariantsHandler.cs rename to src/Imprink.Application/Commands/ProductVariants/GetProductVariants.cs index 1e56414..a7ed4ac 100644 --- a/src/Imprink.Application/Commands/ProductVariants/GetProductVariantsHandler.cs +++ b/src/Imprink.Application/Commands/ProductVariants/GetProductVariants.cs @@ -12,7 +12,7 @@ public class GetProductVariantsQuery : IRequest> public bool InStockOnly { get; set; } = false; } -public class GetProductVariantsHandler( +public class GetProductVariants( IUnitOfWork unitOfWork, IMapper mapper) : IRequestHandler> diff --git a/src/Imprink.Application/Commands/ProductVariants/UpdateProductVariantHandler.cs b/src/Imprink.Application/Commands/ProductVariants/UpdateProductVariant.cs similarity index 97% rename from src/Imprink.Application/Commands/ProductVariants/UpdateProductVariantHandler.cs rename to src/Imprink.Application/Commands/ProductVariants/UpdateProductVariant.cs index e45232c..b91ee4b 100644 --- a/src/Imprink.Application/Commands/ProductVariants/UpdateProductVariantHandler.cs +++ b/src/Imprink.Application/Commands/ProductVariants/UpdateProductVariant.cs @@ -18,7 +18,7 @@ public class UpdateProductVariantCommand : IRequest public bool IsActive { get; set; } } -public class UpdateProductVariantHandler( +public class UpdateProductVariant( IUnitOfWork unitOfWork, IMapper mapper) : IRequestHandler diff --git a/src/Imprink.Application/Commands/Products/CreateProductHandler.cs b/src/Imprink.Application/Commands/Products/CreateProduct.cs similarity index 97% rename from src/Imprink.Application/Commands/Products/CreateProductHandler.cs rename to src/Imprink.Application/Commands/Products/CreateProduct.cs index 7b93c3c..9f10a4e 100644 --- a/src/Imprink.Application/Commands/Products/CreateProductHandler.cs +++ b/src/Imprink.Application/Commands/Products/CreateProduct.cs @@ -16,7 +16,7 @@ public class CreateProductCommand : IRequest public Guid? CategoryId { get; set; } } -public class CreateProductHandler( +public class CreateProduct( IUnitOfWork uw, IMapper mapper) : IRequestHandler diff --git a/src/Imprink.Application/Commands/Products/DeleteProductHandler.cs b/src/Imprink.Application/Commands/Products/DeleteProduct.cs similarity index 95% rename from src/Imprink.Application/Commands/Products/DeleteProductHandler.cs rename to src/Imprink.Application/Commands/Products/DeleteProduct.cs index c839fad..a032586 100644 --- a/src/Imprink.Application/Commands/Products/DeleteProductHandler.cs +++ b/src/Imprink.Application/Commands/Products/DeleteProduct.cs @@ -8,7 +8,7 @@ public class DeleteProductCommand : IRequest public Guid Id { get; set; } } -public class DeleteProductHandler( +public class DeleteProduct( IUnitOfWork uw) : IRequestHandler { diff --git a/src/Imprink.Application/Commands/Products/GetProductById.cs b/src/Imprink.Application/Commands/Products/GetProductById.cs new file mode 100644 index 0000000..565aaaf --- /dev/null +++ b/src/Imprink.Application/Commands/Products/GetProductById.cs @@ -0,0 +1,6 @@ +namespace Imprink.Application.Commands.Products; + +public class GetProductById +{ + +} \ No newline at end of file diff --git a/src/Imprink.Application/Commands/Products/GetProductsHandler.cs b/src/Imprink.Application/Commands/Products/GetProducts.cs similarity index 98% rename from src/Imprink.Application/Commands/Products/GetProductsHandler.cs rename to src/Imprink.Application/Commands/Products/GetProducts.cs index 0ef998d..8b3c97d 100644 --- a/src/Imprink.Application/Commands/Products/GetProductsHandler.cs +++ b/src/Imprink.Application/Commands/Products/GetProducts.cs @@ -9,7 +9,7 @@ public class GetProductsQuery : IRequest> public ProductFilterParameters FilterParameters { get; set; } = new(); } -public class GetProductsHandler( +public class GetProducts( IUnitOfWork unitOfWork) : IRequestHandler> { diff --git a/src/Imprink.Application/Commands/Products/UpdateProductCommand.cs b/src/Imprink.Application/Commands/Products/UpdateProduct.cs similarity index 95% rename from src/Imprink.Application/Commands/Products/UpdateProductCommand.cs rename to src/Imprink.Application/Commands/Products/UpdateProduct.cs index c60cbb6..28defbe 100644 --- a/src/Imprink.Application/Commands/Products/UpdateProductCommand.cs +++ b/src/Imprink.Application/Commands/Products/UpdateProduct.cs @@ -4,7 +4,7 @@ using MediatR; namespace Imprink.Application.Commands.Products; -public class UpdateProductCommand : IRequest +public class UpdateProduct : IRequest { public Guid Id { get; set; } public string Name { get; set; } = null!; @@ -18,10 +18,10 @@ public class UpdateProductCommand : IRequest public class UpdateProductHandler( IUnitOfWork unitOfWork) - : IRequestHandler + : IRequestHandler { public async Task Handle( - UpdateProductCommand request, + UpdateProduct request, CancellationToken cancellationToken) { await unitOfWork.BeginTransactionAsync(cancellationToken); diff --git a/src/Imprink.Application/Commands/Users/DeleteUserRoleHandler.cs b/src/Imprink.Application/Commands/Users/DeleteUserRole.cs similarity index 97% rename from src/Imprink.Application/Commands/Users/DeleteUserRoleHandler.cs rename to src/Imprink.Application/Commands/Users/DeleteUserRole.cs index 6b55762..e648abb 100644 --- a/src/Imprink.Application/Commands/Users/DeleteUserRoleHandler.cs +++ b/src/Imprink.Application/Commands/Users/DeleteUserRole.cs @@ -7,7 +7,7 @@ namespace Imprink.Application.Commands.Users; public record DeleteUserRoleCommand(string Sub, Guid RoleId) : IRequest; -public class DeleteUserRoleHandler( +public class DeleteUserRole( IUnitOfWork uw, IMapper mapper) : IRequestHandler diff --git a/src/Imprink.Application/Commands/Users/GetAllRolesHandler.cs b/src/Imprink.Application/Commands/Users/GetAllRoles.cs similarity index 94% rename from src/Imprink.Application/Commands/Users/GetAllRolesHandler.cs rename to src/Imprink.Application/Commands/Users/GetAllRoles.cs index ec4d093..d3f8ba3 100644 --- a/src/Imprink.Application/Commands/Users/GetAllRolesHandler.cs +++ b/src/Imprink.Application/Commands/Users/GetAllRoles.cs @@ -6,7 +6,7 @@ namespace Imprink.Application.Commands.Users; public record GetAllRolesCommand : IRequest>; -public class GetAllRolesHandler( +public class GetAllRoles( IUnitOfWork uw, IMapper mapper): IRequestHandler> { diff --git a/src/Imprink.Application/Commands/Users/GetUserRolesHandler.cs b/src/Imprink.Application/Commands/Users/GetUserRoles.cs similarity index 96% rename from src/Imprink.Application/Commands/Users/GetUserRolesHandler.cs rename to src/Imprink.Application/Commands/Users/GetUserRoles.cs index 5517ee0..5e3bb1d 100644 --- a/src/Imprink.Application/Commands/Users/GetUserRolesHandler.cs +++ b/src/Imprink.Application/Commands/Users/GetUserRoles.cs @@ -7,7 +7,7 @@ namespace Imprink.Application.Commands.Users; public record GetUserRolesCommand(string Sub) : IRequest>; -public class GetUserRolesHandler( +public class GetUserRoles( IUnitOfWork uw, IMapper mapper) : IRequestHandler> diff --git a/src/Imprink.Application/Commands/Users/SetUserFullNameHandler.cs b/src/Imprink.Application/Commands/Users/SetUserFullName.cs similarity index 97% rename from src/Imprink.Application/Commands/Users/SetUserFullNameHandler.cs rename to src/Imprink.Application/Commands/Users/SetUserFullName.cs index 0f4a1ca..fd22823 100644 --- a/src/Imprink.Application/Commands/Users/SetUserFullNameHandler.cs +++ b/src/Imprink.Application/Commands/Users/SetUserFullName.cs @@ -8,7 +8,7 @@ namespace Imprink.Application.Commands.Users; public record SetUserFullNameCommand(string FirstName, string LastName) : IRequest; -public class SetUserFullNameHandler( +public class SetUserFullName( IUnitOfWork uw, IMapper mapper, ICurrentUserService userService) diff --git a/src/Imprink.Application/Commands/Users/SetUserPhoneHandler.cs b/src/Imprink.Application/Commands/Users/SetUserPhone.cs similarity index 97% rename from src/Imprink.Application/Commands/Users/SetUserPhoneHandler.cs rename to src/Imprink.Application/Commands/Users/SetUserPhone.cs index f3876e7..38ede88 100644 --- a/src/Imprink.Application/Commands/Users/SetUserPhoneHandler.cs +++ b/src/Imprink.Application/Commands/Users/SetUserPhone.cs @@ -8,7 +8,7 @@ namespace Imprink.Application.Commands.Users; public record SetUserPhoneCommand(string PhoneNumber) : IRequest; -public class SetUserPhoneHandler( +public class SetUserPhone( IUnitOfWork uw, IMapper mapper, ICurrentUserService userService) diff --git a/src/Imprink.Application/Commands/Users/SetUserRoleHandler.cs b/src/Imprink.Application/Commands/Users/SetUserRole.cs similarity index 97% rename from src/Imprink.Application/Commands/Users/SetUserRoleHandler.cs rename to src/Imprink.Application/Commands/Users/SetUserRole.cs index e826982..63d54bb 100644 --- a/src/Imprink.Application/Commands/Users/SetUserRoleHandler.cs +++ b/src/Imprink.Application/Commands/Users/SetUserRole.cs @@ -8,7 +8,7 @@ namespace Imprink.Application.Commands.Users; public record SetUserRoleCommand(string Sub, Guid RoleId) : IRequest; -public class SetUserRoleHandler( +public class SetUserRole( IUnitOfWork uw, IMapper mapper) : IRequestHandler diff --git a/src/Imprink.Application/Commands/Users/SyncUserHandler.cs b/src/Imprink.Application/Commands/Users/SyncUser.cs similarity index 97% rename from src/Imprink.Application/Commands/Users/SyncUserHandler.cs rename to src/Imprink.Application/Commands/Users/SyncUser.cs index e30da35..7f22f21 100644 --- a/src/Imprink.Application/Commands/Users/SyncUserHandler.cs +++ b/src/Imprink.Application/Commands/Users/SyncUser.cs @@ -7,7 +7,7 @@ namespace Imprink.Application.Commands.Users; public record SyncUserCommand(Auth0User User) : IRequest; -public class SyncUserHandler( +public class SyncUser( IUnitOfWork uw, IMapper mapper) : IRequestHandler diff --git a/src/Imprink.Application/Validation/Addresses/CreateAddressCommandValidator.cs b/src/Imprink.Application/Validation/Addresses/CreateAddressCommandValidator.cs new file mode 100644 index 0000000..28f4db2 --- /dev/null +++ b/src/Imprink.Application/Validation/Addresses/CreateAddressCommandValidator.cs @@ -0,0 +1,117 @@ +using FluentValidation; +using Imprink.Application.Commands.Addresses; + +namespace Imprink.Application.Validation.Addresses; + +public class CreateAddressCommandValidator : AbstractValidator +{ + public CreateAddressCommandValidator() + { + RuleFor(x => x.AddressType) + .NotEmpty() + .WithMessage("Address type is required.") + .MaximumLength(50) + .WithMessage("Address type must not exceed 50 characters.") + .Must(BeValidAddressType) + .WithMessage("Address type must be one of: Home, Work, Billing, Shipping, Other."); + + RuleFor(x => x.FirstName) + .MaximumLength(100) + .WithMessage("First name must not exceed 100 characters.") + .Matches(@"^[a-zA-Z\s\-'\.]*$") + .When(x => !string.IsNullOrEmpty(x.FirstName)) + .WithMessage("First name can only contain letters, spaces, hyphens, apostrophes, and periods."); + + RuleFor(x => x.LastName) + .MaximumLength(100) + .WithMessage("Last name must not exceed 100 characters.") + .Matches(@"^[a-zA-Z\s\-'\.]*$") + .When(x => !string.IsNullOrEmpty(x.LastName)) + .WithMessage("Last name can only contain letters, spaces, hyphens, apostrophes, and periods."); + + RuleFor(x => x.Company) + .MaximumLength(200) + .WithMessage("Company name must not exceed 200 characters."); + + RuleFor(x => x.AddressLine1) + .NotEmpty() + .WithMessage("Address line 1 is required.") + .MaximumLength(255) + .WithMessage("Address line 1 must not exceed 255 characters."); + + RuleFor(x => x.AddressLine2) + .MaximumLength(255) + .WithMessage("Address line 2 must not exceed 255 characters."); + + RuleFor(x => x.ApartmentNumber) + .MaximumLength(20) + .WithMessage("Apartment number must not exceed 20 characters."); + + RuleFor(x => x.BuildingNumber) + .MaximumLength(20) + .WithMessage("Building number must not exceed 20 characters."); + + RuleFor(x => x.Floor) + .MaximumLength(20) + .WithMessage("Floor must not exceed 20 characters."); + + RuleFor(x => x.City) + .NotEmpty() + .WithMessage("City is required.") + .MaximumLength(100) + .WithMessage("City must not exceed 100 characters.") + .Matches(@"^[a-zA-Z\s\-'\.]*$") + .WithMessage("City can only contain letters, spaces, hyphens, apostrophes, and periods."); + + RuleFor(x => x.State) + .NotEmpty() + .WithMessage("State is required.") + .MaximumLength(100) + .WithMessage("State must not exceed 100 characters."); + + RuleFor(x => x.PostalCode) + .NotEmpty() + .WithMessage("Postal code is required.") + .MaximumLength(20) + .WithMessage("Postal code must not exceed 20 characters.") + .Matches(@"^[a-zA-Z0-9\s\-]*$") + .WithMessage("Postal code can only contain letters, numbers, spaces, and hyphens."); + + RuleFor(x => x.Country) + .NotEmpty() + .WithMessage("Country is required.") + .MaximumLength(100) + .WithMessage("Country must not exceed 100 characters.") + .Matches(@"^[a-zA-Z\s\-'\.]*$") + .WithMessage("Country can only contain letters, spaces, hyphens, apostrophes, and periods."); + + RuleFor(x => x.PhoneNumber) + .MaximumLength(20) + .WithMessage("Phone number must not exceed 20 characters.") + .Matches(@"^[\+]?[0-9\s\-\(\)\.]*$") + .When(x => !string.IsNullOrEmpty(x.PhoneNumber)) + .WithMessage("Phone number format is invalid. Use numbers, spaces, hyphens, parentheses, periods, and optional + prefix."); + + RuleFor(x => x.Instructions) + .MaximumLength(500) + .WithMessage("Instructions must not exceed 500 characters."); + + RuleFor(x => x) + .Must(HaveNameOrCompany) + .WithMessage("Either first name and last name, or company name must be provided.") + .WithName("Address"); + } + + private static bool BeValidAddressType(string addressType) + { + var validTypes = new[] { "Home", "Work", "Billing", "Shipping", "Other" }; + return validTypes.Contains(addressType, StringComparer.OrdinalIgnoreCase); + } + + private static bool HaveNameOrCompany(CreateAddressCommand command) + { + var hasName = !string.IsNullOrWhiteSpace(command.FirstName) && !string.IsNullOrWhiteSpace(command.LastName); + var hasCompany = !string.IsNullOrWhiteSpace(command.Company); + return hasName || hasCompany; + } +} \ No newline at end of file diff --git a/src/Imprink.Application/Validation/Orders/CreateOrderCommandValidator.cs b/src/Imprink.Application/Validation/Orders/CreateOrderCommandValidator.cs new file mode 100644 index 0000000..5f30658 --- /dev/null +++ b/src/Imprink.Application/Validation/Orders/CreateOrderCommandValidator.cs @@ -0,0 +1,76 @@ +using FluentValidation; +using Imprink.Application.Commands.Orders; + +namespace Imprink.Application.Validation.Orders; + +public class CreateOrderCommandValidator : AbstractValidator +{ + public CreateOrderCommandValidator() + { + RuleFor(x => x.Quantity) + .GreaterThan(0) + .WithMessage("Quantity must be greater than 0.") + .LessThanOrEqualTo(1000) + .WithMessage("Quantity cannot exceed 1000 items per order."); + + RuleFor(x => x.ProductId) + .NotEmpty() + .WithMessage("Product ID is required."); + + RuleFor(x => x.ProductVariantId) + .NotEmpty() + .WithMessage("Product variant ID is required."); + + RuleFor(x => x.AddressId) + .NotEmpty() + .WithMessage("Address ID is required."); + + RuleFor(x => x.ComposingImageUrl) + .MaximumLength(2048) + .WithMessage("Composing image URL must not exceed 2048 characters.") + .Must(BeValidUrl) + .When(x => !string.IsNullOrEmpty(x.ComposingImageUrl)) + .WithMessage("Composing image URL must be a valid URL."); + + RuleFor(x => x.CustomizationImageUrl) + .MaximumLength(2048) + .WithMessage("Customization image URL must not exceed 2048 characters.") + .Must(BeValidUrl) + .When(x => !string.IsNullOrEmpty(x.CustomizationImageUrl)) + .WithMessage("Customization image URL must be a valid URL."); + + RuleFor(x => x.CustomizationDescription) + .MaximumLength(2000) + .WithMessage("Customization description must not exceed 2000 characters."); + + RuleFor(x => x.OriginalImageUrls) + .Must(HaveValidImageUrls) + .When(x => x.OriginalImageUrls != null && x.OriginalImageUrls.Length > 0) + .WithMessage("All original image URLs must be valid URLs.") + .Must(x => x == null || x.Length <= 10) + .WithMessage("Cannot have more than 10 original images."); + + RuleForEach(x => x.OriginalImageUrls) + .MaximumLength(2048) + .WithMessage("Each original image URL must not exceed 2048 characters.") + .Must(BeValidUrl) + .WithMessage("Each original image URL must be a valid URL."); + } + + private static bool BeValidUrl(string url) + { + if (string.IsNullOrEmpty(url)) + return true; + + return Uri.TryCreate(url, UriKind.Absolute, out var result) + && (result.Scheme == Uri.UriSchemeHttp || result.Scheme == Uri.UriSchemeHttps); + } + + private static bool HaveValidImageUrls(string[]? urls) + { + if (urls == null || urls.Length == 0) + return true; + + return urls.All(url => !string.IsNullOrEmpty(url) && BeValidUrl(url)); + } +} \ No newline at end of file diff --git a/src/Imprink.Application/Validation/Products/UpdateProductCommandValidator.cs b/src/Imprink.Application/Validation/Products/UpdateProductCommandValidator.cs index 3607612..21ac02d 100644 --- a/src/Imprink.Application/Validation/Products/UpdateProductCommandValidator.cs +++ b/src/Imprink.Application/Validation/Products/UpdateProductCommandValidator.cs @@ -3,7 +3,7 @@ using Imprink.Application.Commands.Products; namespace Imprink.Application.Validation.Products; -public class UpdateProductCommandValidator : AbstractValidator +public class UpdateProductCommandValidator : AbstractValidator { public UpdateProductCommandValidator() { diff --git a/src/Imprink.WebApi/Controllers/ProductsController.cs b/src/Imprink.WebApi/Controllers/ProductsController.cs index 9c08e74..6d7c0b2 100644 --- a/src/Imprink.WebApi/Controllers/ProductsController.cs +++ b/src/Imprink.WebApi/Controllers/ProductsController.cs @@ -34,7 +34,7 @@ public class ProductsController(IMediator mediator) : ControllerBase [Authorize(Roles = "Admin")] public async Task> UpdateProduct( Guid id, - [FromBody] UpdateProductCommand command) + [FromBody] UpdateProduct command) { if (id != command.Id) return BadRequest("ID mismatch"); diff --git a/src/Imprink.WebApi/Startup.cs b/src/Imprink.WebApi/Startup.cs index 564050c..06c954b 100644 --- a/src/Imprink.WebApi/Startup.cs +++ b/src/Imprink.WebApi/Startup.cs @@ -24,7 +24,7 @@ public static class Startup services.AddDatabaseContexts(builder.Configuration); - services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(CreateProductHandler).Assembly)); + services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(CreateProduct).Assembly)); services.AddValidatorsFromAssembly(typeof(Auth0UserValidator).Assembly); diff --git a/tests/Imprink.Application.Tests/CreateCategoryHandlerIntegrationTest.cs b/tests/Imprink.Application.Tests/CreateCategoryHandlerIntegrationTest.cs index 67430c4..3f95438 100644 --- a/tests/Imprink.Application.Tests/CreateCategoryHandlerIntegrationTest.cs +++ b/tests/Imprink.Application.Tests/CreateCategoryHandlerIntegrationTest.cs @@ -15,7 +15,7 @@ public class CreateCategoryHandlerIntegrationTest : IDisposable { private readonly ApplicationDbContext _context; private readonly IServiceProvider _serviceProvider; - private readonly CreateCategoryHandler _handler; + private readonly CreateCategory _handler; private readonly SqliteConnection _connection; public CreateCategoryHandlerIntegrationTest() @@ -38,11 +38,11 @@ public class CreateCategoryHandlerIntegrationTest : IDisposable services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); _serviceProvider = services.BuildServiceProvider(); _context = _serviceProvider.GetRequiredService(); - _handler = _serviceProvider.GetRequiredService(); + _handler = _serviceProvider.GetRequiredService(); _context.Database.EnsureCreated(); } @@ -216,7 +216,7 @@ public class CreateCategoryHandlerIntegrationTest : IDisposable var initialCount = await _context.Categories.CountAsync(); - var handler = _serviceProvider.GetRequiredService(); + var handler = _serviceProvider.GetRequiredService(); var result = await handler.Handle(command, CancellationToken.None); diff --git a/tests/Imprink.Application.Tests/UpdateCategoryHandlerUnitTest.cs b/tests/Imprink.Application.Tests/UpdateCategoryHandlerUnitTest.cs index 3336fe8..6fd74b8 100644 --- a/tests/Imprink.Application.Tests/UpdateCategoryHandlerUnitTest.cs +++ b/tests/Imprink.Application.Tests/UpdateCategoryHandlerUnitTest.cs @@ -6,13 +6,13 @@ using Moq; namespace Imprink.Application.Tests; -public class UpdateCategoryHandlerTests +public class UpdateCategoryTests { private readonly Mock _unitOfWorkMock; private readonly Mock _categoryRepositoryMock; - private readonly UpdateCategoryHandler _handler; + private readonly UpdateCategory _handler; - public UpdateCategoryHandlerTests() + public UpdateCategoryTests() { _unitOfWorkMock = new Mock(); _categoryRepositoryMock = new Mock(); @@ -20,7 +20,7 @@ public class UpdateCategoryHandlerTests _unitOfWorkMock.Setup(x => x.CategoryRepository) .Returns(_categoryRepositoryMock.Object); - _handler = new UpdateCategoryHandler(_unitOfWorkMock.Object); + _handler = new UpdateCategory(_unitOfWorkMock.Object); } [Fact]