From a8ea8c6cc267d886a37f7fda0759c6416f50b618 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Fri, 6 Nov 2026 17:40:34 +0400 Subject: [PATCH] =?UTF-8?q?[1916]=20=D0=98=D0=BC=D0=BF=D0=BE=D1=80=D1=82?= =?UTF-8?q?=20=D0=95=D0=A6=D0=9F:=20=D1=81=D0=B2=D0=BE=D0=B4=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B8=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B8,=20=D0=BF=D1=80=D0=B5=D0=B4=D1=83=D0=BF?= =?UTF-8?q?=D1=80=D0=B5=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20?= =?UTF-8?q?=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ревью PR #217, раунд 2: - после записи (без «Пробного прогона») показывается та же сводка с заголовком «Импорт завершён» и одной кнопкой «Закрыть»; список справочника обновляется сразу; - «ГК/ЮЛ пропущено» → «без изменений»: это GK_EXISTS/LE_EXISTS, не ошибки; - таблица «Ошибки и предупреждения»: кроме шести кодов пропуска — предупреждения RF_CREATED и UNKNOWN_FLAG (§13.2) с тегом уровня; - тесты issueLines. Co-Authored-By: Claude Opus 5.5 --- .../ImportCompanyGroupsModal.tsx | 49 ++++++++++++------- .../ImportSummary.tsx | 38 +++++++++----- .../ImportCompanyGroupsModal/consts.ts | 8 ++- .../ImportCompanyGroupsModal/utils.test.ts | 42 ++++++++++++++++ .../ImportCompanyGroupsModal/utils.ts | 18 +++++-- 5 files changed, 122 insertions(+), 33 deletions(-) create mode 100644 web/src/widgets/CatalogueCompanyGroup/ImportCompanyGroupsModal/utils.test.ts diff --git a/web/src/widgets/CatalogueCompanyGroup/ImportCompanyGroupsModal/ImportCompanyGroupsModal.tsx b/web/src/widgets/CatalogueCompanyGroup/ImportCompanyGroupsModal/ImportCompanyGroupsModal.tsx index 0e3ff9e..51a2f81 100644 --- a/web/src/widgets/CatalogueCompanyGroup/ImportCompanyGroupsModal/ImportCompanyGroupsModal.tsx +++ b/web/src/widgets/CatalogueCompanyGroup/ImportCompanyGroupsModal/ImportCompanyGroupsModal.tsx @@ -21,14 +21,28 @@ type FormValues = { dry_run: boolean; }; +/** Отчёт последнего запуска; dryRun — был ли это пробный прогон (от него зависят заголовок, текст и кнопки сводки). */ +type ImportResult = { + report: ImportReportOut; + dryRun: boolean; +}; + const ON_EXISTING_OPTIONS: { value: OnExisting; label: string }[] = [ { value: 'skip', label: 'Пропустить существующие' }, { value: 'update', label: 'Обновить существующие' }, ]; +function modalTitle(result: ImportResult | null): string { + if (!result) { + return 'Импорт групп компаний из файла'; + } + return result.dryRun ? 'Сводка импорта' : 'Импорт завершён'; +} + /** - * Импорт выгрузки ЕЦП CRM. Пробный прогон заменяет форму сводкой: из неё — закрытие окна или возврат к форме - * («К загрузке файла», файл и значения формы сохраняются); после записи — уведомление и закрытие окна. + * Импорт выгрузки ЕЦП CRM. Ответ заменяет форму сводкой (отчёт §13.3). После пробного прогона из сводки — закрытие окна + * или возврат к форме («К загрузке файла», файл и значения формы сохраняются); после записи — только закрытие, + * список справочника обновляется сразу. */ export const ImportCompanyGroupsModal: React.FC = ({ open, onCancel, onImported }) => { const [form] = Form.useForm(); @@ -36,7 +50,7 @@ export const ImportCompanyGroupsModal: React.FC = ({ open, onCancel, onIm const [fileList, setFileList] = useState([]); const [loading, setLoading] = useState(false); - const [dryRunReport, setDryRunReport] = useState(null); + const [result, setResult] = useState(null); const handleOk = async () => { const file = fileList[0]?.originFileObj; @@ -47,13 +61,10 @@ export const ImportCompanyGroupsModal: React.FC = ({ open, onCancel, onIm setLoading(true); try { const report = await importDirectory(file, values.dry_run, values.on_existing); - if (values.dry_run) { - setDryRunReport(report); - return; + setResult({ report, dryRun: values.dry_run }); + if (!values.dry_run) { + onImported(); } - notification.success({ description: 'Импорт завершён' }); - onImported(); - onCancel(); } catch (e) { notification.error({ description: e instanceof ApiError ? e.message : 'Не удалось выполнить импорт' }); } finally { @@ -69,7 +80,7 @@ export const ImportCompanyGroupsModal: React.FC = ({ open, onCancel, onIm return ( = ({ open, onCancel, onIm cancelText='Отмена' cancelButtonProps={{ disabled: loading }} footer={ - dryRunReport ? ( -
- + result ? ( +
+ {result.dryRun && ( + + )} @@ -92,13 +105,13 @@ export const ImportCompanyGroupsModal: React.FC = ({ open, onCancel, onIm confirmLoading={loading} closable={!loading} destroyOnHidden - width={dryRunReport ? 880 : 720}> + width={result ? 880 : 720}>
+ style={{ display: result ? 'none' : undefined }}>