EIS v2: Python + React Full-Stack Rebuild from Rails
Sign Up Free

Preview site — latest 100 public prompts. Sign up free on markmyprompt.com for the full library.

Get started →
R
Rajsekhar B
@rajsekharb4209
7/7/2026

EIS v2: Python + React Full-Stack Rebuild from Rails

reactpythonrebuild
# EIS v2 — Python + React Rebuild (Local First)

## Your role
You are a senior full-stack engineer rebuilding the **EIS (Env IoT Solutions)** dashboard from a legacy **Ruby on Rails 6** app into **Python backend + React frontend**. Work incrementally, test each phase, and keep the legacy Rails app as read-only reference only — do not extend Rails.

## Workspace layout (expected on my Mac)
- `eiotsolutions-rails-reference/eiotsolutions/` — extracted Rails reference (from AWS backup)
- `eiotsolutions-rails-reference/eis-db-backup.sql` — MySQL dump (sensitive — never commit)
- `eis-v2/backend/` — NEW Python API (create this)
- `eis-v2/frontend/` — NEW React app (create this)

If paths differ, ask me once, then proceed.

---

## Why we are rebuilding
Rails + ERB + jQuery + SlimSelect is hard to maintain. We want:
- Clean React UI (MUI or React Select for dropdowns — no SlimSelect)
- Python API with clear service layer
- Celery + Redis for background jobs (PDF, email, EIS data fetch)
- Same business behavior as production (NFPA LS compliance is critical)

---

## Target tech stack (use this unless blocked)

### Backend
- **Python 3.11+**
- **Django 5 + Django REST Framework** (preferred — similar to Rails monolith patterns)
- **PostgreSQL** for new app DB (import/migrate from MySQL dump OR use MySQL initially if Postgres migration is too slow — document choice)
- **Celery + Redis** for async jobs
- **python-dotenv** for secrets
- **WeasyPrint** or **ReportLab** for NFPA PDFs (port layout from Rails `NfpaReportPdfJob` — match output, not necessarily same library)

### Frontend
- **React 18 + TypeScript + Vite**
- **MUI (Material UI)** for layout, tables, forms, selects
- **React Router** for navigation
- **TanStack Query (react-query)** for API caching
- **Axios** for HTTP

### Auth
- JWT or session-based API auth replacing Devise
- Roles: `sa` (admin), `vr` (viewer), `pu` (pick up from Rails `users.role`)
- Building access via `user_buildings` table logic

---

## Legacy reference — read these first before coding

### Schema & data
- `eiotsolutions-rails-reference/eiotsolutions/db/schema.rb` — all tables
- Key tables: `users`, `user_buildings`, `sites`, `buildings`, `floors`, `sensors`, `readings`, `life_safety_details`, `ls_reports`, `aq_reports`, `alerts`, `aqi_settings`, `life_safety_settings`, `nfpa_report_exports`, `smtp_configs`

### Business logic (PORT WITH TESTS — highest risk)
- `app/services/ls_test_result_mapper.rb` — NDL, NNT, Passed, Failed, compliant labels
- `app/services/life_safety/` — annual/monthly queries, compliance evaluator, monthly compliance
- `app/jobs/nfpa_report_pdf_job.rb` — NFPA PDF structure (monthly grid + annual summary + detail)
- `lib/tasks/fetch_eis_data.rake` — EIS API ingestion (Keycloak token + prod-api-eis.ilumisolutions.net)
- `lib/tasks/high_aqi_common_ls.rake` — LS/AQ report aggregation, monthly/yearly LsReport creation
- `lib/setup_cron.rb` — schedules (15 min fetch, etc.)

### UI reference (behavior, not copy-paste ERB)
- `app/views/home/_header.html.erb` — nav: AQ, LS, Events, Reports, Alerts, Admin
- `app/views/home/dashboard.html.erb`, `aqi_view.html.erb`, `life_safety_view.html.erb`
- `app/views/home/report_data.html.erb` — reports + NFPA PDF export
- `app/views/home/settings.html.erb` — alerts settings pattern (mirror for future report settings)
- `app/controllers/home_controller.rb` — main routes/actions

### External APIs (from rake tasks)
- Token: `https://identity.ilumisolutions.net/realms/meshtek-eis/protocol/openid-connect/token`
- API base: `https://prod-api-eis.ilumisolutions.net/api`
- Endpoints: `eisreadings?type=QUALITY`, `eislsdetail?type=LSD`, etc.
- Credentials come from `.env` — do NOT hardcode; ask me to fill `.env.example`

---

## Database setup (local)

1. Import `eis-db-backup.sql` into local MySQL OR migrate to Postgres
2. Document connection in `eis-v2/backend/.env.example`
3. Phase 1: Django models can mirror existing table names to avoid data migration pain
4. Never commit SQL dumps or production passwords

Production DB name was `eis_prod_2026`. Local name: `eis_dev`.

---

## Implementation phases — follow in order

### PHASE 0 — Project scaffold (Day 1)
- Create monorepo `eis-v2/` with `backend/` and `frontend/`
- Backend: Django project `config`, apps: `core`, `accounts`, `buildings`, `life_safety`, `air_quality`, `reports`
- Frontend: Vite React TS, MUI theme (purple accent `#662f92` like current EIS branding)
- CORS enabled for `http://localhost:5173`
- `.gitignore`: `*.sql`, `.env`, `node_modules`, `__pycache__`, `.venv`
- README with how to run backend, frontend, celery, redis locally

