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