Skip to content

Commit

Permalink
Filter Licences by Licence Holder Name on the 2PT Review Licences Page (
Browse files Browse the repository at this point in the history
#809)

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

Add the functionality to be able to filter on the two-part tariff review screen by licence holder name.
  • Loading branch information
Jozzey authored Mar 15, 2024
1 parent 8165edd commit d007dca
Show file tree
Hide file tree
Showing 13 changed files with 371 additions and 89 deletions.
3 changes: 1 addition & 2 deletions app/controllers/bill-runs.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ async function create (request, h) {

async function review (request, h) {
const { id } = request.params

const pageData = await ReviewBillRunService.go(id)
const pageData = await ReviewBillRunService.go(id, request.payload)

return h.view('bill-runs/review.njk', {
pageTitle: 'Review licences',
Expand Down
24 changes: 16 additions & 8 deletions app/models/bill-run.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ class BillRunModel extends BaseModel {

static get relationMappings () {
return {
region: {
relation: Model.BelongsToOneRelation,
modelClass: 'region.model',
billRunVolumes: {
relation: Model.HasManyRelation,
modelClass: 'bill-run-volume.model',
join: {
from: 'billRuns.regionId',
to: 'regions.id'
from: 'billRuns.id',
to: 'billRunVolumes.billRunId'
}
},
bills: {
Expand All @@ -32,12 +32,20 @@ class BillRunModel extends BaseModel {
to: 'bills.billRunId'
}
},
billRunVolumes: {
region: {
relation: Model.BelongsToOneRelation,
modelClass: 'region.model',
join: {
from: 'billRuns.regionId',
to: 'regions.id'
}
},
reviewLicences: {
relation: Model.HasManyRelation,
modelClass: 'bill-run-volume.model',
modelClass: 'review-licence.model',
join: {
from: 'billRuns.id',
to: 'billRunVolumes.billRunId'
to: 'reviewLicences.billRunId'
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions app/models/review-licence.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ class ReviewLicenceModel extends BaseModel {

static get relationMappings () {
return {
billRun: {
relation: Model.BelongsToOneRelation,
modelClass: 'bill-run.model',
join: {
from: 'reviewLicences.billRunId',
to: 'billRuns.id'
}
},
licence: {
relation: Model.BelongsToOneRelation,
modelClass: 'licence.model',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,33 @@ const { formatLongDate } = require('../../base.presenter.js')
/**
* Prepares and processes bill run and licence data for presentation
*
* @param {module:BillRunModel} billRun the data from the bill run
* @param {module:LicenceModel} licences the licences data asociated with the bill run
* @param {module:BillRunModel} billRun The data from the bill run
* @param {module:LicenceModel} licences The licences data asociated with the bill run
* @param {String} filterLicenceHolder The string that the licence holder is to be filtered on if any
*
* @returns {Object} the prepared bill run and licence data to be passed to the review page
* @returns {Object} The prepared bill run and licence data to be passed to the review page
*/
function go (billRun, licences) {
const { licencesToReviewCount, preparedLicences } = _prepareLicences(licences)
function go (billRun, licences, filterLicenceHolder) {
const { numberOfLicencesToReview, preparedLicences } = _prepareLicences(licences)

const preparedBillRun = _prepareBillRun(billRun, preparedLicences, licencesToReviewCount)
const preparedBillRun = _prepareBillRun(billRun, preparedLicences, numberOfLicencesToReview)
const filterData = { openFilter: false }

return { ...preparedBillRun, preparedLicences }
if (filterLicenceHolder) {
filterData.openFilter = true
filterData.licenceHolder = filterLicenceHolder
}

return { ...preparedBillRun, preparedLicences, filterData }
}

function _prepareLicences (licences) {
let licencesToReviewCount = 0
let numberOfLicencesToReview = 0
const preparedLicences = []

for (const licence of licences) {
if (licence.status === 'review') {
licencesToReviewCount++
numberOfLicencesToReview++
}

preparedLicences.push({
Expand All @@ -41,18 +48,19 @@ function _prepareLicences (licences) {
})
}

return { preparedLicences, licencesToReviewCount }
return { preparedLicences, numberOfLicencesToReview }
}

function _prepareBillRun (billRun, billRunLicences, licencesToReviewCount) {
function _prepareBillRun (billRun, preparedLicences, numberOfLicencesToReview) {
return {
region: billRun.region.displayName,
status: billRun.status,
dateCreated: formatLongDate(billRun.createdAt),
financialYear: _financialYear(billRun.toFinancialYearEnding),
billRunType: 'two-part tariff',
numberOfLicences: billRunLicences.length,
licencesToReviewCount
numberOfLicencesDisplayed: preparedLicences.length,
numberOfLicencesToReview,
totalNumberOfLicences: billRun.reviewLicences[0].totalNumberOfLicences
}
}

Expand All @@ -64,13 +72,12 @@ function _financialYear (financialYearEnding) {
}

function _getIssueOnLicence (issues) {
if (issues.length > 1) {
// if there is more than one issue the issues will be seperated by a comma
if (issues.includes(',')) {
return 'Multiple Issues'
} else if (issues.length === 1) {
return issues[0]
} else {
return ''
}

return issues
}

module.exports = {
Expand Down
13 changes: 13 additions & 0 deletions app/routes/bill-runs.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ const routes = [
description: 'Review two-part tariff match and allocation results'
}
},
{
method: 'POST',
path: '/bill-runs/{id}/review',
handler: BillRunsController.review,
options: {
auth: {
access: {
scope: ['billing']
}
},
description: 'POST request recieved when filtering applied to review two-part tariff match and allocation results'
}
},
{
method: 'GET',
path: '/bill-runs/{id}/review/{licenceId}',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,48 @@ const ReviewLicenceModel = require('../../../models/review-licence.model.js')
* ref.
*
* @param {String} id The UUID for the bill run
* @param {Object} payload The `request.payload` containing the filter data. This only contains data when there is a
* POST request, which only occurs when a filter is applied to the results.
*
* @returns {Promise<Object>} an object containing the billRun data and an array of licences for the bill run
* @returns {Promise<Object>} An object containing the billRun data and an array of licences for the bill run. Also
* included is any data that has been used to filter the results
*/
async function go (id) {
const billRun = await _fetchBillRun(id)
const licences = await _fetchBillRunLicences(id)
async function go (id, payload) {
const filterLicenceHolder = payload?.filterLicenceHolder

return { billRun, licences }
}
const billRun = await _fetchBillRun(id)
const licences = await _fetchBillRunLicences(id, filterLicenceHolder)

async function _fetchBillRunLicences (id) {
return ReviewLicenceModel.query()
.where('billRunId', id)
.orderBy('status', 'desc')
return { billRun, licences, filterLicenceHolder }
}

async function _fetchBillRun (id) {
return BillRunModel.query()
.findById(id)
.select([
'id',
'createdAt',
'status',
'toFinancialYearEnding',
'batchType'
])
.select('id', 'createdAt', 'status', 'toFinancialYearEnding', 'batchType')
.withGraphFetched('region')
.modifyGraph('region', (builder) => {
builder.select([
'id',
'displayName'
])
builder.select('id', 'displayName')
})
.withGraphFetched('reviewLicences')
.modifyGraph('reviewLicences', (builder) => {
builder.count('licenceId as totalNumberOfLicences')
.groupBy('billRunId')
})
}

async function _fetchBillRunLicences (id, filterLicenceHolder) {
const reviewLicenceQuery = ReviewLicenceModel.query()
.where('billRunId', id)
.orderBy('status', 'desc')

if (filterLicenceHolder) {
reviewLicenceQuery.whereILike('licenceHolder', `%${filterLicenceHolder}%`)
}

return reviewLicenceQuery
}

module.exports = {
go
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ const ReviewBillRunPresenter = require('../../../presenters/bill-runs/two-part-t
/**
* Orchestrates fetching and presenting the data needed for the review bill run page
*
* @param {string} id The UUID for the bill run to review
* @param {String} id The UUID for the bill run to review
* @param {Object} payload The `request.payload` containing the filter data. This is only passed to the service when
* there is a POST request, which only occurs when a filter is applied to the results.
*
* @returns {Promise<Object>} an object representing the `pageData` needed by the review bill run template. It contains details of
* the bill run and the licences linked to it.
* @returns {Promise<Object>} An object representing the `pageData` needed by the review bill run template. It contains
* details of the bill run and the licences linked to it as well as any data that has been used to filter the results.
*/
async function go (id) {
const { billRun, licences } = await FetchBillRunLicencesService.go(id)
async function go (id, payload = null) {
const { billRun, licences, filterLicenceHolder } = await FetchBillRunLicencesService.go(id, payload)

const pageData = ReviewBillRunPresenter.go(billRun, licences)
const pageData = ReviewBillRunPresenter.go(billRun, licences, filterLicenceHolder)

return pageData
}
Expand Down
67 changes: 56 additions & 11 deletions app/views/bill-runs/review.njk
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@

{% block breadcrumbs %}
{# Back link #}
{{
govukBackLink({
{{ govukBackLink({
text: 'Go back to bill runs',
href: '/billing/batch/list'
})
}}
}) }}
{% endblock %}

{% block content %}
Expand All @@ -36,10 +34,10 @@
{% endif %}

<p class="govuk-body">
{{govukTag({
{{ govukTag({
text: status,
classes: colour
})}}
}) }}
</p>

{# Bill run meta-data #}
Expand Down Expand Up @@ -102,10 +100,10 @@
</div>

{# Dynamic message either telling the user they have issues to deal with or that they can generate bills #}
{% if licencesToReviewCount > 0 %}
{% if numberOfLicencesToReview > 0 %}
<section class="govuk-!-margin-bottom-9">
{{ govukInsetText({
text: 'You need to review ' + licencesToReviewCount + ' licences with returns data issues. You can then continue and send the bill run.'
text: 'You need to review ' + numberOfLicencesToReview + ' licences with returns data issues. You can then continue and send the bill run.'
}) }}
</section>
{% else %}
Expand All @@ -118,11 +116,51 @@
<section class="govuk-!-margin-bottom-9">
{{ govukButton({
classes: "govuk-button--secondary govuk-!-margin-bottom-0",
text: 'Cancel bill run',
href: 'cancel'
text: "Cancel bill run",
href: "cancel"
}) }}
</section>


{% set filtersForm %}
<h2 class="govuk-heading-m govuk-!-margin-bottom-3">Filter by</h2>

<form method="post" novalidate action="review">
{{ govukInput({
label: {
text: "Licence holder",
classes: "govuk-label--s",
isPageHeading: false
},
classes: "govuk-input--width-20",
id: "filterLicenceHolder",
name: "filterLicenceHolder",
value: filterData.licenceHolder
}) }}

<div class="govuk-button-group">
{{ govukButton({
text: "Apply filters"
}) }}

{{ govukButton({
text: "Clear filters",
classes: "govuk-button--secondary ",
name: "clearFilters",
type: "reset",
href: "review"
}) }}
</div>
</form>
{% endset %}

{{ govukDetails({
summaryText: "Filter licences",
html: filtersForm | safe,
classes: "govuk-!-margin-bottom-2",
open: filterData.openFilter
}) }}

{# Generate the row data for the table #}
{% set tableRows = [] %}
{% if preparedLicences.length > 0 %}
Expand Down Expand Up @@ -154,9 +192,16 @@
{% endfor %}
{% endif %}

{# Sets the caption to be used in the table below #}
{% if totalNumberOfLicences > numberOfLicencesDisplayed %}
{% set caption = "Showing " + numberOfLicencesDisplayed + " of " + totalNumberOfLicences + " licences" %}
{% else %}
{% set caption = "Showing all " + totalNumberOfLicences + " licences" %}
{% endif %}

{# Table displaying details of the licences in the bill run. These results take into account any filter that is set #}
{{ govukTable({
caption: "Showing all " + numberOfLicences + " licences",
caption: caption,
captionClasses: "govuk-table__caption--s govuk-!-margin-bottom-2",
firstCellIsHeader: false,
head: [
Expand Down
Loading

0 comments on commit d007dca

Please sign in to comment.