feat: replacement

This commit is contained in:
Ola Malmgren
2026-05-22 20:33:21 +02:00
parent 4d705a1005
commit f19e2d4e0d
26 changed files with 1951 additions and 20 deletions

View File

@@ -2,9 +2,14 @@
Prioriterade förbättringar och kända luckor. Top-down ungefär i prioritetsordning.
## Bäställningsdisclaimer
- det är bäställarens ansvar att veta hur mycket dom får lov i sin by.
60 liter per 40 deltagare. 2012 (4,8liter) PC5(12,2 liter) PC10 (23,8 liter)
## P0 — innan skarp lansering
- [ ] **Rate-limit på `POST /api/bookings`**: enkel IP-baserad throttle (t.ex. 5 bokningar/timme/IP) för att stoppa spam/bots. Implementera i `src/app/api/bookings/route.ts` eller via en middleware-wrapper.
- [ ] **Rate-limit på `POST /api/bookings` och `POST /api/customer/magic-link`**: enkel IP-baserad throttle (t.ex. 5 bokningar/timme/IP) för att stoppa spam/bots. Magic-link-endpointen är extra känslig — utan throttling kan någon trigga obegränsat med mejl. Implementera i respektive route eller via en middleware-wrapper.
- [ ] **Honeypot eller hCaptcha på formuläret**: bokningsformuläret är publikt utan skydd. Honeypot är minimalistiskt och räcker ofta.
- [ ] **Generera riktigt `AUTH_SECRET`**: dokumenterat i README men måste göras manuellt vid deploy.
- [ ] **Verifiera Mailjet-avsändare**: `MAIL_FROM_EMAIL` måste vara verifierad i Mailjet-kontot innan mejl kommer fram.
@@ -20,6 +25,8 @@ Prioriterade förbättringar och kända luckor. Top-down ungefär i prioritetsor
- [ ] **Lagerbegränsning per produkt**: idag finns kapacitet bara på upphämtnings-slots. Lägg `totalStock``Product` och kontrollera i POST-routen att `Σ confirmed quantity ≤ stock`.
- [ ] **Mailjet Templates (Template-ID) istället för inline HTML**: gör det möjligt att ändra mejldesign utan redeploy. Inline HTML kvar som fallback om template-id saknas.
- [ ] **Resend-bekräftelse loggar**: idag skickar admin-knappen "Resend confirmation" tyst — visa toast/success vid lyckad sändning.
- [ ] **Statusmejl vid byte SCHEDULED/DELIVERED**: kund får idag bara bekräftelse på att begäran är mottagen — borde få mejl när admin schemalägger eller markerar levererat.
- [ ] **Cleanup-jobb för expired customer-tokens**: `CustomerMagicLink` och `CustomerSession` rensas inte automatiskt. Lägg till en cron eller städa i `getCustomerEmail`/`consumeMagicLink`.
- [ ] **Bookings-vy: paginering**: nuvarande tar `take: 200`. Lägg cursor-paginering vid skarp volym.
- [ ] **PDF-faktureringsunderlag per bokning**: utöver CSV — en PDF som matchar fakturamall, lättare att bifoga.
- [ ] **Audit log för admin-actions**: tabell `AuditEvent` med vem som ändrade status, körde resend, etc.
@@ -49,6 +56,8 @@ Prioriterade förbättringar och kända luckor. Top-down ungefär i prioritetsor
## Beslutslogg
- **2026-05-22**: `ReplacementRequest` snapshottar pris från `Product` (samma som ny flaska) vid request-tid — fält `sku/nameSv/nameEn/unitPriceOre/vatBp/lineTotalOre`. CSV-export utökad med `LineType=Booking|Replacement`-kolumn; CANCELLED-byten exkluderas, `BillableQuantity` = quantity om `status=DELIVERED` annars 0. En faktura per org = original-rader + levererade byten.
- **2026-05-22**: Kund-portal (`/min-sida`) + flaskbyte tillagt som del av MVP. Magic-link på begäran (kund matar in mejl, får länk via mejl). Token-scope = alla bokningar för mejlen. `ReplacementRequest`-modell kopplad till `BookingItem` + valbar `PickupSlot`. Inga antalsgränser — admin avgör per ärende.
- **2026-05-22**: Valt SQLite + Prisma 5 (inte 7) för MVP. SQLite-fil i Docker-volym räcker för ett event. Prisma 5 fungerar utan `prisma.config.ts`.
- **2026-05-22**: `prisma db push` istället för `migrate deploy` i entrypoint — färre artefakter att hålla reda på i MVP. Byt vid stabilt schema.
- **2026-05-22**: Priser i öre (`Int`) snarare än `Decimal` — enklare och säkrare för en valuta (SEK).