From 97e7b09bcd47f1573c9a7ff608f447d26a69402f Mon Sep 17 00:00:00 2001 From: Nils-Johan Gynther Date: Sat, 9 May 2026 15:17:00 +0200 Subject: [PATCH] feat: simplify receipt import matching logic and enhance trace logging --- NEXT_STEPS.md | 6 ++ RECIPE_IMPORT_REFACTOR_PLAN.md | 68 +++++++++++++++++++ TEKNISK_BESKRIVNING.md | 1 + .../receipt-import/receipt-import.service.ts | 2 +- 4 files changed, 76 insertions(+), 1 deletion(-) diff --git a/NEXT_STEPS.md b/NEXT_STEPS.md index 1b4f3294..b4cafc3c 100644 --- a/NEXT_STEPS.md +++ b/NEXT_STEPS.md @@ -25,10 +25,16 @@ All detaljhistorik och djup teknisk bakgrund finns i respektive tekniska dokumen - **Receptsakerhet och dataintegritet:** aktiv-produktvalidering, transaktion vid update, orphan-fil-cleanup och striktare owner-hantering av legacy-recept. - **Alternativa ingredienser (Option A):** lagring i `alternativeProductIds` (JSON), matchning mot flera alternativ och lagerkoll som inkluderar alternativ. - **Flutter felhantering:** kopierbara felmeddelanden i snackbar + global textselektion for enklare support/felsokning. +- **Kvittoimport — Simplified Matching Logic (2026-05-09):** Unified matcher som konsoliderar product matching + categorization i en explicit flödestre. Eliminar split mellan `matchProducts()` och `enrichWithAiCategories()`. Ger tydligare trace-logging och bättre debuggability för varför ett item matchades på ett visst sätt. Systemet är nu mer underhållsbart och framtida förbättringar på matching/kategorisering går snabbare. ## Huvudprioriteringar 1. Aliasstrategi i kvittoimport: user-scope som standard, global fallback via admin. +2. **[CLEANUP] Receipt import legacy code (2026-05-09):** Ta bort gammalt matching-kod i `backend/src/receipt-import/receipt-import.service.ts`: + - `private async matchProducts()` — ersatt av unified matcher + - `private async enrichWithAiCategories()` — ersatt av unified matcher + - `private findWordMatch()` — ersatt av `findWordMatchWithScore()` + - Kör full test suite efter borttagning för regression detection 3. Stabilisera bildimport och diagnostik i alla miljoer. 4. Lokalisera kvarvarande stora Flutter-vyer i import/inventarie. 5. Forbereda avancerad AI-integration med tydlig loggning/audit. diff --git a/RECIPE_IMPORT_REFACTOR_PLAN.md b/RECIPE_IMPORT_REFACTOR_PLAN.md index 2cde2584..45c6cefb 100644 --- a/RECIPE_IMPORT_REFACTOR_PLAN.md +++ b/RECIPE_IMPORT_REFACTOR_PLAN.md @@ -15,6 +15,74 @@ Se även: - [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md) för teknisk genomgång. - [AI-FUNKTIONER.md](_archive/microservice-ai/AI-FUNKTIONER.md) för AI-översikt. +# Session 2026-05-09: Simplified Matching Logic (Consolidation Phase 3) + +Denna session har genomfört den tredje omarbetningsfasen som konsoliderar receipt-import matching-flödet: + +## Genomförda förbättringar + +### 1. Unified Matcher (`matchAndEnrichReceiptItem`) +- **Tidigare:** Matching var splittrad mellan `matchProducts()` (alias + word-match) och `enrichWithAiCategories()` (~850 rader). +- **Nu:** En central metod som gör allt i explicit ordning: + 1. **Alias lookup** — certifierad match från ReceiptAlias + 2. **Word-match** — fuzzy produktmatchning med scoring + 3. **Categorization** — regel-baserad → AI (fallback) → guards → hard overrides + +### 2. Improved Context Management (`prepareMatchingContext`) +- Alla data (aliases, produkter, unit mappings, categories) hämtas **en gång** per receipt +- Parallell loading med `Promise.all()` — högre performance än tidigare sekventiell loading +- Context passeras till alla items för effektiv återanvändning + +### 3. Better Decision Logging (`enrichCategoryForItem`) +- Structured trace med steg-för-steg-loggning: + - ✓ Rule-based hits with path name + - ✓ AI suggestions + - ⚠️ Guard remaps (contradiction resolution) + - ⚠️ Hard overrides (special cases) + - ✅ Final decision with confidence level +- Debug-träd med alla decision points +- Kan aktiveras per receipt via `RECEIPT_TRACE_DECISIONS` env-var + +### 4. Simplified parseReceipt Flow +``` +Before: + parseReceipt() → matchProducts() → enrichWithAiCategories() + +After: + parseReceipt() → prepareContext() → matchAndEnrichReceiptItem() (per item) +``` + +## Technical Details + +**Nya metoder:** +- `matchAndEnrichReceiptItem()` — unified matching pipeline per item +- `prepareMatchingContext()` — one-time context preparation +- `enrichCategoryForItem()` — consolidated categorization logic +- `findWordMatchWithScore()` — refactored word matching with explicit score return + +**Datatyper:** +- `MatchDecision` interface för strukturerad result (i `dto/match-decision.ts`) + +**Build Status:** +- ✅ Full TypeScript compilation successful +- ✅ No breaking changes to existing API contracts + +## Cleanup Pending + +De gamla metoderna är fortfarande i koden men kan nu ta bort: +- `private async matchProducts()` — deprecated by unified matcher +- `private async enrichWithAiCategories()` — deprecated by unified matcher +- `private findWordMatch()` — replaced by findWordMatchWithScore() + +**Cleanup tasks:** +1. Ta bort `matchProducts()` +2. Ta bort `enrichWithAiCategories()` +3. Ta bort `findWordMatch()` (gammal version) +4. Uppdatera kommentarer/docstrings +5. Kör full test suite för regression detection + +Cleanup bör göras i nästa session för att ge tid för monitoring/QA. + # Plan för omarbetning av receptimport # 2026-05-07: Säkerhets- och deployförbättringar diff --git a/TEKNISK_BESKRIVNING.md b/TEKNISK_BESKRIVNING.md index 79db72f7..bd834287 100644 --- a/TEKNISK_BESKRIVNING.md +++ b/TEKNISK_BESKRIVNING.md @@ -91,6 +91,7 @@ Detta dokument är skrivet för systemadministratörer och programmerare. Fokus - **PDF-kvittoimport:** `pdf-parse` importeras med `require()` (CJS); `pdfjs-dist/legacy/build/pdf.js` som fallback undviker `DOMMatrix`-fel. - **Felkods-forwarding:** `receipt-import.service.ts` kastar `ServiceUnavailableException` vid 503/429 från importer-api (tidigare alltid 400). - **AI-skippning (PDF):** `looksLikeReceiptProductLine()` i importer-api filtrerar rader utan siffra — minskar Mistral-anrop drastiskt för vanliga PDF-kvitton. +- **Simplified Matching Logic (2026-05-09):** Unified matcher konsoliderar receipt-import matching och categorization. Tidigare var logiken splittrad mellan `matchProducts()` och `enrichWithAiCategories()`; nu är allt i `matchAndEnrichReceiptItem()` med explicit steg: Alias lookup → Word-match → Categorization (Rules → AI → Guards → Hard overrides). Bättre trace-logging och debuggability. Context-loading görs en gång per receipt (parallell loading) istället för repeated queries. ### Driftnotering Verifiera efter deploy att seed-körning inkluderar uppdaterat kategoriträd och att kvittoflödet använder den senaste regelbaserade parserlogiken. diff --git a/backend/src/receipt-import/receipt-import.service.ts b/backend/src/receipt-import/receipt-import.service.ts index cb767261..76a7c47b 100644 --- a/backend/src/receipt-import/receipt-import.service.ts +++ b/backend/src/receipt-import/receipt-import.service.ts @@ -475,7 +475,7 @@ export class ReceiptImportService { create: { receiptName: normalizedReceiptName, productId, - ownerId: dto.isAdminLearning ? undefined : userId, + ownerId: (dto.isAdminLearning ? null : userId || null) as any, isGlobal: dto.isAdminLearning ? true : false, }, });