Skip to content

Commit

Permalink
Select additional submission options page (#988)
Browse files Browse the repository at this point in the history
Select additional submission options page

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

Additional options for submission page.

Currently the options are "multiple upload", or "none", there is scope to add more later.

Appropriate notifications will be shown on the check page to the user based on selection.
  • Loading branch information
Demwunz authored May 17, 2024
1 parent a660acd commit e69fcee
Show file tree
Hide file tree
Showing 16 changed files with 725 additions and 1 deletion.
26 changes: 26 additions & 0 deletions app/controllers/return-requirements.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

const AbstractionPeriodService = require('../services/return-requirements/abstraction-period.service.js')
const AdditionalSubmissionOptionsService = require('../services/return-requirements/additional-submission-options.service.js')
const AddService = require('../services/return-requirements/add.service.js')
const AgreementsExceptionsService = require('../services/return-requirements/agreements-exceptions.service.js')
const CancelService = require('../services/return-requirements/cancel.service.js')
Expand All @@ -25,6 +26,7 @@ const SetupService = require('../services/return-requirements/setup.service.js')
const SiteDescriptionService = require('../services/return-requirements/site-description.service.js')
const StartDateService = require('../services/return-requirements/start-date.service.js')
const SubmitAbstractionPeriod = require('../services/return-requirements/submit-abstraction-period.service.js')
const SubmitAdditionalSubmissionOptionsService = require('../services/return-requirements/submit-additional-submission-options.service.js')
const SubmitAgreementsExceptions = require('../services/return-requirements/submit-agreements-exceptions.service.js')
const SubmitCancel = require('../services/return-requirements/submit-cancel.service.js')
const SubmitCheckService = require('../services/return-requirements/submit-check.service.js')
Expand Down Expand Up @@ -59,6 +61,16 @@ async function add (request, h) {
return h.redirect(`/system/return-requirements/${sessionId}/purpose/${requirementIndex}`)
}

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

const pageData = await AdditionalSubmissionOptionsService.go(sessionId)

return h.view('return-requirements/additional-submission-options.njk', {
...pageData
})
}

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

Expand Down Expand Up @@ -265,6 +277,18 @@ async function submitAgreementsExceptions (request, h) {
return h.redirect(`/system/return-requirements/${sessionId}/check`)
}

