Уведомления назначенным пользователям (#9)
Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz> Reviewed-on: http://git.tnsu.kz/gorbenko.pavel/tnsu-approval-route/pulls/9
This commit was merged in pull request #9.
This commit is contained in:
@@ -4,6 +4,7 @@ import '@pnp/sp/lists';
|
||||
import '@pnp/sp/items';
|
||||
import '@pnp/sp/site-users/web';
|
||||
import '@pnp/sp/search';
|
||||
import { AadHttpClient } from '@microsoft/sp-http';
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import {
|
||||
APPROVAL_PHASE,
|
||||
@@ -20,6 +21,15 @@ import {
|
||||
// списки SharePoint, только с другого клиента).
|
||||
const DATA_LIST_SUFFIX = /\s*—\s*данные\s*$/;
|
||||
|
||||
// Тот же поток оповещения согласующего/исполнителя, что и в request-portal
|
||||
// (src/webparts/requestPortal/shared/config.ts) — один и тот же список
|
||||
// согласования пишут оба веб-парта, поток сам находит по RowID согласующего,
|
||||
// статус и заявку и уведомляет письмом. Авторизация — AadHttpClient с
|
||||
// ресурсом Flow Service (обычный fetch → 401 из-за Entra-триггера).
|
||||
const FLOW_RESOURCE = 'https://service.flow.microsoft.com/';
|
||||
const FLOW_NOTIFY_URL =
|
||||
'https://eab3d2815f2beb42bf2e7ec1731708.92.environment.api.powerplatform.com:443/powerautomate/automations/direct/cu/07/workflows/b21516edf8a14287a65a39e4116dfe4f/triggers/manual/paths/invoke?api-version=1';
|
||||
|
||||
// Внутренние имена колонок списка согласования — 1:1 с FIELDS в
|
||||
// request-portal/src/webparts/requestPortal/shared/approval/approvalList.service.ts.
|
||||
// Это тот же самый список SharePoint, поэтому имена колонок должны совпадать
|
||||
@@ -102,10 +112,12 @@ export class RequestManageService {
|
||||
// Title списка данных → Title списка согласования. undefined, если Title не
|
||||
// оканчивается на «— данные» (список заведён не по конвенции request-portal,
|
||||
// управлять маршрутом для него отсюда нельзя).
|
||||
private async approvalListTitle(sp: SPFI, listId: string): Promise<string | undefined> {
|
||||
private async listTitles(sp: SPFI, listId: string): Promise<{ dataListTitle: string; approvalListTitle: string | undefined }> {
|
||||
const info = (await sp.web.getList(listId).select('Title')()) as { Title: string };
|
||||
if (!DATA_LIST_SUFFIX.test(info.Title)) return undefined;
|
||||
return `${info.Title.replace(DATA_LIST_SUFFIX, '')} — согласование`;
|
||||
const approvalListTitle = DATA_LIST_SUFFIX.test(info.Title)
|
||||
? `${info.Title.replace(DATA_LIST_SUFFIX, '')} — согласование`
|
||||
: undefined;
|
||||
return { dataListTitle: info.Title, approvalListTitle };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,16 +180,16 @@ export class RequestManageService {
|
||||
const sp = this.clientFor(requestType.siteUrl);
|
||||
const dataList = sp.web.getList(requestType.listId);
|
||||
|
||||
const [requestRow, approvalListTitle] = await Promise.all([
|
||||
const [requestRow, { dataListTitle, approvalListTitle }] = await Promise.all([
|
||||
dataList.items
|
||||
.getById(requestId)
|
||||
.select('Id', 'Title', 'Status', 'Created', 'Author/Title')
|
||||
.expand('Author')() as Promise<IRawDataRow>,
|
||||
this.approvalListTitle(sp, requestType.listId)
|
||||
this.listTitles(sp, requestType.listId)
|
||||
]);
|
||||
|
||||
if (!approvalListTitle) {
|
||||
return { request: toSummary(requestRow), siteUrl: requestType.siteUrl, approvalListTitle: '', rows: [] };
|
||||
return { request: toSummary(requestRow), siteUrl: requestType.siteUrl, dataListTitle, approvalListTitle: '', rows: [] };
|
||||
}
|
||||
|
||||
const approvalList = sp.web.lists.getByTitle(approvalListTitle);
|
||||
@@ -217,7 +229,7 @@ export class RequestManageService {
|
||||
};
|
||||
});
|
||||
|
||||
return { request: toSummary(requestRow), siteUrl: requestType.siteUrl, approvalListTitle, rows };
|
||||
return { request: toSummary(requestRow), siteUrl: requestType.siteUrl, dataListTitle, approvalListTitle, rows };
|
||||
}
|
||||
|
||||
/** email → числовой Id пользователя сайта (Person-поле требует Id, не email). */
|
||||
@@ -305,4 +317,33 @@ export class RequestManageService {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправить уведомление согласующему/исполнителю конкретной строки маршрута —
|
||||
* тот же поток Power Automate, что и request-portal (см. FLOW_NOTIFY_URL
|
||||
* выше): поток сам находит по RowID согласующего, статус и заявку и шлёт
|
||||
* письмо. В отличие от request-portal (там вызывается автоматически после
|
||||
* решения), здесь — по явному клику на кнопку в таблице маршрута, поэтому
|
||||
* ошибку НЕ глушим — вызывающая сторона показывает её пользователю.
|
||||
*/
|
||||
public async notifyRow(
|
||||
requestTypeId: number,
|
||||
matrix: Pick<ManagedRequestMatrix, 'request' | 'dataListTitle' | 'approvalListTitle'>,
|
||||
rowId: number
|
||||
): Promise<void> {
|
||||
const client = await this.context.aadHttpClientFactory.getClient(FLOW_RESOURCE);
|
||||
const res = await client.post(FLOW_NOTIFY_URL, AadHttpClient.configurations.v1, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
RequestTypeId: requestTypeId,
|
||||
RowID: rowId,
|
||||
RequestID: matrix.request.id,
|
||||
ListName: matrix.dataListTitle,
|
||||
ApproveListName: matrix.approvalListTitle
|
||||
})
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error(`Поток оповещения: ${res.status} ${res.statusText}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user