refactor: расчёт маршрута заявки в 1С вынесен в planRoute
Сбор условий маршрута (вид работ, база 1С, отдел) и запрос маршрута с схлопыванием повторов переехали из формы в planRoute.ts. Поведение формы не меняется; функцию сможет использовать страница «Проверка маршрутов», чтобы проверять ровно тот маршрут, что видит заявитель. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,6 @@ import {
|
|||||||
ApprovalHistory,
|
ApprovalHistory,
|
||||||
StatusBadge,
|
StatusBadge,
|
||||||
useMatrixEditor,
|
useMatrixEditor,
|
||||||
getPlannedMatrix,
|
|
||||||
loadRoutePhase,
|
loadRoutePhase,
|
||||||
isOpenedRouteReady,
|
isOpenedRouteReady,
|
||||||
resolveWriteListId,
|
resolveWriteListId,
|
||||||
@@ -57,7 +56,7 @@ import { RequestSection } from './sections/RequestSection';
|
|||||||
import { ContactSection } from './sections/ContactSection';
|
import { ContactSection } from './sections/ContactSection';
|
||||||
import { useStableCallback } from '../../shared/useStableCallback';
|
import { useStableCallback } from '../../shared/useStableCallback';
|
||||||
import { applyManagerOverride, managerEmail } from './managerOverride';
|
import { applyManagerOverride, managerEmail } from './managerOverride';
|
||||||
import { dedupeRouteRows } from './dedupeRoute';
|
import { planTicket1CPhase, ticket1cRouteFieldValues } from './planRoute';
|
||||||
import { handoffToPlanner } from './plannerHandoff';
|
import { handoffToPlanner } from './plannerHandoff';
|
||||||
import { submitStatus } from './submitStatus';
|
import { submitStatus } from './submitStatus';
|
||||||
|
|
||||||
@@ -174,27 +173,19 @@ const Ticket1CForm: React.FC<IRequestFormProps> = ({
|
|||||||
// см. fieldValues), а не выбирается заявителем. Поэтому матрица здесь ВСЕГДА
|
// см. fieldValues), а не выбирается заявителем. Поэтому матрица здесь ВСЕГДА
|
||||||
// нередактируема (editable=false) — заявитель только видит, кто согласует, без
|
// нередактируема (editable=false) — заявитель только видит, кто согласует, без
|
||||||
// возможности добавить/убрать/переставить согласующего.
|
// возможности добавить/убрать/переставить согласующего.
|
||||||
// Базы 1С — мультивыбор, а approval-route принимает value только строкой:
|
// Расчёт маршрута вынесен в planRoute.ts — им же пользуется страница
|
||||||
// передаём все выбранные базы одной записью через пробел (как CompaniesJson в
|
// «Проверка маршрутов», чтобы проверять ровно то, что видит заявитель.
|
||||||
// RecruitingHire), условия в админке — «База 1С содержит ЗУП/АТП/ATS».
|
|
||||||
const databasesFieldValue = data.DB1C.slice().sort().join(' ');
|
|
||||||
const fieldValues = useMemo(
|
const fieldValues = useMemo(
|
||||||
() => [
|
() => ticket1cRouteFieldValues({ WorkType: data.WorkType, DB1C: data.DB1C, Department: data.Department }),
|
||||||
{ fieldName: 'WorkType', value: data.WorkType },
|
[data.WorkType, data.DB1C, data.Department]
|
||||||
{ fieldName: 'DB1C', value: databasesFieldValue },
|
|
||||||
{ fieldName: 'Department', value: data.Department }
|
|
||||||
],
|
|
||||||
[data.WorkType, databasesFieldValue, data.Department]
|
|
||||||
);
|
);
|
||||||
const matrixKey = `${userEmail}-${editId ?? 'new'}-${data.WorkType}-${databasesFieldValue}-${data.Department}`;
|
const matrixKey = [userEmail, editId ?? 'new', ...fieldValues.map((f) => f.value)].join('-');
|
||||||
const matrixReady =
|
const matrixReady =
|
||||||
isOpenedRouteReady(editId, requestStatus, requestTypeId) && (!!editId || (!!data.WorkType && !!requestTypeId));
|
isOpenedRouteReady(editId, requestStatus, requestTypeId) && (!!editId || (!!data.WorkType && !!requestTypeId));
|
||||||
const loadMatrix = useCallback(
|
const loadMatrix = useCallback(
|
||||||
() =>
|
() =>
|
||||||
loadRoutePhase(approval, editId, requestStatus, 'Approval', async () =>
|
loadRoutePhase(approval, editId, requestStatus, 'Approval', () =>
|
||||||
dedupeRouteRows(
|
planTicket1CPhase(context, requestTypeId as number, userEmail, approval, 'Approval', fieldValues)
|
||||||
await getPlannedMatrix(context, requestTypeId as number, userEmail, approval, 'Approval', null, fieldValues)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
[context, userEmail, approval, editId, requestStatus, fieldValues, requestTypeId]
|
[context, userEmail, approval, editId, requestStatus, fieldValues, requestTypeId]
|
||||||
);
|
);
|
||||||
@@ -204,10 +195,8 @@ const Ticket1CForm: React.FC<IRequestFormProps> = ({
|
|||||||
// в карточке Planner, в портале отмечает «Выполнено» (см. plannerHandoff.ts).
|
// в карточке Planner, в портале отмечает «Выполнено» (см. plannerHandoff.ts).
|
||||||
const loadExecutors = useCallback(
|
const loadExecutors = useCallback(
|
||||||
() =>
|
() =>
|
||||||
loadRoutePhase(approval, editId, requestStatus, 'Execution', async () =>
|
loadRoutePhase(approval, editId, requestStatus, 'Execution', () =>
|
||||||
dedupeRouteRows(
|
planTicket1CPhase(context, requestTypeId as number, userEmail, approval, 'Execution', fieldValues)
|
||||||
await getPlannedMatrix(context, requestTypeId as number, userEmail, approval, 'Execution', null, fieldValues)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
[context, userEmail, approval, editId, requestStatus, fieldValues, requestTypeId]
|
[context, userEmail, approval, editId, requestStatus, fieldValues, requestTypeId]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||||
|
import {
|
||||||
|
ApprovalListService,
|
||||||
|
ApprovalStatus,
|
||||||
|
getPlannedMatrix,
|
||||||
|
IMatrixRow,
|
||||||
|
IResolveFieldValue
|
||||||
|
} from '../../shared/approval';
|
||||||
|
import { IFormData } from './model';
|
||||||
|
import { dedupeRouteRows } from './dedupeRoute';
|
||||||
|
|
||||||
|
/** Поля заявки, от которых зависит маршрут 1С (условия шагов в админке маршрута #8). */
|
||||||
|
export type Ticket1CRouteInput = Pick<IFormData, 'WorkType' | 'DB1C' | 'Department'>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Значения полей для условных шагов маршрута (fieldValues при resolve).
|
||||||
|
*
|
||||||
|
* Базы 1С — мультивыбор, а approval-route принимает value только строкой:
|
||||||
|
* все выбранные базы уходят одной записью через пробел (как CompaniesJson в
|
||||||
|
* RecruitingHire), условия в админке — «DB1C содержит ЗУП/АТП/ATS».
|
||||||
|
*/
|
||||||
|
export function ticket1cRouteFieldValues(input: Ticket1CRouteInput): IResolveFieldValue[] {
|
||||||
|
return [
|
||||||
|
{ fieldName: 'WorkType', value: input.WorkType },
|
||||||
|
{ fieldName: 'DB1C', value: input.DB1C.slice().sort().join(' ') },
|
||||||
|
{ fieldName: 'Department', value: input.Department }
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запланированный маршрут одной фазы заявки в 1С. Один источник для формы и для
|
||||||
|
* страницы «Проверка маршрутов» — проверка должна видеть ровно то, что увидит
|
||||||
|
* пользователь, включая схлопывание повторов на шаге.
|
||||||
|
*/
|
||||||
|
export async function planTicket1CPhase(
|
||||||
|
context: WebPartContext,
|
||||||
|
requestTypeId: number,
|
||||||
|
userEmail: string,
|
||||||
|
approval: ApprovalListService,
|
||||||
|
phase: ApprovalStatus,
|
||||||
|
fieldValues: IResolveFieldValue[]
|
||||||
|
): Promise<IMatrixRow[]> {
|
||||||
|
const rows = await getPlannedMatrix(context, requestTypeId, userEmail, approval, phase, null, fieldValues);
|
||||||
|
return dedupeRouteRows(rows);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user