Skip to content

Commit

Permalink
Flag licences removed from workflow for supp billing (#1388)
Browse files Browse the repository at this point in the history
https://eaflood.atlassian.net/browse/WATER-4137

As part of the work to flag licences for the new two-part tariff supplementary billing, we need to be able to flag licences that are removed from the workflow. If a licence is in workflow it does not get picked up for annual billing. This means if the licence is removed without any new charge information added, then we risk the licence not being billed for the year. During the deletion of the workflow record, the UI repo now makes a call to our supplementary endpoint to allow the system to flag the licence. This change adds an additional service to our ProcessBillingFlagsService, that can take the workflowId and work out if the licence needs to be flagged for two-part tariff supplementary billing.
  • Loading branch information
Beckyrose200 authored Oct 21, 2024
1 parent 4c62291 commit 461cb3c
Show file tree
Hide file tree
Showing 6 changed files with 431 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict'

/**
* Determines if a licence being removed from workflow should be flagged for supplementary billing
* @module DetermineWorkflowYearsService
*/

const FetchLicenceService = require('./fetch-licence.service.js')
const { determineCurrentFinancialYear } = require('../../../lib/general.lib.js')
const LicenceModel = require('../../../models/licence.model.js')

/**
* Determines if a licence being removed from workflow should be flagged for supplementary billing and two-part tariff
* supplementary billing.
*
* The service is passed the id of a workflow record and determines if it should be flagged for any supplementary
* billing. This is worked out based on the licences charge information data. If the licence has any charge versions
* that are sroc we can flag it for supplementary billing and two-part tariff then we set flagForBilling to true.
*
* The flags are then passed back to the service this was called from, where it works out which years the two-part
* tariff flags should be put on.
*
* @param {string} workflowId - The UUID for the workflow record to fetch
*
* @returns {object} - An object containing the related licence, charge information start and end date and if the
* licence should be flagged for two-part tariff supplementary billing
*/
async function go (workflowId) {
const licence = await FetchLicenceService.go(workflowId)
const { endDate } = determineCurrentFinancialYear()

// Due to the fact the database gives us the licence back in snake case, we need to convert the references to camel
// case so the other services can use the result
const result = {
licence: {
id: licence.id,
regionId: licence.region_id
},
startDate: licence.created_at,
endDate,
twoPartTariff: licence.two_part_tariff_charge_versions,
flagForBilling: false
}

if (!licence.include_in_sroc_billing && licence.sroc_charge_versions) {
await _flagForSrocSupplementary(licence.id)
}

result.flagForBilling = result.twoPartTariff

return result
}

async function _flagForSrocSupplementary (id) {
return LicenceModel.query().patch({ includeInSrocBilling: true }).where('id', id)
}

module.exports = {
go
}
72 changes: 72 additions & 0 deletions app/services/licences/supplementary/fetch-licence.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use strict'

/**
* Fetches existing supplementary details about a licence being removed from workflow
* @module FetchLicenceService
*/

const { db } = require('../../../../db/db.js')

/**
* Fetches existing supplementary details about a licence being removed from workflow
*
* We need to get the `created at` date from the workflow record to determine which supplementary years we need to flag.
* The query also determines what sroc or two-part tariff charge versions the licence has.
*
* When processing the flags we have to work out whether to include the licence in sroc supplementary billing or in
* two-part tariff supplementary billing.
*
* NOTE: We do not care about pre sroc charge versions. We are not setting the `include_in_pre_sroc_billing` flag due to
* using the old billing engine that then generates £0 bill runs. Only our new sroc billing engines can handle £0 bill
* runs.
*
* @param {string} workflowId - The UUID for the workflow record related to the licence
*
* @returns {Promise<object>} - The data needed to determine which supplementary flags the licence needs
*/
async function go (workflowId) {
const query = _query()

const { rows: [row] } = await db.raw(query, [workflowId])

return row
}

function _query () {
return `
SELECT
l.include_in_sroc_billing,
l.id,
l.region_id,
EXISTS (
SELECT 1
FROM public.charge_versions cv
WHERE cv.licence_id = l.id
AND cv.start_date > '2022-03-31'
) AS sroc_charge_versions,
EXISTS (
SELECT 1
FROM public.charge_references cr
INNER JOIN public.charge_elements ce
ON ce.charge_reference_id = cr.id
WHERE cr.charge_version_id = (
SELECT cv.id
FROM public.charge_versions cv
WHERE cv.licence_id = l.id
AND cv.start_date > '2022-03-31'
LIMIT 1
)
AND ce.section_127_Agreement = TRUE
AND cr.adjustments->>'s127' = 'true'
) AS two_part_tariff_charge_versions,
w.created_at
FROM licences l
INNER JOIN workflows w
ON l.id = w.licence_id
WHERE w.id = ?
`
}

module.exports = {
go
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ const DetermineBillingYearsService = require('./determine-billing-years.service.
const DetermineExistingBillRunYearsService = require('./determine-existing-bill-run-years.service.js')
const DetermineChargeVersionYearsService = require('./determine-charge-version-years.service.js')
const DetermineReturnLogYearsService = require('./determine-return-log-years.service.js')
const DetermineWorkflowYearsService = require('./determine-workflow-years.service.js')
const { calculateAndLogTimeTaken, currentTimeInNanoseconds } = require('../../../lib/general.lib.js')

/**
* Orchestrates flagging a licence for supplementary billing
*
* This service orchestrates the process of flagging a licence for supplementary billing.
* It retrieves details of the charge version, including the licence information, start and end dates, whether the
* Based on the ID the service receives (chargeVersionId, returnId, workflowId) it retrieves details of the related
* charge version, including the licence information, start and end dates, whether the
* charge version has two-part tariff indicators, and if it should be flagged for supplementary billing.
*
* If the licence qualifies for flagging, the relevant dates are passed to the `DetermineBillingYearsService`, which
Expand All @@ -42,6 +44,8 @@ async function go (payload) {
result = await DetermineChargeVersionYearsService.go(payload.chargeVersionId)
} else if (payload.returnId) {
result = await DetermineReturnLogYearsService.go(payload.returnId)
} else if (payload.workflowId) {
result = await DetermineWorkflowYearsService.go(payload.workflowId)
} else {
return
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
'use strict'

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

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

// Test helpers
const { determineCurrentFinancialYear } = require('../../../../app/lib/general.lib.js')
const LicenceHelper = require('../../../support/helpers/licence.helper.js')
const LicenceModel = require('../../../../app/models/licence.model.js')

// Things we need to stub
const FetchLicenceService = require('../../../../app/services/licences/supplementary/fetch-licence.service.js')

// Thing under test
const DetermineWorkflowYearsService = require('../../../../app/services/licences/supplementary/determine-workflow-years.service.js')

describe('Determine Workflow Years Service', () => {
const currentFinancialYear = determineCurrentFinancialYear()
const workflowId = '1c995768-35fe-45c4-bb80-dc242052e94d'

let licence
let licenceData

before(async () => {
licence = await LicenceHelper.add()
licenceData = {
include_in_sroc_billing: false,
id: licence.id,
region_id: licence.regionId,
sroc_charge_versions: false,
two_part_tariff_charge_versions: false,
created_at: new Date('2024-04-01')
}
})

afterEach(() => {
Sinon.restore()
})

describe('when passed a workflowId', () => {
describe('that relates to a licence with no sroc charge versions', () => {
beforeEach(async () => {
Sinon.stub(FetchLicenceService, 'go').resolves(licenceData)
})

it('returns flagForBilling and twoPartTariff as false', async () => {
const result = await DetermineWorkflowYearsService.go(workflowId)

expect(result.twoPartTariff).to.equal(false)
expect(result.flagForBilling).to.equal(false)
})

it('does not flag the licence for sroc supplementary billing', async () => {
await DetermineWorkflowYearsService.go(workflowId)

const result = await LicenceModel.query().findById(licence.id)

expect(result.includeInSrocBilling).to.equal(false)
})
})

describe('that relates to a licence with sroc charge versions', () => {
describe('but has no two-part tariff indicators', () => {
beforeEach(async () => {
licenceData.sroc_charge_versions = true

Sinon.stub(FetchLicenceService, 'go').resolves(licenceData)
})

it('flags the licence for sroc supplementary billing', async () => {
await DetermineWorkflowYearsService.go(workflowId)

const result = await LicenceModel.query().findById(licence.id)

expect(result.includeInSrocBilling).to.equal(true)
})

it('returns the licence data', async () => {
const result = await DetermineWorkflowYearsService.go(workflowId)

expect(result.licence.id).to.equal(licence.id)
expect(result.licence.regionId).to.equal(licence.regionId)
expect(result.startDate).to.equal(new Date('2024-04-01'))
expect(result.endDate).to.equal(currentFinancialYear.endDate)
})

it('returns the flagForBilling and twoPartTariff as false', async () => {
const result = await DetermineWorkflowYearsService.go(workflowId)

expect(result.twoPartTariff).to.equal(false)
expect(result.flagForBilling).to.equal(false)
})
})
})

describe('that relates to a licence with sroc two-part tariff charge versions', () => {
describe('and the licence is already flagged for sroc supplementary billing', () => {
before(async () => {
licenceData.two_part_tariff_charge_versions = true
licenceData.include_in_sroc_billing = true

Sinon.stub(FetchLicenceService, 'go').resolves(licenceData)
})

it('returns flagForBilling and twoPartTariff as true', async () => {
const result = await DetermineWorkflowYearsService.go(workflowId)

expect(result.twoPartTariff).to.equal(true)
expect(result.flagForBilling).to.equal(true)
})
})
})
})
})
58 changes: 58 additions & 0 deletions test/services/licences/supplementary/fetch-licence.service.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use strict'

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

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

// Test helpers
const ChargeElementHelper = require('../../../support/helpers/charge-element.helper.js')
const ChargeReferenceHelper = require('../../../support/helpers/charge-reference.helper.js')
const ChargeVersionHelper = require('../../../support/helpers/charge-version.helper.js')
const LicenceHelper = require('../../../support/helpers/licence.helper.js')
const WorkflowHelper = require('../../../support/helpers/workflow.helper.js')

// Thing under test
const FetchLicenceService = require('../../../../app/services/licences/supplementary/fetch-licence.service.js')

describe('Fetch Licence Service', () => {
let workflow

describe('when passed a valid workflow id', () => {
let licence

before(async () => {
licence = await LicenceHelper.add()

workflow = await WorkflowHelper.add({ licenceId: licence.id })

// sroc charge version
const chargeVersion = await ChargeVersionHelper.add({ licenceId: licence.id })

// two-part tariff indicators
const chargeReference = await ChargeReferenceHelper.add(
{ chargeVersionId: chargeVersion.id, adjustments: { s127: true } }
)

await ChargeElementHelper.add({ chargeReferenceId: chargeReference.id })
})

it('fetches the licence data related to that workflow record', async () => {
const result = await FetchLicenceService.go(workflow.id)

expect(result.id).to.equal(licence.id)
expect(result.region_id).to.equal(licence.regionId)
expect(result.include_in_sroc_billing).to.equal(licence.includeInSrocBilling)
expect(result.created_at).to.equal(workflow.createdAt)
})

it('outlines which charge versions the licence has', async () => {
const result = await FetchLicenceService.go(workflow.id)

expect(result.sroc_charge_versions).to.equal(true)
expect(result.two_part_tariff_charge_versions).to.equal(true)
})
})
})
Loading

0 comments on commit 461cb3c

Please sign in to comment.