# PTW Admin API Documentation

Base URL (unified server): `http://localhost:<APP_PORT>/api/ptw`

Standalone PTW server default port: **3005** (`ptw_backend/.env.example`). In production-style dev, PTW is mounted by `combined-server.mjs` at `/api/ptw/*`.

Frontend client: `ptw_frontend/` — axios base URL defaults to `/api/ptw` (`VITE_API_BASE_URL`).

---

## Authentication

All PTW Admin routes require an **admin JWT** (`requireAdmin` middleware).

```http
Authorization: Bearer <jwt_token>
```

- Tokens are issued by the HSE/SAT login flow (same JWT family as ORAC/SWI).
- Accepted secrets: `JWT_SECRET`, `JWT_USER_SECRET`, `JWT_ADMIN_SECRET`, `JWT_EXECUTOR_SECRET`.
- Role is read from `role`, `role_name`, `roles[]`, `roleIds[]`, or `isAdmin: true`.
- Admin role name defaults to `admin` (`JWT_ADMIN_ROLE`).

### Auth errors

| Status | Meaning |
|--------|---------|
| `401` | Missing/invalid `Authorization` header or expired JWT |
| `403` | Valid JWT but not admin role |

---

## Health

| Method | Path | Auth | Description |
|--------|------|------|-------------|
| `GET` | `/api/ptw/health` | No | `{ "status": "ok" }` |

---

## Response conventions

### Dedicated controllers (permits, users, tickets, dashboard, submissions)

- **List:** JSON array of rows (may include joined columns).
- **Get one:** JSON object.
- **Create:** `201` with `{ insertedId, ... }` or controller-specific shape.
- **Update / delete:** `{ affectedRows }` or updated row.
- **Errors:** `{ "message": "..." }` via `ApiError`.

### Generic CRUD routers

Most lookup and mapping tables use `createCrudRouter`:

| Method | Path pattern | Description |
|--------|--------------|-------------|
| `GET` | `/<table>` | List; query params filter by exact column match |
| `GET` | `/<table>/:pk` | Get one row by primary key |
| `POST` | `/<table>` | Insert; body = column map |
| `PUT` | `/<table>/:pk` | Partial/full update |
| `DELETE` | `/<table>/:pk` | Delete row |

**Query filters:** `column=value` for equality; `column_like=value` for `LIKE %value%`.

**Composite keys:** path segments follow declared PK order, e.g.  
`PUT /ptw_form_section_map/:form_id/:section_id`.

### Generic CRUD — SQL patterns

List with optional filters (`?status_id=1`, `?name_like=hot`):

```sql
SELECT * FROM `<table>`
WHERE `<column>` = ?
-- AND `<column>` LIKE ?   -- when using column_like query param
;
```

Get one by primary key:

```sql
SELECT * FROM `<table>` WHERE `<pk>` = ? LIMIT 1;
```

Create:

```sql
INSERT INTO `<table>` (`col1`, `col2`) VALUES (?, ?);
```

Update:

```sql
UPDATE `<table>` SET `col1` = ?, `col2` = ? WHERE `<pk>` = ?;
```

Delete:

```sql
DELETE FROM `<table>` WHERE `<pk>` = ?;
```

Each page doc in `docs/api-pages/` includes the **exact SQL** (or transaction sequence) run by dedicated controllers.

### Schema reference

Full table definitions: `ptw_backend/sql/ptw.sql` (MySQL `hse` schema).

Key tables by area:

| Area | Tables |
|------|--------|
| Permits | `ptw_permits`, `ptw_submissions`, `ptw_answers`, `ptw_answers_media`, `ptw_opening_closing_map` |
| Forms | `ptw_form_details`, `ptw_section_details`, `ptw_questions`, `ptw_question_options`, `ptw_form_section_map`, `ptw_section_question_map`, `ptw_location_forms_details`, `ptw_alternative_sections` |
| Lookups | `ptw_job_type`, `ptw_form_type`, `ptw_question_type`, `ptw_permit_status`, `locations`, `roles`, … |
| Users | `users`, `user_role`, `users_logs` |
| Tickets | `tickets`, `tickets_logs` |

---

## API documentation by page

Each admin screen maps to the endpoints it calls. See `docs/api-pages/`:

| Nav ID | Page doc |
|--------|----------|
| `overview` | [Dashboard (Overview)](docs/api-pages/overview.md) |
| `users-access` | [Users & Access](docs/api-pages/users-access.md) |
| `activity-log` | [Activity Log](docs/api-pages/activity-log.md) |
| `permits-submissions` | [Permits & Submissions](docs/api-pages/permits-submissions.md) |
| `permit-preview` | [Submitted Forms (Preview)](docs/api-pages/permit-preview.md) |
| `fill-form` | [Fill Permit Form](docs/api-pages/fill-form.md) |
| `permit-handover` / `permit-audit` / `permit-handback` | [Permit Lifecycle](docs/api-pages/permit-lifecycle.md) |
| `form-management` | [Form Management](docs/api-pages/form-management.md) |
| `job-type-management` | [Job Type Management](docs/api-pages/job-type-management.md) |
| `section-management` | [Section Management](docs/api-pages/section-management.md) |
| `question-management` | [Question Management](docs/api-pages/question-management.md) |
| `raise-ticket` | [Raise Ticket](docs/api-pages/raise-ticket.md) |
| `ticket-list` | [Ticket List](docs/api-pages/ticket-list.md) |
| `ticket-logs` | [Ticket Logs](docs/api-pages/ticket-logs.md) |

**Shared lookup data** used on many pages: [Master & location lookups](docs/api-pages/shared-master-data.md).

---

## Route modules (backend source)

| Module | File | Mount prefix |
|--------|------|--------------|
| Master lookups | `src/routes/masterRoutes.js` | `/api/ptw/<table>` |
| Locations | `src/routes/locationRoutes.js` | `/api/ptw/locations`, `/location_departments` |
| Users | `src/routes/userRoutes.js` | `/api/ptw/users`, `/user_role`, … |
| Tickets | `src/routes/ticketRoutes.js` | `/api/ptw/tickets`, `/tickets_logs` |
| Forms | `src/routes/formRoutes.js` | `/api/ptw/ptw_form_details`, … |
| Permits & submissions | `src/routes/permitRoutes.js` | `/api/ptw/ptw_permits`, `/submissions`, … |

Router entry: `src/routes/index.js` — all sub-routers wrapped with `requireAdmin`.
