project design

This commit is contained in:
Administrator
2026-04-30 18:28:05 +00:00
parent 96c0067ef1
commit 65394f6436
14 changed files with 5190 additions and 74 deletions
+310
View File
@@ -0,0 +1,310 @@
# Features & Priorities — RentFlow
## MVP (Phase 1) — Must Ship Before Launch
### Subscription & Billing
- [x] Company signup → plan selection → payment via AmanPay or PayPal
- [x] 14-day free trial (no payment required until trial ends)
- [x] Company status: PENDING → TRIALING → ACTIVE / PAST_DUE / SUSPENDED
- [x] Subscription gate middleware on all dashboard API routes
- [x] Trial / past-due banners in dashboard
- [x] Suspended account blocks dashboard; public site stays up
- [x] Manual renewal flow: company pays via AmanPay (card/cash/e-wallet) or PayPal
- [x] Invoice history (AmanPay transaction IDs or PayPal capture IDs)
- [x] Supported currencies: MAD, USD, EUR
### Tenant Isolation (Fleet Management)
- [x] Every Prisma query scoped by `companyId`
- [x] `requireTenant` middleware attaches `companyId` from authenticated employee
- [x] Vehicle, customer, reservation IDs validated against `companyId` before any operation
- [x] No cross-company data exposure — enforced at API level, not just UI
- [x] Add / edit / archive vehicles
- [x] Vehicle photos (Cloudinary)
- [x] Published / unpublished toggle (controls marketplace + public site visibility)
- [x] Vehicle categories, specs, features list
### Offers / Promotions System
- [x] Create offer (%, fixed amount, free day, special rate)
- [x] Valid from / until dates
- [x] Applicable to: all vehicles / by category / specific vehicles
- [x] Optional promo code + max redemptions
- [x] Minimum rental days
- [x] `isPublic` flag — show on global marketplace
- [x] `isFeatured` flag — featured carousel placement (plan-gated: GROWTH+)
- [x] Offer applied at booking (discount calculated, stored on Reservation)
- [x] Offer performance stats (redemptions, revenue impact)
- [x] Offer banner image upload
### Global Marketplace (rentflow.com/explore)
- [x] Featured offers carousel on /explore home
- [x] Search vehicles by city, dates, category, price range
- [x] Company cards (logo, rating, offer badge)
- [x] Company marketplace profile page (vehicles + offers + reviews)
- [x] Vehicle detail page (photos, specs, redirect CTA to company site)
- [x] Cross-company availability check
- [x] Filter by category, transmission, price, features
- [x] Marketplace listing toggle per company (opt out)
### Renter Account System
- [x] Renter signup / login (own auth, separate from Employee/Clerk)
- [x] Email verification
- [x] Renter profile (name, phone, locale, currency)
- [x] Cross-company reservation history in /renter/dashboard
- [x] Save / unsave companies
- [x] Guest booking (no account required, but prompted to sign up after)
- [x] When renter books, auto-create Customer record in that company's CRM
### Online Reservations (all sources)
- [x] Booking from dashboard (employee creates manually)
- [x] Booking from company public site (BookingSource: PUBLIC_SITE)
- [x] Booking from global marketplace (BookingSource: MARKETPLACE)
- [x] Reservation lifecycle: DRAFT → CONFIRMED → ACTIVE → COMPLETED
- [x] Offer / promo code applied at booking step
- [x] Availability check before confirming
- [x] Booking confirmation (number, summary, company contact)
- [x] Cancel with reason + `cancelledBy` (COMPANY / RENTER / SYSTEM)
### Branding & White-Label Public Site
- [x] Company display name, logo, tagline, hero image
- [x] Primary brand color picker
- [x] Subdomain: `{slug}.rentflow.com` (claimed during onboarding)
- [x] Real-time subdomain availability check
- [x] Vercel wildcard domain routing (`*.rentflow.com`)
- [x] Company public site: home with offers, vehicle listing, vehicle detail, booking, confirmation
- [x] Offers page on public site
- [x] "Powered by RentFlow" badge (removable on Pro)
- [x] Site language + currency preference
### Payments — Rental (AmanPay + PayPal)
- [x] Company connects their own AmanPay merchant account (Merchant ID + Secret Key)
- [x] Company connects their own PayPal business account
- [x] Collect payment at booking (marketplace redirect + public site)
- [x] AmanPay widget: national card, international card, cash (3000+ points), e-wallet
- [x] PayPal buttons component (standard checkout)
- [x] If no payment method configured: "Contact to reserve" + pay on pickup flow
- [x] Payment status per reservation
- [x] Refund on cancellation (via AmanPay or PayPal API)
- [x] Guest checkout (no renter account required)
### Notifications — Full System
- [x] **Email** (Resend) — all notification types, rich HTML templates
- [x] **SMS** (Twilio) — confirmations, reminders, payment alerts
- [x] **WhatsApp** (Twilio WhatsApp API) — confirmations, reminders (key for AR/FR)
- [x] **In-App** (Socket.io + Redis) — real-time bell icon in dashboard + renter site
- [x] **Push** (Firebase FCM) — renter PWA push notifications
- [x] `Notification` table — logs every delivery attempt per channel
- [x] `NotificationPreference` table — per-user opt-in/out per type + channel
- [x] Preferences UI: matrix toggle (notification type × channel)
- [x] All company events: new booking, cancelled, payment received, trial ending, maintenance due, offer expiring, new review
- [x] All renter events: confirmed, 24h reminder, 2h reminder, vehicle ready, return reminder, cancelled, refund, new offer from saved company, review request
- [x] Scheduled notifications via cron (reminders, trial ending, maintenance due)
### Reviews
- [x] Renter submits review (only after reservation COMPLETED)
- [x] 15 stars overall + vehicle + service
- [x] Text comment
- [x] Company can reply to review
- [x] Reviews shown on marketplace company profile
- [x] Average rating on company card + brand settings
### Customer CRM
- [x] Auto-created from any booking source
- [x] Company-scoped view (never cross-company)
- [x] Linked to global Renter account (if booked as logged-in renter)
- [x] Rental history, notes, flag/blacklist
### Auth & Onboarding
- [x] Company employee auth via Clerk
- [x] Renter auth via own JWT (separate)
- [x] Onboarding step 2: branding + subdomain
- [x] Onboarding step 4: "Your vehicles now appear on the RentFlow marketplace"
- [x] Role system: OWNER / MANAGER / AGENT
### Platform Admin Panel
- [x] `AdminUser` model: email, password (bcrypt), role (SUPER_ADMIN/ADMIN/SUPPORT/FINANCE/VIEWER), 2FA (TOTP), last login tracking
- [x] `AdminPermission` model: per-admin resource+action overrides on top of role defaults
- [x] `AuditLog` model: every admin action logged (action, resource, before/after JSON, IP, note)
- [x] Admin JWT auth (separate from Clerk and renter JWT) — 8h expiry
- [x] TOTP 2FA: setup with QR code, verify, enforce for ADMIN+ roles
- [x] Role hierarchy: VIEWER < FINANCE < SUPPORT < ADMIN < SUPER_ADMIN
- [x] Admin role access matrix: 17 dashboard features × 5 roles
- [x] `admin.rentflow.com` separate app (Next.js)
- [x] **Company management**: list, search/filter, create, edit, suspend, reactivate, delete
- [x] **Company staff management**: list employees per company, add employee, edit (name/email/role), deactivate/reactivate, reset password
- [x] **Impersonation**: ADMIN+ can log in as any company employee (Clerk impersonation session), with dashboard banner
- [x] **Subscription override**: force status, change plan, add free period with auto-revert
- [x] Manual invoice mark-as-paid
- [x] **Renter management**: list, search, view history, block/unblock
- [x] **Audit log UI**: searchable, filterable by admin/action/company, CSV export
- [x] Admin user management (SUPER_ADMIN only): create/edit/deactivate admins, set roles
- [x] Platform metrics: MRR, churn, active companies, marketplace stats, notification delivery rates
- [x] Prisma seed creates first SUPER_ADMIN from env vars
- [x] Employee role control matrix (OWNER/MANAGER/AGENT) with 17 feature permissions documented
---
### Advanced Rental Operations (Phase 1)
#### Vehicle Damage Inspection
- [x] Interactive top-down SVG damage map in check-in/check-out workflow
- [x] 22 clickable zones (hood, roof, doors, fenders, bumpers, wheels, windshield, mirrors, interior, undercarriage)
- [x] 5 severity levels per zone: SCRATCH, DENT, CRACK, MISSING, OTHER — each shown in distinct color
- [x] Optional note per damaged zone
- [x] Optional damage photos upload (Cloudinary)
- [x] `DamageReport` model — one per check-in, one per check-out (`@@unique([reservationId, type])`)
- [x] Fuel level and odometer recorded at each inspection
- [x] Customer acknowledgement timestamp + name
- [x] Damage map rendered in PDF contract (static SVG with color markers) — CHECKIN + CHECKOUT side by side
#### Insurance Policies
- [x] `InsurancePolicy` model: name, type (CDW, SCDW, THEFT, THIRD_PARTY, FULL, BASIC, ROADSIDE, PERSONAL, CUSTOM)
- [x] Three charge types: PER_DAY, PER_RENTAL (flat), PERCENTAGE_OF_RENTAL
- [x] Required vs optional flag — required policies auto-apply, cannot be opted out
- [x] `ReservationInsurance` junction: snapshot of policy terms locked at booking time
- [x] `insuranceTotal` cached on Reservation for fast invoice generation
- [x] Insurance line items in customer invoice with charge type label
- [x] Insurance shown on rental contract
#### Second / Additional Driver
- [x] `AdditionalDriver` model: full personal details + license info
- [x] Charge types: FREE, PER_DAY, FLAT
- [x] Company configures default charge in `ContractSettings`
- [x] License validation applied to additional drivers (same 3-month rule)
- [x] Additional driver(s) listed on contract + invoice line item (if charged)
- [x] Employee can approve/deny flagged additional driver license
#### Driver License Validation
- [x] `licenseExpiry`, `licenseIssuedAt`, `licenseCountry`, `licenseNumber`, `licenseCategory` fields on Customer
- [x] `LicenseStatus` enum: PENDING, VALID, EXPIRING, APPROVED, DENIED, EXPIRED
- [x] **3-month rule**: if license expires within 90 days → status=EXPIRING → requires employee approval
- [x] **Expired**: status=EXPIRED → automatic flag → employee must explicitly approve or deny before confirmation
- [x] License validation badge on customer record (green/amber/red)
- [x] Warning banner on reservation detail when customer has EXPIRING or EXPIRED license
- [x] Approve / Deny buttons for OWNER and MANAGER roles only
- [x] Approval logged: who approved, when, and note
#### Age-Based & Experience-Based Pricing Rules
- [x] `PricingRule` model: configurable per company
- [x] Conditions: AGE_LESS_THAN, AGE_GREATER_THAN, LICENSE_YEARS_LESS_THAN, LICENSE_YEARS_GREATER_THAN
- [x] **Default rule: Under-25 surcharge** (+15% of base rental, configurable)
- [x] **Default rule: 5+ years experience discount** (5%, configurable)
- [x] Adjustment types: PERCENTAGE, FLAT_PER_DAY, FLAT_TOTAL
- [x] Rules applied to primary driver AND all additional drivers (each rule applied once even if multiple drivers qualify)
- [x] Rules shown as line items on invoice (surcharges positive, discounts negative)
- [x] Snapshot of applied rules stored in `Reservation.pricingRulesApplied` JSON
#### Fuel / Gasoline Policy (Structured)
- [x] `FuelPolicyType` enum: FULL_TO_FULL, FULL_TO_EMPTY, SAME_TO_SAME, PREPAID, FREE
- [x] Multilingual policy description auto-generated from type (EN/FR/AR)
- [x] Optional custom note added by company
- [x] Fuel level recorded at check-in AND check-out via `DamageReport.fuelLevel`
- [x] Policy printed on contract in customer's language
#### Full Invoice Price Breakdown
- [x] Line items: base rental × days, per insurance policy, additional driver (if charged), pricing rule surcharges, pricing rule discounts, security deposit (refundable label)
- [x] Category labels per line: RENTAL, INSURANCE, ADDITIONAL_DRIVER, SURCHARGE, DISCOUNT, DEPOSIT
- [x] Tax/VAT line (if `ContractSettings.showTax = true`)
- [x] Subtotal → discounts → surcharges → insurance → tax → deposit → GRAND TOTAL
- [x] All amounts formatted in company's currency and locale
#### Billing Period Reporting (Accountant Export)
- [x] Reports page at `/dashboard/reports`
- [x] Preset periods: This Week, This Month, This Year, Custom range
- [x] Summary cards: total bookings, base revenue, discounts given, insurance collected, additional driver revenue, net collected
- [x] Full reservations table: contract#, invoice#, customer, vehicle, plate, dates, days, base, discount, insurance, additional driver, pricing adjustments, total, payment status, source
- [x] Export as CSV (one click) — for import into accounting software (QuickBooks, Sage, etc.)
- [x] Report generated on-demand from DB — no pre-computed tables
---
## Phase 2 — Post-Launch
### Fleet Enhancements
- [ ] Maintenance log with cost tracking
- [ ] Maintenance due alerts (date + mileage)
- [ ] Vehicle availability calendar view in dashboard
### CRM Enhancements
- [ ] Repeat customer detection + discount
- [ ] Customer communication log (emails sent)
- [ ] Customer lifetime value stat
### Analytics
- [ ] Revenue chart (day/week/month)
- [ ] Fleet utilization rate + underperforming vehicles alert
- [ ] Offer ROI analysis (revenue gained vs discounted)
- [ ] Marketplace impressions per vehicle
- [ ] CSV export
### Renter Experience
- [ ] Renter "Continue with Google" auth
- [ ] Favorite vehicles across companies
- [ ] Renter profile completion % indicator
- [ ] Booking modification request (change dates)
### Public Site Enhancements
- [ ] About page with company description + team photo
- [ ] Google Maps embed for pickup location
- [ ] "Request to book" mode (no immediate payment)
- [ ] WhatsApp floating button
---
## Phase 3 — Growth
### Custom Domain (Pro)
- [ ] Company enters `cars.acme.com` in /dashboard/brand
- [ ] Vercel API auto-provisions domain
- [ ] DNS instructions shown
- [ ] SSL automatic
### Marketplace Enhancements
- [ ] City/region pages (`/explore/cities/paris`)
- [ ] Renter 2FA
- [ ] Sponsored listing (pay-per-click for marketplace placement)
- [ ] AI-powered vehicle recommendations based on renter history
### Advanced Offers
- [ ] Flash sales (limited time countdown timer)
- [ ] Loyalty program (repeat renter discounts)
- [ ] Bundle offers (car + extras)
### Integrations
- [ ] Google Calendar sync
- [ ] QuickBooks export
- [ ] Zapier webhooks
### Documents — Rental Contracts & Customer Bills
- [x] `ContractSettings` model: per-company legal name, RC/ICE number, tax ID, custom terms, fuel/deposit/damage policies, additional clauses, signature block, footer notes, invoice tax settings, numbering prefixes
- [x] `contractNumber` + `invoiceNumber` fields on Reservation — assigned once via atomic DB transaction, never reset
- [x] `checkInFuelLevel` / `checkOutFuelLevel` fields for contract accuracy
- [x] **Rental Contract PDF** — branded with company logo + name + primary color, contains: customer details, vehicle data + cover photo, rental dates/locations, financial table (rate × days discount + deposit), all policy clauses, full T&Cs, signature lines (company + customer)
- [x] **Customer Invoice PDF** — branded, contains: company legal info + tax ID, bill-to block, line items table (vehicle, deposit, tax if configured), totals (subtotal, discount, tax, grand total), payment details (AmanPay/PayPal transaction ID, paid date), PAID/PENDING stamp
- [x] **Both documents support EN / FR / AR** — all labels, date formats, and currency format per company locale
- [x] **On-demand generation** — PDFs are NEVER stored. Generated fresh from DB data on every request. No Cloudinary PDF upload.
- [x] **Streaming PDF response**`Content-Type: application/pdf`, `Content-Disposition: inline` (view in browser tab) or `attachment` (download)
- [x] **Print from browser** — user opens PDF in new tab and prints via native browser print dialog
- [x] **Email with PDF attachment** — Resend sends email with both documents as attached PDFs
- [x] **Send contract + invoice together** — single API call generates both and attaches both to one email
- [x] **Custom recipient email** — override the customer's email address when sending (for forwarding)
- [x] **Renter self-download** — renter can download their own contract/invoice from `/renter/dashboard`
- [x] **Settings preview** — preview contract/invoice PDF with real company branding + sample data before finalizing settings
- [x] **Automatic triggers**: invoice sent on payment confirmed; contract sent on check-in completed
### Multi-location per company
- [ ] Multiple pickup/return locations
- [ ] Location-aware vehicle assignment
- [ ] Distance filter on marketplace
---
## Out of Scope
- GPS / telematics
- Driver license OCR / ID verification
- Insurance products
- Fuel management
- Peer-to-peer (this is B2B SaaS + B2C marketplace, not P2P)
- Native mobile app (PWA covers push notifications)