How erkamvural/ev_csms works
1. Overall shape
- This repository is a modular monolith for EV charging station management.
- It has two deployable applications: a FastAPI backend and a React/Vite frontend, composed around business-capability modules rather than technical layers.
2. Runtime and infrastructure
- Local/runtime stack is driven by Docker Compose.
- Core infrastructure includes PostgreSQL with PostGIS, Redis, the backend API on port 8000, and the frontend on port 3000.
- Database schema changes are managed with Alembic and run automatically at startup.
3. Backend architecture pattern
- Each backend module follows the same internal structure: domain, adapters, service_layer, entrypoints, and tests.
- This is strongly aligned with Cosmic Python / DDD: domain logic stays isolated, repositories and ORM mappings sit in adapters, and HTTP concerns live only in entrypoints.
4. Main backend modules
- identity: authentication, user management, roles/permissions, JWT handling, RBAC.
- station_catalog: charging station and charger metadata, nearby/searchable station views, and sync with external map data.
- charging: charging session lifecycle, meter simulation, auto-stop scheduling, cost calculation.
- reservation: reservation lifecycle, missed-reservation checks, reservation scheduling.
- payments: wallet/top-up/hold/refund flows and integration with a payment gateway.
- notification: email/SMS notification generation and delivery.
- audit: immutable audit logging of actions.
- reporting: analytical/read-model style data for dashboards and operational reporting.
5. Core backend data flow
- Requests enter through a module’s FastAPI router in entrypoints/api.py.
- The router calls a service-layer handler, which applies business rules inside the domain model.
- Changes are persisted through a Unit of Work and repository abstraction into PostgreSQL.
- Domain events are emitted through the shared messaging layer and can trigger other modules asynchronously or synchronously.
6. Cross-module coordination
- The backend is intentionally decoupled: modules do not appear to share a single large service layer.
- Coordination happens mainly through domain events and the shared_kernel/message_bus.py rather than direct tight coupling.
- This is important for the architecture diagram: modules are peers connected through events, not a layered “global services” blob.
7. Identity and access boundary
- Authentication uses JWT, and authorization is enforced with RBAC.
- The frontend has an AuthContext and permission utilities, while the backend identity module owns token issuance, user repositories, and role logic.
- Other modules likely consume identity claims rather than reimplementing access control.
8. Station catalog and external geospatial services
- Station catalog is the boundary to Google Maps / Google Places integrations.
- It also owns station syncing jobs and nearby-station queries, which depend on location-aware persistence in PostGIS.
- On the frontend, this appears as map views, station lists, filters, and geolocation-driven discovery.
9. Charging, reservation, and payments workflow
- Charging manages active sessions, meter progression, and stopping logic, including scheduled/automatic shutdown.
- Reservation handles booking and expiry/missed-reservation handling.
- Payments manages wallet balances, reserved funds, deductions, releases, refunds, and gateway integration; the presence of iyzico_gateway.py indicates an external PSP integration.
- These three modules form the transactional core of the system and likely exchange events for deposit, reservation, and charging outcomes.
10. Notifications, audit, and reporting as downstream consumers
- notification turns events into user-facing email/SMS messages using template rendering plus provider adapters.
- audit records system actions for traceability and compliance.
- reporting consumes persisted operational data to provide dashboard metrics, station performance, financial analytics, and user activity views.
- These modules are read-heavy or event-driven and should be shown as downstream of the transactional modules.
11. Frontend structure
- The frontend is organized by feature slices matching backend capabilities: identity, station catalog, charging, reservation, payments, notification, audit, reporting.
- Each feature has its own API client, hooks, components, and types.
- Shared UI primitives, a common Axios instance, and an event bus live under src/shared.
12. Frontend-to-backend communication
- UI components call feature-specific API wrappers, which use a shared HTTP client to reach the backend.
- Hooks encapsulate data fetching and mutations, while pages compose feature components into screens.
- This makes the frontend a thin orchestration layer over backend module APIs rather than a separate domain system.
13. Persistence and operational scripts
- PostgreSQL is the source of truth for application data.
- Alembic migrations include the initial schema and seed data for admin/stations.
- There are also repository-level scripts for backfills, checks, exports, and seed operations, which support operational data maintenance.
14. Tests and quality boundaries
- Each backend module has both unit and integration tests, plus repository-level e2e tests.
- This reinforces the module boundary: domain rules are tested apart from persistence and API wiring.
- The repo also contains multiple test/report artifacts, suggesting significant verification around critical flows like charging, reservations, payments, and user deletion.
15. How to draw the architecture
- A good diagram would show: Frontend feature modules → backend FastAPI module routers → service layer → domain/repositories → PostgreSQL/PostGIS.
- Surrounding that core, show external services for Google Maps/Places, email/SMS, payment gateway, plus Redis and background schedulers.
- Add event flows from charging/reservation/payments/identity into notification, audit, and reporting to capture the system’s main coupling mechanism.
Main entry points: App.tsx App shell · main.py API app · docker-compose.yaml PostgreSQL · shared_kernel Shared kernel
Components 25
Frontend
React/Vite feature-sliced UI
- App shell · Routes, pages, and feature composition
EV_CSMS/frontend/src/app/App.tsx - Shared UI · Axios client, event bus, reusable primitives
EV_CSMS/frontend/src/shared - Identity UI · Auth, profile, permissions, vehicles
EV_CSMS/frontend/src/features/identity - Station UI · Map views, discovery, station browsing
EV_CSMS/frontend/src/features/station_catalog - Charging UI · Session control, progress, history
EV_CSMS/frontend/src/features/charging - Reservation UI · Create and manage reservations
EV_CSMS/frontend/src/features/reservation - Payments UI · Wallet, top-up, transactions
EV_CSMS/frontend/src/features/payments - Notification UI · Notification inbox and status
EV_CSMS/frontend/src/features/notification - Audit UI · Audit log browsing and filters
EV_CSMS/frontend/src/features/audit - Reporting UI · Dashboards and analytics views
EV_CSMS/frontend/src/features/reporting
Backend
FastAPI modular monolith
- API app · Application startup and router assembly
EV_CSMS/backend/app/main.py - Shared kernel · Auth helpers, domain base, message bus
EV_CSMS/backend/shared_kernel - Identity · JWT auth, users, roles, RBAC
EV_CSMS/backend/modules/identity - Station catalog · Stations, chargers, search, sync
EV_CSMS/backend/modules/station_catalog - Charging · Session lifecycle, meters, auto-stop
EV_CSMS/backend/modules/charging - Reservation · Booking, expiry, missed checks
EV_CSMS/backend/modules/reservation - Payments · Wallet, holds, refunds, gateway
EV_CSMS/backend/modules/payments - Notification · Email/SMS generation and delivery
EV_CSMS/backend/modules/notification - Audit · Immutable action logging
EV_CSMS/backend/modules/audit - Reporting · Read models and analytics
EV_CSMS/backend/modules/reporting
Infra
Local runtime, database, migrations
- PostgreSQL · Source of truth with PostGIS
EV_CSMS/docker-compose.yaml - Alembic · Schema and seed migrations
EV_CSMS/backend/alembic - Compose stack · Backend, frontend, Redis, database
EV_CSMS/docker-compose.yaml - Redis · Shared cache and async support
EV_CSMS/docker-compose.yaml
External
Third-party services
- External services · Google Maps/Places, email/SMS, payment gateway
Connections 48
- App shell → Shared UI: uses · Pages and features share HTTP, events, and UI primitives
- App shell → Identity UI: composes · App routes identity screens
- App shell → Station UI: composes · App routes station discovery screens
- App shell → Charging UI: composes · App routes charging screens
- App shell → Reservation UI: composes · App routes reservation screens
- App shell → Payments UI: composes · App routes wallet and payment screens
- App shell → Notification UI: composes · App routes notification screens
- App shell → Audit UI: composes · App routes audit screens
- App shell → Reporting UI: composes · App routes reporting screens
- Identity UI → Identity: API · Auth and profile flows call the identity backend
- Station UI → Station catalog: API · Station search and map views query catalog endpoints
- Charging UI → Charging: API · Session control talks to charging endpoints
- Reservation UI → Reservation: API · Reservation screens call reservation endpoints
- Payments UI → Payments: API · Wallet and transaction flows call payments endpoints
- Notification UI → Notification: API · Notification screens read notification endpoints
- Audit UI → Audit: API · Audit views read audit endpoints
- Reporting UI → Reporting: API · Dashboards read reporting endpoints
- API app → Identity: routes · FastAPI mounts identity routers
- API app → Station catalog: routes · FastAPI mounts station catalog routers
- API app → Charging: routes · FastAPI mounts charging routers
- API app → Reservation: routes · FastAPI mounts reservation routers
- API app → Payments: routes · FastAPI mounts payments routers
- API app → Notification: routes · FastAPI mounts notification routers
- API app → Audit: routes · FastAPI mounts audit routers
- API app → Reporting: routes · FastAPI mounts reporting routers
- Identity → Shared kernel: bus/auth · Uses shared auth and message bus primitives
- Station catalog → Shared kernel: bus · Publishes and consumes domain events through shared kernel
- Charging → Shared kernel: bus · Publishes and consumes domain events through shared kernel
- Reservation → Shared kernel: bus · Publishes and consumes domain events through shared kernel
- Payments → Shared kernel: bus · Publishes and consumes domain events through shared kernel
- Notification → Shared kernel: bus · Consumes domain events for delivery
- Audit → Shared kernel: bus · Consumes domain events for logging
- Reporting → Shared kernel: bus · Consumes persisted events and read data
- Identity → PostgreSQL: persist · Identity state stored in PostgreSQL
- Station catalog → PostgreSQL: persist · Stations and geospatial data stored in PostgreSQL/PostGIS
- Charging → PostgreSQL: persist · Charging sessions and meter state stored in PostgreSQL
- Reservation → PostgreSQL: persist · Reservations and expiry state stored in PostgreSQL
- Payments → PostgreSQL: persist · Wallet and transaction state stored in PostgreSQL
- Notification → PostgreSQL: persist · Notification records stored in PostgreSQL
- Audit → PostgreSQL: persist · Audit log stored immutably in PostgreSQL
- Reporting → PostgreSQL: read model · Reporting queries and analytics are read from PostgreSQL
- Alembic → PostgreSQL: migrate · Alembic creates and seeds schema
- Compose stack → API app: runs · Compose starts the API service
- Compose stack → App shell: runs · Compose starts the web client
- Compose stack → PostgreSQL: includes · Compose provides PostgreSQL/PostGIS
- Compose stack → Redis: includes · Compose provides Redis
- Station catalog → External services: maps · Station sync and nearby search use Google Maps/Places
- Notification → External services: deliver · Email and SMS providers are used for outbound notifications