diff --git a/src/webparts/ctFormsPortal/forms/ct/components/utils/flowResult.test.ts b/src/webparts/ctFormsPortal/forms/ct/components/utils/flowResult.test.ts new file mode 100644 index 0000000..7bb07c4 --- /dev/null +++ b/src/webparts/ctFormsPortal/forms/ct/components/utils/flowResult.test.ts @@ -0,0 +1,48 @@ +import { mapFlowResult } from './flowResult'; + +describe('mapFlowResult (ответ потока разбора КП)', () => { + // СТ 367: в КП нет сертификатов, поток вернул sertificates: null → String(null) = «null», + // и в шаге 3 у всех поставщиков в «Сертификатах» стоял текст «null». + it('null в текстовых полях — пусто, а не строка «null»', () => { + const result = mapFlowResult({ + position: null, unit: null, conditions: null, deliveryType: null, + deadline: null, sertificates: null, supplier: null, supplierBIN: null, + }); + + expect(result).toEqual({}); + }); + + it('null в числах — не распознано (undefined), а не 0', () => { + const result = mapFlowResult({ price: null, cost: null, quantity: null }); + + expect(result).toEqual({}); + }); + + it('заполненные поля переносятся как есть', () => { + const result = mapFlowResult({ + position: 'Дюбель-гвоздь 6 x 40', + unit: 'шт.', + conditions: '40% предоплата, 60% перед отгрузкой', + deadline: '25-30 рабочих дней', + supplier: 'BuildCore Supply Ltd.', + price: '0.10', + cost: 1527.5, + quantity: 15275, + }); + + expect(result).toEqual({ + position: 'Дюбель-гвоздь 6 x 40', + unit: 'шт.', + conditions: '40% предоплата, 60% перед отгрузкой', + deadline: '25-30 рабочих дней', + supplier: 'BuildCore Supply Ltd.', + price: 0.1, + cost: 1527.5, + quantity: 15275, + }); + }); + + it('нечисловая цена — 0, как раньше', () => { + expect(mapFlowResult({ price: 'по запросу' }).price).toBe(0); + }); +}); diff --git a/src/webparts/ctFormsPortal/forms/ct/components/utils/flowResult.ts b/src/webparts/ctFormsPortal/forms/ct/components/utils/flowResult.ts new file mode 100644 index 0000000..a09cf9c --- /dev/null +++ b/src/webparts/ctFormsPortal/forms/ct/components/utils/flowResult.ts @@ -0,0 +1,29 @@ +import { FlowResult } from '../types/domain'; + +// Поток отдаёт null, когда в КП поля нет (например, сертификатов). String(null) давал строку «null», +// и она показывалась в шаге 3 и уходила в SP. null и undefined — «не распознано». +function optionalText(value: unknown): string | undefined { + return value !== undefined && value !== null ? String(value) : undefined; +} + +// Нечисловое значение (например, «по запросу») — 0, как и раньше. +function optionalNumber(value: unknown): number | undefined { + return value !== undefined && value !== null ? Number(value) || 0 : undefined; +} + +// Разбор ответа потока КП (JSON из responsev2.predictionOutput.text) — как в КПС (_mapFlowResult). +export function mapFlowResult(parsed: Record): FlowResult { + return { + position: optionalText(parsed.position), + unit: optionalText(parsed.unit), + conditions: optionalText(parsed.conditions), + deliveryType: optionalText(parsed.deliveryType), + deadline: optionalText(parsed.deadline), + sertificates: optionalText(parsed.sertificates), + cost: optionalNumber(parsed.cost), + price: optionalNumber(parsed.price), + quantity: optionalNumber(parsed.quantity), + supplier: optionalText(parsed.supplier), + supplierBIN: optionalText(parsed.supplierBIN), + }; +} diff --git a/src/webparts/ctFormsPortal/forms/ct/services/CtService.ts b/src/webparts/ctFormsPortal/forms/ct/services/CtService.ts index dafe497..536e5f4 100644 --- a/src/webparts/ctFormsPortal/forms/ct/services/CtService.ts +++ b/src/webparts/ctFormsPortal/forms/ct/services/CtService.ts @@ -33,6 +33,7 @@ import { import { CriteriaRecord, plainTextFromSp } from "../components/utils/criteria"; import { pickRowToNotify } from "../components/utils/approvalAccess"; import { buildPositionKeys } from "../components/utils/positionKey"; +import { mapFlowResult } from "../components/utils/flowResult"; import { NoOfferSupplierEntry, NoOfferSupplierRecord, @@ -1612,35 +1613,7 @@ export class CtService { } catch { return {}; } - return { - position: - parsed.position !== undefined ? String(parsed.position) : undefined, - unit: parsed.unit !== undefined ? String(parsed.unit) : undefined, - conditions: - parsed.conditions !== undefined ? String(parsed.conditions) : undefined, - deliveryType: - parsed.deliveryType !== undefined - ? String(parsed.deliveryType) - : undefined, - deadline: - parsed.deadline !== undefined ? String(parsed.deadline) : undefined, - sertificates: - parsed.sertificates !== undefined - ? String(parsed.sertificates) - : undefined, - cost: parsed.cost !== undefined ? Number(parsed.cost) || 0 : undefined, - price: parsed.price !== undefined ? Number(parsed.price) || 0 : undefined, - quantity: - parsed.quantity !== undefined - ? Number(parsed.quantity) || 0 - : undefined, - supplier: - parsed.supplier !== undefined ? String(parsed.supplier) : undefined, - supplierBIN: - parsed.supplierBIN !== undefined - ? String(parsed.supplierBIN) - : undefined, - }; + return mapFlowResult(parsed); } async loadOffersForPositions(positionSpIds: number[]): Promise<