diff --git a/app/services/supplementary-billing/check-live-bill-run.service.js b/app/services/supplementary-billing/check-live-bill-run.service.js new file mode 100644 index 0000000000..671a56edd0 --- /dev/null +++ b/app/services/supplementary-billing/check-live-bill-run.service.js @@ -0,0 +1,39 @@ +'use strict' + +/** + * Checks whether a "live" bill run exists for the specified region, scheme, type and financial year + * @module CheckLiveBillRunService + */ + +const BillingBatchModel = require('../../models/water/billing-batch.model.js') + +const LIVE_STATUSES = ['processing', 'ready', 'review', 'queued'] + +/** + * Check whether a "live" bill run exists for the specified region, scheme, type and financial year + * + * We define "live" as having the status `processing`, `ready`, `review` or `queued` + * + * @param {*} regionId The id of the region to be checked + * @param {*} financialYear The financial year to be checked + * + * @returns {Boolean} Whether a "live" bill run exists + */ +async function go (regionId, financialYear) { + const numberOfLiveBillRuns = await BillingBatchModel.query() + .select('billing_batch_id') + .where({ + regionId, + toFinancialYearEnding: financialYear, + scheme: 'sroc', + batchType: 'supplementary' + }) + .whereIn('status', LIVE_STATUSES) + .resultSize() + + return numberOfLiveBillRuns !== 0 +} + +module.exports = { + go +} diff --git a/app/services/supplementary-billing/initiate-billing-batch.service.js b/app/services/supplementary-billing/initiate-billing-batch.service.js index ac1a613d66..cba3394c97 100644 --- a/app/services/supplementary-billing/initiate-billing-batch.service.js +++ b/app/services/supplementary-billing/initiate-billing-batch.service.js @@ -7,6 +7,7 @@ const BillingPeriodService = require('./billing-period.service.js') const ChargingModuleCreateBillRunService = require('../charging-module/create-bill-run.service.js') +const CheckLiveBillRunService = require('./check-live-bill-run.service.js') const CreateBillingBatchPresenter = require('../../presenters/supplementary-billing/create-billing-batch.presenter.js') const CreateBillingBatchService = require('./create-billing-batch.service.js') const CreateBillingBatchEventService = require('./create-billing-batch-event.service.js') @@ -28,6 +29,13 @@ async function go (billRunRequestData) { const { region, scheme, type, user } = billRunRequestData + const financialYear = billingPeriod.endDate.getFullYear() + const liveBillRunExists = await CheckLiveBillRunService.go(region, financialYear) + + if (liveBillRunExists) { + throw Error(`Batch already live for region ${region}`) + } + const chargingModuleBillRun = await ChargingModuleCreateBillRunService.go(region, 'sroc') // A failed response will be due to a failed `RequestLib` request so format an error message accordingly and throw it diff --git a/test/services/supplementary-billing/check-live-bill-run.service.test.js b/test/services/supplementary-billing/check-live-bill-run.service.test.js new file mode 100644 index 0000000000..0b5859c744 --- /dev/null +++ b/test/services/supplementary-billing/check-live-bill-run.service.test.js @@ -0,0 +1,61 @@ +'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 + +// Test helpers +const BillingBatchHelper = require('../../support/helpers/water/billing-batch.helper.js') +const DatabaseHelper = require('../../support/helpers/database.helper.js') + +// Thing under test +const CheckLiveBillRunService = require('../../../app/services/supplementary-billing/check-live-bill-run.service.js') + +describe('Check Live Bill Run service', () => { + let billRun + + beforeEach(async () => { + await DatabaseHelper.clean() + }) + + describe('when an sroc supplementary bill run exists for this region and financial year', () => { + describe('with a status considered to be "live"', () => { + beforeEach(async () => { + billRun = await BillingBatchHelper.add() + }) + + it('returns `true`', async () => { + const result = await CheckLiveBillRunService.go(billRun.regionId, 2023) + + expect(result).to.be.true() + }) + }) + + describe('with a status not considered to be "live"', () => { + beforeEach(async () => { + billRun = await BillingBatchHelper.add({ status: 'sent' }) + }) + + it('returns `false`', async () => { + const result = await CheckLiveBillRunService.go(billRun.regionId, 2023) + + expect(result).to.be.false() + }) + }) + }) + + describe('when an sroc supplementary bill run does not exist for this region and financial year', () => { + beforeEach(async () => { + billRun = await BillingBatchHelper.add({ fromFinancialYearEnding: 2024, toFinancialYearEnding: 2024 }) + }) + + it('returns `false`', async () => { + const result = await CheckLiveBillRunService.go(billRun.regionId, 2023) + + expect(result).to.be.false() + }) + }) +}) diff --git a/test/services/supplementary-billing/initiate-billing-batch.service.test.js b/test/services/supplementary-billing/initiate-billing-batch.service.test.js index 708cc0a2c6..f38212f6d2 100644 --- a/test/services/supplementary-billing/initiate-billing-batch.service.test.js +++ b/test/services/supplementary-billing/initiate-billing-batch.service.test.js @@ -17,6 +17,7 @@ const RegionHelper = require('../../support/helpers/water/region.helper.js') // Things we need to stub const BillingPeriodService = require('../../../app/services/supplementary-billing/billing-period.service.js') const ChargingModuleCreateBillRunService = require('../../../app/services/charging-module/create-bill-run.service.js') +const CheckLiveBillRunService = require('../../../app/services/supplementary-billing/check-live-bill-run.service.js') // Thing under test const InitiateBillingBatchService = require('../../../app//services/supplementary-billing/initiate-billing-batch.service.js') @@ -40,6 +41,7 @@ describe('Initiate Billing Batch service', () => { } Sinon.stub(BillingPeriodService, 'go').returns([currentBillingPeriod]) + Sinon.stub(CheckLiveBillRunService, 'go').resolves(false) }) afterEach(() => { @@ -107,7 +109,20 @@ describe('Initiate Billing Batch service', () => { }) }) - describe('and the error doesn\'t include a messge', () => { + describe('because a bill run already exists for this region and financial year', () => { + beforeEach(() => { + CheckLiveBillRunService.go.resolves(true) + }) + + it('rejects with an appropriate error', async () => { + const err = await expect(InitiateBillingBatchService.go(validatedRequestData)).to.reject() + + expect(err).to.be.an.error() + expect(err.message).to.equal(`Batch already live for region ${validatedRequestData.region}`) + }) + }) + + describe('and the error doesn\'t include a message', () => { beforeEach(() => { Sinon.stub(ChargingModuleCreateBillRunService, 'go').resolves({ succeeded: false,