diff --git a/src/Printbase.Application/Printbase.Application.csproj b/src/Printbase.Application/Printbase.Application.csproj
index e80f671..da6040d 100644
--- a/src/Printbase.Application/Printbase.Application.csproj
+++ b/src/Printbase.Application/Printbase.Application.csproj
@@ -17,8 +17,4 @@
-
-
-
-
diff --git a/src/Printbase.Application/Products/Commands/CreateProduct/CreateProductCommand.cs b/src/Printbase.Application/Products/Commands/CreateProduct/CreateProductCommand.cs
deleted file mode 100644
index f107b64..0000000
--- a/src/Printbase.Application/Products/Commands/CreateProduct/CreateProductCommand.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using MediatR;
-using Printbase.Application.Products.Dtos;
-
-namespace Printbase.Application.Products.Commands.CreateProduct;
-
-public class CreateProductCommand : IRequest
-{
- public string Name { get; set; } = string.Empty;
- public string? Description { get; set; }
- public Guid TypeId { get; set; }
- public List? Variants { get; set; }
-}
\ No newline at end of file
diff --git a/src/Printbase.Application/Products/Commands/CreateProduct/CreateProductCommandHandler.cs b/src/Printbase.Application/Products/Commands/CreateProduct/CreateProductCommandHandler.cs
deleted file mode 100644
index b02d710..0000000
--- a/src/Printbase.Application/Products/Commands/CreateProduct/CreateProductCommandHandler.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-using MediatR;
-using Printbase.Application.Products.Dtos;
-using Printbase.Domain.Entities.Products;
-using Printbase.Domain.Repositories;
-
-namespace Printbase.Application.Products.Commands.CreateProduct;
-
-public class CreateProductCommandHandler(
- IProductRepository productRepository,
- IProductVariantRepository variantRepository,
- IProductTypeRepository typeRepository)
- : IRequestHandler
-{
- private readonly IProductRepository _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository));
- private readonly IProductVariantRepository _variantRepository = variantRepository ?? throw new ArgumentNullException(nameof(variantRepository));
- private readonly IProductTypeRepository _typeRepository = typeRepository ?? throw new ArgumentNullException(nameof(typeRepository));
-
- public async Task Handle(CreateProductCommand request, CancellationToken cancellationToken)
- {
- var productType = await _typeRepository.GetByIdAsync(request.TypeId, includeRelations: true, cancellationToken);
- if (productType == null)
- {
- throw new ArgumentException($"Product type with ID {request.TypeId} not found");
- }
-
- var product = new Product
- {
- Id = Guid.NewGuid(),
- Name = request.Name,
- Description = request.Description,
- TypeId = request.TypeId,
- CreatedAt = DateTime.UtcNow,
- IsActive = true
- };
-
- var createdProduct = await _productRepository.AddAsync(product, cancellationToken);
-
- var productVariants = new List();
- if (request.Variants != null && request.Variants.Count != 0)
- {
- foreach (var variant in request.Variants.Select(variantDto => new ProductVariant
- {
- Id = Guid.NewGuid(),
- ProductId = createdProduct.Id,
- Color = variantDto.Color,
- Size = variantDto.Size,
- Price = variantDto.Price,
- Discount = variantDto.Discount,
- Stock = variantDto.Stock,
- SKU = variantDto.SKU ?? GenerateSku(createdProduct.Name, variantDto.Color, variantDto.Size),
- CreatedAt = DateTime.UtcNow,
- IsActive = true
- }))
- {
- var createdVariant = await _variantRepository.AddAsync(variant, cancellationToken);
- productVariants.Add(createdVariant);
- }
- }
-
- var productDto = new ProductDto
- {
- Id = createdProduct.Id,
- Name = createdProduct.Name,
- Description = createdProduct.Description,
- TypeId = createdProduct.TypeId,
- TypeName = productType.Name,
- GroupName = productType.Group.Name,
- CreatedAt = createdProduct.CreatedAt,
- IsActive = createdProduct.IsActive,
- Variants = productVariants.Select(v => new ProductVariantDto
- {
- Id = v.Id,
- Color = v.Color,
- Size = v.Size,
- Price = v.Price,
- Discount = v.Discount,
- Stock = v.Stock,
- SKU = v.SKU,
- IsActive = v.IsActive
- }).ToList()
- };
-
- return productDto;
- }
-
- public static string GenerateSku(string productName, string? color, string? size)
- {
- var prefix = productName.Length >= 3 ? productName[..3].ToUpper() : productName.ToUpper();
- var colorPart = !string.IsNullOrEmpty(color) ? color[..Math.Min(3, color.Length)].ToUpper() : "XXX";
- var sizePart = !string.IsNullOrEmpty(size) ? size.ToUpper() : "OS";
- var randomPart = new Random().Next(100, 999).ToString();
-
- return $"{prefix}-{colorPart}-{sizePart}-{randomPart}";
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.Application/Products/Commands/CreateProduct/CreateProductVariantDto.cs b/src/Printbase.Application/Products/Commands/CreateProduct/CreateProductVariantDto.cs
deleted file mode 100644
index ac2ffbb..0000000
--- a/src/Printbase.Application/Products/Commands/CreateProduct/CreateProductVariantDto.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace Printbase.Application.Products.Commands.CreateProduct;
-
-public class CreateProductVariantDto
-{
- public string? Color { get; set; }
- public string? Size { get; set; }
- public decimal Price { get; set; }
- public decimal? Discount { get; set; }
- public int Stock { get; set; }
- public string? SKU { get; set; }
-}
\ No newline at end of file
diff --git a/src/Printbase.Application/Products/Dtos/AllProductsDto.cs b/src/Printbase.Application/Products/Dtos/AllProductsDto.cs
deleted file mode 100644
index 0363924..0000000
--- a/src/Printbase.Application/Products/Dtos/AllProductsDto.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Printbase.Application.Products.Dtos;
-
-public class AllProductsDto
-{
- public ICollection Products {get;set;}
-}
\ No newline at end of file
diff --git a/src/Printbase.Application/Products/Dtos/ProductDto.cs b/src/Printbase.Application/Products/Dtos/ProductDto.cs
deleted file mode 100644
index d7b0acd..0000000
--- a/src/Printbase.Application/Products/Dtos/ProductDto.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Printbase.Application.Products.Dtos;
-
-public class ProductDto
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
- public string? Description { get; set; }
- public Guid TypeId { get; set; }
- public string TypeName { get; set; } = string.Empty;
- public string GroupName { get; set; } = string.Empty;
- public ICollection Variants { get; set; } = new List();
- public DateTime CreatedAt { get; set; }
- public DateTime? UpdatedAt { get; set; }
- public bool IsActive { get; set; }
-}
\ No newline at end of file
diff --git a/src/Printbase.Application/Products/Dtos/ProductVariantDto.cs b/src/Printbase.Application/Products/Dtos/ProductVariantDto.cs
deleted file mode 100644
index 78fab47..0000000
--- a/src/Printbase.Application/Products/Dtos/ProductVariantDto.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Printbase.Application.Products.Dtos;
-
-public class ProductVariantDto
-{
- public Guid Id { get; set; }
- public string? Color { get; set; }
- public string? Size { get; set; }
- public decimal Price { get; set; }
- public decimal? Discount { get; set; }
- public decimal DiscountedPrice => Discount is > 0 ? Price - Price * Discount.Value / 100m : Price;
- public int Stock { get; set; }
- public string? SKU { get; set; }
- public bool IsActive { get; set; }
-}
\ No newline at end of file
diff --git a/src/Printbase.Application/Products/Queries/GetAllProducts/GetAllProductsQuery.cs b/src/Printbase.Application/Products/Queries/GetAllProducts/GetAllProductsQuery.cs
deleted file mode 100644
index e3b29f8..0000000
--- a/src/Printbase.Application/Products/Queries/GetAllProducts/GetAllProductsQuery.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using MediatR;
-using Printbase.Application.Products.Dtos;
-
-namespace Printbase.Application.Products.Queries.GetAllProducts;
-
-public class GetAllProductsQuery(bool includeVariants = true) : IRequest
-{
- public bool IncludeVariants { get; } = includeVariants;
-}
\ No newline at end of file
diff --git a/src/Printbase.Application/Products/Queries/GetAllProducts/GetAllProductsQueryHandler.cs b/src/Printbase.Application/Products/Queries/GetAllProducts/GetAllProductsQueryHandler.cs
deleted file mode 100644
index a856c49..0000000
--- a/src/Printbase.Application/Products/Queries/GetAllProducts/GetAllProductsQueryHandler.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using MediatR;
-using Printbase.Application.Products.Dtos;
-using Printbase.Domain.Repositories;
-
-namespace Printbase.Application.Products.Queries.GetAllProducts;
-
-public class GetAllProductsQueryHandler(IProductRepository productRepository)
- : IRequestHandler
-{
- private readonly IProductRepository _productRepository = productRepository
- ?? throw new ArgumentNullException(nameof(productRepository));
-
- public async Task Handle(GetAllProductsQuery request, CancellationToken cancellationToken)
- {
- var products = await _productRepository.GetAllAsync(true, cancellationToken);
-
- var allProducts = new AllProductsDto
- {
- Products = products.Select(p => new ProductDto
- {
- Id = p.Id,
- Name = p.Name,
- Description = p.Description,
- TypeId = p.TypeId,
- TypeName = p.Type.Name,
- GroupName = p.Type.Group.Name,
- CreatedAt = p.CreatedAt,
- UpdatedAt = p.UpdatedAt,
- IsActive = p.IsActive,
- Variants = request.IncludeVariants
- ? p.Variants.Select(v => new ProductVariantDto
- {
- Id = v.Id,
- Color = v.Color,
- Size = v.Size,
- Price = v.Price,
- Discount = v.Discount,
- Stock = v.Stock,
- SKU = v.SKU,
- IsActive = v.IsActive
- }).ToList()
- : []
- }).ToList()
- };
-
- return allProducts;
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.Application/Products/Queries/GetProductById/GetProductByIdQuery.cs b/src/Printbase.Application/Products/Queries/GetProductById/GetProductByIdQuery.cs
deleted file mode 100644
index 6fef39d..0000000
--- a/src/Printbase.Application/Products/Queries/GetProductById/GetProductByIdQuery.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using MediatR;
-using Printbase.Application.Products.Dtos;
-
-namespace Printbase.Application.Products.Queries.GetProductById;
-
-public class GetProductByIdQuery(Guid id, bool includeVariants = true) : IRequest
-{
- public Guid Id { get; } = id;
- public bool IncludeVariants { get; } = includeVariants;
-}
\ No newline at end of file
diff --git a/src/Printbase.Application/Products/Queries/GetProductById/GetProductByIdQueryHandler.cs b/src/Printbase.Application/Products/Queries/GetProductById/GetProductByIdQueryHandler.cs
deleted file mode 100644
index 87ee864..0000000
--- a/src/Printbase.Application/Products/Queries/GetProductById/GetProductByIdQueryHandler.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using AutoMapper;
-using MediatR;
-using Printbase.Application.Products.Dtos;
-using Printbase.Domain.Repositories;
-
-namespace Printbase.Application.Products.Queries.GetProductById;
-
-public class GetProductByIdQueryHandler(IProductRepository productRepository, IMapper mapper)
- : IRequestHandler
-{
- private readonly IProductRepository _productRepository = productRepository
- ?? throw new ArgumentNullException(nameof(productRepository));
- private readonly IMapper _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
-
- public async Task Handle(GetProductByIdQuery request, CancellationToken cancellationToken)
- {
- var product = await _productRepository.GetByIdAsync(request.Id, includeRelations: true, cancellationToken);
-
- if (product == null)
- {
- return null;
- }
-
- var productDto = new ProductDto
- {
- Id = product.Id,
- Name = product.Name,
- Description = product.Description,
- TypeId = product.TypeId,
- TypeName = product.Type.Name,
- GroupName = product.Type.Group.Name,
- CreatedAt = product.CreatedAt,
- UpdatedAt = product.UpdatedAt,
- IsActive = product.IsActive
- };
-
- if (request.IncludeVariants)
- {
- productDto.Variants = product.Variants
- .Select(v => new ProductVariantDto
- {
- Id = v.Id,
- Color = v.Color,
- Size = v.Size,
- Price = v.Price,
- Discount = v.Discount,
- Stock = v.Stock,
- SKU = v.SKU,
- IsActive = v.IsActive
- })
- .ToList();
- }
-
- return productDto;
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.Domain/Entities/Products/Product.cs b/src/Printbase.Domain/Entities/Products/Product.cs
deleted file mode 100644
index 573ed8d..0000000
--- a/src/Printbase.Domain/Entities/Products/Product.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Printbase.Domain.Entities.Products;
-
-public class Product
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
- public string? Description { get; set; }
- public Guid TypeId { get; set; }
- public ProductType Type { get; set; } = null!;
- public ICollection Variants { get; set; } = new List();
- public DateTime CreatedAt { get; set; }
- public DateTime? UpdatedAt { get; set; }
- public bool IsActive { get; set; }
-}
\ No newline at end of file
diff --git a/src/Printbase.Domain/Entities/Products/ProductGroup.cs b/src/Printbase.Domain/Entities/Products/ProductGroup.cs
deleted file mode 100644
index e608022..0000000
--- a/src/Printbase.Domain/Entities/Products/ProductGroup.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Printbase.Domain.Entities.Products;
-
-public class ProductGroup
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
- public string? Description { get; set; }
- public ICollection Types { get; set; } = new List();
- public DateTime CreatedAt { get; set; }
- public DateTime? UpdatedAt { get; set; }
- public bool IsActive { get; set; }
-}
\ No newline at end of file
diff --git a/src/Printbase.Domain/Entities/Products/ProductType.cs b/src/Printbase.Domain/Entities/Products/ProductType.cs
deleted file mode 100644
index b12d6b0..0000000
--- a/src/Printbase.Domain/Entities/Products/ProductType.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Printbase.Domain.Entities.Products;
-
-public class ProductType
-{
- public Guid Id { get; set; }
- public string Name { get; set; } = string.Empty;
- public string? Description { get; set; }
- public Guid GroupId { get; set; }
- public ProductGroup Group { get; set; } = null!;
- public ICollection Products { get; set; } = new List();
- public DateTime CreatedAt { get; set; }
- public DateTime? UpdatedAt { get; set; }
- public bool IsActive { get; set; }
-}
\ No newline at end of file
diff --git a/src/Printbase.Domain/Entities/Products/ProductVariant.cs b/src/Printbase.Domain/Entities/Products/ProductVariant.cs
deleted file mode 100644
index c6246ba..0000000
--- a/src/Printbase.Domain/Entities/Products/ProductVariant.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace Printbase.Domain.Entities.Products;
-
-public class ProductVariant
-{
- public Guid Id { get; set; }
- public Guid ProductId { get; set; }
- public string? Color { get; set; }
- public string? Size { get; set; }
- public decimal Price { get; set; }
- public decimal? Discount { get; set; }
- public int Stock { get; set; }
- public string? SKU { get; set; }
- public Product Product { get; set; } = null!;
- public DateTime CreatedAt { get; set; }
- public DateTime? UpdatedAt { get; set; }
- public bool IsActive { get; set; }
-
- public decimal GetDiscountedPrice()
- {
- if (Discount is > 0)
- {
- return Price - Price * Discount.Value / 100m;
- }
-
- return Price;
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.Domain/Repositories/IProductGroupRepository.cs b/src/Printbase.Domain/Repositories/IProductGroupRepository.cs
deleted file mode 100644
index ab963a0..0000000
--- a/src/Printbase.Domain/Repositories/IProductGroupRepository.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Printbase.Domain.Entities.Products;
-
-namespace Printbase.Domain.Repositories;
-
-public interface IProductGroupRepository
-{
- Task GetByIdAsync(Guid id, bool includeRelations = false, CancellationToken cancellationToken = default);
- Task> GetAllAsync(bool includeRelations = false, CancellationToken cancellationToken = default);
- Task AddAsync(ProductGroup group, CancellationToken cancellationToken = default);
- Task UpdateAsync(ProductGroup group, CancellationToken cancellationToken = default);
- Task DeleteAsync(Guid id, CancellationToken cancellationToken = default);
- Task ExistsAsync(Guid id, CancellationToken cancellationToken = default);
-}
\ No newline at end of file
diff --git a/src/Printbase.Domain/Repositories/IProductRepository.cs b/src/Printbase.Domain/Repositories/IProductRepository.cs
deleted file mode 100644
index f810121..0000000
--- a/src/Printbase.Domain/Repositories/IProductRepository.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Printbase.Domain.Entities.Products;
-
-namespace Printbase.Domain.Repositories;
-
-public interface IProductRepository
-{
- Task GetByIdAsync(Guid id, bool includeRelations = false, CancellationToken cancellationToken = default);
- Task> GetAllAsync(bool includeRelations = false, CancellationToken cancellationToken = default);
- Task> GetByTypeIdAsync(Guid typeId, bool includeRelations = false, CancellationToken cancellationToken = default);
- Task AddAsync(Product product, CancellationToken cancellationToken = default);
- Task UpdateAsync(Product product, CancellationToken cancellationToken = default);
- Task DeleteAsync(Guid id, CancellationToken cancellationToken = default);
- Task ExistsAsync(Guid id, CancellationToken cancellationToken = default);
-}
\ No newline at end of file
diff --git a/src/Printbase.Domain/Repositories/IProductTypeRepository.cs b/src/Printbase.Domain/Repositories/IProductTypeRepository.cs
deleted file mode 100644
index 0603b59..0000000
--- a/src/Printbase.Domain/Repositories/IProductTypeRepository.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Printbase.Domain.Entities.Products;
-
-namespace Printbase.Domain.Repositories;
-
-public interface IProductTypeRepository
-{
- Task GetByIdAsync(Guid id, bool includeRelations = false, CancellationToken cancellationToken = default);
- Task> GetAllAsync(bool includeRelations = false, CancellationToken cancellationToken = default);
- Task> GetByGroupIdAsync(Guid groupId, CancellationToken cancellationToken = default);
- Task AddAsync(ProductType type, CancellationToken cancellationToken = default);
- Task UpdateAsync(ProductType type, CancellationToken cancellationToken = default);
- Task DeleteAsync(Guid id, CancellationToken cancellationToken = default);
- Task ExistsAsync(Guid id, CancellationToken cancellationToken = default);
-}
\ No newline at end of file
diff --git a/src/Printbase.Domain/Repositories/IProductVariantRepository.cs b/src/Printbase.Domain/Repositories/IProductVariantRepository.cs
deleted file mode 100644
index de6b560..0000000
--- a/src/Printbase.Domain/Repositories/IProductVariantRepository.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Printbase.Domain.Entities.Products;
-
-namespace Printbase.Domain.Repositories;
-
-public interface IProductVariantRepository
-{
- Task GetByIdAsync(Guid id, bool includeRelations = false, CancellationToken cancellationToken = default);
- Task> GetAllAsync(bool includeRelations = false, CancellationToken cancellationToken = default);
- Task> GetByProductIdAsync(Guid productId, CancellationToken cancellationToken = default);
- Task AddAsync(ProductVariant variant, CancellationToken cancellationToken = default);
- Task UpdateAsync(ProductVariant variant, CancellationToken cancellationToken = default);
- Task DeleteAsync(Guid id, CancellationToken cancellationToken = default);
- Task ExistsAsync(Guid id, CancellationToken cancellationToken = default);
-}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/Database/ApplicationDbContext.cs b/src/Printbase.Infrastructure/Database/ApplicationDbContext.cs
index 5e056f5..a8aaeb4 100644
--- a/src/Printbase.Infrastructure/Database/ApplicationDbContext.cs
+++ b/src/Printbase.Infrastructure/Database/ApplicationDbContext.cs
@@ -5,39 +5,4 @@ namespace Printbase.Infrastructure.Database;
public class ApplicationDbContext(DbContextOptions? options) : DbContext(options)
{
- public DbSet Products { get; set; } = null!;
- public DbSet ProductVariants { get; set; } = null!;
- public DbSet ProductTypes { get; set; } = null!;
- public DbSet ProductGroups { get; set; } = null!;
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- base.OnModelCreating(modelBuilder);
-
- modelBuilder.Entity()
- .HasMany(p => p.Variants)
- .WithOne(v => v.Product)
- .HasForeignKey(v => v.ProductId)
- .OnDelete(DeleteBehavior.Cascade);
-
- modelBuilder.Entity()
- .HasOne(p => p.Type)
- .WithMany(t => t.Products)
- .HasForeignKey(p => p.TypeId)
- .OnDelete(DeleteBehavior.Restrict);
-
- modelBuilder.Entity()
- .HasOne(t => t.Group)
- .WithMany(g => g.Types)
- .HasForeignKey(t => t.GroupId)
- .OnDelete(DeleteBehavior.Cascade);
-
- modelBuilder.Entity()
- .Property(v => v.Price)
- .HasPrecision(18, 2);
-
- modelBuilder.Entity()
- .Property(v => v.Discount)
- .HasPrecision(18, 2);
- }
}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/DbEntities/Products/ProductDbEntity.cs b/src/Printbase.Infrastructure/DbEntities/Products/ProductDbEntity.cs
deleted file mode 100644
index 06a7e96..0000000
--- a/src/Printbase.Infrastructure/DbEntities/Products/ProductDbEntity.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-
-namespace Printbase.Infrastructure.DbEntities.Products;
-
-[Table("Products")]
-public class ProductDbEntity
-{
- [Key, Required]
- public Guid Id { get; set; }
-
- [MaxLength(50), Required]
- public required string Name { get; set; }
-
- [MaxLength(1000)]
- public string? Description { get; set; }
-
- [Required]
- public Guid TypeId { get; set; }
-
- [Required]
- public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
-
- public DateTime? UpdatedAt { get; set; }
-
- [Required]
- public bool IsActive { get; set; } = true;
-
- [ForeignKey(nameof(TypeId)), Required]
- public required ProductTypeDbEntity Type { get; set; }
-
- [InverseProperty(nameof(ProductVariantDbEntity.Product)), Required]
- public required ICollection Variants { get; set; } = [];
-}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/DbEntities/Products/ProductGroupDbEntity.cs b/src/Printbase.Infrastructure/DbEntities/Products/ProductGroupDbEntity.cs
deleted file mode 100644
index b9b4285..0000000
--- a/src/Printbase.Infrastructure/DbEntities/Products/ProductGroupDbEntity.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Microsoft.EntityFrameworkCore;
-
-namespace Printbase.Infrastructure.DbEntities.Products;
-
-[Table("ProductGroups")]
-[Index(nameof(Name), IsUnique = true)]
-public class ProductGroupDbEntity
-{
- [Key, Required]
- public Guid Id { get; set; }
-
- [MaxLength(50), Required]
- public required string Name { get; set; }
-
- [MaxLength(255)]
- public string? Description { get; set; }
-
- [InverseProperty(nameof(ProductTypeDbEntity.Group)), Required]
- public required ICollection Types { get; set; } = [];
-
- [Required]
- public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
-
- public DateTime? UpdatedAt { get; set; }
-
- [Required]
- public bool IsActive { get; set; } = true;
-}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/DbEntities/Products/ProductTypeDbEntity.cs b/src/Printbase.Infrastructure/DbEntities/Products/ProductTypeDbEntity.cs
deleted file mode 100644
index 4cda53f..0000000
--- a/src/Printbase.Infrastructure/DbEntities/Products/ProductTypeDbEntity.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Microsoft.EntityFrameworkCore;
-
-namespace Printbase.Infrastructure.DbEntities.Products;
-
-[Table("ProductTypes")]
-[Index(nameof(Name), nameof(GroupId), IsUnique = true)]
-public class ProductTypeDbEntity
-{
- [Key, Required]
- public Guid Id { get; set; }
-
- [MaxLength(50), Required]
- public required string Name { get; set; }
-
- [MaxLength(255)]
- public string? Description { get; set; }
-
- [Required]
- public Guid GroupId { get; set; }
-
- [ForeignKey(nameof(GroupId)), Required]
- public required ProductGroupDbEntity Group { get; set; }
-
- [InverseProperty(nameof(ProductDbEntity.Type)), Required]
- public required ICollection Products { get; set; } = [];
-
- [Required]
- public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
-
- public DateTime? UpdatedAt { get; set; }
-
- [Required]
- public bool IsActive { get; set; } = true;
-}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/DbEntities/Products/ProductVariantDbEntity.cs b/src/Printbase.Infrastructure/DbEntities/Products/ProductVariantDbEntity.cs
deleted file mode 100644
index 0c5f48b..0000000
--- a/src/Printbase.Infrastructure/DbEntities/Products/ProductVariantDbEntity.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Microsoft.EntityFrameworkCore;
-
-namespace Printbase.Infrastructure.DbEntities.Products;
-
-[Table("ProductVariants")]
-[Index(nameof(ProductId), nameof(Color), nameof(Size), IsUnique = true)]
-public class ProductVariantDbEntity
-{
- [Key, Required]
- public Guid Id { get; set; }
-
- [Required]
- public Guid ProductId { get; set; }
-
- [MaxLength(50)]
- public string? Color { get; set; }
-
- [MaxLength(20)]
- public string? Size { get; set; }
-
- [Column(TypeName = "decimal(18,2)"), Required]
- [Range(0.01, 9999999.99)]
- public decimal Price { get; set; }
-
- [Range(0, 100)]
- public decimal? Discount { get; set; }
-
- [Required]
- [Range(0, int.MaxValue)]
- public int Stock { get; set; }
-
- [MaxLength(50)]
- public string? SKU { get; set; }
-
- [ForeignKey(nameof(ProductId)), Required]
- public required ProductDbEntity Product { get; set; }
-
- [Required]
- public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
-
- public DateTime? UpdatedAt { get; set; }
-
- [Required]
- public bool IsActive { get; set; } = true;
-}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/Mappings/ProductMappingProfile.cs b/src/Printbase.Infrastructure/Mappings/ProductMappingProfile.cs
deleted file mode 100644
index 8a7e2ab..0000000
--- a/src/Printbase.Infrastructure/Mappings/ProductMappingProfile.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using AutoMapper;
-using Printbase.Application.Products.Commands.CreateProduct;
-using Printbase.Application.Products.Dtos;
-using Printbase.Domain.Entities.Products;
-using Printbase.Infrastructure.DbEntities.Products;
-
-namespace Printbase.Infrastructure.Mappings;
-
-public class ProductMappingProfile : Profile
-{
- public ProductMappingProfile()
- {
- // Product DbEntity -> Domain Entity
- CreateMap()
- .ForMember(dest => dest.Type,
- opt => opt.MapFrom(src => src.Type))
- .ForMember(dest => dest.Variants,
- opt => opt.MapFrom(src => src.Variants));
-
- // ProductGroup DbEntity -> Domain Entity
- CreateMap()
- .ForMember(dest => dest.Types,
- opt => opt.MapFrom(src => src.Types));
-
- // ProductType DbEntity -> Domain Entity
- CreateMap()
- .ForMember(dest => dest.Group,
- opt => opt.MapFrom(src => src.Group))
- .ForMember(dest => dest.Products,
- opt => opt.MapFrom(src => src.Products));
-
- // ProductVariant DbEntity -> Domain Entity
- CreateMap()
- .ForMember(dest => dest.Product,
- opt => opt.MapFrom(src => src.Product));
-
- // Product Domain Entity -> DbEntity
- CreateMap()
- .ForMember(dest => dest.Type,
- opt => opt.Ignore()) // in repo
- .ForMember(dest => dest.Variants,
- opt => opt.Ignore()); // in repo
-
- // ProductVariant Domain Entity -> DbEntity
- CreateMap()
- .ForMember(dest => dest.Product,
- opt => opt.Ignore()); // in repo
-
- // ProductType Domain Entity -> DbEntity
- CreateMap()
- .ForMember(dest => dest.Group,
- opt => opt.Ignore()) // in repo
- .ForMember(dest => dest.Products,
- opt => opt.Ignore()); // in repo
-
- // ProductGroup Domain Entity -> DbEntity
- CreateMap()
- .ForMember(dest => dest.Types,
- opt => opt.Ignore()); // in repo
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/Migrations/20250504210542_InitialCreate.Designer.cs b/src/Printbase.Infrastructure/Migrations/20250504210542_InitialCreate.Designer.cs
deleted file mode 100644
index a12209d..0000000
--- a/src/Printbase.Infrastructure/Migrations/20250504210542_InitialCreate.Designer.cs
+++ /dev/null
@@ -1,231 +0,0 @@
-//
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using Printbase.Infrastructure.Database;
-
-#nullable disable
-
-namespace Printbase.Infrastructure.Migrations
-{
- [DbContext(typeof(ApplicationDbContext))]
- [Migration("20250504210542_InitialCreate")]
- partial class InitialCreate
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "9.0.4")
- .HasAnnotation("Relational:MaxIdentifierLength", 128);
-
- SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductDbEntity", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uniqueidentifier");
-
- b.Property("CreatedAt")
- .HasColumnType("datetime2");
-
- b.Property("Description")
- .HasMaxLength(1000)
- .HasColumnType("nvarchar(1000)");
-
- b.Property("IsActive")
- .HasColumnType("bit");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("TypeId")
- .HasColumnType("uniqueidentifier");
-
- b.Property("UpdatedAt")
- .HasColumnType("datetime2");
-
- b.HasKey("Id");
-
- b.HasIndex("TypeId");
-
- b.ToTable("Products");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductGroupDbEntity", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uniqueidentifier");
-
- b.Property("CreatedAt")
- .HasColumnType("datetime2");
-
- b.Property("Description")
- .HasMaxLength(255)
- .HasColumnType("nvarchar(255)");
-
- b.Property("IsActive")
- .HasColumnType("bit");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("UpdatedAt")
- .HasColumnType("datetime2");
-
- b.HasKey("Id");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("ProductGroups");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductTypeDbEntity", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uniqueidentifier");
-
- b.Property("CreatedAt")
- .HasColumnType("datetime2");
-
- b.Property("Description")
- .HasMaxLength(255)
- .HasColumnType("nvarchar(255)");
-
- b.Property("GroupId")
- .HasColumnType("uniqueidentifier");
-
- b.Property("IsActive")
- .HasColumnType("bit");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("UpdatedAt")
- .HasColumnType("datetime2");
-
- b.HasKey("Id");
-
- b.HasIndex("GroupId");
-
- b.HasIndex("Name", "GroupId")
- .IsUnique();
-
- b.ToTable("ProductTypes");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductVariantDbEntity", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uniqueidentifier");
-
- b.Property("Color")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("CreatedAt")
- .HasColumnType("datetime2");
-
- b.Property("Discount")
- .HasPrecision(18, 2)
- .HasColumnType("decimal(18,2)");
-
- b.Property("IsActive")
- .HasColumnType("bit");
-
- b.Property("Price")
- .HasPrecision(18, 2)
- .HasColumnType("decimal(18,2)");
-
- b.Property("ProductId")
- .HasColumnType("uniqueidentifier");
-
- b.Property("SKU")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("Size")
- .HasMaxLength(20)
- .HasColumnType("nvarchar(20)");
-
- b.Property("Stock")
- .HasColumnType("int");
-
- b.Property("UpdatedAt")
- .HasColumnType("datetime2");
-
- b.HasKey("Id");
-
- b.HasIndex("ProductId", "Color", "Size")
- .IsUnique()
- .HasFilter("[Color] IS NOT NULL AND [Size] IS NOT NULL");
-
- b.ToTable("ProductVariants");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductDbEntity", b =>
- {
- b.HasOne("Printbase.Infrastructure.DbEntities.Products.ProductTypeDbEntity", "Type")
- .WithMany("Products")
- .HasForeignKey("TypeId")
- .OnDelete(DeleteBehavior.Restrict)
- .IsRequired();
-
- b.Navigation("Type");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductTypeDbEntity", b =>
- {
- b.HasOne("Printbase.Infrastructure.DbEntities.Products.ProductGroupDbEntity", "Group")
- .WithMany("Types")
- .HasForeignKey("GroupId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Group");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductVariantDbEntity", b =>
- {
- b.HasOne("Printbase.Infrastructure.DbEntities.Products.ProductDbEntity", "Product")
- .WithMany("Variants")
- .HasForeignKey("ProductId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Product");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductDbEntity", b =>
- {
- b.Navigation("Variants");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductGroupDbEntity", b =>
- {
- b.Navigation("Types");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductTypeDbEntity", b =>
- {
- b.Navigation("Products");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/src/Printbase.Infrastructure/Migrations/20250504210542_InitialCreate.cs b/src/Printbase.Infrastructure/Migrations/20250504210542_InitialCreate.cs
deleted file mode 100644
index c5e1a22..0000000
--- a/src/Printbase.Infrastructure/Migrations/20250504210542_InitialCreate.cs
+++ /dev/null
@@ -1,149 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace Printbase.Infrastructure.Migrations
-{
- ///
- public partial class InitialCreate : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.CreateTable(
- name: "ProductGroups",
- columns: table => new
- {
- Id = table.Column(type: "uniqueidentifier", nullable: false),
- Name = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false),
- Description = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true),
- CreatedAt = table.Column(type: "datetime2", nullable: false),
- UpdatedAt = table.Column(type: "datetime2", nullable: true),
- IsActive = table.Column(type: "bit", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_ProductGroups", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "ProductTypes",
- columns: table => new
- {
- Id = table.Column(type: "uniqueidentifier", nullable: false),
- Name = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false),
- Description = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true),
- GroupId = table.Column(type: "uniqueidentifier", nullable: false),
- CreatedAt = table.Column(type: "datetime2", nullable: false),
- UpdatedAt = table.Column(type: "datetime2", nullable: true),
- IsActive = table.Column(type: "bit", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_ProductTypes", x => x.Id);
- table.ForeignKey(
- name: "FK_ProductTypes_ProductGroups_GroupId",
- column: x => x.GroupId,
- principalTable: "ProductGroups",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateTable(
- name: "Products",
- columns: table => new
- {
- Id = table.Column(type: "uniqueidentifier", nullable: false),
- Name = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false),
- Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
- TypeId = table.Column(type: "uniqueidentifier", nullable: false),
- CreatedAt = table.Column(type: "datetime2", nullable: false),
- UpdatedAt = table.Column(type: "datetime2", nullable: true),
- IsActive = table.Column(type: "bit", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Products", x => x.Id);
- table.ForeignKey(
- name: "FK_Products_ProductTypes_TypeId",
- column: x => x.TypeId,
- principalTable: "ProductTypes",
- principalColumn: "Id",
- onDelete: ReferentialAction.Restrict);
- });
-
- migrationBuilder.CreateTable(
- name: "ProductVariants",
- columns: table => new
- {
- Id = table.Column(type: "uniqueidentifier", nullable: false),
- ProductId = table.Column(type: "uniqueidentifier", nullable: false),
- Color = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
- Size = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: true),
- Price = table.Column(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
- Discount = table.Column(type: "decimal(18,2)", precision: 18, scale: 2, nullable: true),
- Stock = table.Column(type: "int", nullable: false),
- SKU = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true),
- CreatedAt = table.Column(type: "datetime2", nullable: false),
- UpdatedAt = table.Column(type: "datetime2", nullable: true),
- IsActive = table.Column(type: "bit", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_ProductVariants", x => x.Id);
- table.ForeignKey(
- name: "FK_ProductVariants_Products_ProductId",
- column: x => x.ProductId,
- principalTable: "Products",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateIndex(
- name: "IX_ProductGroups_Name",
- table: "ProductGroups",
- column: "Name",
- unique: true);
-
- migrationBuilder.CreateIndex(
- name: "IX_Products_TypeId",
- table: "Products",
- column: "TypeId");
-
- migrationBuilder.CreateIndex(
- name: "IX_ProductTypes_GroupId",
- table: "ProductTypes",
- column: "GroupId");
-
- migrationBuilder.CreateIndex(
- name: "IX_ProductTypes_Name_GroupId",
- table: "ProductTypes",
- columns: new[] { "Name", "GroupId" },
- unique: true);
-
- migrationBuilder.CreateIndex(
- name: "IX_ProductVariants_ProductId_Color_Size",
- table: "ProductVariants",
- columns: new[] { "ProductId", "Color", "Size" },
- unique: true,
- filter: "[Color] IS NOT NULL AND [Size] IS NOT NULL");
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "ProductVariants");
-
- migrationBuilder.DropTable(
- name: "Products");
-
- migrationBuilder.DropTable(
- name: "ProductTypes");
-
- migrationBuilder.DropTable(
- name: "ProductGroups");
- }
- }
-}
diff --git a/src/Printbase.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Printbase.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
deleted file mode 100644
index c26eaeb..0000000
--- a/src/Printbase.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
+++ /dev/null
@@ -1,228 +0,0 @@
-//
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using Printbase.Infrastructure.Database;
-
-#nullable disable
-
-namespace Printbase.Infrastructure.Migrations
-{
- [DbContext(typeof(ApplicationDbContext))]
- partial class ApplicationDbContextModelSnapshot : ModelSnapshot
- {
- protected override void BuildModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "9.0.4")
- .HasAnnotation("Relational:MaxIdentifierLength", 128);
-
- SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductDbEntity", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uniqueidentifier");
-
- b.Property("CreatedAt")
- .HasColumnType("datetime2");
-
- b.Property("Description")
- .HasMaxLength(1000)
- .HasColumnType("nvarchar(1000)");
-
- b.Property("IsActive")
- .HasColumnType("bit");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("TypeId")
- .HasColumnType("uniqueidentifier");
-
- b.Property("UpdatedAt")
- .HasColumnType("datetime2");
-
- b.HasKey("Id");
-
- b.HasIndex("TypeId");
-
- b.ToTable("Products");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductGroupDbEntity", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uniqueidentifier");
-
- b.Property("CreatedAt")
- .HasColumnType("datetime2");
-
- b.Property("Description")
- .HasMaxLength(255)
- .HasColumnType("nvarchar(255)");
-
- b.Property("IsActive")
- .HasColumnType("bit");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("UpdatedAt")
- .HasColumnType("datetime2");
-
- b.HasKey("Id");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("ProductGroups");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductTypeDbEntity", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uniqueidentifier");
-
- b.Property("CreatedAt")
- .HasColumnType("datetime2");
-
- b.Property("Description")
- .HasMaxLength(255)
- .HasColumnType("nvarchar(255)");
-
- b.Property("GroupId")
- .HasColumnType("uniqueidentifier");
-
- b.Property("IsActive")
- .HasColumnType("bit");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("UpdatedAt")
- .HasColumnType("datetime2");
-
- b.HasKey("Id");
-
- b.HasIndex("GroupId");
-
- b.HasIndex("Name", "GroupId")
- .IsUnique();
-
- b.ToTable("ProductTypes");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductVariantDbEntity", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uniqueidentifier");
-
- b.Property("Color")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("CreatedAt")
- .HasColumnType("datetime2");
-
- b.Property("Discount")
- .HasPrecision(18, 2)
- .HasColumnType("decimal(18,2)");
-
- b.Property("IsActive")
- .HasColumnType("bit");
-
- b.Property("Price")
- .HasPrecision(18, 2)
- .HasColumnType("decimal(18,2)");
-
- b.Property("ProductId")
- .HasColumnType("uniqueidentifier");
-
- b.Property("SKU")
- .HasMaxLength(50)
- .HasColumnType("nvarchar(50)");
-
- b.Property("Size")
- .HasMaxLength(20)
- .HasColumnType("nvarchar(20)");
-
- b.Property("Stock")
- .HasColumnType("int");
-
- b.Property("UpdatedAt")
- .HasColumnType("datetime2");
-
- b.HasKey("Id");
-
- b.HasIndex("ProductId", "Color", "Size")
- .IsUnique()
- .HasFilter("[Color] IS NOT NULL AND [Size] IS NOT NULL");
-
- b.ToTable("ProductVariants");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductDbEntity", b =>
- {
- b.HasOne("Printbase.Infrastructure.DbEntities.Products.ProductTypeDbEntity", "Type")
- .WithMany("Products")
- .HasForeignKey("TypeId")
- .OnDelete(DeleteBehavior.Restrict)
- .IsRequired();
-
- b.Navigation("Type");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductTypeDbEntity", b =>
- {
- b.HasOne("Printbase.Infrastructure.DbEntities.Products.ProductGroupDbEntity", "Group")
- .WithMany("Types")
- .HasForeignKey("GroupId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Group");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductVariantDbEntity", b =>
- {
- b.HasOne("Printbase.Infrastructure.DbEntities.Products.ProductDbEntity", "Product")
- .WithMany("Variants")
- .HasForeignKey("ProductId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Product");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductDbEntity", b =>
- {
- b.Navigation("Variants");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductGroupDbEntity", b =>
- {
- b.Navigation("Types");
- });
-
- modelBuilder.Entity("Printbase.Infrastructure.DbEntities.Products.ProductTypeDbEntity", b =>
- {
- b.Navigation("Products");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/src/Printbase.Infrastructure/Repositories/ProductGroupRepository.cs b/src/Printbase.Infrastructure/Repositories/ProductGroupRepository.cs
deleted file mode 100644
index 29e04c4..0000000
--- a/src/Printbase.Infrastructure/Repositories/ProductGroupRepository.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using AutoMapper;
-using Microsoft.EntityFrameworkCore;
-using Printbase.Domain.Entities.Products;
-using Printbase.Domain.Repositories;
-using Printbase.Infrastructure.Database;
-using Printbase.Infrastructure.DbEntities.Products;
-
-namespace Printbase.Infrastructure.Repositories;
-
-public class ProductGroupRepository(ApplicationDbContext dbContext, IMapper mapper) : IProductGroupRepository
-{
- private readonly ApplicationDbContext _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
- private readonly IMapper _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
-
- public async Task GetByIdAsync(Guid id, bool includeRelations = false, CancellationToken cancellationToken = default)
- {
- IQueryable query = _dbContext.ProductGroups;
-
- if (includeRelations) query = query.Include(g => g.Types);
-
- var dbEntity = await query.FirstOrDefaultAsync(g => g.Id == id, cancellationToken);
-
- return dbEntity == null ? null : _mapper.Map(dbEntity);
- }
-
- public async Task> GetAllAsync(bool includeRelations = false, CancellationToken cancellationToken = default)
- {
- IQueryable query = _dbContext.ProductGroups;
-
- if (includeRelations) query = query.Include(g => g.Types);
-
- var dbEntities = await query.ToListAsync(cancellationToken);
-
- return _mapper.Map>(dbEntities);
- }
-
- public async Task AddAsync(ProductGroup group, CancellationToken cancellationToken = default)
- {
- var dbEntity = _mapper.Map(group);
-
- _dbContext.ProductGroups.Add(dbEntity);
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return _mapper.Map(dbEntity);
- }
-
- public async Task UpdateAsync(ProductGroup group, CancellationToken cancellationToken = default)
- {
- var existingEntity = await _dbContext.ProductGroups
- .Include(g => g.Types)
- .FirstOrDefaultAsync(g => g.Id == group.Id, cancellationToken);
-
- if (existingEntity == null) throw new KeyNotFoundException($"ProductGroup with ID {group.Id} not found");
-
- _mapper.Map(group, existingEntity);
-
- existingEntity.UpdatedAt = DateTime.UtcNow;
-
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return _mapper.Map(existingEntity);
- }
-
- public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
- {
- var entity = await _dbContext.ProductGroups.FindAsync([id], cancellationToken);
-
- if (entity == null) return false;
-
- _dbContext.ProductGroups.Remove(entity);
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return true;
- }
-
- public async Task ExistsAsync(Guid id, CancellationToken cancellationToken = default)
- {
- return await _dbContext.ProductGroups.AnyAsync(g => g.Id == id, cancellationToken);
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/Repositories/ProductRepository.cs b/src/Printbase.Infrastructure/Repositories/ProductRepository.cs
deleted file mode 100644
index fa33590..0000000
--- a/src/Printbase.Infrastructure/Repositories/ProductRepository.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-using AutoMapper;
-using Microsoft.EntityFrameworkCore;
-using Printbase.Domain.Entities.Products;
-using Printbase.Domain.Repositories;
-using Printbase.Infrastructure.Database;
-using Printbase.Infrastructure.DbEntities.Products;
-
-namespace Printbase.Infrastructure.Repositories;
-
-public class ProductRepository(ApplicationDbContext dbContext, IMapper mapper) : IProductRepository
-{
- private readonly ApplicationDbContext _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
- private readonly IMapper _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
-
- public async Task GetByIdAsync(Guid id, bool includeRelations = false, CancellationToken cancellationToken = default)
- {
- IQueryable query = _dbContext.Products;
-
- if (includeRelations)
- {
- query = query
- .Include(p => p.Type)
- .ThenInclude(t => t.Group)
- .Include(p => p.Variants);
- }
-
- var dbEntity = await query.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
-
- return dbEntity == null ? null : _mapper.Map(dbEntity);
- }
-
- public async Task> GetAllAsync(bool includeRelations = false, CancellationToken cancellationToken = default)
- {
- IQueryable query = _dbContext.Products;
-
- if (includeRelations)
- {
- query = query
- .Include(p => p.Type)
- .ThenInclude(t => t.Group)
- .Include(p => p.Variants);
- }
-
- var dbEntities = await query.ToListAsync(cancellationToken);
-
- return _mapper.Map>(dbEntities);
- }
-
- public async Task> GetByTypeIdAsync(Guid typeId, bool includeRelations = false, CancellationToken cancellationToken = default)
- {
- var query = _dbContext.Products.Where(p => p.TypeId == typeId);
-
- if (includeRelations)
- {
- query = query
- .Include(p => p.Type)
- .ThenInclude(t => t.Group)
- .Include(p => p.Variants);
- }
-
- var dbEntities = await query.ToListAsync(cancellationToken);
-
- return _mapper.Map>(dbEntities);
- }
-
- public async Task AddAsync(Product product, CancellationToken cancellationToken = default)
- {
- var dbEntity = _mapper.Map(product);
-
- dbEntity.Type = await _dbContext.ProductTypes.FindAsync([product.TypeId], cancellationToken)
- ?? throw new InvalidOperationException($"ProductType with ID {product.TypeId} not found");
-
- _dbContext.Products.Add(dbEntity);
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return _mapper.Map(dbEntity);
- }
-
- public async Task UpdateAsync(Product product, CancellationToken cancellationToken = default)
- {
- var existingEntity = await _dbContext.Products
- .Include(p => p.Variants)
- .FirstOrDefaultAsync(p => p.Id == product.Id, cancellationToken);
-
- if (existingEntity == null) throw new KeyNotFoundException($"Product with ID {product.Id} not found");
-
- _mapper.Map(product, existingEntity);
-
- if (existingEntity.TypeId != product.TypeId)
- {
- existingEntity.Type = await _dbContext.ProductTypes.FindAsync([product.TypeId], cancellationToken)
- ?? throw new InvalidOperationException($"ProductType with ID {product.TypeId} not found");
- existingEntity.TypeId = product.TypeId;
- }
-
- existingEntity.UpdatedAt = DateTime.UtcNow;
-
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return _mapper.Map(existingEntity);
- }
-
- public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
- {
- var entity = await _dbContext.Products.FindAsync([id], cancellationToken);
-
- if (entity == null) return false;
-
- _dbContext.Products.Remove(entity);
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return true;
- }
-
- public async Task ExistsAsync(Guid id, CancellationToken cancellationToken = default)
- {
- return await _dbContext.Products.AnyAsync(p => p.Id == id, cancellationToken);
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/Repositories/ProductTypeRepository.cs b/src/Printbase.Infrastructure/Repositories/ProductTypeRepository.cs
deleted file mode 100644
index b016b72..0000000
--- a/src/Printbase.Infrastructure/Repositories/ProductTypeRepository.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-using AutoMapper;
-using Microsoft.EntityFrameworkCore;
-using Printbase.Domain.Entities.Products;
-using Printbase.Domain.Repositories;
-using Printbase.Infrastructure.Database;
-using Printbase.Infrastructure.DbEntities.Products;
-
-namespace Printbase.Infrastructure.Repositories;
-
-public class ProductTypeRepository(ApplicationDbContext dbContext, IMapper mapper) : IProductTypeRepository
-{
- private readonly ApplicationDbContext _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
- private readonly IMapper _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
-
- public async Task GetByIdAsync(Guid id, bool includeRelations = false, CancellationToken cancellationToken = default)
- {
- IQueryable query = _dbContext.ProductTypes;
-
- if (includeRelations)
- {
- query = query
- .Include(t => t.Group)
- .Include(t => t.Products);
- }
-
- var dbEntity = await query.FirstOrDefaultAsync(t => t.Id == id, cancellationToken);
-
- return dbEntity == null ? null : _mapper.Map(dbEntity);
- }
-
- public async Task> GetAllAsync(bool includeRelations = false, CancellationToken cancellationToken = default)
- {
- IQueryable query = _dbContext.ProductTypes;
-
- if (includeRelations)
- {
- query = query
- .Include(t => t.Group)
- .Include(t => t.Products);
- }
-
- var dbEntities = await query.ToListAsync(cancellationToken);
-
- return _mapper.Map>(dbEntities);
- }
-
- public async Task> GetByGroupIdAsync(Guid groupId, CancellationToken cancellationToken = default)
- {
- var dbEntities = await _dbContext.ProductTypes
- .Where(t => t.GroupId == groupId)
- .ToListAsync(cancellationToken);
-
- return _mapper.Map>(dbEntities);
- }
-
- public async Task AddAsync(ProductType type, CancellationToken cancellationToken = default)
- {
- var dbEntity = _mapper.Map(type);
-
- dbEntity.Group = await _dbContext.ProductGroups.FindAsync([type.GroupId], cancellationToken)
- ?? throw new InvalidOperationException($"ProductGroup with ID {type.GroupId} not found");
-
- _dbContext.ProductTypes.Add(dbEntity);
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return _mapper.Map(dbEntity);
- }
-
- public async Task UpdateAsync(ProductType type, CancellationToken cancellationToken = default)
- {
- var existingEntity = await _dbContext.ProductTypes
- .Include(t => t.Products)
- .FirstOrDefaultAsync(t => t.Id == type.Id, cancellationToken);
-
- if (existingEntity == null) throw new KeyNotFoundException($"ProductType with ID {type.Id} not found");
-
- _mapper.Map(type, existingEntity);
-
- if (existingEntity.GroupId != type.GroupId)
- {
- existingEntity.Group = await _dbContext.ProductGroups.FindAsync([type.GroupId], cancellationToken)
- ?? throw new InvalidOperationException($"ProductGroup with ID {type.GroupId} not found");
- existingEntity.GroupId = type.GroupId;
- }
-
- existingEntity.UpdatedAt = DateTime.UtcNow;
-
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return _mapper.Map(existingEntity);
- }
-
- public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
- {
- var entity = await _dbContext.ProductTypes.FindAsync([id], cancellationToken);
-
- if (entity == null)
- {
- return false;
- }
-
- _dbContext.ProductTypes.Remove(entity);
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return true;
- }
-
- public async Task ExistsAsync(Guid id, CancellationToken cancellationToken = default)
- {
- return await _dbContext.ProductTypes.AnyAsync(t => t.Id == id, cancellationToken);
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.Infrastructure/Repositories/ProductVariantRepository.cs b/src/Printbase.Infrastructure/Repositories/ProductVariantRepository.cs
deleted file mode 100644
index e2761fb..0000000
--- a/src/Printbase.Infrastructure/Repositories/ProductVariantRepository.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-using AutoMapper;
-using Microsoft.EntityFrameworkCore;
-using Printbase.Domain.Entities.Products;
-using Printbase.Domain.Repositories;
-using Printbase.Infrastructure.Database;
-using Printbase.Infrastructure.DbEntities.Products;
-
-namespace Printbase.Infrastructure.Repositories;
-
-public class ProductVariantRepository(ApplicationDbContext dbContext, IMapper mapper) : IProductVariantRepository
-{
- private readonly ApplicationDbContext _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
- private readonly IMapper _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
-
- public async Task GetByIdAsync(Guid id, bool includeRelations = false, CancellationToken cancellationToken = default)
- {
- IQueryable query = _dbContext.ProductVariants;
-
- if (includeRelations)
- query = query.Include(v => v.Product)
- .ThenInclude(p => p.Type);
-
- var dbEntity = await query.FirstOrDefaultAsync(v => v.Id == id, cancellationToken);
-
- return dbEntity == null ? null : _mapper.Map(dbEntity);
- }
-
- public async Task> GetAllAsync(bool includeRelations = false, CancellationToken cancellationToken = default)
- {
- IQueryable query = _dbContext.ProductVariants;
-
- if (includeRelations)
- query = query.Include(v => v.Product)
- .ThenInclude(p => p.Type);
-
- var dbEntities = await query.ToListAsync(cancellationToken);
-
- return _mapper.Map>(dbEntities);
- }
-
- public async Task> GetByProductIdAsync(Guid productId, CancellationToken cancellationToken = default)
- {
- var dbEntities = await _dbContext.ProductVariants
- .Where(v => v.ProductId == productId)
- .ToListAsync(cancellationToken);
-
- return _mapper.Map>(dbEntities);
- }
-
- public async Task AddAsync(ProductVariant variant, CancellationToken cancellationToken = default)
- {
- var dbEntity = _mapper.Map(variant);
-
- dbEntity.Product = await _dbContext.Products.FindAsync([variant.ProductId], cancellationToken)
- ?? throw new InvalidOperationException($"Product with ID {variant.ProductId} not found");
-
- _dbContext.ProductVariants.Add(dbEntity);
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return _mapper.Map(dbEntity);
- }
-
- public async Task UpdateAsync(ProductVariant variant, CancellationToken cancellationToken = default)
- {
- var existingEntity = await _dbContext.ProductVariants
- .FindAsync([variant.Id], cancellationToken);
-
- if (existingEntity == null) throw new KeyNotFoundException($"ProductVariant with ID {variant.Id} not found");
-
- _mapper.Map(variant, existingEntity);
-
- if (existingEntity.ProductId != variant.ProductId)
- {
- existingEntity.Product = await _dbContext.Products.FindAsync([variant.ProductId], cancellationToken)
- ?? throw new InvalidOperationException($"Product with ID {variant.ProductId} not found");
- existingEntity.ProductId = variant.ProductId;
- }
-
- existingEntity.UpdatedAt = DateTime.UtcNow;
-
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return _mapper.Map(existingEntity);
- }
-
- public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
- {
- var entity = await _dbContext.ProductVariants.FindAsync([id], cancellationToken);
-
- if (entity == null) return false;
-
- _dbContext.ProductVariants.Remove(entity);
- await _dbContext.SaveChangesAsync(cancellationToken);
-
- return true;
- }
-
- public async Task ExistsAsync(Guid id, CancellationToken cancellationToken = default)
- {
- return await _dbContext.ProductVariants.AnyAsync(v => v.Id == id, cancellationToken);
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.WebApi/Controllers/ProductsController.cs b/src/Printbase.WebApi/Controllers/ProductsController.cs
deleted file mode 100644
index 337f398..0000000
--- a/src/Printbase.WebApi/Controllers/ProductsController.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using MediatR;
-using Microsoft.AspNetCore.Mvc;
-using Printbase.Application.Products.Commands.CreateProduct;
-using Printbase.Application.Products.Queries.GetAllProducts;
-using Printbase.Application.Products.Queries.GetProductById;
-
-namespace Printbase.WebApi.Controllers;
-
-[ApiController]
-[Route("api/[controller]")]
-public class ProductsController(IMediator mediator) : ControllerBase
-{
- private readonly IMediator _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
-
- [HttpGet]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task GetAllProducts()
- {
- var query = new GetAllProductsQuery();
- var result = await _mediator.Send(query);
-
- if (result == null) return NotFound();
- return Ok(result);
- }
-
- [HttpGet("{id:guid}")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task GetProductById(Guid id, [FromQuery] bool includeVariants = true)
- {
- var query = new GetProductByIdQuery(id, includeVariants);
- var result = await _mediator.Send(query);
-
- if (result == null) return NotFound();
- return Ok(result);
- }
-
- [HttpPost]
- [ProducesResponseType(StatusCodes.Status201Created)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
- public async Task CreateProduct([FromBody] CreateProductCommand command)
- {
- if (!ModelState.IsValid) return BadRequest(ModelState);
-
- try
- {
- var result = await _mediator.Send(command);
- return CreatedAtAction(nameof(GetProductById), new { id = result.Id }, result);
- }
- catch (ArgumentException ex)
- {
- return BadRequest(ex.Message);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Printbase.WebApi/Startup.cs b/src/Printbase.WebApi/Startup.cs
index 000273e..9ec1ea7 100644
--- a/src/Printbase.WebApi/Startup.cs
+++ b/src/Printbase.WebApi/Startup.cs
@@ -1,10 +1,5 @@
-using System.Reflection;
using Microsoft.EntityFrameworkCore;
-using Printbase.Application.Products.Commands.CreateProduct;
-using Printbase.Domain.Repositories;
using Printbase.Infrastructure.Database;
-using Printbase.Infrastructure.Mappings;
-using Printbase.Infrastructure.Repositories;
namespace Printbase.WebApi;
@@ -13,29 +8,11 @@ public static class Startup
public static void ConfigureServices(WebApplicationBuilder builder)
{
var services = builder.Services;
-
+
services.AddDbContext(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
-
- services.AddMediatR(cfg => {
- cfg.RegisterServicesFromAssembly(typeof(CreateProductCommand).Assembly);
- cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
- });
-
- services.AddScoped();
- services.AddScoped();
- services.AddScoped();
- services.AddScoped();
-
- services.AddAutoMapper(cfg =>
- {
- cfg.AddProfile();
- }, typeof(ProductMappingProfile).Assembly);
- services.AddSwaggerGen();
- services.AddControllers();
- services.AddOpenApi();
}
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
@@ -57,14 +34,12 @@ public static class Startup
if (env.IsDevelopment())
{
- Console.WriteLine("Development environment variables applied");
app.UseSwagger();
app.UseSwaggerUI();
app.UseDeveloperExceptionPage();
}
else
{
- Console.WriteLine("Production environment variables applied");
app.UseExceptionHandler("/Error");
app.UseHsts();
app.UseHttpsRedirection();
diff --git a/tests/Printbase.Application.Tests/Products/Commands/CreateProduct/GenerateSkuTests.cs b/tests/Printbase.Application.Tests/Products/Commands/CreateProduct/GenerateSkuTests.cs
deleted file mode 100644
index d08bcac..0000000
--- a/tests/Printbase.Application.Tests/Products/Commands/CreateProduct/GenerateSkuTests.cs
+++ /dev/null
@@ -1,187 +0,0 @@
-using Printbase.Application.Products.Commands.CreateProduct;
-
-namespace Printbase.Application.Tests.Products.Commands.CreateProduct;
-
-using Xunit;
-
-public class GenerateSkuTests
-{
- [Fact]
- public void GenerateSku_WithValidInputs_ReturnsCorrectFormat()
- {
- // Arrange
- const string productName = "Shirt";
- const string color = "Blue";
- const string size = "Medium";
-
- // Act
- var sku = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var parts = sku.Split('-');
-
- // Assert
- Assert.Equal(4, parts.Length);
- Assert.Equal("SHI", parts[0]);
- Assert.Equal("BLU", parts[1]);
- Assert.Equal("MEDIUM", parts[2]);
- Assert.Matches(@"^\d{3}$", parts[3]);
- }
-
- [Fact]
- public void GenerateSku_WithShortProductName_UsesEntireProductName()
- {
- // Arrange
- const string productName = "CU";
- const string color = "Black";
- const string size = "Large";
-
- // Act
- var sku = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var parts = sku.Split('-');
-
- // Assert
- Assert.Equal("CU", parts[0]);
- Assert.Equal("BLA", parts[1]);
- Assert.Equal("LARGE", parts[2]);
- }
-
- [Fact]
- public void GenerateSku_WithShortColor_UsesEntireColor()
- {
- // Arrange
- const string productName = "Mug";
- const string color = "Red";
- const string size = "Small";
-
- // Act
- var sku = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var parts = sku.Split('-');
-
- // Assert
- Assert.Equal("MUG", parts[0]);
- Assert.Equal("RED", parts[1]);
- Assert.Equal("SMALL", parts[2]);
- }
-
- [Fact]
- public void GenerateSku_WithNullColor_UsesXXX()
- {
- // Arrange
- const string productName = "Case";
- string? color = null;
- const string size = "Standard";
-
- // Act
- var sku = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var parts = sku.Split('-');
-
- // Assert
- Assert.Equal("CAS", parts[0]);
- Assert.Equal("XXX", parts[1]);
- Assert.Equal("STANDARD", parts[2]);
- }
-
- [Fact]
- public void GenerateSku_WithEmptyColor_UsesXXX()
- {
- // Arrange
- const string productName = "Notebook";
- const string color = "";
- const string size = "Standard";
-
- // Act
- var sku = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var parts = sku.Split('-');
-
- // Assert
- Assert.Equal("NOT", parts[0]);
- Assert.Equal("XXX", parts[1]);
- Assert.Equal("STANDARD", parts[2]);
- }
-
- [Fact]
- public void GenerateSku_WithNullSize_UsesOS()
- {
- // Arrange
- const string productName = "Watch";
- const string color = "Silver";
- string? size = null;
-
- // Act
- var sku = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var parts = sku.Split('-');
-
- // Assert
- Assert.Equal("WAT", parts[0]);
- Assert.Equal("SIL", parts[1]);
- Assert.Equal("OS", parts[2]);
- }
-
- [Fact]
- public void GenerateSku_WithEmptySize_UsesOS()
- {
- // Arrange
- const string productName = "Shirt";
- const string color = "Black";
- const string size = "";
-
- // Act
- var sku = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var parts = sku.Split('-');
-
- // Assert
- Assert.Equal("SHI", parts[0]);
- Assert.Equal("BLA", parts[1]);
- Assert.Equal("OS", parts[2]);
- }
-
- [Fact]
- public void GenerateSku_CaseInsensitivity_OutputsUppercase()
- {
- // Arrange
- const string productName = "hat";
- const string color = "red";
- const string size = "small";
-
- // Act
- var sku = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var parts = sku.Split('-');
-
- // Assert
- Assert.Equal("HAT", parts[0]);
- Assert.Equal("RED", parts[1]);
- Assert.Equal("SMALL", parts[2]);
- }
-
- [Fact]
- public void GenerateSku_RandomPartIsInRange()
- {
- // Arrange
- const string productName = "Book";
- const string color = "Green";
- const string size = "Medium";
-
- // Act
- var sku = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var parts = sku.Split('-');
- var randomPart = int.Parse(parts[3]);
-
- // Assert
- Assert.InRange(randomPart, 100, 999);
- }
-
- [Fact]
- public void GenerateSku_GeneratesUniqueSKUs()
- {
- // Arrange
- const string productName = "Mug";
- const string color = "White";
- const string size = "Regular";
-
- // Act
- var sku1 = CreateProductCommandHandler.GenerateSku(productName, color, size);
- var sku2 = CreateProductCommandHandler.GenerateSku(productName, color, size);
-
- // Assert
- Assert.NotEqual(sku1, sku2);
- }
-}
\ No newline at end of file