async function submitAdditionalSubmissionOptions (request, h) {
const { params: { sessionId }, payload, yar } = request

const pageData = await SubmitAdditionalSubmissionOptionsService.go(sessionId, payload, yar)

if (pageData.error) {
return h.view('return-requirements/additional-submission-options.njk', pageData)
}

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

async function submitCancel (request, h) {
const { sessionId } = request.params
const { licenceId } = request.payload
Expand Down Expand Up @@ -468,6 +492,7 @@ async function submitStartDate (request, h) {
module.exports = {
abstractionPeriod,
add,
additionalSubmissionOptions,
agreementsExceptions,
approved,
cancel,
Expand All @@ -487,6 +512,7 @@ module.exports = {
siteDescription,
startDate,
submitAbstractionPeriod,
submitAdditionalSubmissionOptions,
submitAgreementsExceptions,
submitCancel,
submitCheck,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict'

/**
* Formats data for the `/return-requirements/{sessionId}/additional-submission-options` page
* @module AdditionalSubmissionOptionsPresenter
*/

/**
* Formats data for the `/return-requirements/{sessionId}/additional-submission-options` page
*
* @param {module:SessionModel} session - The returns requirements session instance
*
* @returns {Object} - The data formatted for the view template
*/
function go (session) {
const { id: sessionId, licence: { id: licenceId, licenceRef }, additionalSubmissionOptions } = session
const data = {
additionalSubmissionOptions: additionalSubmissionOptions ?? [],
backLink: `/system/return-requirements/${sessionId}/check`,
licenceId,
licenceRef,
sessionId
}

return data
}

module.exports = {
go
}
3 changes: 2 additions & 1 deletion app/presenters/return-requirements/check.presenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ const { formatLongDate } = require('../base.presenter.js')
const { returnRequirementReasons } = require('../../lib/static-lookups.lib.js')

function go (session) {
const { id: sessionId, journey, licence, note, reason } = session
const { additionalSubmissionOptions, id: sessionId, journey, licence, note, reason } = session

return {
additionalSubmissionOptions: additionalSubmissionOptions ?? [],
journey,
licenceRef: licence.licenceRef,
note: note ? note.content : null,
Expand Down
26 changes: 26 additions & 0 deletions app/routes/return-requirement.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,32 @@ const routes = [
}

},
{
method: 'GET',
path: '/return-requirements/{sessionId}/additional-submission-options',
handler: ReturnRequirementsController.additionalSubmissionOptions,
options: {
auth: {
access: {
scope: ['billing']
}
},
description: 'Select additional submission options for the return requirement'
}
},
{
method: 'POST',
path: '/return-requirements/{sessionId}/additional-submission-options',
handler: ReturnRequirementsController.submitAdditionalSubmissionOptions,
options: {
auth: {
access: {
scope: ['billing']
}
},
description: 'Submit additional submission options for the return requirement'
}
},
{
method: 'GET',
path: '/return-requirements/{sessionId}/agreements-exceptions/{requirementIndex}',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict'

/**
* Orchestrates fetching and presenting the data for
* `/return-requirements/{sessionId}/additional-submission-options` page
* @module AdditionalSubmissionOptionsService
*/

const AdditionalSubmissionOptionsPresenter = require('../../presenters/return-requirements/additional-submission-options.presenter.js')
const SessionModel = require('../../models/session.model.js')

/**
* Orchestrates fetching and presenting the data for
* `/return-requirements/{sessionId}/additional-submission-options` page
*
* Supports generating the data needed for the points page in the return requirements setup journey. It fetches the
* current session record and combines it with the checkboxes and other information needed for the form.
*
* @param {string} sessionId - The UUID of the current session
*
* @returns {Promise<Object>} The view data for the points page
*/
async function go (sessionId) {
const session = await SessionModel.query().findById(sessionId)

const formattedData = AdditionalSubmissionOptionsPresenter.go(session)

return {
activeNavBar: 'search',
pageTitle: 'Select any additional submission options for the return requirements',
...formattedData
}
}

module.exports = {
go
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
'use strict'

/**
* Orchestrates validating the data for `/return-requirements/{sessionId}/additional-submission-options` page
* @module AdditionalSubmissionOptionsService
*/

const AdditionalSubmissionOptionsPresenter = require('../../presenters/return-requirements/additional-submission-options.presenter.js')
const AdditionalSubmissionOptionsValidator = require('../../validators/return-requirements/additional-submission-options.validator.js')
const SessionModel = require('../../models/session.model.js')

/**
* Orchestrates validating the data for `/return-requirements/{sessionId}/additional-submission-options` page
*
* It first retrieves the session instance for the returns requirements 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} 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, yar) {
const session = await SessionModel.query().findById(sessionId)

_handleOneOptionSelected(payload)

const validationResult = _validate(payload)

if (!validationResult) {
const notification = _notification(session, payload)
await _save(session, payload)

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

return {}
}

const submittedSessionData = _submittedSessionData(session, payload)

return {
activeNavBar: 'search',
error: validationResult,
pageTitle: 'Select any additional submission options for the return requirements',
...submittedSessionData
}
}

/**
* When a single additional submission option is checked by the user, it returns as a string. When multiple options are
* checked, the 'additionalSubmissionOptions' is returned as an array.
* This function works to make those single selected string 'additionalSubmissionOptions' into an array for uniformity.
*/
function _handleOneOptionSelected (payload) {
if (!Array.isArray(payload.additionalSubmissionOptions)) {
payload.additionalSubmissionOptions = [payload.additionalSubmissionOptions]
}
}

function _notification (session, payload) {
const { additionalSubmissionOptions } = session ?? {}

if (additionalSubmissionOptions !== payload.additionalSubmissionOptions) {
return {
text: 'Changes updated',
title: 'Updated'
}
}

return null
}

async function _save (session, payload) {
session.additionalSubmissionOptions = payload.additionalSubmissionOptions

return session.$update()
}

function _submittedSessionData (session, payload) {
session.additionalSubmissionOptions = payload.additionalSubmissionOptions ?? []

return AdditionalSubmissionOptionsPresenter.go(session)
}

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

if (!validation.error) {
return null
}

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

return {
text: message
}
}

module.exports = {
go
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict'

/**
* Validates data submitted for the `/return-requirements/{sessionId}/additional-submission-options` page
* @module AdditionalSubmissionOptionsValidator
*/

const Joi = require('joi')

/**
* Validates data submitted for the `/return-requirements/{sessionId}/additional-submission-options` page
*
* When setting up a requirement users must specify additional-submission-options for the return requirement.
* Users must select one or more points linked to the licence.
* If these requirements are not met the validation will return an error.
*
* @param {Object} options - The options extracted from payload taken from the request to be validated
*
* @returns {Object} The result from calling Joi's schema.validate(). If any errors are found the `error:` property will
* also exist detailing what the issue is.
*/
function go (payload) {
const additionalSubmissionOptions = payload.additionalSubmissionOptions

const errorMessage = 'Select additional submission options for the requirements for returns'

const schema = Joi.object({
additionalSubmissionOptions: Joi.array()
.items(Joi.string())
.required()
}).messages({
'any.required': errorMessage,
'array.sparse': errorMessage
})

return schema.validate({ additionalSubmissionOptions }, { abortEarly: false })
}

module.exports = {
go
}
Loading

0 comments on commit e69fcee

Please sign in to comment.