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

Implement Charging Module Create Bill Run Service #84

Merged
merged 11 commits into from
Jan 11, 2023
74 changes: 74 additions & 0 deletions app/services/charging-module-create-bill-run.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
'use strict'

/**
* Connects with the Charging Module to create a new bill run
* @module ChargingModuleCreateBillRunService
*/

const ChargeModuleTokenService = require('./charge-module-token.service.js')
const RegionModel = require('../models/water/region.model.js')
const RequestLib = require('../lib/request.lib.js')

const servicesConfig = require('../../config/services.config.js')

/**
* Sends a request to the Charging Module to create a new bill run and returns the result.
*
* @param {string} regionId The UUID of the region the bill run is to be created for
* @param {string} ruleset The ruleset that the bill run is to be created for, either `sroc` or `presroc`
*
* @returns {Object} result An object representing the result of the request
* @returns {boolean} result.succeeded Whether the bill run creation request was successful
* @returns {Object} result.response Details of the created bill run if successful; or the error response if not
*/
async function go (regionId, ruleset) {
const url = new URL('/v3/wrls/bill-runs', servicesConfig.chargingModule.url)

const authentication = await ChargeModuleTokenService.go()

const options = await _options(regionId, ruleset, authentication)
const result = await RequestLib.post(url.href, options)

return _parseResult(result)
}

async function _options (regionId, ruleset, authentication) {
const region = await _getChargeRegionId(regionId)

return {
headers: {
authorization: `Bearer ${authentication.accessToken}`
},
body: {
region,
ruleset
}
}
}

// Gets the single-letter charge region id for the provided region id UUID
async function _getChargeRegionId (regionId) {
const result = await RegionModel.query()
.select('chargeRegionId')
.findOne('regionId', regionId)

return result.chargeRegionId
}

function _parseResult (result) {
// Simply return the result as-is if we were unsuccessful
if (!result.succeeded) {
return result
}

const parsedBody = JSON.parse(result.response.body)

return {
succeeded: true,
response: parsedBody.billRun
}
}

module.exports = {
go
}
102 changes: 102 additions & 0 deletions test/services/charging-module-create-bill-run.service.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
'use strict'

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

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

// Test helpers
const DatabaseHelper = require('../support/helpers/database.helper.js')
const RegionHelper = require('../support/helpers/water/region.helper.js')

// Things we need to stub
const ChargeModuleTokenService = require('../../app/services/charge-module-token.service.js')
const RequestLib = require('../../app/lib/request.lib.js')

// Thing under test
const ChargingModuleCreateBillRunService = require('../../app/services/charging-module-create-bill-run.service.js')

describe('Charge module create bill run service', () => {
let testRegion

beforeEach(async () => {
await DatabaseHelper.clean()
testRegion = await RegionHelper.add()

Sinon.stub(ChargeModuleTokenService, 'go').resolves({
accessToken: 'ACCESS_TOKEN',
expiresIn: 3600
})
})

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

describe('when the service can create a bill run', () => {
let result

beforeEach(async () => {
Sinon.stub(RequestLib, 'post').resolves({
succeeded: true,
response: {
statusCode: 200,
body: '{"billRun": {"id": "2bbbe459-966e-4026-b5d2-2f10867bdddd", "billRunNumber": 10004}}'
}
})

result = await ChargingModuleCreateBillRunService.go(testRegion.regionId, 'sroc')
})

it('calls the Charging Module with the required options', async () => {
const requestArgs = RequestLib.post.firstCall.args

expect(requestArgs[0]).to.endWith('/wrls/bill-runs')
expect(requestArgs[1].headers).to.include({ authorization: 'Bearer ACCESS_TOKEN' })
expect(requestArgs[1].body).to.include({ region: testRegion.chargeRegionId, ruleset: 'sroc' })
})

it('returns a `true` success status', async () => {
expect(result.succeeded).to.be.true()
})

it('returns the bill run id and number in the `response`', async () => {
const { response } = result

expect(response.id).to.equal('2bbbe459-966e-4026-b5d2-2f10867bdddd')
expect(response.billRunNumber).to.equal(10004)
})
})

describe('when the service cannot create a bill run', () => {
let result

beforeEach(async () => {
Sinon.stub(RequestLib, 'post').resolves({
succeeded: false,
response: {
statusCode: 403,
error: 'Forbidden',
message: "Unauthorised for regime 'wrls'"
}
})

result = await ChargingModuleCreateBillRunService.go(testRegion.regionId, 'sroc')
})

it('returns a `false` success status', async () => {
expect(result.succeeded).to.be.false()
})

it('returns the error in the `response`', async () => {
const { response } = result

expect(response.statusCode).to.equal(403)
expect(response.error).to.equal('Forbidden')
expect(response.message).to.equal("Unauthorised for regime 'wrls'")
})
})
})