Commit Graph

58 Commits

Author SHA1 Message Date
Тимур Городецкий c1e8792174 feat(ct): поставщик-победитель записывается в шапку СТ на шаге 3
По «Сохранить и продолжить» выбранный поставщик пишется в лукап winSupplier: на шаге 4 меняется
только статус, а поставщик мог быть как обычной колонкой, так и добавленным на шаге 3.
2026-10-20 14:28:45 +05:00
Тимур Городецкий 5192311fff fix: заголовок меню портала «Снабжение» вместо заглушки «Договора»
Название вынесено в SIDEBAR_BRAND — реестр и база контрагентов берут его из одного места.
2026-10-20 14:26:21 +05:00
Тимур Городецкий 4079bddc71 fix(approval): повторная отправка на согласование не падает на удалении старого маршрута
recycle() слал POST без Content-Type с пустым odata-version — SPFx (jsonRequest) сам бросал
«requires the OData-Version header to be 3.0 or 4.0» до запроса. writeRoute общий: повторная
отправка после доработки/перезапуска ломалась во всех трёх формах; в КПС тот же recycle.
2026-10-02 12:29:23 +05:00
Тимур Городецкий 045a4f655b refactor(ct): режим формы — по автору и статусу СТ, а не по регистру ctid/ctId
Раньше ?ctid= (ссылки потока, реестр не-черновиков) включал режим согласующего любому, кто открыл,
и режим залипал в сессии: автор СТ «На доработке» по ссылке из письма не мог править.
Теперь getCtAccess: автор правит в draft…formed и «На доработке»; согласующий и автор на
согласовании/после — просмотр с ценами на шаге 3; посторонний — просмотр без цен.
ctid/ctId равнозначны, approvalSent/isNotificationLink убраны.
2026-10-02 12:07:59 +05:00
Тимур Городецкий 2f00a2dcc9 fix(ct): «Сохранить и продолжить» на шаге 3 пишет «Не получены КП» и доп. информацию в SP
Вызовы syncNoOfferSuppliers/replaceCriteria из п.3 и п.4 претензий не попали в коммиты
f5853b1 и 2b102b8 (вошли только импорты): без них согласующий и PDF не видели поставщиков
без КП и доп. поля, если шаг 2 прошли крошками.
2026-10-02 12:07:44 +05:00
Тимур Городецкий 34da9ae165 fix(ct): поток уведомлений получает строку того, кто вернул на доработку или отклонил
Без активного согласующего форма отправляла потоку последнюю строку маршрута — при возврате на
доработку это мог быть следующий согласующий в статусе «Ждёт очереди», и в письме инициатору
нельзя было указать, кто вернул и с каким комментарием. Теперь (pickRowToNotify): активный
согласующий → его строка; иначе строка «На доработке» или «Отклонено»; иначе последняя.
2026-10-02 11:13:07 +05:00
Тимур Городецкий 90759fc4bc fix(ct): подсветка минимальной суммы в каждой позиции, а не только в общем итоге
Минимум по позиции считался, но подсветку получали только строка «Итого по позиции» у комплекта
и строки доп. расходов — обычная ячейка «Сумма, ₸» не подсвечивалась никогда, и зелёный был виден
только в общем итоге. Итог комплекта к тому же пересчитывался отдельно (без override цены в ₸ и
кол-ва позиции по умолчанию) и сравнивался строгим ===, поэтому минимум терялся на копейках.
Теперь суммы «поставщик × позиция» — один источник (sumPositionTotals), сравнение с допуском
(isMinPositionTotal), минимальная сумма зелёная в каждой позиции.
2026-10-01 17:44:07 +05:00
Тимур Городецкий 2593021a70 feat(ct): кнопка «На доработку» у согласующего; после доработки маршрут идёт с начала
Вернуть СТ инициатору на исправление было нельзя — только «Отклонить». Теперь у согласующего
(шаг 4 и шаг 3 по ссылке из Teams) есть «На доработку» с обязательным комментарием. Строка и СТ
получают статус «На доработке», СТ сразу открыта инициатору для правки, на шаге 4 — плашка, кто
вернул и что исправить. Повторная отправка переписывает маршрут целиком — согласование с начала.
«Отклонить» с перезапуском работает как раньше.

