using foodmarket.Domain.Catalog; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace foodmarket.Infrastructure.Persistence.Configurations; internal static class CatalogConfigurations { public static void ConfigureCatalog(this ModelBuilder b) { b.Entity(ConfigureCountry); b.Entity(ConfigureCurrency); b.Entity(ConfigureUnit); b.Entity(ConfigureCounterparty); b.Entity(ConfigureStore); b.Entity(ConfigureRetailPoint); b.Entity(ConfigureProductGroup); b.Entity(ConfigurePriceType); b.Entity(ConfigureProduct); b.Entity(ConfigureProductPrice); b.Entity(ConfigureBarcode); b.Entity(ConfigureImage); } private static void ConfigureCountry(EntityTypeBuilder b) { b.ToTable("countries"); b.Property(x => x.Code).HasMaxLength(2).IsRequired(); b.Property(x => x.Name).HasMaxLength(100).IsRequired(); b.HasIndex(x => x.Code).IsUnique(); } private static void ConfigureCurrency(EntityTypeBuilder b) { b.ToTable("currencies"); b.Property(x => x.Code).HasMaxLength(3).IsRequired(); b.Property(x => x.Name).HasMaxLength(100).IsRequired(); b.Property(x => x.Symbol).HasMaxLength(5).IsRequired(); b.HasIndex(x => x.Code).IsUnique(); } private static void ConfigureUnit(EntityTypeBuilder b) { b.ToTable("units_of_measure"); b.Property(x => x.Code).HasMaxLength(10).IsRequired(); b.Property(x => x.Name).HasMaxLength(100).IsRequired(); b.Property(x => x.Description).HasMaxLength(500); b.HasIndex(x => new { x.OrganizationId, x.Code }).IsUnique(); } private static void ConfigureCounterparty(EntityTypeBuilder b) { b.ToTable("counterparties"); b.Property(x => x.Name).HasMaxLength(255).IsRequired(); b.Property(x => x.LegalName).HasMaxLength(500); b.Property(x => x.Bin).HasMaxLength(20); b.Property(x => x.Iin).HasMaxLength(20); b.Property(x => x.TaxNumber).HasMaxLength(20); b.Property(x => x.Phone).HasMaxLength(50); b.Property(x => x.Email).HasMaxLength(255); b.Property(x => x.BankName).HasMaxLength(255); b.Property(x => x.BankAccount).HasMaxLength(50); b.Property(x => x.Bik).HasMaxLength(20); b.Property(x => x.ContactPerson).HasMaxLength(255); b.HasOne(x => x.Country).WithMany().HasForeignKey(x => x.CountryId).OnDelete(DeleteBehavior.Restrict); b.HasIndex(x => new { x.OrganizationId, x.Name }); b.HasIndex(x => new { x.OrganizationId, x.Bin }); } private static void ConfigureStore(EntityTypeBuilder b) { b.ToTable("stores"); b.Property(x => x.Name).HasMaxLength(200).IsRequired(); b.Property(x => x.Code).HasMaxLength(50); b.Property(x => x.Phone).HasMaxLength(50); b.Property(x => x.ManagerName).HasMaxLength(200); b.HasIndex(x => new { x.OrganizationId, x.Name }); } private static void ConfigureRetailPoint(EntityTypeBuilder b) { b.ToTable("retail_points"); b.Property(x => x.Name).HasMaxLength(200).IsRequired(); b.Property(x => x.Code).HasMaxLength(50); b.Property(x => x.Phone).HasMaxLength(50); b.Property(x => x.FiscalSerial).HasMaxLength(50); b.Property(x => x.FiscalRegNumber).HasMaxLength(50); b.HasOne(x => x.Store).WithMany().HasForeignKey(x => x.StoreId).OnDelete(DeleteBehavior.Restrict); b.HasIndex(x => new { x.OrganizationId, x.Name }); } private static void ConfigureProductGroup(EntityTypeBuilder b) { b.ToTable("product_groups"); b.Property(x => x.Name).HasMaxLength(200).IsRequired(); b.Property(x => x.Path).HasMaxLength(1000); b.HasOne(x => x.Parent) .WithMany(x => x.Children) .HasForeignKey(x => x.ParentId) .OnDelete(DeleteBehavior.Restrict); b.HasIndex(x => new { x.OrganizationId, x.ParentId }); b.HasIndex(x => new { x.OrganizationId, x.Path }); } private static void ConfigurePriceType(EntityTypeBuilder b) { b.ToTable("price_types"); b.Property(x => x.Name).HasMaxLength(100).IsRequired(); b.HasIndex(x => new { x.OrganizationId, x.Name }).IsUnique(); } private static void ConfigureProduct(EntityTypeBuilder b) { b.ToTable("products"); b.Property(x => x.Name).HasMaxLength(500).IsRequired(); b.Property(x => x.Article).HasMaxLength(500); b.Property(x => x.MinStock).HasPrecision(18, 4); b.Property(x => x.MaxStock).HasPrecision(18, 4); b.Property(x => x.PurchasePrice).HasPrecision(18, 4); b.Property(x => x.ImageUrl).HasMaxLength(1000); b.HasOne(x => x.UnitOfMeasure).WithMany().HasForeignKey(x => x.UnitOfMeasureId).OnDelete(DeleteBehavior.Restrict); b.HasOne(x => x.ProductGroup).WithMany().HasForeignKey(x => x.ProductGroupId).OnDelete(DeleteBehavior.Restrict); b.HasOne(x => x.DefaultSupplier).WithMany().HasForeignKey(x => x.DefaultSupplierId).OnDelete(DeleteBehavior.Restrict); b.HasOne(x => x.CountryOfOrigin).WithMany().HasForeignKey(x => x.CountryOfOriginId).OnDelete(DeleteBehavior.Restrict); b.HasOne(x => x.PurchaseCurrency).WithMany().HasForeignKey(x => x.PurchaseCurrencyId).OnDelete(DeleteBehavior.Restrict); b.HasIndex(x => new { x.OrganizationId, x.Name }); b.HasIndex(x => new { x.OrganizationId, x.Article }); b.HasIndex(x => new { x.OrganizationId, x.ProductGroupId }); b.HasIndex(x => new { x.OrganizationId, x.IsActive }); } private static void ConfigureProductPrice(EntityTypeBuilder b) { b.ToTable("product_prices"); b.Property(x => x.Amount).HasPrecision(18, 4); b.HasOne(x => x.Product).WithMany(p => p.Prices).HasForeignKey(x => x.ProductId).OnDelete(DeleteBehavior.Cascade); b.HasOne(x => x.PriceType).WithMany().HasForeignKey(x => x.PriceTypeId).OnDelete(DeleteBehavior.Restrict); b.HasOne(x => x.Currency).WithMany().HasForeignKey(x => x.CurrencyId).OnDelete(DeleteBehavior.Restrict); b.HasIndex(x => new { x.ProductId, x.PriceTypeId }).IsUnique(); } private static void ConfigureBarcode(EntityTypeBuilder b) { b.ToTable("product_barcodes"); // Up to 500 to accommodate GS1 DataMatrix / crypto-tail tracking codes (Честный ЗНАК etc.) b.Property(x => x.Code).HasMaxLength(500).IsRequired(); b.HasOne(x => x.Product).WithMany(p => p.Barcodes).HasForeignKey(x => x.ProductId).OnDelete(DeleteBehavior.Cascade); b.HasIndex(x => new { x.OrganizationId, x.Code }).IsUnique(); } private static void ConfigureImage(EntityTypeBuilder b) { b.ToTable("product_images"); b.Property(x => x.Url).HasMaxLength(1000).IsRequired(); b.HasOne(x => x.Product).WithMany(p => p.Images).HasForeignKey(x => x.ProductId).OnDelete(DeleteBehavior.Cascade); b.HasIndex(x => x.ProductId); } }