Skip to content

Commit

Permalink
Add new bill summaries presenter (#542)
Browse files Browse the repository at this point in the history
https://eaflood.atlassian.net/browse/WATER-4223

This presenter has been added to format the summarised data for each bill linked to a selected bill run. The data will be used in a new bill run page that will replace the existing one in the legacy service.

The page displays top-level details about the bill run (date created type, region etc) and then a summary for each bill linked to the bill run. This presenter handles the bill summary information returned by `FetchBillRunService`.

If a bill run contains bills linked to both water companies and other abstractors it will display them in 2 separate tables. If only one type of bill is present just a single table is shown. This is why the presenter takes the bills and groups them. The Nunjucks template will then decide whether to show just one table or both with captions based on how many groups this presenter returns.
  • Loading branch information
Cruikshanks authored Dec 16, 2023
1 parent 4d0b401 commit 5858831
Show file tree
Hide file tree
Showing 2 changed files with 312 additions and 0 deletions.
97 changes: 97 additions & 0 deletions app/presenters/bill-runs/view-bill-summaries.presenter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
'use strict'

/**
* Formats summary data of bills connected to a bill run for the bill run summary page
* @module ViewBillSummariesPresenter
*/

const { formatMoney } = require('../base.presenter.js')

function go (billSummaries) {
const waterCompanies = _waterCompanies(billSummaries)
const otherAbstractors = _otherAbstractors(billSummaries)

const billGroups = []

if (waterCompanies.length > 0) {
billGroups.push({
type: 'water-companies',
caption: _caption(waterCompanies, true),
bills: waterCompanies
})
}

if (otherAbstractors.length > 0) {
billGroups.push({
type: 'other-abstractors',
caption: _caption(otherAbstractors, false),
bills: otherAbstractors
})
}

return billGroups
}

function _bills (summaries) {
return summaries.map((summary) => {
const {
agentName,
allLicences,
id,
companyName,
financialYearEnding,
accountNumber,
netAmount
} = summary

const licences = allLicences.split(',')

return {
id,
accountNumber,
billingContact: _billingContact(agentName, companyName),
licences,
licencesCount: licences.length,
financialYear: financialYearEnding,
total: formatMoney(netAmount, true)
}
})
}

function _billingContact (agentName, companyName) {
if (agentName) {
return agentName
}

return companyName
}

function _caption (bills, isWaterCompany) {
const numberOfRows = bills.length

if (numberOfRows === 1) {
return isWaterCompany ? '1 water company' : '1 other abstractor'
}

return isWaterCompany ? `${numberOfRows} water companies` : `${numberOfRows} other abstractors`
}

function _otherAbstractors (summaries) {
const filteredSummaries = summaries.filter((summary) => {
return !summary.waterCompany
})

return _bills(filteredSummaries)
}

function _waterCompanies (summaries) {
const filteredSummaries = summaries.filter((summary) => {
return summary.waterCompany
})

return _bills(filteredSummaries)
}

module.exports = {
go
}
215 changes: 215 additions & 0 deletions test/presenters/bill-runs/view-bill-summaries.presenter.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
'use strict'

// Test framework dependencies
const Lab = require('@hapi/lab')
const Code = require('@hapi/code')

const { describe, it, beforeEach } = exports.lab = Lab.script()
const { expect } = Code

// Thing under test
const ViewBillSummariesPresenter = require('../../../app/presenters/bill-runs/view-bill-summaries.presenter.js')

describe('View Bill Summaries presenter', () => {
let billSummaries

describe('when provided with a populated licence summaries', () => {
beforeEach(() => {
billSummaries = _testBillSummaries()
})

it('correctly presents the data', () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result).to.equal([
{
type: 'water-companies',
caption: '1 water company',
bills: [
{
id: '64924759-8142-4a08-9d1e-1e902cd9d316',
accountNumber: 'E22288888A',
billingContact: 'Acme Water Services Ltd',
licences: ['17/53/001/A/101', '17/53/002/B/205', '17/53/002/C/308'],
licencesCount: 3,
financialYear: 2023,
total: '£213,178.00'
}
]
},
{
type: 'other-abstractors',
caption: '2 other abstractors',
bills: [
{
id: '7c8a248c-b71e-463c-bea8-bc5e0a5d95e2',
accountNumber: 'E11101999A',
billingContact: 'Geordie Leforge',
licences: ['17/53/001/G/782'],
licencesCount: 1,
financialYear: 2023,
total: '-£97.00'
},
{
id: '88f85abd-129d-4fb6-b82e-b92224992b1d',
accountNumber: 'E33397999A',
billingContact: 'Flint & Michigan Squash Club Ltd',
licences: ['17/53/001/Z/459'],
licencesCount: 1,
financialYear: 2023,
total: '£79.09'
}
]
}
])
})

describe('when all the summaries are for water companies', () => {
beforeEach(() => {
billSummaries.forEach((summary) => {
summary.waterCompany = true
})
})

it('returns just the water companies group', () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result).to.have.length(1)
expect(result[0].type).to.equal('water-companies')
})
})

describe('when all the summaries are for other abstractors', () => {
beforeEach(() => {
billSummaries.forEach((summary) => {
summary.waterCompany = false
})
})

it('returns just the other abstractors group', () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result).to.have.length(1)
expect(result[0].type).to.equal('other-abstractors')
})
})