Решение rework добавлено в общий ApproverService/DecisionPanel, но кнопка включена только в СТ ОМТС
(allowRework); в ОИД/КПС статус недостижим. В SP в Choice status «Сравнительная таблица» и
«Согласование СТ» добавлено «На доработке» (и «Отклонено» в статус СТ, которое форма уже писала).
Уведомление инициатору при доработке — в потоке Power Automate (вне репо).
2026-10-01 17:26:29 +05:00
Тимур Городецкий 04cd6fe690 fix(ct): файл КП сохраняется с префиксом СТ — одноимённый КП другой СТ не перезаписывает его
КП загружались в корень библиотеки под исходным именем с перезаписью: «КП.pdf» одной СТ затирал
«КП.pdf» другой, и согласующий первой СТ открывал чужое КП. Теперь файл хранится как
«<id СТ>_<имя>» (buildKpStorageName); это имя идёт в поиск уже загруженного файла, поток, список
«Загруженные КП» и ссылку на файл. Повторная загрузка того же файла в эту же СТ по-прежнему
распознаётся.
2026-10-01 17:03:14 +05:00
Тимур Городецкий 56247fc98f feat(ct): ссылки на КП на шаге 3 для согласующих; участие в цепочке — по почте
Согласующий по ссылке из Teams попадает сразу на шаг 3, а ссылки на КП были только на шаге 2 —
открыть КП при согласовании было негде. Теперь под таблицей сравнения блок «Коммерческие
предложения» (поставщик → файл). Показывается тем же, кому видны цены: в КП тоже цены.
Участие в цепочке согласования сверялось по ФИО — при другом написании согласующему скрывались
цены (и теперь КП); сверяем по почте без учёта регистра, ФИО — запасной вариант.
2026-10-01 16:56:40 +05:00
Тимур Городецкий fa6d88f2ab feat(ct): подсветка несоответствия ед. изм. поставщика и заявки на шаге 3
Несоответствие единиц было видно только по незаметной «*» и только при включённом тумблере.
Теперь «Ед. изм.» поставщика подсвечивается жёлтым, если отличается от заявки (подсказка «В
заявке: кг, у поставщика: т»). С включённым тумблером единица, кол-во и цены подсвечиваются
голубым, если пересчитаны в ед. заявки, и красным, если пересчитать нельзя (шт ↔ кг). Статус —
чистая функция getUnitStatus; у тумблера — легенда цветов вместо «*».
2026-10-01 16:45:10 +05:00
Тимур Городецкий fa92cb4e2e fix(ct): «Перевести в ед. изм. заявки» понимает синонимы и штучные единицы
Тумблер знал только массу, длину, площадь и объём в одном написании. «Штука» в заявке и «шт.»
в КП считались разными незнакомыми единицами — тумблер помечал их «пересчёт невозможен», и
казалось, что он ничего не делает. Теперь единица приводится к канонической через словарь
синонимов (шт/Штука/ед, кг/Килограмм, л/Литр, кв.м./м², пог.м/м.п. и т.д.), добавлены штучные
единицы (компл, упак, пара, рулон, лист, мешок — между собой не пересчитываются). Заодно
«кв.м.» с точкой на конце снова распознаётся: точку срезали после поиска синонимов.
2026-10-01 16:38:51 +05:00
Тимур Городецкий 64a377276c fix(ct): своя строка «Дополнительной информации» по ссылке — без HTML-обёртки SharePoint
Значение своей строки хранится в comment, а это в «Критерии» ОМТС многострочное поле с
форматированием: SharePoint отдаёт его как <div class="ExternalClass…">да</div>, и по ссылке
показывалась разметка. При загрузке теперь остаётся чистый текст (plainTextFromSp).
2026-10-01 16:29:13 +05:00
Тимур Городецкий 2b102b8772 fix(ct): «Дополнительная информация» сохраняется в SP; списки для оплаты, поставки, сертификатов
Ручные правки условий и свои строки («Добавить условие») жили только в браузере: saveCriteria
не вызывался, и согласующий, PDF и автор в новой вкладке видели лишь то, что распознал ИИ.
Теперь по «Сохранить» шага 3 «Критерии» этой СТ заменяются текущими (replaceCriteria), а при
открытии грузятся по СТ, а не по поставщику из всех СТ (loadCriteriaForCt). Свои строки
хранятся в новой колонке criteriaLabel, значение — в comment, как в ОИД.

