From feaeea4d24c4b328a14a4642072d71542e5b8f51 Mon Sep 17 00:00:00 2001 From: Becky Ransome <91424856+Beckyrose200@users.noreply.github.com> Date: Wed, 1 May 2024 17:12:05 +0100 Subject: [PATCH] Fix amended billable returns banner two-part tariff review (#962) During testing it was noted that the amended billable returns banner broke during a previous PR (https://github.com/DEFRA/water-abstraction-system/pull/942). It is currently always being displayed. This is because it displays the banner if the amended volume doesn't equal the source volume and since the 'calculated' column no longer exists in the db it therefore never equals each other. This change is to fix the banner to display it only when there is a change to the amended amount. --- app/controllers/bill-runs.controller.js | 4 +- .../match-details.presenter.js | 3 +- .../two-part-tariff/match-details.service.js | 9 +- ...submit-amended-billable-returns.service.js | 4 +- app/views/bill-runs/match-details.njk | 7 +- .../match-details.presenter.test.js | 1 - .../match-details.service.test.js | 85 +++++++++++++++++-- ...t-amended-billable-returns.service.test.js | 33 +++++-- 8 files changed, 122 insertions(+), 24 deletions(-) diff --git a/app/controllers/bill-runs.controller.js b/app/controllers/bill-runs.controller.js index e10f2ca9cd..484e57e374 100644 --- a/app/controllers/bill-runs.controller.js +++ b/app/controllers/bill-runs.controller.js @@ -77,7 +77,7 @@ async function index (request, h) { async function matchDetails (request, h) { const { id: billRunId, licenceId, reviewChargeElementId } = request.params - const pageData = await MatchDetailsService.go(billRunId, licenceId, reviewChargeElementId) + const pageData = await MatchDetailsService.go(billRunId, licenceId, reviewChargeElementId, request.yar) return h.view('bill-runs/match-details.njk', { pageTitle: 'View match details', @@ -124,7 +124,7 @@ async function send (request, h) { async function submitAmendedBillableReturns (request, h) { const { id: billRunId, licenceId, reviewChargeElementId } = request.params - const pageData = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElementId, request.payload) + const pageData = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElementId, request.payload, request.yar) if (pageData.error) { return h.view('bill-runs/amend-billable-returns.njk', pageData) diff --git a/app/presenters/bill-runs/two-part-tariff/match-details.presenter.js b/app/presenters/bill-runs/two-part-tariff/match-details.presenter.js index 465f997c7b..8bf9ece2e6 100644 --- a/app/presenters/bill-runs/two-part-tariff/match-details.presenter.js +++ b/app/presenters/bill-runs/two-part-tariff/match-details.presenter.js @@ -38,8 +38,7 @@ function go (billRun, reviewChargeElement, licenceId) { authorisedVolume: reviewChargeElement.chargeElement.authorisedAnnualQuantity, issues: reviewChargeElement.issues?.length > 0 ? reviewChargeElement.issues.split(', ') : [] }, - matchedReturns: _matchedReturns(reviewChargeElement.reviewReturns), - showBanner: reviewChargeElement.allocated !== reviewChargeElement.calculated + matchedReturns: _matchedReturns(reviewChargeElement.reviewReturns) } } diff --git a/app/services/bill-runs/two-part-tariff/match-details.service.js b/app/services/bill-runs/two-part-tariff/match-details.service.js index 7e5e8accb1..6d70f3b212 100644 --- a/app/services/bill-runs/two-part-tariff/match-details.service.js +++ b/app/services/bill-runs/two-part-tariff/match-details.service.js @@ -15,15 +15,20 @@ const MatchDetailsPresenter = require('../../../presenters/bill-runs/two-part-ta * @param {String} billRunId - The UUID for the bill run * @param {String} licenceId - The UUID of the licence that is being reviewed * @param {String} reviewChargeElementId - The UUID of the review charge element being viewed + * @param {Object} yar - The Hapi `request.yar` session manager passed on by the controller * * @returns {Promise} the 'pageData' needed to view the match details of an individual charge */ -async function go (billRunId, licenceId, reviewChargeElementId) { +async function go (billRunId, licenceId, reviewChargeElementId, yar) { const { billRun, reviewChargeElement } = await FetchMatchDetailsService.go(billRunId, reviewChargeElementId) + const [bannerMessage] = yar.flash('banner') const pageData = MatchDetailsPresenter.go(billRun, reviewChargeElement, licenceId) - return pageData + return { + bannerMessage, + ...pageData + } } module.exports = { diff --git a/app/services/bill-runs/two-part-tariff/submit-amended-billable-returns.service.js b/app/services/bill-runs/two-part-tariff/submit-amended-billable-returns.service.js index df3c2c95be..12d213bb19 100644 --- a/app/services/bill-runs/two-part-tariff/submit-amended-billable-returns.service.js +++ b/app/services/bill-runs/two-part-tariff/submit-amended-billable-returns.service.js @@ -17,14 +17,16 @@ const ReviewChargeElementModel = require('../../../models/review-charge-element. * @param {String} licenceId - The UUID of the licence that is being reviewed * @param {String} reviewChargeElementId - The UUID of the review charge element being updated * @param {Object} payload - The submitted form data + * @param {Object} yar - The Hapi `request.yar` session manager passed on by the controller * * @returns {Promise} The updated value for the billable returns */ -async function go (billRunId, licenceId, reviewChargeElementId, payload) { +async function go (billRunId, licenceId, reviewChargeElementId, payload, yar) { const validationResult = _validate(payload) if (!validationResult) { await _persistAmendedBillableReturns(reviewChargeElementId, payload) + yar.flash('banner', 'The billable returns for this licence have been updated') return { error: null } } diff --git a/app/views/bill-runs/match-details.njk b/app/views/bill-runs/match-details.njk index c25f08c9aa..f5bf041af2 100644 --- a/app/views/bill-runs/match-details.njk +++ b/app/views/bill-runs/match-details.njk @@ -16,10 +16,11 @@ {% endblock %} {% block content %} - {% if showBanner %} + {# Billable returns ammended banner #} + {% if bannerMessage %} {{ govukNotificationBanner({ - text: "The billable returns for this licence have been updated", - titleText: "Element updated" + titleText: 'Element updated', + text: bannerMessage }) }} {% endif %} diff --git a/test/presenters/bill-runs/two-part-tariff/match-details.presenter.test.js b/test/presenters/bill-runs/two-part-tariff/match-details.presenter.test.js index b7ba8f809d..371f527c9d 100644 --- a/test/presenters/bill-runs/two-part-tariff/match-details.presenter.test.js +++ b/test/presenters/bill-runs/two-part-tariff/match-details.presenter.test.js @@ -24,7 +24,6 @@ describe('Match Details presenter', () => { financialYear: '2022 to 2023', chargePeriod: '1 April 2022 to 5 June 2022', licenceId: '5aa8e752-1a5c-4b01-9112-d92a543b70d1', - showBanner: true, chargeElement: { chargeElementId: 'b4d70c89-de1b-4f68-a47f-832b338ac044', description: 'Trickle Irrigation - Direct', diff --git a/test/services/bill-runs/two-part-tariff/match-details.service.test.js b/test/services/bill-runs/two-part-tariff/match-details.service.test.js index 621bb1092e..62725ee02e 100644 --- a/test/services/bill-runs/two-part-tariff/match-details.service.test.js +++ b/test/services/bill-runs/two-part-tariff/match-details.service.test.js @@ -10,7 +10,6 @@ const { expect } = Code // Things we need to stub const FetchMatchDetailsService = require('../../../../app/services/bill-runs/two-part-tariff/fetch-match-details.service.js') -const MatchDetailsPresenter = require('../../../../app/presenters/bill-runs/two-part-tariff/match-details.presenter.js') // Thing under test const MatchDetailsService = require('../../../../app/services/bill-runs/two-part-tariff/match-details.service.js') @@ -25,21 +24,93 @@ describe('Match Details Service', () => { const billRunId = 'cc4bbb18-0d6a-4254-ac2c-7409de814d7e' const licenceId = '9a8a148d-b71e-463c-bea8-bc5e0a5d95e2' + let yarStub + beforeEach(() => { Sinon.stub(FetchMatchDetailsService, 'go').resolves({ - billRun: 'bill run data', - reviewChargeElement: 'charge element details' + billRun: _billRun(), + reviewChargeElement: _reviewChargeElementData() }) - Sinon.stub(MatchDetailsPresenter, 'go').resolves('page data') + yarStub = { flash: Sinon.stub().returns(['The billable returns for this licence have been updated']) } }) it('will fetch the charge element data and return it once formatted by the presenter', async () => { - const result = await MatchDetailsService.go(billRunId, licenceId, reviewChargeElementId) + const result = await MatchDetailsService.go(billRunId, licenceId, reviewChargeElementId, yarStub) + + expect(result.bannerMessage).to.equal('The billable returns for this licence have been updated') + + // NOTE: The service mainly just regurgitates what the MatchDetailsPresenter returns. So, we don't diligently + // check each property of the result because we know this will have been covered by the MatchDetailsPresenter expect(FetchMatchDetailsService.go.called).to.be.true() - expect(MatchDetailsPresenter.go.called).to.be.true() - expect(result).to.equal('page data') + expect(result.billRunId).to.equal('6620135b-0ecf-4fd4-924e-371f950c0526') + expect(result.licenceId).to.equal('9a8a148d-b71e-463c-bea8-bc5e0a5d95e2') + expect(result.chargeElement.chargeElementId).to.equal('b4d70c89-de1b-4f68-a47f-832b338ac044') + expect(result.chargeElement.billableVolume).to.equal(0) }) }) }) + +function _billRun () { + return { + id: '6620135b-0ecf-4fd4-924e-371f950c0526', + fromFinancialYearEnding: 2023, + toFinancialYearEnding: 2023 + } +} + +function _reviewChargeElementData () { + return { + id: 'b4d70c89-de1b-4f68-a47f-832b338ac044', + reviewChargeReferenceId: '9e5d87d7-073e-420e-b12d-73ca220dd8ef', + chargeElementId: 'b345f1f1-496b-4049-a647-6bcd123dcf68', + allocated: 10, + amendedAllocated: 0, + chargeDatesOverlap: false, + issues: null, + status: 'ready', + createdAt: new Date('2024-04-02'), + updatedAt: new Date('2024-04-02'), + reviewReturns: [ + { + id: 'c4cdbfa9-4528-4776-b62f-fa667b797717', + reviewLicenceId: '674ffa02-51be-4caa-b25e-cc1fea1ac057', + returnId: 'v1:1:01/57/14/1646:15584914:2022-04-01:2023-03-31', + returnReference: '10031343', + quantity: 0, + allocated: 0, + underQuery: false, + returnStatus: 'completed', + nilReturn: false, + abstractionOutsidePeriod: false, + receivedDate: new Date('2022-06-03'), + dueDate: new Date('2022-06-03'), + purposes: [{ + tertiary: { code: '400', description: 'Spray Irrigation - Direct' } + }], + description: 'Lands at Mosshayne Farm, Exeter & Broadclyst', + startDate: new Date('2022-04-01'), + endDate: new Date('2022-05-06'), + issues: null, + createdAt: new Date('2024-04-02'), + updatedAt: new Date('2024-04-02') + } + ], + chargeElement: { + description: 'Trickle Irrigation - Direct', + abstractionPeriodStartDay: 1, + abstractionPeriodStartMonth: 4, + abstractionPeriodEndDay: 31, + abstractionPeriodEndMonth: 3, + authorisedAnnualQuantity: 200 + }, + reviewChargeReference: { + id: '9e5d87d7-073e-420e-b12d-73ca220dd8ef', + reviewChargeVersion: { + chargePeriodStartDate: new Date('2022-04-01'), + chargePeriodEndDate: new Date('2022-06-05') + } + } + } +} diff --git a/test/services/bill-runs/two-part-tariff/submit-amended-billable-returns.service.test.js b/test/services/bill-runs/two-part-tariff/submit-amended-billable-returns.service.test.js index 4ebcfe2ffc..0d93d45cd8 100644 --- a/test/services/bill-runs/two-part-tariff/submit-amended-billable-returns.service.test.js +++ b/test/services/bill-runs/two-part-tariff/submit-amended-billable-returns.service.test.js @@ -25,10 +25,13 @@ describe('Submit Amended Billable Returns Service', () => { const licenceId = '9a8a148d-b71e-463c-bea8-bc5e0a5d95e2' let payload let reviewChargeElement + let yarStub beforeEach(async () => { await DatabaseSupport.clean() + yarStub = { flash: Sinon.stub() } + reviewChargeElement = await ReviewChargeElementHelper.add() }) @@ -46,12 +49,21 @@ describe('Submit Amended Billable Returns Service', () => { }) it('saves the submitted option', async () => { - await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload) + await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload, yarStub) const reviewChargeElementData = await _fetchReviewChargeElement(reviewChargeElement.id) expect(reviewChargeElementData.amendedAllocated).to.equal(10) }) + + it("sets the banner message to 'The billable returns for this licence have been updated'", async () => { + await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload, yarStub) + + const [flashType, bannerMessage] = yarStub.flash.args[0] + + expect(flashType).to.equal('banner') + expect(bannerMessage).to.equal('The billable returns for this licence have been updated') + }) }) describe('with a valid payload for customQuantity', () => { @@ -64,12 +76,21 @@ describe('Submit Amended Billable Returns Service', () => { }) it('saves the submitted value', async () => { - await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload) + await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload, yarStub) const reviewChargeElementData = await _fetchReviewChargeElement(reviewChargeElement.id) expect(reviewChargeElementData.amendedAllocated).to.equal(20) }) + + it("sets the banner message to 'The billable returns for this licence have been updated'", async () => { + await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload, yarStub) + + const [flashType, bannerMessage] = yarStub.flash.args[0] + + expect(flashType).to.equal('banner') + expect(bannerMessage).to.equal('The billable returns for this licence have been updated') + }) }) describe('with an invalid payload', () => { @@ -85,7 +106,7 @@ describe('Submit Amended Billable Returns Service', () => { }) it('returns the page data for the view', async () => { - const result = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload) + const result = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload, yarStub) expect(result).to.equal({ activeNavBar: 'search', @@ -110,7 +131,7 @@ describe('Submit Amended Billable Returns Service', () => { }) it('returns page data with an error for the radio form element', async () => { - const result = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload) + const result = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload, yarStub) expect(result.error).to.equal({ message: 'Select the billable quantity', @@ -130,7 +151,7 @@ describe('Submit Amended Billable Returns Service', () => { }) it('returns the page data for the view', async () => { - const result = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload) + const result = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload, yarStub) expect(result).to.equal({ activeNavBar: 'search', @@ -155,7 +176,7 @@ describe('Submit Amended Billable Returns Service', () => { }) it('returns page data with an error for the custom quantity input form element', async () => { - const result = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload) + const result = await SubmitAmendedBillableReturnsService.go(billRunId, licenceId, reviewChargeElement.id, payload, yarStub) expect(result.error).to.equal({ message: 'The quantity must be a number',