diff --git a/app/data/vaccinations-recorded.js b/app/data/vaccinations-recorded.js index c5de4ae2..76a4257b 100644 --- a/app/data/vaccinations-recorded.js +++ b/app/data/vaccinations-recorded.js @@ -142,6 +142,270 @@ module.exports = [ injectionSite: "Left arm", notes: "", editable: true + }, + + // Additional records below ensure every batch at Jane Smith's organisation + // (Central Manchester Trust, RW3) has at least 2 vaccination records + + { + id: "700001", + date: { day: "24", month: "11", year: "2025" }, + vaccine: "COVID-19", + vaccineProduct: "Comirnaty 3 LP.8.1", + patient: { + name: "Priya Patel", + nhsNumber: "9111222333" + }, + batchNumber: "8535345", // Batch AB2514 + batchExpiryDate: "2028-03-06", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3NM", // North Manchester General Hospital + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Right arm", + notes: "", + editable: true + }, + { + id: "700002", + date: { day: "24", month: "11", year: "2025" }, + vaccine: "flu", + vaccineProduct: "Adjuvanted Trivalent Influenza Vaccine (aTIV)", + patient: { + name: "Michael Osei", + nhsNumber: "9111222334" + }, + batchNumber: "634643636", // Batch 914-151 + batchExpiryDate: "2028-02-19", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3NM", // North Manchester General Hospital + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Left arm", + notes: "", + editable: true + }, + { + id: "700003", + date: { day: "23", month: "11", year: "2025" }, + vaccine: "flu", + vaccineProduct: "Adjuvanted Trivalent Influenza Vaccine (aTIV)", + patient: { + name: "Sarah Kowalski", + nhsNumber: "9111222335" + }, + batchNumber: "634643636", // Batch 914-151 + batchExpiryDate: "2028-02-19", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3NM", // North Manchester General Hospital + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Right arm", + notes: "", + editable: true + }, + { + id: "700004", + date: { day: "22", month: "11", year: "2025" }, + vaccine: "COVID-19", + vaccineProduct: "Comirnaty 3 LP.8.1", + patient: { + name: "Liam O'Connor", + nhsNumber: "9111222336" + }, + batchNumber: "343643636", // Batch NT2524 + batchExpiryDate: "2028-03-06", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3HT", // Heaton Moor Health Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Left arm", + notes: "", + editable: true + }, + { + id: "700005", + date: { day: "21", month: "11", year: "2025" }, + vaccine: "COVID-19", + vaccineProduct: "Comirnaty 3 LP.8.1", + patient: { + name: "Grace Nakamura", + nhsNumber: "9111222337" + }, + batchNumber: "343643636", // Batch NT2524 + batchExpiryDate: "2028-03-06", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3HT", // Heaton Moor Health Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Right arm", + notes: "", + editable: true + }, + { + id: "700006", + date: { day: "20", month: "11", year: "2025" }, + vaccine: "pertussis", + vaccineProduct: "Adacel vaccine suspension", + patient: { + name: "Daniel Wojcik", + nhsNumber: "9111222338" + }, + batchNumber: "46464363", // Batch M8-25-14 + batchExpiryDate: "2027-11-19", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3HT", // Heaton Moor Health Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Left arm", + notes: "", + editable: true + }, + { + id: "700007", + date: { day: "19", month: "11", year: "2025" }, + vaccine: "pertussis", + vaccineProduct: "Adacel vaccine suspension", + patient: { + name: "Freya Thomsen", + nhsNumber: "9111222339" + }, + batchNumber: "46464363", // Batch M8-25-14 + batchExpiryDate: "2027-11-19", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3HT", // Heaton Moor Health Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Right arm", + notes: "", + editable: true + }, + { + id: "700008", + date: { day: "18", month: "11", year: "2025" }, + vaccine: "flu", + vaccineProduct: "Adjuvanted Trivalent Influenza Vaccine (aTIV)", + patient: { + name: "Tomasz Nowak", + nhsNumber: "9111222340" + }, + batchNumber: "25523523", // Batch 194-151 + batchExpiryDate: "2027-12-04", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3HT", // Heaton Moor Health Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Left arm", + notes: "", + editable: true + }, + { + id: "700009", + date: { day: "17", month: "11", year: "2025" }, + vaccine: "flu", + vaccineProduct: "Adjuvanted Trivalent Influenza Vaccine (aTIV)", + patient: { + name: "Amara Okafor", + nhsNumber: "9111222341" + }, + batchNumber: "25523523", // Batch 194-151 + batchExpiryDate: "2027-12-04", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3HT", // Heaton Moor Health Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Right arm", + notes: "", + editable: true + }, + { + id: "700010", + date: { day: "16", month: "11", year: "2025" }, + vaccine: "RSV", + vaccineProduct: "Abrysvo", + patient: { + name: "Harold Fitzgerald", + nhsNumber: "9111222342" + }, + batchNumber: "46436346", // Batch ANEUEC-91 + batchExpiryDate: "2027-11-23", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3HT", // Heaton Moor Health Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Left arm", + notes: "", + editable: true + }, + { + id: "700011", + date: { day: "15", month: "11", year: "2025" }, + vaccine: "RSV", + vaccineProduct: "Abrysvo", + patient: { + name: "Beatrice Lindqvist", + nhsNumber: "9111222343" + }, + batchNumber: "46436346", // Batch ANEUEC-91 + batchExpiryDate: "2027-11-23", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW3HT", // Heaton Moor Health Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Right arm", + notes: "", + editable: true + }, + { + id: "700012", + date: { day: "14", month: "11", year: "2025" }, + vaccine: "COVID-19", + vaccineProduct: "Comirnaty 3 LP.8.1", + patient: { + name: "Ellis Marsh", + nhsNumber: "9111222344" + }, + batchNumber: "325252145", // Batch PN8471 + batchExpiryDate: "2024-02-06", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW07E", // Central Manchester Medical Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Left arm", + notes: "", + editable: true + }, + { + id: "700013", + date: { day: "13", month: "11", year: "2025" }, + vaccine: "COVID-19", + vaccineProduct: "Comirnaty 3 LP.8.1", + patient: { + name: "Nadia Hussain", + nhsNumber: "9111222345" + }, + batchNumber: "325252145", // Batch PN8471 + batchExpiryDate: "2024-02-06", + organisationId: "RW3", // Central Manchester Trust + siteId: "RW07E", // Central Manchester Medical Centre + vaccinatorId: "2387441662601", // Jane Smith + eligibility: "Based on age", + consent: "patient", + injectionSite: "Right arm", + notes: "", + editable: true } ] diff --git a/app/routes/vaccines.js b/app/routes/vaccines.js index a799cb13..88367ad0 100644 --- a/app/routes/vaccines.js +++ b/app/routes/vaccines.js @@ -309,6 +309,8 @@ module.exports = (router) => { const addedType = req.query.addedType const deactivated = req.query.deactivated === 'true' const reactivated = req.query.reactivated === 'true' + const updated = req.query.updated === 'true' + const updatedRecordsCount = parseInt(req.query.updatedRecordsCount) || 0 const updatedBatchNumber = req.query.batchNumber const vaccine = data.vaccineStock.find((vaccine) => vaccine.id === req.params.id) @@ -370,6 +372,8 @@ module.exports = (router) => { addedType, deactivated, reactivated, + updated, + updatedRecordsCount, updatedBatchNumber }) }) @@ -450,6 +454,31 @@ module.exports = (router) => { }) }) + // Checking how many records will be affected by an update to a batch + router.post('/vaccines/:vaccineId/:batchNumber/update-check', (req, res) => { + + const data = req.session.data + const vaccine = data.vaccineStock.find((vaccine) => vaccine.id === req.params.vaccineId) + if (!vaccine) { res.redirect('/vaccines'); return } + const batch = vaccine.batches.find((batch) => batch.batchNumber === req.params.batchNumber) + if (!batch) { res.redirect(`/vaccines/${vaccine.id}`); return } + + const affectedRecordsCount = (data.vaccinationsRecorded || []).filter((record) => { + return record.organisationId === vaccine.organisationId && + record.siteId === vaccine.siteId && + record.vaccine === vaccine.vaccine && + record.vaccineProduct === vaccine.vaccineProduct && + record.batchNumber === batch.id + }).length + + res.render('vaccines/update-batch-check', { + data, + vaccine, + batch, + affectedRecordsCount + }) + }) + // Updating a batch router.post('/vaccines/:vaccineId/:batchNumber/update', (req, res) => { @@ -461,10 +490,29 @@ module.exports = (router) => { const expiryDate = new Date(data.batchExpiryDate.year, (parseInt(data.batchExpiryDate.month) - 1), data.batchExpiryDate.day, 12).toISOString().substring(0,10) + let updatedRecordsCount = 0 + + if (data.updateExistingRecords === 'yes') { + for (const record of (data.vaccinationsRecorded || [])) { + if (record.organisationId === vaccine.organisationId && + record.siteId === vaccine.siteId && + record.vaccine === vaccine.vaccine && + record.vaccineProduct === vaccine.vaccineProduct && + record.batchNumber === batch.id) { + record.batchExpiryDate = expiryDate + updatedRecordsCount++ + } + } + } + + const updatedBatchNumber = data.batchNumber + batch.batchNumber = data.batchNumber; batch.expiryDate = expiryDate; - res.redirect('/vaccines/' + vaccine.id) + req.session.data.updateExistingRecords = '' + + res.redirect(`/vaccines/${vaccine.id}?updated=true&batchNumber=${encodeURIComponent(updatedBatchNumber)}&updatedRecordsCount=${updatedRecordsCount}`) }) // View page to deactivate a batch diff --git a/app/views/vaccines/edit-batch.html b/app/views/vaccines/edit-batch.html index 44f417cb..4db56248 100644 --- a/app/views/vaccines/edit-batch.html +++ b/app/views/vaccines/edit-batch.html @@ -14,9 +14,7 @@

