fix(ct): null из потока КП не превращается в строку «null»
Когда в КП нет поля (например, сертификатов), поток отдаёт null, а String(null) давал «null» — он показывался в «Сертификатах» шага 3 и сохранялся в «Критерии». Разбор ответа вынесен в mapFlowResult: null — «не распознано», как уже сделано в КПС и ОИД.
This commit is contained in:
@@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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<string, unknown>): 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),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
import { CriteriaRecord, plainTextFromSp } from "../components/utils/criteria";
|
import { CriteriaRecord, plainTextFromSp } from "../components/utils/criteria";
|
||||||
import { pickRowToNotify } from "../components/utils/approvalAccess";
|
import { pickRowToNotify } from "../components/utils/approvalAccess";
|
||||||
import { buildPositionKeys } from "../components/utils/positionKey";
|
import { buildPositionKeys } from "../components/utils/positionKey";
|
||||||
|
import { mapFlowResult } from "../components/utils/flowResult";
|
||||||
import {
|
import {
|
||||||
NoOfferSupplierEntry,
|
NoOfferSupplierEntry,
|
||||||
NoOfferSupplierRecord,
|
NoOfferSupplierRecord,
|
||||||
@@ -1612,35 +1613,7 @@ export class CtService {
|
|||||||
} catch {
|
} catch {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return {
|
return mapFlowResult(parsed);
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadOffersForPositions(positionSpIds: number[]): Promise<
|
async loadOffersForPositions(positionSpIds: number[]): Promise<
|
||||||
|
|||||||
Reference in New Issue
Block a user