Skip to content

Commit

Permalink
Refactor CreateEventService for bill runs (#73)
Browse files Browse the repository at this point in the history
https://eaflood.atlassian.net/browse/WATER-3831

We've created the model and a service wrapper for creating events. But at this time we are only interested in creating an `event` when a new bill run is initialised. That means some fields will always be set with a certain value.

Also, based on reviewing existing events created by the legacy code the `metadata` holds a formatted version of a bill run. So, we need to handle that.

All this means we'd be better placed to refactor the existing service to focus on new bill-run events.

** Notes

- Add migrations for missing fields
  There are columns on the `regions` and `billing_batches` tables that the existing logic extracts data from that isn't present in our test db. So, we add alter migrations for the missing fields and update our helpers accordingly.

- Add presenter needed to format metadata content
  The metadata field in an event record doesn't just contain a dump of the BillingBatch as JSON. Instead, it is a specifically formatted object. So, we need something that will convert the `BillingBatchModel` instance into the content we need.

- Add source as a default in BillingBatchHelper
  Source is populated when a billing batch event is created for real. So, we ensure it's populated in our helper to reflect that.
  • Loading branch information
Cruikshanks authored Jan 2, 2023
1 parent 031bc77 commit 6d4e6e8
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
'use strict'

/**
* Formats a `BillingBatchModel` into the metadata content needed for a bill batch's 'event' record
* @module CreateBillingBatchEventPresenter
*/

function go (billingBatch) {
const {
batchType,
billingBatchId,
creditNoteCount,
creditNoteValue,
dateCreated,
createdAt,
dateUpdated,
updatedAt,
fromFinancialYearEnding,
invoiceCount,
invoiceValue,
isSummer,
netTotal,
region,
source,
status,
toFinancialYearEnding
} = billingBatch
return {
batch: {
id: billingBatchId,
type: batchType,
region: {
id: region.regionId,
code: region.chargeRegionId,
name: region.name,
type: 'region',
displayName: region.displayName,
numericCode: region.naldRegionId
},
source,
status,
endYear: { yearEnding: toFinancialYearEnding },
invoices: [],
isSummer,
netTotal,
startYear: { yearEnding: fromFinancialYearEnding },
// NOTE: In the 'real' schema timestamp fields are dateCreated & dateUpdated. If you follow the standard
// convention of using a trigger as seen in db/migrations/[*]_create_update_timestamp_trigger.js you get
// createdAt & updatedAt. In our testing schema we use the later. To ensure unit tests pass we need to account
// for both.
dateCreated: dateCreated ?? createdAt,
dateUpdated: dateUpdated ?? updatedAt,
invoiceCount,
invoiceValue,
creditNoteCount,
creditNoteValue
}
}
}

module.exports = {
go
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict'

/**
* Creates the event for when a new billing batch is initialised
* @module CreateBillingBatchEventService
*/

const CreateBillingBatchEventPresenter = require('../../presenters/supplementary-billing/create-billing-batch-event.presenter.js')
const EventModel = require('../../models/event.model.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
*
* @returns {Object} The newly created event record
*/
async function go (billingBatch, issuer) {
const event = await EventModel.query()
.insert({
type: 'billing-batch',
subtype: billingBatch.batchType,
issuer,
metadata: _metadata(billingBatch),
status: 'start'
})
.returning('*')

return event
}

function _metadata (billingBatch) {
return CreateBillingBatchEventPresenter.go(billingBatch)
}

module.exports = {
go
}
37 changes: 0 additions & 37 deletions app/services/supplementary-billing/create-event.service.js

This file was deleted.

22 changes: 22 additions & 0 deletions db/migrations/20230102173756_alter_regions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict'

const tableName = 'regions'

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

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

const tableName = 'billing_batches'

exports.up = async function (knex) {
await knex
.schema
.withSchema('water')
.alterTable(tableName, table => {
table.boolean('is_summer').notNullable().defaultTo(false)
})
}

exports.down = function (knex) {
return knex
.schema
.withSchema('water')
.alterTable(tableName, table => {
table.dropColumns('is_summer')
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict'

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

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

// Test helpers
const BillingBatchHelper = require('../../support/helpers/billing-batch.helper.js')
const BillingBatchModel = require('../../../app/models/billing-batch.model.js')
const DatabaseHelper = require('../../support/helpers/database.helper.js')
const RegionHelper = require('../../support/helpers/region.helper.js')

// Thing under test
const CreateBillingBatchEventPresenter = require('../../../app/presenters/supplementary-billing/create-billing-batch-event.presenter.js')

describe('Create Billing Batch Event presenter', () => {
beforeEach(async () => {
await DatabaseHelper.clean()
})

describe('when a BillingBatchModel instance is provided', () => {
let billingBatch

beforeEach(async () => {
const region = await RegionHelper.add()
const testBillingBatch = await BillingBatchHelper.add({ regionId: region.regionId })

billingBatch = await BillingBatchModel.query()
.findById(testBillingBatch.billingBatchId)
.withGraphFetched('region')
})

it('correctly presents the data', () => {
const result = CreateBillingBatchEventPresenter.go(billingBatch)

expect(result.batch).to.exist()
expect(result.batch.id).to.equal(billingBatch.billingBatchId)
expect(result.batch.type).to.equal(billingBatch.batchType)
expect(result.batch.source).to.equal(billingBatch.source)
expect(result.batch.status).to.equal(billingBatch.status)
expect(result.batch.isSummer).to.equal(billingBatch.isSummer)
expect(result.batch.netTotal).to.equal(billingBatch.netTotal)

expect(result.batch.dateCreated).to.equal(billingBatch.createdAt)
expect(result.batch.dateUpdated).to.equal(billingBatch.updatedAt)
expect(result.batch.invoiceCount).to.equal(billingBatch.invoiceCount)
expect(result.batch.invoiceValue).to.equal(billingBatch.invoiceValue)
expect(result.batch.creditNoteCount).to.equal(billingBatch.creditNoteCount)
expect(result.batch.creditNoteValue).to.equal(billingBatch.creditNoteValue)

expect(result.batch.region).to.equal({
id: billingBatch.region.regionId,
code: billingBatch.region.chargeRegionId,
name: billingBatch.region.name,
type: 'region',
displayName: billingBatch.region.displayName,
numericCode: billingBatch.region.naldRegionId
})

expect(result.batch.endYear).to.equal({ yearEnding: billingBatch.toFinancialYearEnding })
expect(result.batch.startYear).to.equal({ yearEnding: billingBatch.fromFinancialYearEnding })
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use strict'

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

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

// Test helpers
const BillingBatchHelper = require('../../support/helpers/billing-batch.helper.js')
const BillingBatchModel = require('../../../app/models/billing-batch.model.js')
const DatabaseHelper = require('../../support/helpers/database.helper.js')
const EventModel = require('../../../app/models/event.model.js')
const RegionHelper = require('../../support/helpers/region.helper.js')

// Thing under test
const CreateBillingBatchEventService = require('../../../app/services/supplementary-billing/create-billing-batch-event.service.js')

describe('Create Event service', () => {
beforeEach(async () => {
await DatabaseHelper.clean()
})

describe('when a BillingBatchModel instance is provided', () => {
const issuer = 'test.user@defra.gov.uk'
let billingBatch

beforeEach(async () => {
const region = await RegionHelper.add()
const testBillingBatch = await BillingBatchHelper.add({ regionId: region.regionId })

billingBatch = await BillingBatchModel.query()
.findById(testBillingBatch.billingBatchId)
.withGraphFetched('region')
})

it('creates an event record', async () => {
const result = await CreateBillingBatchEventService.go(billingBatch, issuer)

expect(result).to.be.an.instanceOf(EventModel)

expect(result.type).to.equal('billing-batch')
expect(result.subtype).to.equal(billingBatch.batchType)
expect(result.issuer).to.equal(issuer)
expect(result.status).to.equal('start')

expect(result.metadata).to.exist()
expect(result.metadata.batch.id).to.equal(billingBatch.billingBatchId)
})
})
})
45 changes: 0 additions & 45 deletions test/services/supplementary-billing/create-event.service.test.js

This file was deleted.

4 changes: 3 additions & 1 deletion test/support/helpers/billing-batch.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const BillingBatchModel = require('../../../app/models/billing-batch.model.js')
* - `toFinancialYearEnding` - 2023
* - `status` - processing
* - `scheme` - sroc
* - `source` - wrls
*
* @param {Object} [data] Any data you want to use instead of the defaults used here or in the database
*
Expand Down Expand Up @@ -45,7 +46,8 @@ function defaults (data = {}) {
fromFinancialYearEnding: 2023,
toFinancialYearEnding: 2023,
status: 'processing',
scheme: 'sroc'
scheme: 'sroc',
source: 'wrls'
}

return {
Expand Down
6 changes: 5 additions & 1 deletion test/support/helpers/region.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const RegionModel = require('../../../app/models/region.model.js')
*
* - `chargeRegionId` - S
* - `naldRegionId` - 9
* - `name` - Sroc Supplementary Bill (Test)
* - `displayName` - Sroc Test
*
* @param {Object} [data] Any data you want to use instead of the defaults used here or in the database
*
Expand All @@ -37,7 +39,9 @@ function add (data = {}) {
function defaults (data = {}) {
const defaults = {
chargeRegionId: 'S',
naldRegionId: 9
naldRegionId: 9,
name: 'Sroc Supplementary Bill (Test)',
displayName: 'Sroc Test'
}

return {
Expand Down

0 comments on commit 6d4e6e8

Please sign in to comment.