- Introduced user guide for Flutter frontend in README.md, detailing user flows and recent improvements. - Created next steps roadmap for Flutter migration in next_steps_flutter.md, outlining current tasks and priorities. - Developed technical description for Flutter frontend in teknisk_beskrivning_flutter.md, covering architecture and security status. - Removed outdated migration documentation for Prisma P3009 and added recovery steps for failed migrations in migrering-MSI.md. - Established a release checklist for product launches in produktlansering.md, ensuring security and stability measures are met. - Formulated a systematic backend review and optimization plan in review_backend.md, focusing on reducing complexity and improving performance.
12 KiB
Nyheter och förbättringar (2026-05-10)
- Admin-inventarie: Full CRUD, merge, filter, sortering, preview och säkerhet för admin i inventarietabellen. Endast admin kan se och hantera alla användares inventarieposter via nya endpoints och adminpanel i Flutter.
- User-scope och IDOR-skydd: Inventory och produkter är nu strikt user-scopade. Alla operationer kräver och filtrerar på userId. Tester verifierar att åtkomst nekas vid försök till IDOR.
- Säkerhetshärdning: DTO-validering, guard-ordning, logging, throttling, merge abuse-skydd, och rollbaserad access är implementerat och testat.
- Optimeringar: DRY i service-lager, striktare query parsing, preview-cache, API-cleanup, och kodduplication eliminerad.
- Testtäckning: Utökade enhets-, integrations- och säkerhetstester för alla kritiska flöden.
Sessionlogg: Receipt Import Cleanup & Optimization
Datum: 2026-05-09
Mål under sessionen
- Rensa bort legacy/deprecated kod i receipt-import.
- Förenkla och optimera kvarvarande kod på ett säkert sätt.
- Säkerställa att kategori-förslag visas för okända varor i import-UI.
Genomförda förändringar
1) Legacy/deprecated kod borttagen (backend)
Fil: backend/src/receipt-import/receipt-import.service.ts
- Borttaget:
inferPackageDebugFromRawName() - Borttaget:
cachedCategories+loadCategories()+ constructor-anrop - Borttaget:
matchProducts() - Borttaget:
findWordMatch()(gammal variant) - Borttaget:
enrichWithAiCategories()
Fil: backend/src/receipt-import/receipt-import.controller.ts
- Borttaget endpoint:
POST /receipt-import/refresh-categories(obsolet efter borttagen cache-metod)
2) Tester uppdaterade till unified matcher
Fil: backend/src/receipt-import/receipt-import.service.spec.ts
- Tester migrerade från anrop av borttagna
matchProducts()tillmatchAndEnrichReceiptItem(). - Tester gröna efter uppdatering.
3) Säkra förenklingar/optimeringar (backend)
Fil: backend/src/receipt-import/receipt-import.service.ts
- Infört tydliga typer för matchningskontext (
MatchingContext) och debug-objekt. - Extraherat helpers för:
- signaltextbyggande
- enhetsmappning
- Reducerad duplicering i kategoriseringsflöde.
- In-memory index i matchningskontext för snabbare uppslag:
aliasByReceiptNameunitMappingByKey
- Bakåtkompatibilitet behållen via fallback när index-fält saknas.
4) UI-fix: kategori-förslag visades inte för okända varor
Fil: flutter/lib/features/import/presentation/receipt_import_tab.dart
- Fixat så kategori-förslag visas även om rad saknar matchad produkt.
- Edit-state fylls nu även för rader med endast kategori-förslag.
- Label i UI visar
Kategoriförslagnär produkt saknas.
5) Diagnostik tillagd (backend)
Fil: backend/src/receipt-import/receipt-import.service.ts
- Varningslogg om kategorier inte kunde laddas eller om listan blev tom.
- Syfte: snabbare felsökning när kategori-förslag uteblir.
Verifiering under sessionen
- Backend build: OK (
npm run build) - Backend tests: OK (66/66)
- Flutter analyze (berörda filer): OK
Notering: terminalhistorik innehöll äldre felutskrifter, men senaste verifieringarna var gröna.
Kvar att göra nästa gång
- Deploya senaste backend + flutter till servern.
- Re-testa receipt import med PDF i produktion.
- Bekräfta att rader utan produkt nu visar
Kategoriförslagdirekt i listan. - Vid fortsatt problem: kontrollera nya varningsloggar från
prepareMatchingContexti backend-loggar.
Snabb fortsättning (checklista)
- Deploy backend
- Deploy flutter
- Import-test med samma PDF
- Verifiera kategori-förslag för okända varor
- Dela loggutdrag om något saknas
Sessionlogg: Produkthantering & UI-optimeringar (samma dag, senare)
Mål under denna del
- Fixa scroll-issue i kvittoimport-gränssnittet (7 rader men bara 5 synliga).
- Implementera product rename/merge för både admins och regular users.
- Eliminera kodduplicering i backend-service.
- Optimera admin-panel och deploy-process.
Genomförda förändringar
1) Scroll-issue fixat i receipt import UI
Fil: flutter/lib/features/import/presentation/receipt_import_tab.dart
- Problem:
SizedBox(height: 620px, child: ListView.builder(...))inutiSingleChildScrollViewskapade konfligerade scroll-handlers. - Lösning: Tog bort
SizedBox-begränsningen, användshrinkWrap: trueochphysics: NeverScrollableScrollPhysics()på ListView så parentSingleChildScrollViewhanterar all scrolling. - Resultat: ✅ Alla 7 rader nu synliga.
2) Product rename & merge för admin (backend)
Fil: backend/src/products/products.controller.ts
- Två nya endpoints:
PATCH /products/:id/canonical-name— admin kan byta namn på vilken produkt som helstPOST /products/merge— admin kan slå ihop två produkter
- Decorator:
@Roles('admin')
3) Private product endpoints för vanliga users (backend)
Fil: backend/src/products/products.controller.ts
- Två nya parallella endpoints för user-owned private products:
PATCH /products/private/:id/canonical-name— user kan byta namn på egen privat produktPOST /products/private/merge— user kan slå ihop egna privata produkter
- JWT extraction:
const userId = req.user.id(ingen@Roles-behov, user kan bara redigera sin egna data) - Security:
ForbiddenExceptionom produkt inte är privat eller inte ägs av user
4) Backend service refaktorering — kodduplicering eliminerad
Fil: backend/src/products/products.service.ts
- Två nya private helper-metoder:
_updateCanonicalNameCore(id, canonicalName)— shared logik för trim + Prisma update_mergeCore(sourceId, targetId)— shared logik för transaction, inventory transfer, soft-delete
- Alla fyra public metoder (
updateCanonicalName,updateCanonicalNamePrivate,merge,mergePrivate) använder nu dessa helpers - Exception fix: Bytte
throw new Error(...)tillthrow new ForbiddenException(...)för authorization-fel (korrekt HTTP 403) - Resultat: ~80 rader kodduplicering eliminerad, bättre underhållbarhet
5) API-path konstanter för Flutter (frontend)
Fil: flutter/lib/core/api/api_paths.dart
- Lade till två nya constants i
ProductApiPaths:static const mergePrivate = '/products/private/merge'static String canonicalNamePrivate(int id) => '/products/private/$id/canonical-name'
6) Admin repository uppdaterad (frontend)
Fil: flutter/lib/features/admin/data/admin_repository.dart
- Två nya metoder:
updateCanonicalNamePrivate(int productId, String canonicalName)— user renamemergeProductsPrivate({required sourceId, required targetId})— user merge
- Komment: "Admin kan uppdatera vilken produkt som helst; users kan bara uppdatera sina egna privata produkter"
7) Admin panel optimeringar (frontend)
Fil: flutter/lib/features/admin/presentation/admin_products_panel.dart
- Caching av kategorierna:
_cachedCategoryOptionsberäknas en gång istället för varje build - Enklare
_nameForId(): Bytte frånwhere().toList()till en enkel for-loop med early return - Parallell restore:
_restoreSelected()använderFuture.wait()istället för seriebaserade await - Expression switch:
_sortLabel()förkortat från 12-radigt switch till en enda rad med expression switch
8) Deploy-script förbättring
Fil: deploy.sh
- Nya flaggor för selektiv build:
--backend— bygga bara backend--flutter— bygga bara Flutter--importer— bygga bara microservice-importer--pull-always— tvinga Docker att hämta senaste base image (för prod-säkerhet)
- Default: bygger alla tre, använder
--pull=falseför snabbhet (ej prod) --seedflag för opt-in databaskällning- Help:
./deploy.sh --helpvisar användning
Verifiering
- ✅ Backend build: OK (
npm run build) - ✅ Backend tests: OK
- ✅ Flutter analyze: OK (alla berörda filer)
- ✅ TypeScript-fel: Inga
- ✅ Git diff: Alla 4 filer granskat och godkänt
Öppna uppgifter (nästa steg)
- Deploy backend + Flutter med
./deploy.sh --backend --flutter - Testa i produktion:
- Verifiera 7 rader nu synliga i receipt import
- Verifiera admin kan byta namn på produkter
- Verifiera admin kan slå ihop produkter
- Verifiera users kan redigera sina egna privata produkter
- UI för users: Om private rename/merge ska exponeras i användar-app (backend redan klart, saknas bara UI)
- Unit/integration tests för private endpoints
Sessionlogg: Aliasstrategi i kvittoimport (samma dag, senare)
Mål under denna del
- Göra aliasstrategin konsekvent med user-scope som standard och global fallback via admin.
- Sluta lära alias automatiskt vid manuell korrigering och kräva explicit val i UI.
- Härda backend mot brusiga eller ogiltiga alias.
Genomförda förändringar
1) Gemensam aliasnormalisering och guardrails (backend)
Filer:
-
backend/src/common/utils/receipt-alias.ts -
backend/src/receipt-alias/receipt-alias.service.ts -
backend/src/receipt-import/receipt-import.service.ts -
Infört gemensam utility för aliasnormalisering (
trim, lowercase, kollapsad whitespace). -
Infört validering som blockerar tomma alias och brusiga alias som
rabatt,summa,pant,att betala,totalt, m.fl. -
Receipt import och alias-API använder nu samma regler för både lookup och sparande.
2) Receipt import lär inte längre alias automatiskt (Flutter)
Filer:
-
flutter/lib/features/import/data/receipt_import_session.dart -
flutter/lib/features/import/presentation/edit_dialog.dart -
flutter/lib/features/import/presentation/receipt_import_tab.dart -
Infört explicit
learnAlias-val i edit-dialogen. -
Alias sparas nu bara om användaren aktivt markerar att kvittonamnet ska läras in.
-
Valet persisteras i receipt import-sessionen så att tabbyte inte tappar användarens val.
-
Om raden redan matchades via alias visas förklarande text i stället för ny aliasinlärning.
3) Aliasöversikter visar scope tydligare (Flutter)
Filer:
-
flutter/lib/features/admin/domain/receipt_alias.dart -
flutter/lib/features/profile/presentation/user_aliases_screen.dart -
flutter/lib/features/admin/presentation/admin_aliases_panel.dart -
Aliasmodellen utökad med
ownerIdochisGlobal. -
User alias-skärmen visar nu skillnad mellan
Privat aliasochGlobal fallback. -
Delete-knapp visas bara för privata alias i användarvyn, så UI:t matchar backend-behörigheten.
-
Adminpanelen visar scope även för aliasposter.
4) Tester för aliasflödet
Filer:
-
backend/src/receipt-import/receipt-import.service.spec.ts -
backend/src/receipt-alias/receipt-alias.service.spec.ts -
Tester tillagda för normalisering av whitespace vid alias-lookup.
-
Tester tillagda för alias-upsert med normalisering.
-
Tester tillagda för blockering av brusalias.
-
Tester tillagda för behörighetsregler kring globala alias och borttagning.
Verifiering
- ✅ Backend tests: 31/31 gröna för berörda aliasspecar
- ✅ Flutter analyze: OK för alla berörda alias/import-filer
Kvar att göra
- Manuell test i appen: receipt import med explicit alias-inlärning.
- Produktionstest: verifiera att privata alias och global fallback beter sig rätt mot riktiga kvitton.
- Bedöm om aliasöversikterna behöver mer avancerad filtrering eller redigering senare.
Snabb checklista för nästa session
- Deploy backend + Flutter
- Testa scroll-fix i prod
- Testa admin rename/merge
- Testa private endpoints (API-test eller manual)
- Implementera user-UI för private rename/merge (valfritt)