feat: перестановка ждущих шагов маршрута в поданных заявках на подбор и приём

Алтынай Бултурукова (право canEditRoute) просила менять порядок участников
уже поданной заявки. Стрелки у шагов согласования и исполнения: меняются
местами только соседние шаги одной фазы, оба «Ждут очереди» — активный и
пройденные шаги не трогаются, поэтому никто не теряет заявку и оповещать
некого. Строки перечитываются перед записью, StepOrder пишется одним батчем.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Тимур Городецкий
2026-10-08 12:39:10 +05:00
parent 962d8f9c5c
commit cfe97dc67e
11 changed files with 357 additions and 23 deletions
@@ -8,6 +8,7 @@ import { REQUEST_STATUS, APPROVAL_PHASE } from './models/statuses';
import { IApprovalRow } from './models/IApprovalRow';
import { ISiteUser } from './models/ISiteUser';
import { emitRequestsChanged } from '../requestEvents';
import { planQueuedStepMove, StepMoveDirection } from './queuedStepMove';
// approve/return/reject — согласующий; execute — исполнитель отметил «Выполнено».
export type ApproverDecision = 'approve' | 'return' | 'reject' | 'execute';
@@ -141,6 +142,29 @@ export class ApproverService {
emitRequestsChanged();
}
/**
* Поменять местами ещё не начатый шаг маршрута с соседним ждущим шагом той же
* фазы (согласование или исполнение) — право см. routeEditRights.ts, правило
* см. queuedStepMove.ts.
*
* Строки перечитываются с сервера прямо перед записью: пока на экране открыт
* маршрут, кто-то мог уже согласовать, и сосед стал активным, — тогда
* перестановка отменяется, а не ломает очередь.
*
* Участники не меняются, поэтому заявку не «трогаем» (см. touchRequest): права
* на элемент данных пересчитывать незачем, оповещать тоже некого — активный
* шаг остаётся прежним.
*/
public async moveQueuedStep(requestId: number, rowId: number, direction: StepMoveDirection): Promise<void> {
const rows = await this.approval.getForRequest(requestId);
const changes = planQueuedStepMove(rows, rowId, direction);
if (!changes) {
throw new Error('Маршрут уже изменился (шаг взят в работу или решён) — обновите заявку.');
}
await this.approval.setStepOrders(changes);
emitRequestsChanged();
}
/**
* Шаг фазы «Исполнение», который ещё можно заменить или удалить: ждёт очереди
* или уже активен («На исполнении»). Выполненный шаг — решение человека, его