feat: implement alias strategy for receipt import with matchedVia tracking
Test Suite / test (24.15.0) (push) Has been cancelled

This commit is contained in:
Nils-Johan Gynther
2026-05-07 14:15:45 +02:00
parent d92272e554
commit 73309cb110
3 changed files with 58 additions and 7 deletions
+32 -3
View File
@@ -146,14 +146,36 @@ sker på remote server. Säkerställ att inga absoluta Windows-sökvägar anv
---
## Nyheter och förbättringar (2026-05-02)
## Nyheter och förbättringar (2026-05-07)
- **Alias-strategi och matchedVia:**
- Backend: `ParsedReceiptItem` har fått fältet `matchedVia: 'alias' | 'wordmatch' | 'ai' | 'none'` som sätts i matchningslogiken och returneras till klienten.
- Flutter: matchedVia visas som badge i UI (Alias/Ordmatch/AI-kategori). Alias-lärande är öppet för alla användare (user-alias), admins kan spara globala alias.
- Användare kan se och radera sina alias på profilsidan. Admin-panelen visar produkt-ID och tydligare radstruktur.
- Prioritering: Egna alias (ownerId=userId) används före globala alias (isGlobal=true), därefter ordmatchning och sist AI.
- Tester: 3 nya tester för matchedVia i backend, totalt 66 tester gröna.
- **Inventory user-scope och IDOR-skydd:** InventoryItem-modellen har fått userId, migration har backfillat data, och alla endpoints kräver nu CurrentUser. Service och controller är uppdaterade, och tester för IDOR-skydd är på plats.
- **.gitignore och deploy-hygien:** backend/dist och backend/tsconfig.tsbuildinfo är nu ignorerade och ej längre spårade. .env och .env.* ignoreras, .env.example är komplett.
- **CI/CD-härdning:** npm audit och prisma validate körs i pipeline. Testsviten (63 tester) och build måste passera.
- **CI/CD-härdning:** npm audit och prisma validate körs i pipeline. Testsviten (66 tester) och build måste passera.
### Ny databasarkitektur: user-scoped produkter
### Alias-strategi och matchedVia (detaljer)
- **Datamodell:**
- `ReceiptAlias` har fälten `ownerId` (user-alias), `isGlobal` (global alias) och prioriteras i matchningslogik.
- `matchedVia` sätts i backend och skickas till Flutter.
- **UI-flöde:**
- Vid kvittoimport visas badge för matchkälla.
- "Spara som alias" är tillgängligt för alla användare (sparar user-alias), admins kan spara globalt.
- Profilsidan har en alias-lista där användaren kan radera egna alias.
- Admin-panelen visar alla globala alias, produktnamn och produkt-ID.
- **Prioriteringsordning:**
1. Egna alias (ownerId=userId)
2. Globala alias (isGlobal=true)
3. Ordmatchning
4. AI-kategori
Produkttabellen är omgjord till ett fullständigt user-scope-modell. Beslutet grundar sig på att en global produktkatalog skapade falska matchningar i kvittoimport för nya användare (produkter "hittades" fast användaren aldrig lagt till dem).
@@ -192,6 +214,7 @@ Nya noder sedan 2026-05-01:
| L3 under Allergi mejeri | Matfett |
| L3 under Allergi mejeri | Allergi matlagning |
### Regelbaserad kategoridetektion (`ruleBasedCategorySuggestion`)
Funktionen i `receipt-import.service.ts` matchar kvittonamn mot nyckelord och returnerar rätt kategori direkt — utan AI-anrop. Täcker:
@@ -203,7 +226,13 @@ Funktionen i `receipt-import.service.ts` matchar kvittonamn mot nyckelord och re
`AiService.suggestCategory()` remappar `low`/`medium`-konfidenspoäng till L1-föräldern istället för att returnera ett potentiellt fel L2/L3. Loggning sker via NestJS Logger.
### Förbättrad produktmatchning
### Förbättrad produktmatchning och alias
`matchProducts()` i `receipt-import.service.ts`:
- Returnerar nu även `matchedVia` för varje rad: 'alias', 'wordmatch', 'ai' eller 'none'.
- Alias prioriteras enligt ovan.
- Flutter visar badge och styr alias-lärande utifrån matchedVia.
`findWordMatch()` i `receipt-import.service.ts`:
- **Diakritiksnormalisering** — `normalizeToken()` konverterar å→a, ä→a, ö→o före jämförelse. Löser t.ex. `gradde` == `grädde`.