diff --git a/app/data/appointments.js b/app/data/appointments.js new file mode 100644 index 00000000..c0181f22 --- /dev/null +++ b/app/data/appointments.js @@ -0,0 +1,240 @@ +// These are organisations set up as using RAVS +module.exports = [ + + { + id: "163473464363", + date: "today", + time: "10:00", + patient: { + nhsNumber: "9123123123", + firstName: "Alan", + lastName: "Teapot", + dateOfBirth: "1969-04-16", + contactDetails: { + mobile: "07588547704", + phone: "0111432626", + email: "alan.teapot@btinternet.com" + } + }, + vaccinations: [ + "COVID-19" + ] + }, + { + id: "923532535", + date: "today", + time: "10:30", + patient: { + nhsNumber: "9841414141", + firstName: "Keith", + lastName: "Napkin", + dateOfBirth: "1976-02-12", + contactDetails: { + mobile: "077345813941" + } + }, + vaccinations: [ + "COVID-19", + "Flu" + ] + }, + { + id: "2364364369", + date: "today", + time: "10:40", + patient: { + nhsNumber: "9841515715", + firstName: "Lynn", + lastName: "Feather", + dateOfBirth: "1963-05-23", + contactDetails: { + email: "lynn.feather@gmail.com" + } + }, + vaccinations: [ + "Flu", "RSV" + ] + }, + { + id: "3026352592", + date: "today", + time: "11:10", + cancelled: { + reason: "patient" + }, + patient: { + nhsNumber: "98357151513", + firstName: "Lorna", + lastName: "Biscuitbarrel", + dateOfBirth: "1962-08-19", + contactDetails: { + mobile: "07364824944" + } + }, + vaccinations: [ + "Flu" + ] + }, + { + id: "410059235", + date: "today", + time: "11:20", + patient: { + nhsNumber: "9847471413", + firstName: "Moira", + lastName: "Packet", + dateOfBirth: "1950-04-14", + contactDetails: { + mobile: "07623842424" + } + }, + vaccinations: [ + "COVID-19" + ] + }, + { + id: "5019581446", + date: "today", + time: "11:30", + patient: { + nhsNumber: "9841411411", + firstName: "Cliff", + lastName: "Sugarbowl", + dateOfBirth: "1957-01-23", + contactDetails: { + mobile: "07623913141" + } + }, + vaccinations: [ + "COVID-19" + ] + }, + { + id: "69263464", + date: "today", + time: "11:40", + patient: { + nhsNumber: "9841411411", + firstName: "James", + lastName: "Brown", + dateOfBirth: "1952-04-19", + contactDetails: { + mobile: "0723456123", + email: "james.brown@hotmail.com" + } + }, + vaccinations: [ + "COVID-19" + ] + }, + { + id: "7692855825", + date: "today", + time: "11:50", + patient: { + nhsNumber: "9917425141", + firstName: "Emma", + lastName: "Blue", + dateOfBirth: "1973-01-23", + contactDetails: { + mobile: "07524222525", + email: "emma.blue123@nhs.net" + } + }, + vaccinations: [ + "COVID-19", "RSV" + ] + }, + { + id: "8928558275", + date: "today", + time: "12:10", + cancelled: { + reason: "organisation" + }, + patient: { + nhsNumber: "9741851731", + firstName: "Charlie", + lastName: "Green", + dateOfBirth: "1983-06-12", + contactDetails: { + email: "charlie.green@hotmail.com" + } + }, + vaccinations: [ + "COVID-19" + ] + }, + { + id: "9255253581", + date: "today", + time: "12:40", + cancelled: { + reason: "auto" + }, + patient: { + nhsNumber: "9951736814", + firstName: "Jason", + lastName: "White", + dateOfBirth: "1998-03-19", + contactDetails: { + email: "jw225235@gmail.com" + } + }, + vaccinations: [ + "Flu" + ] + }, + { + id: "634633242", + date: "yesterday", + time: "11:20", + patient: { + nhsNumber: "9918571751", + firstName: "Danny", + lastName: "Green", + dateOfBirth: "1998-03-19", + contactDetails: { + email: "dgreen@gmail.com" + } + }, + vaccinations: [ + "Flu" + ] + }, + { + id: "10363212525", + date: "yesterday", + time: "13:20", + patient: { + nhsNumber: "99472754141", + firstName: "Jason", + lastName: "Black", + dateOfBirth: "1967-09-21", + contactDetails: { + email: "jblack@hotmail.com" + } + }, + vaccinations: [ + "Flu" + ], + vaccinationIds: ["464743636"] + }, + { + id: "64639185885", + date: "tomorrow", + time: "11:20", + patient: { + nhsNumber: "9017474141", + firstName: "Mohammed", + lastName: "Khan", + dateOfBirth: "1993-01-23", + contactDetails: { + email: "mk25325@gmail.com" + } + }, + vaccinations: [ + "Flu" + ] + } +] diff --git a/app/data/session-data-defaults.js b/app/data/session-data-defaults.js index c0027bf0..53a33eff 100644 --- a/app/data/session-data-defaults.js +++ b/app/data/session-data-defaults.js @@ -1,4 +1,5 @@ const allOrganisations = require('./all-organisations') +const appointments = require('./appointments') const featureFlags = require('./feature-flags') const organisations = require('./organisations') const users = require('./users') @@ -13,10 +14,11 @@ module.exports = { users: users, vaccines: vaccines, vaccineStock: vaccineStock, + appointments: appointments, lists: [], nhsNumberKnown: "yes", - currentUserId: "2387441662601", - currentOrganisationId: "RW3", + currentUserId: "46436346", // Jeremy Blue + currentOrganisationId: "FA424", // Pickfords Pharmacy vaccinationsRecorded: vaccinationsRecorded, // These are the options for extracting CSV reports diff --git a/app/data/users.js b/app/data/users.js index f3b4d98c..fd68212d 100644 --- a/app/data/users.js +++ b/app/data/users.js @@ -116,14 +116,14 @@ module.exports = [ "firstName": "Paulina", "lastName": "Sloan" }, - // Each pharmacy in Paulina Sloan’s chain has its own vaccinator + // Each pharmacy in Paulina Sloan’s chain has its own vaccinator, some of who are also admins { "id": "46436346", "email": "jeremy.blue@nhs.net", "organisations": [ { "id": "FA424", - "permissionLevel": "Recorder", + "permissionLevel": "Lead administrator", "status": "Active", "vaccinator": true } diff --git a/app/data/vaccine-stock.js b/app/data/vaccine-stock.js index 32927538..f703deed 100644 --- a/app/data/vaccine-stock.js +++ b/app/data/vaccine-stock.js @@ -409,6 +409,34 @@ module.exports = [ } ] }, + { + id: "7436323", + vaccine: "Flu", + vaccineProduct: "Adjuvanted Trivalent Influenza Vaccine (aTIV)", + organisationId: "FA424", // Pickfords Pharmacy + siteId: "FA424X", // Pickfords Pharmacy + batches: [ + { + id: "464735235325", + batchNumber: "714-14", + expiryDate: "2026-12-14" + } + ] + }, + { + id: "9235235325", + vaccine: "COVID-19", + vaccineProduct: "Comirnaty 3 LP.8.1", + organisationId: "FA424", // Pickfords Pharmacy + siteId: "FA424X", // Pickfords Pharmacy + batches: [ + { + id: "82725252", + batchNumber: "AB-255", + expiryDate: "2027-01-22" + } + ] + }, { id: "2514771", vaccine: "flu (London service)", diff --git a/app/filters.js b/app/filters.js index ce8b19fc..dd43b8b3 100644 --- a/app/filters.js +++ b/app/filters.js @@ -18,9 +18,10 @@ module.exports = function () { filters.findById = findById - filters.dayName = function(isoDate) { + filters.dayName = function(isoDate, style = 'short') { const date = new Date(Date.parse(isoDate)) - const dateFormatter = new Intl.DateTimeFormat('en-GB', {weekday: 'short'}); + const weekdayStyle = (style === 'long') ? 'long' : 'short' + const dateFormatter = new Intl.DateTimeFormat('en-GB', {weekday: weekdayStyle}); return dateFormatter.format(date) } diff --git a/app/routes.js b/app/routes.js index db5607e4..dd32140b 100644 --- a/app/routes.js +++ b/app/routes.js @@ -43,6 +43,7 @@ router.use('/regions{*splat}', authorise({userType: 'regional'})) router.use('/support{*splat}', authorise({userType: 'admin'})) require('./routes/apply')(router) +require('./routes/appointments')(router) require('./routes/record-vaccinations')(router) require('./routes/regions')(router) require('./routes/user-admin')(router) diff --git a/app/routes/appointments.js b/app/routes/appointments.js new file mode 100644 index 00000000..d7b9d129 --- /dev/null +++ b/app/routes/appointments.js @@ -0,0 +1,68 @@ +module.exports = (router) => { + + router.get('/appointments', (req, res) => { + const data = req.session.data + + const day = 86400000 // number of milliseconds in a day + const today = (new Date()).toISOString().substring(0,10) + const yesterday = (new Date(Date.now() - day)).toISOString().substring(0,10) + const tomorrow = (new Date(Date.now() + day)).toISOString().substring(0,10) + const requestedDay = req.query.date + const allowedDays = [yesterday, today, tomorrow] + + if (requestedDay && !allowedDays.includes(requestedDay)) { + return res.redirect('/appointments') + } + + const currentDay = requestedDay || today + const currentDate = new Date(currentDay) + const previousDay = (new Date(currentDate.getTime() - day)).toISOString().substring(0,10) + const nextDay = (new Date(currentDate.getTime() + day)).toISOString().substring(0,10) + const isYesterday = currentDay === yesterday + const isTomorrow = currentDay === tomorrow + + let appointments = data.appointments + + if (currentDay === today) { + appointments = appointments.filter((appointment) => appointment.date === "today" || appointment.date === today) + } else if (nextDay === today) { + appointments = appointments.filter((appointment) => appointment.date === "yesterday" || appointment.date === today) + } else if (previousDay === today) { + appointments = appointments.filter((appointment) => appointment.date === "tomorrow" || appointment.date === today) + } else { + appointments = appointments.filter((appointment) => appointment.date === today) + } + + const scheduledAppointments = appointments.filter((appointment) => !appointment.cancelled && (appointment.vaccinationIds || []).length === 0) + + const cancelledAppointments = appointments.filter((appointment) => appointment.cancelled) + + const completedAppointments = appointments.filter((appointment) => (appointment.vaccinationIds || []).length > 0) + + let vaccinators = [] + + if (data.vaccinatorIds) { + vaccinators = data.users.filter((user) => data.vaccinatorIds.includes(user.id)) + } + + + res.render('appointments/index', { + scheduledAppointments, + cancelledAppointments, + completedAppointments, + today, + currentDay, + previousDay, + nextDay, + isYesterday, + isTomorrow, + vaccinators + }) + }) + + + router.get('/appointments/vaccinators', (req, res) => { + res.redirect('/appointments') + }) +} + diff --git a/app/routes/record-vaccinations.js b/app/routes/record-vaccinations.js index 5de6bd4c..b253cb03 100644 --- a/app/routes/record-vaccinations.js +++ b/app/routes/record-vaccinations.js @@ -53,12 +53,33 @@ module.exports = router => { }) }) + router.get('/record-vaccinations/vaccination-date', (req, res) => { + + const data = req.session.data + const appointmentId = data.appointmentId + + if (appointmentId) { + const appointment = data.appointments.find((appointment) => appointment.id === appointmentId) + + if (appointment.date === "today") { + // Set vaccination date to today and skip question + req.session.data.vaccinationToday = "yes" + return res.redirect('/record-vaccinations/delivery-team') + + } + } + + res.render('record-vaccinations/vaccination-date') + }) + router.post('/record-vaccinations/answer-date', (req, res) => { const data = req.session.data if (!data.vaccinationToday) { return res.redirect('/record-vaccinations/?showErrors=yes') } + + res.redirect('/record-vaccinations/delivery-team') }) @@ -72,6 +93,12 @@ module.exports = router => { const sitesInUse = currentOrganisation.sites.filter((site) => siteIdsWithVaccines.includes(site.id)) + // If there’s only 1 site set up (eg a pharmacy), then + // set that and skip this question. + if (sitesInUse.length === 1) { + data.siteId = sitesInUse[0].id + return res.redirect('/record-vaccinations/vaccinator') + } if (req.query.showErrors === "yes") { if (!req.session.data.siteId) { @@ -127,6 +154,14 @@ module.exports = router => { } } + // If we’re recording a vaccination from today’s appointments, and there’s + // only 1 vaccinator set as present, then set them as the vaccinator + // and skip the question. + if (data.appointmentId && Array.isArray(data.vaccinatorIds) && data.vaccinatorIds.length == 1) { + req.session.data.vaccinatorId = data.vaccinatorIds[0] + return res.redirect('/record-vaccinations/vaccine') + } + res.render('record-vaccinations/vaccinator', { vaccinatorError, otherVaccinators @@ -598,6 +633,7 @@ module.exports = router => { const yearToday = (dateToday.getFullYear()) if (data.vaccinationToday === 'yes') { + data.vaccinationDate = {} data.vaccinationDate.day = String(dayToday) data.vaccinationDate.month = String(monthToday) data.vaccinationDate.year = String(yearToday) @@ -627,6 +663,16 @@ module.exports = router => { data.lastAddedVaccinationId = generatedId + // Add the vaccination ID to the appointment so that + // we can filter the appointments list by which ones have + // been given + if (data.appointmentId) { + const appointment = data.appointments.find((appointment) => appointment.id == data.appointmentId) + + appointment.vaccinationIds ||= [] + appointment.vaccinationIds.push(generatedId) + } + res.redirect('/record-vaccinations/done') }) @@ -716,6 +762,7 @@ module.exports = router => { } if (answer === 'same-vaccination-another-patient') { + data.appointmentId = "" req.session.data.firstName = "" req.session.data.lastName = "" @@ -741,6 +788,7 @@ module.exports = router => { res.redirect('/record-vaccinations/patient-history?repeatPatient=yes&repeatVaccination=no') } else if (answer === 'different-vaccination-another-patient') { + data.appointmentId = "" req.session.data.vaccine = "" req.session.data.vaccineProduct = "" @@ -751,6 +799,22 @@ module.exports = router => { req.session.data.vaccineDose = "" res.redirect('/record-vaccinations/?repeatPatient=no&repeatVaccination=no') + + } else if (answer === 'appointments') { + data.appointmentId = "" + + req.session.data.vaccine = "" + req.session.data.vaccineProduct = "" + req.session.data.vaccineBatch = "" + req.session.data.eligibility = "" + req.session.data.nhsNumber = "" + req.session.data.healthcareWorker = "" + req.session.data.vaccineDose = "" + req.session.data.vaccinationToday = "" + req.session.data.vaccinatorId = "" + + res.redirect('/appointments') + } else { res.redirect('/record-vaccinations/done?showErrors=yes') } diff --git a/app/views/appointments/_cancelled.html b/app/views/appointments/_cancelled.html new file mode 100644 index 00000000..65abf7a7 --- /dev/null +++ b/app/views/appointments/_cancelled.html @@ -0,0 +1,53 @@ +
| Time | +Name and NHS number | +Date of birth | +Vaccines | + +Contact details | +Cancellation reason | + + + +
|---|---|---|---|---|---|
| {{ appointment.time }}am | +
+ {{ appointment.patient.firstName }}
+ {{ appointment.patient.lastName }}
+ {{ appointment.patient.nhsNumber }}
+ |
+ + {{ appointment.patient.dateOfBirth | govukDate }} + | ++ {{ appointment.vaccinations | join(", ") }} + | + +
+ {% if appointment.patient.contactDetails.mobile %}
+ {{ appointment.patient.contactDetails.mobile }} + {% endif %} + {% if appointment.patient.contactDetails.email %} + {{ appointment.patient.contactDetails.email }} + {% endif %} + |
+ + {% if appointment.cancelled.reason == "patient" %} + Patient + {% elif appointment.cancelled.reason == "organisation" %} + Us + {% elif appointment.cancelled.reason == "auto" %} + Automatic + {% endif %} + | +
| Time | +Name and NHS number | +Date of birth | +Vaccines booked | +Contact details | + + {% if currentDay == today %} +Action | + {% endif %} + +
|---|---|---|---|---|---|
| {{ appointment.time }}am | +
+ {{ appointment.patient.firstName }}
+ {{ appointment.patient.lastName }}
+ {{ appointment.patient.nhsNumber }}
+ |
+
+ {{ appointment.patient.dateOfBirth | govukDate }}
+ {{ appointment.patient.dateOfBirth | age }} old
+ |
+
+ {{ appointment.vaccinations | join(" ") | safe }} + |
+
+ {% if appointment.patient.contactDetails.mobile %}
+ {{ appointment.patient.contactDetails.mobile }} + {% endif %} + {% if appointment.patient.contactDetails.email %} + {{ appointment.patient.contactDetails.email }} + {% endif %} + |
+ {% if currentDay == today %}
+ + Record + | + {% endif %} +
| Time | +Name and NHS number | +Date of birth | +Vaccines booked | +Contact details | + +
|---|---|---|---|---|
| {{ appointment.time }}am | +
+ {{ appointment.patient.firstName }}
+ {{ appointment.patient.lastName }}
+ {{ appointment.patient.nhsNumber }}
+ |
+ + {{ appointment.patient.dateOfBirth | govukDate }} + | +
+ {{ appointment.vaccinations | join(" ") | safe }} + |
+
+ {% if appointment.patient.contactDetails.mobile %}
+ {{ appointment.patient.contactDetails.mobile }} + {% endif %} + {% if appointment.patient.contactDetails.email %} + {{ appointment.patient.contactDetails.email }} + {% endif %} + |
+
Imported from Manage your appointments
+ +