Deliverable: empty app runs; health check `GET /api/health` returns OK.

---

### PHASE 1 — Auth + navigation shell (Week 1)
**Backend**
- Port `users` + `user_buildings` access control
- Login endpoint returning JWT (or session cookie)
- `GET /api/me` — current user + role + allowed sites/buildings

**Frontend**
- Login page
- App shell matching EIS header: AQ | LS | Events | Reports | Alerts | Admin
- Site + Building multi-select filters (MUI Autocomplete or React Select — must work reliably)
- Stats bar: BUILDINGS, SITES, DEVICES counts (from API)
- Protected routes; redirect to login if unauthenticated

Deliverable: login as existing user from DB; pick site/building; header renders.

---

### PHASE 2 — AQ dashboard (Week 2)
**Backend**
- `GET /api/aq/dashboard?building_id=` — latest readings per sensor, 24H high, 30D high
- Port gauge band logic from Rails JS/docs if needed (segments, cap at 500)

**Frontend**
- AQ dashboard page: semi-circular gauge (Chart.js or MUI-compatible chart)
- Sensor table: IAQ, CO, CO2, NOx, PM*, RHM, TMP, VOC columns
- Match columns from `aqi_view` / dashboard

Deliverable: AQ page matches Rails data for one test building (e.g. Hasco).

---

### PHASE 3 — LS dashboard (Week 2–3)
**Backend**
- `GET /api/ls/dashboard?building_id=` — unit status counts, LS type counts, current month testing stats
- `GET /api/ls/sensors/:sensor_id/detail` — LS detail view data

**Frontend**
- LS summary page like `life_safety_view`
- LS detail page like `ls_detailed_view`

Deliverable: LS dashboard + detail for one building.

---

### PHASE 4 — Reports (Week 3–4)
**Backend**
- `GET /api/reports/ls?building_id=&type=monthly|annual&month=&year=`
- `GET /api/reports/aq?...` (read from `aq_reports`)
- CSV export endpoints

**Frontend**
- Reports page like `report_data.html.erb`
- Filters: report type, month/year, pagination
- Download CSV button

Deliverable: reports table matches Rails for same filters.

---

### PHASE 5 — NFPA PDF export (Week 4–6) — CRITICAL
**Backend**
- Port `LsTestResultMapper` to Python with unit tests (copy cases from Rails behavior)
- Port `LifeSafety::MonthlyCompliance`, `AnnualSummaryQuery`, `AnnualDetailQuery` logic
- Celery task `generate_nfpa_pdf(export_id)` mirroring `NfpaReportPdfJob`
- Store PDFs in `backend/media/reports/` or `public/reports/`
- API: `POST /api/reports/nfpa/export`, poll status, download

**Known business rules to implement (from client RCAs)**
- Annual report: exclude sensors where `created_at > end_of_report_year` (e.g. TB5 must not appear in 2025 report)
- Annual new-unit waiver (when approved): units installed in report year with no annual test but passing monthly → Compliant YES + provision date in Comments
- Monthly: grace period `provisioned_at + 1 month + 7 days`

**Frontend**
- "Download NFPA report" button with async polling modal (like current UX)

Deliverable: PDF for Hasco CT Office monthly/annual matches Rails output closely; unit tests green.

---

### PHASE 6 — Alerts (Week 5–6)
- Alert list pages: AQ alerts, LS alerts, sensor alerts
- Alert settings page pattern from Rails `settings.html.erb` (internal user picker from `user_buildings`)

---

### PHASE 7 — Background jobs (Week 6+)
- Celery task port of `fetch_eis_data.rake` (every 15 min — use Celery Beat)
- Port `high_aqi_common_ls.rake` aggregation for `ls_reports` / `aq_reports`
- Use env vars for EIS API credentials

---

### PHASE 8 — LS Report Settings + Archive + Auto-email (from client mockups)
**Only after Phase 5 PDF works**

**Settings**
- Reports nav dropdown: Report Settings | LS Report Archive
- LS Report Settings per building:
  - Internal Auto Send toggle + Monthly/Annual notify types
  - External Auto Send toggle + Monthly/Annual notify types
  - Add External modal: Name, Title, Email (stored per **site**, no dashboard login)
- Internal recipients = all users with `user_buildings` access to that building

**Archive**
- Page listing `nfpa_report_exports` (ready PDFs), filter site/building/report type, 7-year history
- Checkbox multi-select + Download Selected (zip)

**Scheduled jobs**
- Monthly: 2nd of month 1:00 AM UTC — previous month PDF per eligible building
- Annual: Jan 2 1:00 AM UTC — previous year PDF
- Email PDF as attachment via SMTP (`smtp_configs` table port)

---

## Coding standards
- Minimize scope per PR/commit; one phase at a time
- Python: type hints, services in `services/` not fat views
- React: functional components, hooks, no jQuery
- Write tests for compliance logic (pytest)
- Match existing API field names where possible for easier frontend mapping
- Comments only for non-obvious NFPA business rules

## Do NOT
- Do not modify Rails reference code except to read it
- Do not commit SQL dumps, `.env`, or SMTP passwords
- Do not use SlimSelect
- Do not big-bang rewrite everything in one pass
- Do not change NFPA compliance rules without citing Rails reference behavior

## Environment variables (.env.example)
0 likes0 comments

Want to like, comment or save this prompt?

Sign up free to interact, create and organise your own AI prompts.

Get Started Free
EIS v2: Python + React Full-Stack Rebuild from Rails | Mark My Prompt