sla в общем готово
This commit is contained in:
@@ -141,6 +141,10 @@ const RecruitingHireForm: React.FC<IRequestFormProps> = ({ requestType, context,
|
|||||||
position: r.position,
|
position: r.position,
|
||||||
allowReassign: r.allowReassign,
|
allowReassign: r.allowReassign,
|
||||||
order: r.order,
|
order: r.order,
|
||||||
|
// Транзитом из маршрута в строку списка: наследование бэкенд применил
|
||||||
|
// при resolve, форма только переносит значения (см. IMatrixRow.slaHours).
|
||||||
|
slaHours: r.slaHours,
|
||||||
|
askOverdueReason: r.askOverdueReason,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Удаление уже прикреплённого файла (в правке) — сразу из заявки.
|
// Удаление уже прикреплённого файла (в правке) — сразу из заявки.
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
||||||
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
||||||
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
||||||
|
{ "internalName": "SLAhours", "title": "SLA, часов", "type": "Number" },
|
||||||
|
{ "internalName": "AskOverdueReason", "title": "Опрос причины просрочки", "type": "Boolean" },
|
||||||
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,11 @@ const RecruitingSelectionForm: React.FC<IRequestFormProps> = ({ requestType, con
|
|||||||
email: r.email,
|
email: r.email,
|
||||||
position: r.position,
|
position: r.position,
|
||||||
allowReassign: r.allowReassign,
|
allowReassign: r.allowReassign,
|
||||||
order: r.order
|
order: r.order,
|
||||||
|
// Транзитом из маршрута в строку списка: наследование бэкенд применил
|
||||||
|
// при resolve, форма только переносит значения (см. IMatrixRow.slaHours).
|
||||||
|
slaHours: r.slaHours,
|
||||||
|
askOverdueReason: r.askOverdueReason
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const handleRemoveAttachment = (fileName: string): void => {
|
const handleRemoveAttachment = (fileName: string): void => {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
||||||
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
||||||
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
||||||
|
{ "internalName": "SLAhours", "title": "SLA, часов", "type": "Number" },
|
||||||
|
{ "internalName": "AskOverdueReason", "title": "Опрос причины просрочки", "type": "Boolean" },
|
||||||
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,11 @@ const Ticket1CForm: React.FC<IRequestFormProps> = ({ requestType, context, onCan
|
|||||||
email: r.email,
|
email: r.email,
|
||||||
position: r.position,
|
position: r.position,
|
||||||
allowReassign: r.allowReassign,
|
allowReassign: r.allowReassign,
|
||||||
order: r.order
|
order: r.order,
|
||||||
|
// Транзитом из маршрута в строку списка: наследование бэкенд применил
|
||||||
|
// при resolve, форма только переносит значения (см. IMatrixRow.slaHours).
|
||||||
|
slaHours: r.slaHours,
|
||||||
|
askOverdueReason: r.askOverdueReason
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const handleRemoveAttachment = (fileName: string): void => {
|
const handleRemoveAttachment = (fileName: string): void => {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
||||||
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
||||||
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
||||||
|
{ "internalName": "SLAhours", "title": "SLA, часов", "type": "Number" },
|
||||||
|
{ "internalName": "AskOverdueReason", "title": "Опрос причины просрочки", "type": "Boolean" },
|
||||||
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,11 @@ const VacationForm: React.FC<IRequestFormProps> = ({ requestType, context, onCan
|
|||||||
email: r.email,
|
email: r.email,
|
||||||
position: r.position,
|
position: r.position,
|
||||||
allowReassign: r.allowReassign,
|
allowReassign: r.allowReassign,
|
||||||
order: r.order
|
order: r.order,
|
||||||
|
// Транзитом из маршрута в строку списка: наследование бэкенд применил
|
||||||
|
// при resolve, форма только переносит значения (см. IMatrixRow.slaHours).
|
||||||
|
slaHours: r.slaHours,
|
||||||
|
askOverdueReason: r.askOverdueReason
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const save = (status: string): (() => Promise<void>) => async (): Promise<void> => {
|
const save = (status: string): (() => Promise<void>) => async (): Promise<void> => {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
||||||
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
||||||
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
||||||
|
{ "internalName": "SLAhours", "title": "SLA, часов", "type": "Number" },
|
||||||
|
{ "internalName": "AskOverdueReason", "title": "Опрос причины просрочки", "type": "Boolean" },
|
||||||
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,6 +164,10 @@ const WorkplaceSetupForm: React.FC<IRequestFormProps> = ({ requestType, context,
|
|||||||
position: r.position,
|
position: r.position,
|
||||||
allowReassign: r.allowReassign,
|
allowReassign: r.allowReassign,
|
||||||
order: r.order,
|
order: r.order,
|
||||||
|
// Транзитом из маршрута в строку списка: наследование бэкенд применил
|
||||||
|
// при resolve, форма только переносит значения (см. IMatrixRow.slaHours).
|
||||||
|
slaHours: r.slaHours,
|
||||||
|
askOverdueReason: r.askOverdueReason,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Удаление уже прикреплённого файла (в правке) — сразу из заявки.
|
// Удаление уже прикреплённого файла (в правке) — сразу из заявки.
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
{ "internalName": "StepOrder", "title": "Порядок", "type": "Number" },
|
||||||
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
{ "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" },
|
||||||
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
{ "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] },
|
||||||
|
{ "internalName": "SLAhours", "title": "SLA, часов", "type": "Number" },
|
||||||
|
{ "internalName": "AskOverdueReason", "title": "Опрос причины просрочки", "type": "Boolean" },
|
||||||
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
{ "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ const FIELDS = {
|
|||||||
allowReassign: 'AllowReassignToOtherApprovers', // «Можно перепоручать» (Да/Нет)
|
allowReassign: 'AllowReassignToOtherApprovers', // «Можно перепоручать» (Да/Нет)
|
||||||
phase: 'Phase', // «Фаза» (Choice): Согласование | Исполнение
|
phase: 'Phase', // «Фаза» (Choice): Согласование | Исполнение
|
||||||
delegatedBy: 'DelegatedBy', // «Кем переназначено» (User) → DelegatedById
|
delegatedBy: 'DelegatedBy', // «Кем переназначено» (User) → DelegatedById
|
||||||
|
slaHours: 'SLAhours', // «SLA, часов» (Number) — пусто значит «взять у типа заявки»
|
||||||
|
askOverdueReason: 'AskOverdueReason', // «Опрос причины просрочки» (Да/Нет)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Согласующий для записи в список.
|
// Согласующий для записи в список.
|
||||||
@@ -45,6 +47,18 @@ export interface IApproverToWrite {
|
|||||||
* (ApprovalMatrix/useMatrixEditor) всегда даёт уникальный order по позиции —
|
* (ApprovalMatrix/useMatrixEditor) всегда даёт уникальный order по позиции —
|
||||||
* это поле для параллельных шагов, приходящих из внешнего маршрута напрямую. */
|
* это поле для параллельных шагов, приходящих из внешнего маршрута напрямую. */
|
||||||
order?: number;
|
order?: number;
|
||||||
|
/**
|
||||||
|
* SLA шага в часах и признак опроса причины просрочки — приходят из resolve
|
||||||
|
* с уже применённым наследованием «шаг перекрывает тип заявки» (см. бэкенд
|
||||||
|
* ResolveStepAsync). Портал их не вычисляет, только переносит в строку.
|
||||||
|
*
|
||||||
|
* undefined/null — «в строке не задано»: тогда напоминания используют SLA
|
||||||
|
* типа заявки. Ноль — это НЕ пусто, а «напоминать сразу».
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @rushstack/no-new-null -- null = «не задано» (в SharePoint пустая колонка)
|
||||||
|
slaHours?: number | null;
|
||||||
|
// eslint-disable-next-line @rushstack/no-new-null -- см. slaHours
|
||||||
|
askOverdueReason?: boolean | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Все запросы к списку «<форма> — согласование». listTitle задаётся формой.
|
// Все запросы к списку «<форма> — согласование». listTitle задаётся формой.
|
||||||
@@ -101,6 +115,9 @@ export class ApprovalListService {
|
|||||||
[FIELDS.order]: order,
|
[FIELDS.order]: order,
|
||||||
[FIELDS.allowReassign]: a.allowReassign,
|
[FIELDS.allowReassign]: a.allowReassign,
|
||||||
[FIELDS.phase]: phase,
|
[FIELDS.phase]: phase,
|
||||||
|
// ?? null, а не || null: ноль часов — значимое значение.
|
||||||
|
[FIELDS.slaHours]: a.slaHours ?? null,
|
||||||
|
[FIELDS.askOverdueReason]: a.askOverdueReason ?? null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,6 +239,8 @@ export class ApprovalListService {
|
|||||||
FIELDS.order,
|
FIELDS.order,
|
||||||
FIELDS.allowReassign,
|
FIELDS.allowReassign,
|
||||||
FIELDS.phase,
|
FIELDS.phase,
|
||||||
|
FIELDS.slaHours,
|
||||||
|
FIELDS.askOverdueReason,
|
||||||
`${FIELDS.approver}/Title`,
|
`${FIELDS.approver}/Title`,
|
||||||
`${FIELDS.approver}/EMail`
|
`${FIELDS.approver}/EMail`
|
||||||
)
|
)
|
||||||
@@ -240,6 +259,11 @@ export class ApprovalListService {
|
|||||||
comment: (r[FIELDS.comment] as string) || '',
|
comment: (r[FIELDS.comment] as string) || '',
|
||||||
allowReassign: (r[FIELDS.allowReassign] as boolean) ?? false,
|
allowReassign: (r[FIELDS.allowReassign] as boolean) ?? false,
|
||||||
phase: (r[FIELDS.phase] as string) || APPROVAL_PHASE.approval,
|
phase: (r[FIELDS.phase] as string) || APPROVAL_PHASE.approval,
|
||||||
|
// Читаем, чтобы не потерять при пересохранении: writeRoute удаляет
|
||||||
|
// строки и создаёт их заново из матрицы, и без этих полей SLA,
|
||||||
|
// проставленный при первой отправке, обнулился бы у черновика.
|
||||||
|
slaHours: (r[FIELDS.slaHours] as number | null) ?? null,
|
||||||
|
askOverdueReason: (r[FIELDS.askOverdueReason] as boolean | null) ?? null,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ export async function getPlannedMatrix(
|
|||||||
comment: '',
|
comment: '',
|
||||||
allowReassign: s.allowReassignToOtherApprovers,
|
allowReassign: s.allowReassignToOtherApprovers,
|
||||||
phase,
|
phase,
|
||||||
|
slaHours: s.slaHours,
|
||||||
|
askOverdueReason: s.askOverdueReason,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,4 +47,12 @@ export interface IResolvedRouteStep {
|
|||||||
// Предупреждение маршрута по этому шагу (например, роль не разрешилась в
|
// Предупреждение маршрута по этому шагу (например, роль не разрешилась в
|
||||||
// конкретного человека) — приходит от API, показываем автору при желании.
|
// конкретного человека) — приходит от API, показываем автору при желании.
|
||||||
warning: string | null;
|
warning: string | null;
|
||||||
|
// SLA шага в часах и признак опроса причины просрочки. Наследование
|
||||||
|
// «шаг перекрывает тип заявки» бэкенд уже применил — здесь итоговое значение,
|
||||||
|
// его достаточно записать в строку списка согласования.
|
||||||
|
// null — SLA не настроен, напоминаний по шагу не будет.
|
||||||
|
// eslint-disable-next-line @rushstack/no-new-null -- зеркалит nullable-контракт бэкенда
|
||||||
|
slaHours: number | null;
|
||||||
|
// eslint-disable-next-line @rushstack/no-new-null -- см. slaHours
|
||||||
|
askOverdueReason: boolean | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,16 @@ export interface IMatrixRow {
|
|||||||
// редактировании — переключается кнопкой и заново раздаёт order (см.
|
// редактировании — переключается кнопкой и заново раздаёт order (см.
|
||||||
// useMatrixEditor/withOrders).
|
// useMatrixEditor/withOrders).
|
||||||
parallelWithPrev?: boolean;
|
parallelWithPrev?: boolean;
|
||||||
|
/**
|
||||||
|
* SLA шага и признак опроса причины просрочки. Матрица здесь — транзитное
|
||||||
|
* звено: значения приходят из resolve (или читаются из уже записанных строк)
|
||||||
|
* и уходят обратно в список при сохранении. На форме они не показываются и
|
||||||
|
* не редактируются — правятся в админке.
|
||||||
|
*
|
||||||
|
* null/undefined — «не задано», работает SLA типа заявки. Ноль — «сразу».
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @rushstack/no-new-null -- null приходит из SharePoint и значит «не задано»
|
||||||
|
slaHours?: number | null;
|
||||||
|
// eslint-disable-next-line @rushstack/no-new-null -- см. slaHours
|
||||||
|
askOverdueReason?: boolean | null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user