phase1a: catalog domain (countries, currencies, vat, units, counterparties, stores, retail points, products)

Domain (foodmarket.Domain.Catalog):
- Global references: Country (ISO-2), Currency (ISO-3 + symbol + minor unit)
- Tenant references: VatRate (Percent + IncludedInPrice + IsDefault), UnitOfMeasure (ОКЕИ code + DecimalPlaces)
- Counterparty: kind (Supplier/Customer/Both), type (Legal/Individual), BIN/IIN/TaxNumber, bank details
- Store + RetailPoint with fiscal placeholders
- ProductGroup: hierarchy via ParentId + denormalized Path
- PriceType (Розничная/Оптовая), Product (article, VAT, group, supplier, flags IsService/IsWeighed/IsAlcohol/IsMarked, min/max stock)
- ProductPrice (composite unique product+priceType), ProductBarcode (EAN13/EAN8/CODE128/UPC), ProductImage

Infrastructure:
- CatalogConfigurations with fluent API (indexes, precision 18/4 for money, FK with Restrict)
- 13 new DbSets on AppDbContext + builder.ConfigureCatalog()
- Migration Phase1Catalog — adds countries, currencies, vat_rates, units_of_measure, counterparties, stores, retail_points, product_groups, price_types, products, product_prices, product_barcodes, product_images

Seeders:
- SystemReferenceSeeder (always): 12 countries (KZ, RU, CN, TR, …), 5 currencies (KZT primary, RUB, USD, EUR, CNY)
- DevDataSeeder extended: for Demo Market seeds VAT (0%, 12% default+included), units (шт/кг/л/м/уп), price types (Розничная default, Оптовая), main store, POS-1

Total DB schema: 26 tables.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
nurdotnet 2026-04-21 19:16:10 +05:00
parent 047cf841f2
commit cb66684134
22 changed files with 3424 additions and 3 deletions

View file

@ -95,6 +95,7 @@
builder.Services.AddSwaggerGen(); builder.Services.AddSwaggerGen();
builder.Services.AddHostedService<OpenIddictClientSeeder>(); builder.Services.AddHostedService<OpenIddictClientSeeder>();
builder.Services.AddHostedService<SystemReferenceSeeder>();
builder.Services.AddHostedService<DevDataSeeder>(); builder.Services.AddHostedService<DevDataSeeder>();
var app = builder.Build(); var app = builder.Build();

View file

@ -1,5 +1,6 @@
using foodmarket.Infrastructure.Identity; using foodmarket.Domain.Catalog;
using foodmarket.Domain.Organizations; using foodmarket.Domain.Organizations;
using foodmarket.Infrastructure.Identity;
using foodmarket.Infrastructure.Persistence; using foodmarket.Infrastructure.Persistence;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -29,7 +30,7 @@ public async Task StartAsync(CancellationToken ct)
var userMgr = scope.ServiceProvider.GetRequiredService<UserManager<User>>(); var userMgr = scope.ServiceProvider.GetRequiredService<UserManager<User>>();
var roleMgr = scope.ServiceProvider.GetRequiredService<RoleManager<Role>>(); var roleMgr = scope.ServiceProvider.GetRequiredService<RoleManager<Role>>();
foreach (var role in new[] { SystemRoles.Admin, SystemRoles.Manager, SystemRoles.Cashier, SystemRoles.Storekeeper }) foreach (var role in new[] { SystemRoles.SuperAdmin, SystemRoles.Admin, SystemRoles.Manager, SystemRoles.Cashier, SystemRoles.Storekeeper })
{ {
if (!await roleMgr.RoleExistsAsync(role)) if (!await roleMgr.RoleExistsAsync(role))
{ {
@ -53,6 +54,8 @@ public async Task StartAsync(CancellationToken ct)
await db.SaveChangesAsync(ct); await db.SaveChangesAsync(ct);
} }
await SeedTenantReferencesAsync(db, demoOrg.Id, ct);
const string adminEmail = "admin@food-market.local"; const string adminEmail = "admin@food-market.local";
var admin = await userMgr.FindByEmailAsync(adminEmail); var admin = await userMgr.FindByEmailAsync(adminEmail);
if (admin is null) if (admin is null)
@ -73,5 +76,68 @@ public async Task StartAsync(CancellationToken ct)
} }
} }
private static async Task SeedTenantReferencesAsync(AppDbContext db, Guid orgId, CancellationToken ct)
{
var anyVat = await db.VatRates.IgnoreQueryFilters().AnyAsync(v => v.OrganizationId == orgId, ct);
if (!anyVat)
{
db.VatRates.AddRange(
new VatRate { OrganizationId = orgId, Name = "Без НДС", Percent = 0m, IsDefault = false },
new VatRate { OrganizationId = orgId, Name = "НДС 12%", Percent = 12m, IsIncludedInPrice = true, IsDefault = true }
);
}
var anyUnit = await db.UnitsOfMeasure.IgnoreQueryFilters().AnyAsync(u => u.OrganizationId == orgId, ct);
if (!anyUnit)
{
db.UnitsOfMeasure.AddRange(
new UnitOfMeasure { OrganizationId = orgId, Code = "796", Symbol = "шт", Name = "штука", DecimalPlaces = 0, IsBase = true },
new UnitOfMeasure { OrganizationId = orgId, Code = "166", Symbol = "кг", Name = "килограмм", DecimalPlaces = 3 },
new UnitOfMeasure { OrganizationId = orgId, Code = "112", Symbol = "л", Name = "литр", DecimalPlaces = 3 },
new UnitOfMeasure { OrganizationId = orgId, Code = "006", Symbol = "м", Name = "метр", DecimalPlaces = 3 },
new UnitOfMeasure { OrganizationId = orgId, Code = "625", Symbol = "уп", Name = "упаковка", DecimalPlaces = 0 }
);
}
var anyPriceType = await db.PriceTypes.IgnoreQueryFilters().AnyAsync(p => p.OrganizationId == orgId, ct);
if (!anyPriceType)
{
db.PriceTypes.AddRange(
new PriceType { OrganizationId = orgId, Name = "Розничная", IsDefault = true, IsRetail = true, SortOrder = 1 },
new PriceType { OrganizationId = orgId, Name = "Оптовая", SortOrder = 2 }
);
}
var mainStore = await db.Stores.IgnoreQueryFilters().FirstOrDefaultAsync(s => s.OrganizationId == orgId && s.IsMain, ct);
if (mainStore is null)
{
mainStore = new Store
{
OrganizationId = orgId,
Name = "Основной склад",
Code = "MAIN",
Kind = StoreKind.Warehouse,
IsMain = true,
Address = "Алматы, ул. Пример 1",
};
db.Stores.Add(mainStore);
await db.SaveChangesAsync(ct);
}
var anyRetail = await db.RetailPoints.IgnoreQueryFilters().AnyAsync(r => r.OrganizationId == orgId, ct);
if (!anyRetail)
{
db.RetailPoints.Add(new RetailPoint
{
OrganizationId = orgId,
Name = "Касса 1",
Code = "POS-1",
StoreId = mainStore.Id,
});
}
await db.SaveChangesAsync(ct);
}
public Task StopAsync(CancellationToken ct) => Task.CompletedTask; public Task StopAsync(CancellationToken ct) => Task.CompletedTask;
} }

