-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1950771
commit 623d033
Showing
2 changed files
with
115 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
'use strict' | ||
|
||
/** | ||
* Connects with the Charging Module to send a bill run | ||
* @module ChargingModuleSendBillRunService | ||
*/ | ||
|
||
const ChargingModuleRequestLib = require('../../lib/charging-module-request.lib.js') | ||
|
||
/** | ||
* Approve then send a bill run in the Charging Module API | ||
* | ||
* Our service does in one step what the CHA does in two; approve the bill run then 'send' it. Approving a CHA bill run | ||
* doesn't actually do anything. It just changes the state to `approved` which the bill run has to be in before the bill | ||
* run can be sent. | ||
* | ||
* Sending a bill run is the final step. Once sent a bill run cannot be changed or deleted. Sending involves the CHA | ||
* generating a bill number for every bill in the bill run. It then generates a transaction reference for the bill run | ||
* itself. This reference is used to name the transaction import file which the CHA also generates at this time. This | ||
* is the file that will make it's way to SOP and be used to generate the invoice and credit notes that customers | ||
* receive. | ||
* | ||
* For small bill runs the process is near instantaneous. Larger bill runs however it can take a number of seconds. | ||
* Because of this when the request is first made the CHA switches the bill run's status to `sending`. Only when the | ||
* process is complete does the status get set to `sent`. | ||
* | ||
* It's this we are waiting for because then we can extract the generated bill numbers and transaction file reference | ||
* and apply them to our bill run records. | ||
* | ||
* See {@link https://defra.github.io/sroc-charging-module-api-docs/#/bill-run/SendBillRun | CHA API docs} for more | ||
* details | ||
* @param {string} billRunId - UUID of the charging module API bill run to send | ||
* | ||
* @returns {Promise<Object>} The result of the request; whether it succeeded and the response or error returned | ||
*/ | ||
async function go (billRunId) { | ||
const path = `v3/wrls/bill-runs/${billRunId}/generate` | ||
const result = await ChargingModuleRequestLib.patch(path) | ||
|
||
return result | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
'use strict' | ||
|
||
/** | ||
* Connects with the Charging Module to send a bill run | ||
* @module ChargingModuleSendBillRunService | ||
*/ | ||
|
||
const { setTimeout } = require('node:timers/promises') | ||
|
||
const BillRunStatusService = require('./bill-run-status.service.js') | ||
const ExpandedError = require('../../errors/expanded.error.js') | ||
|
||
const ONE_SECOND = 1000 | ||
|
||
async function go (billRunId, statusToWaitFor, maximumAttempts = 120) { | ||
let attempts = 0 | ||
let status | ||
|
||
// | ||
do { | ||
await _pause(attempts) | ||
|
||
const result = await BillRunStatusService.go(billRunId) | ||
|
||
if (!result.succeeded) { | ||
_requestFailed(billRunId, result) | ||
} | ||
|
||
status = result.response.body.status | ||
attempts += 1 | ||
} while (status !== statusToWaitFor || attempts >= maximumAttempts) | ||
|
||
if (status !== statusToWaitFor) { | ||
_statusNotAchieved(billRunId, statusToWaitFor, status, attempts, maximumAttempts) | ||
} | ||
} | ||
|
||
/** | ||
* Pause for one second between requests so that we are not bombarding the Charging Module | ||
*/ | ||
function _pause (attempts) { | ||
// If attempts is 0 then this is the first attempt so don't pause | ||
if (attempts === 0) { | ||
return | ||
} | ||
|
||
return setTimeout(ONE_SECOND) | ||
} | ||
|
||
function _requestFailed (billRunId, result) { | ||
const error = new ExpandedError( | ||
'Charging Module status request failed', | ||
{ billRunExternalId: billRunId, responseBody: result.response.body } | ||
) | ||
|
||
throw error | ||
} | ||
|
||
function _statusNotAchieved (billRunId, statusToWaitFor, status, attempts, maximumAttempts) { | ||
const error = new ExpandedError( | ||
'Charging Module wait for status failed', | ||
{ billRunExternalId: billRunId, statusToWaitFor, lastStatus: status, attempts, maximumAttempts } | ||
) | ||
|
||
throw error | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |