Rebadge the rest of the files

This commit is contained in:
lumijiez
2025-06-03 18:24:40 +03:00
parent 1b6f69fcf9
commit 6a675ac111
77 changed files with 5931 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
using Imprink.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration;
public class EntityBaseConfiguration<T> : IEntityTypeConfiguration<T> where T : EntityBase
{
public virtual void Configure(EntityTypeBuilder<T> builder)
{
builder.HasKey(e => e.Id);
builder.Property(e => e.Id)
.HasDefaultValueSql("NEWID()");
builder.Property(e => e.CreatedAt)
.IsRequired();
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)
.HasDatabaseName($"IX_{typeof(T).Name}_CreatedAt");
builder.HasIndex(e => e.ModifiedAt)
.HasDatabaseName($"IX_{typeof(T).Name}_ModifiedAt");
builder.HasIndex(e => e.CreatedBy)
.HasDatabaseName($"IX_{typeof(T).Name}_CreatedBy");
}
}

View File

@@ -0,0 +1,39 @@
using Imprink.Domain.Entities.Orders;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Orders;
public class OrderAddressConfiguration : EntityBaseConfiguration<OrderAddress>
{
public override void Configure(EntityTypeBuilder<OrderAddress> builder)
{
base.Configure(builder);
builder.Property(oa => oa.OrderId)
.IsRequired();
builder.Property(oa => oa.Street)
.IsRequired()
.HasMaxLength(200);
builder.Property(oa => oa.City)
.IsRequired()
.HasMaxLength(100);
builder.Property(oa => oa.State)
.HasMaxLength(100);
builder.Property(oa => oa.PostalCode)
.IsRequired()
.HasMaxLength(20);
builder.Property(oa => oa.Country)
.IsRequired()
.HasMaxLength(100);
builder.HasIndex(oa => oa.OrderId)
.IsUnique()
.HasDatabaseName("IX_OrderAddress_OrderId");
}
}

View File

@@ -0,0 +1,77 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Orders;
public class OrderConfiguration : EntityBaseConfiguration<Order>
{
public override void Configure(EntityTypeBuilder<Order> builder)
{
base.Configure(builder);
builder.Property(o => o.UserId)
.IsRequired()
.HasMaxLength(450);
builder.Property(o => o.OrderDate)
.IsRequired();
builder.Property(o => o.TotalPrice)
.IsRequired()
.HasColumnType("decimal(18,2)");
builder.Property(o => o.OrderStatusId)
.IsRequired();
builder.Property(o => o.ShippingStatusId)
.IsRequired();
builder.Property(o => o.OrderNumber)
.IsRequired()
.HasMaxLength(50);
builder.Property(o => o.Notes)
.HasMaxLength(1000);
builder.HasOne<ApplicationUser>()
.WithMany(u => u.Orders)
.HasForeignKey(o => o.UserId)
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(o => o.OrderStatus)
.WithMany(os => os.Orders)
.HasForeignKey(o => o.OrderStatusId)
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(o => o.ShippingStatus)
.WithMany(ss => ss.Orders)
.HasForeignKey(o => o.ShippingStatusId)
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(o => o.OrderAddress)
.WithOne(oa => oa.Order)
.HasForeignKey<OrderAddress>(oa => oa.OrderId)
.OnDelete(DeleteBehavior.Cascade);
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");
builder.HasIndex(o => o.OrderStatusId)
.HasDatabaseName("IX_Order_OrderStatusId");
builder.HasIndex(o => o.ShippingStatusId)
.HasDatabaseName("IX_Order_ShippingStatusId");
builder.HasIndex(o => new { o.UserId, o.OrderDate })
.HasDatabaseName("IX_Order_User_Date");
}
}

View File

