diff --git a/backend/src/receipt-import/receipt-import.service.ts b/backend/src/receipt-import/receipt-import.service.ts index c19eb569..ea8cfa30 100644 --- a/backend/src/receipt-import/receipt-import.service.ts +++ b/backend/src/receipt-import/receipt-import.service.ts @@ -45,6 +45,21 @@ function normalizeForRules(value: string): string { .trim(); } +function hasPorkLikeSignal(normalized: string): boolean { + return ( + normalized.includes('bacon') || + normalized.includes('bacn') || + normalized.includes('baco') || + /\bbac[a-z0-9]{1,5}\b/.test(normalized) || + /\bsidflask\b/.test(normalized) || + /\bpancetta\b/.test(normalized) || + /\bflask\b/.test(normalized) || + /\bflaskfile\b/.test(normalized) || + /\bkarr[eé]\b/.test(normalized) || + /\bkotlett\b/.test(normalized) + ); +} + @Injectable() export class ReceiptImportService { private readonly logger = new Logger(ReceiptImportService.name); @@ -378,12 +393,24 @@ export class ReceiptImportService { } const normalized = normalizeForRules(signalText); + return hasPorkLikeSignal(normalized); + } + + private resolvePorkCategory( + categories: Awaited>, + ) { return ( - /\bbacon\b/.test(normalized) || - /\bbacn\b/.test(normalized) || - /\bbaco\b/.test(normalized) || - /\bsidflask\b/.test(normalized) || - /\bpancetta\b/.test(normalized) + categories.find( + (c) => + c.name.toLowerCase() === 'fläsk' && + c.path.toLowerCase().startsWith('kött, chark & fågel > kött > '), + ) || + categories.find( + (c) => + c.name.toLowerCase() === 'kött' && + c.path.toLowerCase() === 'kött, chark & fågel > kött', + ) || + categories.find((c) => c.path.toLowerCase() === 'kött, chark & fågel') ); } @@ -393,22 +420,15 @@ export class ReceiptImportService { categories: Awaited>, ): CategorySuggestion { const normalized = normalizeForRules(signalText); - const hasBaconLikeSignal = - /\bbacon\b/.test(normalized) || - /\bbacn\b/.test(normalized) || - /\bbaco\b/.test(normalized) || - /\bbac[a-z]{1,3}\b/.test(normalized) || - /\bsidflask\b/.test(normalized) || - /\bpancetta\b/.test(normalized); + const hasBaconLikeSignal = hasPorkLikeSignal(normalized); if (!hasBaconLikeSignal) return suggestion; - const l3Pork = categories.find( - (c) => - c.name.toLowerCase() === 'fläsk' && - c.path.toLowerCase().startsWith('kött, chark & fågel > kött > '), - ); - if (!l3Pork) return suggestion; + const l3Pork = this.resolvePorkCategory(categories); + if (!l3Pork) { + this.logger.warn(`Hard-override: pork signal hittad men ingen köttkategori kunde hittas för "${signalText}"`); + return suggestion; + } if (suggestion.categoryId === l3Pork.id) return suggestion; @@ -458,22 +478,10 @@ export class ReceiptImportService { }; // ── Regel: Kött/chark (bacon/fläsk m.m.) ──────────────────────────── - const hasPorkSignal = - /\bbacon\b/.test(normalized) || - /\bbacn\b/.test(normalized) || - /\bbaco\b/.test(normalized) || - /\bsidflask\b/.test(normalized) || - /\bpancetta\b/.test(normalized) || - /\bflask\b/.test(normalized) || - /\bflaskfile\b/.test(normalized) || - /\bkarr[eé]\b/.test(normalized) || - /\bkotlett\b/.test(normalized); + const hasPorkSignal = hasPorkLikeSignal(normalized); if (hasPorkSignal) { - const l3Pork = findCategory({ - name: 'fläsk', - startsWith: 'kött, chark & fågel > kött > ', - }); + const l3Pork = this.resolvePorkCategory(categories); const hit = toSuggestion(l3Pork, 'high'); if (hit) return hit; } @@ -797,16 +805,7 @@ export class ReceiptImportService { categories: Awaited>, ): CategorySuggestion { const normalized = normalizeForRules(rawName); - const hasPorkSignal = - /\bbacon\b/.test(normalized) || - /\bbacn\b/.test(normalized) || - /\bbaco\b/.test(normalized) || - /\bsidflask\b/.test(normalized) || - /\bpancetta\b/.test(normalized) || - /\bflask\b/.test(normalized) || - /\bflaskfile\b/.test(normalized) || - /\bkarr[eé]\b/.test(normalized) || - /\bkotlett\b/.test(normalized); + const hasPorkSignal = hasPorkLikeSignal(normalized); if (hasPorkSignal) { const aiPath = suggestion.path.toLowerCase(); @@ -815,11 +814,7 @@ export class ReceiptImportService { if (!isClearlyWrongBranch) return suggestion; - const l3Pork = categories.find( - (c) => - c.name.toLowerCase() === 'fläsk' && - c.path.toLowerCase().startsWith('kött, chark & fågel > kött > '), - ); + const l3Pork = this.resolvePorkCategory(categories); if (!l3Pork) return suggestion; this.logger.log(