- Updated "teknisk_beskrivning_flutter.md" to streamline content and remove outdated sections, focusing on architecture, environment, and recent technical additions. - Enhanced "migrering-MSI.md" with post-migration updates and clarifications for target audience. - Revised "produktlansering.md" to serve as a release checklist, ensuring it complements existing documentation without duplication. Co-authored-by: Copilot <copilot@github.com>
11 KiB
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ödunderFastfoodbröd. -
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 irecipe-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.tsutökat medFileInterceptor,@HttpCode(200)Dockerfileuppdaterad:apk add tesseract-ocr tesseract-ocr-data-swe tesseract-ocr-data-eng
2. imageUrl i quick-import-svaret ✅
imageUrl?: stringtillagd iParsedRecipe-interfacet (base.parser.ts)- ICA-parsern extraherar nu
recipe.image(string/array/objekt-varianter) QuickImportResultutökad medimageUrl?,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återapplication/octet-streambackend/src/receipt-parsing/receipt-parsing.module.ts- Registrerad i
app.module.ts
4. Health-endpoint ✅
GET /api/health→{status: "ok"}inline iapp.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 returneratimageUrl)IMPORTER_SERVICE_URLenv-variabel med fallbackhttp://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()ochenrichWithAiCategories()behålls (DB-krav)RECEIPT_IMPORT_MODEL-konstanten flyttad tillai.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, dockerfilebackend/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-apifårdepends_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 (
downloadAndOptimizeImagevidRecipesService.create()) matchProducts()ochenrichWithAiCategories()stannar i recipe-app (DB-krav)
Fas 1 — Utöka microservice-importer
Steg 1–3 ä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 5–7 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 5–7 ä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
POST /api/quick-import(recipe-app backend) med ICA-URL → samma svar som idagPOST /api/quick-importmed PDF-fil → samma svarPOST /api/recipes/parse-markdownmed markdown → ingredienser med produkt-ID:nPOST /api/receipt-importmed kvittobild → matchade items med DB-produkt-ID:n- Autentisering fungerar (hanteras av recipe-app backend som tidigare)
docker compose upstartar 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-importsplittad: AI-del → microservice, produktmatchning + DB → recipe-app backend