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

Filter Licences by Licence Holder Name on the 2PT Review Licences Page #809

Merged
merged 21 commits into from
Mar 15, 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
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
Loading