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
+15 -3
View File
@@ -34,6 +34,12 @@ En fullstack-applikation för hantering av hemmavaror och recept. Håll koll på
Detta dokument är skrivet för användare och produktägare. Fokus är vad som fungerar i appen och vad som förbättrats i det dagliga flödet. Detta dokument är skrivet för användare och produktägare. Fokus är vad som fungerar i appen och vad som förbättrats i det dagliga flödet.
### Nytt sedan senaste sessionerna ### Nytt sedan senaste sessionerna
- **Alias-strategi för kvittoimport:**
- Backend och Flutter har nu stöd för användarspecifika alias (user-alias) och globala alias (admin).
- Varje rad i kvittoimporten visar nu en badge som anger hur matchningen skedde: **Alias**, **Ordmatch** eller **AI-kategori**.
- Alla användare kan spara egna alias direkt vid import ("Spara som alias"), admins kan spara globala alias.
- Ny profilsida: användare kan se och radera sina alias.
- Admin-panelen för alias visar nu produkt-ID och tydligare radstruktur.
- Kvittoimporten har blivit mer träffsäker för förpackningar och mängder (t.ex. rader med multipack och "2st"). - Kvittoimporten har blivit mer träffsäker för förpackningar och mängder (t.ex. rader med multipack och "2st").
- Kategorisering av brödrelaterade produkter har förbättrats så att färre varor hamnar fel. - Kategorisering av brödrelaterade produkter har förbättrats så att färre varor hamnar fel.
- Ny underkategori i kategoriträdet: `Bröd & Kakor > Bröd > Fastfoodbröd > Korvbröd`. - Ny underkategori i kategoriträdet: `Bröd & Kakor > Bröd > Fastfoodbröd > Korvbröd`.
@@ -43,9 +49,15 @@ Detta dokument är skrivet för användare och produktägare. Fokus är vad som
--- ---
## Funktioner ### Funktioner
### Inventorie (Hemmavaror) ### Kvittoimport och alias
- **Alias-badge:** Varje rad i kvittoimporten visar nu en badge som anger om matchningen skedde via Alias, Ordmatch eller AI-kategori.
- **Spara som alias:** Alla användare kan spara egna alias direkt vid import. Admins kan spara globala alias.
- **Alias-hantering:** Användare kan se och radera sina alias på profilsidan. Admins har en förbättrad panel med produkt-ID och tydligare radstruktur.
- **Prioritering:** Systemet prioriterar användarens egna alias före globala alias och ordmatchning.
### Inventarie (Hemmavaror)
- **Lägg till, redigera och ta bort varor** — hantera produkt, kvantitet, enhet, plats, märke och bäst före-datum - **Lägg till, redigera och ta bort varor** — hantera produkt, kvantitet, enhet, plats, märke och bäst före-datum
- **Filtrera och sortera** — efter plats (kyl, frys, skafferi), bäst före-datum, och namn (A–Ö) - **Filtrera och sortera** — efter plats (kyl, frys, skafferi), bäst före-datum, och namn (A–Ö)
- **Konsumera varor** — registrera förbrukad mängd med eventuell kommentar - **Konsumera varor** — registrera förbrukad mängd med eventuell kommentar
@@ -57,7 +69,7 @@ Detta dokument är skrivet för användare och produktägare. Fokus är vad som
- **Grupperat per kategori** — produkterna i baslagret visas grupperade under kategorirubrik - **Grupperat per kategori** — produkterna i baslagret visas grupperade under kategorirubrik
- **Lägg till och ta bort** — välj från produktlistan via sökbar dropdown, ta bort med ett klick - **Lägg till och ta bort** — välj från produktlistan via sökbar dropdown, ta bort med ett klick
--- ----
### 📌 Så använder du Inventarie och Baslager ### 📌 Så använder du Inventarie och Baslager
+11 -1
View File
@@ -296,7 +296,17 @@ Analysen blir en egen endpoint.
--- ---
## 6. Receptmodul
---
## 7. Alias-strategi och matchedVia (2026-05-07)
- Alias-strategin är nu fullt implementerad:
- Backend och Flutter stödjer user-alias och globala alias.
- matchedVia-badge visas i UI (Alias/Ordmatch/AI).
- Användare kan spara egna alias, admins kan spara globala.
- Profilsidan har alias-lista för användare, admin-panelen visar produkt-ID och radstruktur.
- Backend har 3 nya tester för matchedVia, totalt 66 tester gröna.
### Fil: `backend/src/recipes/recipes.module.ts` ### Fil: `backend/src/recipes/recipes.module.ts`
+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-02)
## Nyheter och förbättringar (2026-05-07) ## 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. - **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. - **.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). 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 | Matfett |
| L3 under Allergi mejeri | Allergi matlagning | | L3 under Allergi mejeri | Allergi matlagning |
### Regelbaserad kategoridetektion (`ruleBasedCategorySuggestion`) ### Regelbaserad kategoridetektion (`ruleBasedCategorySuggestion`)
Funktionen i `receipt-import.service.ts` matchar kvittonamn mot nyckelord och returnerar rätt kategori direkt — utan AI-anrop. Täcker: 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. `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`: `findWordMatch()` i `receipt-import.service.ts`:
- **Diakritiksnormalisering** — `normalizeToken()` konverterar å→a, ä→a, ö→o före jämförelse. Löser t.ex. `gradde` == `grädde`. - **Diakritiksnormalisering** — `normalizeToken()` konverterar å→a, ä→a, ö→o före jämförelse. Löser t.ex. `gradde` == `grädde`.