feat: письмо инициатору при отклонении и возврате заявки
Поток RequestsNotification умеет ветки «Отклонено» и «Возврат на доработку», но портал их не вызывал: notifyActiveStep ищет только активные строки, а после такого решения их нет — инициатор узнавал о решении, только открыв заявку. notifyInitiatorOfReturn шлёт в тот же поток RowID строки, по которой решил текущий пользователь; подключён в onDecided всех форм, кроме «Изменения условий ТД» (доработаем позже). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { AadHttpClient } from '@microsoft/sp-http';
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { FLOW_RESOURCE, FLOW_NOTIFY_URL, getNotificationsEnabled, getNotifyOnlyTo } from '../config';
|
||||
import { getCreatedBy } from '../createdBy';
|
||||
import { ApprovalListService } from './approvalList.service';
|
||||
import { IApprovalRow } from './models/IApprovalRow';
|
||||
import { REQUEST_STATUS } from './models/statuses';
|
||||
import { pickRowsToNotify } from './notifyTargets';
|
||||
|
||||
// Данные формы для тела запроса к потоку (постоянны для формы).
|
||||
@@ -42,11 +44,17 @@ export async function postToFlow(context: WebPartContext, flowUrl: string, body:
|
||||
// живому человеку лучше не слать».
|
||||
async function isNotifyAllowed(approval: ApprovalListService, approverId: number): Promise<boolean> {
|
||||
if (!getNotificationsEnabled()) return false;
|
||||
if (!getNotifyOnlyTo()) return true;
|
||||
return isRecipientAllowed(await approval.resolveUserEmail(approverId));
|
||||
}
|
||||
|
||||
// То же ограничение notifyOnlyTo, когда адрес получателя уже известен.
|
||||
function isRecipientAllowed(email: string): boolean {
|
||||
if (!getNotificationsEnabled()) return false;
|
||||
|
||||
const onlyTo = getNotifyOnlyTo();
|
||||
if (!onlyTo) return true;
|
||||
|
||||
const email = await approval.resolveUserEmail(approverId);
|
||||
if (email.toLowerCase() === onlyTo.toLowerCase()) return true;
|
||||
|
||||
console.warn(
|
||||
@@ -109,3 +117,51 @@ export async function notifyActiveStep(
|
||||
pickRowsToNotify(rows, rowId).map((row) => notifyRow(context, approval, requestId, target, row))
|
||||
);
|
||||
}
|
||||
|
||||
// Решения, после которых заявка уходит обратно к инициатору и ему нужно письмо.
|
||||
const RETURNED_TO_INITIATOR_STATUSES: string[] = [REQUEST_STATUS.rejected, REQUEST_STATUS.returned];
|
||||
|
||||
// Сообщить инициатору, что заявку отклонили или вернули на доработку. Вызывать
|
||||
// в onDecided с новым статусом заявки — при любом другом статусе ничего не делает.
|
||||
//
|
||||
// Поток тот же, что у notifyActiveStep: у него есть ветки «Отклонено» и «Возврат
|
||||
// на доработку», в которых он пишет не согласующему строки, а автору заявки.
|
||||
// notifyActiveStep до них не доходит — после такого решения активных строк нет.
|
||||
//
|
||||
// Строка — та, по которой решил ТЕКУЩИЙ пользователь: он только что принял
|
||||
// решение. Искать «любую отклонённую» нельзя — на параллельном шаге второй
|
||||
// участник может решить по уже отклонённой заявке, и в письме оказался бы чужой
|
||||
// комментарий.
|
||||
//
|
||||
// Некритично, как и notifyActiveStep: ошибки глотаем.
|
||||
export async function notifyInitiatorOfReturn(
|
||||
context: WebPartContext,
|
||||
approval: ApprovalListService,
|
||||
requestId: number,
|
||||
target: INotifyTarget,
|
||||
requestStatus: string
|
||||
): Promise<void> {
|
||||
if (RETURNED_TO_INITIATOR_STATUSES.indexOf(requestStatus) === -1) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const [rows, userId, initiator] = await Promise.all([
|
||||
approval.getForRequest(requestId),
|
||||
approval.getCurrentUserId(),
|
||||
getCreatedBy(target.dataListName, requestId),
|
||||
]);
|
||||
const decidedRow = rows.filter((r) => r.status === requestStatus && r.approverId === userId)[0];
|
||||
if (!decidedRow || !isRecipientAllowed(initiator?.email || '')) {
|
||||
return;
|
||||
}
|
||||
await postToFlow(context, FLOW_NOTIFY_URL, {
|
||||
RequestTypeId: target.requestTypeId,
|
||||
RowID: decidedRow.id,
|
||||
RequestID: requestId,
|
||||
ListName: target.dataListName,
|
||||
ApproveListName: target.approvalListName,
|
||||
});
|
||||
} catch {
|
||||
// не критично — просто не отправили уведомление
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user