Spring Boot + Thymeleaf app: fleet, drivers, vendors, bookings, billing/ settlements, payments, maintenance, inspections, reviews, telematics, audit log, staff/user management, and separate admin/vendor/driver portals. Includes Docker Compose deployment (app + Postgres). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
11 KiB
Car Rental Management System — Implementation Plan
Status: DRAFT for review · Date: 2026-06-26 Baseline: Spring Boot 3.3.4 · Java 17 · Thymeleaf · PostgreSQL · Spring Security (admin + customer chains, Google OAuth2) Purpose: turn the current customer-booking + admin-CRUD app into the full multi-party platform described in the feature spec.
1. Scope summary
The current app covers ~25–30% of the spec (customer-facing booking + basic admin car/booking CRUD). This plan adds the four missing pillars — Driver, Vendor, Billing/Settlement, Reporting — plus the Organization/config foundation and enrichment of Fleet, Customer, and Booking.
Current coverage vs target:
| Area | Now | Target |
|---|---|---|
| Organization / Config | ~20% | Org profile, staff users + permissions, tax/currency/commission config, category masters |
| Fleet & Car | ~45% | + year, colour, ownership, feature tags, hourly/monthly rates, documents+expiry, maintenance |
| Driver | 0% | full module |
| Vendor | 0% | full module + vendor login + settlement |
| Customer | ~50% | + categories (Individual/Company/Corporate), GST/billing |
| Trip Booking | ~40% | + with-driver, hours/months, tax & driver charges, invoice |
| Billing/Settlement | ~5% | invoices, commission, settlements, profit split |
| Reporting | 0% | filtered reports + Excel/PDF export, dashboards |
| Customer page | ~55% | richer filters + driver option |
2. Target architecture
- Single Spring Boot modular-monolith (no microservices). Package-by-feature:
org,fleet,driver,vendor,customer,booking,billing,reporting,web,security,config. - Three security filter chains (extends today's pattern):
/admin/**→ staff (ROLE_ADMIN, ROLE_STAFF) — existing admin chain, expanded/vendor/**→ ROLE_VENDOR — new vendor portal chain- everything else → customers + Google OAuth (existing customer chain)
- Persistence: PostgreSQL + JPA. Move
ddl-auto=update→ Flyway migrations (versioned schema; required once money/settlement tables exist). - Money: always
BigDecimal, scale 2, currency from config. Neverdouble. - Exports: Apache POI (Excel), OpenPDF or Flying Saucer (HTML→PDF) for invoices/statements/reports.
- Server-side rendering stays Thymeleaf; add small JS for dynamic price calc on the customer page.
3. Role & permission model
Replace the 2-value Role enum with a richer model:
Role (enum): ADMIN, STAFF, VENDOR, CUSTOMER
Permission (enum): MANAGE_FLEET, MANAGE_DRIVERS, MANAGE_VENDORS, MANAGE_BOOKINGS,
MANAGE_BILLING, VIEW_REPORTS, MANAGE_CONFIG, MANAGE_USERS
ADMIN= all permissions.STAFF= a configurable subset (stored per-user).VENDOR= scoped to own data only (own cars, own trips, own settlements).- Authorization: method-level
@PreAuthorize("hasAuthority('MANAGE_FLEET')")on services/controllers.
4. Domain model (entities & key fields)
New entities in bold; modified existing in italics.
4.1 Organization / Config
- Organization — name, legalName, logoUrl, address, gstNumber, contactEmail, phone, currencyCode
- SystemConfig (singleton) — currencyCode, defaultTaxPercent, defaultCommissionPercent, defaultDriverDailyCharge, invoicePrefix, settlementCycle (WEEKLY/MONTHLY)
- Category (generic master) —
type(VEHICLE / DRIVER / CUSTOMER), name, description, active → replaces hard-coded enums so categories are admin-configurable - User — add
permissions(set),vendor(nullable FK for vendor-portal users)
4.2 Fleet
- Car — add:
yearOfRegistration,colour,ownership(OWNED / VENDOR),vendor(nullable FK),hourlyRate,dailyRate(rename pricePerDay),monthlyRate,unitsTotal,featureTags(AC, GPS, … as a set/element-collection),status(ACTIVE / MAINTENANCE / RETIRED) - CarDocument — car FK, docType (RC / INSURANCE / PERMIT / POLLUTION), fileUrl, issuedDate, expiryDate
- CarPhoto — car FK, url, sortOrder (gallery instead of single imageUrl)
4.3 Driver
- Driver — name, phone, licenceNumber, licenceExpiry, yearsExperience, category (FK Category), employmentType (EMPLOYED / VENDOR), vendor (nullable FK), hourlyCharge, dailyCharge, monthlyCharge, status (AVAILABLE / ON_TRIP / OFF), photoUrl
- DriverDocument — driver FK, docType, fileUrl, expiryDate
- Trip history derived from
Bookingwheredriver = X
4.4 Vendor
- Vendor — name, contactPerson, phone, email, address, gstNumber, bankAccount/settlementDetails, commissionPercent (nullable → overrides global), active
- Vendor login = a
Userwith ROLE_VENDOR linked to the Vendor - VendorSettlement — vendor FK, periodStart, periodEnd, grossRevenue, commissionAmount, driverCharges, netPayable, status (DRAFT / FINALISED / PAID), generatedAt
4.5 Customer
- User (customer) — add:
customerCategory(INDIVIDUAL / COMPANY / CORPORATE),companyName,gstNumber,billingAddress,contactPersons(for company/corporate)
4.6 Booking & Billing
- Booking — add:
driver(nullable FK),withDriver(bool),rentalUnit(HOUR / DAY / MONTH),quantity(units of the period),vehicleCharge,driverCharge,taxPercent,taxAmount,commissionPercent,commissionAmount,revenueOwner(OWNED / VENDOR),vendor(nullable FK) - Invoice — booking FK, invoiceNumber, issuedAt, lineItems, subtotal, tax, total, pdfUrl
- CommissionRule — scope (GLOBAL / VENDOR / VEHICLE), refId, percent (resolution order: vehicle → vendor → global)
4.7 ER overview (relationships)
Organization 1─* User
User *─1 Vendor (vendor-portal users) Vendor 1─* Car
Vendor 1─* Driver Car 1─* CarDocument / CarPhoto
Category 1─* Car / Driver / User(customer) Driver 1─* DriverDocument
Customer(User) 1─* Booking Car 1─* Booking
Driver 1─* Booking (optional) Booking 1─1 Invoice
Vendor 1─* Booking (revenue attribution) Vendor 1─* VendorSettlement
5. Calculation rules (single source of truth)
periodCount = ceil(duration in chosen unit) // HOUR / DAY / MONTH
vehicleCharge = rate(unit) × periodCount × units
driverCharge = withDriver ? driverRate(unit) × periodCount : 0
subtotal = vehicleCharge + driverCharge
taxAmount = subtotal × taxPercent/100
total = subtotal + taxAmount
// Vendor settlement (per vendor trip)
commissionPercent = resolve(vehicle → vendor → global)
commissionAmount = vehicleCharge × commissionPercent/100
netVendorPayable = vehicleCharge − commissionAmount + (vendorDriverCharge − orgDriverMargin)
// Owned vs vendor profit split tracked via Booking.revenueOwner
All money BigDecimal, RoundingMode.HALF_UP, scale 2, currency from SystemConfig.
6. Screen inventory
Admin / Staff (/admin)
- Dashboard (KPIs + owned-vs-vendor split), Fleet (list/form + docs/photos/maintenance), Drivers (list/form/profile + trip history), Vendors (list/form + settlements), Customers (list/detail), Bookings (list/detail/assign-driver/invoice), Billing & Settlements, Reports (filter + export), Settings (org, config, categories, staff & permissions)
Vendor portal (/vendor) — new
- Login, Dashboard (own trips/revenue), My Cars, My Drivers, Trips (period filter), Settlements (view + export PDF/Excel)
Customer page (public)
- Home, Car listing with filters (category, date, seating, transmission, price, driver option) + live price, Car detail, Booking (with/without driver + category), Register/Login, My Bookings + invoices
7. Phased delivery plan
Each phase is independently shippable and ends with a working app + tests.
Phase 0 — Foundations (enablers)
- Add Flyway; convert current schema to
V1__baseline.sql; turn offddl-auto - Expand
Role+ addPermission; method security Organization+SystemConfig+Categorymaster; Settings screens- Replace hard-coded category enums with
Categorylookups (keep enums as seed data)
Phase 1 — Fleet enrichment
- Car: year, colour, ownership, feature tags, hourly/daily/monthly rates, units, status(maintenance)
- CarDocument + CarPhoto with expiry tracking + expiry warnings on dashboard
- Maintenance blocking in availability logic
Phase 2 — Driver module
- Driver entity + documents + categories + charges + availability
- Driver list/form/profile + trip history; driver-availability check
Phase 3 — Vendor module
- Vendor onboarding + ROLE_VENDOR login + vendor filter chain (
/vendor/**) - Vendor dashboard (own cars/drivers/trips); commission config (global/vendor/vehicle)
Phase 4 — Booking upgrades
- With/without driver + driver category assignment
- Hourly/daily/monthly periods; tax + driver-charge calc; revenue attribution
- Driver double-booking prevention; invoice generation (PDF)
Phase 5 — Billing & settlement
- Invoices/receipts for customers
- Vendor settlement aggregation per cycle + statement (Excel + PDF) + profit split
Phase 6 — Reporting
- Filtered reports (date, vehicle, category, driver, vendor, customer category, ownership, status)
- Excel + PDF export; summary dashboard (owned vs vendor); vendor-wise & driver-wise reports
Phase 7 — Customer page polish
- Full filter set + live cost-by-duration; with-driver booking flow; responsive QA
8. Dependencies to add
flyway-core+flyway-database-postgresqlorg.apache.poi:poi-ooxml(Excel)com.github.librepdf:openpdfororg.xhtmlrenderer:flying-saucer-pdf(PDF from Thymeleaf)- (already present: web, security, oauth2-client, data-jpa, validation, thymeleaf, postgresql, lombok)
9. Cross-cutting concerns
- Migrations: every schema change via Flyway; never edit a shipped migration.
- Validation: bean validation + show
th:errorson all admin/vendor forms (current admin forms lack this). - Auditing:
createdAt/updatedAt/createdByvia JPA auditing on money-bearing entities. - Performance: fix N+1 in booking/report queries with fetch-joins; add pagination to all admin tables.
- Files: documents/photos need storage — decide local disk vs S3-compatible (config-driven path).
- Testing: service-layer unit tests for all calc rules;
@WebMvcTestfor access control per chain. - Seed data: keep
DataInitializerfor org/config/admin + demo vendor/driver/cars.
10. Decisions (LOCKED — 2026-06-26, recommended defaults accepted)
- File storage → local filesystem (config-driven path) for v1.
- PDF library → Flying Saucer (Thymeleaf HTML/CSS → PDF).
- Tenancy → single organization per install.
- Staff permissions → per-user permission checkboxes (granular
Permissionset). - Settlement cycle → monthly default.
- Bookings → day/month for v1 (hourly rate fields stored, hourly booking flow deferred).
Deviation from §7
- Flyway is deferred to a later hardening phase. During active development the app keeps
spring.jpa.hibernate.ddl-auto=update, which additively creates the new tables/columns without disrupting the running PostgreSQL database. Flyway baseline will be introduced before production.
Plan locked. Implementation started with Phase 0 — Foundations.