View file

@ -0,0 +1,78 @@
using foodmarket.Domain.Catalog;
using foodmarket.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;
namespace foodmarket.Api.Seed;
// Seeds global reference data (countries, currencies). Runs in all environments.
public class SystemReferenceSeeder : IHostedService
{
private readonly IServiceProvider _services;
public SystemReferenceSeeder(IServiceProvider services)
{
_services = services;
}
public async Task StartAsync(CancellationToken ct)
{
using var scope = _services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await SeedCountriesAsync(db, ct);
await SeedCurrenciesAsync(db, ct);
await db.SaveChangesAsync(ct);
}
public Task StopAsync(CancellationToken ct) => Task.CompletedTask;
private static async Task SeedCountriesAsync(AppDbContext db, CancellationToken ct)
{
// Kazakhstan first, then common trade partners.
var wanted = new[]
{
new Country { Code = "KZ", Name = "Казахстан", SortOrder = 1 },
new Country { Code = "RU", Name = "Россия", SortOrder = 2 },
new Country { Code = "CN", Name = "Китай", SortOrder = 3 },
new Country { Code = "TR", Name = "Турция", SortOrder = 4 },
new Country { Code = "BY", Name = "Беларусь", SortOrder = 5 },
new Country { Code = "UZ", Name = "Узбекистан", SortOrder = 6 },
new Country { Code = "KG", Name = "Кыргызстан", SortOrder = 7 },
new Country { Code = "DE", Name = "Германия", SortOrder = 10 },
new Country { Code = "US", Name = "США", SortOrder = 11 },
new Country { Code = "KR", Name = "Южная Корея", SortOrder = 12 },
new Country { Code = "IT", Name = "Италия", SortOrder = 13 },
new Country { Code = "PL", Name = "Польша", SortOrder = 14 },
};
var existingCodes = await db.Countries.Select(c => c.Code).ToListAsync(ct);
foreach (var c in wanted)
{
if (!existingCodes.Contains(c.Code))
{
db.Countries.Add(c);
}
}
}
private static async Task SeedCurrenciesAsync(AppDbContext db, CancellationToken ct)
{
var wanted = new[]
{
new Currency { Code = "KZT", Name = "Тенге", Symbol = "₸", MinorUnit = 2 },
new Currency { Code = "RUB", Name = "Российский рубль", Symbol = "₽", MinorUnit = 2 },
new Currency { Code = "USD", Name = "Доллар США", Symbol = "$", MinorUnit = 2 },
new Currency { Code = "EUR", Name = "Евро", Symbol = "€", MinorUnit = 2 },
new Currency { Code = "CNY", Name = "Китайский юань", Symbol = "¥", MinorUnit = 2 },
};
var existingCodes = await db.Currencies.Select(c => c.Code).ToListAsync(ct);
foreach (var c in wanted)
{
if (!existingCodes.Contains(c.Code))
{
db.Currencies.Add(c);
}
}
}
}

View file

@ -0,0 +1,25 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
public class Counterparty : TenantEntity
{
public string Name { get; set; } = null!; // отображаемое имя
public string? LegalName { get; set; } // полное юридическое имя
public CounterpartyKind Kind { get; set; } // Supplier / Customer / Both
public CounterpartyType Type { get; set; } // Юрлицо / Физлицо
public string? Bin { get; set; } // БИН (для юрлиц РК)
public string? Iin { get; set; } // ИИН (для физлиц РК)
public string? TaxNumber { get; set; } // ИНН (для РФ) или другой идентификатор
public Guid? CountryId { get; set; }
public Country? Country { get; set; }
public string? Address { get; set; }
public string? Phone { get; set; }
public string? Email { get; set; }
public string? BankName { get; set; }
public string? BankAccount { get; set; }
public string? Bik { get; set; }
public string? ContactPerson { get; set; }
public string? Notes { get; set; }
public bool IsActive { get; set; } = true;
}

View file

@ -0,0 +1,11 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
// Global reference (not tenant-scoped). Shared across organizations.
public class Country : Entity
{
public string Code { get; set; } = null!; // ISO 3166-1 alpha-2, e.g. "KZ"
public string Name { get; set; } = null!;
public int SortOrder { get; set; }
}

View file

@ -0,0 +1,13 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
// Global reference (not tenant-scoped).
public class Currency : Entity
{
public string Code { get; set; } = null!; // ISO 4217, e.g. "KZT"
public string Name { get; set; } = null!;
public string Symbol { get; set; } = null!; // "₸"
public int MinorUnit { get; set; } = 2; // 2 = two decimal places
public bool IsActive { get; set; } = true;
}

View file

@ -0,0 +1,31 @@
namespace foodmarket.Domain.Catalog;
public enum CounterpartyKind
{
Supplier = 1,
Customer = 2,
Both = 3,
}
public enum CounterpartyType
{
LegalEntity = 1,
Individual = 2,
}
public enum StoreKind
{
Warehouse = 1,
RetailFloor = 2,
}
public enum BarcodeType
{
Ean13 = 1,
Ean8 = 2,
Code128 = 3,
Code39 = 4,
Upca = 5,
Upce = 6,
Other = 99,
}

View file

@ -0,0 +1,13 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
// Тип цены: Розничная, Оптовая, Минимальная и т.д. По одной организации может быть несколько.
public class PriceType : TenantEntity
{
public string Name { get; set; } = null!;
public bool IsDefault { get; set; } // цена по умолчанию для новых товаров
public bool IsRetail { get; set; } // используется на кассе
public int SortOrder { get; set; }
public bool IsActive { get; set; } = true;
}

View file

@ -0,0 +1,44 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
public class Product : TenantEntity
{
public string Name { get; set; } = null!;
public string? Article { get; set; } // артикул
public string? Description { get; set; }
public Guid UnitOfMeasureId { get; set; }
public UnitOfMeasure? UnitOfMeasure { get; set; }
public Guid VatRateId { get; set; }
public VatRate? VatRate { get; set; }
public Guid? ProductGroupId { get; set; }
public ProductGroup? ProductGroup { get; set; }
public Guid? DefaultSupplierId { get; set; } // основной поставщик
public Counterparty? DefaultSupplier { get; set; }
public Guid? CountryOfOriginId { get; set; } // страна происхождения
public Country? CountryOfOrigin { get; set; }
public bool IsService { get; set; } // услуга, а не физический товар
public bool IsWeighed { get; set; } // весовой (продаётся с весов)
public bool IsAlcohol { get; set; } // алкоголь (подакцизный)
public bool IsMarked { get; set; } // маркируемый (Datamatrix)
public decimal? MinStock { get; set; } // минимальный остаток (для уведомлений)
public decimal? MaxStock { get; set; } // максимальный остаток (для автозаказа)
public decimal? PurchasePrice { get; set; } // закупочная цена по умолчанию
public Guid? PurchaseCurrencyId { get; set; }
public Currency? PurchaseCurrency { get; set; }
public string? ImageUrl { get; set; } // основное изображение (остальные в ProductImage)
public bool IsActive { get; set; } = true;
public ICollection<ProductPrice> Prices { get; set; } = [];
public ICollection<ProductBarcode> Barcodes { get; set; } = [];
public ICollection<ProductImage> Images { get; set; } = [];
}

View file

@ -0,0 +1,12 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
public class ProductBarcode : TenantEntity
{
public Guid ProductId { get; set; }
public Product? Product { get; set; }
public string Code { get; set; } = null!;
public BarcodeType Type { get; set; } = BarcodeType.Ean13;
public bool IsPrimary { get; set; }
}

View file

@ -0,0 +1,15 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
// Иерархическая группа товаров (категория). Произвольная вложенность через ParentId.
public class ProductGroup : TenantEntity
{
public string Name { get; set; } = null!;
public Guid? ParentId { get; set; }
public ProductGroup? Parent { get; set; }
public ICollection<ProductGroup> Children { get; set; } = [];
public string Path { get; set; } = ""; // денормализованный путь "Электроника/Телефоны/Смартфоны" для фильтрации
public int SortOrder { get; set; }
public bool IsActive { get; set; } = true;
}

View file

@ -0,0 +1,12 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
public class ProductImage : TenantEntity
{
public Guid ProductId { get; set; }
public Product? Product { get; set; }
public string Url { get; set; } = null!;
public bool IsMain { get; set; }
public int SortOrder { get; set; }
}

View file

@ -0,0 +1,17 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
public class ProductPrice : TenantEntity
{
public Guid ProductId { get; set; }
public Product? Product { get; set; }
public Guid PriceTypeId { get; set; }
public PriceType? PriceType { get; set; }
public decimal Amount { get; set; }
public Guid CurrencyId { get; set; }
public Currency? Currency { get; set; }
}

View file

@ -0,0 +1,17 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
// Точка продаж (магазин/отдел). Привязана к складу, с которого продаёт.
public class RetailPoint : TenantEntity
{
public string Name { get; set; } = null!;
public string? Code { get; set; }
public Guid StoreId { get; set; } // склад, с которого идут продажи
public Store? Store { get; set; }
public string? Address { get; set; }
public string? Phone { get; set; }
public string? FiscalSerial { get; set; } // серийный номер ККМ (заполнится когда подключим фискализацию)
public string? FiscalRegNumber { get; set; } // регистрационный номер в ОФД
public bool IsActive { get; set; } = true;
}

View file

@ -0,0 +1,16 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
// Склад: физическое место хранения товаров. Может быть чисто склад или торговый зал.
public class Store : TenantEntity
{
public string Name { get; set; } = null!;
public string? Code { get; set; } // внутренний код склада
public StoreKind Kind { get; set; } = StoreKind.Warehouse;
public string? Address { get; set; }
public string? Phone { get; set; }
public string? ManagerName { get; set; }
public bool IsMain { get; set; } // основной склад организации
public bool IsActive { get; set; } = true;
}

View file

@ -0,0 +1,14 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
// Tenant-scoped справочник единиц измерения.
public class UnitOfMeasure : TenantEntity
{
public string Code { get; set; } = null!; // ОКЕИ код: "796" (шт), "166" (кг), "112" (л)
public string Symbol { get; set; } = null!; // "шт", "кг", "л", "м"
public string Name { get; set; } = null!; // "штука", "килограмм", "литр"
public int DecimalPlaces { get; set; } // 0 для шт, 3 для кг/л
public bool IsBase { get; set; } // базовая единица этой организации
public bool IsActive { get; set; } = true;
}

View file

@ -0,0 +1,13 @@
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Catalog;
// Tenant-scoped: разные организации могут работать в разных режимах (с НДС / упрощёнка).
public class VatRate : TenantEntity
{
public string Name { get; set; } = null!; // "НДС 12%", "Без НДС"
public decimal Percent { get; set; } // 12.00, 0.00
public bool IsIncludedInPrice { get; set; } // входит ли в цену или начисляется сверху
public bool IsDefault { get; set; }
public bool IsActive { get; set; } = true;
}

View file

@ -1,10 +1,11 @@
using foodmarket.Application.Common.Tenancy; using foodmarket.Application.Common.Tenancy;
using foodmarket.Domain.Catalog;
using foodmarket.Domain.Common; using foodmarket.Domain.Common;
using foodmarket.Infrastructure.Identity; using foodmarket.Infrastructure.Identity;
using foodmarket.Domain.Organizations; using foodmarket.Domain.Organizations;
using foodmarket.Infrastructure.Persistence.Configurations;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace foodmarket.Infrastructure.Persistence; namespace foodmarket.Infrastructure.Persistence;
@ -20,6 +21,20 @@ public AppDbContext(DbContextOptions<AppDbContext> options, ITenantContext tenan
public DbSet<Organization> Organizations => Set<Organization>(); public DbSet<Organization> Organizations => Set<Organization>();
public DbSet<Country> Countries => Set<Country>();
public DbSet<Currency> Currencies => Set<Currency>();
public DbSet<VatRate> VatRates => Set<VatRate>();
public DbSet<UnitOfMeasure> UnitsOfMeasure => Set<UnitOfMeasure>();
public DbSet<Counterparty> Counterparties => Set<Counterparty>();
public DbSet<Store> Stores => Set<Store>();
public DbSet<RetailPoint> RetailPoints => Set<RetailPoint>();
public DbSet<ProductGroup> ProductGroups => Set<ProductGroup>();
public DbSet<PriceType> PriceTypes => Set<PriceType>();
public DbSet<Product> Products => Set<Product>();
public DbSet<ProductPrice> ProductPrices => Set<ProductPrice>();
public DbSet<ProductBarcode> ProductBarcodes => Set<ProductBarcode>();
public DbSet<ProductImage> ProductImages => Set<ProductImage>();
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
@ -46,6 +61,8 @@ protected override void OnModelCreating(ModelBuilder builder)
b.HasIndex(o => o.Name); b.HasIndex(o => o.Name);
}); });
builder.ConfigureCatalog();
// Apply multi-tenant query filter to every entity that implements ITenantEntity // Apply multi-tenant query filter to every entity that implements ITenantEntity
foreach (var entityType in builder.Model.GetEntityTypes()) foreach (var entityType in builder.Model.GetEntityTypes())
{ {

View file

@ -0,0 +1,170 @@
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<Country>(ConfigureCountry);
b.Entity<Currency>(ConfigureCurrency);
b.Entity<VatRate>(ConfigureVatRate);
b.Entity<UnitOfMeasure>(ConfigureUnit);
b.Entity<Counterparty>(ConfigureCounterparty);
b.Entity<Store>(ConfigureStore);
b.Entity<RetailPoint>(ConfigureRetailPoint);
b.Entity<ProductGroup>(ConfigureProductGroup);
b.Entity<PriceType>(ConfigurePriceType);
b.Entity<Product>(ConfigureProduct);
b.Entity<ProductPrice>(ConfigureProductPrice);
b.Entity<ProductBarcode>(ConfigureBarcode);
b.Entity<ProductImage>(ConfigureImage);
}
private static void ConfigureCountry(EntityTypeBuilder<Country> 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<Currency> 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 ConfigureVatRate(EntityTypeBuilder<VatRate> b)
{
b.ToTable("vat_rates");
b.Property(x => x.Name).HasMaxLength(100).IsRequired();
b.Property(x => x.Percent).HasPrecision(5, 2);
b.HasIndex(x => new { x.OrganizationId, x.Name }).IsUnique();
}
private static void ConfigureUnit(EntityTypeBuilder<UnitOfMeasure> b)
{
b.ToTable("units_of_measure");
b.Property(x => x.Code).HasMaxLength(10).IsRequired();
b.Property(x => x.Symbol).HasMaxLength(20).IsRequired();
b.Property(x => x.Name).HasMaxLength(100).IsRequired();
b.HasIndex(x => new { x.OrganizationId, x.Code }).IsUnique();
}
private static void ConfigureCounterparty(EntityTypeBuilder<Counterparty> 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 });
b.HasIndex(x => new { x.OrganizationId, x.Kind });
}
private static void ConfigureStore(EntityTypeBuilder<Store> 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<RetailPoint> 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<ProductGroup> 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<PriceType> 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<Product> b)
{
b.ToTable("products");
b.Property(x => x.Name).HasMaxLength(500).IsRequired();
b.Property(x => x.Article).HasMaxLength(100);
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.VatRate).WithMany().HasForeignKey(x => x.VatRateId).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<ProductPrice> 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<ProductBarcode> b)
{
b.ToTable("product_barcodes");
b.Property(x => x.Code).HasMaxLength(100).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<ProductImage> 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);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,647 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace foodmarket.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class Phase1Catalog : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "countries",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Code = table.Column<string>(type: "character varying(2)", maxLength: 2, nullable: false),
Name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
SortOrder = table.Column<int>(type: "integer", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_countries", x => x.Id);
});
migrationBuilder.CreateTable(
name: "currencies",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Code = table.Column<string>(type: "character varying(3)", maxLength: 3, nullable: false),
Name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
Symbol = table.Column<string>(type: "character varying(5)", maxLength: 5, nullable: false),
MinorUnit = table.Column<int>(type: "integer", nullable: false),
IsActive = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_currencies", x => x.Id);
});
migrationBuilder.CreateTable(
name: "price_types",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
IsDefault = table.Column<bool>(type: "boolean", nullable: false),
IsRetail = table.Column<bool>(type: "boolean", nullable: false),
SortOrder = table.Column<int>(type: "integer", nullable: false),
IsActive = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_price_types", x => x.Id);
});
migrationBuilder.CreateTable(
name: "product_groups",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
ParentId = table.Column<Guid>(type: "uuid", nullable: true),
Path = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: false),
SortOrder = table.Column<int>(type: "integer", nullable: false),
IsActive = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_product_groups", x => x.Id);
table.ForeignKey(
name: "FK_product_groups_product_groups_ParentId",
column: x => x.ParentId,
principalSchema: "public",
principalTable: "product_groups",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "stores",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
Code = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
Kind = table.Column<int>(type: "integer", nullable: false),
Address = table.Column<string>(type: "text", nullable: true),
Phone = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
ManagerName = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
IsMain = table.Column<bool>(type: "boolean", nullable: false),
IsActive = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_stores", x => x.Id);
});
migrationBuilder.CreateTable(
name: "units_of_measure",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Code = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: false),
Symbol = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: false),
Name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
DecimalPlaces = table.Column<int>(type: "integer", nullable: false),
IsBase = table.Column<bool>(type: "boolean", nullable: false),
IsActive = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_units_of_measure", x => x.Id);
});
migrationBuilder.CreateTable(
name: "vat_rates",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
Percent = table.Column<decimal>(type: "numeric(5,2)", precision: 5, scale: 2, nullable: false),
IsIncludedInPrice = table.Column<bool>(type: "boolean", nullable: false),
IsDefault = table.Column<bool>(type: "boolean", nullable: false),
IsActive = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_vat_rates", x => x.Id);
});
migrationBuilder.CreateTable(
name: "counterparties",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
LegalName = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
Kind = table.Column<int>(type: "integer", nullable: false),
Type = table.Column<int>(type: "integer", nullable: false),
Bin = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: true),
Iin = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: true),
TaxNumber = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: true),
CountryId = table.Column<Guid>(type: "uuid", nullable: true),
Address = table.Column<string>(type: "text", nullable: true),
Phone = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
Email = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
BankName = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
BankAccount = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
Bik = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: true),
ContactPerson = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
Notes = table.Column<string>(type: "text", nullable: true),
IsActive = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_counterparties", x => x.Id);
table.ForeignKey(
name: "FK_counterparties_countries_CountryId",
column: x => x.CountryId,
principalSchema: "public",
principalTable: "countries",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "retail_points",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
Code = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
StoreId = table.Column<Guid>(type: "uuid", nullable: false),
Address = table.Column<string>(type: "text", nullable: true),
Phone = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
FiscalSerial = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
FiscalRegNumber = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
IsActive = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_retail_points", x => x.Id);
table.ForeignKey(
name: "FK_retail_points_stores_StoreId",
column: x => x.StoreId,
principalSchema: "public",
principalTable: "stores",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "products",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: false),
Article = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
Description = table.Column<string>(type: "text", nullable: true),
UnitOfMeasureId = table.Column<Guid>(type: "uuid", nullable: false),
VatRateId = table.Column<Guid>(type: "uuid", nullable: false),
ProductGroupId = table.Column<Guid>(type: "uuid", nullable: true),
DefaultSupplierId = table.Column<Guid>(type: "uuid", nullable: true),
CountryOfOriginId = table.Column<Guid>(type: "uuid", nullable: true),
IsService = table.Column<bool>(type: "boolean", nullable: false),
IsWeighed = table.Column<bool>(type: "boolean", nullable: false),
IsAlcohol = table.Column<bool>(type: "boolean", nullable: false),
IsMarked = table.Column<bool>(type: "boolean", nullable: false),
MinStock = table.Column<decimal>(type: "numeric(18,4)", precision: 18, scale: 4, nullable: true),
MaxStock = table.Column<decimal>(type: "numeric(18,4)", precision: 18, scale: 4, nullable: true),
PurchasePrice = table.Column<decimal>(type: "numeric(18,4)", precision: 18, scale: 4, nullable: true),
PurchaseCurrencyId = table.Column<Guid>(type: "uuid", nullable: true),
ImageUrl = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
IsActive = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_products", x => x.Id);
table.ForeignKey(
name: "FK_products_counterparties_DefaultSupplierId",
column: x => x.DefaultSupplierId,
principalSchema: "public",
principalTable: "counterparties",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_products_countries_CountryOfOriginId",
column: x => x.CountryOfOriginId,
principalSchema: "public",
principalTable: "countries",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_products_currencies_PurchaseCurrencyId",
column: x => x.PurchaseCurrencyId,
principalSchema: "public",
principalTable: "currencies",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_products_product_groups_ProductGroupId",
column: x => x.ProductGroupId,
principalSchema: "public",
principalTable: "product_groups",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_products_units_of_measure_UnitOfMeasureId",
column: x => x.UnitOfMeasureId,
principalSchema: "public",
principalTable: "units_of_measure",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_products_vat_rates_VatRateId",
column: x => x.VatRateId,
principalSchema: "public",
principalTable: "vat_rates",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "product_barcodes",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ProductId = table.Column<Guid>(type: "uuid", nullable: false),
Code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
Type = table.Column<int>(type: "integer", nullable: false),
IsPrimary = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_product_barcodes", x => x.Id);
table.ForeignKey(
name: "FK_product_barcodes_products_ProductId",
column: x => x.ProductId,
principalSchema: "public",
principalTable: "products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "product_images",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ProductId = table.Column<Guid>(type: "uuid", nullable: false),
Url = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: false),
IsMain = table.Column<bool>(type: "boolean", nullable: false),
SortOrder = table.Column<int>(type: "integer", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_product_images", x => x.Id);
table.ForeignKey(
name: "FK_product_images_products_ProductId",
column: x => x.ProductId,
principalSchema: "public",
principalTable: "products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "product_prices",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ProductId = table.Column<Guid>(type: "uuid", nullable: false),
PriceTypeId = table.Column<Guid>(type: "uuid", nullable: false),
Amount = table.Column<decimal>(type: "numeric(18,4)", precision: 18, scale: 4, nullable: false),
CurrencyId = table.Column<Guid>(type: "uuid", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_product_prices", x => x.Id);
table.ForeignKey(
name: "FK_product_prices_currencies_CurrencyId",
column: x => x.CurrencyId,
principalSchema: "public",
principalTable: "currencies",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_product_prices_price_types_PriceTypeId",
column: x => x.PriceTypeId,
principalSchema: "public",
principalTable: "price_types",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_product_prices_products_ProductId",
column: x => x.ProductId,
principalSchema: "public",
principalTable: "products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_counterparties_CountryId",
schema: "public",
table: "counterparties",
column: "CountryId");
migrationBuilder.CreateIndex(
name: "IX_counterparties_OrganizationId_Bin",
schema: "public",
table: "counterparties",
columns: new[] { "OrganizationId", "Bin" });
migrationBuilder.CreateIndex(
name: "IX_counterparties_OrganizationId_Kind",
schema: "public",
table: "counterparties",
columns: new[] { "OrganizationId", "Kind" });
migrationBuilder.CreateIndex(
name: "IX_counterparties_OrganizationId_Name",
schema: "public",
table: "counterparties",
columns: new[] { "OrganizationId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_countries_Code",
schema: "public",
table: "countries",
column: "Code",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_currencies_Code",
schema: "public",
table: "currencies",
column: "Code",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_price_types_OrganizationId_Name",
schema: "public",
table: "price_types",
columns: new[] { "OrganizationId", "Name" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_product_barcodes_OrganizationId_Code",
schema: "public",
table: "product_barcodes",
columns: new[] { "OrganizationId", "Code" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_product_barcodes_ProductId",
schema: "public",
table: "product_barcodes",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_product_groups_OrganizationId_ParentId",
schema: "public",
table: "product_groups",
columns: new[] { "OrganizationId", "ParentId" });
migrationBuilder.CreateIndex(
name: "IX_product_groups_OrganizationId_Path",
schema: "public",
table: "product_groups",
columns: new[] { "OrganizationId", "Path" });
migrationBuilder.CreateIndex(
name: "IX_product_groups_ParentId",
schema: "public",
table: "product_groups",
column: "ParentId");
migrationBuilder.CreateIndex(
name: "IX_product_images_ProductId",
schema: "public",
table: "product_images",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_product_prices_CurrencyId",
schema: "public",
table: "product_prices",
column: "CurrencyId");
migrationBuilder.CreateIndex(
name: "IX_product_prices_PriceTypeId",
schema: "public",
table: "product_prices",
column: "PriceTypeId");
migrationBuilder.CreateIndex(
name: "IX_product_prices_ProductId_PriceTypeId",
schema: "public",
table: "product_prices",
columns: new[] { "ProductId", "PriceTypeId" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_products_CountryOfOriginId",
schema: "public",
table: "products",
column: "CountryOfOriginId");
migrationBuilder.CreateIndex(
name: "IX_products_DefaultSupplierId",
schema: "public",
table: "products",
column: "DefaultSupplierId");
migrationBuilder.CreateIndex(
name: "IX_products_OrganizationId_Article",
schema: "public",
table: "products",
columns: new[] { "OrganizationId", "Article" });
migrationBuilder.CreateIndex(
name: "IX_products_OrganizationId_IsActive",
schema: "public",
table: "products",
columns: new[] { "OrganizationId", "IsActive" });
migrationBuilder.CreateIndex(
name: "IX_products_OrganizationId_Name",
schema: "public",
table: "products",
columns: new[] { "OrganizationId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_products_OrganizationId_ProductGroupId",
schema: "public",
table: "products",
columns: new[] { "OrganizationId", "ProductGroupId" });
migrationBuilder.CreateIndex(
name: "IX_products_ProductGroupId",
schema: "public",
table: "products",
column: "ProductGroupId");
migrationBuilder.CreateIndex(
name: "IX_products_PurchaseCurrencyId",
schema: "public",
table: "products",
column: "PurchaseCurrencyId");
migrationBuilder.CreateIndex(
name: "IX_products_UnitOfMeasureId",
schema: "public",
table: "products",
column: "UnitOfMeasureId");
migrationBuilder.CreateIndex(
name: "IX_products_VatRateId",
schema: "public",
table: "products",
column: "VatRateId");
migrationBuilder.CreateIndex(
name: "IX_retail_points_OrganizationId_Name",
schema: "public",
table: "retail_points",
columns: new[] { "OrganizationId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_retail_points_StoreId",
schema: "public",
table: "retail_points",
column: "StoreId");
migrationBuilder.CreateIndex(
name: "IX_stores_OrganizationId_Name",
schema: "public",
table: "stores",
columns: new[] { "OrganizationId", "Name" });
migrationBuilder.CreateIndex(
name: "IX_units_of_measure_OrganizationId_Code",
schema: "public",
table: "units_of_measure",
columns: new[] { "OrganizationId", "Code" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_vat_rates_OrganizationId_Name",
schema: "public",
table: "vat_rates",
columns: new[] { "OrganizationId", "Name" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "product_barcodes",
schema: "public");
migrationBuilder.DropTable(
name: "product_images",
schema: "public");
migrationBuilder.DropTable(
name: "product_prices",
schema: "public");
migrationBuilder.DropTable(
name: "retail_points",
schema: "public");
migrationBuilder.DropTable(
name: "price_types",
schema: "public");
migrationBuilder.DropTable(
name: "products",
schema: "public");
migrationBuilder.DropTable(
name: "stores",
schema: "public");
migrationBuilder.DropTable(
name: "counterparties",
schema: "public");
migrationBuilder.DropTable(
name: "currencies",
schema: "public");
migrationBuilder.DropTable(
name: "product_groups",
schema: "public");
migrationBuilder.DropTable(
name: "units_of_measure",
schema: "public");
migrationBuilder.DropTable(
name: "vat_rates",
schema: "public");
migrationBuilder.DropTable(
name: "countries",
schema: "public");
}
}
}

View file

@ -334,6 +334,665 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("OpenIddictTokens", "public"); b.ToTable("OpenIddictTokens", "public");
}); });
modelBuilder.Entity("foodmarket.Domain.Catalog.Counterparty", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("BankAccount")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("BankName")
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<string>("Bik")
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<string>("Bin")
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<string>("ContactPerson")
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<Guid?>("CountryId")
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<string>("Iin")
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<bool>("IsActive")
.HasColumnType("boolean");
b.Property<int>("Kind")
.HasColumnType("integer");
b.Property<string>("LegalName")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<string>("Notes")
.HasColumnType("text");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<string>("Phone")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("TaxNumber")
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CountryId");
b.HasIndex("OrganizationId", "Bin");
b.HasIndex("OrganizationId", "Kind");
b.HasIndex("OrganizationId", "Name");
b.ToTable("counterparties", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.Country", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(2)
.HasColumnType("character varying(2)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<int>("SortOrder")
.HasColumnType("integer");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("countries", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.Currency", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(3)
.HasColumnType("character varying(3)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsActive")
.HasColumnType("boolean");
b.Property<int>("MinorUnit")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("Symbol")
.IsRequired()
.HasMaxLength(5)
.HasColumnType("character varying(5)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("currencies", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.PriceType", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsActive")
.HasColumnType("boolean");
b.Property<bool>("IsDefault")
.HasColumnType("boolean");
b.Property<bool>("IsRetail")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<int>("SortOrder")
.HasColumnType("integer");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("OrganizationId", "Name")
.IsUnique();
b.ToTable("price_types", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Article")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<Guid?>("CountryOfOriginId")
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("DefaultSupplierId")
.HasColumnType("uuid");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("ImageUrl")
.HasMaxLength(1000)
.HasColumnType("character varying(1000)");
b.Property<bool>("IsActive")
.HasColumnType("boolean");
b.Property<bool>("IsAlcohol")
.HasColumnType("boolean");
b.Property<bool>("IsMarked")
.HasColumnType("boolean");
b.Property<bool>("IsService")
.HasColumnType("boolean");
b.Property<bool>("IsWeighed")
.HasColumnType("boolean");
b.Property<decimal?>("MaxStock")
.HasPrecision(18, 4)
.HasColumnType("numeric(18,4)");
b.Property<decimal?>("MinStock")
.HasPrecision(18, 4)
.HasColumnType("numeric(18,4)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<Guid?>("ProductGroupId")
.HasColumnType("uuid");
b.Property<Guid?>("PurchaseCurrencyId")
.HasColumnType("uuid");
b.Property<decimal?>("PurchasePrice")
.HasPrecision(18, 4)
.HasColumnType("numeric(18,4)");
b.Property<Guid>("UnitOfMeasureId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("VatRateId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("CountryOfOriginId");
b.HasIndex("DefaultSupplierId");
b.HasIndex("ProductGroupId");
b.HasIndex("PurchaseCurrencyId");
b.HasIndex("UnitOfMeasureId");
b.HasIndex("VatRateId");
b.HasIndex("OrganizationId", "Article");
b.HasIndex("OrganizationId", "IsActive");
b.HasIndex("OrganizationId", "Name");
b.HasIndex("OrganizationId", "ProductGroupId");
b.ToTable("products", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.ProductBarcode", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsPrimary")
.HasColumnType("boolean");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<Guid>("ProductId")
.HasColumnType("uuid");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ProductId");
b.HasIndex("OrganizationId", "Code")
.IsUnique();
b.ToTable("product_barcodes", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.ProductGroup", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsActive")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<Guid?>("ParentId")
.HasColumnType("uuid");
b.Property<string>("Path")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("character varying(1000)");
b.Property<int>("SortOrder")
.HasColumnType("integer");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ParentId");
b.HasIndex("OrganizationId", "ParentId");
b.HasIndex("OrganizationId", "Path");
b.ToTable("product_groups", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.ProductImage", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsMain")
.HasColumnType("boolean");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<Guid>("ProductId")
.HasColumnType("uuid");
b.Property<int>("SortOrder")
.HasColumnType("integer");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Url")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("character varying(1000)");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("product_images", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.ProductPrice", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 4)
.HasColumnType("numeric(18,4)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("CurrencyId")
.HasColumnType("uuid");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<Guid>("PriceTypeId")
.HasColumnType("uuid");
b.Property<Guid>("ProductId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CurrencyId");
b.HasIndex("PriceTypeId");
b.HasIndex("ProductId", "PriceTypeId")
.IsUnique();
b.ToTable("product_prices", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.RetailPoint", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("Code")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("FiscalRegNumber")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("FiscalSerial")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<bool>("IsActive")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<string>("Phone")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<Guid>("StoreId")
.HasColumnType("uuid");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("StoreId");
b.HasIndex("OrganizationId", "Name");
b.ToTable("retail_points", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.Store", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Address")
.HasColumnType("text");
b.Property<string>("Code")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsActive")
.HasColumnType("boolean");
b.Property<bool>("IsMain")
.HasColumnType("boolean");
b.Property<int>("Kind")
.HasColumnType("integer");
b.Property<string>("ManagerName")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<string>("Phone")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("OrganizationId", "Name");
b.ToTable("stores", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.UnitOfMeasure", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("character varying(10)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("DecimalPlaces")
.HasColumnType("integer");
b.Property<bool>("IsActive")
.HasColumnType("boolean");
b.Property<bool>("IsBase")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<string>("Symbol")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("OrganizationId", "Code")
.IsUnique();
b.ToTable("units_of_measure", "public");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.VatRate", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsActive")
.HasColumnType("boolean");
b.Property<bool>("IsDefault")
.HasColumnType("boolean");
b.Property<bool>("IsIncludedInPrice")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<Guid>("OrganizationId")
.HasColumnType("uuid");
b.Property<decimal>("Percent")
.HasPrecision(5, 2)
.HasColumnType("numeric(5,2)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("OrganizationId", "Name")
.IsUnique();
b.ToTable("vat_rates", "public");
});
modelBuilder.Entity("foodmarket.Domain.Organizations.Organization", b => modelBuilder.Entity("foodmarket.Domain.Organizations.Organization", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -569,6 +1228,133 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Navigation("Authorization"); b.Navigation("Authorization");
}); });
modelBuilder.Entity("foodmarket.Domain.Catalog.Counterparty", b =>
{
b.HasOne("foodmarket.Domain.Catalog.Country", "Country")
.WithMany()
.HasForeignKey("CountryId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("Country");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.Product", b =>
{
b.HasOne("foodmarket.Domain.Catalog.Country", "CountryOfOrigin")
.WithMany()
.HasForeignKey("CountryOfOriginId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("foodmarket.Domain.Catalog.Counterparty", "DefaultSupplier")
.WithMany()
.HasForeignKey("DefaultSupplierId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("foodmarket.Domain.Catalog.ProductGroup", "ProductGroup")
.WithMany()
.HasForeignKey("ProductGroupId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("foodmarket.Domain.Catalog.Currency", "PurchaseCurrency")
.WithMany()
.HasForeignKey("PurchaseCurrencyId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("foodmarket.Domain.Catalog.UnitOfMeasure", "UnitOfMeasure")
.WithMany()
.HasForeignKey("UnitOfMeasureId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("foodmarket.Domain.Catalog.VatRate", "VatRate")
.WithMany()
.HasForeignKey("VatRateId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("CountryOfOrigin");
b.Navigation("DefaultSupplier");
b.Navigation("ProductGroup");
b.Navigation("PurchaseCurrency");
b.Navigation("UnitOfMeasure");
b.Navigation("VatRate");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.ProductBarcode", b =>
{
b.HasOne("foodmarket.Domain.Catalog.Product", "Product")
.WithMany("Barcodes")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.ProductGroup", b =>
{
b.HasOne("foodmarket.Domain.Catalog.ProductGroup", "Parent")
.WithMany("Children")
.HasForeignKey("ParentId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("Parent");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.ProductImage", b =>
{
b.HasOne("foodmarket.Domain.Catalog.Product", "Product")
.WithMany("Images")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.ProductPrice", b =>
{
b.HasOne("foodmarket.Domain.Catalog.Currency", "Currency")
.WithMany()
.HasForeignKey("CurrencyId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("foodmarket.Domain.Catalog.PriceType", "PriceType")
.WithMany()
.HasForeignKey("PriceTypeId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("foodmarket.Domain.Catalog.Product", "Product")
.WithMany("Prices")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Currency");
b.Navigation("PriceType");
b.Navigation("Product");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.RetailPoint", b =>
{
b.HasOne("foodmarket.Domain.Catalog.Store", "Store")
.WithMany()
.HasForeignKey("StoreId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Store");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b =>
{ {
b.Navigation("Authorizations"); b.Navigation("Authorizations");
@ -580,6 +1366,20 @@ protected override void BuildModel(ModelBuilder modelBuilder)
{ {
b.Navigation("Tokens"); b.Navigation("Tokens");
}); });
modelBuilder.Entity("foodmarket.Domain.Catalog.Product", b =>
{
b.Navigation("Barcodes");
b.Navigation("Images");
b.Navigation("Prices");
});
modelBuilder.Entity("foodmarket.Domain.Catalog.ProductGroup", b =>
{
b.Navigation("Children");
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }