+
+
+ Демо-данные
+
+
+ Заполняет организацию реалистичными данными для демонстрации стейджа: 50 товаров
+ в 5 группах, 10 контрагентов, 5 приёмок, 30 продаж, 1 опт-отгрузка,
+ 1 списание, 1 перемещение, 1 инвентаризация. Идемпотентно — повторный
+ запуск не создаст дубликатов.
+
+
+ {status.isLoading && (
+ Загружаю статус…
+ )}
+
+ {s && (
+
+
Товаров: {s.products}
+
Групп: {s.groups}
+
Контрагентов: {s.counterparties}
+
Складов: {s.stores}
+
Приёмок: {s.supplies}
+
Продаж: {s.sales}
+
Опт: {s.demands}
+
Списаний: {s.losses}
+
Перемещений: {s.transfers}
+
Инвентар.: {s.inventories}
+
+ )}
+
+
+
+ {seed.isSuccess && !seeded && (
+
+ Демо-данные созданы. Перезагрузите страницу каталога чтобы увидеть.
+
+ )}
+ {seed.error && (
+ {(seed.error as Error).message}
+ )}
+
+
+ )
+}
diff --git a/tests/e2e/scenarios/stage-demo-seed.steps.ts b/tests/e2e/scenarios/stage-demo-seed.steps.ts
new file mode 100644
index 0000000..ef8dbc3
--- /dev/null
+++ b/tests/e2e/scenarios/stage-demo-seed.steps.ts
@@ -0,0 +1,130 @@
+/**
+ * Stage demo seeder: запуск + проверка наполнения + идемпотентность.
+ */
+import { login, makeClient } from '../lib/api.js'
+import type { CheckResult, Step, Report } from '../lib/report.js'
+
+type Ctx = {
+ apiOnly: boolean
+ ts: number
+ email?: string
+ password?: string
+ token?: string
+ initialSummary?: SeedSummary
+}
+interface SeedSummary {
+ alreadySeeded: boolean
+ groups: number; products: number; counterparties: number
+ supplies: number; sales: number; demands: number
+ losses: number; transfers: number; inventories: number; stores: number
+}
+interface StepCtx { ctx: Ctx; step: Step; report: Report }
+
+const TS = Date.now()
+function check(step: Step, c: CheckResult) { step.checks.push(c) }
+function asString(x: unknown): string {
+ if (x == null) return ''
+ return typeof x === 'string' ? x : JSON.stringify(x)
+}
+
+async function bootstrap(ctx: Ctx): Promise