chore(receipt-import): include quantity and package details in decision trace

This commit is contained in:
Nils-Johan Gynther
2026-05-02 23:12:24 +02:00
parent 5286db4385
commit b7d68afd58
@@ -60,6 +60,45 @@ function hasPorkLikeSignal(normalized: string): boolean {
);
}
function inferPackageDebugFromRawName(rawName: string): {
packageCount: number;
packQuantity: number | null;
packUnit: string | null;
} {
const normalized = rawName.toLowerCase();
// e.g. "3x120g", "2 x 1.5l"
const multiPack = /(\d+)\s*[x×]\s*(\d+(?:[\.,]\d+)?)\s*(ml|cl|dl|l|g|kg)\b/i.exec(normalized);
if (multiPack) {
const count = Number.parseInt(multiPack[1], 10);
const qty = Number.parseFloat(multiPack[2].replace(',', '.'));
const unit = multiPack[3].toLowerCase();
return {
packageCount: Number.isFinite(count) && count > 0 ? count : 1,
packQuantity: Number.isFinite(qty) ? qty : null,
packUnit: unit,
};
}
// e.g. "5dl", "1,5l"
const singlePack = /(\d+(?:[\.,]\d+)?)\s*(ml|cl|dl|l|g|kg)\b/i.exec(normalized);
if (singlePack) {
const qty = Number.parseFloat(singlePack[1].replace(',', '.'));
const unit = singlePack[2].toLowerCase();
return {
packageCount: 1,
packQuantity: Number.isFinite(qty) ? qty : null,
packUnit: unit,
};
}
return {
packageCount: 1,
packQuantity: null,
packUnit: null,
};
}
@Injectable()
export class ReceiptImportService {
private readonly logger = new Logger(ReceiptImportService.name);
@@ -281,7 +320,11 @@ export class ReceiptImportService {
if (traceEnabled) trace.push(msg);
};
pushTrace(`start raw="${item.rawName}" signal="${signalText || item.rawName}"`);
const pkg = inferPackageDebugFromRawName(item.rawName);
pushTrace(
`start raw="${item.rawName}" signal="${signalText || item.rawName}" parsedQuantity=${item.quantity ?? 'null'} parsedUnit=${item.unit ?? 'null'} packageCount=${pkg.packageCount} packQuantity=${pkg.packQuantity ?? 'null'} packUnit=${pkg.packUnit ?? 'null'}`,
);
pushTrace(
`match matchedProductId=${item.matchedProductId ?? 'null'} suggestedProductId=${item.suggestedProductId ?? 'null'}`,
);