describe('when there are both water company and other abstractor bills', () => {
// NOTE: The template iterates through the groups and builds the tables. When both groups are present we want
// the water companies table first which is why the order of the groups is important.
it('the first group is always the water companies and the second the other abstractors', () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result).to.have.length(2)
expect(result[0].type).to.equal('water-companies')
expect(result[1].type).to.equal('other-abstractors')
})
})

describe("the group 'caption' property", () => {
describe('when there is only 1 water bill summary', () => {
it("the group's caption is singular (1 water company)", () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result[0].caption).to.equal('1 water company')
})
})

describe('when there are multiple water bill summaries', () => {
beforeEach(() => {
billSummaries[0].waterCompany = true
})

it("the group's caption is pluralised (2 water companies)", () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result[0].caption).to.equal('2 water companies')
})
})

describe('when there is only 1 other abstractor bill summary', () => {
beforeEach(() => {
billSummaries[0].waterCompany = true
})

it("the group's caption is singular (1 other abstractor)", () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result[1].caption).to.equal('1 other abstractor')
})
})

describe('when there are multiple other abstractor bill summaries', () => {
it("the group's caption is pluralised (2 other abstractors)", () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result[1].caption).to.equal('2 other abstractors')
})
})
})

describe("the bill 'billingContact' property", () => {
describe('when the bill does have an agent company name', () => {
it('returns the agent company name', () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result[1].bills[0].billingContact).to.equal('Geordie Leforge')
})
})

describe('when the bill does not have an agent company name', () => {
it('returns the company name', () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result[1].bills[1].billingContact).to.equal('Flint & Michigan Squash Club Ltd')
})
})
})

describe("the bill 'licences' property", () => {
it('splits the licenses provided by , and places the resulting references into an array', () => {
const result = ViewBillSummariesPresenter.go(billSummaries)

expect(result[0].bills[0].licences).to.equal(['17/53/001/A/101', '17/53/002/B/205', '17/53/002/C/308'])
})
})
})
})

function _testBillSummaries () {
return [
{
id: '7c8a248c-b71e-463c-bea8-bc5e0a5d95e2',
billingAccountId: 'e8bd9fe1-47eb-42f2-a507-786bccd35aee',
accountNumber: 'E11101999A',
netAmount: -9700,
financialYearEnding: 2023,
companyName: 'H M Scotty & Daughter',
agentName: 'Geordie Leforge',
allLicences: '17/53/001/G/782',
waterCompany: false
},
{
id: '64924759-8142-4a08-9d1e-1e902cd9d316',
billingAccountId: 'ee3f5562-26ad-4d58-9b59-5c388a13d7d0',
accountNumber: 'E22288888A',
netAmount: 21317800,
financialYearEnding: 2023,
companyName: 'Acme Water Services Ltd',
agentName: null,
allLicences: '17/53/001/A/101,17/53/002/B/205,17/53/002/C/308',
waterCompany: true
},
{
id: '88f85abd-129d-4fb6-b82e-b92224992b1d',
billingAccountId: '5313ce61-0f35-4e37-b8b9-a1b4f408f32e',
accountNumber: 'E33397999A',
netAmount: 7909,
financialYearEnding: 2023,
companyName: 'Flint & Michigan Squash Club Ltd',
agentName: null,
allLicences: '17/53/001/Z/459',
waterCompany: false
}
]
}

0 comments on commit 5858831

Please sign in to comment.