@@ -0,0 +1,64 @@
using Imprink.Domain.Entities.Orders;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Orders;
public class OrderItemConfiguration : EntityBaseConfiguration<OrderItem>
{
public override void Configure(EntityTypeBuilder<OrderItem> builder)
{
base.Configure(builder);
builder.Property(oi => oi.OrderId)
.IsRequired();
builder.Property(oi => oi.ProductId)
.IsRequired();
builder.Property(oi => oi.Quantity)
.IsRequired()
.HasDefaultValue(1);
builder.Property(oi => oi.UnitPrice)
.IsRequired()
.HasColumnType("decimal(18,2)");
builder.Property(oi => oi.TotalPrice)
.IsRequired()
.HasColumnType("decimal(18,2)");
builder.Property(oi => oi.CustomizationImageUrl)
.HasMaxLength(500);
builder.Property(oi => oi.CustomizationDescription)
.HasMaxLength(2000);
builder.HasOne(oi => oi.Order)
.WithMany(o => o.OrderItems)
.HasForeignKey(oi => oi.OrderId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne(oi => oi.Product)
.WithMany(p => p.OrderItems)
.HasForeignKey(oi => oi.ProductId)
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(oi => oi.ProductVariant)
.WithMany(pv => pv.OrderItems)
.HasForeignKey(oi => oi.ProductVariantId)
.OnDelete(DeleteBehavior.Restrict);
builder.HasIndex(oi => oi.OrderId)
.HasDatabaseName("IX_OrderItem_OrderId");
builder.HasIndex(oi => oi.ProductId)
.HasDatabaseName("IX_OrderItem_ProductId");
builder.HasIndex(oi => oi.ProductVariantId)
.HasDatabaseName("IX_OrderItem_ProductVariantId");
builder.HasIndex(oi => new { oi.OrderId, oi.ProductId })
.HasDatabaseName("IX_OrderItem_Order_Product");
}
}

View File

@@ -0,0 +1,31 @@
using Imprink.Domain.Entities.Orders;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Orders;
public class OrderStatusConfiguration : IEntityTypeConfiguration<OrderStatus>
{
public void Configure(EntityTypeBuilder<OrderStatus> builder)
{
builder.HasKey(os => os.Id);
builder.Property(os => os.Id)
.ValueGeneratedNever();
builder.Property(os => os.Name)
.IsRequired()
.HasMaxLength(50);
builder.HasIndex(os => os.Name)
.IsUnique()
.HasDatabaseName("IX_OrderStatus_Name");
builder.HasData(
new OrderStatus { Id = 0, Name = "Pending" },
new OrderStatus { Id = 1, Name = "Processing" },
new OrderStatus { Id = 2, Name = "Completed" },
new OrderStatus { Id = 3, Name = "Cancelled" }
);
}
}

View File

@@ -0,0 +1,31 @@
using Imprink.Domain.Entities.Orders;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Orders;
public class ShippingStatusConfiguration : IEntityTypeConfiguration<ShippingStatus>
{
public void Configure(EntityTypeBuilder<ShippingStatus> builder)
{
builder.HasKey(ss => ss.Id);
builder.Property(ss => ss.Id)
.ValueGeneratedNever();
builder.Property(ss => ss.Name)
.IsRequired()
.HasMaxLength(50);
builder.HasIndex(ss => ss.Name)
.IsUnique()
.HasDatabaseName("IX_ShippingStatus_Name");
builder.HasData(
new ShippingStatus { Id = 0, Name = "Prepping" },
new ShippingStatus { Id = 1, Name = "Packaging" },
new ShippingStatus { Id = 2, Name = "Shipped" },
new ShippingStatus { Id = 3, Name = "Delivered" }
);
}
}

View File

@@ -0,0 +1,105 @@
using Imprink.Domain.Entities.Product;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Products;
public class CategoryConfiguration : EntityBaseConfiguration<Category>
{
public override void Configure(EntityTypeBuilder<Category> builder)
{
base.Configure(builder);
builder.Property(c => c.Name)
.IsRequired()
.HasMaxLength(200);
builder.Property(c => c.Description)
.HasMaxLength(2000);
builder.Property(c => c.ImageUrl)
.HasMaxLength(500);
builder.Property(c => c.SortOrder)
.IsRequired()
.HasDefaultValue(0);
builder.Property(c => c.IsActive)
.IsRequired()
.HasDefaultValue(true);
builder.Property(c => c.ParentCategoryId)
.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(c => c.ParentCategory)
.WithMany(c => c.SubCategories)
.HasForeignKey(c => c.ParentCategoryId)
.OnDelete(DeleteBehavior.Restrict);
builder.HasIndex(c => c.Name)
.HasDatabaseName("IX_Category_Name");
builder.HasIndex(c => c.IsActive)
.HasDatabaseName("IX_Category_IsActive");
builder.HasIndex(c => c.ParentCategoryId)
.HasDatabaseName("IX_Category_ParentCategoryId");
builder.HasIndex(c => new { c.ParentCategoryId, c.SortOrder })
.HasDatabaseName("IX_Category_Parent_SortOrder");
builder.HasIndex(c => new { c.IsActive, c.SortOrder })
.HasDatabaseName("IX_Category_Active_SortOrder");
builder.HasData(
new Category
{
Id = Guid.Parse("11111111-1111-1111-1111-111111111111"),
Name = "Textile",
Description = "Textile and fabric-based products",
IsActive = true,
SortOrder = 1,
CreatedAt = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc),
ModifiedAt = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc),
CreatedBy = "system@printbase.com",
ModifiedBy = "system@printbase.com"
},
new Category
{
Id = Guid.Parse("22222222-2222-2222-2222-222222222222"),
Name = "Hard Surfaces",
Description = "Products for hard surface printing",
IsActive = true,
SortOrder = 2,
CreatedAt = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc),
ModifiedAt = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc),
CreatedBy = "system@printbase.com",
ModifiedBy = "system@printbase.com"
},
new Category
{
Id = Guid.Parse("33333333-3333-3333-3333-333333333333"),
Name = "Paper",
Description = "Paper-based printing products",
IsActive = true,
SortOrder = 3,
CreatedAt = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc),
ModifiedAt = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc),
CreatedBy = "system@printbase.com",
ModifiedBy = "system@printbase.com"
}
);
}
}

View File

