Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bill runs setup season page to journey #808

Merged
merged 7 commits into from
Mar 12, 2024
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
32 changes: 32 additions & 0 deletions app/controllers/bill-runs-setup.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

const InitiateSessionService = require('../services/bill-runs/setup/initiate-session.service.js')
const RegionService = require('../services/bill-runs/setup/region.service.js')
const SeasonService = require('../services/bill-runs/setup/season.service.js')
const SubmitRegionService = require('../services/bill-runs/setup/submit-region.service.js')
const SubmitSeasonService = require('../services/bill-runs/setup/submit-season.service.js')
const SubmitTypeService = require('../services/bill-runs/setup/submit-type.service.js')
const SubmitYearService = require('../services/bill-runs/setup/submit-year.service.js')
const TypeService = require('../services/bill-runs/setup/type.service.js')
Expand All @@ -25,6 +27,18 @@ async function region (request, h) {
})
}

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

const pageData = await SeasonService.go(sessionId)

return h.view('bill-runs/setup/season.njk', {
activeNavBar: 'bill-runs',
pageTitle: 'Select the season',
...pageData
})
}

async function setup (_request, h) {
const session = await InitiateSessionService.go()

Expand All @@ -51,6 +65,22 @@ async function submitRegion (request, h) {
return h.redirect(`/system/bill-runs/setup/${sessionId}/year`)
}

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

const pageData = await SubmitSeasonService.go(sessionId, request.payload)

if (pageData.error) {
return h.view('bill-runs/setup/season.njk', {
activeNavBar: 'bill-runs',
pageTitle: 'Select the season',
...pageData
})
}

return h.redirect(`/system/bill-runs/setup/${sessionId}/generate`)
}

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

