## 1. Requirements
### 1.1 Functional Requirements (FR)
#### Core Operations
* **Vehicle Entry**:
* Detect vehicle at entry gate and identify type (CAR, MOTORBIKE, TRUCK, EV, etc.).
* Assign a suitable parking spot or deny entry if the lot is full.
* Issue a ticket (QR, barcode, or license-plate-linked) with an entry timestamp.
* **Vehicle Exit**:
* Scan ticket/license plate at the exit gate.
* Compute fees based on duration and pricing rules.
* Accept multiple payment methods and open the barrier upon success.
* Close the ticket and free the assigned spot.
* **Spot Allocation**:
* Support multiple spot types: `COMPACT`, `LARGE`, `MOTORBIKE`, `EV_CHARGING`, `DISABLED`.
* Configurable allocation rules: Closest-to-entry, floor preference, EV-only, etc.
* **Real-time Availability**:
* Query available spots by lot, floor, or spot-type.
* Provide real-time counts and zone-based guidance.
* **Payments**:
* Support cash (optional), card, and e-wallets.
* Handle refund/cancel policies and grace periods.
* Support lost-ticket fee policies.
#### Management & Audit
* **Admin Operations**:
* Manage parking lot structure (lots, floors, spots).
* Configure pricing rules and seasonal promotions.
* Manual overrides: Force open/close gates, mark spots for maintenance.
* **Enforcement & Audit**:
* Maintain a complete history of tickets, payments, and spot changes.
* Manual dispute handling and overrides.
#### Nice-to-Have
* **License Plate Recognition (LPR)**: Automated entry/exit without physical tickets.
* **Reservations**: Pre-booking for premium members or special events.
* **Multi-lot Management**: Portfolio-wide management from a single interface.
### 1.2 Non-Functional Requirements (NFR)
* **Availability**: Gates must remain operational even if cloud connectivity is lost (99.9%+ target).
* **Latency**: Fast throughput at gates; ticket issuance and allocation should be `< 300ms p95`.
* **Consistency**: Strong consistency for spot occupancy to prevent double-allocation.
* **Scalability**: Handle peak bursts (e.g., stadium events) with high contention on allocation.
* **Reliability**: Offline-first edge support with local cache synchronization.
* **Security**: Role-Based Access Control (RBAC), audit logs, and PCI compliance (tokenization).
* **Data Privacy**: Encryption of PII (license plates) at rest and clear retention policies.
## 2. API Design
### 2.1 Key Domain Objects
```json
{
"ParkingLot": {
"lotId": "string",
"name": "string",
"address": "string",
"timezone": "string"
},
"Floor": {
"floorId": "string",
"lotId": "string",
"level": "integer"
},
"Spot": {
"spotId": "string",
"floorId": "string",
"type": "COMPACT | LARGE | MOTORBIKE | EV_CHARGING | DISABLED",
"status": "AVAILABLE | OCCUPIED | OUT_OF_SERVICE | RESERVED",
"zone": "string"
},
"Ticket": {
"ticketId": "string",
"lotId": "string",
"vehicle": { "plate": "string?", "type": "string" },
"entryGateId": "string",
"entryAt": "ISO8601",
"assignedSpotId": "string",
"status": "ACTIVE | CLOSED | LOST"
},
"Payment": {
"paymentId": "string",
"ticketId": "string",
"amount": "decimal",
"currency": "string",
"method": "CARD | CASH | WALLET",
"status": "string",
"providerRef": "string"
}
}
```
### 2.2 Public-facing APIs
#### Entry Flow
`POST /v1/tickets/entry`
```json
// Request
{
"lotId": "L1",
"gateId": "GATE_E_01",
"vehicle": { "type": "CAR", "plate": "SGP1234A" },
"preferences": { "needEvCharging": false, "needDisabled": false }
}
// Response
{
"ticketId": "T_9f...",
"issuedAt": "2026-02-24T10:01:22+08:00",
"spot": { "spotId": "S_2_041", "floorId": "F2", "zone": "B" },
"barcode": "....",
"status": "ACTIVE"
}
```
#### Exit Quote
`GET /v1/tickets/{ticketId}/quote`
```json
{
"ticketId": "T_9f...",
"entryAt": "...",
"exitAt": "...",
"amount": 6.50,
"currency": "SGD",
"breakdown": [{"rule": "weekday_hourly", "amount": 6.50}]
}
```
#### Payment
`POST /v1/payments`
```json
{
"ticketId": "T_9f...",
"method": "CARD",
"paymentToken": "tok_xxx",
"idempotencyKey": "uuid-unique"
}
```
#### Exit Confirmation
`POST /v1/tickets/{ticketId}/exit`
```json
{
"gateId": "GATE_X_02",
"paidPaymentId": "P_12...",
"vehiclePlate": "SGP1234A"
}
```
#### Availability
`GET /v1/lots/{lotId}/availability?spotType=COMPACT`
```json
{ "lotId": "L1", "counts": { "COMPACT": 120, "EV_CHARGING": 8 } }
```
### 2.3 Admin APIs
* `PUT /v1/spots/{spotId}`: Update status or type.
* `POST /v1/pricingRules/publish`: Publish a new rule version.
* `GET /v1/reports/occupancy?from=...&to=...`: Generate occupancy reports.
### 2.4 API Correctness Rules
1. **Idempotency**: All state-changing endpoints must support `Idempotency-Key` to safely handle retries.
2. **Concurrency**: Gate endpoints must tolerate retries without double-allocating spots.
3. **Clock Source**: Use server time (anchored to the lot's timezone) for all billing calculations.
## 3. High-Level Design
### 3.1 Architecture Style (Edge + Central)
The system follows a classic hybrid architecture:
* **Edge (On-prem)**: Local gate controllers for low-latency hardware integration and offline fallback.
* **Central (Cloud)**: Portfolio management, global pricing rules, reporting, and payment orchestration.
### 3.2 Logical Services
* **Gate Service (Edge)**: Hardware interfacing (barriers, scanners, LPR) with local fallback logic.
* **Ticket Service**: Manages ticket lifecycle (Active -> Closed/Lost).
* **Spot Inventory Service**: Source of truth for spot states and real-time counts.
* **Allocation Service**: Policy-based engine for choosing the best available spot.
* **Pricing Service**: Versioned engine to compute fees based on duration and lot rules.
* **Payment Service**: Integrates with Payment Service Providers (PSP) and manages transaction states.
* **Event Bus**: Kafka/Pulsar stream for propagating state changes (TicketCreated, SpotOccupied) to analytics and monitoring.
### 3.3 Data Stores
* **Spot Inventory DB**: Requires strong consistency (Postgres with row-level locks or Redis + Lua).
* **Ticket DB**: Transactional store, partitioned by `lotId` or time for performance.
* **Event Store**: Distributed log (Kafka) for durable event streaming.
## 4. Detailed Component Design
### 4.1 Spot Inventory + Allocation
#### Atomic Reservation Algorithm
To prevent overselling, spot status updates must be atomic:
```sql
-- Select candidate spots by policy
SELECT spot_id FROM spots
WHERE lot_id = ? AND type = ? AND status = 'AVAILABLE'
ORDER BY distance_to_gate ASC
LIMIT 10;
-- Atomic update
UPDATE spots
SET status = 'OCCUPIED'
WHERE spot_id = ? AND status = 'AVAILABLE';
-- If RowsAffected == 1, allocation succeeded.
```
#### Performance Optimization: Zone-Counters
Maintain a `zone_availability` table with transactional counters:
1. Identify a zone with `available_count > 0`.
2. Query for spots only within that high-probability zone to reduce lock contention across the entire table.
### 4.2 Ticket Service
* **State Machine**: `ACTIVE` → (`CLOSED` | `LOST`). `CLOSED` requires payment satisfaction.
* **Plate Handling**: License plates are hashed and encrypted. Original values are stored only if required for compliance.
### 4.3 Pricing Service
Uses a versioned JSON rules engine to build a timeline:
* Evaluate time bands (hourly, daily, flat).
* Apply priority rules (holidays, guest types).
* Return a transparent breakdown for the user.
### 4.4 Payment Service
* **States**: `INITIATED` -> `AUTHORIZED` -> `CAPTURED/FAILED` -> `REFUNDED`.
* **PSP Integration**: Uses tokenization to minimize PCI scope on internal systems.
### 4.5 Edge Gate Service (Offline-First)
* **Local Fallback**: Gate keeps a cache of availability and pricing rules.
* **Conflict Mitigation**: If offline, issue tickets with a local sequence prefix and sync upon restoration. Operates on a "pre-allocated quota" to prevent overselling while disconnected.
### 4.6 Observability
* **Allocation Accuracy**: Cross-check sensor data vs database states.
* **Latency Metrics**: Track p95 for entry/exit gates.
* **Operational Health**: Monitor offline mode durations and synchronization success rates.