Add comprehensive documentation for Flutter frontend migration and backend review
Test Suite / test (24.15.0) (push) Has been cancelled

- Introduced user guide for Flutter frontend in README.md, detailing user flows and recent improvements.
- Created next steps roadmap for Flutter migration in next_steps_flutter.md, outlining current tasks and priorities.
- Developed technical description for Flutter frontend in teknisk_beskrivning_flutter.md, covering architecture and security status.
- Removed outdated migration documentation for Prisma P3009 and added recovery steps for failed migrations in migrering-MSI.md.
- Established a release checklist for product launches in produktlansering.md, ensuring security and stability measures are met.
- Formulated a systematic backend review and optimization plan in review_backend.md, focusing on reducing complexity and improving performance.
This commit is contained in:
Nils-Johan Gynther
2026-05-10 00:28:59 +02:00
parent 1709bb1dad
commit ca8987d9e4
14 changed files with 10 additions and 10 deletions
+266
View File
@@ -0,0 +1,266 @@
This file has been removed as all relevant information has been migrated.
# Prisma P3009 recovery (MySQL, migrationer)
**Problem:**
Prisma migrationer kan fastna i failed state (P3009) om en migration körts med fel SQL-citering (t.ex. "User" istället för `User` i MySQL) eller om deploy avbryts mitt i en migrering.
**Symptom:**
```
migrate found failed migrations in the target database, new migrations will not be applied. The `20260506144000_add_ai_engine_enabled` migration ... failed
```
**Lösning/playbook:**
1. Rätta migrationsfilen så att den använder backticks (`) för tabell- och kolumnnamn (MySQL-stil).
2. Kör:
```bash
docker exec recipe-api sh -lc "cd /app && npx prisma migrate resolve --rolled-back 20260506144000_add_ai_engine_enabled --schema prisma/schema.prisma"
docker exec recipe-api sh -lc "cd /app && npx prisma migrate deploy --schema prisma/schema.prisma"
```
3. Om deploy klagar på duplicate column (dvs kolumnen finns redan):
```bash
docker exec recipe-api sh -lc "cd /app && npx prisma migrate resolve --applied 20260506144000_add_ai_engine_enabled --schema prisma/schema.prisma"
docker exec recipe-api sh -lc "cd /app && npx prisma migrate deploy --schema prisma/schema.prisma"
```
4. Verifiera status:
```bash
docker exec recipe-api sh -lc "cd /app && npx prisma migrate status --schema prisma/schema.prisma"
```
**Lessons learned:**
- Kontrollera alltid SQL-citering i migrationsfiler (MySQL kräver backticks, inte dubbla citattecken).
- Vid P3009: använd `migrate resolve` för att markera migrationen som rolled-back eller applied beroende på DB-läge.
- Kör alltid migrationskommandon i rätt container/miljö för att undvika env- och version-mismatch.
# Session 2026-05-06: Migreringar för user-scoped AI och premium
Denna session:
- Lade till `aiEngineEnabled` på User i Prisma-schema och migrerade databasen (manuell SQL vid behov).
- Implementerade endpoint och logik för admin att toggla AI per användare.
- Säkerställde att alla AI-funktioner är user-scoped och premiumstyrda.
- Lessons learned: Vid DB-connectivity-problem krävs ibland manuell migration och resolve (se driftsekvens i TEKNISK_BESKRIVNING.md).
Se även:
- [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md) för drift- och migreringsdetaljer.
# Migrering: Import-funktion → microservice-importer
## Status: ✅ GENOMFÖRD 2026-04-30
## Dokumentstatus (2026-05-03)
### Målgrupp
Detta dokument är för systemadministratörer och utvecklare som ansvarar för integrationen mellan recipe-app och microservice-importer.
### Tillägg efter genomförd migrering
- Kvittoparsningens regelbaserade tolkning har förbättrats för multipack och enheter.
- Brödrelaterade kategoriregler och contradiction guards har utökats för högre träffsäkerhet.
- Klientens kvittosession i Flutter är nu persistent utan att ändra backendkontrakt eller införa serverlagring av sessionen.
- Kategoriträdet i seed-data har utökats med `Korvbröd` under `Fastfoodbröd`.
- **PDF-fix (2026-05-03):** `pdf-parse` använder `require()` istället för ESM-import; `pdfjs-dist/legacy/build/pdf.js` är fallback vid parsningsfel — löser `DOMMatrix is not defined` i Node.js Alpine-miljö.
- **Felkods-forwarding (2026-05-03):** `receipt-import.service.ts` returnerar nu `ServiceUnavailableException` (503) vid 503/429 från importer-api istället för `BadRequestException` (400).
- **Reproducerbart bygge (2026-05-03):** `package-lock.json` spåras i git; Dockerfile för importer-api kör `npm ci`.
- **AI-optimering (2026-05-03):** `looksLikeReceiptProductLine()` filtrerar PDF-rader utan siffra innan Mistral-anrop — minskar onödiga API-anrop vid kvittoimport.
- **Scope:** quick-import, parse-markdown, receipt-import
- **Arkitektur:** Backend-till-backend — recipe-app NestJS-backend anropar microservice-importer internt via HTTP. Frontend ändras inte.
- **OCR:** Implementerat i microservice-importer (tesseract.js + Alpine apk-paket)
- **Infra:** `importer-api`-tjänst i `recipe-app/compose.yml`, port 3001 intern
- **Driftsatt:** 2026-04-30, alla containers Healthy
---
## Fas 1 — Utöka microservice-importer ✅
**1. OCR-stöd och multipart i quick-import** ✅
- `QuickImportService.importFromUpload()` tillagd — hanterar PDF (pdf-parse) och bild (tesseract.js)
- `quick-import.controller.ts` utökat med `FileInterceptor`, `@HttpCode(200)`
- `Dockerfile` uppdaterad: `apk add tesseract-ocr tesseract-ocr-data-swe tesseract-ocr-data-eng`
**2. `imageUrl` i quick-import-svaret** ✅
- `imageUrl?: string` tillagd i `ParsedRecipe`-interfacet (`base.parser.ts`)
- ICA-parsern extraherar nu `recipe.image` (string/array/objekt-varianter)
- `QuickImportResult` utökad med `imageUrl?`, `imageWarning?`, source `'image'`
- `normalizeImageUrl()` hanterar protokollrelativa URL:er (`//cdn.ica.se/...`)
**3. Ny `ReceiptParsingModule`** ✅
- `backend/src/receipt-parsing/receipt-parsing.service.ts` — Mistral AI-parsning av kvitto (bild/PDF)
- `backend/src/receipt-parsing/receipt-parsing.controller.ts` — `POST /api/receipt-import/parse`, `@HttpCode(200)`, tillåter `application/octet-stream`
- `backend/src/receipt-parsing/receipt-parsing.module.ts`
- Registrerad i `app.module.ts`
**4. Health-endpoint** ✅
- `GET /api/health` → `{status: "ok"}` inline i `app.module.ts`
**5. Bugfixar i document-service** ✅
- `document-service.module.ts`: korrigerade importvägar + klassnamn (`DocumentImportModule` → `DocumentServiceModule`)
- `services/document-import.service.ts`: parsersökväg `./parsers/` → `../parsers/`
- Borttagna dubbletter: `services/web-scraping.module.ts`, `services/document-service.module.ts`
---
## Fas 2 — Anpassa recipe-app backend ✅
**5. Refaktorera `QuickImportService`** ✅
- All lokal parsning (ICA, pdf-parse, tesseract) borttagen
- Delegerar URL-import: `POST importer-api:3001/api/quick-import` (JSON)
- Delegerar filuploading: `POST importer-api:3001/api/quick-import` (FormData, `new Uint8Array(file.buffer)`)
- `downloadAndOptimizeImage()` behålls lokalt (körs efter microservice returnerat `imageUrl`)
- `IMPORTER_SERVICE_URL` env-variabel med fallback `http://importer-api:3001`
**6. Refaktorera `ReceiptImportService`** ✅
- AI-parsning (Mistral, pdf-parse) borttagen ur recipe-app
- Delegerar till `POST importer-api:3001/api/receipt-import/parse` (FormData)
- `matchProducts()` och `enrichWithAiCategories()` behålls (DB-krav)
- `RECEIPT_IMPORT_MODEL`-konstanten flyttad till `ai.controller.ts` (lokal konstant)
**7. Refaktorera `RecipesService.parseMarkdown()`** ✅
- Delegerar markdown-parsning till `POST importer-api:3001/api/recipes/parse-markdown`
- Fallback till lokal `parseRecipeMarkdown()` vid driftavbrott
- Levenshtein-produktmatchning behålls lokalt
---
## Fas 3 — Infrastruktur ✅
**8. `importer-api` i `recipe-app/compose.yml`** ✅
- Build-context: `../microservice-importer`, dockerfile `backend/Dockerfile`
- Image: `recipe-importer-api:local`, `pull_policy: never`
- Nätverk: `recipe-internal` (ej exponerad externt)
- Env: `MISTRAL_API_KEY`, `PORT=3001`
- Healthcheck: `wget -qO- http://127.0.0.1:3001/api/health`
- `recipe-api` får `depends_on: importer-api: condition: service_healthy`
---
## Relevanta filer som ändrades
| Fil | Förändring |
|---|---|
| `microservice-importer/backend/src/web-scraping-service/parsers/base.parser.ts` | `imageUrl?` i `ParsedRecipe` |
| `microservice-importer/backend/src/web-scraping-service/parsers/ica.parser.ts` | Extraherar `recipe.image` |
| `microservice-importer/backend/src/web-scraping-service/services/quick-import.service.ts` | Omskriven: OCR, PDF, imageUrl, importFromUpload |
| `microservice-importer/backend/src/web-scraping-service/controllers/quick-import.controller.ts` | FileInterceptor, HttpCode(200) |
| `microservice-importer/backend/src/web-scraping-service/web-scraping.module.ts` | Fixade importvägar + klassnamn |
| `microservice-importer/backend/src/document-service/document-service.module.ts` | Fixade importvägar + klassnamn |
| `microservice-importer/backend/src/document-service/services/document-import.service.ts` | Fixad parsersökväg |
| `microservice-importer/backend/src/receipt-parsing/` | Ny modul (service, controller, module) |
| `microservice-importer/backend/src/app.module.ts` | ReceiptParsingModule + HealthController |
| `microservice-importer/backend/Dockerfile` | apk add tesseract-ocr |
| `recipe-app/backend/src/quick-import/quick-import.service.ts` | Delegerar till importer-api |
| `recipe-app/backend/src/receipt-import/receipt-import.service.ts` | AI-del delegeras, matchning behålls |
| `recipe-app/backend/src/recipes/recipes.service.ts` | parseMarkdown delegeras, matchning behålls |
| `recipe-app/backend/src/ai/ai.controller.ts` | RECEIPT_IMPORT_MODEL lokal konstant |
| `recipe-app/compose.yml` | importer-api-tjänst tillagd |
---
## Avgränsningar (oförändrade)
- **Frontend ändras inte** — samma proxy-routes, samma API-kontrakt
- **Auth stannar i recipe-app backend** — microservice-importer exponeras bara internt
- **Bildoptimering** behålls i recipe-app (`downloadAndOptimizeImage` vid `RecipesService.create()`)
- `matchProducts()` och `enrichWithAiCategories()` stannar i recipe-app (DB-krav)
---
## Fas 1 — Utöka microservice-importer
*Steg 13 är oberoende och kan utföras parallellt.*
**1. Lägg till OCR-stöd (tesseract.js)**
Ny `ImageParser` i `backend/src/web-scraping-service/parsers/`. Controllern
`quick-import.controller.ts` utökas att acceptera `multipart/form-data` för
bilder vid sidan av JSON-body för URL-anrop.
**2. Lägg till `imageUrl` i quick-import-svaret**
`quick-import.service.ts` returnerar idag `{ markdown, source }`. Komplettera
med `imageUrl?` (original-URL från skrapad sida).
**3. Ny `ReceiptParsingModule` stateless kvittoparsning**
Ny modul `backend/src/receipt-parsing/` med endpoint `POST /api/receipt-import/parse`.
- PDF → text via `pdf-parse`; bild → base64
- Anropar Mistral AI med kvitto-prompt
- Returnerar: `[{ rawName, quantity, unit, price, brand, origin }]`
- Ingen databaskoppling — rent stateless
---
## Fas 2 — Anpassa recipe-app backend
*Beror på Fas 1. Steg 57 kan utföras parallellt.*
**4. Lägg till `HttpModule` + `IMPORTER_SERVICE_URL`**
recipe-app backend registrerar NestJS:s `HttpModule` (axios-wrapper).
`IMPORTER_SERVICE_URL` sätts som env-variabel (`http://importer-api:3001` i Docker).
**5. Refaktorera `QuickImportService`**
Ta bort lokal ICA-parsning, pdf-parse och tesseract — anropa istället
microservice-importer `POST /api/quick-import` (eller `POST /api/document-import`
för PDF). `QuickImportModule` behåller sin controller och DTO (API-kontrakt oförändrat).
**6. Refaktorera `ReceiptImportService`**
- AI-parsning → delegeras till `POST $IMPORTER_URL/api/receipt-import/parse`
- Produktmatchning (Levenshtein mot `Product`, `ReceiptAlias`) — behålls i recipe-app (DB-krav)
- Slår ihop och returnerar samma svar som idag till frontend
**7. Refaktorera `RecipesService.parseMarkdown()`**
- Anropar `POST $IMPORTER_URL/api/recipes/parse-markdown` → `{ name, ingredients[], ... }`
- Kör befintlig Levenshtein-produktmatchning mot `Product`-tabellen i recipe-app
- Returnerar sammansatt svar — API-kontraktet mot frontend oförändrat
**8. Ta bort lokala parsningsberoenden**
Ta bort `pdf-parse`, `tesseract.js`, `node-fetch` etc. ur recipe-app backend
`package.json` när steg 57 är verifierade.
---
## Fas 3 — Infrastruktur
*Kan påbörjas parallellt med Fas 1.*
**9. Länka microservice-importer i recipe-app:s Docker Compose**
Lägg till `importer-api`-tjänst i `recipe-app/compose.yml` (byggs från
`../microservice-importer/backend`). Delar `recipe-network` med recipe-app
backend. Sätt `IMPORTER_SERVICE_URL=http://importer-api:3001` i recipe-app
backend-tjänstens env.
---
## Relevanta filer
| Fil | Förändring |
|---|---|
| `microservice-importer/backend/src/web-scraping-service/` | Ny ImageParser, imageUrl i svar |
| `microservice-importer/backend/src/` | Ny `receipt-parsing/` modul |
| `recipe-app/backend/src/quick-import/quick-import.service.ts` | Ersätt lokal parsning med HTTP-anrop |
| `recipe-app/backend/src/receipt-import/receipt-import.service.ts` | AI-del delegeras, matchning behålls |
| `recipe-app/backend/src/recipes/recipes.service.ts` | parseMarkdown delegeras, matchning behålls |
| `recipe-app/backend/src/app.module.ts` | Registrera HttpModule |
| `recipe-app/backend/package.json` | Ta bort pdf-parse, tesseract.js |
| `recipe-app/compose.yml` | Lägg till importer-api tjänst |
| `recipe-app/frontend/` | **Ändras inte** |
---
## Verifiering
1. `POST /api/quick-import` (recipe-app backend) med ICA-URL → samma svar som idag
2. `POST /api/quick-import` med PDF-fil → samma svar
3. `POST /api/recipes/parse-markdown` med markdown → ingredienser med produkt-ID:n
4. `POST /api/receipt-import` med kvittobild → matchade items med DB-produkt-ID:n
5. Autentisering fungerar (hanteras av recipe-app backend som tidigare)
6. `docker compose up` startar microservice-importer som intern tjänst
---
## Avgränsningar
- **Frontend ändras inte** — samma proxy-routes, samma API-kontrakt
- **Auth stannar i recipe-app backend** — microservice-importer exponeras bara internt på Docker-nätverket
- **Bildoptimering vid sparande** behålls i recipe-app (sker vid `RecipesService.create()`, inte vid import)
- `receipt-import` splittad: AI-del → microservice, produktmatchning + DB → recipe-app backend
## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR.
## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR.