From 5f45b7da202070f066fd1b4324ed4006bb5ffa55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B8=D0=BC=D1=83=D1=80=20=D0=93=D0=BE=D1=80=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=D1=86=D0=BA=D0=B8=D0=B9?= Date: Fri, 4 Sep 2026 11:13:50 +0500 Subject: [PATCH] =?UTF-8?q?fix(oid):=20=D0=BE=D0=BF=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=B1=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=BB=D0=BE=D0=BD=D0=B5=D0=BD=D0=B8=D0=B8/=D1=81=D0=BE?= =?UTF-8?q?=D0=B3=D0=BB=D0=B0=D1=81=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8=20?= =?UTF-8?q?(Step3=20Teams-=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B0=20=D0=B8=20?= =?UTF-8?q?Step4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Step3ComparisonTable/useStep3Approval.ts | 15 +++++++++++---- .../components/Step4Approval/useStep4Approval.ts | 7 +++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/webparts/ctFormsPortal/forms/oid/components/Step3ComparisonTable/useStep3Approval.ts b/src/webparts/ctFormsPortal/forms/oid/components/Step3ComparisonTable/useStep3Approval.ts index 9654dc9..3297fc3 100644 --- a/src/webparts/ctFormsPortal/forms/oid/components/Step3ComparisonTable/useStep3Approval.ts +++ b/src/webparts/ctFormsPortal/forms/oid/components/Step3ComparisonTable/useStep3Approval.ts @@ -103,8 +103,6 @@ export function useStep3Approval(args: UseStep3ApprovalArgs) { : m, ); onSave({ approvalChain: updatedChain }); - const nextPending = updatedChain.find((m) => m.status === "pending"); - if (nextPending?.spApprovalId) await notify(nextPending.spApprovalId); const allDone = updatedChain.every( (m) => m.status === "approved" || @@ -112,12 +110,19 @@ export function useStep3Approval(args: UseStep3ApprovalArgs) { m.status === "recommends", ); if (allDone) { + // Финал: статус «Согласовано» ДО оповещения, и шлём по currentMember (у него + // spApprovalId точно есть) — иначе на финале «Согласована» не уходит, а поток + // читает ещё «На согласовании». Порядок как в ветке отклонения / в Step4. await service.updateOIDStatus(oid.id, "approved"); onSave({ approvalChain: updatedChain, oid: { ...oid, status: "approved" }, }); + if (currentMember.spApprovalId) await notify(currentMember.spApprovalId); onStepComplete(4); + } else { + const nextPending = updatedChain.find((m) => m.status === "pending"); + if (nextPending?.spApprovalId) await notify(nextPending.spApprovalId); } } else { const othersToDelete = approvalChain.filter( @@ -145,8 +150,10 @@ export function useStep3Approval(args: UseStep3ApprovalArgs) { approvalChain: finalChain, oid: { ...oid, status: "rejected" }, }); - const initiator = finalChain.find((m) => m.role === "Инициатор"); - if (initiator?.spApprovalId) await notify(initiator.spApprovalId); + // Шлём по отклонившему (currentMember) — у него spApprovalId гарантированно есть + // (проверен в начале). У инициатора он мог отсутствовать после манипуляций с цепочкой, + // из-за чего reject по Teams-ссылке вообще не дёргал поток. + await notify(currentMember.spApprovalId); } setActionDialog(null); } catch (err) { diff --git a/src/webparts/ctFormsPortal/forms/oid/components/Step4Approval/useStep4Approval.ts b/src/webparts/ctFormsPortal/forms/oid/components/Step4Approval/useStep4Approval.ts index c80bbbd..7846bc4 100644 --- a/src/webparts/ctFormsPortal/forms/oid/components/Step4Approval/useStep4Approval.ts +++ b/src/webparts/ctFormsPortal/forms/oid/components/Step4Approval/useStep4Approval.ts @@ -304,8 +304,11 @@ export function useStep4Approval(args: UseStep4ApprovalArgs) { approvalChain: finalChain, oid: { ...oid!, status: "rejected" }, }); - const initiator = finalChain.find((m) => m.role === "Инициатор"); - if (initiator?.spApprovalId) await notify(initiator.spApprovalId); + // Уведомляем по spId ОТКЛОНИВШЕГО (currentMember) — он гарантированно есть (проверен в + // начале обработчика). У инициатора spApprovalId мог отсутствовать после манипуляций с + // цепочкой, из-за чего reject вообще не дёргал поток. Ветку письма определяет статус СТ + // («Отклонено»), получателя — автор СТ, поэтому чей элемент согласования передан — не важно. + await notify(currentMember.spApprovalId); } closeActionDialog();