feat(migration): enforce ownerId requirement in Product table
- Removed all products without an owner to maintain data integrity. - Updated ownerId column to be non-nullable. - Modified foreign key constraint for ownerId to use ON DELETE CASCADE.
This commit is contained in:
@@ -15,6 +15,66 @@ sker på remote server. Säkerställ att inga absoluta Windows-sökvägar anv
|
||||
|
||||
---
|
||||
|
||||
## Nyheter och förbättringar (2026-05-02)
|
||||
|
||||
### Ny databasarkitektur: user-scoped produkter
|
||||
|
||||
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).
|
||||
|
||||
**Vad som ändrades:**
|
||||
|
||||
| Komponent | Förändring |
|
||||
|---|---|
|
||||
| `Product.ownerId` | `Int?` → `Int` (obligatorisk, non-nullable) |
|
||||
| `Product.owner` | `onDelete: SetNull` → `onDelete: Cascade` |
|
||||
| `db/seeds/seed_all.sql` | Innehåller nu enbart kategorier — inga `INSERT INTO Product` |
|
||||
| Migration `20260502160000` | Raderar alla globala produkter (`ownerId IS NULL`), gör FK non-null |
|
||||
| `receipt-import.service.ts` | `matchProducts(items, userId)` filtrerar på `ownerId = userId` |
|
||||
| `receipt-import.controller.ts` | Extraherar `userId` från JWT och skickar till service |
|
||||
|
||||
**Flöde för nya användare:**
|
||||
1. Kvittoimport → AI/OCR parsar kvitto → inga produktmatcher (user har inga produkter ännu)
|
||||
2. Regelbaserad kategoridetektion + AI-kategorisering körs för alla rader
|
||||
3. Användaren bekräftar i Flutter → produkten skapas via `POST /products` med `ownerId = userId`
|
||||
4. Nästa kvittoimport med samma vara → alias/ordmatch hittar den user-ägda produkten
|
||||
|
||||
**Framtida mallar (planerat):** En mallhanterare i UI kan låta användare seeda sin produktkatalog från fördefinierade livsmedelsmallar utan att det kräver global data i databasen.
|
||||
|
||||
### Kategorisystem utökat
|
||||
|
||||
Nya noder sedan 2026-05-01:
|
||||
|
||||
| Nivå | Kategori |
|
||||
|---|---|
|
||||
| L2 under Bröd & Kakor | Kondis & fika |
|
||||
| L3 under Kondis & fika | Kaffebröd (wienerbröd, donuts, munkar, kanelbullar m.m.) |
|
||||
| L2 under Dryck | Te & choklad |
|
||||
| L3 under Te & choklad | Te (chai, vanilla chai, ceylon te m.m.) |
|
||||
| L3 under Allergi mejeri | Laktosfri mjölk |
|
||||
| L3 under Allergi mejeri | Filmjölk & Yoghurt |
|
||||
| L3 under Allergi mejeri | Kvarg & Cottage cheese |
|
||||
| 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:
|
||||
- **Te** — `te`, `tea`, `chai`, `tepas`, `tepak`
|
||||
- **Kaffebröd** — `wienerbrod`, `donut`, `munk`, `croissant`, `kanelbulle`, `bakelse`, `semla`, `dammsugare`, `kladdkaka`, `muffin`, `cupcake`, `chokladboll`
|
||||
- **Allergi mejeri** — kombinationer av mejeri-markörer + allergen/växtbaserade markörer
|
||||
|
||||
### AI-guardrail
|
||||
|
||||
`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
|
||||
|
||||
`findWordMatch()` i `receipt-import.service.ts`:
|
||||
- **Diakritiksnormalisering** — `normalizeToken()` konverterar å→a, ä→a, ö→o före jämförelse. Löser t.ex. `gradde` == `grädde`.
|
||||
- **Enstaka lång partiell matchning** — ett produktord på ≥5 tecken som är en delmatchning räcker nu som stark signal. Löser t.ex. "Vispgrädde 5dl" → produkt "grädde".
|
||||
|
||||
---
|
||||
|
||||
## Nyheter och förbättringar (2026-04-30)
|
||||
|
||||
- **Microservice-importer integrerad** — `importer-api` körs nu som intern Docker-tjänst i `recipe-app/compose.yml`. All URL-skrapning, OCR, PDF-parsning och AI-kvittoparsning delegeras dit. `recipe-api` behåller Levenshtein-matchning, produktdatabas och AI-kategorisering. Se [migrering-MSI.md](migrering-MSI.md) för fullständig lista över ändrade filer.
|
||||
|
||||
Reference in New Issue
Block a user