VIVA
Pharmacy Backend Flowchart

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

ClassificationQueueReview in Phase 6Example
POMPrescriber queueFull clinical review → Rx + e-signing (Phase 7)Finasteride, Sildenafil
P (Pharmacy)Pharmacist queuePharmacist reviews & approves (logged, timestamped, auditable — no e-signing)Viagra Connect
GSL / Test KitPharmacy team queueTeam 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

ClassificationWho reviewsWhat happens on approvalAudit record
POMRegistered prescriberFull Rx generated + e-signed in SignatureRx (Phase 7)Signed Rx hash, timestamp, prescriber ID
P (Pharmacy)PharmacistApproval logged — no Rx or e-signing needed. Skips Phase 7 → Phase 8Pharmacist ID, timestamp, decision logged
GSL / Test KitPharmacy teamOrder processed directly — no clinical review needed. Skips Phase 7 → Phase 8Team 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.

PHASE 7A — ONE-OFF ORDER
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
PHASE 7B — INSTALMENT ORDER
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-Off7B — Instalment
What patient selectedSingle orderInstalment plan (e.g. 3, 6, or 12 months — configurable per product)
What prescriber sees"One-off order""Instalment plan — X months" (prominently displayed)
Rx scopeCovers single orderSingle Rx covering full instalment period
After signingOne dispatchPharmacy auto-dispatches monthly (Instalment X of Y)
RenewalPatient reorders manuallyPatient 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

MonthWhat happens
1Initial order — consultation, review, Rx, dispatch (Instalment 1/3)
2Auto-dispatch by pharmacy (Instalment 2/3). Patient reminded to re-confirm.
3Auto-dispatch (Instalment 3/3). Plan complete.
3 (end)Patient renews: reviews answers, ticks boxes, pays → new plan starts
4–6Second plan runs (Instalment 1/3, 2/3, 3/3)
7–9Third plan (if renewed)
10–12Fourth 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 expiredAnswers expired & cleared — fresh consultation required

Error / Exception Paths Summary

All rejection and error scenarios with refund status.

ScenarioWhat happensRefund?Terminal state
Auto-denial from form logicPatient told treatment not suitable, advised to see GPNo — before paymentAuto-Denied
Payment fails at checkoutPatient shown error, can retryN/A — never capturedAwaiting Payment
ID check failsUpload requested → manual review → if still fails, rejectedYes — via StripeRejected → Refunded
Clinician requests more infoPatient messaged, consultation pausedNo — still activeAwaiting Response
Clinician denies treatmentReason logged, patient notified after refund confirmedYes — via StripeRejected → Refunded
Repeat submission detectedFlag shown to clinician during Phase 6 reviewNo — informationalFlagged for Review
Consultation abandonedReminder email sent. Flagged at 7 days, abandonable at 30 days.N/A — before paymentAbandoned (Draft)
Patient requests cancellationMessage to pharmacy team. Manual cancel + refund.Yes — manualCancelled → Refunded
Consultation timeout (30 days)Team can reject/refund after 30 days.Yes — manualAbandoned → Refunded
Delivery failed / returnedDelivery Failed screen. Team re-dispatches, contacts, or refunds.Depends on actionDelivery Failed
API unavailable (any)Order tagged "Pending (API Unavailable)". Auto-retry: 5min → 30min → 2hr → flag manual.No — still activePending (API Down)
Instalment payment fails (month 2+)Pharmacy notified. Patient contacted. Dispatch paused.May cancel remainingInstalment Paused
12-month hard limit reachedPatient cannot renew. Must complete full new consultation.No — not an errorConsultation Required

Key API Integrations

All external system integrations with direction and timing.

SystemAPIDirectionWhen
LexisNexis IDUIdentity verificationWebsite → LexisNexisPhase 4 — after payment
SignatureRxCreate PrescriptionWebsite → SignatureRxPhase 7 — prescriber approves POM
SignatureRxSigned Rx webhookSignatureRx → WebsitePhase 7 → triggers Phase 8 (GP letter + patient msg + pharmacy queue)
Royal MailCreate ShipmentWebsite → Royal MailPhase 11 — after order packed
Royal MailTracking webhookRoyal Mail → WebsitePhase 12 — delivery updates
TitanPMRPatient data pushWebsite → TitanPMRPhase 9 — after order confirmed
StripeFull capture / first instalmentWebsite → StripePhase 3 — after plan selection
StripeRecurring instalment chargeStripe → auto-chargePhase 13 — monthly for instalment plans
StripeRefund confirmation webhookStripe → WebsiteAfter team issues refund

Optional Extras

Features we ideally want but can be deferred. These are not blockers — the core flow works without them.

PriorityFeatureWhat it doesWhereFallback
HighStock managementTrack stock levels, block dispatch if out of stockPhase 11Manual tracking
HighTitanPMR APIAuto-push patient data to PMRPhase 9Manual export
MediumRoyal Mail tracking webhookAuto-update delivery statusPhase 12Manual status update
MediumNotification batchingDigest emails for prescribersPhase 5Immediate per case
MediumAnswer-diff detectionCompare repeat submission answersPhase 10Manual comparison
LowLow-stock alertsEmail when stock is lowPhase 11Depends 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