26b937afba
Исключённые поставщики хранятся отдельно от «Оценки поставщиков», чтобы отчёт СТ, INCORE и потоки их не видели. Колонки — копия офферов своей формы плюс СТ и причина; файл КП — числом, лукап на библиотеку не читается через REST. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
102 lines
8.5 KiB
Markdown
102 lines
8.5 KiB
Markdown
# 0001. Исключение поставщика из сравнения вместо удаления
|
||
|
||
- Статус: Принято
|
||
- Дата: 2026-10-27
|
||
- Задача: #1
|
||
- Источник: Асиля Сарниязова, Teams, 2026-10-23, п.4: «Я случайно удалила из таблицы
|
||
поставщика — и не смогла вернуть его назад, хоть и есть КП»
|
||
|
||
## Контекст
|
||
|
||
На Шаге 3 (таблица сравнения) крестик на колонке поставщика удаляет его безвозвратно во всех
|
||
трёх формах — СТ, ОИД, КПС:
|
||
|
||
- колонка убирается из состояния формы, введённые цены стираются;
|
||
- при сохранении все офферы по позициям СТ уходят в корзину и заново пишутся только
|
||
оставшиеся поставщики (обычная правка записи на списках офферов заблокирована ресивером);
|
||
- вернуть поставщика можно только повторной загрузкой КП на Шаге 2, цены, введённые руками,
|
||
теряются.
|
||
|
||
Офферы читает не только портал:
|
||
|
||
- СТ — бэкенд `api.tnsu.kz/Report/CT` (PDF/Excel-отчёт, уходит в пакет INCORE);
|
||
- ОИД — поток ИИ-комментария читает «Оценку поставщиков ОИД» сам;
|
||
- потоки уведомлений — внешние, читают ли они офферы, по коду не определить.
|
||
|
||
В закупочных системах (SAP Ariba, Coupa, Procore и др.) участника не удаляют, а отклоняют
|
||
с причиной, и это остаётся в истории.
|
||
|
||
## Варианты
|
||
|
||
**А. Флаг `isExcluded` на каждом оффере** в списках «Оценка поставщиков», «… ОИД», «… КПС».
|
||
|
||
- Плюс: одна колонка, исключённые лежат рядом с обычными.
|
||
- Минус: все сторонние читатели начнут видеть исключённых, пока каждый не добавит фильтр —
|
||
бэкенд отчёта СТ (иначе исключённый попадёт в PDF и INCORE), поток ИИ ОИД, возможно потоки
|
||
уведомлений. Выкатка строго по порядку: колонка → бэкенд и потоки → портал.
|
||
|
||
**Б. JSON-снимок в шапке СТ** — колонка `excludedSuppliers` (Note) в «Сравнительной таблице»
|
||
каждой формы.
|
||
|
||
- Плюс: «Оценка поставщиков» не меняется, сторонние читатели ничего не замечают.
|
||
- Минус: размер. Строка оффера — 200–300 символов; 3 поставщика × 100 позиций = 60–90 тыс.
|
||
символов, с комплектами — вдвое больше. Предел многострочной колонки SP — около 64 тыс.
|
||
Сохранение упадёт на обычных объёмах.
|
||
|
||
**В. Отдельный список «Исключённые предложения»** под каждую форму («…», «… ОИД», «… КПС»):
|
||
те же колонки, что в «Оценке поставщиков», плюс лукап на СТ.
|
||
|
||
- Плюс: в «Оценке поставщиков» только активные поставщики — бэкенд, отчёт, INCORE и потоки
|
||
не дорабатываются, порядок выкатки не важен.
|
||
- Плюс: одна строка на оффер, объём не ограничен.
|
||
- Минус: три новых списка, перенос строк между списками при исключении и возврате.
|
||
|
||
## Решение
|
||
|
||
Вариант **В**.
|
||
|
||
- Крестик исключает поставщика: колонка скрывается, итоги, минимумы, рекомендация и ИИ его
|
||
не учитывают. Если исключили выбранного — выбор сбрасывается.
|
||
- При исключении **причина обязательна**. Она хранится вместе с исключёнными строками.
|
||
- Под таблицей у автора — плашка «Исключены из сравнения: поставщик — причина [Вернуть]».
|
||
- **Согласующий исключённых пока не видит.** Данные для него грузятся так же, но показ
|
||
выключен константой — включить можно без доработки хранения.
|
||
- **Повторная загрузка КП** исключённого поставщика на Шаге 2 его не возвращает: он остаётся
|
||
исключённым до «Вернуть».
|
||
- При сохранении цены исключённых пишутся в «Исключённые предложения», в «Оценку
|
||
поставщиков» не попадают. При открытии СТ исключённые читаются по id СТ.
|
||
- «Вернуть» → при сохранении строки переезжают обратно в «Оценку поставщиков».
|
||
- Поставщик без цен — одна строка-маркер без позиции, чтобы колонка не терялась.
|
||
- Позицию сняли на Шаге 1 — её строки в «Исключённых» тоже уходят в корзину.
|
||
- Запись офферов и исключённых — в общем модуле для трёх форм, чтобы позже перенести
|
||
сохранение на бэкенд без переделки компонентов.
|
||
|
||
## Устройство списков
|
||
|
||
Манифесты — `provisioning/manifests/{ct,oid,kps}.provisioning.json`.
|
||
|
||
- Колонки — копия «Оценки поставщиков» своей формы (чтобы «Вернуть» восстановило оффер
|
||
целиком) плюс `CT` (найти исключённых при открытии СТ) и `reason` (причина).
|
||
- Ссылки на обычные списки — Lookup, файл КП — сразу `offerFileId: Number`: лукап на
|
||
библиотеку документов не читается через REST.
|
||
- Номер строки комплекта — в `Title`, как в «Оценке поставщиков» (`поставщик-позиция-N`):
|
||
один формат во всех списках, разбор переиспользуется (`parseOfferItemIndex`).
|
||
- Причина повторяется в каждой строке поставщика — осознанная денормализация. Отдельный
|
||
список «Исключённые поставщики» дал бы 6 списков вместо 3 ради короткого текста.
|
||
- Поставщик без цен — строка без `position`, чтобы колонка не терялась.
|
||
|
||
## Последствия
|
||
|
||
- Три новых списка на `/sites/sed` — описать в `provisioning/manifests/{ct,oid,kps}`,
|
||
создать через `Provision-Lists.ps1` (сначала тест, потом бой).
|
||
- Доработка Шага 3 и загрузки СТ во всех трёх формах, Jest-тесты на исключение и возврат.
|
||
- Попутно закрываются баги удаления: в ОИД выбор остаётся на удалённом поставщике, в КПС
|
||
удалённый поставщик без КП возвращается после перезагрузки.
|
||
|
||
## Ответы на открытые вопросы (2026-10-27, Тимур)
|
||
|
||
1. Согласующий исключённых — заложить, но пока не показывать.
|
||
2. Повторная загрузка КП не возвращает исключённого поставщика.
|
||
3. Причина исключения — обязательная.
|
||
4. Списки создаются через `Provision-Lists.ps1` по манифестам (сначала тест, потом бой).
|