diff --git a/frontend/src/webparts/approvalAdmin/components/screens/ManageByUserScreen.tsx b/frontend/src/webparts/approvalAdmin/components/screens/ManageByUserScreen.tsx index fb61df3..2cf5b80 100644 --- a/frontend/src/webparts/approvalAdmin/components/screens/ManageByUserScreen.tsx +++ b/frontend/src/webparts/approvalAdmin/components/screens/ManageByUserScreen.tsx @@ -265,7 +265,11 @@ export const ManageByUserScreen: React.FC = ({ api, di // Фаза 2: «чистые» строки — параллельно, друг от друга не зависят. const replaced = await mapWithLimit( clean, - row => requestManage.reassignApprover(row, row.id, email, position), + row => + requestManage.reassignApprover(row, row.id, email, position, { + ticketId: row.ticketId, + dataListId: row.listId + }), { onSettled: advanceProgress } ); replaced.forEach(result => { diff --git a/frontend/src/webparts/approvalAdmin/components/screens/ManageRequestsScreen.tsx b/frontend/src/webparts/approvalAdmin/components/screens/ManageRequestsScreen.tsx index 0300a92..4c9fda1 100644 --- a/frontend/src/webparts/approvalAdmin/components/screens/ManageRequestsScreen.tsx +++ b/frontend/src/webparts/approvalAdmin/components/screens/ManageRequestsScreen.tsx @@ -433,7 +433,10 @@ export const ManageRequestsScreen: React.FC = ({ api // SharePoint, и параллельные update по одному элементу списка могут // затереть друг друга (последний выигрывает). return requestManage - .reassignApprover(matrix, rowId, email, position) + .reassignApprover(matrix, rowId, email, position, { + ticketId: matrix.request.id, + dataListId: matrix.request.listId + }) .then(() => requestManage.updateRowSla(matrix, rowId, slaHours, askOverdueReason)) .then(() => { const found = findEmployeeByEmail(employees.items, email); @@ -507,7 +510,7 @@ export const ManageRequestsScreen: React.FC = ({ api setMatrix({ ...matrix, rows: [...matrix.rows, ghostRow] }); requestManage - .addRow(matrix, matrix.request.id, phase, order, initialStatus, email, position, false) + .addRow(matrix, matrix.request.id, phase, order, initialStatus, email, position, false, matrix.request.listId) .then(() => reloadMatrix(true)) .catch((e: Error) => { setMatrix(previous); diff --git a/frontend/src/webparts/approvalAdmin/services/requestManageService.ts b/frontend/src/webparts/approvalAdmin/services/requestManageService.ts index 28f4cd7..cb8cb05 100644 --- a/frontend/src/webparts/approvalAdmin/services/requestManageService.ts +++ b/frontend/src/webparts/approvalAdmin/services/requestManageService.ts @@ -87,13 +87,32 @@ export class RequestManageService { }); } + /** + * Права на заявку новому человеку в маршруте выдаёт бэкенд портала по вебхуку + * на изменение элемента СПИСКА ДАННЫХ. Правка одного лишь списка согласования + * вебхук не вызывает — новый человек видел бы «Элемент не найден». Поэтому + * после смены/добавления человека пишем в заявку её текущий RequestStatus как + * есть: значение то же, но у элемента появляется новая версия и приходит + * вебхук (то же делает request-portal, ApproverService.touchRequest). + * + * dataListId — серверный относительный url списка данных (партиции), где лежит + * заявка (ManagedRequestSummary.listId / UserApprovalRow.listId). + */ + private async touchRequest(siteUrl: string, dataListId: string, ticketId: number): Promise { + const item = this.clientFor(siteUrl).web.getList(dataListId).items.getById(ticketId); + const current = (await item.select('RequestStatus')()) as { RequestStatus?: string }; + await item.update({ RequestStatus: current.RequestStatus || '' }); + } + /** Переназначить согласующего/исполнителя строки. Вызывающая сторона обязана - * проверить isEditableRowStatus(row.status) — сервис это не перепроверяет. */ + * проверить isEditableRowStatus(row.status) — сервис это не перепроверяет. + * request — заявка строки: по ней «трогается» элемент списка данных, см. touchRequest. */ public async reassignApprover( matrix: Pick, rowId: number, email: string, - position: string + position: string, + request: { ticketId: number; dataListId: string } ): Promise { const sp = this.clientFor(matrix.siteUrl); const approverId = await this.resolveUserId(sp, email); @@ -101,6 +120,7 @@ export class RequestManageService { Title: position, [`${FIELDS.approver}Id`]: approverId }); + await this.touchRequest(matrix.siteUrl, request.dataListId, request.ticketId); } /** @@ -148,7 +168,8 @@ export class RequestManageService { status: string, email: string, position: string, - allowReassign: boolean + allowReassign: boolean, + dataListId: string ): Promise { const sp = this.clientFor(matrix.siteUrl); const approverId = await this.resolveUserId(sp, email); @@ -161,6 +182,7 @@ export class RequestManageService { AllowReassignToOtherApprovers: allowReassign, [FIELDS.phase]: phase }); + await this.touchRequest(matrix.siteUrl, dataListId, ticketId); } /**