По просьбе заказчика: «Условия оплаты» — готовые варианты (частые формулировки из SP) или свой
вариант; «Сертификаты» — Да/Нет; «Условия поставки» можно сменить и после заполнения ИИ
(раньше заполненное показывалось текстом без выбора).
2026-10-01 16:18:02 +05:00
Тимур Городецкий f5853b1ad5 feat(ct): поставщики без КП — списком под таблицей сравнения, в т.ч. у согласующего
Поставщиков без КП убрали из колонок (64973a2), но взамен нигде не показывали. Теперь на
шаге 3 под «Дополнительной информацией» — список «Поставщики, не предоставившие КП» с
комментарием. «Не получены КП» сохраняются с привязкой к СТ (колонка CT была в списке, но не
заполнялась, а дедуп шёл по названию на все СТ) и синхронизируются по «Сохранить» на шагах
2 и 3 — удалённые убираются; по ссылке согласующий видит список из SP. Комментарий больше
не теряется при возврате на шаг 2.
2026-10-01 15:34:03 +05:00
Тимур Городецкий efedfc7658 fix(ct): повторное сохранение шага 1 обновляет позиции той же СТ, а не создаёт новую
Вернулись на шаг 1 и нажали «Сохранить и продолжить» — создавалась ещё одна СТ (№10 → №11) с
теми же позициями. Предложения оставались в прежней СТ, а форма переключалась на новую,
которая по ссылке открывалась без поставщиков. Теперь, если СТ уже создана, позиции
обновляются: новые дописываются, снятые уходят в корзину вместе с их предложениями, проект
в шапке меняется при смене проекта (planStep1Save).

Заодно при возврате на шаг 1 прежний выбор виден и сохраняется: позиции нераскрытых
потребностей берутся из формы, выбранные считаются по id — раньше галочки не стояли,
«Только выбранные» был пуст, «Сохранить» неактивна.
2026-10-01 15:11:39 +05:00
Тимур Городецкий 6ef39f8fc9 fix(ct): по ссылке и без сессии «Наименование ТМЦ» берётся из КП, а не из заявки
При открытии СТ по ссылке (согласующий) или в новой вкладке предложения собирались из SP без
поля supplierPosition, и шаг 3 подставлял вместо названия из КП название позиции заявки.
Согласующий не видел, что поставщик предложил другую модель или аналог, а автор, сохранив
шаг 3 без сессии, записывал в SP название заявки поверх названия поставщика. Теперь название
читается из SP и переносится (сборка офферов вынесена в buildOffersFromSpRecords).
2026-10-01 14:28:32 +05:00
Тимур Городецкий 85145e0d6e feat(ct): лишний КП поставщика убирается корзиной вместо окна «заменить / добавить»
Окно на каждый второй КП поставщика при пакетной загрузке (6 файлов — 6 окон) было непонятно.
Теперь вопросов при загрузке нет: каждый КП — своя колонка. В «Загруженных КП» файлы одного
поставщика сгруппированы с пометкой «N КП — сравниваются отдельными колонками», а корзина
(и крестик у обработанного файла) убирает КП из сравнения — колонку, цены и записи этого
файла в SP, с подтверждением. Раньше корзина только прятала строку, колонка оставалась.
Так заменяют исправленный КП: загружают новый, старый убирают.

Заменяет окно из 744b603 (п.2).
2026-10-01 12:58:25 +05:00
Тимур Городецкий dc88dfe5ff feat(ct): колонки одного поставщика с несколькими КП различаются в шапке, Adata и ИИ
У поставщика с несколькими КП колонки выглядели одинаково: в шапке подписывается файл КП,
в «Дополнительной информации», ИИ-комментарии и выборе рекомендованного используется имя
«Название (файл)» — ИИ сопоставляет поставщиков по имени и путал одинаковые. Adata проверяет
компанию: кэш и результат проверки получают все её колонки, «Проверить всех» делает один
платный запрос на компанию, а не на колонку.

Этап 3 из 4 (п.2).
2026-10-01 12:39:02 +05:00
Тимур Городецкий 744b603972 feat(ct): выбор «заменить / добавить отдельно» при втором КП того же поставщика
Система не отличает исправленный КП от отдельного предложения поставщика: поставщик
определяется только по названию. Теперь, когда поток назвал поставщика, у которого в СТ уже
есть КП, обработка ждёт выбора в окне. «Заменить» — прежние колонки поставщика уходят из
сравнения, их записи в SP — в корзину (после записи нового КП, чтобы не потерять данные при
сбое). «Добавить отдельным предложением» — отдельная колонка. Закрытие окна — «добавить»:
ничего не удаляется. Несколько КП подряд — вопросы по очереди.

Этап 2 из 4 (п.2).
2026-10-01 12:22:09 +05:00
Тимур Городецкий 3e95f1470f feat(ct): несколько КП одного поставщика — отдельные колонки в таблице сравнения
Колонка таблицы сравнения теперь «поставщик + файл КП» (id `${spId}_${kpFileSpId}`), а не только
поставщик. Два КП одного поставщика (напр. в KZT и USD) раньше схлопывались в одну колонку —
оставался последний файл, второе предложение пропадало. Теперь каждый КП — своя колонка со своей
валютой; записи в SP различаются по offerFileId: дедуп и чистка повторной обработки не трогают
записи другого КП того же поставщика, восстановление по ссылке раскладывает их по колонкам.
Старые колонки без файла (данные до изменения) работают как раньше.

