Files
request-portal/src/webparts/requestPortal/forms/ServiceRequest
Тимур Городецкий 153c966f0b feat: история согласования — маршрут пересохраняется патчем
При доработке и повторной отправке writeRoute раньше удалял все строки
маршрута и создавал заново — кто вернул или отклонил заявку и с каким
комментарием, терялось. Теперь маршрут пересохраняется патчем
(planRoutePatch + ApprovalListService.patchSteps): строки, что остаются в
маршруте, обновляются на месте, и их прошлые решения лежат в истории
версий; недостающие шаги создаются, выпавшие и строки делегатов уходят в
корзину. Всё одним пакетом. Проверено пилотами на увольнении и рабочем
месте (обе фазы, уход в корзину). Аварийный откат для всех форм —
ROUTE_PATCH_ENABLED = false.

Из версий строк маршрута и заявки собирается лента «История
согласования» (shared/approval/history): отправки, решения с
комментариями и временем на шаге, делегирование, замена исполнителя,
у кого заявка сейчас. Свёрнутый раздел в карточке и в форме доработки
всех форм, грузится только при раскрытии.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 12:42:42 +05:00
..
2026-09-01 12:48:41 +00:00
2026-09-01 12:48:41 +00:00
2026-09-01 12:48:41 +00:00

Заявка на услуги (wh-service-request)

Назначение: электронный аналог бумажной Service Requisition Form ПТО — заявка на договор/услуги/работы (субподряд, поставка, аренда) по проекту. Категория: Склад / Снабжение Списки SP: «Заявка на услуги — данные», «Заявка на услуги — согласование» RequestTypeId (внешний API маршрутов): резолвится в рантайме по pageUrl (см. docs/forms.md)

Маршрут

  • Фазы: согласование (без фазы исполнения — договор дальше ведётся вне портала)
  • Особенности: маршрут зависит от выбранного проекта (ProjectId, oid из ProjectPicker) — пока проект не выбран, resolveRoute отвечает 404, и матрица не резолвится (см. matrixReady в ServiceRequestForm.tsx, тот же приём, что в TmcTransferForm)

Особое поведение

  • Подача за другого: заявитель — PeopleField, по умолчанию текущий пользователь, можно выбрать любого — маршрут резолвится на ВЫБРАННОГО (см. handleRequesterChange).
  • Табличная часть «Приложения» (Annexes) — описание документа + номер приложения + сам файл, прикреплённый прямо к строке (fileName, хранится как встроенное вложение элемента списка — см. shared/attachments). Отдельного общего блока «Вложения» у формы нет: каждый файл привязан к своей строке.
  • Табличная часть «Смета» (Costs) — список групп (разделов работ), внутри каждой свои позиции; название группы необязательно. Сумма по позиции, по группе и общий итог считаются на лету (qty × rate, см. cost.ts), не хранятся в структуре — правка количества/цены не может их рассинхронизировать.
  • Под «Объём работ» (текстовое поле) — детализация по позициям в ТОМ ЖЕ формате, что и смета: группы/позиции/цена/сумма (WorkVolumes, см. CostGroupsEditor.tsx — общий редактор, переиспользуется и в CostsSection, и здесь). Дополняет текст итоговыми цифрами, не заменяет его.
  • Costs/WorkVolumes сериализуются в JSON-колонки (EstimateJson/WorkVolumesJson) ОБЪЕКТОМ { groups, total } — готовый итог кладётся прямо в JSON рядом с группами (см. serializeGroups/parseGroupedJson в cost.ts), а не отдельной числовой колонкой: он и так пересчитывается из groups при каждом сохранении, отдельная колонка была бы лишней схемой ради того же значения. Сама форма читает только groups — total из хранилища не доверяет, всегда считает заново (costTotal); total в JSON нужен тем, кто читает колонку напрямую (отчёты, sp-query), не поднимая форму.
  • Annexes сериализуется в AnnexesJson просто массивом (без обёртки total — там считать нечего) — тот же приём, что в TmcTransfer (ItemsJson).
  • Продолжительность работ под датами «начало/окончание» — производная величина (считается на лету), в SharePoint не пишется.
  • Фазы исполнения нет: saveServiceRequest пишет маршрут с пустым списком исполнителей.

Секции формы

HeaderSection, ScopeSection, AnnexesSection, CostsSection, RemarksSection

Точки входа

  • rptype: wh-service-request
  • Режим согласующего (просмотр): есть (ServiceRequestView)
  • «Создать на основе»: —