diff --git a/src/webparts/requestPortal/shared/approval/approvalSubmission.service.ts b/src/webparts/requestPortal/shared/approval/approvalSubmission.service.ts index a7edf90..974b663 100644 --- a/src/webparts/requestPortal/shared/approval/approvalSubmission.service.ts +++ b/src/webparts/requestPortal/shared/approval/approvalSubmission.service.ts @@ -1,5 +1,4 @@ import { WebPartContext } from '@microsoft/sp-webpart-base'; -import { log } from '@tnsu/monitoring-web'; import { resolveRoute } from './approvalRoute.service'; import { ApprovalListService, IApproverToWrite } from './approvalList.service'; import { IMatrixRow } from './models/IMatrixRow'; @@ -69,11 +68,6 @@ export async function writeApprovers( await approval.createSteps(requestId, approvers, rowStatus, APPROVAL_PHASE.approval, 1); if (submitted) { await approval.activateNextQueued(requestId); - log.info('Заявка отправлена на согласование', { - 'request.id': requestId, - 'request.status': status, - 'route.approvers': approvers.length, - }); } } @@ -144,11 +138,5 @@ export async function writeRoute( if (submitted) { await approval.activateNextQueued(requestId); - log.info('Заявка отправлена на согласование', { - 'request.id': requestId, - 'request.status': status, - 'route.approvers': approvers.length, - 'route.executors': executors.length, - }); } } diff --git a/src/webparts/requestPortal/shared/approval/approverDecision.service.ts b/src/webparts/requestPortal/shared/approval/approverDecision.service.ts index b19e9aa..970e1c6 100644 --- a/src/webparts/requestPortal/shared/approval/approverDecision.service.ts +++ b/src/webparts/requestPortal/shared/approval/approverDecision.service.ts @@ -345,14 +345,7 @@ export class ApproverService { const rows = await this.approval.getForRequest(requestId); const requestStatus = this.computeRequestStatus(rows); await this.updateRequestStatus(requestId, requestStatus); - log.info(DECISION_MESSAGE[decision], { - 'request.id': requestId, - 'request.list': this.dataListRef, - 'request.status': requestStatus, - 'approval.decision': decision, - 'approval.rowId': rowId, - 'approval.comment': comment.slice(0, 500), - }); + await this.logDecision(requestId, rowId, decision, comment, requestStatus); emitRequestsChanged(); return requestStatus; } @@ -381,6 +374,42 @@ export class ApproverService { return REQUEST_STATUS.execution; } + /** + * Решение — в логи мониторинга, с кодом и названием заявки, чтобы её было видно прямо в списке логов. + * Код и название дочитываются отдельно; не получилось — пишем без них: решение уже применено. + */ + private async logDecision( + requestId: number, + rowId: number, + decision: ApproverDecision, + comment: string, + requestStatus: string + ): Promise { + let code = ''; + let title = ''; + try { + const item = (await this.dataList().items.getById(requestId).select('Title', 'RequestUniqueCode')()) as { + Title?: string; + RequestUniqueCode?: string; + }; + code = item.RequestUniqueCode || ''; + title = item.Title || ''; + } catch { + // без кода и названия — лог всё равно нужен + } + const what = [code, title].filter(Boolean).join(' · ') || `№${requestId}`; + log.info(`${DECISION_MESSAGE[decision]}: ${what}`, { + 'request.id': requestId, + 'request.code': code, + 'request.title': title, + 'request.list': this.dataListRef, + 'request.status': requestStatus, + 'approval.decision': decision, + 'approval.rowId': rowId, + 'approval.comment': comment.slice(0, 500), + }); + } + private dataList(): IList { return this.dataListRef.startsWith('/') ? getSP().web.getList(this.dataListRef) diff --git a/src/webparts/requestPortal/shared/dataList.ts b/src/webparts/requestPortal/shared/dataList.ts index 1ba49b7..1eab111 100644 --- a/src/webparts/requestPortal/shared/dataList.ts +++ b/src/webparts/requestPortal/shared/dataList.ts @@ -7,6 +7,8 @@ import { getSP } from './pnp/pnpjs'; import { buildRequestUniqueCode } from './requestCode'; import { dataListTitle } from './listTitles'; import { RequestTypeId } from '../models/types'; +import { REQUEST_TYPES } from '../data/requests'; +import { isSubmittedStatus } from './approval/models/statuses'; /** * Список данных, в который фактически пишем: listId (конкретная партиция — @@ -51,6 +53,7 @@ export async function saveRequestItem( if (existingId) { await list.items.getById(existingId).update(item); + logSaved(formId, existingId, undefined, item, false); return { id: existingId }; } @@ -59,8 +62,34 @@ export async function saveRequestItem( // Код известен только после создания элемента (нужен его Id). const code = buildRequestUniqueCode(codePrefix, id, new Date()); await list.items.getById(id).update({ RequestUniqueCode: code }); - // Событие для мониторинга: кто (пользователь — из токена) и какую заявку создал. Отправка на согласование - // и решения пишутся отдельно — approvalSubmission.service.ts и approverDecision.service.ts. - log.info('Создана заявка', { 'request.type': formId, 'request.id': id, 'request.code': code }); + logSaved(formId, id, code, item, true); return { id, code }; } + +/** + * События для мониторинга: какая заявка создана и отправлена на согласование (пользователь — из токена). + * В тексте — вид, код и название заявки, чтобы её было видно прямо в списке логов. Решения согласующих + * пишет approverDecision.service.ts. + */ +function logSaved( + formId: RequestTypeId, + id: number, + code: string | undefined, + item: Record, + created: boolean +): void { + const typeTitle = REQUEST_TYPES.find((t) => t.id === formId)?.title ?? formId; + const title = typeof item.Title === 'string' ? item.Title : ''; + const status = typeof item.RequestStatus === 'string' ? item.RequestStatus : ''; + const what = [typeTitle, code, title].filter(Boolean).join(' · '); + const attributes = { + 'request.type': formId, + 'request.typeTitle': typeTitle, + 'request.id': id, + 'request.code': code ?? '', + 'request.title': title, + 'request.status': status, + }; + if (created) log.info(`Создана заявка: ${what}`, attributes); + if (isSubmittedStatus(status)) log.info(`Заявка отправлена на согласование: ${what}`, attributes); +}