BUG-027: Декомпозиция
Минимальный фикс на фронте erp-admin/web. Бэк не трогаем — он работает по спеке.
Код
Admin Franchise (erp-admin/web)
-
web/src/pages/payroll/PayrollPage.tsx:208-224— переписатьhandleExportCsv:items.length === 0→showToast("Нет ведомостей для экспорта", "error"); return;items.length > 1→showToast("В выборке N ведомостей. Сузьте фильтр до одной ТТ", "error"); return;items.length === 1→exportPayrollCsv(items[0].id)→ download blob →payroll-${period}.csv
-
web/src/pages/payroll/PayrollPage.tsx:348-352— на кнопке«Экспорт CSV»добавитьdisabled={items.length === 0 || actionLoading === "export"} -
pnpm --filter @erp/admin-web exec tsc --noEmit— пройти typecheck
Backend / BFF / shared
Не требуется. Спека GET /payroll/{id}/export корректна, реализация работает.
Спеки
Не требуются. Поведение покрыто существующим контрактом.
Тест
- Положительный: 1 ведомость в выборке → клик → скачивается CSV с UTF-8 BOM и русскими заголовками
- Отрицательный 1: пустая выборка → кнопка
disabled, клика нет - Отрицательный 2: >1 ведомость → toast, файл не скачивается
- Regression: остальные кнопки PayrollPage (calculate / confirm / mark-paid) — не задеваем
Деплой
erp-admin (admin-bff + admin-frontend контейнеры в erp-front namespace). Один сервис.