Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Prepare Licence For Allocation Service #656

Merged
merged 9 commits into from
Jan 15, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
'use strict'

/**
* Prepares the charge version for matching
* @module PrepareChargeVersionService
*/
const DetermineAbstractionPeriodService = require('../determine-abstraction-periods.service.js')
const DetermineChargePeriodService = require('../determine-charge-period.service.js')

/**
* Prepares the charge version for matching with its returns
*
* This function performs the following steps:
*
* Sorts all charge references belonging to the charge version by subsistence charge in descending order. This ensures
* that allocation is performed with the highest subsistence charge first.
*
* Determines the charge period for the charge version using an external service and sets it as a property on the charge
* version object.
*
* Loops through each charge reference's elements, preparing them for matching. This involves determining the
* abstraction period for each element and adding properties such as returnLogs, allocatedQuantity, and
* abstractionPeriods.
*
* @param {module:ChargeVersionModel} chargeVersion - The charge version to prepare
* @param {Object} billingPeriod Object with a `startDate` and `endDate` property representing the period being billed
*/
function go (chargeVersion, billingPeriod) {
const { chargeReferences } = chargeVersion

_sortChargeReferencesBySubsistenceCharge(chargeReferences)
chargeVersion.chargePeriod = DetermineChargePeriodService.go(chargeVersion, billingPeriod)

chargeReferences.forEach((chargeReference) => {
const { chargeElements } = chargeReference

_prepareChargeElementsForMatching(chargeElements, chargeVersion.chargePeriod)
})
}

function _prepareChargeElementsForMatching (chargeElements, chargePeriod) {
chargeElements.forEach((chargeElement) => {
const {
abstractionPeriodStartDay,
abstractionPeriodStartMonth,
abstractionPeriodEndDay,
abstractionPeriodEndMonth
} = chargeElement

const abstractionPeriods = DetermineAbstractionPeriodService.go(
chargePeriod,
abstractionPeriodStartDay,
abstractionPeriodStartMonth,
abstractionPeriodEndDay,
abstractionPeriodEndMonth
)

chargeElement.returnLogs = []
chargeElement.allocatedQuantity = 0
chargeElement.abstractionPeriods = abstractionPeriods
})
}

function _sortChargeReferencesBySubsistenceCharge (chargeReferences) {
return chargeReferences.sort((firstChargeReference, secondChargeReference) => {
const { subsistenceCharge: subsistenceChargeFirst } = firstChargeReference.chargeCategory
const { subsistenceCharge: subsistenceChargeSecond } = secondChargeReference.chargeCategory

if (subsistenceChargeFirst > subsistenceChargeSecond) {
return -1
}

if (subsistenceChargeFirst < subsistenceChargeSecond) {
return 1
}

return 0
})
}

module.exports = {
go
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use strict'

/**
* Prepares the return logs to be matched to a charge element
* @module PrepareReturnLogsService
*/

const DetermineAbstractionPeriodService = require('../determine-abstraction-periods.service.js')
const FetchReturnLogsForLicenceService = require('./fetch-return-logs-for-licence.service.js')
const { periodsOverlap } = require('../../../lib/general.lib.js')

/**
* Prepares return logs for matching with abstraction periods and performs checks for potential issues
*
* This function fetches the return logs for the given licence using an external service and attaches them to the
* licence object. It then prepares each return log for matching by determining abstraction periods and checking for
* issues.
*
* @param {module:LicenceModel} licence - An individual licence to prepare the return logs for
* @param {Object} billingPeriod Object with a `startDate` and `endDate` property representing the period being billed
*/
async function go (licence, billingPeriod) {
await _prepareReturnLogs(licence, billingPeriod)
}

function _abstractionOutsidePeriod (returnAbstractionPeriods, returnLine) {
const { startDate, endDate } = returnLine

return !periodsOverlap(returnAbstractionPeriods, [{ startDate, endDate }])
}

/**
* Checks a return record for potential issues based on specific criteria and flags it accordingly
*/
function _checkReturnForIssues (returnLog) {
if (returnLog.nilReturn) {
return true
}

if (returnLog.underQuery) {
return true
}

if (returnLog.status !== 'completed') {
return true
}

if (returnLog.returnSubmissions.length === 0 || returnLog.returnSubmissions[0].returnSubmissionLines.length === 0) {
return true
}

return false
}

async function _prepareReturnLogs (licence, billingPeriod) {
licence.returnLogs = await FetchReturnLogsForLicenceService.go(licence.licenceRef, billingPeriod)

_prepReturnsForMatching(licence.returnLogs, billingPeriod)
}

function _prepReturnsForMatching (returnLogs, billingPeriod) {
returnLogs.forEach((returnLog) => {
const { periodStartDay, periodStartMonth, periodEndDay, periodEndMonth, returnSubmissions } = returnLog
const abstractionPeriods = DetermineAbstractionPeriodService.go(
billingPeriod,
periodStartDay,
periodStartMonth,
periodEndDay,
periodEndMonth
)

let quantity = 0
let abstractionOutsidePeriod = false

returnSubmissions[0]?.returnSubmissionLines.forEach((returnSubmissionLine) => {
if (!abstractionOutsidePeriod) {
abstractionOutsidePeriod = _abstractionOutsidePeriod(abstractionPeriods, returnSubmissionLine)
}
returnSubmissionLine.unallocated = returnSubmissionLine.quantity / 1000
quantity += returnSubmissionLine.unallocated
})

returnLog.nilReturn = returnSubmissions[0]?.nilReturn ?? false
returnLog.quantity = quantity
returnLog.allocatedQuantity = 0
returnLog.abstractionPeriods = abstractionPeriods
returnLog.abstractionOutsidePeriod = abstractionOutsidePeriod
returnLog.matched = false

returnLog.issues = (_checkReturnForIssues(returnLog))
})
}

module.exports = {
go
}
Loading
Loading