Files
recipe-app/.kilo/plans/1779121909294-silent-star.md
T
Nils-Johan Gynther d5f903db98
Test Suite / backend-pr-quick (push) Has been skipped
Test Suite / quick-import-pr-quick (push) Has been skipped
Test Suite / backend-full (push) Failing after 3m41s
Test Suite / flutter-quality (push) Successful in 2m3s
chore(import): improve error handling and add flyer integration
- Replace BadRequestException with UnauthorizedException for authentication failures in flyer-import and flyer-selection controllers
- Add bulk selection endpoint in FlyerSelectionController for creating multiple selections in one request
- Update FlyerSelectionModule to include new FlyerSelectionMatcherService and FlyerSelectionSyncController
- Extend FlyerSelectionService with createMany method for bulk operations
- Add new DTOs for bulk selection and receipt matching functionality
- Update ReceiptImportService to accept FlyerSelectionService dependency and track successful rows
- Extend SaveReceiptResponse with flyerAutoSync field for receipt-to-flyer matching results
- Add new API paths for flyer import and selection endpoints
- Update Flutter UI to include Flyer import tab and adjust tab controller length
- Add new domain models and repository methods for flyer import functionality
- Update test files to include new FlyerSelectionService dependency
- Modify .kilo plan documentation to reflect current system architecture
2026-05-18 22:51:27 +02:00

7.4 KiB

Plan: Fortsatt implementation av FlyerImport (autoflöde + UX i /import Flutter)

Målbild

Implementera ett komplett flyer-flöde med så få klick som möjligt där:

  • användaren markerar planerade inköp i FlyerImportTab
  • kvittoimporten matchar automatiskt mot öppna FlyerSelection och sätter status=bought
  • användaren bara behöver ingripa vid osäker matchning

Detta följer båda underlagen:

  1. ingen befintlig flyer-UX i /import ännu (behöver byggas)
  2. maximal automation i punkt 3 (sync med kvittoimport)

Principer för “så få klick som möjligt”

  • Default är automation: matcha och uppdatera utan extra dialoger.
  • UI ska vara “review first, edit only when needed”.
  • Endast två manuella åtgärder i happy path:
    1. markera planerade flyer-varor
    2. importera kvitto
  • Manuell override ska finnas men inte blockera flödet.

Fas 1: Backend-kontrakt för auto-sync

1.1 Nya/utökade endpoints

Implementera i backend/src/flyer-selection:

  • POST /flyer-selections/receipt-match-preview

    • Input: kvittorader (normaliserad struktur), weekKey (optional), sessionId (optional)
    • Output: matchförslag per kvittorad + confidence + reasonCodes + kandidat-selection
    • Används för transparent UI-annotering före commit
  • POST /flyer-selections/receipt-match-commit

    • Input: samma payload + optional overrides
    • Output: antal uppdaterade selections, listor över bought, unmatched, ambiguous
    • Utför transaktionell statusuppdatering (planned -> bought)
  • GET /flyer-selections/open

    • Query: weekKey, retailer, pagination
    • Returnerar öppna selections (status=planned) för snabb klienthämtning

Notering: Behåll befintliga CRUD-rutter under /flyer-sessions/:sessionId/selections.

1.2 Matchningsmotor (service-nivå)

I FlyerSelectionService lägg till en intern matcher med prioriterad strategi:

  1. productId exact (högsta prio)
  2. normalized name exact
  3. alias/ordöverlap (token)
  4. quantity/unit-stöd som förstärkning (inte ensam källa)

Regler:

  • En FlyerSelection kan bara konsumeras en gång per commit.
  • Confidence-trösklar:
    • >=0.90: auto-commit-kandidat
    • 0.70-0.89: ambiguous (kräver override för commit)
    • <0.70: unmatched
  • Returnera alltid matchedVia, confidence, reasonCodes.

1.3 Datamodell-justeringar (om behövs)

Nuvarande schema räcker i stort, men planera följande icke-blockerande förbättringar:

  • FlyerSelection:
    • boughtAt DateTime?
    • boughtSource String? (t.ex. receipt_auto, receipt_manual)
    • receiptImportBatchId String? för spårbarhet
  • Index:
    • (userId, status, updatedAt) för snabb hämtning av öppna poster

Migration i separat steg efter kod.

1.4 Säkerhet och robusthet

  • Validera alltid user-scope i alla nya endpoints.
  • Rate-limit på match-endpoints (liknande befintlig throttle-nivå).
  • Transaktion (prisma.$transaction) för commit så statusuppdatering blir atomisk.
  • Idempotens: commit med samma receiptImportBatchId ska inte dubbeluppdatera.

Fas 2: Flutter UX i /import (ny flyer-tab)

2.1 Lägg till FlyerImportTab

Uppdatera ImportScreen så tabbar blir:

  1. Recept
  2. Kvitto
  3. Flyer

