Skip to content

Commit

Permalink
Add notifications download presenter (#1684)
Browse files Browse the repository at this point in the history
* Add notifications download presenter

https://eaflood.atlassian.net/browse/WATER-4776

As part of the work to implement notifications in the system repo we have a requirement to download the recipients data as a CSV.

This change updates the notification download service to use the fetch download service and download recipients presenter.

The download recipients presenter will map the data into a csv format. The headers are defined and set in the order expected for the csv and the rows mapped based on the recipient data.

The notion of a Registered licence and unregistered licence is used in the CSV to signify the notification method (currently email / letter).


---------

Co-authored-by: Alan Cruikshanks <[email protected]>
  • Loading branch information
jonathangoulding and Cruikshanks authored Feb 6, 2025
1 parent 21ad4e3 commit c43fd92
Show file tree
Hide file tree
Showing 5 changed files with 444 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use strict'

/**
* Formats data for the `/notifications/setup/download` link
* @module DownloadRecipientsPresenter
*/

const { contactName } = require('../../crm.presenter.js')
const { formatDateObjectToISO } = require('../../../lib/dates.lib.js')
const { transformArrayToCSVRow } = require('../../../lib/transform-to-csv.lib.js')

const HEADERS = [
'Licences',
'Return references',
'Returns period start date',
'Returns period end date',
'Returns due date',
'Message type',
'Message reference',
'Email',
'Recipient name',
'Address line 1',
'Address line 2',
'Address line 3',
'Address line 4',
'Address line 5',
'Address line 6',
'Postcode'
]

/**
* Formats data for the `/notifications/setup/download` link.
*
* This function takes an array of recipient objects and transforms it into a CSV
* string suitable for download.
*
* The headers are fixed and in the correct order. If a value for a row does not match the header then it will default
* to an empty string.
*
* @param {object[]} recipients - An array of recipients
*
* @returns {string} - A CSV-formatted string that includes the recipients' data, with the first
* row as column headers and subsequent rows corresponding to the recipient details.
*/
function go(recipients) {
const rows = _transformToCsv(recipients)

return [HEADERS + '\n', ...rows].join('')
}

function _address(contact) {
if (!contact) {
return ['', '', '', '', '', '', '']
}

return [
contact.addressLine1,
contact.addressLine2,
contact.addressLine3,
contact.addressLine4,
contact.town || contact.county,
contact.country,
contact.postcode
]
}
/**
* Transforms the recipients' data into a CSV-compatible format.
*
* The order of the object dictates the CSV header order.
*
* @private
*/
function _transformToCsv(recipients) {
return recipients.map((recipient) => {
const { contact } = recipient

const row = [
recipient.licence_ref,
recipient.return_reference,
formatDateObjectToISO(recipient.start_date),
formatDateObjectToISO(recipient.end_date),
formatDateObjectToISO(recipient.due_date),
contact ? 'letter' : 'email',
'invitations',
recipient.email || '',
contact ? contactName(recipient.contact) : '',
..._address(contact)
]

return transformArrayToCSVRow(row)
})
}

module.exports = {
go
}
16 changes: 13 additions & 3 deletions app/services/notifications/setup/download-recipients.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
* @module DownloadRecipientsService
*/

const DetermineReturnsPeriodService = require('./determine-returns-period.service.js')
const DownloadRecipientsPresenter = require('../../../presenters/notifications/setup/download-recipients.presenter.js')
const FetchDownloadRecipientsService = require('./fetch-download-recipients.service.js')
const SessionModel = require('../../../models/session.model.js')

/**
Expand All @@ -19,12 +22,19 @@ const SessionModel = require('../../../models/session.model.js')
*/
async function go(sessionId) {
const session = await SessionModel.query().findById(sessionId)
const { notificationType, referenceCode } = session
const { notificationType, referenceCode, returnsPeriod } = session

const csv = 'Licences\n12234\n'
const determinedReturnsPeriod = DetermineReturnsPeriodService.go(returnsPeriod)

const recipients = await FetchDownloadRecipientsService.go(
determinedReturnsPeriod.returnsPeriod.dueDate,
determinedReturnsPeriod.summer
)

const formattedData = DownloadRecipientsPresenter.go(recipients)

return {
data: csv,
data: formattedData,
type: 'text/csv',
filename: `${notificationType} - ${referenceCode}.csv`
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const { db } = require('../../../../db/db.js')
* different contacts types (but still preferring the registered over unregistered licence).
*
* @param {Date} dueDate
* @param {boolean} summer
* @param {string} summer
*
* @returns {Promise<object[]>} - matching recipients
*/
Expand Down
Loading

0 comments on commit c43fd92

Please sign in to comment.