Overview
Every reservation in PaparcApp follows a 4-state lifecycle from creation to completion. Each state has specific rules about what actions can be performed and which transitions are allowed.Database Table:
Status Column:
DAO:
Main Controllers:
reservationStatus Column:
status (VARCHAR)DAO:
models/reservation-dao.jsMain Controllers:
adminController.js, authController.jsState Diagram
State Definitions
PENDIENTE (Pending)
PENDIENTE (Pending)
Meaning: Reservation created but vehicle has not arrived yetAllowed Actions:
- ✅ Edit dates, services (customer & admin)
- ✅ Cancel (customer & admin)
- ✅ Assign parking spot (admin)
- ✅ Upload photos (admin)
- ✅ Start check-in (admin, if requirements met)
- ❌ Cannot finalize (must be EN CURSO first)
- ❌ Cannot edit if less than 5 photos for check-in
- ❌ Cannot start without parking spot assigned
- Public booking form (
/booking) - Admin walk-in form (
/admin/reservations/new)
EN CURSO (In Progress)
EN CURSO (In Progress)
Meaning: Vehicle has checked in and is currently parked in the facilityAllowed Actions:
- ✅ Edit exit date and services (customer & admin)
- ✅ Update vehicle/customer info (admin)
- ✅ Upload more photos (admin)
- ✅ Finalize check-out (admin, with payment)
- ❌ Cannot cancel (vehicle already inside)
- ❌ Cannot edit entry date (already happened)
- ❌ Parking spot cannot be cleared (must remain assigned)
FINALIZADA (Finished)
FINALIZADA (Finished)
Meaning: Vehicle has checked out and customer has paidAllowed Actions:
- 👁️ View only (read-only for all users)
- ❌ Cannot edit any fields
- ❌ Cannot cancel
- ❌ Cannot upload photos
- ❌ Cannot change status
is_paid=truepayment_method='EFECTIVO'or'TARJETA'
CANCELADA (Cancelled)
CANCELADA (Cancelled)
Meaning: Reservation was cancelled (customer no-show or explicit cancellation)Allowed Actions:
- 👁️ View only (appears in history)
- ❌ Cannot edit
- ❌ Cannot reactivate
- ❌ Cannot transition to any other state
cod_parking_spotset toNULL(frees parking spot)
State Transitions
1. PENDIENTE → EN CURSO (Check-in)
Pre-conditions
Admin must ensure:
- Minimum 5 photos uploaded
- Parking spot assigned (
cod_parking_spotnot NULL) - Current status is PENDIENTE
Trigger Action
Admin clicks “Receive Vehicle” button in reservation details pageRoute:
Controller:
PATCH /admin/reservations/:id/startController:
adminController.js:startReservation() (line 396-430)Why 5 photos? This is PaparcApp’s business rule to document vehicle condition (front, rear, sides, dashboard, interior) to protect against damage disputes.
2. PENDIENTE → CANCELADA (Cancellation)
Who Can Cancel
- Customer: Via profile page (if logged in and reservation owner)
- Admin: Via reservation details page
Customer Cancellation
Route:
Controller:
DELETE /users/profile/reservation/:id/cancelController:
authController.js:cancelReservation() (line 348-379)Admin Cancellation
Route:
Controller:
PATCH /admin/reservations/:id/cancelController:
adminController.js:cancelReservation() (line 350-386)3. EN CURSO → FINALIZADA (Check-out)
Trigger Action
Admin clicks “Finalize and Check Out” buttonRoute:
Controller:
PATCH /admin/reservations/:id/finalizeController:
adminController.js:finalizeReservation() (line 440-475)Payment Method Selection
Frontend shows SweetAlert2 modal with options:
- EFECTIVO (Cash)
- TARJETA (Card)
Photo Evidence Workflow
Why Photos Are Required
Customer Protection
Proves vehicle condition at arrival to avoid false damage claims
Business Protection
Documents pre-existing damage to avoid liability for prior issues
Upload Process
Submit Photo
POST
Controller:
/admin/reservations/:id/photosController:
adminController.js:addPhoto() (line 486-526)Request body:Photo Data Model
Table:photo_evidence
file_path: URL to image (e.g., Cloudinary, S3, or local path)description: Optional text (e.g., “Front bumper”, “Interior dashboard”)taken_at: Auto-generated timestamp
Photo Retrieval
Photos are fetched with reservation details:Payment Processing
Current Implementation
Payment Fields inreservation table:
is_paid(BOOLEAN):falseby default,truewhen finalizedpayment_method(VARCHAR):NULL,'EFECTIVO', or'TARJETA'
Finalization Flow
- Admin clicks “Finalize”
- Modal prompts for payment method
- Admin confirms customer paid (cash/card)
- Backend sets
is_paid = trueand stores method - Reservation moves to FINALIZADA
Future Payment Integration
To add real payment processing:Pre-payment for Online Bookings
- Integrate Stripe/PayPal in booking flow
- Store
payment_intent_idin database - Set
is_paid = trueimmediately
On-site Payment Terminal
- Integrate POS system API
- Fetch payment status before finalizing
- Store transaction ID
Business Rules Summary
Editing Rules
Editing Rules
| Status | Entry Date | Exit Date | Services | Vehicle Info | Parking Spot | Photos |
|---|---|---|---|---|---|---|
| PENDIENTE | ✅ | ✅ | ✅ | ✅ (admin) | ✅ | ✅ |
| EN CURSO | ❌ | ✅ | ✅ | ✅ (admin) | ✅ | ✅ |
| FINALIZADA | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| CANCELADA | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Cancellation Rules
Cancellation Rules
- Only PENDIENTE reservations can be cancelled
- Customers can cancel their own PENDIENTE bookings
- Admins can cancel any PENDIENTE booking
- EN CURSO reservations cannot be cancelled (must finalize)
Check-in Requirements
Check-in Requirements
All must be met to transition PENDIENTE → EN CURSO:
- Status is PENDIENTE
- Minimum 5 photos uploaded
- Parking spot assigned (not NULL)
Check-out Requirements
Check-out Requirements
All must be met to transition EN CURSO → FINALIZADA:
- Status is EN CURSO
- Payment method selected (EFECTIVO or TARJETA)
Pricing Rules
Pricing Rules
- Price always recalculated on server when editing
- Client-submitted prices ignored (security)
- Calculated by
pricingService.calculateTotalPrice():- Base rate from service tier × days
- Multiplied by vehicle type coefficient
- Plus additional services (fixed prices)
Database Schema
Reservation Table
status: State machine valueis_paid: Payment flagcod_parking_spot: Assigned spot code (e.g., “A-15”)reservation_date: When booking was created (audit trail)
Related Tables
Transaction Safety
All state changes use database transactions to ensure atomicity:If any step fails (e.g., foreign key violation), the entire transaction rolls back—no partial updates.
Code References
| Feature | File | Line Range |
|---|---|---|
| Start Reservation | controllers/adminController.js | 396-430 |
| Finalize Reservation | controllers/adminController.js | 440-475 |
| Cancel Reservation (Admin) | controllers/adminController.js | 350-386 |
| Cancel Reservation (Customer) | controllers/authController.js | 348-379 |
| Edit Reservation (Customer) | controllers/authController.js | 382-436 |
| Add Photo Evidence | controllers/adminController.js | 486-526 |
| Create Reservation | models/reservation-dao.js | 239-354 |
| Update Reservation | models/reservation-dao.js | 140-228 |
| Start DAO Method | models/reservation-dao.js | 469-493 |
| Finalize DAO Method | models/reservation-dao.js | 502-528 |
| Cancel DAO Method | models/reservation-dao.js | 438-459 |
| Add Photo DAO Method | models/reservation-dao.js | 539-566 |
| Get Full Reservation | models/reservation-dao.js | 65-130 |
Error Scenarios
Best Practices
Always Recalculate Price
Never trust client-submitted prices. Always recalculate on server using
pricingService.calculateTotalPrice()Validate State Before Transition
Check current status before allowing any state change to prevent invalid workflows
Use Transactions
Wrap multi-table updates in BEGIN/COMMIT transactions to ensure data consistency
Lock Critical Fields
Make entry date read-only when EN CURSO to prevent backdating after check-in
Next Steps
Public Booking
How reservations are created
User Profile
Customer reservation management
Admin Dashboard
Staff processing workflows
