Skip to content

Commit

Permalink
Add a note to return submissions (#1662)
Browse files Browse the repository at this point in the history
https://eaflood.atlassian.net/browse/WATER-4807

Create functionality to allow the user to add/edit/remove a note from a return submission.

The link to allow the user to add/edit/remove a note will be on the "Check details and enter new volumes or readings" page.

The migrations for the `notes` and `created_by` columns can be found in these PRs:

- DEFRA/water-abstraction-returns#406
- #1661
  • Loading branch information
Jozzey authored Jan 29, 2025
1 parent a1dd0fa commit fe52ea6
Show file tree
Hide file tree
Showing 18 changed files with 993 additions and 217 deletions.
37 changes: 36 additions & 1 deletion app/controllers/return-logs-setup.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
*/

const CheckService = require('../services/return-logs/setup/check.service.js')
const DeleteNoteService = require('../services/return-logs/setup/delete-note.service.js')
const InitiateSessionService = require('../services/return-logs/setup/initiate-session.service.js')
const MeterDetailsService = require('../services/return-logs/setup/meter-details.service.js')
const MeterProvidedService = require('../services/return-logs/setup/meter-provided.service.js')
const NoteService = require('../services/return-logs/setup/note.service.js')
const ReceivedService = require('../services/return-logs/setup/received.service.js')
const ReportedService = require('../services/return-logs/setup/reported.service.js')
const SingleVolumeService = require('../services/return-logs/setup/single-volume.service.js')
const SubmissionService = require('../services/return-logs/setup/submission.service.js')
const SubmitMeterDetailsService = require('../services/return-logs/setup/submit-meter-details.service.js')
const SubmitMeterProvidedService = require('../services/return-logs/setup/submit-meter-provided.service.js')
const SubmitNoteService = require('../services/return-logs/setup/submit-note.service.js')
const SubmitReceivedService = require('../services/return-logs/setup/submit-received.service.js')
const SubmitReportedService = require('../services/return-logs/setup/submit-reported.service.js')
const SubmitSingleVolumeService = require('../services/return-logs/setup/submit-single-volume.service.js')
Expand All @@ -24,11 +27,19 @@ const UnitsService = require('../services/return-logs/setup/units.service.js')

async function check(request, h) {
const { sessionId } = request.params
const pageData = await CheckService.go(sessionId)
const pageData = await CheckService.go(sessionId, request.yar)

return h.view('return-logs/setup/check.njk', pageData)
}

async function deleteNote(request, h) {
const { sessionId } = request.params

await DeleteNoteService.go(sessionId, request.yar)

return h.redirect(`/system/return-logs/setup/${sessionId}/check`)
}

async function guidance(_request, h) {
return h.view('return-logs/setup/guidance.njk')
}
Expand All @@ -47,6 +58,14 @@ async function meterProvided(request, h) {
return h.view('return-logs/setup/meter-provided.njk', pageData)
}

async function note(request, h) {
const { sessionId } = request.params

const pageData = await NoteService.go(sessionId)

return h.view('return-logs/setup/note.njk', pageData)
}

async function received(request, h) {
const { sessionId } = request.params
const pageData = await ReceivedService.go(sessionId)
Expand Down Expand Up @@ -116,6 +135,19 @@ async function submitMeterProvided(request, h) {
return h.redirect(`/system/return-logs/setup/${sessionId}/meter-details`)
}

async function submitNote(request, h) {
const { sessionId } = request.params
const { user } = request.auth.credentials

const pageData = await SubmitNoteService.go(sessionId, request.payload, user, request.yar)

if (pageData.error) {
return h.view('return-logs/setup/note.njk', pageData)
}

return h.redirect(`/system/return-logs/setup/${sessionId}/check`)
}

async function submitReceived(request, h) {
const {
params: { sessionId },
Expand Down Expand Up @@ -201,16 +233,19 @@ async function units(request, h) {

module.exports = {
check,
deleteNote,
guidance,
meterDetails,
meterProvided,
note,
received,
reported,
setup,
singleVolume,
submission,
submitMeterDetails,
submitMeterProvided,
submitNote,
submitReceived,
submitReported,
submitSingleVolume,
Expand Down
29 changes: 29 additions & 0 deletions app/presenters/return-logs/setup/note.presenter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict'

/**
* Formats data for the `/return-logs/setup/{sessionId}/note` page
* @module NotePresenter
*/

/**
* Formats data for the `/return-logs/setup/{sessionId}/note` page
*
* @param {module:SessionModel} session - The returns log session instance
*
* @returns {object} The data formatted for the view template
*/
function go(session) {
const { id: sessionId, note, returnReference } = session

return {
backLink: `/system/return-logs/setup/${sessionId}/check`,
note: note ? note.content : null,
pageTitle: 'Add a note',
returnReference,
sessionId
}
}

module.exports = {
go
}
36 changes: 36 additions & 0 deletions app/routes/return-logs-setup.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,42 @@ const routes = [
}
}
},
{
method: 'GET',
path: '/return-logs/setup/{sessionId}/delete-note',
options: {
handler: ReturnLogsSetupController.deleteNote,
auth: {
access: {
scope: ['billing']
}
}
}
},
{
method: 'GET',
path: '/return-logs/setup/{sessionId}/note',
options: {
handler: ReturnLogsSetupController.note,
auth: {
access: {
scope: ['billing']
}
}
}
},
{
method: 'POST',
path: '/return-logs/setup/{sessionId}/note',
options: {
handler: ReturnLogsSetupController.submitNote,
auth: {
access: {
scope: ['billing']
}
}
}
},
{
method: 'GET',
path: '/return-logs/setup/{sessionId}/received',
Expand Down
16 changes: 14 additions & 2 deletions app/services/return-logs/setup/check.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,32 @@ const CheckPresenter = require('../../../presenters/return-logs/setup/check.pres
* Orchestrates fetching and presenting the data needed for the `/return-logs/setup/{sessionId}/check` page
*
* @param {string} sessionId - The UUID of the current session
* @param {object} yar - The Hapi `request.yar` session manager passed on by the controller
*
* @returns {Promise<object>} page data needed by the view template
*/
async function go(sessionId) {
async function go(sessionId, yar) {
const session = await SessionModel.query().findById(sessionId)

await _markCheckPageVisited(session)

const formattedData = CheckPresenter.go(session)

const notification = yar.flash('notification')[0]

return {
activeNavBar: 'search',
...formattedData
...formattedData,
notification
}
}

async function _markCheckPageVisited(session) {
session.checkPageVisited = true

return session.$update()
}

module.exports = {
go
}
39 changes: 39 additions & 0 deletions app/services/return-logs/setup/delete-note.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict'

/**
* Deletes the note from the return log currently being setup
* @module DeleteNoteService
*/

const SessionModel = require('../../../models/session.model.js')

/**
* Deletes the note from the return log currently being setup
*
* It first retrieves the session instance for the return log journey in progress. Then it removes the notes
* data from the session.
*
* @param {string} sessionId - The id of the current session
* @param {object} yar - The Hapi `request.yar` session manager passed on by the controller
*/
async function go(sessionId, yar) {
const session = await SessionModel.query().findById(sessionId)
const notification = {
title: 'Removed',
text: 'Note removed'
}

yar.flash('notification', notification)

await _save(session)
}

async function _save(session) {
delete session.note

return session.$update()
}

module.exports = {
go
}
34 changes: 34 additions & 0 deletions app/services/return-logs/setup/note.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict'

/**
* Orchestrates fetching and presenting the data for `/return-logs/setup/{sessionId}/note` page
* @module NoteService
*/

const NotePresenter = require('../../../presenters/return-logs/setup/note.presenter.js')
const SessionModel = require('../../../models/session.model.js')

/**
* Orchestrates fetching and presenting the data for `/return-logs/setup/{sessionId}/note` page
*
* Supports generating the data needed for the note page in the return log setup journey. It fetches the
* current session record and combines it with textarea information needed for the form.
*
* @param {string} sessionId - The UUID for return log setup session record
*
* @returns {Promise<object>} The view data for the note page
*/
async function go(sessionId) {
const session = await SessionModel.query().findById(sessionId)

const formattedData = NotePresenter.go(session)

return {
activeNavBar: 'search',
...formattedData
}
}

module.exports = {
go
}
107 changes: 107 additions & 0 deletions app/services/return-logs/setup/submit-note.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
'use strict'

/**
* Orchestrates validating the data for `/return-logs/setup/{sessionId}/note` page
* @module SubmitNoteService
*/

const NotePresenter = require('../../../presenters/return-logs/setup/note.presenter.js')
const NoteValidator = require('../../../validators/return-logs/setup/note.validator.js')
const SessionModel = require('../../../models/session.model.js')

/**
* Orchestrates validating the data for `/return-logs/setup/{sessionId}/note` page
*
* It first retrieves the session instance for the return log journey in progress.
*
* The validation result is then combined with the output of the presenter to generate the page data needed by the view.
* If there was a validation error the controller will re-render the page so needs this information. If all is well the
* controller will redirect to the next page in the journey.
*
* @param {string} sessionId - The id of the current session
* @param {object} payload - The submitted form data
* @param {object} user - The logged in user details
* @param {object} yar - The Hapi `request.yar` session manager passed on by the controller
*
* @returns {Promise<object>} If no errors it returns an empty object else the page data for the note page including the
* validation error details
*/
async function go(sessionId, payload, user, yar) {
const session = await SessionModel.query().findById(sessionId)
const validationResult = _validate(payload)

if (!validationResult) {
const notification = _notification(session, payload.note)

await _save(session, payload, user)

if (notification) {
yar.flash('notification', notification)
}

return {}
}

const submittedSessionData = _submittedSessionData(session, payload)

return {
activeNavBar: 'search',
error: validationResult,
...submittedSessionData
}
}

function _notification(session, newNote) {
const {
data: { note }
} = session

if (!note && newNote) {
return {
text: 'Note added',
title: 'Added'
}
}

if (note?.content !== newNote) {
return {
text: 'Note updated',
title: 'Updated'
}
}

return null
}

async function _save(session, payload, user) {
session.note = {
content: payload.note,
userEmail: user.username
}

return session.$update()
}

function _submittedSessionData(session, payload) {
session.note = payload.note ? payload.note : null

return NotePresenter.go(session)
}

function _validate(payload) {
const validation = NoteValidator.go(payload)

if (!validation.error) {
return null
}

const { message } = validation.error.details[0]

return {
text: message
}
}

module.exports = {
go
}
Loading

0 comments on commit fe52ea6

Please sign in to comment.