Expand Down Expand Up @@ -113,8 +143,10 @@ async function year (request, h) {

module.exports = {
region,
season,
setup,
submitRegion,
submitSeason,
submitType,
submitYear,
type,
Expand Down
24 changes: 24 additions & 0 deletions app/presenters/bill-runs/setup/season.presenter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict'

/**
* Formats data for the `/bill-runs/setup/{sessionId}/season` page
* @module SeasonPresenter
*/

/**
* Formats data for the `/bill-runs/setup/{sessionId}/season` page
*
* @param {module:SessionModel} session - The session instance to format
*
* @returns {Object} - The data formatted for the view template
*/
function go (session) {
return {
sessionId: session.id,
selectedSeason: session.data.season ? session.data.season : null
}
}

module.exports = {
go
}
26 changes: 26 additions & 0 deletions app/routes/bill-runs-setup.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@ const routes = [
description: 'Submit the region for the bill run'
}
},
{
method: 'GET',
path: '/bill-runs/setup/{sessionId}/season',
handler: BillRunsSetupController.season,
options: {
auth: {
access: {
scope: ['billing']
}
},
description: 'Select the season for the bill run'
}
},
{
method: 'POST',
path: '/bill-runs/setup/{sessionId}/season',
handler: BillRunsSetupController.submitSeason,
options: {
auth: {
access: {
scope: ['billing']
}
},
description: 'Submit the season for the bill run'
}
},
{
method: 'GET',
path: '/bill-runs/setup',
Expand Down
32 changes: 32 additions & 0 deletions app/services/bill-runs/setup/season.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict'

/**
* Orchestrates fetching and presenting the data for `/bill-runs/setup/{sessionId}/season` page
* @module BillRunsCreateSeasonService
*/

const SessionModel = require('../../../models/session.model.js')
const SeasonPresenter = require('../../../presenters/bill-runs/setup/season.presenter.js')

/**
* Orchestrates fetching and presenting the data for `/bill-runs/setup/{sessionId}/season` page
*
* Supports generating the data needed for the type page in the create bill run journey. It fetches the current
* session record and formats the data needed for the form.
*
* @param {string} sessionId - The UUID for setup bill run session record
*
* @returns {Promise<Object>} The view data for the season page
*/
async function go (sessionId) {
const session = await SessionModel.query().findById(sessionId)
const formattedData = SeasonPresenter.go(session)

return {
...formattedData
}
}

module.exports = {
go
}
4 changes: 2 additions & 2 deletions app/services/bill-runs/setup/submit-region.service.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

/**
* Orchestrates validating the data for `/bill-runs/setup/{sessionId}/region` page
* Handles the user submission for the `/bill-runs/setup/{sessionId}/region` page
* @module SubmitRegionService
*/

Expand All @@ -11,7 +11,7 @@ const RegionValidator = require('../../../validators/bill-runs/setup/region.vali
const SessionModel = require('../../../models/session.model.js')

/**
* Orchestrates validating the data for `/bill-runs/setup/{sessionId}/region` page
* Handles the user submission for the `/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.
Expand Down
74 changes: 74 additions & 0 deletions app/services/bill-runs/setup/submit-season.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
'use strict'

/**
* Handles the user submission for the `/bill-runs/setup/{sessionId}/type` page
* @module SubmitSeasonService
*/

const SessionModel = require('../../../models/session.model.js')
const SeasonPresenter = require('../../../presenters/bill-runs/setup/season.presenter.js')
const SeasonValidator = require('../../../validators/bill-runs/setup/season.validator.js')

/**
* Handles the user submission for the `/bill-runs/setup/{sessionId}/type` 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 empty object. This will
* indicate to the controller that the submission was successful triggering it to redirect to the next page in the
* journey.
*
* 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 empty object if there are no errors else the page data for the type page including the
* validation error details
*/
async function go (sessionId, payload) {
const session = await SessionModel.query().findById(sessionId)

const validationResult = _validate(payload)

if (!validationResult) {
await _save(session, payload)

return {}
}

const formattedData = SeasonPresenter.go(session)

return {
error: validationResult,
...formattedData
}
}

async function _save (session, payload) {
const currentData = session.data

currentData.season = payload.season

return session.$query().patch({ data: currentData })
}

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

if (!validation.error) {
return null
}

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

return {
text: message
}
}

module.exports = {
go
}
40 changes: 40 additions & 0 deletions app/validators/bill-runs/setup/season.validator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict'

/**
* Validates data submitted for the `/bill-runs/setup/{sessionId}/season` page
* @module SeasonValidator
*/

const Joi = require('joi')

const VALID_VALUES = [
'summer',
'winter_all_year'
]

/**
* Validates data submitted for the `/bill-runs/setup/{sessionId}/season` 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) {
const schema = Joi.object({
season: Joi.string()
.required()
.valid(...VALID_VALUES)
.messages({
'any.required': 'Select the season',
'any.only': 'Select the season',
'string.empty': 'Select the season'
})
})

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

module.exports = {
go
}
62 changes: 62 additions & 0 deletions app/views/bill-runs/setup/season.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{% 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 + '/year'
})
}}
{% endblock %}

{% block content %}
{% if error %}
{{ govukErrorSummary({
titleText: 'There is a problem',
errorList: [
{
text: error.text,
href: '#season-error'
}
]
}) }}
{% endif %}

<div class="govuk-body">
<form method="post">
{{ govukRadios({
attributes: {
'data-test': 'bill-run-season'
},
name: 'season',
errorMessage: error,
fieldset: {
legend: {
text: pageTitle,
isPageHeading: true,
classes: 'govuk-fieldset__legend--l govuk-!-margin-bottom-6'
}
},
items: [
{
text: 'Summer',
value: 'summer',
checked: 'summer' == selectedSeason
},
{
text: 'Winter and All year',
value: 'winter_all_year',
checked: 'winter_all_year' == selectedSeason
}
]
}) }}

{{ govukButton({ text: 'Continue', preventDoubleClick: true }) }}
</form>
</div>
{% endblock %}
Loading
Loading