-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add bill runs setup region page to journey (#804)
https://eaflood.atlassian.net/browse/WATER-4375 > Part of a series of changes related to replacing the create bill run journey to incorporate changes for two-part tariff This adds the second page to the setup bill run journey; select a region. This has a bit more complexity than [Add bill runs setup type page to journey](#802) because depending on the bill run type selected, we are either done or need to go to another page in the journey.
- Loading branch information
1 parent
5dde8aa
commit f84d03c
Showing
16 changed files
with
718 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
'use strict' | ||
|
||
/** | ||
* Formats data for the `/bill-runs/setup/{sessionId}/region` page | ||
* @module RegionPresenter | ||
*/ | ||
|
||
/** | ||
* Formats data for the `/bill-runs/setup/{sessionId}/region` page | ||
* | ||
* @param {module:SessionModel} session - The session instance to format | ||
* @param {module:RegionsModel[]} regions - UUID and display name of all regions | ||
* | ||
* @returns {Object} - The data formatted for the view template | ||
*/ | ||
function go (session, regions) { | ||
return { | ||
sessionId: session.id, | ||
regions, | ||
selectedRegion: session.data.region ? session.data.region : null | ||
} | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
'use strict' | ||
|
||
/** | ||
* Fetches just the ID and display name for all regions | ||
* @module FetchRegionsService | ||
*/ | ||
|
||
const RegionModel = require('../../../models/region.model.js') | ||
|
||
/** | ||
* Fetches just the ID and display name for all regions | ||
* | ||
* @returns {Promise<Object[]>} The display name and ID for all regions in the service ordered by display name | ||
*/ | ||
async function go () { | ||
return RegionModel.query() | ||
.select([ | ||
'id', | ||
'displayName' | ||
]) | ||
.orderBy([ | ||
{ column: 'displayName', order: 'asc' } | ||
]) | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
'use strict' | ||
|
||
/** | ||
* Orchestrates fetching and presenting the data for `/bill-runs/setup/{sessionId}/region` page | ||
* @module RegionService | ||
*/ | ||
|
||
const FetchRegionsService = require('./fetch-regions.service.js') | ||
const RegionPresenter = require('../../../presenters/bill-runs/setup/region.presenter.js') | ||
const SessionModel = require('../../../models/session.model.js') | ||
|
||
/** | ||
* Orchestrates fetching and presenting the data for `/bill-runs/setup/{sessionId}/region` page | ||
* | ||
* Supports generating the data needed for the region page in the setup bill run journey. It fetches the current | ||
* session record and combines it with the radio buttons and other information needed for the form. | ||
* | ||
* @param {string} sessionId - The UUID for setup bill run session record | ||
* | ||
* @returns {Promise<Object>} The view data for the region page | ||
*/ | ||
async function go (sessionId) { | ||
const session = await SessionModel.query().findById(sessionId) | ||
const regions = await FetchRegionsService.go() | ||
|
||
const formattedData = RegionPresenter.go(session, regions) | ||
|
||
return { | ||
...formattedData | ||
} | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
'use strict' | ||
|
||
/** | ||
* Orchestrates validating the data for `/bill-runs/setup/{sessionId}/region` page | ||
* @module SubmitRegionService | ||
*/ | ||
|
||
const FetchRegionsService = require('./fetch-regions.service.js') | ||
const RegionPresenter = require('../../../presenters/bill-runs/setup/region.presenter.js') | ||
const RegionValidator = require('../../../validators/bill-runs/setup/region.validator.js') | ||
const SessionModel = require('../../../models/session.model.js') | ||
|
||
/** | ||
* Orchestrates validating the data for `/bill-runs/setup/{sessionId}/region` page | ||
* | ||
* It first retrieves the session instance for the setup bill run journey in progress. It then validates the payload of | ||
* the submitted request. | ||
* | ||
* If there is no validation error it will save the selected value to the session then return an object with a | ||
* `setupComplete:` property. If the bill run type was not two-part tariff this will be true. Else it will be false. | ||
* The fact the property exists will tell the controller the submission was successful. Whether the property | ||
* `setupComplete:` is true or false will be used to determine which page to direct the user to next. | ||
* | ||
* If there is a validation error it is combined with the output of the presenter to generate the page data needed to | ||
* re-render the view with an error message. | ||
* | ||
* @param {string} sessionId - The UUID of the current session | ||
* @param {Object} payload - The submitted form data | ||
* | ||
* @returns {Promise<Object>} An object with a `setupComplete:` property if there are no errors else the page data for | ||
* the region page including the validation error details | ||
*/ | ||
async function go (sessionId, payload) { | ||
const session = await SessionModel.query().findById(sessionId) | ||
const regions = await FetchRegionsService.go() | ||
|
||
const validationResult = _validate(payload, regions) | ||
|
||
if (!validationResult) { | ||
await _save(session, payload) | ||
|
||
// The journey is complete (we don't need any details) if the bill run type is not 2PT | ||
return { setupComplete: !session.data.type.startsWith('two_part') } | ||
} | ||
|
||
const formattedData = RegionPresenter.go(session, regions) | ||
|
||
return { | ||
error: validationResult, | ||
...formattedData | ||
} | ||
} | ||
|
||
async function _save (session, payload) { | ||
const currentData = session.data | ||
|
||
currentData.region = payload.region | ||
|
||
return session.$query().patch({ data: currentData }) | ||
} | ||
|
||
function _validate (payload, regions) { | ||
const validation = RegionValidator.go(payload, regions) | ||
|
||
if (!validation.error) { | ||
return null | ||
} | ||
|
||
const { message } = validation.error.details[0] | ||
|
||
return { | ||
text: message | ||
} | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
'use strict' | ||
|
||
/** | ||
* Validates data submitted for the `/bill-runs/setup/{sessionId}/region` page | ||
* @module BillRunsCreateRegionValidator | ||
*/ | ||
|
||
const Joi = require('joi') | ||
|
||
/** | ||
* Validates data submitted for the `/bill-runs/setup/{sessionId}/region` page | ||
* | ||
* @param {Object} payload - The payload from the request to be validated | ||
* | ||
* @returns {Object} the result from calling Joi's schema.validate(). It will be an object with a `value:` property. If | ||
* any errors are found the `error:` property will also exist detailing what the issues were | ||
*/ | ||
function go (data, regions) { | ||
const validValues = regions.map((region) => { | ||
return region.id | ||
}) | ||
|
||
const schema = Joi.object({ | ||
region: Joi.string() | ||
.required() | ||
.valid(...validValues) | ||
.messages({ | ||
'any.required': 'Select the region', | ||
'any.only': 'Select the region', | ||
'string.empty': 'Select the region' | ||
}) | ||
}) | ||
|
||
return schema.validate(data, { abortEarly: false }) | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
{% extends 'layout.njk' %} | ||
{% from "govuk/components/back-link/macro.njk" import govukBackLink %} | ||
{% from "govuk/components/button/macro.njk" import govukButton %} | ||
{% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %} | ||
{% from "govuk/components/radios/macro.njk" import govukRadios %} | ||
|
||
{% block breadcrumbs %} | ||
{# Back link #} | ||
{{ | ||
govukBackLink({ | ||
text: 'Back', | ||
href: '/system/bill-runs/setup/' + sessionId + '/type' | ||
}) | ||
}} | ||
{% endblock %} | ||
|
||
{% block content %} | ||
{% if error %} | ||
{{ govukErrorSummary({ | ||
titleText: "There is a problem", | ||
errorList: [ | ||
{ | ||
text: error.text, | ||
href: '#region-error' | ||
} | ||
] | ||
}) }} | ||
{% endif %} | ||
|
||
<div class="govuk-body"> | ||
<form method="post"> | ||
{% set regionItems = [] %} | ||
{% for region in regions %} | ||
{% set regionItem = { text: region.displayName, value: region.id, checked: region.id == selectedRegion } %} | ||
|
||
{# Push our item into the region items array #} | ||
{% set regionItems = (regionItems.push(regionItem), regionItems) %} | ||
{% endfor %} | ||
|
||
{{ govukRadios({ | ||
attributes: { | ||
'data-test': 'bill-run-region' | ||
}, | ||
name: 'region', | ||
errorMessage: error, | ||
fieldset: { | ||
legend: { | ||
text: pageTitle, | ||
isPageHeading: true, | ||
classes: 'govuk-fieldset__legend--l govuk-!-margin-bottom-6' | ||
} | ||
}, | ||
items: regionItems | ||
}) }} | ||
|
||
{{govukButton({ text: 'Continue', preventDoubleClick: true }) }} | ||
</form> | ||
</div> | ||
{% endblock %} |
Oops, something went wrong.