fix: update documentation status and enhance technical description for microservice importer
Test Suite / test (24.15.0) (push) Has been cancelled

This commit is contained in:
Nils-Johan Gynther
2026-05-11 16:41:20 +02:00
parent c639eae270
commit 4596b80408
3 changed files with 230 additions and 263 deletions
+28 -203
View File
@@ -1,218 +1,43 @@
# Microservice Importer
Intern import-tjänst (`importer-api`) för [recipe-app](../recipe-app). Hanterar URL-skrapning, OCR, PDF-parsning och AI-kvittoparsning utan databas. Körs som Docker-tjänst på det interna `recipe-internal`-nätverket exponeras ej externt.
Intern import-tjänst (`importer-api`) för [recipe-app](../recipe-app). Den hanterar URL-skrapning, OCR, PDF-parsning och AI-kvittoparsning utan databas. Tjänsten körs som Docker-tjänst på det interna `recipe-internal`-nätverket och exponeras inte externt.
## Dokumentstatus (2026-05-03)
## Dokumentstatus (2026-05-10)
### Målgrupp
Detta dokument är för systemadministratörer och utvecklare som driftar eller vidareutvecklar importtjänsten.
Det här dokumentet är skrivet för systemadministratörer och utvecklare som driftar eller vidareutvecklar importtjänsten. För arkitektur, drift och tekniska detaljer, se [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md). För roadmap och prioriteringar, se [next_steps_MSImporter.md](next_steps_MSImporter.md).
### Tillägg från senaste sessionerna
- Regelbaserad kvittotolkning har förbättrats för multipack, enheter och antaluttryck.
- Parserstödet för brödrelaterade produkter och guardrails mot felkategorisering har utökats.
- Integrationen med klienten för kvitto-session är fortfarande stateless i denna tjänst; ingen serverlagring av användarsession infördes.
- Kvittokategorisering: nya regler för pasta, grädde, ägg, juice, godis, och potatis samt justerad AI-guardrail.
- Testinfrastruktur: parametriserade enhetstester för kvittoimport (18 testfall) och CI/CD-pipeline med automatiserad testkörning på push.- **PDF-fix:** `pdf-parse` importeras nu med `require()` (CJS-kompatibilitet). `pdfjs-dist/legacy/build/pdf.js` används som fallback för att undvika `DOMMatrix is not defined` i Node.js-miljö.
- **Retry-förbättring:** Mistral 429/503 → väntar `3000 * attempt` ms innan nytt försök.
- **Reproducerbart bygge:** `package-lock.json` spåras i git; Dockerfile kör `npm ci`.
- **AI-skippning för icke-produktrader:** `looksLikeReceiptProductLine()` filtrerar PDF-rader utan siffra (header/footer/butiksinformation) — dessa skickas inte till Mistral.
## Viktigt!! Kod- och byggpraxis!
Säkerställ att inga absoluta Windows-sökvägar används i koden, för att stödja bygg och drift på Linux/Ubuntu
## Vad tjänsten gör
---
- Tar emot URL:er, filer och markdown för importflöden
- Skrapar receptsidor och extraherar `imageUrl` när det finns
- Kör OCR för bilder och skannade dokument
- Tolkar kvitton via Mistral AI
- Returnerar strukturerad data till recipe-app utan att lagra någon session eller databaspost
## Features
## Flöden
### Quick-import (`POST /api/quick-import`)
- **URL-skrapning** — ICA.se (JSON-LD) och generisk parser. Extraherar `imageUrl` från receptbild.
- **OCR (bild)** — tesseract.js, svenska+engelska. Returnerar `source: 'image'`.
- **PDF-parsning** — pdf-parse för digitala PDFs, OCR-fallback för skannade.
- **Multipart** — Tar emot antingen JSON-body (`{ url }`) eller FormData (`file`).
- `POST /api/quick-import` för URL-skrapning, bild-OCR och PDF-import
- `POST /api/recipes/parse-markdown` för markdown till strukturerat recept
- `POST /api/receipt-import/parse` för kvittobild eller PDF till `ParsedReceiptItem[]`
- `GET /api/health` för Docker healthcheck
### Parse-Markdown (`POST /api/recipes/parse-markdown`)
Tolkar Markdown-recept till strukturerat JSON utan databas.
## Viktigt
### Kvittoparsning (`POST /api/receipt-import/parse`)
- Bild (JPEG/PNG/WebP/HEIC/HEIF) eller PDF
- **Bild:** `mistral-small-2603` (vision-kapabel) med retry-logik (3 försök, `3000 * attempt` ms fördröjning vid 429/503)
- **PDF:** `pdf-parse` → fallback `pdfjs-dist/legacy` → regelbaserad parsning → AI enbart för rader med namntext + siffra
- Returnerar `ParsedReceiptItem[]` med fälten `rawName`, `quantity`, `unit`, `price`, `brand`, `origin`
- Inbyggda regler i AI-prompten styr tolkning av `quantity`/`unit` (se nedan)
- Inga absoluta Windows-sökvägar ska användas i kod eller scripts
- Tjänsten är stateless
- Ingen databas är konfigurerad i tjänsten
- Host-port 3001 används av `wetty` på servern och får därför inte exponeras av importtjänsten
### Health (`GET /api/health`)
Används av Docker-healthcheck i `recipe-app/compose.yml`. Returnerar `{ status: "ok" }`.
## Kort faktadel
---
## Miljövariabler
| Variabel | Beskrivning | Standardvärde |
|---|---|---|
| `MISTRAL_API_KEY` | API-nyckel för Mistral AI | (krävs för kvittoparsning) |
| `PORT` | HTTP-port | `3001` |
---
## Arkitektur
### Backend (NestJS 10, TypeScript 5, Node.js 22-alpine)
**Port:** 3001 (intern, ej exponerad till host)
```
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/ # Quick-import (URL + fil)
│ ├── 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/ # Kvittoparsning via Mistral AI
│ ├── receipt-parsing.module.ts
│ ├── receipt-parsing.controller.ts # POST /api/receipt-import/parse
│ └── receipt-parsing.service.ts
├── document-service/ # PDF-dokumentimport
│ ├── document-service.module.ts
│ ├── controllers/document-import.controller.ts
│ ├── services/document-import.service.ts
│ └── parsers/
│ ├── document.parser.ts
│ └── pdf.parser.ts
└── recipes/ # Markdown-tolkning
├── recipes.module.ts
├── recipes.controller.ts # POST /api/recipes/parse-markdown
├── recipes.service.ts
└── dto/parse-markdown.dto.ts
```
**Viktigt:** Backend har _INGEN_ databaskonfiguration — stateless service.
---
## Kvittoparsning — regler för quantity och unit
Följande regler är inbyggda i AI-prompten och styr hur Mistral tolkar mängd och enhet per produkt:
| Typ | Regel | Exempel |
|---|---|---|
| **Lösvikt** (kött, ost, frukt/grönt vägt i kassan) | `quantity` = faktisk vikt från kvittot, `unit` = `kg`/`g` | `BLANDFÄRS 20%` 0.997 kg → `quantity=0.997, unit="kg"` |
| **Förpackad vara med storlek i namn** (mejeri, dryck, konserver) | `quantity` = antal förpackningar, `unit` = `"förp"` | `MJÖLK 1,5L` × 3 → `quantity=3, unit="förp"` |
| **Multipack** (`NxYg`/`NxYml` i namn) | `quantity=1`, `unit="förp"` — räkna inte upp N | `BACON 3X120G``quantity=1, unit="förp"` |
| **Förpackat innehåll** (bröd, kex, chips) | `quantity` = antal förpackningar, `unit` = `"förp"` | `BRIOCHE SESAM` × 2 → `quantity=2, unit="förp"` |
| **Lösa styckvaror** (enstaka frukt/bröd per st) | `quantity` = antal, `unit` = `"st"` | `BANAN` × 1 → `quantity=1, unit="st"` |
Tillåtna enheter: `st`, `kg`, `g`, `l`, `dl`, `cl`, `ml`, `förp`, `pak`, `burk`, `flaska`
---
## Parser-arkitektur
### Dokument-parsers (`document-service/parsers/`)
Abstrakt bas `DocumentParser` som alla dokumenttyp-specifika parsers ärver från.
### PDF Parser (`pdf.parser.ts`)
Hanterar textbaserade PDFs via `pdf-parse`. Skannade PDFs varnas.
### Webb-parsers (`web-scraping-service/parsers/`)
Abstrakt bas `RecipeParser` med `canHandle(url)` + `parse(html)`. Implementationer:
- **`ica.parser.ts`** — ICA.se, prioriterar JSON-LD structured data, extraherar `imageUrl`
- **`generic.parser.ts`** — Fallback för alla webbplatser
---
## Deployment
`importer-api` byggs och startas via `recipe-app/compose.yml`**ej via sin egen compose-fil**.
**Serverstruktur:**
```
/opt/containers/
microservice-importer/ ← klonas separat, pullas vid deploy
recipe-app/
compose.yml ← definierar importer-api-tjänsten
deploy.sh ← kör docker compose build + up
```
**Deploy:**
```bash
# 1. Uppdatera importer (om ändringar gjorts)
cd /opt/containers/microservice-importer && git pull
# 2. Bygg och starta alla containers
cd /opt/containers/recipe-app && git pull && ./deploy.sh
```
**Loggar:**
```bash
docker logs importer-api -f
```
**Hälsokontroll:**
```bash
docker exec importer-api wget -qO- http://localhost:3001/api/health
# → {"status":"ok"}
```
**OBS:** Host-port 3001 används av `wetty` på servern. `importer-api` exponeras **aldrig** utanför Docker-nätverket — anropas via `http://importer-api:3001` från `recipe-api`.
---
## Tekniska detaljer
### Backend Stack
- **NestJS** 10 — REST API & modular architecture
- **TypeScript** 5 — Type safety
- **Node.js** 22-alpine — Runtime (Alpine Linux)
- **pdf-parse** — PDF text extraction
- **tesseract.js** — OCR (bild och skannade PDFs, svenska + engelska)
- **@mistralai/mistralai** — AI-kvittoparsning (`mistral-small-2603`)
- **multer** — Multipart file upload handling
- **Ingen databas** — Stateless service
### Systempaket (Alpine)
Installerade i Dockerfile runner-stage:
```
tesseract-ocr
tesseract-ocr-data-swe
tesseract-ocr-data-eng
```
### Error Handling
- Centraliserad `GlobalExceptionFilter` (svenska meddelanden)
- Konsistent JSON-responsformat: `{ statusCode, message, timestamp, path }`
- HTTP status codes: 200, 400, 503
---
## Framtida utbyggnader
- [x] PDF-import — textbaserad extraction
- [x] OCR för skannade bild-PDFs (tesseract.js + Alpine-paket)
- [x] Kvittoparsning via Mistral AI
- [x] ICA-receptbildsextraktion (`imageUrl` i `ParsedRecipe`)
- [ ] Fler webbplats-parsers (Arla, Tasteline, Köket.se)
- [ ] Word (.docx) import
- [ ] Swagger/OpenAPI-dokumentation
- [ ] Rate limiting / Caching
---
## Licens
MIT
---
- Runtime: Node.js 22-alpine
- Ramverk: NestJS 10 + TypeScript 5
- OCR: `tesseract.js`
- PDF: `pdf-parse` med `pdfjs-dist/legacy` fallback
- AI: `@mistralai/mistralai`
- Upload: `multer`
- Alpine-paket: `tesseract-ocr`, `tesseract-ocr-data-swe`, `tesseract-ocr-data-eng`
## Support
- **Git Repo** — Gitea på `192.168.50.2:2222/nilsjohan/microservice-importer`
- Git repo: Gitea på `192.168.50.2:2222/nilsjohan/microservice-importer`
+167
View File
@@ -0,0 +1,167 @@
# 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)
+35 -60
View File
@@ -1,21 +1,21 @@
# Plan för vidareutveckling av Microservice Importer
## Dokumentstatus (2026-05-03)
## Dokumentstatus (2026-05-10)
Detta dokument riktar sig till utvecklare och driftansvariga för microservice-importer.
Detta dokument riktar sig till utvecklare och driftansvariga för microservice-importer. Teknisk referens finns i [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md).
### Senast avklarat i angränsande flöden
- Regelbaserad kvittotolkning har stärkts för multipack/enheter och svårare radformat.
- Bröd-/rostbrödklassning har utökade guardrails för att minska felaktig kategorisering.
- Regelbaserad kvittotolkning har stärkts för multipack, enheter och svårare radformat.
- Bröd- och rostbrödklassning har utökade guardrails för att minska felaktig kategorisering.
- Klientens granskningsflöde och sessionpersistens i Flutter är implementerat, vilket minskar avbrott mellan parse och spara.
- Kvittokategorisering: nya regler för pasta, grädde, ägg, juice, godis, och potatis samt justerad AI-guardrail.
- Testinfrastruktur: parametriserade enhetstester för kvittoimport (18 testfall) och CI/CD-pipeline med automatiserad testkörning på push.
- **PDF-parsning stabiliserad:** `pdf-parse` använder nu `require()` för CJS-kompatibilitet; `pdfjs-dist/legacy/build/pdf.js` används som fallback för att undvika `DOMMatrix`-fel i Node.js-miljö.
- **Retry-logik förbättrad:** Mistral-anrop vid 429/503 väntar nu `3000 * attempt` ms (3s, 6s, 9s) i stället för fast 1s.
- **Reproducerbart bygge:** `package-lock.json` är nu spårat i repot; Dockerfile använder `npm ci`.
- **AI-optimering implementerad:** `looksLikeReceiptProductLine()` filtrerar bort PDF-rader utan siffra (header/footer/butiksinformation) innan Mistral-anrop. Minskar drastiskt antal onödiga AI-anrop vid kvittoimport.
- Kvittokategorisering: nya regler för pasta, grädde, ägg, juice, godis och potatis samt justerad AI-guardrail.
- Testinfrastruktur: parametriserade enhetstester för kvittoimport och CI/CD-pipeline med automatiserad testkörning på push.
- PDF-parsning stabiliserad med `require()` och `pdfjs-dist/legacy/build/pdf.js` som fallback.
- Retry-logik förbättrad för 429/503.
- Reproducerbart bygge via `package-lock.json` och `npm ci`.
- `looksLikeReceiptProductLine()` filtrerar bort PDF-rader utan siffra innan Mistral-anrop.
## Status (2026-05-03) — Driftsatt och integrerad med recipe-app
## Status (2026-05-10) — Driftsatt och integrerad med recipe-app
`microservice-importer` körs som intern tjänst (`importer-api`) i `recipe-app/compose.yml`. Alla importflöden är delegerade och driftsatta.
@@ -51,7 +51,7 @@ cd /opt/containers/recipe-app && git pull && ./deploy.sh
### Medel prioritet
- **Fler webbplats-parsers** — Specifika parsers för t.ex. Tasteline, Köket.se, Arla
- **Swagger/OpenAPI** — Automatisk API-dokumentation via `@nestjs/swagger`
- **Testtäckning** — Utökad enhetstesttäckning för parsers och `receipt-parsing.service.ts` (18 testfall för kvittoimport)
- **Testtäckning** — Utökad enhetstesttäckning för parsers och `receipt-parsing.service.ts`
### Låg prioritet / Framtida
- **Caching** — Cacha skrapade sidor för att minska belastning på externa webbplatser
@@ -62,77 +62,52 @@ cd /opt/containers/recipe-app && git pull && ./deploy.sh
## AI-optimering: Mistral-modell och pipeline
**Nuläge:** `mistral-small-2603` används för bildinput (vision). För PDF-flödet extraheras text först via `pdf-parse`/`pdfjs-dist`; sedan regelbaserad parsning; sedan AI enbart för återstående rader.
Nuläget är att `mistral-small-2603` används för bildinput (vision). För PDF-flödet extraheras text först via `pdf-parse` eller `pdfjs-dist`; därefter körs regelbaserad parsning och AI bara för kvarvarande rader.
### Implementerad optimering: AI sist i pipeline (PDF)
Kvittopipelinen för PDF ser nu ut:
```
```text
PDF → pdf-parse / pdfjs-dist → preprocessPdfLines → isIgnoredReceiptLine → ruleBasedParseLine → looksLikeReceiptProductLine → AI
```
**`looksLikeReceiptProductLine(line)`** filtrerar bort rader som saknar siffra (butiksnamn, datum, välkomsttext m.m.) innan Mistral-anropet. Enbart rader med namnliknande text OCH minst ett tal skickas till AI.
**Fördelar:**
- Regelbaserad parsning hanterar standardfall gratis och snabbt (t.ex. "MJÖLK 1,5L", "BLANDFÄRS 997G")
- AI anropas bara för rader som regelverket inte kan tolka entydigt
- Möjlighet att använda en mindre/billigare modell för enklare tolkningsuppgifter
`looksLikeReceiptProductLine(line)` filtrerar bort rader som saknar siffra innan Mistral-anropet. Enbart rader med namnliknande text och minst ett tal skickas till AI.
### Modellval för olika deluppgifter
| Uppgift | Rekommenderad modell | Motivering |
|---|---|---|
| Kvittoparsning (hela bilden, nuläge) | `mistral-small-2603` | Vision-förmåga krävs för bild-input |
| Tolka OCR-text (textbaserad input) | `mistral-small-latest` eller mindre | Enklare uppgift när text redan extraherats |
| Kategorisering av enskild produktrad | `open-mistral-nemo` (7B) | Klassificering, ej vision — kan vara mycket liten |
| Kvittoparsning (hela bilden) | `mistral-small-2603` | Vision-förmåga krävs för bild-input |
| Tolka OCR-text | `mistral-small-latest` eller mindre | Enklare uppgift när text redan extraherats |
| Kategorisering av enskild produktrad | `open-mistral-nemo` (7B) | Klassificering utan vision |
**OBS:** För bild-input (JPEG/PNG/HEIC/WebP) krävs alltid en vision-kapabel modell. Optimering med mindre modell är bara möjlig när Tesseract/pdf-parse redan har extraherat text.
För bild-input krävs alltid en vision-kapabel modell.
---
## Framtida förbättringar
### Schemalagd Uppdatering av Kategorier
- **Mål:** Implementera en schemalagd uppdatering av kategorierna en gång i veckan för att säkerställa att cachen alltid är uppdaterad.
- **Metod:** Använda `cron` för att schemalägga ett anrop till `POST /receipt-import/refresh-categories` en gång i veckan.
- Schemalagd uppdatering av kategorier om det visar sig nödvändigt igen.
---
## Nuvarande implementering
## Nuvarande Implementering
### Manuell Uppdatering av Kategorier
- **Mål:** Låta användaren manuellt uppdatera kategorierna via Flutter-UI.
- **Implementering:**
- En knapp i Flutter-UI:n som låter användaren trigga uppdateringen.
- Anropa `POST /receipt-import/refresh-categories` från Flutter-UI:n när användaren klickar på knappen.
```dart
// Exempel på hur du kan anropa endpointen från Flutter
Future<void> refreshCategories() async {
final response = await http.post(
Uri.parse('http://YOUR_API_URL/receipt-import/refresh-categories'),
headers: {'Authorization': 'Bearer YOUR_JWT_TOKEN'},
);
if (response.statusCode == 200) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Kategorier har uppdaterats.')),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Misslyckades med att uppdatera kategorier.')),
);
}
}
```
- Ingen separat manuell kategoriuppdatering via Flutter-UI finns längre.
- Kvittoparsningen använder i stället nuvarande regler, retry-logik och filtrering i backend.
---
## Arkitektur-noteringar
- Tjänsten är **helt stateless** — ingen databas, ingen session
- Kommunicerar **aldrig direkt** med internet-klienter — exponeras bara på `recipe-internal`-nätverket
- `MISTRAL_API_KEY` injiceras via env (samma nyckel som `recipe-api` använder)
- Alpine Docker-image: systempaket `tesseract-ocr`, `tesseract-ocr-data-swe`, `tesseract-ocr-data-eng` installerade via `apk`
- Host-port 3001 är upptagen av `wetty` på servern — `importer-api` exponeras aldrig till host
- Tjänsten är helt stateless och saknar databas
- Den exponeras bara på `recipe-internal`-nätverket
- `MISTRAL_API_KEY` injiceras via env
- Alpine Docker-image använder `tesseract-ocr`, `tesseract-ocr-data-swe`, `tesseract-ocr-data-eng`
- Host-port 3001 är upptagen av `wetty`, så `importer-api` exponeras aldrig till host
## Referenser
- [README.md](README.md)
- [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md)
## 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.