food-market/src/food-market.api/Seed/SystemReferenceSeeder.cs
nurdotnet cb66684134 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>
2026-04-21 19:16:10 +05:00

79 lines
3.1 KiB
C#

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);
}
}
}
}