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:
parent
047cf841f2
commit
cb66684134
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
78
src/food-market.api/Seed/SystemReferenceSeeder.cs
Normal file
78
src/food-market.api/Seed/SystemReferenceSeeder.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/food-market.domain/Catalog/Counterparty.cs
Normal file
25
src/food-market.domain/Catalog/Counterparty.cs
Normal 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;
|
||||||
|
}
|
||||||
11
src/food-market.domain/Catalog/Country.cs
Normal file
11
src/food-market.domain/Catalog/Country.cs
Normal 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; }
|
||||||
|
}
|
||||||
13
src/food-market.domain/Catalog/Currency.cs
Normal file
13
src/food-market.domain/Catalog/Currency.cs
Normal 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;
|
||||||
|
}
|
||||||
31
src/food-market.domain/Catalog/Enums.cs
Normal file
31
src/food-market.domain/Catalog/Enums.cs
Normal 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,
|
||||||
|
}
|
||||||
13
src/food-market.domain/Catalog/PriceType.cs
Normal file
13
src/food-market.domain/Catalog/PriceType.cs
Normal 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;
|
||||||
|
}
|
||||||
44
src/food-market.domain/Catalog/Product.cs
Normal file
44
src/food-market.domain/Catalog/Product.cs
Normal 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; } = [];
|
||||||
|
}
|
||||||
12
src/food-market.domain/Catalog/ProductBarcode.cs
Normal file
12
src/food-market.domain/Catalog/ProductBarcode.cs
Normal 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; }
|
||||||
|
}
|
||||||
15
src/food-market.domain/Catalog/ProductGroup.cs
Normal file
15
src/food-market.domain/Catalog/ProductGroup.cs
Normal 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;
|
||||||
|
}
|
||||||
12
src/food-market.domain/Catalog/ProductImage.cs
Normal file
12
src/food-market.domain/Catalog/ProductImage.cs
Normal 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; }
|
||||||
|
}
|
||||||
17
src/food-market.domain/Catalog/ProductPrice.cs
Normal file
17
src/food-market.domain/Catalog/ProductPrice.cs
Normal 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; }
|
||||||
|
}
|
||||||
17
src/food-market.domain/Catalog/RetailPoint.cs
Normal file
17
src/food-market.domain/Catalog/RetailPoint.cs
Normal 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;
|
||||||
|
}
|
||||||
16
src/food-market.domain/Catalog/Store.cs
Normal file
16
src/food-market.domain/Catalog/Store.cs
Normal 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;
|
||||||
|
}
|
||||||
14
src/food-market.domain/Catalog/UnitOfMeasure.cs
Normal file
14
src/food-market.domain/Catalog/UnitOfMeasure.cs
Normal 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;
|
||||||
|
}
|
||||||
13
src/food-market.domain/Catalog/VatRate.cs
Normal file
13
src/food-market.domain/Catalog/VatRate.cs
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
1389
src/food-market.infrastructure/Persistence/Migrations/20260421141151_Phase1Catalog.Designer.cs
generated
Normal file
1389
src/food-market.infrastructure/Persistence/Migrations/20260421141151_Phase1Catalog.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue