# Permit Lifecycle (Handover / Audit / Handback)

| | |
|---|---|
| **Nav ID** | `permit-handover`, `permit-audit`, `permit-handback` |
| **Component** | `AdminPermitLifecyclePage.jsx` |
| **Services** | `formsApi.js`, `permitsApi.js` |

---

## Endpoints

Same as [fill-form.md](fill-form.md), with `submission_role` set to `handover`, `audit`, or `handback`.

Audit uses the dedicated **Audit** form type (`ptw_form_type`) and renders the shift audit table (WHO, DATE, three action rows).

---

## SQL queries

### Pre-submit checks

```sql
SELECT * FROM ptw_permits WHERE permit_id = ? LIMIT 1;
-- valid_from must be NOT NULL before handover, audit, or handback

SELECT * FROM `ptw_submissions` WHERE `permit_id` = ?;

SELECT submission_id FROM ptw_submissions
WHERE permit_id = ? AND submission_role = 'handback' LIMIT 1;
-- handback only — audit is repeatable (no duplicate guard)
```

### Submit handover

Uses the full submission transaction from [fill-form.md](fill-form.md), then:

```sql
UPDATE ptw_permits
SET valid_until = DATE_ADD(NOW(), INTERVAL ? HOUR),
    permit_status_id = ?    -- ACTIVE
WHERE permit_id = ?;
```

### Submit audit

Uses the same INSERT transaction as other roles. **No permit status or validity change** — answers are stored only.

```sql
INSERT INTO ptw_submissions (permit_id, submitter_id, form_id, submission_role)
VALUES (?, ?, ?, 'audit');
-- followed by ptw_answers / ptw_answers_media inserts
```

### Submit handback

```sql
-- optional closing link (non-required for handback):
UPDATE ptw_opening_closing_map SET closing_sub_id = ?
WHERE permit_id = ? AND opening_sub_id = ?;

UPDATE ptw_permits
SET permit_status_id = ?, valid_until = NOW()   -- CLOSED
WHERE permit_id = ?;
```

**Controller:** `ptwSubmissionController.js`
