# Teknisk beskrivning av Microservice Importer ## Dokumentstatus (2026-05-10) 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](../recipe-app). Den hanterar URL-skrapning, OCR, PDF-parsning, markdown-parsning och AI-kvittoparsning utan databas eller användarsessioner. ## Arkitektur ### Körmiljö - NestJS 10 - TypeScript 5 - Node.js 22-alpine - Port `3001` internt - Exponeras bara på `recipe-internal`-nätverket ### Moduler ```text 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-parse` eller `pdfjs-dist/legacy/build/pdf.js` som 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 * attempt` ms - PDF-flödet använder fallback för CJS- och Node Alpine-kompatibilitet - `GlobalExceptionFilter` ger konsekventa felobjekt ## Deployment `importer-api` byggs och startas via [recipe-app/compose.yml](../recipe-app/compose.yml) och inte via egen compose-fil. ### Serverlayout ```text /opt/containers/ microservice-importer/ recipe-app/ compose.yml deploy.sh ``` ### Driftsekvens ```bash cd /opt/containers/microservice-importer && git pull cd /opt/containers/recipe-app && git pull && ./deploy.sh ``` ### Hälsokontroll ```bash docker exec importer-api wget -qO- http://localhost:3001/api/health ``` ## Tekniska detaljer ### Byggberoenden - `pdf-parse` - `tesseract.js` - `@mistralai/mistralai` - `multer` ### Alpine-paket - `tesseract-ocr` - `tesseract-ocr-data-swe` - `tesseract-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 `wetty` och 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.ts` prioriterar JSON-LD och extraherar `imageUrl` - `generic.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 ## Referenser - [README.md](README.md) - [NEXT_STEPS.md](next_steps_MSImporter.md)