@@ -0,0 +1,73 @@
using Imprink.Domain.Entities.Product;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Products;
public class ProductConfiguration : EntityBaseConfiguration<Product>
{
public override void Configure(EntityTypeBuilder<Product> builder)
{
base.Configure(builder);
builder.Property(p => p.Name)
.IsRequired()
.HasMaxLength(200);
builder.Property(p => p.Description)
.HasMaxLength(2000);
builder.Property(p => p.BasePrice)
.IsRequired()
.HasColumnType("decimal(18,2)");
builder.Property(p => p.IsCustomizable)
.IsRequired()
.HasDefaultValue(false);
builder.Property(p => p.IsActive)
.IsRequired()
.HasDefaultValue(true);
builder.Property(p => p.ImageUrl)
.HasMaxLength(500);
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)
.HasForeignKey(p => p.CategoryId)
.OnDelete(DeleteBehavior.SetNull);
builder.HasIndex(p => p.Name)
.HasDatabaseName("IX_Product_Name");
builder.HasIndex(p => p.IsActive)
.HasDatabaseName("IX_Product_IsActive");
builder.HasIndex(p => p.IsCustomizable)
.HasDatabaseName("IX_Product_IsCustomizable");
builder.HasIndex(p => p.CategoryId)
.HasDatabaseName("IX_Product_CategoryId");
builder.HasIndex(p => new { p.IsActive, p.IsCustomizable })
.HasDatabaseName("IX_Product_Active_Customizable");
builder.HasIndex(p => new { p.CategoryId, p.IsActive })
.HasDatabaseName("IX_Product_Category_Active");
}
}

View File

@@ -0,0 +1,72 @@
using Imprink.Domain.Entities.Product;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Products;
public class ProductVariantConfiguration : EntityBaseConfiguration<ProductVariant>
{
public override void Configure(EntityTypeBuilder<ProductVariant> builder)
{
base.Configure(builder);
builder.Property(pv => pv.ProductId)
.IsRequired();
builder.Property(pv => pv.Size)
.HasMaxLength(50);
builder.Property(pv => pv.Color)
.HasMaxLength(50);
builder.Property(pv => pv.Price)
.IsRequired()
.HasColumnType("decimal(18,2)");
builder.Property(pv => pv.ImageUrl)
.HasMaxLength(500);
builder.Property(pv => pv.Sku)
.IsRequired()
.HasMaxLength(100);
builder.Property(pv => pv.StockQuantity)
.IsRequired()
.HasDefaultValue(0);
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)
.HasForeignKey(pv => pv.ProductId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasIndex(pv => pv.ProductId)
.HasDatabaseName("IX_ProductVariant_ProductId");
builder.HasIndex(pv => pv.Sku)
.IsUnique()
.HasDatabaseName("IX_ProductVariant_SKU");
builder.HasIndex(pv => pv.IsActive)
.HasDatabaseName("IX_ProductVariant_IsActive");
builder.HasIndex(pv => new { pv.ProductId, pv.Size, pv.Color })
.IsUnique()
.HasDatabaseName("IX_ProductVariant_Product_Size_Color");
}
}

View File

@@ -0,0 +1,62 @@
using Imprink.Domain.Entities.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Users;
public class AddressConfiguration : EntityBaseConfiguration<Address>
{
public override void Configure(EntityTypeBuilder<Address> builder)
{
base.Configure(builder);
builder.Property(a => a.UserId)
.IsRequired()
.HasMaxLength(450);
builder.Property(a => a.AddressType)
.IsRequired()
.HasMaxLength(50);
builder.Property(a => a.Street)
.IsRequired()
.HasMaxLength(200);
builder.Property(a => a.City)
.IsRequired()
.HasMaxLength(100);
builder.Property(a => a.State)
.HasMaxLength(100);
builder.Property(a => a.PostalCode)
.IsRequired()
.HasMaxLength(20);
builder.Property(a => a.Country)
.IsRequired()
.HasMaxLength(100);
builder.Property(a => a.IsDefault)
.IsRequired()
.HasDefaultValue(false);
builder.Property(a => a.IsActive)
.IsRequired()
.HasDefaultValue(true);
builder.HasOne<ApplicationUser>()
.WithMany(u => u.Addresses)
.HasForeignKey(a => a.UserId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasIndex(a => a.UserId)
.HasDatabaseName("IX_Address_UserId");
builder.HasIndex(a => new { a.UserId, a.AddressType })
.HasDatabaseName("IX_Address_User_Type");
builder.HasIndex(a => new { a.UserId, a.IsDefault })
.HasDatabaseName("IX_Address_User_Default");
}
}

View File

@@ -0,0 +1,66 @@
using Imprink.Domain.Entities.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Users;
public class ApplicationRoleConfiguration : IEntityTypeConfiguration<ApplicationRole>
{
public void Configure(EntityTypeBuilder<ApplicationRole> builder)
{
builder.Property(r => r.Description)
.HasMaxLength(500);
builder.Property(r => r.CreatedAt)
.IsRequired()
.HasDefaultValueSql("GETUTCDATE()");
builder.Property(r => r.IsActive)
.IsRequired()
.HasDefaultValue(true);
builder.HasIndex(r => r.IsActive)
.HasDatabaseName("IX_ApplicationRole_IsActive");
var seedDate = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc);
builder.HasData(
new ApplicationRole
{
Id = "1",
Name = "Administrator",
NormalizedName = "ADMINISTRATOR",
Description = "Full system access",
CreatedAt = seedDate,
IsActive = true
},
new ApplicationRole
{
Id = "2",
Name = "Customer",
NormalizedName = "CUSTOMER",
Description = "Standard customer access",
CreatedAt = seedDate,
IsActive = true
},
new ApplicationRole
{
Id = "3",
Name = "OrderManager",
NormalizedName = "ORDERMANAGER",
Description = "Manage orders and fulfillment",
CreatedAt = seedDate,
IsActive = true
},
new ApplicationRole
{
Id = "4",
Name = "ProductManager",
NormalizedName = "PRODUCTMANAGER",
Description = "Manage products and inventory",
CreatedAt = seedDate,
IsActive = true
}
);
}
}

View File

@@ -0,0 +1,30 @@
using Imprink.Domain.Entities.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Imprink.Infrastructure.Configuration.Users;
public class ApplicationUserConfiguration : IEntityTypeConfiguration<ApplicationUser>
{
public void Configure(EntityTypeBuilder<ApplicationUser> builder)
{
builder.Property(u => u.FirstName)
.HasMaxLength(100);
builder.Property(u => u.LastName)
.HasMaxLength(100);
builder.Property(u => u.ProfileImageUrl)
.HasMaxLength(500);
builder.Property(u => u.CreatedAt)
.IsRequired()
.HasDefaultValueSql("GETUTCDATE()");
builder.Property(u => u.LastLoginAt)
.HasDefaultValueSql("GETUTCDATE()");
builder.Property(u => u.IsActive)
.HasDefaultValue(true);
}
}

View File

@@ -0,0 +1,42 @@
using Imprink.Domain.Entities.Orders;
using Imprink.Domain.Entities.Product;
using Imprink.Domain.Entities.Users;
using Imprink.Infrastructure.Configuration.Orders;
using Imprink.Infrastructure.Configuration.Products;
using Imprink.Infrastructure.Configuration.Users;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Database;
public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: IdentityDbContext<ApplicationUser, ApplicationRole, string>(options)
{
public DbSet<Product> Products { get; set; }
public DbSet<ProductVariant> ProductVariants { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }
public DbSet<OrderAddress> OrderAddresses { get; set; }
public DbSet<Address> Addresses { get; set; }
public DbSet<OrderStatus> OrderStatuses { get; set; }
public DbSet<ShippingStatus> ShippingStatuses { get; set; }
public DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new ApplicationUserConfiguration());
modelBuilder.ApplyConfiguration(new ApplicationRoleConfiguration());
modelBuilder.ApplyConfiguration(new ProductConfiguration());
modelBuilder.ApplyConfiguration(new ProductVariantConfiguration());
modelBuilder.ApplyConfiguration(new OrderConfiguration());
modelBuilder.ApplyConfiguration(new OrderItemConfiguration());
modelBuilder.ApplyConfiguration(new OrderAddressConfiguration());
modelBuilder.ApplyConfiguration(new AddressConfiguration());
modelBuilder.ApplyConfiguration(new OrderStatusConfiguration());
modelBuilder.ApplyConfiguration(new ShippingStatusConfiguration());
modelBuilder.ApplyConfiguration(new CategoryConfiguration());
}
}

View File

