Added detailed section about harmonization of import fields between receipt-import, flyer-import, and inventory table. Includes key changes, benefits, and technical details about TypeScript type safety and backward compatibility. Resolves migration issues via prisma migrate resolve.
6.7 KiB
Teknisk beskrivning av Microservice Importer
Dokumentstatus (2026-05-12)
Detta dokument riktar sig till utvecklare och driftansvariga för microservice-importer. Det beskriver arkitektur, drift och tekniska beslut för den interna importtjänsten.
Roll och ansvar
importer-api är en stateless intern tjänst för recipe-app. Den hanterar URL-skrapning, OCR, PDF-parsning, markdown-parsning och AI-kvittoparsning utan databas eller användarsessioner.
Arkitektur
Körmiljö
- NestJS 11
- TypeScript 5
- Node.js 22-alpine
- Port
3001internt - Exponeras bara på
recipe-internal-nätverket
Moduler
src/
├── app.module.ts # Root module + HealthController (GET /api/health)
├── main.ts
├── common/
│ ├── filters/global-exception.filter.ts
│ └── utils/normalize-name.ts
├── web-scraping-service/
│ ├── web-scraping.module.ts
│ ├── controllers/quick-import.controller.ts # POST /api/quick-import
│ ├── services/quick-import.service.ts # Scraping, OCR, PDF
│ └── parsers/
│ ├── base.parser.ts # ParsedRecipe interface
│ ├── ica.parser.ts # ICA.se JSON-LD + imageUrl
│ └── generic.parser.ts
├── receipt-parsing/
│ ├── receipt-parsing.module.ts
│ ├── receipt-parsing.controller.ts # POST /api/receipt-import/parse
│ └── receipt-parsing.service.ts
├── document-service/
│ ├── document-service.module.ts
│ ├── controllers/document-import.controller.ts
│ ├── services/document-import.service.ts
│ └── parsers/
│ ├── document.parser.ts
│ └── pdf.parser.ts
└── recipes/
├── recipes.module.ts
├── recipes.controller.ts # POST /api/recipes/parse-markdown
├── recipes.service.ts
└── dto/parse-markdown.dto.ts
Endpoints
| Endpoint | Funktion |
|---|---|
POST /api/quick-import |
URL-skrapning, bild-OCR och PDF-import |
POST /api/recipes/parse-markdown |
Markdown till strukturerat recept utan databas |
POST /api/receipt-import/parse |
Kvittobild/PDF till ParsedReceiptItem[] via Mistral AI |
GET /api/health |
Hälsokontroll för Docker healthcheck |
Kvittoparsning
Modell och pipeline
- Vision-input använder
mistral-small-2603 - PDF-flödet kör
pdf-parseellerpdfjs-dist/legacy/build/pdf.jssom fallback - Regelbaserad parsning körs före AI när det är möjligt
looksLikeReceiptProductLine()filtrerar bort rader utan siffra så att AI bara används för sannolika produktrader
Mängd- och enhetsregler
Följande regler är inbyggda i kvitto-prompten:
| Typ | Regel | Exempel |
|---|---|---|
| Lösvikt | quantity = faktisk vikt, unit = kg/g |
BLANDFÄRS 20% 0.997 kg |
| Förpackad vara med storlek i namn | quantity = antal förpackningar, unit = förp |
MJÖLK 1,5L × 3 |
| Multipack | quantity=1, unit=förp |
BACON 3X120G |
| Förpackat innehåll | quantity = antal förpackningar, unit = förp |
BRIOCHE SESAM × 2 |
| Lösa styckvaror | quantity = antal, unit = st |
BANAN × 1 |
Tillåtna enheter: st, kg, g, l, dl, cl, ml, förp, pak, burk, flaska.
Retry och stabilitet
- Mistral 429/503 backas av med
3000 * attemptms - PDF-flödet använder fallback för CJS- och Node Alpine-kompatibilitet
GlobalExceptionFilterger konsekventa felobjekt
Deployment
importer-api byggs och startas via recipe-app/compose.yml och inte via egen compose-fil.
Serverlayout
/opt/containers/
microservice-importer/
recipe-app/
compose.yml
deploy.sh
Driftsekvens
cd /opt/containers/microservice-importer && git pull
cd /opt/containers/recipe-app && git pull && ./deploy.sh
Hälsokontroll
docker exec importer-api wget -qO- http://localhost:3001/api/health
Tekniska detaljer
Byggberoenden
pdf-parsetesseract.js@mistralai/mistralaimulter2.1.1
Versionsnotering
- NestJS-paket är uppgraderade till 11-serien för att ta bort sårbarheter i beroendekedjan.
- Nest CLI 11 kräver Node.js 20.11+ i CI- och byggmiljöer.
Alpine-paket
tesseract-ocrtesseract-ocr-data-swetesseract-ocr-data-eng
Viktiga tekniska beslut
- Tjänsten är stateless och saknar databaskonfiguration
- Importer exponeras aldrig externt, bara internt via Docker-nätverket
- Host-port 3001 är upptagen av
wettyoch får därför inte användas av tjänsten
Parser-arkitektur
Dokument-parsers
Abstrakt bas DocumentParser används för dokumenttypsspecifik parsing.
PDF Parser
pdf.parser.ts hanterar textbaserade PDFs. Skannade PDFs varnas och kan falla tillbaka på OCR-vägen.
Webb-parsers
ica.parser.tsprioriterar JSON-LD och extraherarimageUrlgeneric.parser.tsär fallback för webbplatser utan specialparser
Framtida utbyggnader
- Fler webbplats-parsers som Arla, Tasteline och Köket.se
- Word/import av
.docx - Swagger/OpenAPI-dokumentation
- Caching av skrapade sidor om belastningen mot externa webbplatser blir ett problem
Quality-gates (npm scripts + CI)
Tillagda scripts i backend/package.json:
| Script | Kommando |
|---|---|
typecheck |
tsc --noEmit |
audit:high |
npm audit --audit-level=high |
quality:ci |
Kedja: typecheck → build → audit |
CI-workflow (.github/workflows/test.yml) uppdaterad (2026-05-12):
- Bytte
npm installtillnpm ciför reproducerbara byggen. - Ersatte Prisma- och test-steg (saknas i projektet) med:
typecheck→build→audit:high. - Tog bort
continue-on-errorpå build-steget — pipeline fångar nu verkliga fel. npm audit --audit-level=highrapporterar 0 sårbarheter.
Harmonisering av importfält (2026-05-24) Mål: Skapa konsistens mellan kvitto-import, flyer-import och inventory-tabellen Nyckeländringar: ParsedReceiptItem fick categoryId för kategorisättning FlyerImportItem fick origin som mappas från signals.originCountries[0] originCountries array-stöd lades till i inventory för framtida användning Fördelar: Minskat felrisk, enklare underhåll, bättre integration Tekniska detaljer: Typ-säkra ändringar med korrekta TypeScript-typer Bakåtkompatibla ändringar Löst migrationsproblem via prisma migrate resolve