Skip to content
All case studies
production2024 — Present · Enterprise construction group

Construction ERP Platform

A 50+ endpoint production ERP backend — attendance, CRM, procurement, site management, and finance — designed and shipped from a blank repo.

Node.jsTypeScriptExpressSequelizeMySQL 8JWTZodPDFKitRenderRailway

50+

REST endpoints

4

User roles (RBAC)

5

Enterprise modules

15 min

Access-token TTL

The problem

A construction group ran attendance, procurement, and finances across spreadsheets and WhatsApp. Field data was unverifiable, purchase orders had no audit trail, and month-end reconciliation took days. They needed one system of record that field staff, site engineers, accountants, and directors could all trust — each seeing only what their role allows.

Architecture

architecture · Construction ERP Platform
Field / Admin ClientsReact · 4 rolesAuth LayerJWT + refresh queueREST API50+ endpoints · ZodRBAC Middlewareper-route gatesService Layerstate machines · auditMySQL 8Railway · IST-awareCron Jobsoverdue · reports
  • Clean architecture: Route → Controller → Service → Repository, so business rules never leak into HTTP handlers and every module is testable in isolation.
  • Zod schemas validate every request at the boundary; a centralised AppError hierarchy and consistent JSON response envelope keep failure modes predictable across 50+ endpoints.
  • JWT auth with 15-minute access tokens and 7-day rotating refresh tokens. A race-condition-safe parallel refresh queue means ten simultaneous requests with an expired token trigger exactly one refresh — not ten.
  • Granular RBAC middleware gates every endpoint by role (admin, site engineer, accountant, field staff) with permission checks composed per-route, not hard-coded per-controller.
  • GPS-verified attendance: Haversine geofencing validates check-ins against site coordinates, Multer handles selfie capture, and IST-aware MySQL date logic eliminates an entire class of timezone bugs.
  • Material procurement modelled as an explicit state machine (MRN → PO → delivery → inventory) with a full audit trail — invalid transitions are impossible by construction.
  • Financial reconciliation engine: partial payment tracking, cron-driven overdue detection, and P&L / GST report generation rendered to PDF with PDFKit.

Key engineering challenges

Concurrent token refresh under field conditions

Field devices on poor networks fire bursts of parallel requests. When the access token expires, naive interceptors trigger N refresh calls and refresh-token rotation invalidates all but one — logging users out randomly. I built a promise-queue: the first 401 triggers the refresh, subsequent requests await the same promise, and everything retries with the new token.

Timezone-correct attendance without timezone tables

MySQL on the host lacked timezone tables, so CONVERT_TZ silently returned NULL. I moved IST-awareness into the query layer with explicit offset arithmetic and date-boundary handling, making attendance day-rollover correct at midnight IST — verified with boundary-case tests.

Procurement integrity across 4 roles

A PO edited after approval is a financial liability. The state machine enforces legal transitions, every mutation writes an immutable audit row, and RBAC ensures a site engineer can raise an MRN but never approve their own PO.

Where AI fits next

  • RAG over site documents & POs: 'What did we pay for cement across Site 3 this quarter?' answered from the audit trail.
  • Anomaly detection on attendance and payment patterns (duplicate selfies, geofence spoofing, unusual PO velocity).
  • LLM-drafted purchase orders from unstructured supplier quotes with human approval in the existing state machine.

Deployment

Render (Node.js) + Railway MySQL 8.0. SSL, CORS whitelisting, env-driven config, and a tsc → migrate → seed pipeline for repeatable zero-drift deploys.