# RPN (Risk Priority Number) in SAT — How It Works

This document describes how **RPN** is implemented across the SAT stack: data model, form submission, APIs, dashboards, and reporting.

---

## 1. Concept

In this application, **RPN is treated as the product of two numeric factors** stored in master tables:

- **Likelihood of harm** — numeric `value` (from `rpn_likelihood_of_harm`)
- **Severity of harm** — numeric `value` (from `rpn_severity_of_harm`)

**Formula (frontend):**

```text
RPN = Likelihood value × Severity value
```

Values are stored as **strings** in answers (e.g. `answer_value` for the likelihood and severity questions). The dropdown options use the **numeric `value`** from each row; the RPN field is **computed and written** when the user selects likelihood and/or severity.

---

## 2. Database

### Tables

| Table | Purpose |
|--------|---------|
| `rpn_likelihood_of_harm` | Rows: `likelihood_of_harm` (label), `value` (numeric factor used in RPN) |
| `rpn_severity_of_harm` | Rows: `severity_of_harm` (label), `value` (numeric factor used in RPN) |

There is **no separate RPN column** in the database for the form definition. RPN is a **derived answer** on a normal `questions` row whose question text contains `"rpn"` (see below).

---

## 3. Form design (question text)

The **web form submission** (`FormSubmission.js`) does **not** use a fixed question ID for RPN. It **detects** three roles by **substring match on the question text** (case-insensitive):

| Role | Detection rule |
|------|----------------|
| Likelihood question | `question` includes `"likelihood of harm"` |
| Severity question | `question` includes `"severity of harm"` |
| RPN question | `question` includes `"rpn"` |

**Implications:**

- Form templates must use wording that matches these patterns (or the RPN UI will not activate).
- The **RPN question** should be a separate question (e.g. number or text) that will hold the **computed** RPN string; it is **read-only** in the UI and filled automatically when both factors are set.

---

## 4. Submission flow (web — `FormSubmission.js`)

1. On load, the app fetches:
   - `GET /api/rpn/likelihood` → `rpnLikelihoodOptions`
   - `GET /api/rpn/severity` → `rpnSeverityOptions`
2. Likelihood and severity questions render as **`<select>`** elements; options show label + value in parentheses.
3. **Computation** (`computeRpnValue`):
   - Parses both selected values as numbers.
   - If both are valid numbers: `RPN = String(l * s)` (i.e. product of the two **values**).
   - If either is missing/invalid: RPN answer is cleared (`''`).
4. **Updates** when the user changes likelihood or severity (`handleLikelihoodChange` / `handleSeverityChange`): the RPN answer object for `rpnQuestionId` is updated with the same `answer_value`.
5. **Risk band (UI only)** — `getRpnColorClass` maps the numeric RPN to CSS classes:

   | Condition (numeric RPN = `x`) | Class / meaning |
   | ----------------------------- | ---------------- |
   | `x < 8` | Green — “Low risk” |
   | `8 ≤ x < 32` | Yellow — “Medium risk” |
   | `x ≥ 32` | Red — “High risk” |

   *(Note: the in-code comment mentions “1 < x ≤ 8”; the actual condition is `x < 8`.)*

6. On submit, **submission payload** includes answers for **likelihood**, **severity**, and **RPN** question IDs like any other question — stored in `answers.answer_value`.

---

## 5. Backend APIs — RPN master data

| Method | Path | Purpose |
|--------|------|---------|
| GET | `/api/rpn/likelihood` | List all likelihood rows |
| POST | `/api/rpn/likelihood` | Create likelihood row |
| PUT | `/api/rpn/likelihood` | Update likelihood |
| DELETE | `/api/rpn/likelihood/:likelihood_of_harm` | Delete likelihood |
| GET | `/api/rpn/severity` | List all severity rows |
| POST | `/api/rpn/severity` | Create severity row |
| PUT | `/api/rpn/severity` | Update severity |
| DELETE | `/api/rpn/severity/:severity_of_harm` | Delete severity |

Implementation: `rpnRepository.js` → `rpnController.js` → `rpnRoutes.js` (mounted at `/api/rpn`).

---

## 6. Dashboard and analytics (backend)

Dashboard logic lives mainly in `dashboardRepository.js`. RPN-related behaviour differs slightly from the **single-field** product used on the form.

### 6.1 “Critical findings” / RPN range counts

- **Count audits** with at least one **numeric** answer whose value is between **32 and 128** (inclusive) — **not** restricted to “RPN question” text by question text in this query; it uses numeric `answers.answer_value` across submissions (see `getAuditsWithRpnInRangeCount` / `getAuditsWithRpnInRange`).

### 6.2 RPN bar chart — “Audits by RPN value” (`getRpnAuditCounts`)

- Considers answers whose **question text** matches `LOWER(q.question) LIKE '%rpn%'`.
- Per **audit**, sums **all** such RPN answers’ numeric values → `total_rpn`.
- Maps `total_rpn` into **buckets** labeled 1, 2, 4, 8, 16, 32, 64, 128 (ranges of total, e.g. 2–3 → bucket 2, etc.).
- Returns counts per bucket for the bar chart.

### 6.3 RPN distribution pie (`getRpnDistribution`)

- Uses numeric `answer_value` **between 1 and 125** and bands:
  - Low: 1–25  
  - Medium: 26–80  
  - High: 81–125  

### 6.4 Dashboard API endpoints (frontend)

- `GET /api/dashboard/rpn-audit-counts` — bar chart data  
- `GET /api/dashboard/rpn-audits/:rpnValue` — audits in a bucket  
- `GET /api/dashboard/audits-rpn-critical` — critical findings list  

(Exact paths are defined in `SAT_Frontend/src/utils/config.js` and `dashboardRoutes.js`.)

---

## 7. Mobile app

The React Native dashboard (`SAT_mobile`) uses **`/dashboard/rpn-audit-counts`** and related dashboard stats to show RPN charts alongside severity/likelihood distributions — it **consumes** the same backend aggregates, not the form submission UI.

---

## 8. End-to-end checklist

| Step | What to verify |
|------|----------------|
| Master data | `rpn_likelihood_of_harm` and `rpn_severity_of_harm` populated with sensible `value` columns |
| Form | Three questions with text matching: “likelihood of harm”, “severity of harm”, “rpn” |
| Submission | User selects likelihood + severity → RPN field updates automatically and saves |
| Dashboards | Charts use stored answers; RPN bar chart uses questions with `RPN` in text and sums per audit |

---

## 9. File reference

| Area | File(s) |
|------|---------|
| Form UI & logic | `SAT_Frontend/src/components/features/audit-management/FormSubmission.js` |
| API URLs | `SAT_Frontend/src/utils/config.js` |
| RPN CRUD | `SAT_backend/src/repositories/rpnRepository.js`, `controllers/rpnController.js`, `routes/rpnRoutes.js` |
| Dashboard SQL | `SAT_backend/src/repositories/dashboardRepository.js` |
| Schema | `SAT_backend/src/sql/db_schema.sql` (`rpn_likelihood_of_harm`, `rpn_severity_of_harm`) |

---

*Generated from the SAT codebase. Update this document if detection rules, formulas, or dashboard queries change.*