Edit batch

-

Your changes will only apply to vaccination records saved in future.

- -
+ {{ input({ "label": { diff --git a/app/views/vaccines/product-page.html b/app/views/vaccines/product-page.html index 30e234ed..7091d327 100644 --- a/app/views/vaccines/product-page.html +++ b/app/views/vaccines/product-page.html @@ -64,6 +64,25 @@

}) }} {% endif %} + {% if updated %} + {% set html %} +

+ Batch edited +

+

+ {{ ("Batch " + updatedBatchNumber + " has been edited.") if updatedBatchNumber else "Batch has been edited." }} + {% if updatedRecordsCount > 0 %} + {{ updatedRecordsCount }} vaccination record{{ "s" if updatedRecordsCount != 1 }} {{ "was" if updatedRecordsCount == 1 else "were" }} also updated to use the new batch details. + {% endif %} +

+ {% endset %} + + {{ notificationBanner({ + html: html, + type: "success" + }) }} + {% endif %} +

{{ vaccine.vaccineProduct }}

{{ summaryList({ diff --git a/app/views/vaccines/update-batch-check.html b/app/views/vaccines/update-batch-check.html new file mode 100644 index 00000000..1709e428 --- /dev/null +++ b/app/views/vaccines/update-batch-check.html @@ -0,0 +1,146 @@ +{% extends 'layout.html' %} + +{% set pageName = "Check and confirm batch changes" %} + +{% set currentSection = "vaccines" %} + +{% block beforeContent %} + {{ backLink({ href: "/vaccines/" + vaccine.id + "/" + batch.batchNumber, text: "Back" }) }} +{% endblock %} + +{% block content %} +
+
+ +

{{ pageName }}

+ + {% set summaryRows = [] %} + {% set newExpiryDate = data.batchExpiryDate | isoDateFromDateInput %} + + {% if data.batchNumber == batch.batchNumber %} + {% set summaryRows = (summaryRows.push({ + key: { + text: "Batch number" + }, + value: { + html: batch.batchNumber + } + }), summaryRows) %} + {% else %} + {% set summaryRows = (summaryRows.push({ + key: { + text: "Previous batch number" + }, + value: { + html: batch.batchNumber + } + }), summaryRows) %} + {% set summaryRows = (summaryRows.push({ + key: { + text: "New batch number" + }, + value: { + html: data.batchNumber + } + }), summaryRows) %} + {% endif %} + + {% if newExpiryDate == batch.expiryDate %} + {% set summaryRows = (summaryRows.push({ + key: { + text: "Expiry date" + }, + value: { + html: (batch.expiryDate | govukDate) + } + }), summaryRows) %} + {% else %} + {% set summaryRows = (summaryRows.push({ + key: { + text: "Previous expiry date" + }, + value: { + html: (batch.expiryDate | govukDate) + } + }), summaryRows) %} + {% set summaryRows = (summaryRows.push({ + key: { + text: "New expiry date" + }, + value: { + html: (newExpiryDate | govukDate) + } + }), summaryRows) %} + {% endif %} + + {% set summaryRows = (summaryRows.push({ + key: { + text: "Number of records affected" + }, + value: { + html: affectedRecordsCount + } + }), summaryRows) %} + + {{ summaryList({ + classes: "nhsuk-u-margin-bottom-6", + rows: summaryRows + }) }} + + {% if affectedRecordsCount > 0 %} + + + + {{ radios({ + "idPrefix": "update-existing-records", + "name": "updateExistingRecords", + "fieldset": { + "legend": { + "text": pageName, + classes: "nhsuk-u-visually-hidden" + } + }, + "items": [ + { + "value": "yes", + "text": "Update " + affectedRecordsCount + " record" + ("s" if affectedRecordsCount != 1) + " to use " + data.batchNumber, + hint: { + text: "This will change the batch number and expiry date shown on each existing record." + } + }, + { + "value": "no", + "text": "Leave " + affectedRecordsCount + " record" + ("s" if affectedRecordsCount != 1) + " using batch " + batch.batchNumber, + hint: { + text: "The existing records will keep showing the old batch number and expiry date. You can update the records individually through the records tab." + } + } + ] + }) }} + + {{ button({ + "text": "Confirm update" + }) }} + + + {{ details({ + summaryText: "Where will these updates show?", + html: "

Updating this batch will also update the batch number and expiry date on any existing vaccination records that use it. It will update in the PDS and in the patient's GP record.

" + }) }} + + {% else %} + +

No vaccination records have been saved using batch {{ batch.batchNumber }}.

+ +
+ {{ button({ + "text": "Continue" + }) }} +
+ + {% endif %} + +
+
+ +{% endblock %}