@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Imprink.Application\Imprink.Application.csproj" />
<ProjectReference Include="..\Imprink.Domain\Imprink.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\" />
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,824 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace Printbase.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class InitialSetup : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
Description = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, defaultValueSql: "GETUTCDATE()"),
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
FirstName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
LastName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
DateOfBirth = table.Column<DateTime>(type: "datetime2", nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, defaultValueSql: "GETUTCDATE()"),
LastLoginAt = table.Column<DateTime>(type: "datetime2", nullable: false, defaultValueSql: "GETUTCDATE()"),
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
ProfileImageUrl = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
UserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(type: "bit", nullable: false),
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: true),
SecurityStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumber = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumberConfirmed = table.Column<bool>(type: "bit", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "bit", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
LockoutEnabled = table.Column<bool>(type: "bit", nullable: false),
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Categories",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false, defaultValueSql: "NEWID()"),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
Description = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false),
ImageUrl = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
SortOrder = table.Column<int>(type: "int", nullable: false, defaultValue: 0),
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
ParentCategoryId = table.Column<Guid>(type: "uniqueidentifier", 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_Categories", x => x.Id);
table.ForeignKey(
name: "FK_Categories_Categories_ParentCategoryId",
column: x => x.ParentCategoryId,
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "OrderStatuses",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false),
Name = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_OrderStatuses", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ShippingStatuses",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false),
Name = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ShippingStatuses", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Addresses",
columns: table => new
{
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),
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),
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)
},
constraints: table =>
{
table.PrimaryKey("PK_Addresses", x => x.Id);
table.ForeignKey(
name: "FK_Addresses_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false),
ProviderKey = table.Column<string>(type: "nvarchar(450)", nullable: false),
ProviderDisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(450)", nullable: false),
Value = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false, defaultValueSql: "NEWID()"),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
Description = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
BasePrice = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
IsCustomizable = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
ImageUrl = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
CategoryId = table.Column<Guid>(type: "uniqueidentifier", 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_Products", x => x.Id);
table.ForeignKey(
name: "FK_Products_Categories_CategoryId",
column: x => x.CategoryId,
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
});
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_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
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);
});
migrationBuilder.CreateTable(
name: "ProductVariants",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false, defaultValueSql: "NEWID()"),
ProductId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Size = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
Color = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
ImageUrl = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
Sku = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
StockQuantity = table.Column<int>(type: "int", nullable: false, defaultValue: 0),
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: 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_ProductVariants", x => x.Id);
table.ForeignKey(
name: "FK_ProductVariants_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
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),
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)
},
constraints: table =>
{
table.PrimaryKey("PK_OrderAddresses", x => x.Id);
table.ForeignKey(
name: "FK_OrderAddresses_Orders_OrderId",
column: x => x.OrderId,
principalTable: "Orders",
principalColumn: "Id",
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: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "CreatedAt", "Description", "IsActive", "Name", "NormalizedName" },
values: new object[,]
{
{ "1", null, new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "Full system access", true, "Administrator", "ADMINISTRATOR" },
{ "2", null, new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "Standard customer access", true, "Customer", "CUSTOMER" },
{ "3", null, new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "Manage orders and fulfillment", true, "OrderManager", "ORDERMANAGER" },
{ "4", null, new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "Manage products and inventory", true, "ProductManager", "PRODUCTMANAGER" }
});
migrationBuilder.InsertData(
table: "Categories",
columns: new[] { "Id", "CreatedAt", "CreatedBy", "Description", "ImageUrl", "IsActive", "ModifiedAt", "ModifiedBy", "Name", "ParentCategoryId", "SortOrder" },
values: new object[,]
{
{ new Guid("11111111-1111-1111-1111-111111111111"), new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "system@printbase.com", "Textile and fabric-based products", null, true, new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "system@printbase.com", "Textile", null, 1 },
{ new Guid("22222222-2222-2222-2222-222222222222"), new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "system@printbase.com", "Products for hard surface printing", null, true, new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "system@printbase.com", "Hard Surfaces", null, 2 },
{ new Guid("33333333-3333-3333-3333-333333333333"), new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "system@printbase.com", "Paper-based printing products", null, true, new DateTime(2025, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "system@printbase.com", "Paper", null, 3 }
});
migrationBuilder.InsertData(
table: "OrderStatuses",
columns: new[] { "Id", "Name" },
values: new object[,]
{
{ 0, "Pending" },
{ 1, "Processing" },
{ 2, "Completed" },
{ 3, "Cancelled" }
});
migrationBuilder.InsertData(
table: "ShippingStatuses",
columns: new[] { "Id", "Name" },
values: new object[,]
{
{ 0, "Prepping" },
{ 1, "Packaging" },
{ 2, "Shipped" },
{ 3, "Delivered" }
});
migrationBuilder.CreateIndex(
name: "IX_Address_CreatedAt",
table: "Addresses",
column: "CreatedAt");
migrationBuilder.CreateIndex(
name: "IX_Address_CreatedBy",
table: "Addresses",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_Address_ModifiedAt",
table: "Addresses",
column: "ModifiedAt");
migrationBuilder.CreateIndex(
name: "IX_Address_User_Default",
table: "Addresses",
columns: new[] { "UserId", "IsDefault" });
migrationBuilder.CreateIndex(
name: "IX_Address_User_Type",
table: "Addresses",
columns: new[] { "UserId", "AddressType" });
migrationBuilder.CreateIndex(
name: "IX_Address_UserId",
table: "Addresses",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "IX_ApplicationRole_IsActive",
table: "AspNetRoles",
column: "IsActive");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true,
filter: "[NormalizedName] IS NOT NULL");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true,
filter: "[NormalizedUserName] IS NOT NULL");
migrationBuilder.CreateIndex(
name: "IX_Category_Active_SortOrder",
table: "Categories",
columns: new[] { "IsActive", "SortOrder" });
migrationBuilder.CreateIndex(
name: "IX_Category_CreatedAt",
table: "Categories",
column: "CreatedAt");
migrationBuilder.CreateIndex(
name: "IX_Category_CreatedBy",
table: "Categories",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_Category_IsActive",
table: "Categories",
column: "IsActive");
migrationBuilder.CreateIndex(
name: "IX_Category_ModifiedAt",
table: "Categories",
column: "ModifiedAt");
migrationBuilder.CreateIndex(
name: "IX_Category_Name",
table: "Categories",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_Category_Parent_SortOrder",
table: "Categories",
columns: new[] { "ParentCategoryId", "SortOrder" });
migrationBuilder.CreateIndex(
name: "IX_Category_ParentCategoryId",
table: "Categories",
column: "ParentCategoryId");
migrationBuilder.CreateIndex(
name: "IX_OrderAddress_CreatedAt",
table: "OrderAddresses",
column: "CreatedAt");
migrationBuilder.CreateIndex(
name: "IX_OrderAddress_CreatedBy",
table: "OrderAddresses",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_OrderAddress_ModifiedAt",
table: "OrderAddresses",
column: "ModifiedAt");
migrationBuilder.CreateIndex(
name: "IX_OrderAddress_OrderId",
table: "OrderAddresses",
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",
column: "CreatedAt");
migrationBuilder.CreateIndex(
name: "IX_Order_CreatedBy",
table: "Orders",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_Order_ModifiedAt",
table: "Orders",
column: "ModifiedAt");
migrationBuilder.CreateIndex(
name: "IX_Order_OrderDate",
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_ShippingStatusId",
table: "Orders",
column: "ShippingStatusId");
migrationBuilder.CreateIndex(
name: "IX_Order_User_Date",
table: "Orders",
columns: new[] { "UserId", "OrderDate" });
migrationBuilder.CreateIndex(
name: "IX_Order_UserId",
table: "Orders",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_OrderStatus_Name",
table: "OrderStatuses",
column: "Name",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Product_Active_Customizable",
table: "Products",
columns: new[] { "IsActive", "IsCustomizable" });
migrationBuilder.CreateIndex(
name: "IX_Product_Category_Active",
table: "Products",
columns: new[] { "CategoryId", "IsActive" });
migrationBuilder.CreateIndex(
name: "IX_Product_CategoryId",
table: "Products",
column: "CategoryId");
migrationBuilder.CreateIndex(
name: "IX_Product_CreatedAt",
table: "Products",
column: "CreatedAt");
migrationBuilder.CreateIndex(
name: "IX_Product_CreatedBy",
table: "Products",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_Product_IsActive",
table: "Products",
column: "IsActive");
migrationBuilder.CreateIndex(
name: "IX_Product_IsCustomizable",
table: "Products",
column: "IsCustomizable");
migrationBuilder.CreateIndex(
name: "IX_Product_ModifiedAt",
table: "Products",
column: "ModifiedAt");
migrationBuilder.CreateIndex(
name: "IX_Product_Name",
table: "Products",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_ProductVariant_CreatedAt",
table: "ProductVariants",
column: "CreatedAt");
migrationBuilder.CreateIndex(
name: "IX_ProductVariant_CreatedBy",
table: "ProductVariants",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_ProductVariant_IsActive",
table: "ProductVariants",
column: "IsActive");
migrationBuilder.CreateIndex(
name: "IX_ProductVariant_ModifiedAt",
table: "ProductVariants",
column: "ModifiedAt");
migrationBuilder.CreateIndex(
name: "IX_ProductVariant_Product_Size_Color",
table: "ProductVariants",
columns: new[] { "ProductId", "Size", "Color" },
unique: true,
filter: "[Color] IS NOT NULL");
migrationBuilder.CreateIndex(
name: "IX_ProductVariant_ProductId",
table: "ProductVariants",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_ProductVariant_SKU",
table: "ProductVariants",
column: "Sku",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ShippingStatus_Name",
table: "ShippingStatuses",
column: "Name",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Addresses");
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "OrderAddresses");
migrationBuilder.DropTable(
name: "OrderItems");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "Orders");
migrationBuilder.DropTable(
name: "ProductVariants");
migrationBuilder.DropTable(
name: "AspNetUsers");
migrationBuilder.DropTable(
name: "OrderStatuses");
migrationBuilder.DropTable(
name: "ShippingStatuses");
migrationBuilder.DropTable(
name: "Products");
migrationBuilder.DropTable(
name: "Categories");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,111 @@
using Imprink.Domain.Entities.Product;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Repositories;
public class CategoryRepository(ApplicationDbContext context) : ICategoryRepository
{
public async Task<Category?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.Categories
.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
}
public async Task<Category?> GetByIdWithSubCategoriesAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.Categories
.Include(c => c.SubCategories.Where(sc => sc.IsActive))
.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
}
public async Task<Category?> GetByIdWithProductsAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.Categories
.Include(c => c.Products.Where(p => p.IsActive))
.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
}
public async Task<IEnumerable<Category>> GetAllAsync(CancellationToken cancellationToken = default)
{
return await context.Categories
.OrderBy(c => c.SortOrder)
.ThenBy(c => c.Name)
.ToListAsync(cancellationToken);
}
public async Task<IEnumerable<Category>> GetActiveAsync(CancellationToken cancellationToken = default)
{
return await context.Categories
.Where(c => c.IsActive)
.OrderBy(c => c.SortOrder)
.ThenBy(c => c.Name)
.ToListAsync(cancellationToken);
}
public async Task<IEnumerable<Category>> GetRootCategoriesAsync(CancellationToken cancellationToken = default)
{
return await context.Categories
.Where(c => c.ParentCategoryId == null && c.IsActive)
.OrderBy(c => c.SortOrder)
.ThenBy(c => c.Name)
.ToListAsync(cancellationToken);
}
public async Task<IEnumerable<Category>> GetSubCategoriesAsync(Guid parentCategoryId, CancellationToken cancellationToken = default)
{
return await context.Categories
.Where(c => c.ParentCategoryId == parentCategoryId && c.IsActive)
.OrderBy(c => c.SortOrder)
.ThenBy(c => c.Name)
.ToListAsync(cancellationToken);
}
public async Task<Category> AddAsync(Category category, CancellationToken cancellationToken = default)
{
category.Id = Guid.NewGuid();
category.CreatedAt = DateTime.UtcNow;
category.ModifiedAt = DateTime.UtcNow;
context.Categories.Add(category);
await context.SaveChangesAsync(cancellationToken);
return category;
}
public async Task<Category> UpdateAsync(Category category, CancellationToken cancellationToken = default)
{
category.ModifiedAt = DateTime.UtcNow;
context.Categories.Update(category);
await context.SaveChangesAsync(cancellationToken);
return category;
}
public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
{
var category = await GetByIdAsync(id, cancellationToken);
if (category != null)
{
context.Categories.Remove(category);
await context.SaveChangesAsync(cancellationToken);
}
}
public async Task<bool> ExistsAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.Categories
.AnyAsync(c => c.Id == id, cancellationToken);
}
public async Task<bool> HasSubCategoriesAsync(Guid categoryId, CancellationToken cancellationToken = default)
{
return await context.Categories
.AnyAsync(c => c.ParentCategoryId == categoryId, cancellationToken);
}
public async Task<bool> HasProductsAsync(Guid categoryId, CancellationToken cancellationToken = default)
{
return await context.Products
.AnyAsync(p => p.CategoryId == categoryId, cancellationToken);
}
}

