Full Flow Overview
Bird's-eye view of the entire backend — every phase shown. Green = happy path. Red = exit/rejection. Purple = instalment path. Dashed = external API. Click any phase in the sidebar for granular detail.
flowchart TD START["▶ Patient on product page"]:::startNode START --> P1["Phase 1
Product Selection &
Consultation Entry"] P1 --> P2["Phase 2
Consultation Form
(multi-step wizard)"] P2 --> DENY{"Auto-deny?"} DENY -->|YES| AD["✖ Denied
Advised to see GP"]:::redNode DENY -->|NO| P3 P3["Phase 3
Payment & Plan Selection"] P3 --> TYPE{"One-off or
Instalment?"} TYPE -->|ONE-OFF| PAY_A["Pay in full"]:::pathA TYPE -->|INSTALMENT| PAY_B["Pay 1st month"]:::pathB PAY_A --> P4 PAY_B --> P4 P4["Phase 4
ID Verification"]:::apiNode P4 --> ID{"Pass?"} ID -->|YES| P5 ID -->|FAIL| IDX["✖ Rejected + Refund"]:::redNode P5["Phase 5
Review Queue
& Notification"] P5 --> CLASS{"Product
classification?"} CLASS -->|POM| P6_POM["Phase 6
Prescriber Reviews"]:::pomNode CLASS -->|"P item"| P6_P["Phase 6
Pharmacist Reviews"]:::pItemNode CLASS -->|"GSL / Test Kit"| P6_GSL["Phase 6
Pharmacy Team
Processes"]:::gslNode P6_POM --> DEC{"Decision?"} DEC -->|APPROVE| P7_SPLIT{"Order type?"} DEC -->|MORE INFO| P6_POM DEC -->|DENY| DENR["✖ Denied + Refund"]:::redNode P6_P --> DEC_P{"Decision?"} DEC_P -->|APPROVE| P8 DEC_P -->|MORE INFO| P6_P DEC_P -->|DENY| DENR P6_GSL --> P8 P7_SPLIT -->|ONE-OFF| P7A["Phase 7A
Single Rx
(one order)"]:::pathA P7_SPLIT -->|INSTALMENT| P7B["Phase 7B
Single Rx covering
full plan period"]:::pathB P7A --> SIGN P7B --> SIGN SIGN["Prescriber signs in
SignatureRx (FINAL)"]:::apiNode SIGN --> P8["Phase 8
Post-Approval Triggers
Fires immediately on decision:
GP Letter | Patient Msg |
Pharmacy Team Notified"]:::greenNode P8 --> P9["Phase 9
PMR Sync &
Print Slip"]:::supportNode P9 --> P10["Phase 10
Repeat Submission
Detection"]:::supportNode P10 --> P11["Phase 11
Dispatch"]:::apiNode P11 --> P12["Phase 12
Delivery & Tracking"] P12 -->|DELIVERED| DONE["✅ Complete"]:::greenEnd P12 -->|FAILED| DELFAIL["Team action"]:::orangeNode DONE --> NEXT{"Order type?"} NEXT -->|ONE-OFF| REORDER{"Within grace
period?"} REORDER -->|YES| REORD["Re-confirm → reorder"]:::pathA REORD --> P11 REORDER -->|NO| EXPIRED["Fresh consultation"]:::orangeNode NEXT -->|INSTALMENT| P13["Phase 13
Instalment Renewal"]:::pathB P13 -->|"Next month"| P11 P13 -->|"Plan ends &
within 12mo"| RECON["Re-confirm →
new plan"]:::pathB RECON --> P13 P13 -->|"12mo limit /
grace expired"| FRESH["Fresh consultation"]:::orangeNode %% API annotations — side labels connected with dotted lines API_STRIPE["⚡ Stripe
Payment + Refunds"]:::apiLabel API_LEXIS["⚡ LexisNexis
ID Verification"]:::apiLabel API_SRX["⚡ SignatureRx
E-Prescribing"]:::apiLabel API_TITAN["⚡ TitanPMR
Patient Data Sync"]:::apiLabel API_RM["⚡ Royal Mail
Shipping + Tracking"]:::apiLabel API_STRIPE -.-> P3 API_LEXIS -.-> P4 API_SRX -.-> SIGN API_TITAN -.-> P9 API_RM -.-> P11 classDef startNode fill:#1e3a5f,stroke:#60a5fa,color:#fff,stroke-width:2px classDef greenNode fill:#065f46,stroke:#34d399,color:#fff,stroke-width:2px classDef greenEnd fill:#065f46,stroke:#34d399,color:#fff,stroke-width:2px classDef redNode fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px classDef orangeNode fill:#78350f,stroke:#fbbf24,color:#fff,stroke-width:2px classDef apiNode fill:#eef2ff,stroke:#818cf8,color:#3730a3,stroke-width:2px,stroke-dasharray: 5 5 classDef supportNode fill:#f0f4ff,stroke:#93c5fd,color:#1e3a5f,stroke-width:1px,stroke-dasharray: 5 5 classDef pathA fill:#1e3a5f,stroke:#60a5fa,color:#fff,stroke-width:2px classDef pathB fill:#3b1f5e,stroke:#a78bfa,color:#fff,stroke-width:2px classDef pomNode fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px classDef pItemNode fill:#1e3a5f,stroke:#818cf8,color:#fff,stroke-width:2px classDef gslNode fill:#065f46,stroke:#34d399,color:#fff,stroke-width:2px classDef apiLabel fill:#f5f3ff,stroke:#a78bfa,color:#5b21b6,stroke-width:1px,stroke-dasharray: 3 3,font-size:11px
Key Architecture Decisions
- Payment model: Full payment upfront. If rejected at any stage → automatic full refund.
- One-off vs Instalment: Patient selects after consultation, before checkout. The flow splits at Phase 7: 7A = single Rx for one order. 7B = single Rx covering full instalment plan (up to 12 months, configurable per product). Prescriber can override the patient's selected plan length.
- Rx is final: Once the prescriber signs in SignatureRx, the prescription is locked. No void/replacement process.
- Post-approval triggers (Phase 8): SignatureRx webhook fires THREE actions simultaneously: GP letter, patient notification, pharmacy queue entry. GP notified before dispatch.
- Instalment renewal: Pharmacy auto-dispatches monthly (no prescriber re-review). At plan end, patient re-confirms. After 12 months total → fresh consultation required.
- Renewal overlap flag: If a patient triggers a renewal while a previous plan is still active, this is prominently flagged to both the prescriber (Phase 6) and pharmacy team (dispatch) so they can assess whether overlapping supply is appropriate.
- Answer expiry (grace period): After a plan or order ends, the patient has a grace period of plan duration + 1 month to reorder. If that window passes, all consultation answers are cleared and they must start a fresh consultation. (e.g. 3-month plan = 4-month grace, 6-month plan = 7-month grace, one-off = 1 month grace). Configurable per product.
- Three product classifications: POM → prescriber reviews + Rx + e-signing in SignatureRx. P (Pharmacy) → pharmacist reviews + approves (logged & timestamped, no e-signing). GSL / Test Kit → pharmacy team processes directly (no clinical review needed). All three paths support instalments.
Phase 1: Product Selection & Consultation Entry
Patient clicks the CTA on a product page and enters the consultation flow.
flowchart TD A["▶ Patient on product page
(e.g. Regaine, Finasteride)"]:::startNode A --> B["Patient clicks
'Start Your Consultation' CTA"] B --> C["Consultation form loads
for product category"]:::greenNode C --> D["→ PHASE 2"]:::nextPhase classDef startNode fill:#1e3a5f,stroke:#60a5fa,color:#fff classDef greenNode fill:#065f46,stroke:#34d399,color:#fff classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff
Annotation
- System routes patient to the consultation form for that product category (e.g. Hair Loss)
- The product and category are passed through so the correct form loads
- No login or account required at this stage — anyone can start a consultation
- Account creation / login is only required later at checkout (Phase 3)
Phase 2: Consultation Form
Patient completes the consultation form. Auto-denial logic runs in real time.
flowchart TD A["Display consultation form
for category"] A --> B["Patient answers questions"] B --> C{"Does any answer
trigger auto-denial?"} C -->|YES| D["✖ AUTO-DENIED"]:::redNode D --> D1["Show denial message:
'This treatment may not be
suitable — see your GP'"] D1 --> D2["Log denial reason +
email patient"] D2 --> D3["Notify clinical team
(for awareness)"] D3 --> D4["END — Auto-Denied"]:::redEnd C -->|NO| E["Continue to
next question"] E --> F{"All questions
complete?"} F -->|NO| B F -->|YES| G["Patient confirms consent:
T&Cs + remote consultation"] G --> G2["Submit consultation"]:::greenNode G2 --> H["→ PHASE 3"]:::nextPhase classDef redNode fill:#fef2f2,stroke:#f87171,color:#991b1b,stroke-width:2px classDef redEnd fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff
Annotation
- Forms are configurable in the backend — questions, order, and logic rules per category
- Questions cover: medical history, current medications, allergies, symptoms, previous treatments
- Auto-check logic runs on each answer in real time
- Example disqualifier: patient selects a contraindicated medical condition
- Auto-denial happens before payment is taken — no refund needed
- Patient may resubmit — see Phase 10 (repeat submission detection)
Consent
- Before submission, patient must tick consent: T&Cs acceptance + agreement to remote consultation
- Consent is also required at instalment renewal — patient confirms nothing has changed
- After the 12-month hard limit, a full new consultation form is required
Abandonment recovery
- If a logged-in patient starts but does not complete the consultation, the system logs the incomplete session
- After a configurable timeframe (e.g. 1 hour / 24 hours), system sends a reminder email
- Only works for logged-in users (we need their email)
- Non-logged-in abandonments cannot be recovered
Phase 3: Payment & Plan Selection
Consultation is saved, patient selects one-off or instalment plan, and payment is taken.
flowchart TD A["Consultation submitted"] A --> B["System saves full
consultation record +
reference number"] B --> R["Run repeat submission
check → Phase 10"]:::supportNode R --> L{"Logged in?"} L -->|YES| PLAN L -->|NO| M["Prompt: log in or
create account"] M --> N["Patient enters:
name, DOB, email,
phone, delivery address"] N --> PLAN PLAN["Select order type:"] PLAN --> TYPE{"One-off or
Instalment?"} TYPE -->|"ONE-OFF (A)"| QTY_A["Select quantity
(single order)"]:::pathA TYPE -->|"INSTALMENT (B)"| QTY_B["Select instalment plan
(e.g. 3, 6, 12 months)
Configurable per product
Hard limit: 12 months total"]:::pathB QTY_A --> PAY["Patient pays"] QTY_B --> PAY PAY --> F{"Payment
successful?"} F -->|NO| G["↻ Show payment error
— patient can retry"]:::orangeNode G --> PAY F -->|YES| H["Payment captured"]:::greenNode H --> I["Confirmation shown:
'Payment received —
consultation being reviewed'"] I --> J["System records:
order type (one-off / instalment)
instalment count (if applicable)
instalment 1 of X"] J --> K["→ PHASE 4: ID Check"]:::nextPhase classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef orangeNode fill:#fffbeb,stroke:#fbbf24,color:#78350f,stroke-width:2px classDef supportNode fill:#f0f4ff,stroke:#93c5fd,color:#1e3a5f,stroke-dasharray: 5 5 classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff classDef pathA fill:#eef6ff,stroke:#60a5fa,color:#1e3a5f,stroke-width:2px classDef pathB fill:#f3eeff,stroke:#a78bfa,color:#3b1f5e,stroke-width:2px
Annotation
One-off vs Instalment selection
- Patient chooses Path A: One-off (single order) or Path B: Instalment (recurring monthly dispatch)
- Instalment plans: up to 12 months. Duration options are configurable per product in the backend
- 12-month hard limit across ALL instalment plans. After 12 months of continuous treatment, a full fresh consultation is required
- Instalment availability is configurable per product — can be enabled/disabled by the pharmacy team
- Both POM and P items can support instalments
Payment model
- One-off: Full payment upfront for the single order
- Instalment: First month's payment taken now. Subsequent months charged automatically
- If the order is later rejected (ID fail or clinical denial), full refund is issued
Excessive quantity controls
- Clinical/pharmacy team can set maximum quantity per product
- Prescriber can flag orders with excessive quantities during review
- Prescriber / pharmacy team can override the patient's selected plan length (e.g. shorten duration based on clinical judgement)
Patient cancellation (pre-dispatch)
- Patient has a "Request Cancellation" button in their account — available before dispatch
- Button sends a message to the pharmacy team via the messaging centre
- Team manually processes the cancellation and issues a refund
Phase 4: ID Verification
Patient identity is verified via LexisNexis. If it fails, manual upload and review is available.
flowchart TD
A["Call LexisNexis IDU API"]:::apiNode
A --> B{"ID check result?"}
B -->|PASS| C["Record: Verified +
timestamp + reference"]:::greenNode
C --> Z["→ PHASE 5"]:::nextPhase
B -->|FAIL| D["Flag: ID Check —
Action Required"]:::orangeNode
B -->|REFER| D
D --> E["Email patient:
upload photo ID +
proof of address"]
E --> F["Patient uploads
documents"]
F --> G{"Manual verification
by clinical team?"}
G -->|YES| H["Mark ID = Verified"]:::greenNode
H --> Z
G -->|NO| I["Mark ID = Failed"]:::redNode
I --> J["Order status:
Rejected — Awaiting Refund"]
J --> K["Team issues refund"]
K --> L{"Refund confirmed?
(webhook)"}
L -->|YES| M["Rejected & Refunded"]:::refunded
M --> N["Email patient:
order cannot proceed +
refund issued"]
N --> END["END — ID Rejected"]:::redEnd
L -->|NO| O["Stays in
Awaiting Refund queue"]:::orangeNode
classDef apiNode fill:#eef2ff,stroke:#818cf8,color:#3730a3,stroke-width:2px,stroke-dasharray: 5 5
classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px
classDef orangeNode fill:#fffbeb,stroke:#fbbf24,color:#78350f,stroke-width:2px
classDef redNode fill:#fef2f2,stroke:#f87171,color:#991b1b,stroke-width:2px
classDef redEnd fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px
classDef refunded fill:#fef2f2,stroke:#f87171,color:#991b1b
classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff
Annotation
Refund tracking
- Rejected orders move to "Rejected — Awaiting Refund"
- Team issues refund from within the payment processor (e.g. Stripe)
- Patient email only sent after refund is confirmed
Phase 5: Clinical Review Queue & Notification
The consultation enters the review queue and the appropriate clinician is notified. This phase is about the queue and notification — the actual review happens in Phase 6.
flowchart TD A["Consultation enters
clinical review queue"] A --> B["Dashboard shows:
reference, patient, category,
POM/P type, ID status,
order type (one-off / instalment),
instalment count, repeat flag,
renewal flag if repeat instalment"] B --> C{"Product
classification?"} C -->|POM| D["Notification email sent
to prescriber(s)"]:::pomNode C -->|P item| E["Notification email sent
to pharmacist(s)"]:::pNode C -->|"GSL / Test Kit"| GK["Notification sent
to pharmacy team"]:::gslNode D --> F["→ PHASE 6:
Prescriber reviews case"]:::nextPhase E --> F2["→ PHASE 6:
Pharmacist reviews case"]:::nextPhase GK --> F3["→ PHASE 6:
Team processes order"]:::nextPhase classDef pomNode fill:#fef2f2,stroke:#f87171,color:#991b1b,stroke-width:2px classDef pNode fill:#eef2ff,stroke:#818cf8,color:#3730a3,stroke-width:2px classDef gslNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff
Annotation
Three routing paths by product classification
| Classification | Queue | Review in Phase 6 | Example |
|---|---|---|---|
| POM | Prescriber queue | Full clinical review → Rx + e-signing (Phase 7) | Finasteride, Sildenafil |
| P (Pharmacy) | Pharmacist queue | Pharmacist reviews & approves (logged, timestamped, auditable — no e-signing) | Viagra Connect |
| GSL / Test Kit | Pharmacy team queue | Team processes & takes forward (no clinical review needed) | Test kits, GSL products |
Notification email (secure, limited details)
- Contains: consultation reference, product category, type (POM/P), order type (one-off or instalment + count), date/time, direct link to case
- Does NOT contain: patient name, DOB, answers, or any clinical information
- Clinician must log into the website backend to see anything — the link goes to the specific case
Instalment & renewal visibility
- The queue clearly labels whether an order is one-off or instalment
- If instalment: shows the plan duration (e.g. Instalment — 3 months)
- If the patient is renewing on top of a previous instalment (i.e. they triggered a reorder before the last plan finished), this is prominently flagged as: RENEWAL — Instalment Plan 2 (prev. plan still active)
- This ensures the prescriber/pharmacist knows the patient already has an active supply and can assess whether an overlapping order is clinically appropriate
Consultation timeout
- System flags consultations pending review for more than 7 days
- After 30 days of inactivity → flagged as "abandonable" (team makes final call, never auto-expired)
Phase 6: Prescriber / Pharmacist Questionnaire Review
Three different review paths depending on the product classification. POM → prescriber reviews and signs Rx. P (Pharmacy) → pharmacist reviews and approves (logged + timestamped, no e-signing). GSL / Test Kits → pharmacy team processes directly.
flowchart TD
START{"Product
classification?"}
START -->|POM| A_POM["PRESCRIBER REVIEW"]:::pomHeader
A_POM --> B_POM["Prescriber logs in,
opens patient case"]
B_POM --> C_POM["Reviews full consultation:
• All Q&As, ID status, history
• Messages, repeat flag
• Order type + instalment duration
• Renewal flag + prev. plan history"]
C_POM --> D_POM{"Clinical decision?"}
D_POM -->|APPROVE| E_POM["Approved ✓"]:::greenNode
E_POM --> F_POM["→ PHASE 7:
Rx & E-Signing"]:::nextPhase
D_POM -->|MORE INFO| G_POM["Message patient
via messaging centre"]:::orangeNode
G_POM --> H_POM["Awaiting Patient Response"]:::orangeNode
H_POM --> C_POM
D_POM -->|DENY| I_POM["Denial reason +
clinical notes (mandatory)"]:::redNode
I_POM --> J_POM["Rejected → Refund →
Patient notified"]:::redEnd
START -->|"P item
(e.g. Viagra Connect)"| A_P["PHARMACIST REVIEW"]:::pHeader
A_P --> B_P["Pharmacist logs in,
opens patient case"]
B_P --> C_P["Reviews consultation
(same data as POM)"]
C_P --> D_P{"Decision?"}
D_P -->|APPROVE| E_P["Approved ✓
Logged: pharmacist ID,
timestamp, decision"]:::greenNode
E_P --> F_P["No Rx needed — skip Phase 7
→ PHASE 8: Triggers"]:::nextPhase
D_P -->|MORE INFO| G_P["Message patient"]:::orangeNode
G_P --> C_P
D_P -->|DENY| I_P["Denial + refund"]:::redEnd
START -->|"GSL / Test Kit"| A_GSL["PHARMACY TEAM"]:::gslHeader
A_GSL --> B_GSL["Team member opens order"]
B_GSL --> C_GSL["Checks: stock, delivery address,
any flags"]
C_GSL --> D_GSL["Processes order ✓"]:::greenNode
D_GSL --> E_GSL["No clinical review needed
→ PHASE 8: Triggers"]:::nextPhase
classDef pomHeader fill:#fef2f2,stroke:#f87171,color:#991b1b,stroke-width:2px,font-weight:bold
classDef pHeader fill:#eef2ff,stroke:#818cf8,color:#3730a3,stroke-width:2px,font-weight:bold
classDef gslHeader fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px,font-weight:bold
classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px
classDef orangeNode fill:#fffbeb,stroke:#fbbf24,color:#78350f,stroke-width:2px
classDef redNode fill:#fef2f2,stroke:#f87171,color:#991b1b,stroke-width:2px
classDef redEnd fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px
classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff
Annotation
Three review paths
| Classification | Who reviews | What happens on approval | Audit record |
|---|---|---|---|
| POM | Registered prescriber | Full Rx generated + e-signed in SignatureRx (Phase 7) | Signed Rx hash, timestamp, prescriber ID |
| P (Pharmacy) | Pharmacist | Approval logged — no Rx or e-signing needed. Skips Phase 7 → Phase 8 | Pharmacist ID, timestamp, decision logged |
| GSL / Test Kit | Pharmacy team | Order processed directly — no clinical review needed. Skips Phase 7 → Phase 8 | Team member ID, timestamp |
- Phase 5 was the notification and queue entry. Phase 6 is where the reviewer actually logs in and takes action.
- The split between Phase 5 and Phase 6 is deliberate — two distinct system states: "waiting in queue" vs "actively being reviewed".
One-off vs instalment awareness
- The case screen prominently displays whether this is a one-off order or an instalment plan
- If instalment: Instalment — X months badge shown at the top of the case
- Prescriber can override the patient's selected plan length (e.g. shorten from 6 months to 3 months based on clinical judgement)
- This override is logged with the prescriber's reason and applied before Rx generation in Phase 7
Renewal instalment flag (repeat orders)
- If the patient is renewing an instalment (i.e. reordering before or after a previous plan), the case screen shows a prominent renewal banner:
- Badge: RENEWAL — Plan 2 of ongoing treatment
- Shows previous plan history: plan number, dates, total months of treatment to date, whether the previous plan is still active
- If previous plan is still active (patient triggered reorder early), this is highlighted in amber so the prescriber can assess whether overlapping supply is clinically appropriate
- Prescriber sees total cumulative treatment duration to date — this is critical for the 12-month hard limit check
P items (Pharmacy Medicines) — e.g. Viagra Connect
- Pharmacist reviews and simply approves — no e-signing flow needed
- Approval is logged and auditable: pharmacist ID, timestamp, decision recorded
- Flow skips Phase 7 entirely → straight to Phase 8 (post-approval triggers)
GSL / Test Kits
- No clinical review required — pharmacy team processes the order directly
- Team checks stock, delivery address, and any flags
- Flow skips Phase 7 entirely → straight to Phase 8 (post-approval triggers)
- Logged: team member ID + timestamp for audit
Denial
- Mandatory: select reason from predefined list + free-text clinical notes
- Patient rejection email sent only after refund is confirmed
Phase 7: Rx Generation & E-Signing (7A / 7B)
The prescriber generates and signs the prescription inside SignatureRx. The flow splits into Phase 7A (one-off) and Phase 7B (instalment). Both paths merge after signing. For P items, this phase is skipped — pharmacist approval in Phase 6 goes directly to Phase 8.
flowchart TD A["Prescriber clicks
'Approve Treatment'"] A --> B["System auto-populates Rx fields
from consultation + product data"] B --> C["Prescriber reviews / adjusts"] C --> D["Order type shown:
ONE-OFF — single order"]:::pathA D --> E["Prescriber clicks
'Generate Prescription'"] E --> F["🔗 OUTBOUND API
Website → SignatureRx:
CREATE PRESCRIPTION"]:::apiOut F --> G["SignatureRx returns
Rx reference ID"]:::apiIn G --> H["Prescriber signs Rx
inside SignatureRx
(MFA + e-signing)"]:::external H --> I["🔗 INBOUND API (WEBHOOK)
SignatureRx → Website:
Signed Rx + hash + timestamp"]:::apiIn I --> J["Website backend receives
signed Rx via webhook"]:::backendNode J --> J2["Rx LOCKED —
signature is final"]:::greenNode J2 --> K["Website backend
automatically triggers
Phase 8 actions:
GP Letter | Patient Msg |
Pharmacy Team Notified"]:::triggerNode K --> L["→ PHASE 8"]:::nextPhase classDef pathA fill:#eef6ff,stroke:#60a5fa,color:#1e3a5f,stroke-width:2px classDef apiOut fill:#eef2ff,stroke:#818cf8,color:#3730a3,stroke-width:2px,stroke-dasharray: 5 5 classDef apiIn fill:#f0e6ff,stroke:#a78bfa,color:#4c1d95,stroke-width:2px,stroke-dasharray: 5 5 classDef external fill:#fefce8,stroke:#ca8a04,color:#713f12,stroke-width:2px classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef backendNode fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e,stroke-width:2px classDef triggerNode fill:#065f46,stroke:#34d399,color:#fff,stroke-width:2px classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff
flowchart TD A["Prescriber clicks
'Approve Treatment'"] A --> B["System auto-populates Rx fields +
instalment details"] B --> C["Prescriber sees prominently:
INSTALMENT PLAN
Duration: X months
Instalment 1 of X
Can override plan length"]:::pathB C --> D["Prescriber reviews / adjusts"] D --> E["Prescriber clicks
'Generate Prescription'"] E --> F["🔗 OUTBOUND API
Website → SignatureRx:
CREATE PRESCRIPTION
(covers full instalment period)"]:::apiOut F --> G["SignatureRx returns
Rx reference ID"]:::apiIn G --> H["Prescriber signs single Rx
covering all instalments
inside SignatureRx
(MFA + e-signing)"]:::external H --> I["🔗 INBOUND API (WEBHOOK)
SignatureRx → Website:
Signed Rx + hash + timestamp"]:::apiIn I --> J["Website backend receives
signed Rx via webhook"]:::backendNode J --> J2["Rx LOCKED
Instalment plan recorded"]:::greenNode J2 --> K["Website backend stores:
• Instalment 1 of X
• Next dispatch date
• Rx covers full period
• Renewal reminder date"]:::greenNode K --> L["Website backend
automatically triggers
Phase 8 actions:
GP Letter | Patient Msg |
Pharmacy Team Notified"]:::triggerNode L --> M["→ PHASE 8"]:::nextPhase classDef pathB fill:#f3eeff,stroke:#a78bfa,color:#3b1f5e,stroke-width:2px classDef apiOut fill:#eef2ff,stroke:#818cf8,color:#3730a3,stroke-width:2px,stroke-dasharray: 5 5 classDef apiIn fill:#f0e6ff,stroke:#a78bfa,color:#4c1d95,stroke-width:2px,stroke-dasharray: 5 5 classDef external fill:#fefce8,stroke:#ca8a04,color:#713f12,stroke-width:2px classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef backendNode fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e,stroke-width:2px classDef triggerNode fill:#065f46,stroke:#34d399,color:#fff,stroke-width:2px classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff
Annotation
Phase 7A vs 7B — key differences
| 7A — One-Off | 7B — Instalment | |
|---|---|---|
| What patient selected | Single order | Instalment plan (e.g. 3, 6, or 12 months — configurable per product) |
| What prescriber sees | "One-off order" | "Instalment plan — X months" (prominently displayed) |
| Rx scope | Covers single order | Single Rx covering full instalment period |
| After signing | One dispatch | Pharmacy auto-dispatches monthly (Instalment X of Y) |
| Renewal | Patient reorders manually | Patient reminded at month X-1 to re-confirm (Phase 13) |
Where things happen — the API round-trip
- Step 1 — Viva backend (outbound API call): Prescriber clicks "Generate Prescription" → our website sends Rx data to SignatureRx via their API
- Step 2 — SignatureRx (external platform): The prescription is created and the prescriber signs it inside SignatureRx. All MFA and e-signing is handled entirely within SignatureRx — not on our website
- Step 3 — SignatureRx → Viva backend (inbound webhook / API callback): Once signed, SignatureRx sends a webhook back to our website with the signed Rx data (hash, timestamp, prescriber details)
- Step 4 — Viva backend (automatic triggers): Our website backend receives the webhook and immediately triggers Phase 8 actions: GP letter generated, patient notified, pharmacy team notified that the Rx is ready — all fired automatically from the webhook handler, with no manual step in between
Key point: The pharmacy team is informed the instant the prescriber signs. There is no delay or manual handoff — the SignatureRx webhook hits our backend and the triggers fire automatically.
Rx is final
- Once the prescriber signs, the prescription is locked and final
- There is no void/replacement process — the signature represents the prescriber's final clinical decision
- The signed Rx hash, timestamp, and prescriber details are stored permanently for audit
P items skip this phase
- For P (Pharmacy) medicines, the pharmacist approved in Phase 6
- No formal Rx is generated — the approval decision, pharmacist ID, and timestamp serve as the record
- Flow goes directly from Phase 6 → Phase 8
Phase 8: Post-Approval Automated Triggers
When the Rx is signed (POM) or pharmacist approves (P item), the SignatureRx webhook or approval event automatically triggers three parallel actions — all at the same time.
flowchart TD A["SignatureRx signed webhook
(or pharmacist approval event)"]:::apiIn A --> B["Website backend processes
signed Rx / approval"] B --> C["THREE AUTOMATED TRIGGERS
fire simultaneously:"] C --> D["✉ 1. GP LETTER
Auto-generated PDF +
emailed to GP"]:::trigger C --> E["✉ 2. PATIENT MESSAGE
'Your prescription has been
approved and is now
with the pharmacy'"]:::trigger C --> F["⚙ 3. PHARMACY NOTIFICATION
Order enters processing
queue in backend
(labelled: one-off
or instalment X of Y)"]:::trigger D --> D2{"GP email
available?"} D2 -->|YES| D3["Auto-email GP letter"]:::greenNode D2 -->|NO| D4["Flag: GP Email Missing
Team can input later"]:::orangeNode D3 --> D5{"Bounced?"} D5 -->|NO| D6["✅ GP letter sent"]:::greenNode D5 -->|YES| D7["Flag: GP Email Failed
Team corrects email"]:::orangeNode E --> E2["Email + in-app message
to patient account"]:::greenNode F --> F2["Order visible in
dispatch queue"]:::greenNode classDef apiIn fill:#f0e6ff,stroke:#a78bfa,color:#4c1d95,stroke-width:2px,stroke-dasharray: 5 5 classDef trigger fill:#1e3a5f,stroke:#60a5fa,color:#fff,stroke-width:2px classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef orangeNode fill:#fffbeb,stroke:#fbbf24,color:#78350f,stroke-width:2px
Annotation
Why GP letter fires on signing (not dispatch)
- The GP is notified as soon as the prescription is signed — before dispatch
- This gives the GP time to flag concerns or contact the patient/pharmacy before the medication is shipped
- This is a safety measure — the GP should be aware at the earliest possible moment
GP letter content
- Patient name, DOB, medication prescribed/supplied, date, prescriber/pharmacist details
- Generated for ALL approved orders — both POM and P items
- GP email send status: Sent Failed Pending Not Collected
- Clinical team always has a manual field to enter/correct GP email
Patient notification
- Patient receives both an email and an in-app message
- Confirms: what was prescribed, that it's with the pharmacy, and they'll get a dispatch email with tracking
Pharmacy notification
- Order appears in the processing/dispatch queue
- Clearly labelled: One-Off or Instalment 1 of 3
- All gate checks visible (ID, approval, Rx, payment)
Phase 9: PMR Integration & Order Print Slip
Two parallel functions: sync to TitanPMR and a printable order slip for picking/packing.
flowchart TD A["Order approved"] A --> B["Push data to
TitanPMR via API"]:::apiNode A --> E["Print slip available on
Approved Orders screen"] B --> C{"API available?"} C -->|YES| D["✅ Sync complete"]:::greenNode C -->|NO| D2["Staff manually exports
data into TitanPMR"]:::orangeNode E --> F["Staff clicks
'Print Order Slip'"] F --> G["System generates A4/A5
slip from template"] G --> H["Print slip sent
to printer"]:::greenNode classDef apiNode fill:#eef2ff,stroke:#818cf8,color:#3730a3,stroke-dasharray: 5 5 classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef orangeNode fill:#fffbeb,stroke:#fbbf24,color:#78350f,stroke-width:2px
Annotation
Order print slip fields (hardcoded template)
- Patient full name, DOB, address, delivery address
- Item / medication name, pack size, quantity, dosage/directions
- Approved by: prescriber or pharmacist name
- Approval date + timestamp
- Order reference, consultation reference
- Order type: One-Off or Instalment X of Y
Available ONLY from the Approved Orders screen. Internal pharmacy use.
Phase 10: Repeat Submission Detection
Flags patients who submit multiple consultations in a short window.
flowchart TD
A["New consultation submitted"]
A --> B{"Same patient +
same category
within 7 days?"}
B -->|NO| C["No flag —
proceed normally"]:::greenNode
B -->|YES| D["Flag: 'Repeat submission —
X submissions in Y days'"]:::orangeNode
D --> E["Flag visible to clinician
in Phase 6 review"]
E --> F["Clinician can view all
previous submissions"]
classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px
classDef orangeNode fill:#fffbeb,stroke:#fbbf24,color:#78350f,stroke-width:2px
Annotation
- Configurable time window (default 7 days)
- Optional: compare answers between submissions and highlight differences
- Prominent warning banner when clinician opens the case in Phase 6
Phase 11: Order Processing & Dispatch
All gates must pass before dispatch. Royal Mail API generates shipping label and tracking. Instalment orders are clearly labelled.
flowchart TD A["Order appears in
dispatch queue"] A --> A2["Order labelled:
ONE-OFF or
INSTALMENT X of Y"] A2 --> B{"All gates passed?"} B -->|ANY = NO| C["✖ Order blocked"]:::redNode B -->|ALL = YES| D["Staff picks and
packs order"]:::greenNode D --> E["Mark as 'Packed'"] E --> F["API → Royal Mail:
CREATE SHIPMENT"]:::apiNode F --> G["Returns: tracking number +
shipping label (PDF)"] G --> H["Store tracking + print label"] H --> I["Email patient:
'Order dispatched' +
tracking link"] I --> J["Patient receives package
(plain, discreet packaging)"]:::greenNode J --> END["→ PHASE 12"]:::nextPhase classDef apiNode fill:#eef2ff,stroke:#818cf8,color:#3730a3,stroke-dasharray: 5 5 classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef redNode fill:#fef2f2,stroke:#f87171,color:#991b1b,stroke-width:2px classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff
Annotation
Dispatch gate checks (ALL must be YES)
- ID Verified = YES
- Clinical approval = YES
- Prescription signed = YES (if POM)
- Payment confirmed = YES
Instalment dispatch tracking
- Each instalment dispatch logged as Instalment X of Y
- Subsequent instalment dispatches are auto-queued — pharmacy team processes without prescriber re-review
- Pharmacy team can see a report of all upcoming instalment dispatches
Phase 12: Post-Dispatch & Delivery
Delivery tracking, failed delivery handling, and the path to completion or instalment renewal.
flowchart TD A["Royal Mail tracking
update received"] A --> B{"Delivery status?"} B -->|DELIVERED| C["Order status:
'Delivered'"]:::greenNode C --> D["Patient can access:
order history, Rx records,
GP letters in account"] D --> E{"Order type?"} E -->|ONE-OFF| F["✅ ORDER COMPLETE"]:::greenEnd E -->|INSTALMENT| G{"Last instalment
of plan?"} G -->|NO| H["Next instalment
auto-queued for
next month → Phase 11"]:::pathB G -->|YES| I["→ Phase 13:
Instalment Renewal"]:::pathB B -->|FAILED / RETURNED| K["Order status:
'Delivery Failed'"]:::redNode K --> L["Delivery Failed screen"] L --> M["Pharmacy team notified"] M --> N{"Team action?"} N -->|Re-dispatch| O["Update address / re-send"]:::greenNode N -->|Contact patient| P["Message via
messaging centre"]:::orangeNode N -->|Refund| Q["Issue refund"]:::redEnd classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef greenEnd fill:#065f46,stroke:#34d399,color:#fff,stroke-width:2px classDef orangeNode fill:#fffbeb,stroke:#fbbf24,color:#78350f,stroke-width:2px classDef redNode fill:#fef2f2,stroke:#f87171,color:#991b1b,stroke-width:2px classDef redEnd fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px classDef pathB fill:#f3eeff,stroke:#a78bfa,color:#3b1f5e,stroke-width:2px
Annotation
Delivery failure
- Failed deliveries go into a dedicated "Delivery Failed" screen
- Team can: re-dispatch, contact patient, or issue refund
Audit trail (accessible at any time)
- Consultation form and answers, ID check, clinical decision, Rx record, payment, dispatch/tracking, instalment history
Phase 13: Instalment Renewal Flow
How instalment plans renew, the patient re-confirmation process, and the 12-month hard limit.
flowchart TD A["Patient approaching
final month of
instalment plan"]:::pathB A --> B["System sends reminder
at month X-1
(e.g. month 2 of 3):
'Log in to manage
your next order'"] B --> C["Patient logs into
their account"] C --> D["System displays their
latest consultation
form answers
for review"] D --> E["Patient must tick
confirmation boxes:"] E --> E1["☑ I confirm my answers
are still accurate"] E1 --> E2["☑ Nothing has changed
in my medical history"] E2 --> E3["☑ I consent to inform
Viva proactively
if anything changes"] E3 --> F{"Does patient
want to renew?"} F -->|YES| G{"Within 12-month
hard limit?"} G -->|YES| H["New instalment plan starts"]:::pathB H --> I["Payment taken for
first month of
new plan"] I --> J["Pharmacy team processes
(no prescriber review —
clearly labelled as
renewal instalment)"]:::greenNode J --> K["→ Phase 11: Dispatch"]:::nextPhase G -->|"NO — 12 months reached"| L["12-MONTH HARD LIMIT
Answers cleared —
full new consultation
required"]:::orangeNode L --> M["Patient directed to
→ Phase 1"]:::nextPhase F -->|NO| N["Plan ends —
patient can reorder
within grace period"]:::greenNode N --> GRACE{"Reorder within
grace period?
(plan duration + 1 month)"} GRACE -->|YES| REORD["Patient re-confirms
answers → new order
or new plan"]:::pathB REORD --> K GRACE -->|"NO — grace period
expired"| EXPIRED["ANSWERS EXPIRED
All consultation data
cleared — patient must
start fresh"]:::orangeNode EXPIRED --> M classDef pathB fill:#f3eeff,stroke:#a78bfa,color:#3b1f5e,stroke-width:2px classDef greenNode fill:#f0fdf4,stroke:#34d399,color:#065f46,stroke-width:2px classDef orangeNode fill:#fffbeb,stroke:#fbbf24,color:#78350f,stroke-width:2px classDef nextPhase fill:#1e3a5f,stroke:#60a5fa,color:#fff
Annotation
Renewal process
- At month X-1 of the plan (e.g. month 2 of 3), patient receives email + in-app notification
- Patient logs in and is shown their original consultation answers
- They must tick three confirmation boxes — this is their re-consent
- If they confirm, a new instalment plan starts and payment is taken
Pharmacy team processing (no prescriber review)
- Renewal instalments go directly to the pharmacy team — not back to the prescriber
- Clearly labelled in the dispatch queue: Renewal — Instalment Plan 2 (X months)
- Pharmacy team can see at a glance:
- Plan number: which plan this is (e.g. Plan 2, Plan 3)
- Total treatment duration: cumulative months since original consultation
- Previous plan still active? If yes, flagged in amber — the patient triggered a renewal before their last plan finished, so the team should check the overlap is appropriate before dispatching
- Instalment X of Y: where in the current plan this dispatch falls
- Pharmacy team processes and dispatches as normal — but the overlap flag ensures they consciously acknowledge it
12-month hard limit
- 12 months is the absolute maximum for continuous treatment without a fresh consultation
- This is a hard system block — the patient cannot renew past this point
- After 12 months, all consultation answers are cleared — full new consultation required (Phase 1), going through the full review cycle again
Answer expiry (grace period)
- After any plan ends (or a one-off order completes), the patient has a grace period to reorder without redoing the consultation
- Grace period = plan/order duration + 1 month (e.g. 3-month plan = 4-month grace, 6-month plan = 7-month grace, one-off = 1-month grace)
- If the grace period passes, the system clears all stored consultation answers
- The patient must then complete a fresh consultation from scratch (Phase 1)
- This applies to both one-off and instalment patients — the clock starts from the date of the last dispatched order
- Grace period should be configurable per product so it can be adjusted in future
Example timeline: 3-month plans
| Month | What happens |
|---|---|
| 1 | Initial order — consultation, review, Rx, dispatch (Instalment 1/3) |
| 2 | Auto-dispatch by pharmacy (Instalment 2/3). Patient reminded to re-confirm. |
| 3 | Auto-dispatch (Instalment 3/3). Plan complete. |
| 3 (end) | Patient renews: reviews answers, ticks boxes, pays → new plan starts |
| 4–6 | Second plan runs (Instalment 1/3, 2/3, 3/3) |
| 7–9 | Third plan (if renewed) |
| 10–12 | Fourth plan (if renewed) |
| 12+ | HARD LIMIT — answers cleared, full new consultation required |
| Grace period rule (applies to all orders): | |
| Within grace period (plan duration + 1mo) | Patient can reorder (re-confirm answers, no new consultation) |
| Grace period expired | Answers expired & cleared — fresh consultation required |
Error / Exception Paths Summary
All rejection and error scenarios with refund status.
| Scenario | What happens | Refund? | Terminal state |
|---|---|---|---|
| Auto-denial from form logic | Patient told treatment not suitable, advised to see GP | No — before payment | Auto-Denied |
| Payment fails at checkout | Patient shown error, can retry | N/A — never captured | Awaiting Payment |
| ID check fails | Upload requested → manual review → if still fails, rejected | Yes — via Stripe | Rejected → Refunded |
| Clinician requests more info | Patient messaged, consultation paused | No — still active | Awaiting Response |
| Clinician denies treatment | Reason logged, patient notified after refund confirmed | Yes — via Stripe | Rejected → Refunded |
| Repeat submission detected | Flag shown to clinician during Phase 6 review | No — informational | Flagged for Review |
| Consultation abandoned | Reminder email sent. Flagged at 7 days, abandonable at 30 days. | N/A — before payment | Abandoned (Draft) |
| Patient requests cancellation | Message to pharmacy team. Manual cancel + refund. | Yes — manual | Cancelled → Refunded |
| Consultation timeout (30 days) | Team can reject/refund after 30 days. | Yes — manual | Abandoned → Refunded |
| Delivery failed / returned | Delivery Failed screen. Team re-dispatches, contacts, or refunds. | Depends on action | Delivery Failed |
| API unavailable (any) | Order tagged "Pending (API Unavailable)". Auto-retry: 5min → 30min → 2hr → flag manual. | No — still active | Pending (API Down) |
| Instalment payment fails (month 2+) | Pharmacy notified. Patient contacted. Dispatch paused. | May cancel remaining | Instalment Paused |
| 12-month hard limit reached | Patient cannot renew. Must complete full new consultation. | No — not an error | Consultation Required |
Key API Integrations
All external system integrations with direction and timing.
| System | API | Direction | When |
|---|---|---|---|
| LexisNexis IDU | Identity verification | Website → LexisNexis | Phase 4 — after payment |
| SignatureRx | Create Prescription | Website → SignatureRx | Phase 7 — prescriber approves POM |
| SignatureRx | Signed Rx webhook | SignatureRx → Website | Phase 7 → triggers Phase 8 (GP letter + patient msg + pharmacy queue) |
| Royal Mail | Create Shipment | Website → Royal Mail | Phase 11 — after order packed |
| Royal Mail | Tracking webhook | Royal Mail → Website | Phase 12 — delivery updates |
| TitanPMR | Patient data push | Website → TitanPMR | Phase 9 — after order confirmed |
| Stripe | Full capture / first instalment | Website → Stripe | Phase 3 — after plan selection |
| Stripe | Recurring instalment charge | Stripe → auto-charge | Phase 13 — monthly for instalment plans |
| Stripe | Refund confirmation webhook | Stripe → Website | After team issues refund |
Optional Extras
Features we ideally want but can be deferred. These are not blockers — the core flow works without them.
| Priority | Feature | What it does | Where | Fallback |
|---|---|---|---|---|
| High | Stock management | Track stock levels, block dispatch if out of stock | Phase 11 | Manual tracking |
| High | TitanPMR API | Auto-push patient data to PMR | Phase 9 | Manual export |
| Medium | Royal Mail tracking webhook | Auto-update delivery status | Phase 12 | Manual status update |
| Medium | Notification batching | Digest emails for prescribers | Phase 5 | Immediate per case |
| Medium | Answer-diff detection | Compare repeat submission answers | Phase 10 | Manual comparison |
| Low | Low-stock alerts | Email when stock is low | Phase 11 | Depends on stock mgmt |
Priority key
- High = strong business value, build if timeline allows
- Medium = nice to have, defer to v2
- Low = dependent on another optional feature