Fixed erratic order behavior

This commit is contained in:
lumijiez
2025-06-26 00:16:26 +03:00
parent c21c01c432
commit 266aa529fa
27 changed files with 1381 additions and 1179 deletions

View File

@@ -1,13 +1,14 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Application.Services;
using Imprink.Domain.Entities;
using MediatR;
using Microsoft.Extensions.Logging;
namespace Imprink.Application.Commands.Addresses;
public class CreateAddressCommand : IRequest<AddressDto>
{
public string UserId { get; set; } = null!;
public string AddressType { get; set; } = null!;
public string? FirstName { get; set; }
public string? LastName { get; set; }
@@ -27,7 +28,12 @@ public class CreateAddressCommand : IRequest<AddressDto>
public bool IsActive { get; set; } = true;
}
public class CreateAddressHandler(IUnitOfWork uw, IMapper mapper) : IRequestHandler<CreateAddressCommand, AddressDto>
public class CreateAddressHandler(
IUnitOfWork uw,
IMapper mapper,
ICurrentUserService userService,
ILogger<CreateAddressHandler> logger)
: IRequestHandler<CreateAddressCommand, AddressDto>
{
public async Task<AddressDto> Handle(CreateAddressCommand request, CancellationToken cancellationToken)
{
@@ -35,6 +41,10 @@ public class CreateAddressHandler(IUnitOfWork uw, IMapper mapper) : IRequestHand
{
var address = mapper.Map<Address>(request);
address.UserId = userService.GetCurrentUserId()!;
address.CreatedAt = DateTime.UtcNow;
address.ModifiedAt = DateTime.UtcNow;
if (address.IsDefault)
{
var currentDefault = await uw.AddressRepository.GetDefaultByUserIdAsync(address.UserId, cancellationToken);
@@ -46,6 +56,8 @@ public class CreateAddressHandler(IUnitOfWork uw, IMapper mapper) : IRequestHand
}
var createdAddress = await uw.AddressRepository.AddAsync(address, cancellationToken);
await uw.SaveAsync(cancellationToken);
return mapper.Map<AddressDto>(createdAddress);
}, cancellationToken);
}

View File

@@ -1,5 +1,7 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Application.Exceptions;
using Imprink.Application.Services;
using Imprink.Domain.Entities;
using MediatR;
@@ -7,7 +9,6 @@ namespace Imprink.Application.Commands.Orders;
public class CreateOrderCommand : IRequest<OrderDto>
{
public string UserId { get; set; } = null!;
public decimal Amount { get; set; }
public int Quantity { get; set; }
public Guid ProductId { get; set; }
@@ -15,29 +16,30 @@ public class CreateOrderCommand : IRequest<OrderDto>
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 string[]? OriginalImageUrls { get; set; } = [];
public string? CustomizationImageUrl { get; set; } = null!;
public string? CustomizationDescription { get; set; } = null!;
public Guid AddressId { get; set; }
}
public class CreateOrderHandler(IUnitOfWork uw, IMapper mapper) : IRequestHandler<CreateOrderCommand, OrderDto>
public class CreateOrderHandler(IUnitOfWork uw, IMapper mapper, ICurrentUserService userService) : IRequestHandler<CreateOrderCommand, OrderDto>
{
public async Task<OrderDto> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
{
return await uw.TransactAsync(async () =>
{
var sourceAddress = await uw.AddressRepository.GetByIdAndUserIdAsync(request.AddressId, request.UserId, cancellationToken);
var sourceAddress = await uw.AddressRepository.GetByIdAndUserIdAsync(request.AddressId, userService.GetCurrentUserId()!, cancellationToken);
if (sourceAddress == null)
{
throw new ArgumentException($"Address with ID {request.AddressId} not found for user {request.UserId}");
throw new NotFoundException($"Address with ID {request.AddressId} not found for user {userService.GetCurrentUserId()!}");
}
var order = mapper.Map<Order>(request);
order.UserId = userService.GetCurrentUserId()!;
order.OrderDate = DateTime.UtcNow;
order.OrderStatusId = 1;
order.ShippingStatusId = 1;
order.OrderStatusId = 0;
order.ShippingStatusId = 0;
var createdOrder = await uw.OrderRepository.AddAsync(order, cancellationToken);
@@ -70,6 +72,8 @@ public class CreateOrderHandler(IUnitOfWork uw, IMapper mapper) : IRequestHandle
{
createdOrder.ProductVariant = await uw.ProductVariantRepository.GetByIdAsync(createdOrder.ProductVariantId.Value, cancellationToken);
}
await uw.SaveAsync(cancellationToken);
return mapper.Map<OrderDto>(createdOrder);
}, cancellationToken);

View File

@@ -21,6 +21,4 @@ public class AddressDto
public string? Instructions { get; set; }
public bool IsDefault { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}

View File

@@ -11,13 +11,11 @@ public class OrderDto
public Guid? ProductVariantId { get; set; }
public int OrderStatusId { get; set; }
public int ShippingStatusId { get; set; }
public string OrderNumber { get; set; } = null!;
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 string? CustomizationImageUrl { get; set; }
public string[]? OriginalImageUrls { get; set; } = [];
public string? CustomizationDescription { get; set; } = null!;
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }

View File

@@ -0,0 +1,23 @@
using AutoMapper;
using Imprink.Application.Commands.Addresses;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
namespace Imprink.Application.Mappings;
public class AddressMappingProfile : Profile
{
public AddressMappingProfile()
{
CreateMap<CreateAddressCommand, Address>()
.ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore())
.ForMember(dest => dest.ModifiedAt, opt => opt.Ignore())
.ForMember(dest => dest.User, opt => opt.Ignore());
CreateMap<Address, AddressDto>();
CreateMap<AddressDto, Address>()
.ForMember(dest => dest.User, opt => opt.Ignore());
}
}

