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

Select SROC supplementary charge versions for real #27

Merged
merged 13 commits into from
Nov 15, 2022
Merged
7 changes: 5 additions & 2 deletions app/controllers/test/supplementary.controller.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
'use strict'

const FindRegionService = require('../../services/test/find_region.service')
const SupplementaryService = require('../../services/test/supplementary.service.js')

class SupplementaryController {
static async index (_request, h) {
const result = await SupplementaryService.go()
static async index (request, h) {
const { regionId } = await FindRegionService.go(request.query.region)

const result = await SupplementaryService.go(regionId)

return h.response(result).code(200)
}
Expand Down
44 changes: 44 additions & 0 deletions app/services/test/find_region.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict'

/**
* @module FindRegionService
*/

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

/**
* @module FindRegionService
*/

class FindRegionService {
/**
* Returns the `region_id` for the matching record in `water.regions`
*
* > This is a temporary service added whilst developing the new SROC supplementary bill run functionality. We expect
* > the region ID to be provided by the UI as part of the normal workflow
*
* @param {string} naldRegionId The NALD region ID (a number between 1 to 9, 9 being the test region) for the region
* to find
*
* @returns {string} The region_id (a GUID) for the matching region
*/
static async go (naldRegionId) {
const region = await this._fetchRegion(naldRegionId)

return region
}

static async _fetchRegion (naldRegionId) {
const result = await db
.select('region_id')
.from('water.regions')
.where({
nald_region_id: naldRegionId
})
.first()

return result
}
}

module.exports = FindRegionService
32 changes: 18 additions & 14 deletions app/services/test/supplementary.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,30 @@
const { db } = require('../../../db/db')

/**
* Returns charge versions selected for supplementary billing
* At present this returns a set response until further development
*/
* @module SupplementaryService
*/

// Format into the response and return the data
class SupplementaryService {
static async go () {
const chargeVersions = await this._fetchChargeVersions()
const response = {
chargeVersions
}
static async go (regionId) {
const chargeVersions = await this._fetchChargeVersions(regionId)
const response = { chargeVersions }

return response
}

static async _fetchChargeVersions () {
const chargeVersions = db.table('water.charge_versions')
.where('scheme', 'sroc')
.select('chargeVersionId')
.select('licenceRef')
static async _fetchChargeVersions (regionId) {
const chargeVersions = db
.select('chargeVersionId', 'licences.licenceRef')
.from('water.charge_versions')
.innerJoin('water.licences', 'charge_versions.licence_id', 'licences.licence_id')
.where({
scheme: 'sroc',
end_date: null
})
.andWhere({
'licences.include_in_supplementary_billing': 'yes',
'licences.region_id': regionId
})

return chargeVersions
}
Expand Down
35 changes: 35 additions & 0 deletions db/migrations/20221111155222_create_licences.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict'

const tableName = 'licences'

exports.up = async function (knex) {
await knex
.schema
.withSchema('water')
.createTable(tableName, table => {
// Primary Key
table.uuid('licence_id').primary().defaultTo(knex.raw('gen_random_uuid()'))

// Data
table.string('licence_ref')
table.string('include_in_supplementary_billing')

// Automatic timestamps
table.timestamps(false, true)
})

await knex.raw(`
CREATE TRIGGER update_timestamp
BEFORE UPDATE
ON water.${tableName}
FOR EACH ROW
EXECUTE PROCEDURE update_timestamp();
`)
}

exports.down = function (knex) {
return knex
.schema
.withSchema('water')
.dropTableIfExists(tableName)
}
22 changes: 22 additions & 0 deletions db/migrations/20221111184905_alter_charge_versions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict'

const tableName = 'charge_versions'

exports.up = async function (knex) {
await knex
.schema
.withSchema('water')
.alterTable(tableName, table => {
table.uuid('licence_id')
table.date('end_date')
})
}

exports.down = function (knex) {
return knex
.schema
.withSchema('water')
.alterTable(tableName, table => {
table.dropColumns('licence_id', 'end_date')
})
}
35 changes: 35 additions & 0 deletions db/migrations/20221114104700_create_regions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict'

const tableName = 'regions'

exports.up = async function (knex) {
await knex
.schema
.withSchema('water')
.createTable(tableName, table => {
// Primary Key
table.uuid('region_id').primary().defaultTo(knex.raw('gen_random_uuid()'))

// Data
table.string('charge_region_id')
table.integer('nald_region_id')

// Automatic timestamps
table.timestamps(false, true)
})

await knex.raw(`
CREATE TRIGGER update_timestamp
BEFORE UPDATE
ON water.${tableName}
FOR EACH ROW
EXECUTE PROCEDURE update_timestamp();
`)
}

exports.down = function (knex) {
return knex
.schema
.withSchema('water')
.dropTableIfExists(tableName)
}
21 changes: 21 additions & 0 deletions db/migrations/20221114155444_alter_licences.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict'

const tableName = 'licences'

exports.up = async function (knex) {
await knex
.schema
.withSchema('water')
.alterTable(tableName, table => {
table.uuid('region_id')
})
}

exports.down = function (knex) {
return knex
.schema
.withSchema('water')
.alterTable(tableName, table => {
table.dropColumns('region_id')
})
}
7 changes: 6 additions & 1 deletion test/controllers/test/supplementary.controller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ const Sinon = require('sinon')
const { describe, it, beforeEach, after } = exports.lab = Lab.script()
const { expect } = Code

// Test helpers
const LicenceHelper = require('../../support/helpers/licence.helper.js')

// Things we need to stub
const FindRegionService = require('../../../app/services/test/find_region.service')
const SupplementaryService = require('../../../app/services/test/supplementary.service.js')

// For running our service
Expand All @@ -28,12 +32,13 @@ describe('Supplementary controller', () => {
describe('GET /test/supplementary', () => {
const options = {
method: 'GET',
url: '/test/supplementary'
url: '/test/supplementary?region=9'
}

let response

beforeEach(async () => {
Sinon.stub(FindRegionService, 'go').resolves({ regionId: LicenceHelper.defaults().region_id })
Sinon.stub(SupplementaryService, 'go').resolves({ chargeVersions: [] })

response = await server.inject(options)
Expand Down
101 changes: 85 additions & 16 deletions test/services/test/supplementary.service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,114 @@ const { describe, it, beforeEach } = exports.lab = Lab.script()
const { expect } = Code

// Test helpers
const ChargeVersionHelper = require('../../support/helpers/charge_version.helper')
const DatabaseHelper = require('../../support/helpers/database.helper')
const ChargeVersionHelper = require('../../support/helpers/charge_version.helper.js')
const DatabaseHelper = require('../../support/helpers/database.helper.js')
const LicenceHelper = require('../../support/helpers/licence.helper.js')

// Thing under test
const SupplementaryService = require('../../../app/services/test/supplementary.service.js')

describe('Supplementary service', () => {
const testData = {
sroc: { licence_ref: '01/123', scheme: 'sroc' },
alcs: { licence_ref: '01/456', scheme: 'alcs' }
}
const { region_id: regionId } = LicenceHelper.defaults()
let testRecords

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

describe('when there are charge versions to be included in supplimentery billing', () => {
describe('when there are licences to be included in supplementary billing', () => {
beforeEach(async () => {
testRecords = await ChargeVersionHelper.add([testData.sroc, testData.alcs])
// This creates an SROC charge version linked to a licence marked for supplementary billing
const srocChargeVersion = await ChargeVersionHelper.add(
{},
{ include_in_supplementary_billing: 'yes' }
)

// This creates an ALCS (presroc) charge version linked to a licence marked for supplementary billing
const alcsChargeVersion = await ChargeVersionHelper.add(
{ scheme: 'alcs' },
{ include_in_supplementary_billing: 'yes' }
)

testRecords = [srocChargeVersion, alcsChargeVersion]
})

it('returns only those that match', async () => {
const result = await SupplementaryService.go()
it('returns only the current SROC charge versions that are applicable', async () => {
const result = await SupplementaryService.go(regionId)

expect(result.chargeVersions.length).to.equal(1)
expect(result.chargeVersions[0].charge_version_id).to.equal(testRecords[0].charge_version_id)
})
})

describe('when there are no charge versions to be included in supplimentery billing', () => {
beforeEach(async () => {
testRecords = await ChargeVersionHelper.add(testData.alcs)
describe('when there are no licences to be included in supplementary billing', () => {
describe("because none of them are marked 'include_in_supplementary_billing'", () => {
beforeEach(async () => {
// This creates an SROC charge version linked to a licence. But the licence won't be marked for supplementary
// billing
const srocChargeVersion = await ChargeVersionHelper.add()
testRecords = [srocChargeVersion]
})

it('returns no applicable charge versions', async () => {
const result = await SupplementaryService.go(regionId)

expect(result.chargeVersions.length).to.equal(0)
})
})

describe("because all the applicable charge versions are 'alcs' (presroc)", () => {
beforeEach(async () => {
// This creates an ALCS (presroc) charge version linked to a licence marked for supplementary billing
const alcsChargeVersion = await ChargeVersionHelper.add(
{ scheme: 'alcs' },
{ include_in_supplementary_billing: 'yes' }
)
testRecords = [alcsChargeVersion]
})

it('returns no applicable charge versions', async () => {
const result = await SupplementaryService.go(regionId)

expect(result.chargeVersions.length).to.equal(0)
})
})

it('returns no matches', async () => {
const result = await SupplementaryService.go()
describe('because there are no current charge versions (they all have end dates)', () => {
beforeEach(async () => {
// This creates an SROC charge version with an end date linked to a licence marked for supplementary billing
const alcsChargeVersion = await ChargeVersionHelper.add(
{ end_date: new Date(2022, 2, 1) }, // 2022-03-01 - Months are zero indexed :-)
{ include_in_supplementary_billing: 'yes' }
)
testRecords = [alcsChargeVersion]
})

it('returns no applicable charge versions', async () => {
const result = await SupplementaryService.go(regionId)

expect(result.chargeVersions.length).to.equal(0)
})
})

describe('because there are no licences linked to the selected region', () => {
beforeEach(async () => {
// This creates an SROC charge version linked to a licence with an different region than selected
const otherRegionChargeVersion = await ChargeVersionHelper.add(
{},
{
include_in_supplementary_billing: 'yes',
region_id: 'e117b501-e3c1-4337-ad35-21c60ed9ad73'
}
)
testRecords = [otherRegionChargeVersion]
})

it('returns no applicable charge versions', async () => {
const result = await SupplementaryService.go(regionId)

expect(result.chargeVersions.length).to.equal(0)
expect(result.chargeVersions.length).to.equal(0)
})
})
})
})
Loading