feat: история согласования — маршрут пересохраняется патчем
При доработке и повторной отправке writeRoute раньше удалял все строки маршрута и создавал заново — кто вернул или отклонил заявку и с каким комментарием, терялось. Теперь маршрут пересохраняется патчем (planRoutePatch + ApprovalListService.patchSteps): строки, что остаются в маршруте, обновляются на месте, и их прошлые решения лежат в истории версий; недостающие шаги создаются, выпавшие и строки делегатов уходят в корзину. Всё одним пакетом. Проверено пилотами на увольнении и рабочем месте (обе фазы, уход в корзину). Аварийный откат для всех форм — ROUTE_PATCH_ENABLED = false. Из версий строк маршрута и заявки собирается лента «История согласования» (shared/approval/history): отправки, решения с комментариями и временем на шаге, делегирование, замена исполнителя, у кого заявка сейчас. Свёрнутый раздел в карточке и в форме доработки всех форм, грузится только при раскрытии. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,15 @@ import { IMatrixRow } from './models/IMatrixRow';
|
||||
import { ApprovalStatus, IResolveFieldValue } from './models/IApprovalRouteApi';
|
||||
import { APPROVAL_PHASE, REQUEST_STATUS, isSubmittedStatus } from './models/statuses';
|
||||
|
||||
/**
|
||||
* Выключатель пересохранения маршрута патчем — ДЛЯ ВСЕХ форм сразу (см.
|
||||
* writeRoute). Проверено пилотами на «Заявлении на увольнение» и «Организации
|
||||
* рабочего места» 2026-09-29: обновление строк на месте, обе фазы, уход
|
||||
* выпавших шагов в корзину. false — аварийный откат к прежнему «удалить всё и
|
||||
* создать заново» (история прошлых отправок снова перестанет сохраняться).
|
||||
*/
|
||||
const ROUTE_PATCH_ENABLED = true;
|
||||
|
||||
// Планируемый маршрут для НОВОЙ заявки: resolve по email инициатора → строки матрицы.
|
||||
// status выбирает фазу: 'Approval' (согласующие, по умолчанию) или 'Execution'
|
||||
// (исполнители). Имена подтягиваются по executorEmail (бэкенд отдаёт email + должность).
|
||||
@@ -72,6 +81,12 @@ export async function writeApprovers(
|
||||
// очереди. Первого исполнителя переключит на «На исполнении»
|
||||
// approval.activateNextQueued, когда фаза согласования будет пройдена целиком
|
||||
// (см. approverDecision.service.ts/decide).
|
||||
//
|
||||
// Пересохранение — ПАТЧЕМ (ApprovalListService.patchSteps, см. ROUTE_PATCH_ENABLED):
|
||||
// строки, что остаются в маршруте, обновляются на месте, и их прошлые решения
|
||||
// (кто вернул/отклонил и с каким комментарием) сохраняются в истории версий —
|
||||
// из неё строится «История согласования». Раньше маршрут удалялся и создавался
|
||||
// заново, и история прошлых отправок терялась.
|
||||
export async function writeRoute(
|
||||
approval: ApprovalListService,
|
||||
requestId: number,
|
||||
@@ -79,8 +94,6 @@ export async function writeRoute(
|
||||
executors: IApproverToWrite[],
|
||||
status: string
|
||||
): Promise<void> {
|
||||
await approval.deleteForRequest(requestId);
|
||||
|
||||
// При ОТПРАВКЕ все шаги пишем «Ждёт очереди», затем активируем первый —
|
||||
// так активен ровно текущий шаг, остальные ждут. В черновике — статус заявки
|
||||
// (Черновик), без активации.
|
||||
@@ -102,14 +115,26 @@ export async function writeRoute(
|
||||
0
|
||||
);
|
||||
|
||||
await approval.createSteps(requestId, approvers, rowStatus, APPROVAL_PHASE.approval, 1);
|
||||
await approval.createSteps(
|
||||
requestId,
|
||||
executors,
|
||||
rowStatus,
|
||||
APPROVAL_PHASE.execution,
|
||||
lastApprovalStep + 1
|
||||
);
|
||||
if (ROUTE_PATCH_ENABLED) {
|
||||
await approval.patchSteps(
|
||||
requestId,
|
||||
[
|
||||
{ approvers, phase: APPROVAL_PHASE.approval, orderStart: 1 },
|
||||
{ approvers: executors, phase: APPROVAL_PHASE.execution, orderStart: lastApprovalStep + 1 },
|
||||
],
|
||||
rowStatus
|
||||
);
|
||||
} else {
|
||||
await approval.deleteForRequest(requestId);
|
||||
await approval.createSteps(requestId, approvers, rowStatus, APPROVAL_PHASE.approval, 1);
|
||||
await approval.createSteps(
|
||||
requestId,
|
||||
executors,
|
||||
rowStatus,
|
||||
APPROVAL_PHASE.execution,
|
||||
lastApprovalStep + 1
|
||||
);
|
||||
}
|
||||
|
||||
if (submitted) {
|
||||
await approval.activateNextQueued(requestId);
|
||||
|
||||
Reference in New Issue
Block a user