View File

@@ -0,0 +1,38 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
namespace Imprink.Application.Mappings;
public class OrderAddressMappingProfile : Profile
{
public OrderAddressMappingProfile()
{
CreateMap<OrderAddress, OrderAddressDto>();
CreateMap<OrderAddressDto, OrderAddress>()
.ForMember(dest => dest.Order, opt => opt.Ignore());
CreateMap<Address, OrderAddress>()
.ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.OrderId, opt => opt.Ignore())
.ForMember(dest => dest.Order, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore())
.ForMember(dest => dest.ModifiedAt, opt => opt.Ignore())
.ForMember(dest => dest.AddressType, opt => opt.MapFrom(src => src.AddressType))
.ForMember(dest => dest.FirstName, opt => opt.MapFrom(src => src.FirstName))
.ForMember(dest => dest.LastName, opt => opt.MapFrom(src => src.LastName))
.ForMember(dest => dest.Company, opt => opt.MapFrom(src => src.Company))
.ForMember(dest => dest.AddressLine1, opt => opt.MapFrom(src => src.AddressLine1))
.ForMember(dest => dest.AddressLine2, opt => opt.MapFrom(src => src.AddressLine2))
.ForMember(dest => dest.ApartmentNumber, opt => opt.MapFrom(src => src.ApartmentNumber))
.ForMember(dest => dest.BuildingNumber, opt => opt.MapFrom(src => src.BuildingNumber))
.ForMember(dest => dest.Floor, opt => opt.MapFrom(src => src.Floor))
.ForMember(dest => dest.City, opt => opt.MapFrom(src => src.City))
.ForMember(dest => dest.State, opt => opt.MapFrom(src => src.State))
.ForMember(dest => dest.PostalCode, opt => opt.MapFrom(src => src.PostalCode))
.ForMember(dest => dest.Country, opt => opt.MapFrom(src => src.Country))
.ForMember(dest => dest.PhoneNumber, opt => opt.MapFrom(src => src.PhoneNumber))
.ForMember(dest => dest.Instructions, opt => opt.MapFrom(src => src.Instructions));
}
}

View File

@@ -0,0 +1,36 @@
using AutoMapper;
using Imprink.Application.Commands.Orders;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
namespace Imprink.Application.Mappings;
public class OrderMappingProfile : Profile
{
public OrderMappingProfile()
{
CreateMap<CreateOrderCommand, Order>()
.ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.OrderDate, opt => opt.Ignore())
.ForMember(dest => dest.OrderStatusId, opt => opt.Ignore())
.ForMember(dest => dest.ShippingStatusId, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore())
.ForMember(dest => dest.ModifiedAt, opt => opt.Ignore())
.ForMember(dest => dest.OrderStatus, opt => opt.Ignore())
.ForMember(dest => dest.User, opt => opt.Ignore())
.ForMember(dest => dest.ShippingStatus, opt => opt.Ignore())
.ForMember(dest => dest.OrderAddress, opt => opt.Ignore())
.ForMember(dest => dest.Product, opt => opt.Ignore())
.ForMember(dest => dest.ProductVariant, opt => opt.Ignore());
CreateMap<Order, OrderDto>();
CreateMap<OrderDto, Order>()
.ForMember(dest => dest.OrderStatus, opt => opt.Ignore())
.ForMember(dest => dest.User, opt => opt.Ignore())
.ForMember(dest => dest.ShippingStatus, opt => opt.Ignore())
.ForMember(dest => dest.OrderAddress, opt => opt.Ignore())
.ForMember(dest => dest.Product, opt => opt.Ignore())
.ForMember(dest => dest.ProductVariant, opt => opt.Ignore());
}
}

View File

@@ -0,0 +1,15 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
namespace Imprink.Application.Mappings;
public class OrderStatusMappingProfile : Profile
{
public OrderStatusMappingProfile()
{
CreateMap<OrderStatus, OrderStatusDto>();
CreateMap<OrderStatusDto, OrderStatus>();
}
}

View File

@@ -0,0 +1,15 @@
using AutoMapper;
using Imprink.Application.Dtos;
using Imprink.Domain.Entities;
namespace Imprink.Application.Mappings;
public class ShippingStatusMappingProfile : Profile
{
public ShippingStatusMappingProfile()
{
CreateMap<ShippingStatus, ShippingStatusDto>();
CreateMap<ShippingStatusDto, ShippingStatus>();
}
}