Preskoči na sadržaj

E12: Physical Sales (Petrol) - Tasks

Epic: E12: Physical Sales (Petrol)


E12-F1: Petrol Sales Section (Mobile App)

Feature: E12-F1: Petrol Sales Section Mobile

Status Task Verification
Create deeplink handler for petrol-sales/{match_id} Deeplink opens app
Hide section from navigation (accessible only via deeplink) Section not in menu
Check availability on page load Sold out shows message
Implement ticket holder entry form Form submits
Generate 5-digit numeric PIN on submit PIN generated
Store PIN in PetrolPIN table Record created

E12-F2: Petrol Quota Portal

Feature: E12-F2: Petrol Quota Portal

Implementation Note

Petrol quota is configured like other quotas but requires a special quota type identifier to enable PIN-based functionality.

Status Task Verification
Create Petrol Staff role in RBAC Role exists
Implement special quota type identifier for Petrol quotas Quota type stored
Implement PIN lookup endpoint GET /petrol-portal/pins/{pin} Returns customer data
Reserve seats for 20 minutes on PIN lookup Reservation created
Implement POST /petrol-portal/pins/{pin}/confirm endpoint Sale completed
Deliver tickets to customer app on confirm Tickets appear in app

E12-F3: Petrol Reservation Management

Feature: E12-F3: Petrol Reservation Management

Status Task Verification
Set 20-minute TTL on reservation TTL set
Send warning at 5 minutes remaining Warning displayed
Send warning at 1 minute remaining Warning displayed
Auto-release seats on timeout Seats released
Implement POST /petrol-portal/reservations/{id}/cancel Immediate release

E12-F4: Admin Petrol Section (Unified Quota + Auto-QR)

Feature: E12-F4: Admin Petrol Section

Backend (see also tasks-ticketing-backend.md → E12-F4)

Status Task Verification
Deprecate petrol_deeplinks table (drop migration OR stop writing) — deeplink now derived from Petrol quota ID Table no longer referenced by new code
Add partial unique index quotas (match_id) WHERE quota_type='PETROL' AND status='ACTIVE' At most one active Petrol quota per match
Implement POST /admin/petrol/quotas — forces quota_type=PETROL, deferred_payment=TRUE, can_create_subquotas=FALSE, transfer_permission=NO Quota created with forced flags
Implement GET /admin/petrol/quotas (filters: match, status, deferred-payment status, date range) Returns list
Implement GET /admin/petrol/quotas/{id} — includes computed deeplink URL Returns detail
Implement GET /admin/petrol/quotas/{id}/qr.svg and /qr.png (≥600×600) — derived from quota ID SVG/PNG decode back to hns://petrol-sales/{quota-id}
Implement POST /admin/petrol/quotas/{id}/cancel (delegates to existing quota cancellation service) Cancel works, standard options
Reject quota_type=PETROL in generic POST /admin/quotas with redirect hint 400/422 with clear error
Reject duplicate active Petrol quota creation with 409 Concurrent create returns 409
Emit audit events on Petrol quota create/cancel Audit records present

Admin Portal (see also tasks-admin-portal.md → Petrol Management)

Status Task Verification
Add "Petrol Quotas" sub-route under existing /admin/petrol namespace Route renders
Build Create Petrol Quota form (match picker, recipient email, sectors, quantity, algorithm, expiration — forced flags hidden) Form creates via /admin/petrol/quotas
Build Petrol quotas list view with inline QR thumbnail + SVG/PNG download + copy-deeplink Downloads decode correctly; clipboard copy works
Show match context, counters (allocated/reserved/sold), deferred-payment status, cancel action per row All columns present; filters work
Generic Quota section: mark Petrol quotas read-only, show "Managed in Petrol section →" link Mutations disabled from generic list
Generic Create Quota form: reject or redirect if admin picks Petrol type Create blocked with redirect to Petrol section
Restrict Petrol section access to ROLE_MATCH_MANAGER 403 for other roles

Mobile (cross-reference for completeness — belongs to E12-F1)

Status Task Verification
Verify iOS universal link entitlements include petrol-sales/* path apple-app-site-association updated
Verify Android App Links include petrol-sales/* path assetlinks.json updated
Update mobile deeplink handler: resolve /petrol-sales/{quota-id} — load match + sector availability from Petrol quota context Scanning QR opens correct match flow; CANCELLED/EXPIRED quota shows "Petrol sales unavailable"

Last Updated: 2026-04-13