View File

@@ -0,0 +1,165 @@
using Imprink.Domain.Common.Models;
using Imprink.Domain.Entities.Product;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Repositories;
public class ProductRepository(ApplicationDbContext context) : IProductRepository
{
public async Task<Product?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.Products
.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
}
public async Task<Product?> GetByIdWithVariantsAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.Products
.Include(p => p.ProductVariants.Where(pv => pv.IsActive))
.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
}
public async Task<Product?> GetByIdWithCategoryAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.Products
.Include(p => p.Category)
.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
}
public async Task<Product?> GetByIdFullAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.Products
.Include(p => p.Category)
.Include(p => p.ProductVariants.Where(pv => pv.IsActive))
.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
}
public async Task<PagedResult<Product>> GetPagedAsync(ProductFilterParameters filterParameters, CancellationToken cancellationToken = default)
{
var query = context.Products
.Include(p => p.Category)
.AsQueryable();
if (filterParameters.IsActive.HasValue)
{
query = query.Where(p => p.IsActive == filterParameters.IsActive.Value);
}
if (!string.IsNullOrEmpty(filterParameters.SearchTerm))
{
query = query.Where(p => p.Name.Contains(filterParameters.SearchTerm) ||
(p.Description != null && p.Description.Contains(filterParameters.SearchTerm)));
}
if (filterParameters.CategoryId.HasValue)
{
query = query.Where(p => p.CategoryId == filterParameters.CategoryId.Value);
}
if (filterParameters.MinPrice.HasValue)
{
query = query.Where(p => p.BasePrice >= filterParameters.MinPrice.Value);
}
if (filterParameters.MaxPrice.HasValue)
{
query = query.Where(p => p.BasePrice <= filterParameters.MaxPrice.Value);
}
if (filterParameters.IsCustomizable.HasValue)
{
query = query.Where(p => p.IsCustomizable == filterParameters.IsCustomizable.Value);
}
query = filterParameters.SortBy.ToLower() switch
{
"price" => filterParameters.SortDirection.Equals("DESC"
, StringComparison.CurrentCultureIgnoreCase)
? query.OrderByDescending(p => p.BasePrice)
: query.OrderBy(p => p.BasePrice),
"name" => filterParameters.SortDirection.Equals("DESC"
, StringComparison.CurrentCultureIgnoreCase)
? query.OrderByDescending(p => p.Name)
: query.OrderBy(p => p.Name),
_ => query.OrderBy(p => p.Name)
};
var totalCount = await query.CountAsync(cancellationToken);
var items = await query
.Skip((filterParameters.PageNumber - 1) * filterParameters.PageSize)
.Take(filterParameters.PageSize)
.ToListAsync(cancellationToken);
return new PagedResult<Product>
{
Items = items,
TotalCount = totalCount,
PageNumber = filterParameters.PageNumber,
PageSize = filterParameters.PageSize
};
}
public async Task<IEnumerable<Product>> GetByCategoryAsync(Guid categoryId, CancellationToken cancellationToken = default)
{
return await context.Products
.Include(p => p.Category)
.Where(p => p.CategoryId == categoryId && p.IsActive)
.OrderBy(p => p.Name)
.ToListAsync(cancellationToken);
}
public async Task<IEnumerable<Product>> GetCustomizableAsync(CancellationToken cancellationToken = default)
{
return await context.Products
.Include(p => p.Category)
.Where(p => p.IsCustomizable && p.IsActive)
.OrderBy(p => p.Name)
.ToListAsync(cancellationToken);
}
public async Task<Product> AddAsync(Product product, CancellationToken cancellationToken = default)
{
product.Id = Guid.NewGuid();
product.CreatedAt = DateTime.UtcNow;
product.ModifiedAt = DateTime.UtcNow;
context.Products.Add(product);
await context.SaveChangesAsync(cancellationToken);
if (product.CategoryId.HasValue)
{
await context.Entry(product)
.Reference(p => p.Category)
.LoadAsync(cancellationToken);
}
return product;
}
public async Task<Product> UpdateAsync(Product product, CancellationToken cancellationToken = default)
{
product.ModifiedAt = DateTime.UtcNow;
context.Products.Update(product);
await context.SaveChangesAsync(cancellationToken);
return product;
}
public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
{
var product = await GetByIdAsync(id, cancellationToken);
if (product != null)
{
context.Products.Remove(product);
await context.SaveChangesAsync(cancellationToken);
}
}
public async Task<bool> ExistsAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.Products
.AnyAsync(p => p.Id == id, cancellationToken);
}
}

