From 286264d0625061a872e5c8dabd04c8dc61a09d24 Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Wed, 22 Nov 2023 23:04:32 +0000 Subject: [PATCH 1/2] Add new view bill run presenter https://eaflood.atlassian.net/browse/WATER-4223 This presenter has been added to format the bill run data 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 top level information returned by `FetchBillRunService`. --- .../bill-runs/view-bill-run.presenter.js | 135 ++++++++ .../bill-runs/view-bill-run.presenter.test.js | 306 ++++++++++++++++++ 2 files changed, 441 insertions(+) create mode 100644 app/presenters/bill-runs/view-bill-run.presenter.js create mode 100644 test/presenters/bill-runs/view-bill-run.presenter.test.js diff --git a/app/presenters/bill-runs/view-bill-run.presenter.js b/app/presenters/bill-runs/view-bill-run.presenter.js new file mode 100644 index 0000000000..8f6015ffad --- /dev/null +++ b/app/presenters/bill-runs/view-bill-run.presenter.js @@ -0,0 +1,135 @@ +'use strict' + +/** + * Formats bill run data ready for presenting in the view bill run page + * @module ViewBillRunPresenter + */ + +const { + capitalize, + formatLongDate, + formatMoney +} = require('../base.presenter.js') + +function go (billRun) { + const { + batchType, + billingBatchId, + billRunNumber, + createdAt, + creditNoteCount, + creditNoteValue, + invoiceCount, + invoiceValue, + isSummer, + netTotal, + region, + scheme, + status, + transactionFileReference, + toFinancialYearEnding + } = billRun + + const billRunType = _billRunType(batchType, isSummer, scheme) + const regionName = capitalize(region.displayName) + + return { + billsCount: _billsCount(creditNoteCount, invoiceCount, billRunType), + billRunId: billingBatchId, + billRunNumber, + billRunStatus: status, + billRunTotal: _billRunTotal(netTotal), + billRunType, + chargeScheme: _chargeScheme(scheme), + creditsCount: _creditsCount(creditNoteCount), + creditsTotal: formatMoney(creditNoteValue), + dateCreated: formatLongDate(createdAt), + debitsCount: _debitsCount(invoiceCount), + debitsTotal: formatMoney(invoiceValue), + displayCreditDebitTotals: _displayCreditDebitTotals(billRun), + financialYear: _financialYear(toFinancialYearEnding), + pageTitle: _pageTitle(regionName, billRunType), + region: regionName, + transactionFile: transactionFileReference + } +} + +function _billsCount (creditsCount, debitsCount, billRunType) { + const total = creditsCount + debitsCount + + if (total === 1) { + return `1 ${billRunType} bill` + } + + return `${total} ${billRunType} bills` +} + +function _billRunTotal (valueInPence) { + const valueAsMoney = formatMoney(valueInPence) + + if (valueInPence < 0) { + return `${valueAsMoney} credit` + } + + return valueAsMoney +} + +function _billRunType (batchType, isSummer, scheme) { + if (batchType !== 'two_part_tariff') { + return capitalize(batchType) + } + + if (scheme === 'sroc') { + return 'Two-part tariff' + } + + if (isSummer) { + return 'Two-part tariff summer' + } + + return 'Two-part tariff winter and all year' +} + +function _chargeScheme (scheme) { + if (scheme === 'sroc') { + return 'Current' + } + + return 'Old' +} + +function _creditsCount (count) { + if (count === 1) { + return '1 credit note' + } + + return `${count} credit notes` +} + +function _debitsCount (count) { + if (count === 1) { + return '1 invoice' + } + + return `${count} invoices` +} + +function _displayCreditDebitTotals (billRun) { + const { batchType } = billRun + + return batchType === 'supplementary' +} + +function _financialYear (financialYearEnding) { + return `${financialYearEnding - 1} to ${financialYearEnding}` +} + +function _pageTitle (regionName, billRunType) { + const lowercaseBillRunType = billRunType.toLowerCase() + + return `${regionName} ${lowercaseBillRunType}` +} + +module.exports = { + go +} diff --git a/test/presenters/bill-runs/view-bill-run.presenter.test.js b/test/presenters/bill-runs/view-bill-run.presenter.test.js new file mode 100644 index 0000000000..d27b77c42c --- /dev/null +++ b/test/presenters/bill-runs/view-bill-run.presenter.test.js @@ -0,0 +1,306 @@ +'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 ViewBillRunPresenter = require('../../../app/presenters/billing/view-bill-run.presenter.js') + +describe('View Bill Run presenter', () => { + let billRun + + describe('when provided with a populated bill run', () => { + beforeEach(() => { + billRun = _testBillRun() + }) + + it('correctly presents the data', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result).to.equal({ + billsCount: '8 Supplementary bills', + billRunId: '420e948f-1992-437e-8a47-74c0066cb017', + billRunNumber: 10010, + billRunStatus: 'sent', + billRunTotal: '£707.00', + billRunType: 'Supplementary', + chargeScheme: 'Current', + creditsCount: '2 credit notes', + creditsTotal: '£1,992.78', + dateCreated: '1 November 2023', + debitsCount: '6 invoices', + debitsTotal: '£2,699.78', + displayCreditDebitTotals: true, + financialYear: '2023 to 2024', + pageTitle: 'Wales supplementary', + region: 'Wales', + transactionFile: 'nalwi50002t' + }) + }) + + describe("the 'billsCount' property", () => { + describe('when the sum of the invoice and credit count is 1', () => { + beforeEach(() => { + billRun.creditNoteCount = 0 + billRun.invoiceCount = 1 + }) + + it('returns to sum plus the bill run type as singular (1 Supplementary bill)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billsCount).to.equal('1 Supplementary bill') + }) + }) + + describe('when the sum of the invoice and credit count is more than 1', () => { + beforeEach(() => { + billRun.batchType = 'annual' + billRun.creditNoteCount = 5 + billRun.invoiceCount = 7 + }) + + it('returns to sum plus the bill run type pluralised (12 Annual bills)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billsCount).to.equal('12 Annual bills') + }) + }) + }) + + describe("the 'billRunTotal' property", () => { + describe('when the net total is greater than 0', () => { + it('returns the value converted to pounds, formatted as money and showing as a debit (£707.00)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billRunTotal).to.equal('£707.00') + }) + }) + + describe('when the net total is zero', () => { + beforeEach(() => { + billRun.netTotal = 0 + }) + + it('returns the value converted to pounds, formatted as money and showing as a debit (£0.00)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billRunTotal).to.equal('£0.00') + }) + }) + + describe('when the net total is less than zero', () => { + beforeEach(() => { + billRun.netTotal = -70700 + }) + + it('returns the value converted to pounds, formatted as money and showing as a credit (£707.00 credit)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billRunTotal).to.equal('£707.00 credit') + }) + }) + }) + + describe("the 'billRunType' property", () => { + describe('when the bill run is annual', () => { + beforeEach(() => { + billRun.batchType = 'annual' + }) + + it('returns Annual', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billRunType).to.equal('Annual') + }) + }) + + describe('when the bill run is supplementary', () => { + it('returns Supplementary', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billRunType).to.equal('Supplementary') + }) + }) + + describe('when the bill run is two_part_tariff', () => { + beforeEach(() => { + billRun.batchType = 'two_part_tariff' + }) + + describe('and the scheme is sroc', () => { + it('returns Supplementary', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billRunType).to.equal('Two-part tariff') + }) + }) + + describe('and the scheme is alcs', () => { + beforeEach(() => { + billRun.scheme = 'alcs' + }) + + describe('and it is not summer only', () => { + it('returns Supplementary', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billRunType).to.equal('Two-part tariff winter and all year') + }) + }) + + describe('and it is for summer only', () => { + beforeEach(() => { + billRun.isSummer = true + }) + + it('returns Supplementary', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.billRunType).to.equal('Two-part tariff summer') + }) + }) + }) + }) + }) + + describe("the 'chargeScheme' property", () => { + describe('when the bill run is sroc', () => { + it('returns Current', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.chargeScheme).to.equal('Current') + }) + }) + + describe('when the bill run is alcs', () => { + beforeEach(() => { + billRun.scheme = 'alcs' + }) + + it('returns Old', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.chargeScheme).to.equal('Old') + }) + }) + }) + + describe("the 'creditsCount' property", () => { + describe('when there is only 1 credit note', () => { + beforeEach(() => { + billRun.creditNoteCount = 1 + }) + + it('returns the count singular (1 credit note)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.creditsCount).to.equal('1 credit note') + }) + }) + + describe('when there are multiple credit notes', () => { + it('returns the count pluralised (2 credit notes)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.creditsCount).to.equal('2 credit notes') + }) + }) + }) + + describe("the 'debitsCount' property", () => { + describe('when there is only 1 invoice', () => { + beforeEach(() => { + billRun.invoiceCount = 1 + }) + + it('returns the count singular (1 invoice)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.debitsCount).to.equal('1 invoice') + }) + }) + + describe('when there are multiple invoices', () => { + it('returns the count pluralised (6 invoices)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.debitsCount).to.equal('6 invoices') + }) + }) + }) + + describe("the 'displayCreditDebitTotals' property", () => { + describe('when the bill run is not supplementary', () => { + beforeEach(() => { + billRun.batchType = 'annual' + }) + + it('returns false', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.displayCreditDebitTotals).to.be.false() + }) + }) + + describe('when the bill run is supplementary', () => { + it('returns true', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.displayCreditDebitTotals).to.be.true() + }) + }) + }) + + describe("the 'financialYear' property", () => { + it('returns the to and from financial year (2023 to 2024)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.financialYear).to.equal('2023 to 2024') + }) + }) + + describe("the 'pageTitle' property", () => { + it('returns the region name and bill run type (Wales supplementary)', () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.pageTitle).to.equal('Wales supplementary') + }) + }) + + describe("the 'region' property", () => { + it("returns the bill run's region display name capitalized (Wales)", () => { + const result = ViewBillRunPresenter.go(billRun) + + expect(result.region).to.equal('Wales') + }) + }) + }) +}) + +function _testBillRun () { + return { + billingBatchId: '420e948f-1992-437e-8a47-74c0066cb017', + batchType: 'supplementary', + billRunNumber: 10010, + creditNoteCount: 2, + creditNoteValue: -199278, + invoiceCount: 6, + invoiceValue: 269978, + isSummer: false, + netTotal: 70700, + scheme: 'sroc', + source: 'wrls', + status: 'sent', + toFinancialYearEnding: 2024, + transactionFileReference: 'nalwi50002t', + createdAt: new Date('2023-11-01'), + region: { + regionId: 'f6c4699f-9a80-419a-82e7-f785ece727e1', + displayName: 'Wales' + } + } +} From b3b1d75f7be1230c0831592b9b55ce1a17fac4a9 Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Wed, 22 Nov 2023 23:16:46 +0000 Subject: [PATCH 2/2] Doh! --- test/presenters/bill-runs/view-bill-run.presenter.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/presenters/bill-runs/view-bill-run.presenter.test.js b/test/presenters/bill-runs/view-bill-run.presenter.test.js index d27b77c42c..102c667580 100644 --- a/test/presenters/bill-runs/view-bill-run.presenter.test.js +++ b/test/presenters/bill-runs/view-bill-run.presenter.test.js @@ -8,7 +8,7 @@ const { describe, it, beforeEach } = exports.lab = Lab.script() const { expect } = Code // Thing under test -const ViewBillRunPresenter = require('../../../app/presenters/billing/view-bill-run.presenter.js') +const ViewBillRunPresenter = require('../../../app/presenters/bill-runs/view-bill-run.presenter.js') describe('View Bill Run presenter', () => { let billRun