Project case study
ChargeOps Backend.
Spatial booking API and EV charging operations platform
The ChargeOps backend powers spatial station discovery, time-slot bookings, payments and refunds, role-scoped operations, and real-time notifications. It is a Java 21 and Spring Boot application backed by PostgreSQL/PostGIS, Redis, Elasticsearch, Kafka, and Keycloak.
The problem
A driver reservation must remain consistent across payment, check-in, cancellation, and station operations.
My contribution
Defined domain rules, implemented booking and payment workflows, built driver and management interfaces, and maintained project documentation.
Current scope
Final-year software project with web/mobile surfaces and API integration. Charging telemetry is simulated; this is not evidence of a deployed commercial charging network.
A decision in context.
Choice
Keep booking and refund states explicit. The current policy gives a full refund during the eligible grace period, and no voluntary refund after it. Verified station incidents follow a separate review path.
Verification
Compare a scenario against the current policy and trace its booking, payment, and refund states in the implementation. The earlier tiered 100/50/0 policy is obsolete.
Limits
This case study documents implementation and policy decisions; it does not claim commercial usage or independently measured performance.
Key takeaway
The challenge extends beyond a booking screen: payment states, cancellations, refunds, and permissions all need to agree.
Project decisions
What went into
the project.
Spatial Discovery with PostGIS & Elasticsearch
Location-based discovery using PostgreSQL 16 + PostGIS 3.4 (ST_DWithin, ST_DistanceSphere, GIST spatial index) paired with Elasticsearch 9.4.2 for multi-criteria filtering across connector types (CCS2, Type 2, GB/T, CHAdeMO) and real-time power capacity.
10-Minute Hold Lock & Concurrency Defense
During payment, Redis 7 distributed locking holds the requested connector and time range for 10 minutes. The temporary hold reduces booking conflicts while a driver completes checkout.
Transactional Outbox with Apache Kafka
Uses an at-least-once delivery design for critical billing, charging state changes, and notifications using Apache Kafka 4.1.2 (KRaft) and the Transactional Outbox pattern, decoupling synchronous booking commits from downstream side effects.
Multi-Role IAM & Financial Ledger
Keycloak 26.0.8 provides role-based access for drivers, station staff, owners, and platform administrators. Booking earnings and refund liabilities stay in the station owner's double-entry ledger; administrators handle financial disputes case by case, and staff have no financial access.
Check-In Window & Charging Lifecycle
Drivers check in with a connector QR code from the booking start time through the cutoff at 15 minutes before the slot ends. Unclaimed reservations are cancelled as no-shows at the cutoff; active sessions move through checked-in, charging, and completed states with simulated energy and duration telemetry.
Refund Policy & Dispute Handling
The BKG-067 policy grants a full package refund within the 10-minute grace period after payment, before the slot starts and before check-in. Voluntary post-grace cancellations and no-shows receive no refund. Verified station hardware failures can qualify for a full refund through owner or administrator review.
Policy Assistant & Role-Scoped Operations
An owner-only Dify RAG assistant answers questions from bilingual operational and legal documents, with conversation recovery and daily quotas. Backend authorization separates owner ledger access, staff equipment workflows, and administrator governance and dispute review.
Transactional Outbox & Notifications
Booking status changes are written to a database outbox in the same transaction, then dispatched through Kafka. WebSocket/STOMP private queues notify clients about inbox and refund updates; email handles booking confirmations and cancellations.
Implementation
Tools & systems
- Java 21
- Spring Boot
- PostgreSQL 16
- PostGIS 3.4
- Apache Kafka 4.1.2
- Redis 7
- Elasticsearch 9.4.2
- Keycloak 26
- Flyway (V1-V65+)
- Docker
- Prometheus & Grafana