Skip to content

klanvend0/ap-case

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Energy Monitoring Platform

A simplified energy monitoring backend and dashboard for enterprise customers. Organizations have users and energy meters. Meters send index (reading) data; the system computes consumption from successive readings.

Tech Stack

  • Backend: Express + routing-controllers + Prisma + PostgreSQL + TypeScript
  • Frontend: TanStack React Start + shadcn/ui + Tailwind CSS
  • Validation: Zod schemas on all endpoints
  • Auth: JWT-based with role-based access (ADMIN / USER)
  • API Docs: Swagger UI auto-generated from controllers
  • Infra: Docker Compose (Postgres + Backend + Frontend)

Quick Start

With Docker (recommended)

chmod +x run.sh
./run.sh

run.sh will:

  1. Auto-create .env files from .env.example for both backend and frontend (if they don't exist)
  2. Build and start all services via docker compose up --build
  3. Postgres initializes with the configured database
  4. Backend runs Prisma migrations, seeds the default admin user, then starts the Express server
  5. Frontend builds the TanStack Start app and serves it with Vite preview
Service URL
Frontend http://localhost:3000
Swagger UI http://localhost:4000/docs
OpenAPI JSON http://localhost:4000/docs.json

Default admin: admin@example.com / admin123

Tip: After logging in, click Admin Panel🌱 Seed Test Data to populate sample organizations, users, meters, and 24h of readings.

Local Development

# Backend
cd backend
cp .env.example .env  # set DATABASE_URL
npm install
npx prisma migrate deploy
npm run prisma:seed
npm run dev

# Frontend (separate terminal)
cd frontend
npm install
npm run dev

Frontend Pages

Path Access Description
/login Public Login page
/dashboard Authenticated Consumption report with org summary cards, meter filter, readings table
/admin Admin only Full CRUD for organizations, users, meters, and meter assignments

API Documentation

Interactive Swagger UI is available at http://localhost:4000/docs.

All endpoints return JSON. Auth endpoints require Authorization: Bearer <token> header.

Authentication

Method Path Auth Description
POST /auth/login Login, returns JWT token

Body: { "email": "string", "password": "string" }

Organizations (Admin only)

Method Path Description
GET /organizations List all organizations
POST /organizations Create organization
DELETE /organizations/:id Delete organization

Users (Admin only)

Method Path Description
GET /users List all users
POST /users Create user
DELETE /users/:id Delete user

Meters

Method Path Auth Description
GET /meters Authenticated List meters (scoped by role)
POST /meters Admin Create meter
DELETE /meters/:id Admin Delete meter

Meter Readings (Authenticated)

Method Path Description
POST /meter-readings Submit a meter reading

Body: { "meterId": "uuid", "timestamp": "ISO 8601", "index_kwh": number }

  • Computes consumption from the difference between current and previous index
  • Rejects readings where index_kwh < previous reading
  • Rate-limited: 100 requests/minute

Report (Authenticated)

Method Path Description
GET /report?meterIds=id1,id2 Consumption per meter/org (last 24h)
  • Users see only their organization's data
  • Admins see all organizations
  • Filter by meter IDs via query param

Meter Assignments — Bonus (Admin only)

Method Path Description
GET /meter-assignments List all assignments
POST /meter-assignments Assign meter to user
DELETE /meter-assignments/:meterId/:userId Remove assignment

When a user has meter assignments, they can only see/interact with those specific meters.

Test Data (Admin only)

Method Path Description
POST /seed-test-data Seed sample orgs, users, meters, and 24h of readings

Error Handling

All errors return structured responses:

{
  "error": "Human-readable message",
  "code": "ERROR_CODE"
}

Error codes are defined in backend/src/errors.ts.

Bonus Features Implemented

  • Rate limiting on /meter-readings (100 req/min)
  • Meter-level access control: Admins assign specific meters to users via /meter-assignments; users with assignments only see those meters
  • Unit tests: cd backend && npm test (10 tests)
  • Swagger / OpenAPI: Auto-generated at /docs
  • Admin Panel UI: Full CRUD for all resources + seed test data button

Assumptions & Trade-offs

  • UUIDs used for all primary keys
  • Passwords hashed with bcrypt (10 rounds)
  • Tanstack starter with Shadcn for components
  • JWT tokens expire after 24 hours
  • Cascade deletes: deleting an org removes its users, meters, and readings
  • The frontend is a simple SPA dashboard — no fancy design, focused on structure and clarity
  • vite preview is used to serve the frontend in Docker (suitable for demo; I would use a proper server in production)
  • Zod schemas validate all request bodies; structured error codes for every failure case
  • If no user is assigned to a meter, all users in the organization have access to that meter

Project Structure

├── backend/
│   ├── src/
│   │   ├── controllers/     # REST endpoints (7 controllers)
│   │   ├── middlewares/      # Auth checkers
│   │   ├── types/            # TypeScript interfaces
│   │   ├── __tests__/        # Unit tests
│   │   ├── errors.ts         # Error codes & AppException
│   │   ├── schemas.ts        # Zod validation schemas
│   │   ├── prisma.ts         # Prisma client singleton
│   │   └── index.ts          # Express bootstrap + Swagger
│   ├── prisma/
│   │   ├── schema.prisma     # Data model
│   │   ├── migrations/       # SQL migrations
│   │   └── seed.ts           # Default admin seed
│   └── Dockerfile
├── frontend/
│   ├── src/
│   │   ├── routes/           # TanStack file-based routes (login, dashboard, admin)
│   │   ├── components/ui/    # shadcn components
│   │   └── utils/            # API client & auth helpers
│   └── Dockerfile
├── docker-compose.yml
├── run.sh
└── README.md

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages