Part 2 of two. Part 1 — the backend view where the feeds are seen to be running and current — is live:
Data Feeds — Backend Status View. This page is how
the published data is shown to pharmacy staff, in the pharmacy application.
Steer, Matthew 2026-09-23: "now we need to see how it is displayed to the pharmacy — we will need to create a view
for this in the pharmacy app — again, let's keep it basic as there is quite a lot of detail and data we are dealing
with here — once that is done we can then start making necessary modifications."
So v1 is a baseline to be modified, not a finished screen. Parent:
Central Reference Data — D1 (which surface shows it
first: this answers it), §5.3 (getting the data to a client), §5.6 (labelling — a licence condition, not
polish).
The pharmacy application already reads the database that holds the store. Its default connection is the platform
database, so a read-through needs no new credential, no new network path and no copy of the data. Verified live by
querying from inside pharmacy_app:
reference_data tables visible;is_live true, publication dateThe plan (§5.3) leaned towards a cached subset per tenant over read-through. Recommended for v1: read-through,
because the objection to it has gone: there is no link to depend on — it is the same database the pharmacy application
already opens on every request, and the store is on infrastructure we run. Caching would add a fill/prune/refresh job
before a single screen exists.
is_live / published). Superseded and discarded releases are never shown..save() on a mirror model), not by database grant — both applications share the/medicines/ — "Product information" — added to£0.00, never blank.DmdGtin; and pharmacy_stock.SnomedItemMapping for EPS codes).Every page of the view carries, generated from the live release record and never typed into a template:
A label naming a superseded release is a defect, not a cosmetic issue — the acceptance check asserts the label's
presence with the live release identity, rather than eyeballing it.
/medicines/ is reachable to a signed-in pharmacy user and returns the label on every page of the viewprice_pence; a pack with none shows "no published price" and the word£0.00 anywhere in the rendered page — asserted across a sample of both cases.reference_data table (no INSERT/UPDATE/DELETE path in the code).The Drug Tariff feed (phase 4) and price concessions (phase 5, and D10 consent) — a piece of tariff pricing already
exists inside dm+d and is in scope only as dm+d data; ordering or reimbursement use of these figures (the guardrail the
pricing plan postponed); the cached subset and any tenant-side sync; exports; the backend status view (Part 1, live);
who may publish (unchanged); any change to what a client tenant can see of the machinery (nothing — clients never see
feeds, releases or uploads, only published data with its label).
Built by OpenCode on pharmacy_booking_app feature/pharmacy-medicines @ 27dc604 (off 9722205) — a new
pharmacy_medicines app carrying managed=False mirrors of only the tables the view needs, registered in
GLOBAL_APPS so central rows always route to the pharmacy app's default connection, never a sector or client DB.
/medicines/, /medicines/pack/<pk>/ and /medicines/about/, behind PharmacyStaffRequiredMixin (any pharmacy role,
no new permission). 18 new tests; OpenCode measured the search locally at 148 ms.
Deployed and verified live — 2026-09-23 (Hermes). 9722205 → 27dc604 as a git bundle (Forgejo unreachable
from the app host), pharmacy_app and both Celery containers restarted, pharmacy_medicines.0001_initial applied on
the default and the pharmacy tenant ("Applying pharmacy_medicines.0001_initial... OK"), app healthy.
| §5 | Result |
|---|---|
| 1. Reachable + labelled everywhere | PASS — anonymous /medicines/ → 302 on the apex and the client host; signed in → 200; the source line "NHSBSA dm+d, distributed by TRUD — release 3170926, published 21/09/2026" and the not-a-quotation sentence present on the list, detail and about pages |
2. Price / honest absence / never £0.00 |
PASS — priced pack 1327911000001107 → £44.20; unpriced pack 1328011000001109 → "no published price"; £0.00 absent from every page sampled; 0 zero-priced rows in the live release |
| 3. Live-release rows only | PASS — every result carried release_id = 1 (the live release); a pack pk outside it → 404. No superseded release is held in this environment, so that branch rests on the tests rather than a live state |
| 4. One capped query, measured | PASS — 614 packs match paracetam; the view returns the 25-row cap, truncated, with the SQL showing the release filter and LIMIT 26; 186 ms for the query, 317 ms end-to-end (OpenCode's local measure: 148 ms) |
| 5. No write path | PASS — no save/create/update/delete anywhere in the module outside its tests; the pharmacy_medicines suite re-run by me: 18 tests OK, and the full pharmacy suite: 461 tests OK (195 s) |
| 6. Same rows per tenant | PASS — demo.rp.two (apex) and tc.tech.one (org test-client-pharmacy): both 200, the same 25 pack links for ?q=paracetam |
Index decision: none added. ~186 ms server-side for a 614-match term is comfortable for a lookup screen, so the
pg_trgm GIN index on reference_data_dmdampp.name stays the first modification if it is ever felt — and it belongs
in the platform app's migrations, never a write to the store's tables from the pharmacy side.
How it was verified: two scripts run inside the deployed container (docker exec -i pharmacy_app python manage.py shell), exercising the view through Django's test client as a signed-in pharmacy user on both the apex and the client
host, plus direct calls into catalogue for the query shape and the price cases; and the module's own suite.
Deploy reminder: pharmacy application = container pharmacy_app on the app host, repo bind-mounted at /app —
a restart picks up a code change; Forgejo is not reachable from the app host, so commits travel as a git
bundle (as Part 1 did on 2026-09-23).