refactor(ServiceRequest): CostsJson/CostTotal -> EstimateJson/EstimateTotal
Понятнее по смыслу колонки: это смета (Estimate), а не «costs» вообще. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,8 +12,8 @@
|
||||
## Особое поведение
|
||||
- Подача за другого: заявитель — `PeopleField`, по умолчанию текущий пользователь, можно выбрать любого — маршрут резолвится на ВЫБРАННОГО (см. `handleRequesterChange`).
|
||||
- Табличная часть «Приложения» (`Annexes`) — документы заявки (чертежи, ТЗ, ведомости объёмов) с чекбоксом «подтверждено»; не путать с блоком «Вложения» (реальные файлы) — это ОТДЕЛЬНЫЙ учёт, как в бумажной форме.
|
||||
- Табличная часть «Смета» (`Costs`) — список групп (разделов работ), внутри каждой свои позиции; название группы необязательно. Сумма по позиции, по группе и общий итог считаются на лету (`qty × rate`, см. `cost.ts`), не хранятся в структуре — правка количества/цены не может их рассинхронизировать. `CostTotal` дублируется числовой колонкой в SharePoint при сохранении — только для отчётов, форма её не читает обратно.
|
||||
- Обе табличные части сериализуются в JSON-колонки (`AnnexesJson`, `CostsJson`) — тот же приём, что в `TmcTransfer` (`ItemsJson`).
|
||||
- Табличная часть «Смета» (`Costs`) — список групп (разделов работ), внутри каждой свои позиции; название группы необязательно. Сумма по позиции, по группе и общий итог считаются на лету (`qty × rate`, см. `cost.ts`), не хранятся в структуре — правка количества/цены не может их рассинхронизировать. `EstimateTotal` дублируется числовой колонкой в SharePoint при сохранении — только для отчётов, форма её не читает обратно.
|
||||
- Обе табличные части сериализуются в JSON-колонки (`AnnexesJson`, `EstimateJson`) — тот же приём, что в `TmcTransfer` (`ItemsJson`).
|
||||
- Продолжительность работ под датами «начало/окончание» — производная величина (считается на лету), в SharePoint не пишется.
|
||||
- Фазы исполнения нет: `saveServiceRequest` пишет маршрут с пустым списком исполнителей.
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ const SELECT_FIELDS = [
|
||||
'EstimatedFinishDate',
|
||||
'GeneralRemarks',
|
||||
'AnnexesJson',
|
||||
'CostsJson',
|
||||
'EstimateJson',
|
||||
'RequestStatus',
|
||||
'RequestUniqueCode'
|
||||
];
|
||||
@@ -94,7 +94,7 @@ export async function loadServiceRequest(itemId: number, listId?: string): Promi
|
||||
EstimatedFinishDate: toDateInput(item.EstimatedFinishDate),
|
||||
GeneralRemarks: (item.GeneralRemarks as string) || '',
|
||||
Annexes: parseRows<IAnnexRow>(item.AnnexesJson),
|
||||
Costs: parseRows<ICostGroup>(item.CostsJson)
|
||||
Costs: parseRows<ICostGroup>(item.EstimateJson)
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -80,7 +80,7 @@ export const CONTRACT_ACTION_OPTIONS: ISelectOption[] = [
|
||||
* Данные формы «Заявка на услуги» (бумажный аналог — Service Requisition Form
|
||||
* ПТО). Ключи = internalName колонок SP-списка «Заявка на услуги — данные».
|
||||
* Табличные части (Annexes / Costs) в колонки не разворачиваются, а
|
||||
* сериализуются в JSON-колонки AnnexesJson / CostsJson (см. submit.ts / load.ts).
|
||||
* сериализуются в JSON-колонки AnnexesJson / EstimateJson (см. submit.ts / load.ts).
|
||||
*/
|
||||
export interface IFormData {
|
||||
// --- Заявитель ---
|
||||
@@ -132,7 +132,7 @@ export interface IFormData {
|
||||
// --- Табличные части ---
|
||||
/** Приложения к заявке (сериализуются в AnnexesJson). */
|
||||
Annexes: IAnnexRow[];
|
||||
/** Сметная стоимость по группам (сериализуется в CostsJson). */
|
||||
/** Сметная стоимость по группам (сериализуется в EstimateJson). */
|
||||
Costs: ICostGroup[];
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
{ "internalName": "GeneralRemarks", "title": "Общие замечания", "type": "Note" },
|
||||
|
||||
{ "internalName": "AnnexesJson", "title": "Приложения (JSON)", "type": "Note" },
|
||||
{ "internalName": "CostsJson", "title": "Сметная стоимость (JSON)", "type": "Note" },
|
||||
{ "internalName": "CostTotal", "title": "Итого без НДС", "type": "Number", "decimals": 2 }
|
||||
{ "internalName": "EstimateJson", "title": "Сметная стоимость (JSON)", "type": "Note" },
|
||||
{ "internalName": "EstimateTotal", "title": "Итого без НДС", "type": "Number", "decimals": 2 }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ const CostGroup: React.FC<IGroupProps> = ({
|
||||
* Сметная стоимость услуг-работ по разделам (группам). Сумма по позиции,
|
||||
* по группе и общий итог — все производные (qty × цена), считаются на лету
|
||||
* и НЕ хранятся построчно (см. cost.ts): правка количества/цены не может
|
||||
* рассинхронизировать сумму. CostTotal в SharePoint дублируется отдельной
|
||||
* рассинхронизировать сумму. EstimateTotal в SharePoint дублируется отдельной
|
||||
* числовой колонкой при сохранении (см. submit.ts) — только для отчётов,
|
||||
* форма её сама не читает.
|
||||
*/
|
||||
|
||||
@@ -33,12 +33,12 @@ function buildItem(data: IFormData, status: string): Record<string, unknown> {
|
||||
});
|
||||
|
||||
item.AnnexesJson = data.Annexes.length > 0 ? JSON.stringify(data.Annexes) : null;
|
||||
item.CostsJson = data.Costs.length > 0 ? JSON.stringify(data.Costs) : null;
|
||||
item.EstimateJson = data.Costs.length > 0 ? JSON.stringify(data.Costs) : null;
|
||||
// Итог сметы дублируем числовой колонкой намеренно: в самой форме он считается
|
||||
// на лету (см. cost.ts), но представлениям SharePoint и отчётам нужна сумма
|
||||
// без разбора JSON — иначе любой отчёт по заявкам пришлось бы писать кодом.
|
||||
const total = costTotal(data.Costs);
|
||||
item.CostTotal = total > 0 ? total : null;
|
||||
item.EstimateTotal = total > 0 ? total : null;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user