# HQ backend — dashboard-cpsp-executive Main-office **mirror API** for the executive frontend. Domain shapes match site `dashboard-cpsp` so the copied UI can talk to `/api/v1/`. ## Roles | Status | Capabilities | Data scope | |--------|----------------|------------| | `director`, `director_admin` | **View only** (director_admin may repair farm structure writes). Not Django superuser. | **All** sites / GMs | | `buh`, `bu_admin` | **View only** | Rollup of managed GMs' registered active sites | | `gm` | View + register site URLs + sync + **approve cycle close** | Own sites / active sites | | `gm_admin` | Same as GM **except** no cycle-close approval | Own sites / active sites | | `account_admin` | **User Management only** (create / deactivate / reset password). No ops dashboards. Temp passwords shared out-of-band. | Users list (all product users; never lists `superuser`). | | `superuser` | Break-glass: **ops dashboards (director scope) + Manajemen Akun**. Not creatable via UI; hidden from user lists. | All sites / GMs | | `inactive` | Locked out | — | `bootstrap_admin` / seed `admin` uses status `superuser`. This app does not use `is_staff`. GM↔BUH link: `User.managed_by` (confirmed). **Only `gm`** may request a **`buh`** (not `bu_admin` / `gm_admin`); **only that `buh`** may approve. Active site registry ownership: `ActiveSite.managed_by`. GM farm visibility follows the Pengaturan active-site list: only HQ `Site` rows linked to an enabled `ActiveSite` they manage are shown (empty list ⇒ no sites). BUH farm visibility is the union of those lists for **confirmed** managed GMs (read-only Pengaturan rollup; optional GM filter in the header). `POST /api/v1/cycles/{id}/approve-close/` — GM only. `POST /api/v1/active-sites/` — GM / GM Admin. ## Active site registry `GET/POST /api/v1/active-sites/` — register farm-location dashboard APIs. `POST /api/v1/active-sites/{id}/sync/` and `POST /api/v1/active-sites/sync-all/` — pull farm `pusat/export` + `pusat/export/iot` into the HQ mirror (ops + IoT). Cron: `manage.py sync_active_sites_from_farm` every 30 minutes when `ACTIVE_SITE_MIRROR_SYNC_ENABLED=true`. If farm rotated `SITE_API_KEY`, re-register the site (or update `ActiveSite.api_key`) so pull auth succeeds. ## Setup ```bash cd backend python -m venv .venv # Windows: .venv\Scripts\activate pip install -r requirements.txt cp .env.example .env python manage.py migrate python manage.py seed_demo npm run dev # → http://127.0.0.1:8001 ``` Seed logins: | Username | Password | Role | |----------|----------|------| | `admin` | `admin123` | `superuser` (break-glass: ops + Manajemen Akun; hidden from user lists) | | `director` | `director123` | `director` | | `director_admin` | `directoradmin123` | `director_admin` (product; not superuser) | | `buh` | `buh123` | `buh` | | `bu_admin` | `buadmin123` | `bu_admin` | | `gm` | `gm123` | `gm` (owns Sukawarna demo data; managed by `buh`) | | `gm_admin` | `gmadmin123` | `gm_admin` (sites only; no BUH request) | | `account_admin` | `accountadmin123` | `account_admin` (IT Central user management only) | Legacy `staff` login is removed by `seed_demo` (sites reassigned to `gm`). ## Ports | Service | Port | |---------|------| | HQ API | `:8001` | | Executive FE | `:3002` | | Site API (other repo) | `:8000` | | Site FE | `:3001` |