Skip to content

Commit

Permalink
Feature-requirements-for-returns-view-page (#1118)
Browse files Browse the repository at this point in the history
* Add requirements for returns view page

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

The requirements for return journey has been built and the check page has been finished. This showed a page with requirements for returns allowing users to make changes to requirements for returns.

This piece of work will replicate the requirements for returns check page but will not allow users to make changes (the card and information is identical, apart from the title and a return reference).

There will be a link "View" on the licence set up page that links to this page. That is added as part of this change. Work for this was done here - #1054
  • Loading branch information
jonathangoulding authored Jun 21, 2024
1 parent be3ea9a commit 8c76943
Show file tree
Hide file tree
Showing 19 changed files with 1,200 additions and 74 deletions.
13 changes: 12 additions & 1 deletion app/controllers/return-requirements.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const SubmitReturnsCycleService = require('../services/return-requirements/submi
const SubmitSetupService = require('../services/return-requirements/setup/submit-setup.service.js')
const SubmitSiteDescriptionService = require('../services/return-requirements/submit-site-description.service.js')
const SubmitStartDateService = require('../services/return-requirements/submit-start-date.service.js')
const ViewService = require('../services/return-requirements/view.service.js')

async function abstractionPeriod (request, h) {
const { requirementIndex, sessionId } = request.params
Expand Down Expand Up @@ -494,6 +495,15 @@ async function submitStartDate (request, h) {
return h.redirect(`/system/return-requirements/${sessionId}/no-returns-required`)
}

async function view (request, h) {
const { returnVersionId } = request.params
const pageData = await ViewService.go(returnVersionId)

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

module.exports = {
abstractionPeriod,
add,
Expand Down Expand Up @@ -533,5 +543,6 @@ module.exports = {
submitReturnsCycle,
submitSetup,
submitSiteDescription,
submitStartDate
submitStartDate,
view
}
40 changes: 40 additions & 0 deletions app/lib/general.lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,45 @@ function generateAbstractionPointDetail (pointDetail) {
return abstractionPoint
}

/**
* Generate a string that represents an abstraction point based on the assumption the points have already been merged
*
* When abstracting water the point at which this is done can be described in several ways depending on the number of
* Nation Grid References are saved against the abstraction point. This function checks for these references and builds
* a string that defines the details of the abstraction point.
*
* This follows the same out put as generateAbstractionPointDetail but the points have already been merged
*
* @param {Object} pointDetail - Object containing all the details for the point
*
* @returns {String} a description of the abstraction point
*/
function generatePointDetail (pointDetail) {
let abstractionPoint = null

if (pointDetail.ngr4) {
const point1 = pointDetail.ngr1
const point2 = pointDetail.ngr2
const point3 = pointDetail.ngr3
const point4 = pointDetail.ngr4

abstractionPoint = `Within the area formed by the straight lines running between National Grid References ${point1} ${point2} ${point3} and ${point4}`
} else if (pointDetail.ngr2) {
const point1 = pointDetail.ngr1
const point2 = pointDetail.ngr2

abstractionPoint = `Between National Grid References ${point1} and ${point2}`
} else {
const point1 = pointDetail.ngr1

abstractionPoint = `At National Grid Reference ${point1}`
}

abstractionPoint += pointDetail.description !== undefined ? ` (${pointDetail.description})` : ''

return abstractionPoint
}

/**
* Generate a Universally Unique Identifier (UUID)
*
Expand Down Expand Up @@ -295,6 +334,7 @@ module.exports = {
determineCurrentFinancialYear,
flashNotification,
generateAbstractionPointDetail,
generatePointDetail,
generateUUID,
periodsOverlap,
timestampForPostgres,
Expand Down
2 changes: 1 addition & 1 deletion app/presenters/licences/set-up.presenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ function _returnVersions (returnVersions = [{}]) {
return {
action: [{
text: 'View',
link: ''
link: `/system/return-requirements/${returnVersion.id}/view`
}],
endDate: returnVersion.endDate ? formatLongDate(returnVersion.endDate) : '',
reason: returnVersion.reason ? returnRequirementReasons[returnVersion.reason] : '',
Expand Down
24 changes: 21 additions & 3 deletions app/presenters/return-requirements/check.presenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,31 @@ function go (session) {
return {
additionalSubmissionOptions: additionalSubmissionOptions ?? [],
licenceRef: licence.licenceRef,
note: note ? note.content : null,
note: _note(note),
pageTitle: `Check the requirements for returns for ${licence.licenceHolder}`,
reason: returnRequirementReasons[reason],
reasonLink: _reasonLink(sessionId, returnsRequired),
sessionId,
startDate: _startDate(session),
userEmail: note ? note.userEmail : 'No notes added'
startDate: _startDate(session)
}
}

function _note (note) {
if (note?.content) {
return {
actions: [
{ text: 'Change', href: 'note' },
{ text: 'Delete', href: 'delete-note' }
],
text: note.content
}
} else {
return {
actions: [
{ text: 'Add a note', href: 'note' }
],
text: 'No notes added'
}
}
}

Expand Down
143 changes: 143 additions & 0 deletions app/presenters/return-requirements/view.presenter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
'use strict'

/**
* Formats requirements for returns data for the `/return-requirements/{sessionId}/view` page
* @module ViewPresenter
*/

const { formatAbstractionDate } = require('../base.presenter.js')
const { formatLongDate } = require('../base.presenter.js')
const { generatePointDetail } = require('../../lib/general.lib.js')
const { returnRequirementReasons, returnRequirementFrequencies } = require('../../lib/static-lookups.lib.js')

/**
* Formats requirements for returns data for the `/return-requirements/{sessionId}/view` page
*
* @param {ReturnVersionModel[]} requirementsForReturns
* return version, licence, return requirements (requirement, points, purposes)
*
* @returns {Object} requirements for returns data needed by the view template
*/

function go (requirementsForReturns) {
const { createdAt, licence, reason, notes, multipleUpload, returnRequirements, startDate, status, user } =
requirementsForReturns

return {
additionalSubmissionOptions: {
multipleUpload: multipleUpload === true ? 'Yes' : 'No'
},
licenceId: licence.id,
licenceRef: licence.licenceRef,
notes,
pageTitle: `Check the requirements for returns for ${licence.$licenceHolder()}`,
reason: returnRequirementReasons[reason] || '',
requirements: _requirements(returnRequirements),
startDate: formatLongDate(startDate),
status: _status(status),
createdDate: formatLongDate(createdAt),
createdBy: user ? user.username : ''
}
}

function _abstractionPeriod (requirement) {
const {
abstractionPeriodStartDay,
abstractionPeriodStartMonth,
abstractionPeriodEndDay,
abstractionPeriodEndMonth
} = requirement

const startDate = formatAbstractionDate(abstractionPeriodStartDay, abstractionPeriodStartMonth)
const endDate = formatAbstractionDate(abstractionPeriodEndDay, abstractionPeriodEndMonth)

return `From ${startDate} to ${endDate}`
}

function _agreementsExceptions (returnRequirement) {
const agreementsExceptions = _buildAgreementExceptions(returnRequirement)

if (agreementsExceptions.length === 1) {
return agreementsExceptions[0]
}

if (agreementsExceptions.length === 2) {
return agreementsExceptions.join(' and ')
}

return agreementsExceptions.slice(0, agreementsExceptions.length - 1)
.join(', ') + ', and ' + agreementsExceptions[agreementsExceptions.length - 1]
}

function _buildAgreementExceptions (returnRequirement) {
const { fiftySixException, gravityFill, reabstraction, twoPartTariff } = returnRequirement
const agreementsExceptions = []

if (gravityFill) {
agreementsExceptions.push('Gravity fill')
}

if (reabstraction) {
agreementsExceptions.push('Transfer re-abstraction scheme')
}

if (twoPartTariff) {
agreementsExceptions.push('Two-part tariff')
}

if (fiftySixException) {
agreementsExceptions.push('56 returns exception')
}

if (agreementsExceptions.length === 0) {
agreementsExceptions.push('None')
}

return agreementsExceptions
}

function _mapRequirement (requirement) {
return {
abstractionPeriod: _abstractionPeriod(requirement),
agreementsExceptions: _agreementsExceptions(requirement),
frequencyCollected: returnRequirementFrequencies[requirement.collectionFrequency],
frequencyReported: returnRequirementFrequencies[requirement.reportingFrequency],
points: _points(requirement.points),
purposes: _purposes(requirement.purposes),
returnReference: requirement.legacyId,
returnsCycle: requirement.summer === true ? 'Summer' : 'Winter and all year',
siteDescription: requirement.siteDescription,
title: requirement.siteDescription
}
}

function _purposes (returnRequirementPurposes) {
return returnRequirementPurposes.map((returnRequirementPurpose) => {
return returnRequirementPurpose.purposeDetails.description
})
}

function _points (returnRequirementPoints) {
return returnRequirementPoints.map((returnRequirementPoint) => {
return generatePointDetail(returnRequirementPoint)
})
}

function _requirements (requirements) {
return requirements.map((requirement) => {
return _mapRequirement(requirement)
})
}

function _status (status) {
const statuses = {
current: 'approved',
superseded: 'replaced'
}

return statuses[status]
}

module.exports = {
go
}
12 changes: 12 additions & 0 deletions app/routes/return-requirement.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,18 @@ const routes = [
}
}
}
},
{
method: 'GET',
path: '/return-requirements/{returnVersionId}/view',
handler: ReturnRequirementsController.view,
options: {
auth: {
access: {
scope: ['billing']
}
}
}
}
]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
'use strict'

/**
* Fetches requirements for returns by the return version id
* @module FetchRequirementsForReturnsService
*/

const ReturnVersionModel = require('../../models/return-version.model.js')

/**
* Fetches requirements for returns by the return version id
*
* Includes the licence, return requirements (requirement, points, purposes)
*
* @param {string} returnVersionId - The UUID of the selected return version to get requirements for
*
* @returns {Promise<ReturnVersionModel[]>}
* The return version, licence, return requirements (requirement, points, purposes)
*
*/
async function go (returnVersionId) {
const returnVersion = await _fetch(returnVersionId)

return returnVersion
}

async function _fetch (returnVersionId) {
return ReturnVersionModel.query()
.findById(returnVersionId)
.select([
'createdAt',
'id',
'multiple_upload',
'notes',
'reason',
'startDate',
'status'
])
.withGraphFetched('user')
.modifyGraph('user', (builder) => {
builder.select([
'username'
])
})
.withGraphFetched('licence')
.modifyGraph('licence', (builder) => {
builder.select([
'id',
'licenceRef'
]).modify('licenceHolder')
})
.withGraphFetched('returnRequirements')
.modifyGraph('returnRequirements', (builder) => {
builder.select([
'abstractionPeriodEndDay',
'abstractionPeriodEndMonth',
'abstractionPeriodStartDay',
'abstractionPeriodStartMonth',
'collectionFrequency',
'fiftySixException',
'gravityFill',
'id',
'legacyId',
'reabstraction',
'reportingFrequency',
'siteDescription',
'summer',
'twoPartTariff'
])
})
.withGraphFetched('returnRequirements.[returnRequirementPoints as points]')
.modifyGraph('returnRequirements.[returnRequirementPoints as points]', (builder) => {
builder.select([
'description',
'ngr1',
'ngr2',
'ngr3',
'ngr4'
])
})
.withGraphFetched('returnRequirements.[returnRequirementPurposes as purposes.[purpose as purposeDetails]]')
.modifyGraph('returnRequirements.[returnRequirementPurposes as purposes]', (builder) => {
builder.select(['id'])
})
.modifyGraph('returnRequirements.[returnRequirementPurposes as purposes.[purpose as purposeDetails]]', (builder) => {
builder.select(['description'])
})
}

module.exports = {
go
}
Loading

0 comments on commit 8c76943

Please sign in to comment.