fix(super-admin): новая org через UI получает полный bootstrap (как Demo)
POST /api/super-admin/organizations создавал только Store + Admin role в inline-коде — у новой орги не было единиц измерения, типов цен, кастомных ролей шаблонов (Менеджер/Кладовщик/Закупщик/Бухгалтер), кассы. Юзеру приходилось бы заводить всё руками. Решение — переиспользовать DevDataSeeder.SeedTenantReferencesAsync, который уже умеет всё это идемпотентно: - 5 единиц измерения (штука/кг/л/м/упаковка по ОКЕИ) - 2 типа цен (Розничная IsSystem+IsRequired+IsRetail / Оптовая) - «Основной склад» MAIN - «Касса 1» POS-1 - 6 ролей через SeedEmployeeRolesAsync (2 системных + 4 шаблона) Helper повышен с private на public static. В контроллере убран inline Store + AdminRole, после Add(org)+SaveChanges вызывается seed, потом находим уже созданную «Администратор» роль для линковки с Employee. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
92d2eb0432
commit
59983acabd
|
|
@ -1,5 +1,5 @@
|
|||
using foodmarket.Api.Seed;
|
||||
using foodmarket.Application.Common;
|
||||
using foodmarket.Domain.Catalog;
|
||||
using foodmarket.Domain.Organizations;
|
||||
using foodmarket.Infrastructure.Identity;
|
||||
using foodmarket.Infrastructure.Persistence;
|
||||
|
|
@ -100,21 +100,16 @@ public async Task<ActionResult<CreateOrgResult>> Create([FromBody] CreateOrgRequ
|
|||
DefaultCurrencyId = input.Org.DefaultCurrencyId,
|
||||
};
|
||||
_db.Organizations.Add(org);
|
||||
// Системные референсы (Stores, Cashiers, Roles) подсеет DevDataSeeder при
|
||||
// следующем рестарте; для немедленной готовности создаём минимум руками.
|
||||
var mainStore = new Store
|
||||
{
|
||||
OrganizationId = org.Id, Name = "Основной склад", Code = "MAIN", IsMain = true,
|
||||
};
|
||||
_db.Stores.Add(mainStore);
|
||||
await _db.SaveChangesAsync(ct);
|
||||
|
||||
var adminRole = new EmployeeRole
|
||||
{
|
||||
OrganizationId = org.Id,
|
||||
Name = "Администратор", Description = "Полный доступ ко всем разделам организации",
|
||||
IsSystem = true, SortOrder = 0, Permissions = RolePermissions.All(),
|
||||
};
|
||||
_db.EmployeeRoles.Add(adminRole);
|
||||
// Полный bootstrap tenant-сущностей: единицы измерения, типы цен,
|
||||
// «Основной склад», «Касса 1», 6 ролей (2 системные + 4 кастомные шаблона).
|
||||
// Один helper и в DevDataSeeder, и здесь — гарантирует одинаковое
|
||||
// состояние новой орги независимо от пути создания.
|
||||
await DevDataSeeder.SeedTenantReferencesAsync(_db, org.Id, ct);
|
||||
|
||||
var adminRole = await _db.EmployeeRoles.IgnoreQueryFilters()
|
||||
.FirstAsync(r => r.OrganizationId == org.Id && r.IsSystem && r.Name == "Администратор", ct);
|
||||
|
||||
// AppUser админа
|
||||
var existing = await _userMgr.FindByEmailAsync(input.AdminEmail);
|
||||
|
|
|
|||
|
|
@ -117,7 +117,13 @@ private static async Task SeedAdminEmployeeAsync(AppDbContext db, Guid orgId, Gu
|
|||
await db.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
private static async Task SeedTenantReferencesAsync(AppDbContext db, Guid orgId, CancellationToken ct)
|
||||
/// <summary>Bootstrap минимально-достаточного набора tenant-сущностей для
|
||||
/// новой организации: единицы измерения (ОКЕИ), типы цен (Розничная+Оптовая),
|
||||
/// «Основной склад» MAIN, «Касса 1» POS-1, и системные роли через
|
||||
/// SeedEmployeeRolesAsync. Идемпотентно: каждый блок проверяет существующие
|
||||
/// записи. Используется и при первом старте Demo, и при создании org через
|
||||
/// SuperAdmin UI.</summary>
|
||||
public static async Task SeedTenantReferencesAsync(AppDbContext db, Guid orgId, CancellationToken ct)
|
||||
{
|
||||
var anyUnit = await db.UnitsOfMeasure.IgnoreQueryFilters().AnyAsync(u => u.OrganizationId == orgId, ct);
|
||||
if (!anyUnit)
|
||||
|
|
|
|||
Loading…
Reference in a new issue