Skip to content

Commit

Permalink
Refactor Persist Allocated Licences To Results Service (#658)
Browse files Browse the repository at this point in the history
https://eaflood.atlassian.net/browse/WATER-4319

This pull request refactors the 'PersistAllocatedLicencesToResultsService' as part of our ongoing effort to enhance the two-part-tariff service. Initially, we began by creating a 'hack' branch to build and iterate on the two-part-tariff functionality. In the process of working on these branches, we identified a cleaner and more performant approach to implement the overall service.  We realised that the PersistAllocatedLicencesToResultsService would be much cleaner and easier to follow if it only persisted one licence at a time, rather than iterating through every licence. This also makes it easier for testing.
  • Loading branch information
Beckyrose200 authored Jan 15, 2024
1 parent fbe69e1 commit b27e0a3
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 146 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use strict'

/**
* Persists the results from the `allocateReturnsToLicenceService` into the DB
* @module PersistAllocatedLicencesToResultsService
* Persists the results from the `allocateReturnsToChargeElementService` into the DB
* @module PersistAllocatedLicenceToResultsService
*/

const ReviewChargeElementResultModel = require('../../../models/review-charge-element-result.model.js')
Expand All @@ -21,31 +21,29 @@ const ReviewResultModel = require('../../../models/review-result.model.js')
* matching and allocating looks correct or if any issues need resolving first.
*
* @param {String} billRunId - the ID of the two-part tariff bill run being generated
* @param {Object[]} licences - the two-part tariff licences included in the bill run, along with their match and
* @param {module:LicenceModel} licence - the two-part tariff licence included in the bill run, along with their match and
* allocation results
*/
async function go (billRunId, licences) {
for (const licence of licences) {
const { chargeVersions, returnLogs } = licence

const reviewReturnResultIds = await _persistReturnLogs(returnLogs, billRunId, licence)

for (const chargeVersion of chargeVersions) {
const { chargeReferences } = chargeVersion

for (const chargeReference of chargeReferences) {
const { chargeElements } = chargeReference

for (const chargeElement of chargeElements) {
await _persistChargeElement(
billRunId,
licence,
chargeVersion,
chargeReference,
chargeElement,
reviewReturnResultIds
)
}
async function go (billRunId, licence) {
const { chargeVersions, returnLogs } = licence

const reviewReturnResultIds = await _persistReturnLogs(returnLogs, billRunId, licence)

for (const chargeVersion of chargeVersions) {
const { chargeReferences } = chargeVersion

for (const chargeReference of chargeReferences) {
const { chargeElements } = chargeReference

for (const chargeElement of chargeElements) {
await _persistChargeElement(
billRunId,
licence,
chargeVersion,
chargeReference,
chargeElement,
reviewReturnResultIds
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,66 +14,66 @@ const { generateReturnLogId } = require('../../../support/helpers/return-log.hel
const ReviewResultModel = require('../../../../app/models/review-result.model.js')

// Thing under test
const PersistAllocatedLicencesToResultsService = require('../../../../app/services/bill-runs/two-part-tariff/persist-allocated-licences-to-results.service.js')
const PersistAllocatedLicenceToResultsService = require('../../../../app/services/bill-runs/two-part-tariff/persist-allocated-licence-to-results.service.js')

describe('Persist Allocated Licences to Results service', () => {
describe('Persist Allocated Licence to Results service', () => {
const billRunId = generateUUID()

beforeEach(async () => {
await DatabaseHelper.clean()
})

describe('when there are valid records to be persisted', () => {
let testLicences
describe('when there are records to be persisted', () => {
let testLicence

describe('with a charge element that has been matched to a return', () => {
beforeEach(() => {
testLicences = _generateData()
testLicence = _generateData()
})

it('persists the data into the results tables', async () => {
await PersistAllocatedLicencesToResultsService.go(billRunId, testLicences)
await PersistAllocatedLicenceToResultsService.go(billRunId, testLicence)

const result = await ReviewResultModel.query()
.where('licenceId', testLicences[0].id)
.where('licenceId', testLicence.id)
.withGraphFetched('reviewChargeElementResults')
.withGraphFetched('reviewReturnResults')

expect(result[0].billRunId).to.equal(billRunId)
expect(result[0].licenceId).to.equal(testLicences[0].id)
expect(result[0].chargeVersionId).to.equal(testLicences[0].chargeVersions[0].id)
expect(result[0].chargeReferenceId).to.equal(testLicences[0].chargeVersions[0].chargeReferences[0].id)
expect(result[0].chargePeriodStartDate).to.equal(testLicences[0].chargeVersions[0].chargePeriod.startDate)
expect(result[0].chargePeriodEndDate).to.equal(testLicences[0].chargeVersions[0].chargePeriod.endDate)
expect(result[0].chargeVersionChangeReason).to.equal(testLicences[0].chargeVersions[0].changeReason.description)
expect(result[0].licenceId).to.equal(testLicence.id)
expect(result[0].chargeVersionId).to.equal(testLicence.chargeVersions[0].id)
expect(result[0].chargeReferenceId).to.equal(testLicence.chargeVersions[0].chargeReferences[0].id)
expect(result[0].chargePeriodStartDate).to.equal(testLicence.chargeVersions[0].chargePeriod.startDate)
expect(result[0].chargePeriodEndDate).to.equal(testLicence.chargeVersions[0].chargePeriod.endDate)
expect(result[0].chargeVersionChangeReason).to.equal(testLicence.chargeVersions[0].changeReason.description)

expect(result[0].reviewChargeElementResults.chargeElementId).to.equal(
testLicences[0].chargeVersions[0].chargeReferences[0].chargeElements[0].id
testLicence.chargeVersions[0].chargeReferences[0].chargeElements[0].id
)
expect(result[0].reviewChargeElementResults.allocated).to.equal(
testLicences[0].chargeVersions[0].chargeReferences[0].chargeElements[0].allocatedQuantity
testLicence.chargeVersions[0].chargeReferences[0].chargeElements[0].allocatedQuantity
)
// As the aggregate is null on the charge reference the service returns 1
expect(result[0].reviewChargeElementResults.aggregate).to.equal(1)
expect(result[0].reviewChargeElementResults.chargeDatesOverlap).to.equal(
testLicences[0].chargeVersions[0].chargeReferences[0].chargeElements[0].chargeDatesOverlap
testLicence.chargeVersions[0].chargeReferences[0].chargeElements[0].chargeDatesOverlap
)

expect(result[0].reviewReturnResults.returnId).to.equal(testLicences[0].returnLogs[0].id)
expect(result[0].reviewReturnResults.returnReference).to.equal(testLicences[0].returnLogs[0].returnRequirement)
expect(result[0].reviewReturnResults.startDate).to.equal(testLicences[0].returnLogs[0].startDate)
expect(result[0].reviewReturnResults.endDate).to.equal(testLicences[0].returnLogs[0].endDate)
expect(result[0].reviewReturnResults.dueDate).to.equal(testLicences[0].returnLogs[0].dueDate)
expect(result[0].reviewReturnResults.receivedDate).to.equal(testLicences[0].returnLogs[0].receivedDate)
expect(result[0].reviewReturnResults.status).to.equal(testLicences[0].returnLogs[0].status)
expect(result[0].reviewReturnResults.underQuery).to.equal(testLicences[0].returnLogs[0].underQuery)
expect(result[0].reviewReturnResults.nilReturn).to.equal(testLicences[0].returnLogs[0].nilReturn)
expect(result[0].reviewReturnResults.description).to.equal(testLicences[0].returnLogs[0].description)
expect(result[0].reviewReturnResults.purposes).to.equal(testLicences[0].returnLogs[0].purposes)
expect(result[0].reviewReturnResults.quantity).to.equal(testLicences[0].returnLogs[0].quantity)
expect(result[0].reviewReturnResults.allocated).to.equal(testLicences[0].returnLogs[0].allocatedQuantity)
expect(result[0].reviewReturnResults.returnId).to.equal(testLicence.returnLogs[0].id)
expect(result[0].reviewReturnResults.returnReference).to.equal(testLicence.returnLogs[0].returnRequirement)
expect(result[0].reviewReturnResults.startDate).to.equal(testLicence.returnLogs[0].startDate)
expect(result[0].reviewReturnResults.endDate).to.equal(testLicence.returnLogs[0].endDate)
expect(result[0].reviewReturnResults.dueDate).to.equal(testLicence.returnLogs[0].dueDate)
expect(result[0].reviewReturnResults.receivedDate).to.equal(testLicence.returnLogs[0].receivedDate)
expect(result[0].reviewReturnResults.status).to.equal(testLicence.returnLogs[0].status)
expect(result[0].reviewReturnResults.underQuery).to.equal(testLicence.returnLogs[0].underQuery)
expect(result[0].reviewReturnResults.nilReturn).to.equal(testLicence.returnLogs[0].nilReturn)
expect(result[0].reviewReturnResults.description).to.equal(testLicence.returnLogs[0].description)
expect(result[0].reviewReturnResults.purposes).to.equal(testLicence.returnLogs[0].purposes)
expect(result[0].reviewReturnResults.quantity).to.equal(testLicence.returnLogs[0].quantity)
expect(result[0].reviewReturnResults.allocated).to.equal(testLicence.returnLogs[0].allocatedQuantity)
expect(result[0].reviewReturnResults.abstractionOutsidePeriod).to.equal(
testLicences[0].returnLogs[0].abstractionOutsidePeriod
testLicence.returnLogs[0].abstractionOutsidePeriod
)
})
})
Expand All @@ -83,19 +83,19 @@ describe('Persist Allocated Licences to Results service', () => {
const aggregate = 0.5
const returnMatched = false

testLicences = _generateData(aggregate, returnMatched)
testLicence = _generateData(aggregate, returnMatched)
})

it('persists the data into the results tables', async () => {
await PersistAllocatedLicencesToResultsService.go(billRunId, testLicences)
it('persists the return logs data into the results tables', async () => {
await PersistAllocatedLicenceToResultsService.go(billRunId, testLicence)

const result = await ReviewResultModel.query()
.where('licenceId', testLicences[0].id)
.where('licenceId', testLicence.id)
.withGraphFetched('reviewChargeElementResults')
.withGraphFetched('reviewReturnResults')

expect(result[0].billRunId).to.equal(billRunId)
expect(result[0].licenceId).to.equal(testLicences[0].id)
expect(result[0].licenceId).to.equal(testLicence.id)
expect(result[0].chargeVersionId).to.be.null()
expect(result[0].chargeReferenceId).to.be.null()
expect(result[0].chargePeriodStartDate).to.be.null()
Expand All @@ -105,57 +105,58 @@ describe('Persist Allocated Licences to Results service', () => {

expect(result[0].reviewChargeElementResults).to.be.null()

expect(result[0].reviewReturnResults.returnId).to.equal(testLicences[0].returnLogs[0].id)
expect(result[0].reviewReturnResults.returnReference).to.equal(testLicences[0].returnLogs[0].returnRequirement)
expect(result[0].reviewReturnResults.startDate).to.equal(testLicences[0].returnLogs[0].startDate)
expect(result[0].reviewReturnResults.endDate).to.equal(testLicences[0].returnLogs[0].endDate)
expect(result[0].reviewReturnResults.dueDate).to.equal(testLicences[0].returnLogs[0].dueDate)
expect(result[0].reviewReturnResults.receivedDate).to.equal(testLicences[0].returnLogs[0].receivedDate)
expect(result[0].reviewReturnResults.status).to.equal(testLicences[0].returnLogs[0].status)
expect(result[0].reviewReturnResults.underQuery).to.equal(testLicences[0].returnLogs[0].underQuery)
expect(result[0].reviewReturnResults.nilReturn).to.equal(testLicences[0].returnLogs[0].nilReturn)
expect(result[0].reviewReturnResults.description).to.equal(testLicences[0].returnLogs[0].description)
expect(result[0].reviewReturnResults.purposes).to.equal(testLicences[0].returnLogs[0].purposes)
expect(result[0].reviewReturnResults.quantity).to.equal(testLicences[0].returnLogs[0].quantity)
expect(result[0].reviewReturnResults.allocated).to.equal(testLicences[0].returnLogs[0].allocatedQuantity)
expect(result[0].reviewReturnResults.returnId).to.equal(testLicence.returnLogs[0].id)
expect(result[0].reviewReturnResults.returnReference).to.equal(testLicence.returnLogs[0].returnRequirement)
expect(result[0].reviewReturnResults.startDate).to.equal(testLicence.returnLogs[0].startDate)
expect(result[0].reviewReturnResults.endDate).to.equal(testLicence.returnLogs[0].endDate)
expect(result[0].reviewReturnResults.dueDate).to.equal(testLicence.returnLogs[0].dueDate)
expect(result[0].reviewReturnResults.receivedDate).to.equal(testLicence.returnLogs[0].receivedDate)
expect(result[0].reviewReturnResults.status).to.equal(testLicence.returnLogs[0].status)
expect(result[0].reviewReturnResults.underQuery).to.equal(testLicence.returnLogs[0].underQuery)
expect(result[0].reviewReturnResults.nilReturn).to.equal(testLicence.returnLogs[0].nilReturn)
expect(result[0].reviewReturnResults.description).to.equal(testLicence.returnLogs[0].description)
expect(result[0].reviewReturnResults.purposes).to.equal(testLicence.returnLogs[0].purposes)
expect(result[0].reviewReturnResults.quantity).to.equal(testLicence.returnLogs[0].quantity)
expect(result[0].reviewReturnResults.allocated).to.equal(testLicence.returnLogs[0].allocatedQuantity)
expect(result[0].reviewReturnResults.abstractionOutsidePeriod).to.equal(
testLicences[0].returnLogs[0].abstractionOutsidePeriod
testLicence.returnLogs[0].abstractionOutsidePeriod
)
})

it('persists the charge element data into the results tables', async () => {
await PersistAllocatedLicenceToResultsService.go(billRunId, testLicence)

const result = await ReviewResultModel.query()
.where('licenceId', testLicence.id)
.withGraphFetched('reviewChargeElementResults')
.withGraphFetched('reviewReturnResults')

expect(result[1].billRunId).to.equal(billRunId)
expect(result[1].licenceId).to.equal(testLicences[0].id)
expect(result[1].chargeVersionId).to.equal(testLicences[0].chargeVersions[0].id)
expect(result[1].chargeReferenceId).to.equal(testLicences[0].chargeVersions[0].chargeReferences[0].id)
expect(result[1].chargePeriodStartDate).to.equal(testLicences[0].chargeVersions[0].chargePeriod.startDate)
expect(result[1].chargePeriodEndDate).to.equal(testLicences[0].chargeVersions[0].chargePeriod.endDate)
expect(result[1].chargeVersionChangeReason).to.equal(testLicences[0].chargeVersions[0].changeReason.description)
expect(result[1].licenceId).to.equal(testLicence.id)
expect(result[1].chargeVersionId).to.equal(testLicence.chargeVersions[0].id)
expect(result[1].chargeReferenceId).to.equal(testLicence.chargeVersions[0].chargeReferences[0].id)
expect(result[1].chargePeriodStartDate).to.equal(testLicence.chargeVersions[0].chargePeriod.startDate)
expect(result[1].chargePeriodEndDate).to.equal(testLicence.chargeVersions[0].chargePeriod.endDate)
expect(result[1].chargeVersionChangeReason).to.equal(testLicence.chargeVersions[0].changeReason.description)
expect(result[1].reviewReturnResultId).to.be.null()

expect(result[1].reviewChargeElementResults.chargeElementId).to.equal(
testLicences[0].chargeVersions[0].chargeReferences[0].chargeElements[0].id
testLicence.chargeVersions[0].chargeReferences[0].chargeElements[0].id
)
expect(result[1].reviewChargeElementResults.allocated).to.equal(
testLicences[0].chargeVersions[0].chargeReferences[0].chargeElements[0].allocatedQuantity
testLicence.chargeVersions[0].chargeReferences[0].chargeElements[0].allocatedQuantity
)
expect(result[1].reviewChargeElementResults.aggregate).to.equal(
testLicences[0].chargeVersions[0].chargeReferences[0].aggregate
testLicence.chargeVersions[0].chargeReferences[0].aggregate
)
expect(result[1].reviewChargeElementResults.chargeDatesOverlap).to.equal(
testLicences[0].chargeVersions[0].chargeReferences[0].chargeElements[0].chargeDatesOverlap
testLicence.chargeVersions[0].chargeReferences[0].chargeElements[0].chargeDatesOverlap
)

expect(result[1].reviewReturnResults).to.be.null()
})
})
})

describe('when there are NO records to persist', () => {
const testLicences = []

it('does not throw an error', () => {
expect(async () => await PersistAllocatedLicencesToResultsService.go(billRunId, testLicences)).to.not.throw()
})
})
})

function _generateData (aggregate = null, returnMatched = true) {
Expand All @@ -169,63 +170,62 @@ function _generateData (aggregate = null, returnMatched = true) {
]

// All data not required for the tests has been excluded from the generated data
const dataToPersist = [
{
id: generateUUID(),
chargeVersions: [
{
id: generateUUID(),
changeReason: {
description: 'Strategic review of charges (SRoC)'
},
chargeReferences: [
{
id: generateUUID(),
aggregate,
chargeElements: [
{
id: generateUUID(),
returnLogs: returnMatched ? chargeElementReturnLogs : [],
allocatedQuantity: returnMatched ? 32 : 0,
chargeDatesOverlap: false
}
]
}
],
chargePeriod: {
startDate: new Date('2022-04-01'),
endDate: new Date('2023-03-31')
const dataToPersist =
{
id: generateUUID(),
chargeVersions: [
{
id: generateUUID(),
changeReason: {
description: 'Strategic review of charges (SRoC)'
},
chargeReferences: [
{
id: generateUUID(),
aggregate,
chargeElements: [
{
id: generateUUID(),
returnLogs: returnMatched ? chargeElementReturnLogs : [],
allocatedQuantity: returnMatched ? 32 : 0,
chargeDatesOverlap: false
}
]
}
}
],
returnLogs: [
{
id: returnId,
returnRequirement: '10021668',
description: 'DRAINS ETC-DEEPING FEN AND OTHER LINKED SITES',
],
chargePeriod: {
startDate: new Date('2022-04-01'),
endDate: new Date('2023-03-31'),
receivedDate: new Date('2023-03-01'),
dueDate: new Date('2023-04-28'),
status: 'completed',
underQuery: false,
purposes: [
{
tertiary: {
code: '400',
description: 'Spray Irrigation - Direct'
}
}
],
nilReturn: false,
quantity: 32,
allocatedQuantity: returnMatched ? 32 : 0,
abstractionOutsidePeriod: false,
matched: returnMatched
endDate: new Date('2023-03-31')
}
]
}
]
}
],
returnLogs: [
{
id: returnId,
returnRequirement: '10021668',
description: 'DRAINS ETC-DEEPING FEN AND OTHER LINKED SITES',
startDate: new Date('2022-04-01'),
endDate: new Date('2023-03-31'),
receivedDate: new Date('2023-03-01'),
dueDate: new Date('2023-04-28'),
status: 'completed',
underQuery: false,
purposes: [
{
tertiary: {
code: '400',
description: 'Spray Irrigation - Direct'
}
}
],
nilReturn: false,
quantity: 32,
allocatedQuantity: returnMatched ? 32 : 0,
abstractionOutsidePeriod: false,
matched: returnMatched
}
]
}

return dataToPersist
}

0 comments on commit b27e0a3

Please sign in to comment.