View File

@@ -0,0 +1,118 @@
using Imprink.Domain.Entities.Product;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
namespace Imprink.Infrastructure.Repositories;
public class ProductVariantRepository(ApplicationDbContext context) : IProductVariantRepository
{
public async Task<ProductVariant?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.ProductVariants
.FirstOrDefaultAsync(pv => pv.Id == id, cancellationToken);
}
public async Task<ProductVariant?> GetByIdWithProductAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.ProductVariants
.Include(pv => pv.Product)
.ThenInclude(p => p.Category)
.FirstOrDefaultAsync(pv => pv.Id == id, cancellationToken);
}
public async Task<ProductVariant?> GetBySkuAsync(string sku, CancellationToken cancellationToken = default)
{
return await context.ProductVariants
.Include(pv => pv.Product)
.FirstOrDefaultAsync(pv => pv.Sku == sku, cancellationToken);
}
public async Task<IEnumerable<ProductVariant>> GetByProductIdAsync(Guid productId, CancellationToken cancellationToken = default)
{
return await context.ProductVariants
.Include(pv => pv.Product)
.Where(pv => pv.ProductId == productId)
.OrderBy(pv => pv.Size)
.ThenBy(pv => pv.Color)
.ToListAsync(cancellationToken);
}
public async Task<IEnumerable<ProductVariant>> GetActiveByProductIdAsync(Guid productId, CancellationToken cancellationToken = default)
{
return await context.ProductVariants
.Include(pv => pv.Product)
.Where(pv => pv.ProductId == productId && pv.IsActive)
.OrderBy(pv => pv.Size)
.ThenBy(pv => pv.Color)
.ToListAsync(cancellationToken);
}
public async Task<IEnumerable<ProductVariant>> GetInStockByProductIdAsync(Guid productId, CancellationToken cancellationToken = default)
{
return await context.ProductVariants
.Include(pv => pv.Product)
.Where(pv => pv.ProductId == productId && pv.IsActive && pv.StockQuantity > 0)
.OrderBy(pv => pv.Size)
.ThenBy(pv => pv.Color)
.ToListAsync(cancellationToken);
}
public async Task<ProductVariant> AddAsync(ProductVariant productVariant, CancellationToken cancellationToken = default)
{
productVariant.Id = Guid.NewGuid();
productVariant.CreatedAt = DateTime.UtcNow;
productVariant.ModifiedAt = DateTime.UtcNow;
context.ProductVariants.Add(productVariant);
await context.SaveChangesAsync(cancellationToken);
return productVariant;
}
public async Task<ProductVariant> UpdateAsync(ProductVariant productVariant, CancellationToken cancellationToken = default)
{
productVariant.ModifiedAt = DateTime.UtcNow;
context.ProductVariants.Update(productVariant);
await context.SaveChangesAsync(cancellationToken);
return productVariant;
}
public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
{
var productVariant = await GetByIdAsync(id, cancellationToken);
if (productVariant != null)
{
context.ProductVariants.Remove(productVariant);
await context.SaveChangesAsync(cancellationToken);
}
}
public async Task<bool> ExistsAsync(Guid id, CancellationToken cancellationToken = default)
{
return await context.ProductVariants
.AnyAsync(pv => pv.Id == id, cancellationToken);
}
public async Task<bool> SkuExistsAsync(string sku, Guid? excludeId = null, CancellationToken cancellationToken = default)
{
var query = context.ProductVariants.Where(pv => pv.Sku == sku);
if (excludeId.HasValue)
{
query = query.Where(pv => pv.Id != excludeId.Value);
}
return await query.AnyAsync(cancellationToken);
}
public async Task UpdateStockQuantityAsync(Guid id, int quantity, CancellationToken cancellationToken = default)
{
var productVariant = await GetByIdAsync(id, cancellationToken);
if (productVariant != null)
{
productVariant.StockQuantity = quantity;
productVariant.ModifiedAt = DateTime.UtcNow;
await context.SaveChangesAsync(cancellationToken);
}
}
}

View File

@@ -0,0 +1,36 @@
using Imprink.Application;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
namespace Imprink.Infrastructure;
public class UnitOfWork(
ApplicationDbContext context,
IProductRepository productRepository,
IProductVariantRepository productVariantRepository,
ICategoryRepository categoryRepository) : IUnitOfWork
{
public IProductRepository ProductRepository => productRepository;
public IProductVariantRepository ProductVariantRepository => productVariantRepository;
public ICategoryRepository CategoryRepository => categoryRepository;
public async Task SaveAsync(CancellationToken cancellationToken = default)
{
await context.SaveChangesAsync(cancellationToken);
}
public Task BeginTransactionAsync(CancellationToken cancellationToken = default)
{
return context.Database.BeginTransactionAsync(cancellationToken);
}
public async Task CommitTransactionAsync(CancellationToken cancellationToken = default)
{
await context.Database.CommitTransactionAsync(cancellationToken);
}
public async Task RollbackTransactionAsync(CancellationToken cancellationToken = default)
{
await context.Database.RollbackTransactionAsync(cancellationToken);
}
}