Этап 1 из 4: выбора «заменить / добавить отдельно» пока нет — второй КП поставщика всегда
идёт отдельной колонкой.
2026-10-01 11:52:35 +05:00
Тимур Городецкий 9490d5b83f fix(kps): повторно загруженный КП поставщика не даёт вторую колонку в таблице сравнения
Сборщики КПС строили поставщика, предложения и критерии по каждому файлу КП, поэтому тот же
КП под другим именем (или исправленный) давал в таблице вторую колонку того же поставщика
и задвоенные строки позиций. Теперь, как в СТ (5f5f0e7), из нескольких КП одного поставщика
берётся последний. Отбор вынесен в shared/offers/kpFiles и общий для СТ и КПС; дедуп офферов
при загрузке КПС переведён на общий keepLatestOfferRecords (поведение то же).

Заодно в репозиторий попадают тесты step2Persist.test.ts.
2026-10-01 11:02:45 +05:00
Тимур Городецкий 2bf50884c0 fix(oid): повторная обработка КП поставщика заменяет его прежние предложения, а не дублирует
Шаг 2 ОИД писал предложения нового КП рядом с прежними записями поставщика. Шаг 3 всегда
грузит предложения из SP, поэтому позиция выглядела «комплектом» из одинаковых строк, а
автосохранение Шага 3 закрепляло это в SP. Теперь по повторному КП прежние записи поставщика
по тем же позициям уходят в корзину — после записи новых, чтобы при сбое не потерять данные.

Дедуп при загрузке, как в СТ, в ОИД не делаем: номер строки комплекта ОИД в Title не хранит,
и такой дедуп удалил бы настоящие строки комплекта.
2026-10-01 10:59:11 +05:00
Тимур Городецкий 1899a5ab38 fix(ct): повторное «Сохранить» на шаге 3 не создаёт доп. строки и поставщиков второй раз
Доп. строки («Логистика», «Доп. расходы») и новые поставщики шага 3 создаются в SP в начале
сохранения, а их SP-id попадали в стейт только в самом конце. Если дальше падало сохранение
офферов, id терялись, и повторное «Сохранить» создавало те же строки ещё раз. Теперь id
запоминаются сразу после создания — и при успехе, и при сбое (applyCreatedIds).

Заодно в репозиторий попадают тесты расчёта сумм matrixHelpers.test.ts.
2026-10-01 10:56:36 +05:00
Тимур Городецкий d6d92ece3f fix(ct): предложения из КП пишутся в SP сразу при обработке, а не только по «Сохранить»
Предложения писались внутри цикла по позициям и только если поставщика уже определил Syntex.
Syntex отключён, поставщика теперь называет поток — узнаём его после разбора всех позиций,
поэтому при обработке КП в «Оценка поставщиков» не попадало ничего: закрыл вкладку без
«Сохранить» — и разобранные цены пропали. Теперь записи строятся после определения поставщика
(buildKpOffersToSave), а сбои потока и записи идут в консоль вместо пустого catch.
2026-10-01 10:37:54 +05:00
Тимур Городецкий 2316f8bd6d fix(ct): повторная обработка КП не оставляет в SP дубли предложений
Каждая обработка КП создаёт записи в «Оценка поставщиков», а прежние удалялись только
по «Сохранить». Исправленный КП поставщика или файл, загруженный заново, оставлял рядом
старые записи — отсюда дубли в SP (СТ №89, №4). Теперь после создания записи прежние
записи того же поставщика по той же позиции уходят в корзину; порядок «создать, потом
удалить» — чтобы при сбое не потерять предложение.
2026-09-30 16:12:46 +05:00
Тимур Городецкий 76ad9c6242 fix(ct): одна позиция не дублируется в таблице сравнения из-за повторных записей КП
Повторная обработка КП добавляет в «Оценка поставщиков» новые записи, а прежние удаляются
только по «Сохранить» — в SP копились дубли (напр. СТ №89), и шаг 3 рисовал позицию
несколькими одинаковыми под-строками. Загрузчики офферов теперь оставляют одну запись
на (поставщик, позиция, itemIndex) — последнюю по Id. Загрузка по ссылке/без сессии
заодно восстанавливает itemIndex из Title: раньше все строки комплекта шли как 0.

