Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion app/controllers/patient.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ export const patientController = {
},

readAll(request, response, next) {
const { option, programme_id, q, yearGroup } = request.query
const { invitedToClinic, option, programme_id, q, yearGroup } =
request.query
const { data } = request.session

const programmes = Programme.findAll(data)
Expand Down Expand Up @@ -120,6 +121,19 @@ export const patientController = {
)
}

// Filter by programme clinic invitations
if (programme_id && invitedToClinic === 'true') {
results = results.filter(
(patient) => patient.programmes[programme_id]?.invitedToClinic
)
} else if (invitedToClinic === 'true') {
results = results.filter((patient) =>
Object.values(patient.programmes).some(
(programme) => programme.invitedToClinic
)
)
}

// Filter by status
if (filters.report && filters.report !== 'none') {
const ids = programme_ids || programmes.map((programme) => programme.id)
Expand Down Expand Up @@ -196,6 +210,7 @@ export const patientController = {
}))

// Clean up session data
delete data.invitedToClinic
delete data.option
delete data.patientConsent
delete data.patientDeferred
Expand Down Expand Up @@ -233,6 +248,7 @@ export const patientController = {

// Checkboxes
for (const key of [
'invitedToClinic',
'option',
'patientConsent',
'patientDeferred',
Expand Down
63 changes: 54 additions & 9 deletions app/controllers/school.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export const schoolController = {
},

readAll(request, response, next) {
response.locals.schools = School.findAll(request.session.data)
// Combine children with no known school with home-schooled children)
response.locals.schools = School.findAll(request.session.data).filter(
(school) => school.id !== '888888'
)

next()
},
Expand Down Expand Up @@ -93,17 +96,13 @@ export const schoolController = {
},

readPatients(request, response, next) {
const { school_id } = request.params
const { option, programme_id, q, yearGroup } = request.query
const { invitedToClinic, option, programme_id, q, yearGroup } =
request.query
const { data } = request.session
const { school } = response.locals

const patients = Patient.findAll(data).filter(
(patient) => patient.school_id === school_id
)

// Sort
let results = _.sortBy(patients, 'lastName')
let results = _.sortBy(school.patients, 'lastName')

// Query
if (q) {
Expand Down Expand Up @@ -147,6 +146,19 @@ export const schoolController = {
)
}

// Filter by programme clinic invitations
if (programme_id && invitedToClinic === 'true') {
results = results.filter(
(patient) => patient.programmes[programme_id]?.invitedToClinic
)
} else if (invitedToClinic === 'true') {
results = results.filter((patient) =>
Object.values(patient.programmes).some(
(programme) => programme.invitedToClinic
)
)
}

// Filter by status
if (filters.report && filters.report !== 'none') {
const ids =
Expand Down Expand Up @@ -207,7 +219,7 @@ export const schoolController = {

// Results
response.locals.school = school
response.locals.patients = patients
response.locals.patients = school.patients
response.locals.results = getResults(results, request.query)
response.locals.pages = getPagination(results, request.query)

Expand All @@ -225,6 +237,7 @@ export const schoolController = {
}))

// Clean up session data
delete data.invitedToClinic
delete data.option
delete data.patientConsent
delete data.patientDeferred
Expand Down Expand Up @@ -254,6 +267,7 @@ export const schoolController = {

// Checkboxes
for (const key of [
'invitedToClinic',
'option',
'patientConsent',
'patientDeferred',
Expand Down Expand Up @@ -452,5 +466,36 @@ export const schoolController = {
request.flash('success', __(`school.delete.success`))

response.redirect(referrer)
},

inviteToClinic(request, response) {
const { school_id } = request.params
const { data } = request.session
const { __mf } = response.locals

const school = School.findOne(school_id, data)

// Find patients to invite to clinic
const patientSessionsForClinic = school.patients.map(
(patient) => patient.uuid
)

// Invite parents to book into a clinic
for (const patient of school.patients) {
const clinicProgramme_ids = request.body.clinicProgramme_ids.filter(
(item) => item !== '_unchecked'
)

Patient.update(patient.uuid, { clinicProgramme_ids }, data)
}

request.flash(
'success',
__mf(`school.inviteToClinic.success`, {
count: patientSessionsForClinic.length
})
)

response.redirect(school.uri)
}
}
19 changes: 13 additions & 6 deletions app/controllers/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -685,11 +685,11 @@ export const sessionController = {
response.redirect(session.uri)
},

close(request, response) {
inviteToClinic(request, response) {
const { account } = request.app.locals
const { session_id } = request.params
const { data } = request.session
const { __ } = response.locals
const { __mf } = response.locals

// Update session as closed
const session = Session.update(session_id, { closed: true }, data)
Expand All @@ -701,11 +701,13 @@ export const sessionController = {
programme_ids.some((id) => session.programme_ids.includes(id))
)

// Find patients to invite to clinic
const patientSessionsForClinic = session.patientSessionsForClinic.map(
(patient) => patient.uuid
)

// Move patients to clinic
if (clinic) {
const patientSessionsForClinic = session.patientSessionsForClinic.map(
(patient) => patient.uuid
)
for (const patientSession of patientSessionsForClinic) {
const patient = Patient.findOne(patientSession.patient_uuid, data)
patientSession.removeFromSession({
Expand All @@ -716,7 +718,12 @@ export const sessionController = {
}
}

request.flash('success', __(`session.close.success`, { session }))
request.flash(
'success',
__mf(`session.inviteToClinic.success`, {
count: patientSessionsForClinic.length
})
)

response.redirect(session.uri)
}
Expand Down
2 changes: 2 additions & 0 deletions app/datasets/schools.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ export default {
id: '888888',
urn: '888888',
name: 'Unknown school',
yearGroups: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
team_id: '001',
presetNames
},
'999999': {
id: '999999',
urn: '999999',
name: 'Home-schooled',
yearGroups: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
team_id: '001',
presetNames
},
Expand Down
50 changes: 31 additions & 19 deletions app/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -1083,6 +1083,9 @@ export const en = {
programmes: {
label: 'Vaccination programmes'
},
clinicProgramme_ids: {
label: 'Clinic invitations'
},
status: {
label: 'Status'
}
Expand Down Expand Up @@ -1535,6 +1538,25 @@ export const en = {
yes: 'Yes, I want to add this school',
no: 'No, I want to add a different school'
},
inviteToClinic: {
title: 'Invite parents to book a clinic appointment',
label: 'Send clinic invitations',
count:
'{count, plural, =0 {No children} one {1 child} other {# children}} are due a vaccination for at least 1 programme. They have not been invited to a clinic yet.',
description:
'You can now send clinic booking invitations to their parents.',
programme: 'Which programmes do you want to send invitations for?',
flu: '{count, plural, =0 {No children} one {1 child} other {# children}} have not had a flu vaccination',
hpv: '{count, plural, =0 {No children have} one {1 child has} other {# children have}} not had an HPV vaccination',
menacwy:
'{count, plural, =0 {No children have} one {1 child has} other {# children have}} not had an MenACWY vaccination',
mmr: '{count, plural, =0 {No children have} one {1 child has} other {# children have}} not had an MMR vaccination',
'td-ipv':
'{count, plural, =0 {No children have} one {1 child has} other {# children have}} not had a Td/IPV vaccination',
confirm: 'Send clinic invitations',
success:
'{count, plural, =0 {No children} one {1 child} other {# children}} invited to the clinic'
},
patients: {
label: 'Children',
title: 'Children'
Expand Down Expand Up @@ -1892,26 +1914,16 @@ export const en = {
lastName: 'Last name'
}
},
close: {
title: 'Close session',
inviteToClinic: {
title: 'Invite parents to book a clinic appointment',
label: 'Send clinic invitations',
count:
'{count, plural, =0 {No children} one {1 child} other {# children}} were not vaccinated at this school and have not already been invited to a clinic.',
description:
'All sessions for this school have been completed.\n\nWhen you close this session, the following children will be invited to community clinics:',
confirm: 'Close session',
success: '{{session.name}} has been closed'
},
closingSummary: {
noConsentRequest: {
count:
'{count, plural, =0 {No children} one {1 child} other {# children}} whose parents did not receive a consent request'
},
noConsentResponse: {
count:
'{count, plural, =0 {No children} one {1 child} other {# children}} whose parents did not give a consent response'
},
couldNotVaccinate: {
count:
'{count, plural, =0 {No children} one {1 child} other {# children}} who could not be vaccinated'
}
'You can send invitations to their parents to book an appointment to have their children vaccinated at a clinic.\n\nThe next clinic is on %s.',
confirm: 'Send clinic invitations',
success:
'{count, plural, =0 {No children} one {1 child} other {# children}} invited to the clinic'
}
},
texts: {
Expand Down
2 changes: 2 additions & 0 deletions app/models/patient-programme.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ import {
* @param {object} options - Options
* @param {object} [context] - Global context
* @property {object} [context] - Global context
* @property {boolean} [invitedToClinic] - Invited to clinic
* @property {string} patient_uuid - Patient UUID
* @property {string} programme_id - Programme ID
*/
export class PatientProgramme {
constructor(options, context) {
this.context = context
this.invitedToClinic = options?.invitedToClinic
this.patient_uuid = options?.patient_uuid
this.programme_id = options?.programme_id
}
Expand Down
17 changes: 15 additions & 2 deletions app/models/patient.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Parent,
PatientProgramme,
PatientSession,
Programme,
Reply,
Vaccination
} from '../models.js'
Expand Down Expand Up @@ -45,6 +46,7 @@ import {
* @property {Patient} [pendingChanges] - Pending changes to record values
* @property {import('../enums.js').ArchiveRecordReason} [archiveReason] - Archival reason
* @property {string} [archiveReasonOther] - Other archival reason
* @property {Array<string} [clinicProgramme_ids] - Clinic programme invitations
* @property {Array<import('./audit-event.js').AuditEvent>} events - Events
* @property {Array<string>} [reply_uuids] - Reply IDs
* @property {Array<string>} [patientSession_uuids] - Patient session IDs
Expand All @@ -71,6 +73,7 @@ export class Patient extends Child {
this.archiveReasonOther = options?.archiveReasonOther
this.pendingChanges = options?.pendingChanges || {}

this.clinicProgramme_ids = options?.clinicProgramme_ids || []
this.events = options?.events || []
this.reply_uuids = options?.reply_uuids || []
this.patientSession_uuids = options?.patientSession_uuids || []
Expand Down Expand Up @@ -304,13 +307,20 @@ export class Patient extends Child {
for (const programme of Object.values(programmesData).filter(
(programme) => !programme.hidden
)) {
programmes[programme.id] = new PatientProgramme(
const patientProgramme = new PatientProgramme(
{
patient_uuid: this.uuid,
programme_id: programme.id
},
this.context
)

// Patient invited to clinic if invitation needed and invitation sent
patientProgramme.invitedToClinic =
patientProgramme.inviteToSession &&
this.clinicProgramme_ids.includes(programme.id)

programmes[programme.id] = patientProgramme
}

return programmes
Expand Down Expand Up @@ -449,7 +459,10 @@ export class Patient extends Child {
archiveReason: formatOther(this.archiveReasonOther, this.archiveReason),
lastReminderDate: this.lastReminderDate
? `Last reminder sent on ${this.lastReminderDate}`
: 'No reminders sent'
: 'No reminders sent',
clinicProgramme_ids: this.clinicProgramme_ids
.map((id) => Programme.findOne(id, this.context).nameTag)
.join(' ')
}
}

Expand Down
Loading