Skip to content

Commit

Permalink
Additional filters for two-part tariff review (#1166)
Browse files Browse the repository at this point in the history
https://eaflood.atlassian.net/browse/WATER-4544

Currently, on the two-part tariff review page a user can filter the licences by licence name, licence issues or licence status. The business has requested that we add filters to filter by the licence progress and if a licence has multiple issues on it. This PR adds those.
  • Loading branch information
Beckyrose200 authored Jul 8, 2024
1 parent 3a6b47b commit 0d2f958
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 31 deletions.
3 changes: 2 additions & 1 deletion app/lib/static-lookups.lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ const twoPartTariffReviewIssues = {
'returns-late': 'Returns received late',
'return-split-over-refs': 'Return split over charge references',
'some-returns-not-received': 'Some returns not received',
'unable-to-match-return': 'Unable to match return'
'unable-to-match-return': 'Unable to match return',
'multiple-issues': 'Multiple issues'
}

module.exports = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,28 @@ const { formatLongDate } = require('../../base.presenter.js')
* only contain data when there is a POST request, which only occurs when a filter is applied to the results.
* @param {String} filterLicenceStatus The status of the licence to filter the results by. This also only contains data
* when there is a POST request.
* @param {String} filterProgress The progress of the licence to filter the results by. This also only contains data
* when there is a POST request.
* @param {module:LicenceModel} licences The licences data associated with the bill run
*
* @returns {Object} The prepared bill run,licence and filter data to be passed to the review page
*/
function go (billRun, filterIssues, filterLicenceHolderNumber, filterLicenceStatus, licences) {
function go (billRun, filterIssues, filterLicenceHolderNumber, filterLicenceStatus, filterProgress, licences) {
const preparedLicences = _prepareLicences(licences)

const preparedBillRun = _prepareBillRun(billRun, preparedLicences)

const issues = filterIssues ? _prepareIssues(filterIssues) : filterIssues

const filter = { issues, licenceHolderNumber: filterLicenceHolderNumber, licenceStatus: filterLicenceStatus }
const filter = {
issues,
licenceHolderNumber: filterLicenceHolderNumber,
licenceStatus: filterLicenceStatus,
inProgress: filterProgress
}

// this opens the filter on the page if any filter data has been received so the user can see the applied filters
filter.openFilter = (filterIssues || filterLicenceHolderNumber || filterLicenceStatus) !== undefined
filter.openFilter = (filterIssues || filterLicenceHolderNumber || filterLicenceStatus || filterProgress) !== undefined

return { ...preparedBillRun, preparedLicences, filter }
}
Expand All @@ -46,6 +53,8 @@ function _prepareIssues (filterIssues) {
absOutsidePeriod: filterIssues.includes('abs-outside-period'),
aggregateFactor: filterIssues.includes('aggregate-factor'),
checkingQuery: filterIssues.includes('checking-query'),
multipleIssues: filterIssues.includes('multiple-issues'),
noIssues: filterIssues.includes('no-issues'),
noReturnsReceived: filterIssues.includes('no-returns-received'),
overAbstraction: filterIssues.includes('over-abstraction'),
overlapOfChargeDates: filterIssues.includes('overlap-of-charge-dates'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ function _licenceIssues (allElementIssues, allReturnIssues) {
const allIssues = [...allElementIssues, ...allReturnIssues]
const uniqueIssues = new Set(allIssues)

if (uniqueIssues.size > 1) {
uniqueIssues.add('Multiple issues')
}

return [...uniqueIssues].sort()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,28 @@ const DatabaseConfig = require('../../../../config/database.config.js')
* only contain data when there is a POST request, which only occurs when a filter is applied to the results.
* @param {String} filterLicenceStatus The status of the licence to filter the results by. This also only contains data
* when there is a POST request.
* @param {String} filterProgress The progress of the licence to filter the results by. This also only contains data
* when there is a POST request.
* @param {number} page - the page number of licences to be viewed
*
* @returns {Promise<Object>} An object containing the billRun data and an array of licences for the bill run that match
* the selected 'page in the data. Also included is any data that has been used to filter the results
*/
async function go (id, filterIssues, filterLicenceHolderNumber, filterLicenceStatus, page) {
async function go (id, filterIssues, filterLicenceHolderNumber, filterLicenceStatus, filterProgress, page) {
const billRun = await _fetchBillRun(id)
const licences = await _fetchBillRunLicences(id, filterIssues, filterLicenceHolderNumber, filterLicenceStatus, page)
const licences = await _fetchBillRunLicences(
id,
filterIssues,
filterLicenceHolderNumber,
filterLicenceStatus,
filterProgress,
page
)

return { billRun, licences }
}

function _applyFilters (reviewLicenceQuery, filterIssues, filterLicenceHolderNumber, filterLicenceStatus) {
function _applyFilters (reviewLicenceQuery, filterIssues, filterLicenceHolderNumber, filterLicenceStatus, filterProgress) {
if (filterIssues) {
_filterIssues(filterIssues, reviewLicenceQuery)
}
Expand All @@ -53,6 +62,10 @@ function _applyFilters (reviewLicenceQuery, filterIssues, filterLicenceHolderNum
if (filterLicenceStatus) {
reviewLicenceQuery.where('status', filterLicenceStatus)
}

if (filterProgress) {
reviewLicenceQuery.where('progress', 'true')
}
}

async function _fetchBillRun (id) {
Expand All @@ -71,7 +84,7 @@ async function _fetchBillRun (id) {
})
}

async function _fetchBillRunLicences (id, filterIssues, filterLicenceHolderNumber, filterLicenceStatus, page = 1) {
async function _fetchBillRunLicences (id, filterIssues, filterLicenceHolderNumber, filterLicenceStatus, filterProgress, page = 1) {
const reviewLicenceQuery = ReviewLicenceModel.query()
.select('licenceId', 'licenceRef', 'licenceHolder', 'issues', 'progress', 'status')
.where('billRunId', id)
Expand All @@ -81,34 +94,47 @@ async function _fetchBillRunLicences (id, filterIssues, filterLicenceHolderNumbe
])
.page(page - 1, DatabaseConfig.defaultPageSize)

_applyFilters(reviewLicenceQuery, filterIssues, filterLicenceHolderNumber, filterLicenceStatus)
_applyFilters(reviewLicenceQuery, filterIssues, filterLicenceHolderNumber, filterLicenceStatus, filterProgress)

return reviewLicenceQuery
}

function _filterIssues (filterIssues, reviewLicenceQuery) {
// if only a single issue is checked in the filter then a string is returned, otherwise it is an array
// When only one issue is selected in the filter, a string is returned; otherwise, an array is returned.
// The "no issues" filter can only be selected exclusively, so it will always be a string.
if (typeof filterIssues === 'string') {
const lookupIssue = twoPartTariffReviewIssues[filterIssues]
reviewLicenceQuery.whereLike('issues', `%${lookupIssue}%`)
filterIssues === 'no-issues' ? _handleNoIssues(reviewLicenceQuery) : _handleSingleIssue(filterIssues, reviewLicenceQuery)
} else {
// if we have got here then `issues` must be an array containing at least 2 records
const lookupIssues = filterIssues.map((filterIssue) => {
return twoPartTariffReviewIssues[filterIssue]
})

// the number of issues to check for in the where clause will vary depending on the number of issues checked. But
// there will always be at least 2
reviewLicenceQuery.where((builder) => {
builder
.whereLike('issues', `%${lookupIssues[0]}%`)
for (let i = 1; i < lookupIssues.length; i++) {
builder.orWhereLike('issues', `%${lookupIssues[i]}%`)
}
})
_handleMultipleIssues(filterIssues, reviewLicenceQuery)
}
}

function _handleMultipleIssues (filterIssues, reviewLicenceQuery) {
const lookupIssues = filterIssues.map((filterIssue) => {
return twoPartTariffReviewIssues[filterIssue]
})

// Construct a query that checks for multiple issues. There will always be at least two issues to check for.
reviewLicenceQuery.where((builder) => {
builder
.whereLike('issues', `%${lookupIssues[0]}%`)
for (let i = 1; i < lookupIssues.length; i++) {
builder.orWhereLike('issues', `%${lookupIssues[i]}%`)
}
})
}

function _handleNoIssues (reviewLicenceQuery) {
// To search for no issues, check if the issues column is empty
reviewLicenceQuery.where('issues', '')
}

function _handleSingleIssue (filterIssues, reviewLicenceQuery) {
const lookupIssue = twoPartTariffReviewIssues[filterIssues]

reviewLicenceQuery.whereLike('issues', `%${lookupIssue}%`)
}

module.exports = {
go
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const ReviewBillRunPresenter = require('../../../presenters/bill-runs/two-part-t
* 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, page, yar) {
const { filterIssues, filterLicenceHolderNumber, filterLicenceStatus } = _getFilters(id, yar)
const { filterIssues, filterLicenceHolderNumber, filterLicenceStatus, filterProgress } = _getFilters(id, yar)

const selectedPageNumber = page ? Number(page) : 1

Expand All @@ -29,6 +29,7 @@ async function go (id, page, yar) {
filterIssues,
filterLicenceHolderNumber,
filterLicenceStatus,
filterProgress,
selectedPageNumber
)

Expand All @@ -39,6 +40,7 @@ async function go (id, page, yar) {
filterIssues,
filterLicenceHolderNumber,
filterLicenceStatus,
filterProgress,
licences.results
)

Expand All @@ -51,12 +53,12 @@ async function go (id, page, yar) {

function _getFilters (id, yar) {
const filters = yar.get(`review-${id}`)

const filterIssues = filters?.filterIssues
const filterLicenceHolderNumber = filters?.filterLicenceHolderNumber
const filterLicenceStatus = filters?.filterLicenceStatus
const filterProgress = filters?.filterProgress

return { filterIssues, filterLicenceHolderNumber, filterLicenceStatus }
return { filterIssues, filterLicenceHolderNumber, filterLicenceStatus, filterProgress }
}

function _pageTitle (numberOfPages, selectedPageNumber) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ async function go (billRunId, payload, yar) {
const filterIssues = payload?.filterIssues
const filterLicenceHolderNumber = payload?.filterLicenceHolderNumber
const filterLicenceStatus = payload?.filterLicenceStatus
const filterProgress = payload?.filterProgress

if (clearFilters) {
yar.clear(`review-${billRunId}`)
} else {
yar.set(`review-${billRunId}`, {
filterIssues,
filterLicenceHolderNumber,
filterLicenceStatus
filterLicenceStatus,
filterProgress
})
}
}
Expand Down
37 changes: 37 additions & 0 deletions app/views/bill-runs/review.njk
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@
checked: filter.issues.checkingQuery,
attributes: { 'data-test': 'checking-query' }
},
{
value: "multiple-issues",
text: "Multiple issues",
checked: filter.issues.multipleIssues,
attributes: { 'data-test': 'multiple-issues' }
},
{
value: "no-returns-received",
text: "No returns received",
Expand Down Expand Up @@ -221,6 +227,37 @@
text: "Unable to match return",
checked: filter.issues.unableToMatchReturn,
attributes: { 'data-test': 'unable-to-match-return' }
},
{
divider: "or"
},
{
value: "no-issues",
text: "No issues",
checked: filter.issues.noIssues,
attributes: { 'data-test': 'no-issues' },
behaviour: "exclusive"
}
]
}) }}

{# Filter by licence progress #}
{{ govukCheckboxes({
classes: "govuk-checkboxes--small",
name: "filterProgress",
fieldset: {
legend: {
text: "Progress",
isPageHeading: false,
classes: "govuk-fieldset__legend--s"
}
},
items: [
{
value: "in-progress",
text: "In progress",
checked: filter.inProgress,
attributes: { 'data-test': 'in-progress' }
}
]
}) }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('Review Bill Run presenter', () => {
let filterIssues
let filterLicenceHolderNumber
let filterLicenceStatus
let filterProgress
let testBillRun
let testLicences

Expand All @@ -28,6 +29,7 @@ describe('Review Bill Run presenter', () => {
filterIssues = undefined
filterLicenceHolderNumber = undefined
filterLicenceStatus = undefined
filterProgress = undefined
})

it('correctly presents the data', () => {
Expand All @@ -36,6 +38,7 @@ describe('Review Bill Run presenter', () => {
filterIssues,
filterLicenceHolderNumber,
filterLicenceStatus,
filterProgress,
testLicences
)

Expand Down Expand Up @@ -79,6 +82,7 @@ describe('Review Bill Run presenter', () => {
issues: undefined,
licenceHolderNumber: undefined,
licenceStatus: undefined,
inProgress: undefined,
openFilter: false
}
})
Expand All @@ -95,6 +99,7 @@ describe('Review Bill Run presenter', () => {
filterIssues,
filterLicenceHolderNumber,
filterLicenceStatus,
filterProgress,
testLicences
)

Expand All @@ -115,6 +120,7 @@ describe('Review Bill Run presenter', () => {
filterIssues,
filterLicenceHolderNumber,
filterLicenceStatus,
filterProgress,
testLicences
)

Expand All @@ -130,6 +136,7 @@ describe('Review Bill Run presenter', () => {
filterIssues = ['abs-outside-period', 'over-abstraction']
filterLicenceHolderNumber = 'bob'
filterLicenceStatus = 'ready'
filterProgress = true
})

it('correctly presents the data', () => {
Expand All @@ -138,16 +145,20 @@ describe('Review Bill Run presenter', () => {
filterIssues,
filterLicenceHolderNumber,
filterLicenceStatus,
filterProgress,
testLicences
)

expect(result.filter.openFilter).to.equal(true)
expect(result.filter.licenceHolderNumber).to.equal(filterLicenceHolderNumber)
expect(result.filter.licenceStatus).to.equal(filterLicenceStatus)
expect(result.filter.inProgress).to.equal(filterProgress)
expect(result.filter.issues).to.equal({
absOutsidePeriod: true,
aggregateFactor: false,
checkingQuery: false,
multipleIssues: false,
noIssues: false,
noReturnsReceived: false,
overAbstraction: true,
overlapOfChargeDates: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('Determine Licence Issues Service', () => {

expect(licence.issues).to.equal([
'Abstraction outside period',
'Multiple issues',
'No returns received',
'Over abstraction',
'Returns received late',
Expand Down Expand Up @@ -52,6 +53,7 @@ describe('Determine Licence Issues Service', () => {
expect(licence.issues).to.equal([
'Aggregate',
'Checking query',
'Multiple issues',
'Overlap of charge dates',
'Return split over charge references',
'Returns received but not processed',
Expand Down Expand Up @@ -80,6 +82,7 @@ describe('Determine Licence Issues Service', () => {
'Abstraction outside period',
'Aggregate',
'Checking query',
'Multiple issues',
'No returns received',
'Over abstraction',
'Overlap of charge dates',
Expand Down
Loading

0 comments on commit 0d2f958

Please sign in to comment.