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

Tidy supplementary billing code #197

Merged
merged 19 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions app/controllers/check/supplementary.controller.js

This file was deleted.

2 changes: 0 additions & 2 deletions app/plugins/router.plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

const AssetRoutes = require('../routes/assets.routes.js')
const BillRunRoutes = require('../routes/bill-runs.routes')
const CheckRoutes = require('../routes/check.routes.js')
const FilterRoutesService = require('../services/plugins/filter-routes.service.js')
const HealthRoutes = require('../routes/health.routes.js')
const RootRoutes = require('../routes/root.routes.js')
Expand All @@ -24,7 +23,6 @@ const routes = [
...RootRoutes,
...AssetRoutes,
...HealthRoutes,
...CheckRoutes,
...BillRunRoutes
]

Expand Down
19 changes: 0 additions & 19 deletions app/presenters/check/supplementary-data.presenter.js

This file was deleted.

16 changes: 0 additions & 16 deletions app/routes/check.routes.js

This file was deleted.

32 changes: 0 additions & 32 deletions app/services/check/supplementary-data.service.js

This file was deleted.

6 changes: 3 additions & 3 deletions app/services/supplementary-billing/billing-period.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
* **IMPORTANT!** This service currently only handles SROC billing periods and only the 'current year'
*
* Using the current date at the time the service is called, it calculates the billing periods to use. We permit
* changes to charge versions to be retroactively applied up to 5 years. So, a bill run generated in 2022 would need
* to consider every financial year back to 2017.
* changes to charge versions to be retroactively applied up to 5 years. So, a bill run generated in 2022 would need to
* consider every financial year back to 2017.
*
* The exception to that is the change in charge scheme that happened in 2022, when we moved from ALCS (or PRESROC) to
* SROC. Changes prior to 2022 would only apply to a ALCS bill run and vice versa.
*
* @returns {Object[]} an array of billing periods each containing a `startDate` and `endDate`.
* @returns {Object[]} An array of billing periods each containing a `startDate` and `endDate`.
*/
function go () {
// TODO: We have hardcoded the billing period this service returns to be 2022-23 the first year SROC went live. This
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

const ConsolidateDateRangesService = require('./consolidate-date-ranges.service.js')

const ONE_DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000

/**
* Returns the authorised and billable days for a given charge element based on its abstraction periods
*
Expand All @@ -15,9 +17,9 @@ const ConsolidateDateRangesService = require('./consolidate-date-ranges.service.
* start and end day and month, for example 1 Apr to 31 Oct. They do not have years because the intent is they are the
* same period no matter what year it is.
*
* **Authorised** days is how much of the billing period overlaps with the abstraction period. **Billable** days is
* how much of the charge period overlaps with the abstraction period (see params for explanations of billable and
* charge periods).
* **Authorised** days is how much of the billing period overlaps with the abstraction period. **Billable** days is how
* much of the charge period overlaps with the abstraction period (see params for explanations of billable and charge
* periods).
*
* Calculating these values is complicated by the fact a charge element may have multiple abstraction periods. Added to
* that abstraction periods do not intersect nicely with billing or charge periods. The abstraction period might start
Expand All @@ -28,34 +30,30 @@ const ConsolidateDateRangesService = require('./consolidate-date-ranges.service.
* - **1 Jan 2023 to 30 Jun 2023** intersects as 1 Jan 2023 to 31 Mar 2023
*
* The number of days the abstraction period intersects either the billing or charge period is where we get our 'days'
* from. The final complication is we cannot double count. If 2 charge purposes have abstraction periods that overlap
* we must only count one of them. For example
* from. The final complication is we cannot double count. If 2 charge purposes have abstraction periods that overlap we
* must only count one of them. For example
*
* - charge purpose 1 has **1 Jan to 30 Jun**
* - charge purpose 2 has **1 May to 31 Oct**
*
* They overlap 1 May to 30 Jun. To get our days we summate the result for each abstraction period and have to ensure
* we only count this once.
* They overlap 1 May to 30 Jun. To get our days we summate the result for each abstraction period and have to ensure we
* only count this once.
*
* So, a charge purpose's abstraction dates might result in 2 relevant abstraction periods. A charge element might have
* multiple charge purposes. But we must return a single **Authorised** and **Billable** days calculation. This problem
* is what this service tackles.
*
* @param {Object} chargePeriod charge period is determined as the overlap between a charge version's start and end
* dates, and the billing period's (financial year) start and end dates. So, when the charge version and billing period
* are compared the charge period's start date is the latest of the two, and the end date is the earliest of their end
* dates
* @param {Date} chargePeriod.startDate
* @param {Date} chargePeriod.endDate
* @param {Object} billingPeriod the period a billing batch is being calculated for. Currently, this always equates to
* a financial year, for example, 2022-04-01 to 2023-03-31
* @param {Date} billingPeriod.startDate
* @param {Date} billingPeriod.endDate
* @param {module:ChargeElementModel} chargeElement referred to as the 'charge reference' in the UI, for example,
* 4.1.10. A charge version can have multiple charge elements, though each will have a different reference. Each element
* can have multiple charge purposes and it's these that hold the abstraction period data
*
* @returns {Object} an object containing an `authorisedDays` and `billableDays` property
* @param {{startDate: Date, endDate: Date}} chargePeriod Charge period is determined as the overlap between a charge
* version's start and end dates, and the billing period's (financial year) start and end dates. So, when the charge
* version and billing period are compared the charge period's start date is the latest of the two, and the end date is
* the earliest of their end dates
* @param {{startDate: Date, endDate: Date}} billingPeriod The period a billing batch is being calculated for.
* Currently, this always equates to a financial year, for example, 2022-04-01 to 2023-03-31
* @param {module:ChargeElementModel} chargeElement Referred to as the 'charge reference' in the UI, for example,
* 4.1.10. A charge version can have multiple charge elements, though each will have a different reference. Each
* element can have multiple charge purposes and it's these that hold the abstraction period data
*
* @returns {Object} An object containing an `authorisedDays` and `billableDays` property
*/
function go (chargePeriod, billingPeriod, chargeElement) {
const { chargePurposes } = chargeElement
Expand Down Expand Up @@ -166,21 +164,18 @@ function _abstractionPeriods (referencePeriod, chargePurpose) {
* @returns {number} the length of the period in days (inclusive)
*/
function _calculateDays (abstractionOverlapPeriod) {
const DAY_IN_MILLISECONDS = (24 * 60 * 60 * 1000) // (24 hrs * 60 mins * 60 secs * 1000 msecs)

// difference in msecs
const difference = abstractionOverlapPeriod.endDate.getTime() - abstractionOverlapPeriod.startDate.getTime()

// ceil() always rounds up, even if the result is 1.1 (rounds to 2). We add 1 to make the calculation inclusive of
// the last day
return Math.ceil(difference / DAY_IN_MILLISECONDS) + 1
return Math.ceil(difference / ONE_DAY_IN_MILLISECONDS) + 1
}

/**
* Calculates the period that an abstraction period overlaps the reference period
*
* Before we can work out either the authorised or billable days, we first need to work out what part of the
* abstraction period overlaps.
* Before we can work out either the authorised or billable days, we first need to work out what part of the abstraction
* period overlaps.
*
* The simplest way to look at this is that the overlapping period is the latest start date and the earliest end date.
*
Expand All @@ -193,10 +188,11 @@ function _calculateDays (abstractionOverlapPeriod) {
* - 01-NOV-2022 to 31-MAY-2023 - overlap is 01-NOV-2022 to 31-MAR-2023
*
* @param {Object} referencePeriod either the billing period or charge period
* @param {*} abstractionPeriod a start and end date representing the abstraction period relative to the reference
* @param {Object} abstractionPeriod an object containing `startDate` and `endDate` date representing the abstraction
* period relative to the reference
*
* @returns {Object} an object with a start and end date representing the part of the abstraction period that overlaps
* the reference period
* the reference period
*/
function _calculateAbstractionOverlapPeriod (referencePeriod, abstractionPeriod) {
const latestStartDateTimestamp = Math.max(abstractionPeriod.startDate, referencePeriod.startDate)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ const LIVE_STATUSES = ['processing', 'ready', 'review', 'queued']
*
* 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
* @param {String} regionId The id of the region to be checked
* @param {Number} 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')
.select(1)
.where({
regionId,
toFinancialYearEnding: financialYear,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@
* { startDate: 2023-11-01, endDate: 2023-12-01 } // Range 4 unchanged
* ]
*
* @param {Array.<{startDate: Date, endDate: Date}>} dateRanges Array containing a series of date ranges to be
* consolidated, each of which is an Object containing startDate and endDate, both of which are Dates
* @param {{startDate: Date, endDate: Date}[]} dateRanges Array containing a series of date ranges to be consolidated.
*
* @returns {Array.<{startDate: Date, endDate: Date}>} An array of the consolidated date ranges
* @returns {{startDate: Date, endDate: Date}[]} An array of the consolidated date ranges
*/
function go (dateRanges) {
// We sort the date ranges by start date from earliest to latest to make life easier when consolidating them
Expand Down Expand Up @@ -92,9 +91,9 @@ function _consolidateDates (dateRanges) {
return [...acc, previousRange]
}

// If the current range's start date is on or earlier than the previous end date then the current range overlaps (starting
// the same day as the previous one ends counts as overlapping) so we add a new date range to our ongoing acc array,
// starting when the previous range starts and ending when the current range end
// If the current range's start date is on or earlier than the previous end date then the current range overlaps
// (starting the same day as the previous one ends counts as overlapping) so we add a new date range to our ongoing
// acc array, starting when the previous range starts and ending when the current range ends
if (currentRange.startDate <= previousRange.endDate) {
return [...acc, { startDate: previousRange.startDate, endDate: currentRange.endDate }]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ const GeneralLib = require('../../lib/general.lib.js')
/**
* Create an event for when a new bill run is initialised
*
* @param {module:BillingBatchModel} [billingBatch] An instance of `BillingBatchModel` representing the initialised
* billing batch
* @param {String} [issuer] The email address of the user triggering the event
* @param {module:BillingBatchModel} billingBatch An instance of `BillingBatchModel` representing the initialised
* billing batch
* @param {String} issuer The email address of the user triggering the event
*
* @returns {Object} The newly created event record
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ const BillingBatchModel = require('../../models/water/billing-batch.model.js')
* @param {Object} regionId The regionId for the selected region
* @param {Object} billingPeriod The billing period in the format { startDate: 2022-04-01, endDate: 2023-03-31 }
* @param {Object} options Optional params to be overridden
* @param {string} [options.batchType=supplementary] The type of billing batch to create. Defaults to 'supplementary'
* @param {string} [options.scheme=sroc] The applicable charging scheme. Defaults to 'sroc'
* @param {string} [options.source=wrls] Where the billing batch originated from. Records imported from NALD have the
* @param {String} [options.batchType=supplementary] The type of billing batch to create. Defaults to 'supplementary'
* @param {String} [options.scheme=sroc] The applicable charging scheme. Defaults to 'sroc'
* @param {String} [options.source=wrls] Where the billing batch originated from. Records imported from NALD have the
* source 'nald'. Those created in the service use 'wrls'. Defaults to 'wrls'
* @param {string} [options.externalId=null] The id of the bill run as created in the Charging Module
* @param {string} [options.status=queued] The status that the bill run should be created with
* @param {number} [options.errorCode=null] Numeric error code
* @param {String} [options.externalId=null] The id of the bill run as created in the Charging Module
* @param {String} [options.status=queued] The status that the bill run should be created with
* @param {Number} [options.errorCode=null] Numeric error code
*
* @returns {module:BillingBatchModel} The newly created billing batch instance with the `.region` property populated
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
*
* > Charge versions may not have an end date; in this case, we simply use the financial year end date.
*
* @param {module:ChargeVersionModel} chargeVersion the charge version being processed for billing
* @param {number} financialYearEnding the year the financial billing period ends
* @param {module:ChargeVersionModel} chargeVersion The charge version being processed for billing
* @param {Number} financialYearEnding The year the financial billing period ends
*
* @returns {Object} the start and end date of the calculated charge period
* @returns {{startDate: Date, endDate: Date}} The start and end date of the calculated charge period
*/
function go (chargeVersion, financialYearEnding) {
const financialYearStartDate = new Date(financialYearEnding - 1, 3, 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ const DetermineChargePeriodService = require('./determine-charge-period.service.
/**
* Checks if minimum charge applies to a charge version for the given billing period
*
* If the charge version's start date matches the start of the charging period, and the reason for its creation
* is flagged as triggering a minimum charge this service will return true.
* If the charge version's start date matches the start of the charging period, and the reason for its creation is
* flagged as triggering a minimum charge this service will return true.
*
* If either of those tests is false then the service will return false.
*
* @param {module:ChargeVersionModel} chargeVersion the charge version being checked for minimum charge
* @param {number} financialYearEnding the year the financial billing period ends
* @param {module:ChargeVersionModel} chargeVersion The charge version being checked for minimum charge
* @param {Number} financialYearEnding The year the financial billing period ends
*
* @returns {boolean} true if minimum charge applies else false
* @returns {Boolean} true if minimum charge applies else false
*/
function go (chargeVersion, financialYearEnding) {
const chargePeriod = DetermineChargePeriodService.go(chargeVersion, financialYearEnding)
Expand All @@ -30,7 +30,6 @@ function go (chargeVersion, financialYearEnding) {
const triggersMinimumCharge = chargeVersion.changeReason?.triggersMinimumCharge ?? false
const isFirstChargeOnNewLicence = isSharedStartDate && triggersMinimumCharge

// TODO: confirm whether legacy code is correct when it says return true if charge period starts on first april
return isFirstChargeOnNewLicence
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ const ChargeVersionWorkflow = require('../../models/water/charge-version-workflo
* Fetch all SROC charge versions linked to licences flagged for supplementary billing that are in the period being
* billed
*
* @param {string} regionId UUID of the region being billed that the licences must be linked to
* @param {String} regionId UUID of the region being billed that the licences must be linked to
* @param {Object} billingPeriod Object with a `startDate` and `endDate` property representing the period being billed
*
* @returns {Object[]} an array of matching charge versions
* @returns {Object[]} An array of matching charge versions
*/
async function go (regionId, billingPeriod) {
const chargeVersions = await _fetch(regionId, billingPeriod)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@

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

/**
* Fetches the previously billed transactions that match the invoice, licence and year provided, removing any debits
* which are cancelled out by previous credits.
*
* @param {Object} billingInvoice A generated billing invoice that identifies the invoice account ID we need to match
* against
* @param {Object} billingInvoiceLicence A generated billing invoice licence that identifies the licence we need to
* match against
* @param {Number} financialYearEnding The year the financial billing period ends that we need to match against
*
* @returns {Object} The resulting matched billing transactions
*/
async function go (billingInvoice, billingInvoiceLicence, financialYearEnding) {
const billingTransactions = await _fetch(
billingInvoiceLicence.licenceId,
Expand Down
Loading