fix: оповещения параллельного шага — всем участникам и без дублей
Письмо уходило только первому из параллельных согласующих, а после решения одного из них остальные получали повторное. Теперь шаг оповещается целиком при старте и не оповещается снова, если кто-то из его участников уже решил. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,8 @@ import { AadHttpClient } from '@microsoft/sp-http';
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { FLOW_RESOURCE, FLOW_NOTIFY_URL, getNotificationsEnabled, getNotifyOnlyTo } from '../config';
|
||||
import { ApprovalListService } from './approvalList.service';
|
||||
import { REQUEST_STATUS } from './models/statuses';
|
||||
import { IApprovalRow } from './models/IApprovalRow';
|
||||
import { pickRowsToNotify } from './notifyTargets';
|
||||
|
||||
// Данные формы для тела запроса к потоку (постоянны для формы).
|
||||
export interface INotifyTarget {
|
||||
@@ -54,12 +55,40 @@ async function isNotifyAllowed(approval: ApprovalListService, approverId: number
|
||||
return false;
|
||||
}
|
||||
|
||||
// Одна строка маршрута → один вызов потока. Ошибку глотаем здесь, по строке:
|
||||
// сбой письма одному участнику параллельного шага не должен лишать письма остальных.
|
||||
async function notifyRow(
|
||||
context: WebPartContext,
|
||||
approval: ApprovalListService,
|
||||
requestId: number,
|
||||
target: INotifyTarget,
|
||||
row: IApprovalRow
|
||||
): Promise<void> {
|
||||
try {
|
||||
if (!(await isNotifyAllowed(approval, row.approverId))) {
|
||||
return;
|
||||
}
|
||||
await postNotify(context, {
|
||||
RequestTypeId: target.requestTypeId,
|
||||
RowID: row.id,
|
||||
RequestID: requestId,
|
||||
ListName: target.dataListName,
|
||||
ApproveListName: target.approvalListName,
|
||||
});
|
||||
} catch {
|
||||
// не критично — просто не отправили уведомление
|
||||
}
|
||||
}
|
||||
|
||||
// Находит АКТИВНЫЙ шаг маршрута (На согласовании / На исполнении) и уведомляет его.
|
||||
// Вызывать после отправки заявки и после каждого положительного решения. Поток по
|
||||
// переданным полям сам находит согласующего/исполнителя и шлёт уведомление.
|
||||
// Уведомление некритично — ошибки глотаем, чтобы не ронять основной сценарий.
|
||||
//
|
||||
// rowId — уведомить именно эту активную строку, а не первую попавшуюся: при
|
||||
// Параллельный шаг (несколько активных строк с одним StepOrder) оповещается
|
||||
// целиком — каждому участнику свой вызов потока (см. pickRowsToNotify).
|
||||
//
|
||||
// rowId — уведомить именно эту активную строку, а не весь шаг: при
|
||||
// замене/удалении исполнителя на параллельном шаге активных строк несколько, и
|
||||
// письмо должно уйти новому человеку, а не тому, кто уже его получил.
|
||||
export async function notifyActiveStep(
|
||||
@@ -69,27 +98,13 @@ export async function notifyActiveStep(
|
||||
target: INotifyTarget,
|
||||
rowId?: number
|
||||
): Promise<void> {
|
||||
let rows: IApprovalRow[];
|
||||
try {
|
||||
const rows = await approval.getForRequest(requestId);
|
||||
const active = rows.filter(
|
||||
(r) =>
|
||||
(r.status === REQUEST_STATUS.onApproval || r.status === REQUEST_STATUS.onExecution) &&
|
||||
(rowId === undefined || r.id === rowId)
|
||||
)[0];
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
if (!(await isNotifyAllowed(approval, active.approverId))) {
|
||||
return;
|
||||
}
|
||||
await postNotify(context, {
|
||||
RequestTypeId: target.requestTypeId,
|
||||
RowID: active.id,
|
||||
RequestID: requestId,
|
||||
ListName: target.dataListName,
|
||||
ApproveListName: target.approvalListName,
|
||||
});
|
||||
rows = await approval.getForRequest(requestId);
|
||||
} catch {
|
||||
// не критично — просто не отправили уведомление
|
||||
return; // не критично — просто не отправили уведомление
|
||||
}
|
||||
await Promise.all(
|
||||
pickRowsToNotify(rows, rowId).map((row) => notifyRow(context, approval, requestId, target, row))
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user