Fixed erratic order behavior
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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; }
|
||||
|
||||
|
||||
23
src/Imprink.Application/Mappings/AddressMappingProfile.cs
Normal file
23
src/Imprink.Application/Mappings/AddressMappingProfile.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
36
src/Imprink.Application/Mappings/OrderMappingProfile.cs
Normal file
36
src/Imprink.Application/Mappings/OrderMappingProfile.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ namespace Imprink.Domain.Entities;
|
||||
|
||||
public class Order : EntityBase
|
||||
{
|
||||
public string UserId { get; set; } = null!;
|
||||
public required string UserId { get; set; }
|
||||
public DateTime OrderDate { get; set; }
|
||||
public decimal Amount { get; set; }
|
||||
public int Quantity { get; set; }
|
||||
@@ -10,18 +10,17 @@ public class Order : EntityBase
|
||||
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? CustomizationImageUrl { get; set; }
|
||||
public string[] OriginalImageUrls { get; set; } = [];
|
||||
public string CustomizationImageUrl { get; set; } = null!;
|
||||
public string CustomizationDescription { get; set; } = null!;
|
||||
public string? CustomizationDescription { get; set; }
|
||||
|
||||
public OrderStatus OrderStatus { get; set; } = null!;
|
||||
public User User { get; set; } = null!;
|
||||
public ShippingStatus ShippingStatus { get; set; } = null!;
|
||||
public OrderAddress OrderAddress { get; set; } = null!;
|
||||
public Product Product { get; set; } = null!;
|
||||
public ProductVariant? ProductVariant { get; set; }
|
||||
public virtual OrderStatus OrderStatus { get; set; } = null!;
|
||||
public virtual User User { get; set; } = null!;
|
||||
public virtual User? Merchant { get; set; }
|
||||
public virtual ShippingStatus ShippingStatus { get; set; } = null!;
|
||||
public virtual OrderAddress OrderAddress { get; set; } = null!;
|
||||
public virtual Product Product { get; set; } = null!;
|
||||
public virtual ProductVariant? ProductVariant { get; set; }
|
||||
}
|
||||
@@ -18,6 +18,6 @@ public class OrderAddress : EntityBase
|
||||
public required string Country { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? Instructions { get; set; }
|
||||
|
||||
public virtual required Order Order { get; set; }
|
||||
|
||||
public virtual Order Order { get; set; } = null!;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ public interface IAddressRepository
|
||||
{
|
||||
Task<IEnumerable<Address>> GetByUserIdAsync(string userId, CancellationToken cancellationToken = default);
|
||||
Task<IEnumerable<Address>> GetActiveByUserIdAsync(string userId, CancellationToken cancellationToken = default);
|
||||
Task<Address?> GetDefaultByUserIdAsync(string userId, CancellationToken cancellationToken = default);
|
||||
Task<Address?> GetDefaultByUserIdAsync(string? userId, CancellationToken cancellationToken = default);
|
||||
Task<IEnumerable<Address>> GetByUserIdAndTypeAsync(string userId, string addressType, CancellationToken cancellationToken = default);
|
||||
Task<Address?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<Address?> GetByIdAndUserIdAsync(Guid id, string userId, CancellationToken cancellationToken = default);
|
||||
@@ -14,7 +14,7 @@ public interface IAddressRepository
|
||||
Task<Address> UpdateAsync(Address address, CancellationToken cancellationToken = default);
|
||||
Task<bool> DeleteAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<bool> DeleteByUserIdAsync(Guid id, string userId, CancellationToken cancellationToken = default);
|
||||
Task SetDefaultAddressAsync(string userId, Guid addressId, CancellationToken cancellationToken = default);
|
||||
Task SetDefaultAddressAsync(string? userId, Guid addressId, CancellationToken cancellationToken = default);
|
||||
Task DeactivateAddressAsync(Guid addressId, CancellationToken cancellationToken = default);
|
||||
Task ActivateAddressAsync(Guid addressId, CancellationToken cancellationToken = default);
|
||||
Task<bool> ExistsAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
|
||||
@@ -7,7 +7,6 @@ public interface IOrderRepository
|
||||
{
|
||||
Task<Order?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<Order?> GetByIdWithDetailsAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<Order?> GetByOrderNumberAsync(string orderNumber, CancellationToken cancellationToken = default);
|
||||
Task<IEnumerable<Order>> GetByUserIdAsync(string userId, CancellationToken cancellationToken = default);
|
||||
Task<IEnumerable<Order>> GetByUserIdWithDetailsAsync(string userId, CancellationToken cancellationToken = default);
|
||||
Task<IEnumerable<Order>> GetByMerchantIdAsync(string merchantId, CancellationToken cancellationToken = default);
|
||||
@@ -19,9 +18,6 @@ public interface IOrderRepository
|
||||
Task<Order> UpdateAsync(Order order, CancellationToken cancellationToken = default);
|
||||
Task<bool> DeleteAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<bool> ExistsAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<bool> IsOrderNumberUniqueAsync(string orderNumber, CancellationToken cancellationToken = default);
|
||||
Task<bool> IsOrderNumberUniqueAsync(string orderNumber, Guid excludeOrderId, CancellationToken cancellationToken = default);
|
||||
Task<string> GenerateOrderNumberAsync(CancellationToken cancellationToken = default);
|
||||
Task UpdateStatusAsync(Guid orderId, int statusId, CancellationToken cancellationToken = default);
|
||||
Task UpdateShippingStatusAsync(Guid orderId, int shippingStatusId, CancellationToken cancellationToken = default);
|
||||
Task AssignMerchantAsync(Guid orderId, string merchantId, CancellationToken cancellationToken = default);
|
||||
|
||||
@@ -75,7 +75,6 @@ public class AddressConfiguration : EntityBaseConfiguration<Address>
|
||||
builder.HasOne(a => a.User)
|
||||
.WithMany(u => u.Addresses)
|
||||
.HasForeignKey(a => a.UserId)
|
||||
.HasPrincipalKey(u => u.Id)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasIndex(a => a.UserId)
|
||||
@@ -87,4 +86,4 @@ public class AddressConfiguration : EntityBaseConfiguration<Address>
|
||||
builder.HasIndex(a => new { a.UserId, a.IsDefault })
|
||||
.HasDatabaseName("IX_Address_User_Default");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ using Imprink.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace Imprink.Infrastructure;
|
||||
namespace Imprink.Infrastructure.Configuration;
|
||||
|
||||
public class EntityBaseConfiguration<T> : IEntityTypeConfiguration<T> where T : EntityBase
|
||||
{
|
||||
@@ -12,20 +12,16 @@ public class EntityBaseConfiguration<T> : IEntityTypeConfiguration<T> where T :
|
||||
|
||||
builder.Property(e => e.Id)
|
||||
.HasDefaultValueSql("NEWID()");
|
||||
|
||||
builder.Property(e => e.CreatedAt)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(e => e.CreatedAt);
|
||||
|
||||
builder.Property(e => e.ModifiedAt)
|
||||
.IsRequired()
|
||||
.HasDefaultValueSql("GETUTCDATE()");
|
||||
|
||||
builder.Property(e => e.CreatedBy)
|
||||
.IsRequired()
|
||||
.HasMaxLength(450);
|
||||
|
||||
builder.Property(e => e.ModifiedBy)
|
||||
.IsRequired()
|
||||
.HasMaxLength(450);
|
||||
|
||||
builder.HasIndex(e => e.CreatedAt)
|
||||
@@ -35,19 +35,12 @@ public class OrderConfiguration : EntityBaseConfiguration<Order>
|
||||
builder.Property(o => o.ShippingStatusId)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(o => o.OrderNumber)
|
||||
.IsRequired()
|
||||
.HasMaxLength(50);
|
||||
|
||||
builder.Property(o => o.Notes)
|
||||
.HasMaxLength(1000);
|
||||
|
||||
builder.Property(o => o.MerchantId)
|
||||
.HasMaxLength(450);
|
||||
|
||||
builder.Property(o => o.ComposingImageUrl)
|
||||
.HasMaxLength(1000);
|
||||
|
||||
builder.Property(o => o.OriginalImageUrls)
|
||||
.HasConversion(
|
||||
v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null),
|
||||
@@ -55,11 +48,9 @@ public class OrderConfiguration : EntityBaseConfiguration<Order>
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
builder.Property(o => o.CustomizationImageUrl)
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000);
|
||||
|
||||
builder.Property(o => o.CustomizationDescription)
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000);
|
||||
|
||||
builder.HasOne(o => o.OrderStatus)
|
||||
@@ -80,13 +71,11 @@ public class OrderConfiguration : EntityBaseConfiguration<Order>
|
||||
builder.HasOne(o => o.User)
|
||||
.WithMany(u => u.Orders)
|
||||
.HasForeignKey(o => o.UserId)
|
||||
.HasPrincipalKey(u => u.Id)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
builder.HasOne<User>()
|
||||
builder.HasOne(o => o.Merchant)
|
||||
.WithMany(u => u.MerchantOrders)
|
||||
.HasForeignKey(o => o.MerchantId)
|
||||
.HasPrincipalKey(u => u.Id)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
builder.HasOne(o => o.Product)
|
||||
@@ -102,10 +91,6 @@ public class OrderConfiguration : EntityBaseConfiguration<Order>
|
||||
builder.HasIndex(o => o.UserId)
|
||||
.HasDatabaseName("IX_Order_UserId");
|
||||
|
||||
builder.HasIndex(o => o.OrderNumber)
|
||||
.IsUnique()
|
||||
.HasDatabaseName("IX_Order_OrderNumber");
|
||||
|
||||
builder.HasIndex(o => o.OrderDate)
|
||||
.HasDatabaseName("IX_Order_OrderDate");
|
||||
|
||||
@@ -133,4 +118,4 @@ public class OrderConfiguration : EntityBaseConfiguration<Order>
|
||||
builder.HasIndex(o => new { o.ProductId, o.OrderDate })
|
||||
.HasDatabaseName("IX_Order_Product_Date");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,18 +34,6 @@ public class ProductConfiguration : EntityBaseConfiguration<Product>
|
||||
|
||||
builder.Property(p => p.CategoryId)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.Property(c => c.CreatedAt)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.Property(c => c.CreatedBy)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.Property(c => c.ModifiedAt)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.Property(c => c.ModifiedBy)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.HasOne(p => p.Category)
|
||||
.WithMany(c => c.Products)
|
||||
|
||||
@@ -37,18 +37,6 @@ public class ProductVariantConfiguration : EntityBaseConfiguration<ProductVarian
|
||||
builder.Property(pv => pv.IsActive)
|
||||
.IsRequired()
|
||||
.HasDefaultValue(true);
|
||||
|
||||
builder.Property(c => c.CreatedAt)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.Property(c => c.CreatedBy)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.Property(c => c.ModifiedAt)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.Property(c => c.ModifiedBy)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.HasOne(pv => pv.Product)
|
||||
.WithMany(p => p.ProductVariants)
|
||||
|
||||
@@ -8,6 +8,8 @@ public class UserConfiguration : IEntityTypeConfiguration<User>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<User> builder)
|
||||
{
|
||||
builder.HasKey(u => u.Id);
|
||||
|
||||
builder.Property(u => u.Id)
|
||||
.HasMaxLength(450)
|
||||
.ValueGeneratedNever();
|
||||
@@ -47,12 +49,6 @@ public class UserConfiguration : IEntityTypeConfiguration<User>
|
||||
builder.HasIndex(u => u.IsActive)
|
||||
.HasDatabaseName("IX_User_IsActive");
|
||||
|
||||
builder.HasMany(u => u.Addresses)
|
||||
.WithOne()
|
||||
.HasForeignKey(a => a.UserId)
|
||||
.HasPrincipalKey(u => u.Id)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.Ignore(u => u.DefaultAddress);
|
||||
builder.Ignore(u => u.Roles);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -84,7 +84,7 @@ namespace Imprink.Infrastructure.Migrations
|
||||
Name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
Nickname = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
||||
EmailVerified = table.Column<bool>(type: "bit", maxLength: 100, nullable: false),
|
||||
EmailVerified = table.Column<bool>(type: "bit", nullable: false),
|
||||
FirstName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
LastName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
PhoneNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
@@ -130,17 +130,26 @@ namespace Imprink.Infrastructure.Migrations
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false, defaultValueSql: "NEWID()"),
|
||||
UserId = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
AddressType = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
|
||||
Street = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
FirstName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
LastName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
Company = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
|
||||
AddressLine1 = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
AddressLine2 = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
|
||||
ApartmentNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
BuildingNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
Floor = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
City = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
State = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
PostalCode = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false),
|
||||
Country = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
PhoneNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
Instructions = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
IsDefault = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
ModifiedAt = table.Column<DateTime>(type: "datetime2", nullable: false, defaultValueSql: "GETUTCDATE()"),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
ModifiedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false)
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
ModifiedAt = table.Column<DateTime>(type: "datetime2", nullable: true, defaultValueSql: "GETUTCDATE()"),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: true),
|
||||
ModifiedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
@@ -153,46 +162,6 @@ namespace Imprink.Infrastructure.Migrations
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Orders",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false, defaultValueSql: "NEWID()"),
|
||||
UserId = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
OrderDate = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
TotalPrice = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
|
||||
OrderStatusId = table.Column<int>(type: "int", nullable: false),
|
||||
ShippingStatusId = table.Column<int>(type: "int", nullable: false),
|
||||
OrderNumber = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
|
||||
Notes = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
ModifiedAt = table.Column<DateTime>(type: "datetime2", nullable: false, defaultValueSql: "GETUTCDATE()"),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
ModifiedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Orders", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Orders_OrderStatuses_OrderStatusId",
|
||||
column: x => x.OrderStatusId,
|
||||
principalTable: "OrderStatuses",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Orders_ShippingStatuses_ShippingStatusId",
|
||||
column: x => x.ShippingStatusId,
|
||||
principalTable: "ShippingStatuses",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Orders_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "UserRole",
|
||||
columns: table => new
|
||||
@@ -246,21 +215,95 @@ namespace Imprink.Infrastructure.Migrations
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Orders",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false, defaultValueSql: "NEWID()"),
|
||||
UserId = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
OrderDate = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
Amount = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
|
||||
Quantity = table.Column<int>(type: "int", nullable: false, defaultValue: 1),
|
||||
ProductId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
ProductVariantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
OrderStatusId = table.Column<int>(type: "int", nullable: false),
|
||||
ShippingStatusId = table.Column<int>(type: "int", nullable: false),
|
||||
Notes = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
|
||||
MerchantId = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: true),
|
||||
CustomizationImageUrl = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
|
||||
OriginalImageUrls = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
CustomizationDescription = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
ModifiedAt = table.Column<DateTime>(type: "datetime2", nullable: true, defaultValueSql: "GETUTCDATE()"),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: true),
|
||||
ModifiedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Orders", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Orders_OrderStatuses_OrderStatusId",
|
||||
column: x => x.OrderStatusId,
|
||||
principalTable: "OrderStatuses",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Orders_ProductVariants_ProductVariantId",
|
||||
column: x => x.ProductVariantId,
|
||||
principalTable: "ProductVariants",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Orders_Products_ProductId",
|
||||
column: x => x.ProductId,
|
||||
principalTable: "Products",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Orders_ShippingStatuses_ShippingStatusId",
|
||||
column: x => x.ShippingStatusId,
|
||||
principalTable: "ShippingStatuses",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Orders_Users_MerchantId",
|
||||
column: x => x.MerchantId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "FK_Orders_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OrderAddresses",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false, defaultValueSql: "NEWID()"),
|
||||
OrderId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Street = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
AddressType = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
|
||||
FirstName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
LastName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
Company = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
|
||||
AddressLine1 = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
AddressLine2 = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
|
||||
ApartmentNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
BuildingNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
Floor = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
City = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
State = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
PostalCode = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false),
|
||||
Country = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
ModifiedAt = table.Column<DateTime>(type: "datetime2", nullable: false, defaultValueSql: "GETUTCDATE()"),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
ModifiedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false)
|
||||
PhoneNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
Instructions = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
ModifiedAt = table.Column<DateTime>(type: "datetime2", nullable: true, defaultValueSql: "GETUTCDATE()"),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: true),
|
||||
ModifiedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
@@ -273,47 +316,6 @@ namespace Imprink.Infrastructure.Migrations
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OrderItems",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false, defaultValueSql: "NEWID()"),
|
||||
OrderId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
ProductId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
ProductVariantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
Quantity = table.Column<int>(type: "int", nullable: false, defaultValue: 1),
|
||||
UnitPrice = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
|
||||
TotalPrice = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
|
||||
CustomizationImageUrl = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
|
||||
CustomizationDescription = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
ModifiedAt = table.Column<DateTime>(type: "datetime2", nullable: false, defaultValueSql: "GETUTCDATE()"),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
|
||||
ModifiedBy = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OrderItems", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OrderItems_Orders_OrderId",
|
||||
column: x => x.OrderId,
|
||||
principalTable: "Orders",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_OrderItems_ProductVariants_ProductVariantId",
|
||||
column: x => x.ProductVariantId,
|
||||
principalTable: "ProductVariants",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_OrderItems_Products_ProductId",
|
||||
column: x => x.ProductId,
|
||||
principalTable: "Products",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "Categories",
|
||||
columns: new[] { "Id", "CreatedAt", "CreatedBy", "Description", "ImageUrl", "IsActive", "ModifiedAt", "ModifiedBy", "Name", "ParentCategoryId", "SortOrder" },
|
||||
@@ -446,41 +448,6 @@ namespace Imprink.Infrastructure.Migrations
|
||||
column: "OrderId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderItem_CreatedAt",
|
||||
table: "OrderItems",
|
||||
column: "CreatedAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderItem_CreatedBy",
|
||||
table: "OrderItems",
|
||||
column: "CreatedBy");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderItem_ModifiedAt",
|
||||
table: "OrderItems",
|
||||
column: "ModifiedAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderItem_Order_Product",
|
||||
table: "OrderItems",
|
||||
columns: new[] { "OrderId", "ProductId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderItem_OrderId",
|
||||
table: "OrderItems",
|
||||
column: "OrderId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderItem_ProductId",
|
||||
table: "OrderItems",
|
||||
column: "ProductId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderItem_ProductVariantId",
|
||||
table: "OrderItems",
|
||||
column: "ProductVariantId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_CreatedAt",
|
||||
table: "Orders",
|
||||
@@ -491,6 +458,16 @@ namespace Imprink.Infrastructure.Migrations
|
||||
table: "Orders",
|
||||
column: "CreatedBy");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_Merchant_Date",
|
||||
table: "Orders",
|
||||
columns: new[] { "MerchantId", "OrderDate" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_MerchantId",
|
||||
table: "Orders",
|
||||
column: "MerchantId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_ModifiedAt",
|
||||
table: "Orders",
|
||||
@@ -501,17 +478,26 @@ namespace Imprink.Infrastructure.Migrations
|
||||
table: "Orders",
|
||||
column: "OrderDate");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_OrderNumber",
|
||||
table: "Orders",
|
||||
column: "OrderNumber",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_OrderStatusId",
|
||||
table: "Orders",
|
||||
column: "OrderStatusId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_Product_Date",
|
||||
table: "Orders",
|
||||
columns: new[] { "ProductId", "OrderDate" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_ProductId",
|
||||
table: "Orders",
|
||||
column: "ProductId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_ProductVariantId",
|
||||
table: "Orders",
|
||||
column: "ProductVariantId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Order_ShippingStatusId",
|
||||
table: "Orders",
|
||||
@@ -659,24 +645,21 @@ namespace Imprink.Infrastructure.Migrations
|
||||
migrationBuilder.DropTable(
|
||||
name: "OrderAddresses");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OrderItems");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "UserRole");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Orders");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ProductVariants");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Roles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OrderStatuses");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ProductVariants");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ShippingStatuses");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@ public class AddressRepository(ApplicationDbContext context) : IAddressRepositor
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<Address?> GetDefaultByUserIdAsync(string userId, CancellationToken cancellationToken = default)
|
||||
public async Task<Address?> GetDefaultByUserIdAsync(string? userId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await context.Addresses
|
||||
.FirstOrDefaultAsync(a => a.UserId == userId && a.IsDefault && a.IsActive, cancellationToken);
|
||||
@@ -103,7 +103,7 @@ public class AddressRepository(ApplicationDbContext context) : IAddressRepositor
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task SetDefaultAddressAsync(string userId, Guid addressId, CancellationToken cancellationToken = default)
|
||||
public async Task SetDefaultAddressAsync(string? userId, Guid addressId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await UnsetDefaultAddressesAsync(userId, cancellationToken);
|
||||
|
||||
@@ -154,7 +154,7 @@ public class AddressRepository(ApplicationDbContext context) : IAddressRepositor
|
||||
.AnyAsync(a => a.Id == id && a.UserId == userId, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task UnsetDefaultAddressesAsync(string userId, CancellationToken cancellationToken = default)
|
||||
private async Task UnsetDefaultAddressesAsync(string? userId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var defaultAddresses = await context.Addresses
|
||||
.Where(a => a.UserId == userId && a.IsDefault)
|
||||
|
||||
@@ -25,12 +25,6 @@ public class OrderRepository(ApplicationDbContext context) : IOrderRepository
|
||||
.FirstOrDefaultAsync(o => o.Id == id, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<Order?> GetByOrderNumberAsync(string orderNumber, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await context.Orders
|
||||
.FirstOrDefaultAsync(o => o.OrderNumber == orderNumber, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Order>> GetByUserIdAsync(string userId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await context.Orders
|
||||
@@ -134,37 +128,6 @@ public class OrderRepository(ApplicationDbContext context) : IOrderRepository
|
||||
.AnyAsync(o => o.Id == id, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> IsOrderNumberUniqueAsync(string orderNumber, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return !await context.Orders
|
||||
.AnyAsync(o => o.OrderNumber == orderNumber, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> IsOrderNumberUniqueAsync(string orderNumber, Guid excludeOrderId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return !await context.Orders
|
||||
.AnyAsync(o => o.OrderNumber == orderNumber && o.Id != excludeOrderId, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<string> GenerateOrderNumberAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
string orderNumber;
|
||||
bool isUnique;
|
||||
|
||||
do
|
||||
{
|
||||
// Generate order number format: ORD-YYYYMMDD-XXXXXX (where X is random)
|
||||
var datePart = DateTime.UtcNow.ToString("yyyyMMdd");
|
||||
var randomPart = Random.Shared.Next(100000, 999999).ToString();
|
||||
orderNumber = $"ORD-{datePart}-{randomPart}";
|
||||
|
||||
isUnique = await IsOrderNumberUniqueAsync(orderNumber, cancellationToken);
|
||||
}
|
||||
while (!isUnique);
|
||||
|
||||
return orderNumber;
|
||||
}
|
||||
|
||||
public async Task UpdateStatusAsync(Guid orderId, int statusId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var order = await context.Orders
|
||||
|
||||
@@ -52,7 +52,6 @@ public class UnitOfWork(
|
||||
try
|
||||
{
|
||||
var result = await operation();
|
||||
await SaveAsync(cancellationToken);
|
||||
await CommitTransactionAsync(cancellationToken);
|
||||
return result;
|
||||
}
|
||||
@@ -69,7 +68,6 @@ public class UnitOfWork(
|
||||
try
|
||||
{
|
||||
await operation();
|
||||
await SaveAsync(cancellationToken);
|
||||
await CommitTransactionAsync(cancellationToken);
|
||||
}
|
||||
catch
|
||||
|
||||
60
src/Imprink.WebApi/Controllers/AddressesController.cs
Normal file
60
src/Imprink.WebApi/Controllers/AddressesController.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using Imprink.Application.Commands.Addresses;
|
||||
using Imprink.Application.Dtos;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Imprink.WebApi.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("/api/addresses")]
|
||||
public class AddressesController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<AddressDto>> GetAddressById(
|
||||
Guid id,
|
||||
[FromQuery] string? userId = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = await mediator.Send(new GetAddressByIdQuery
|
||||
{
|
||||
Id = id,
|
||||
UserId = userId
|
||||
}, cancellationToken);
|
||||
|
||||
if (result == null)
|
||||
return NotFound();
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet("user/{userId}")]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<IEnumerable<AddressDto>>> GetAddressesByUserId(
|
||||
string userId,
|
||||
[FromQuery] bool activeOnly = false,
|
||||
[FromQuery] string? addressType = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = await mediator.Send(new GetAddressesByUserIdQuery
|
||||
{
|
||||
UserId = userId,
|
||||
ActiveOnly = activeOnly,
|
||||
AddressType = addressType
|
||||
}, cancellationToken);
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<AddressDto>> CreateAddress(
|
||||
[FromBody] CreateAddressCommand command,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return CreatedAtAction(nameof(GetAddressById), new { id = result.Id }, result);
|
||||
}
|
||||
}
|
||||
74
src/Imprink.WebApi/Controllers/OrdersController.cs
Normal file
74
src/Imprink.WebApi/Controllers/OrdersController.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using Imprink.Application.Commands.Orders;
|
||||
using Imprink.Application.Dtos;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Imprink.WebApi.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("/api/orders")]
|
||||
public class OrdersController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<OrderDto>> GetOrderById(
|
||||
Guid id,
|
||||
[FromQuery] bool includeDetails = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = await mediator.Send(new GetOrderByIdQuery
|
||||
{
|
||||
Id = id,
|
||||
IncludeDetails = includeDetails
|
||||
}, cancellationToken);
|
||||
|
||||
if (result == null)
|
||||
return NotFound();
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet("user/{userId}")]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<IEnumerable<OrderDto>>> GetOrdersByUserId(
|
||||
string userId,
|
||||
[FromQuery] bool includeDetails = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = await mediator.Send(new GetOrdersByUserIdQuery
|
||||
{
|
||||
UserId = userId,
|
||||
IncludeDetails = includeDetails
|
||||
}, cancellationToken);
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet("merchant/{merchantId}")]
|
||||
[Authorize(Roles = "Admin,Merchant")]
|
||||
public async Task<ActionResult<IEnumerable<OrderDto>>> GetOrdersByMerchantId(
|
||||
string merchantId,
|
||||
[FromQuery] bool includeDetails = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = await mediator.Send(new GetOrdersByMerchantIdQuery
|
||||
{
|
||||
MerchantId = merchantId,
|
||||
IncludeDetails = includeDetails
|
||||
}, cancellationToken);
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<OrderDto>> CreateOrder(
|
||||
[FromBody] CreateOrderCommand command,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return CreatedAtAction(nameof(GetOrderById), new { id = result.Id }, result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user