Skapa:

  • flutter/lib/features/import/presentation/flyer_import_tab.dart
  • flutter/lib/features/import/data/flyer_import_repository.dart
  • flutter/lib/features/import/data/flyer_import_providers.dart
  • flutter/lib/features/import/domain/flyer_item.dart
  • flutter/lib/features/import/domain/flyer_selection.dart

2.2 Flyer-tabens minimalklick-flöde

Steg i UI:

  1. Upload flyerfil
  2. Visa parserader med förvald checkbox för matchade varor
  3. Primär CTA: Planera markerade (bulk-create/upsert)
  4. Direkt visning av statuschips (planned/bought/skipped)

Klickoptimering:

  • Förifyll plannedQuantity/plannedUnit från flyerdata.
  • Batch-upsert selections i ett enda API-anrop.
  • Visa inline varningar istället för modaler där möjligt.

2.3 Statusöversikt

I flyer-tabben visa sektioner:

  • Planerade (öppna)
  • Nyligen köpta (autouppdaterade från kvitto)
  • Ej matchade vid senaste kvitto (för snabb manuell hantering)

Fas 3: Integrera auto-sync i ReceiptImportTab

3.1 Hook efter receipt parse

I befintlig _submit() i receipt_import_tab.dart:

  1. importera kvitto som idag
  2. anropa receipt-match-preview
  3. annotera UI-rader med matchstatus (icon/chip)
  4. vid Lägg till markerade: anropa receipt-match-commit parallellt/sekventiellt med saveReceipt

3.2 Zero-click commit i happy path

Defaultbeteende vid Lägg till markerade:

  • auto-committa alla matcher med confidence >=0.90
  • lämna ambiguous som planned
  • visa en kompakt snackbar:
    • 2 planerade markerades som köpta
    • 1 kräver manuell kontroll

Ingen extra dialog i standardfall.

3.3 Manuell override (endast vid behov)

Lägg till valfri expandrad i resultatlistan:

  • “Föreslagen flyer-match” + knapp Bekräfta ändå
  • används endast för ambiguous fall

Fas 4: API- och UI-detaljer för låg friktion

4.1 Payload-standard (receipt -> matcher)

Standardisera kvittorad till:

  • rowId (lokalt index eller UUID)
  • rawName
  • normalizedName
  • productId (om redan mappad)
  • quantity
  • unit
  • price

4.2 UX-copy

Konsekventa texter i UI:

  • Automatchad mot flyer
  • Osäker matchning
  • Ej matchad

4.3 WeekKey-hantering

Fallback-ordning vid matchning:

  1. explicit sessionId
  2. explicit weekKey
  3. server beräknar aktuell weekKey

Detta minimerar klientlogik och fel.


Fas 5: Test och kvalitetssäkring

5.1 Backend

  • Unit-tester för matcher-regler och confidence-nivåer
  • Service-tester för commit-idempotens
  • Controller-e2e för user-scope + throttling + felkoder
  • Prisma-transaktionsscenarion (dubbelklick/duplicerat commit)

5.2 Flutter

  • Widget-tester för:
    • FlyerImportTab listning/bulk-planering
    • kvitto-rad med automatch-chip
  • Integrationstester för ReceiptImportTab + auto-sync callback

5.3 Acceptanskriterier (måste uppfyllas)

  • Happy path kräver max 2 aktiva klick från planering till auto-bought.
  • Minst 90% av high-confidence-matchningar autouppdateras korrekt i test-fixtures.
  • Inga writes till Product/Inventory sker i flyer-planeringsfas.

Fas 6: Gradvis lansering

  1. Backend-endpoints bakom feature flag: flyerReceiptAutoSyncEnabled
  2. Aktivera för intern/test-användare först
  3. Mät:
    • andel auto-match
    • andel ambiguous
    • manuell override-frekvens
  4. Finjustera thresholds innan full rollout

Implementeringsordning (konkret)

  1. Backend: matcher + preview/commit endpoints
  2. Backend: idempotens + spårbarhetsfält + migration
  3. Flutter: ny FlyerImportTab + repository/providers
  4. Flutter: integrera preview/commit i ReceiptImportTab
  5. Tester backend + Flutter
  6. Feature flag rollout

Risker och mitigering

  • Felmatchningar: håll konservativ tröskel och auto-commit bara vid hög confidence.
  • Dubbla commits: idempotensnyckel + transaktion.
  • UX-brus: visa detaljer först vid ambiguous, inte i happy path.
  • Prestanda: batcha matchning och undvik N+1-frågor via prefetch av öppna selections.

Definition of Done

  • /import har en fungerande FlyerImportTab.
  • Kvittoimport auto-synkar mot FlyerSelection med minimal friktion.
  • planned -> bought uppdateras automatiskt för high-confidence.
  • Ambiguous fall kan hanteras manuellt utan att blockera flödet.
  • Tester gröna och feature flag klar för kontrollerad utrullning.