Дедуп вынесен в shared/offers, чтобы переиспользовать в ОИД и КПС.
2026-09-30 15:05:08 +05:00
Тимур Городецкий 5f5f0e7f81 fix(ct):пофиксил дублирование позиций в таблице а также убрал добавление поставщика безКП в таблицу 2026-09-23 16:06:26 +05:00
Тимур Городецкий 64973a2232 fix(ct): поставщики без КП с шага 2 не попадают в таблицу сравнения
Они выводились на шаге 3 колонкой с нулевыми ценами, хотя сравнивать у них
нечего. Остаются в списке шага 2 и в «Не получены КП»; ручной ввод цен
сохранён за поставщиками, добавленными на самом шаге 3.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 15:56:14 +05:00
Тимур Городецкий e4b6582e3c feat(ct): выбор валюты у уже загруженных КП на шаге 2
После возврата с шага 3 очередь загрузки пуста, и КП, по умолчанию
сохранённое в тенге, нельзя было перевести в валюту без перезагрузки файла.
Теперь валюта меняется в «Загруженные КП»: обновляются supplier.currency
и пересчёт офферов в тенге; в режиме просмотра показывается код валюты.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 15:32:43 +05:00
Тимур Городецкий a45807f669 fix(ct): список загруженных КП пропадал при открытии СТ без сессии
Лукап offer в «Оценке поставщиков» смотрит на FileLeafRef библиотеки КП,
а SP не отдаёт такой лукап через REST (500), поэтому loadKpFilesForOffers
всегда возвращал пусто и «Загруженные КП» видел только автор в своей сессии.
Id файла теперь дублируется в числовое поле offerFileId и читается оттуда.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 15:30:36 +05:00
Тимур Городецкий adf3efeb64 feat(ct): выбор поставщика из базы данных на шаге СТ 2026-09-17 16:23:56 +05:00
Тимур Городецкий 7e403a8623 feat: извлекаю текст PDF через новый API 2026-09-16 15:01:04 +05:00
Тимур Городецкий b0c08bcc83 fix: финальные оповещения (oid/kps) + ленивая загрузка потребностей 2026-09-14 16:10:39 +05:00
Тимур Городецкий 0914c76e15 fix(ct): оповещения на финале+ починил загрузку по ссылке, сузил блок решения 2026-09-14 10:52:51 +05:00
Тимур Городецкий 37bc153b98 fix: перенес матрицу согласования для всех таблиц со списков на бэк 2026-09-11 16:55:21 +05:00
Тимур Городецкий a762c755fd style(kps): зеленый стиль выбранного поставщика как в СТ 2026-09-08 11:51:48 +05:00
Тимур Городецкий 5f45b7da20 fix(oid): оповещение об отклонении/согласовании (Step3 Teams-ссылка и Step4)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-04 11:13:50 +05:00
Тимур Городецкий 04faca37ae Revert "fix(oid): передаём статус СТ в поток оповещения (не читаем из SP)"
This reverts commit a3ffaf696a.
2026-09-04 09:55:39 +05:00
Тимур Городецкий 7b4382370d chore: версия 1.0.0.2
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-04 09:49:53 +05:00
Тимур Городецкий a3ffaf696a fix(oid): передаём статус СТ в поток оповещения (не читаем из SP)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-04 09:49:26 +05:00
Тимур Городецкий 6217135629 chore: поднять версию решения до 1.0.0.1 для деплоя правок
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 17:59:43 +05:00
Тимур Городецкий abe7cdbbc3 fix(oid): рекомендованный поставщик зелёным, как в СТ
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 16:42:41 +05:00
Тимур Городецкий e50eca4fd4 fix(oid): статус СТ до оповещения — на финале согласования шлём Согласована
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 16:34:33 +05:00
Тимур Городецкий fa47373d57 fix(oid): подсказки поиска в диалоге замены не обрезаются
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 16:15:03 +05:00
Тимур Городецкий 3a8d10a7f5 fix(ct): подсказки поиска в диалоге замены не обрезаются
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 15:09:54 +05:00
Тимур Городецкий 1e367f5fcc fix(ct): фиксируем порядок согласующих (order0) в SP при отправке
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 15:03:19 +05:00
Тимур Городецкий cc44f77975 fix(ct): статус СТ до оповещения и без ложной плашки Teams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-03 14:26:38 +05:00
Тимур Городецкий 899b14b869 feat(oid): импорт работ из заявки на услуги на шаге 1
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-02 15:27:30 +05:00
Тимур Городецкий 9faff36ba2 feat(ct): карточка INCORE во вложениях СТ, кнопка только после согласования
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-02 15:27:21 +05:00