From 96dcb9d1be546819d41163c01bbf4244ab7bacc0 Mon Sep 17 00:00:00 2001 From: Jason Claxton <30830544+Jozzey@users.noreply.github.com> Date: Tue, 10 Oct 2023 11:20:26 +0100 Subject: [PATCH] Create migration script, model, helper and unit tests for `licence_versions` (#456) https://eaflood.atlassian.net/browse/WATER-3486 Whilst working on the unit tests for the enhancement in this PR https://github.com/DEFRA/water-abstraction-system/pull/443 it was found that we would need the migration script, model, helper and unit tests for table `licence_versions`. These will be created in this PR. --- app/models/water/licence-version.model.js | 42 ++++++++++++ app/models/water/licence.model.js | 8 +++ ...009155523_create-water-licence-versions.js | 34 ++++++++++ .../water/licence-version.model.test.js | 68 +++++++++++++++++++ test/models/water/licence.model.test.js | 37 ++++++++++ .../helpers/water/licence-version.helper.js | 68 +++++++++++++++++++ 6 files changed, 257 insertions(+) create mode 100644 app/models/water/licence-version.model.js create mode 100644 db/migrations/20231009155523_create-water-licence-versions.js create mode 100644 test/models/water/licence-version.model.test.js create mode 100644 test/support/helpers/water/licence-version.helper.js diff --git a/app/models/water/licence-version.model.js b/app/models/water/licence-version.model.js new file mode 100644 index 0000000000..bbf6b393cd --- /dev/null +++ b/app/models/water/licence-version.model.js @@ -0,0 +1,42 @@ +'use strict' + +/** + * Model for licenceVersions + * @module LicenceVersionModel + */ + +const { Model } = require('objection') + +const WaterBaseModel = require('./water-base.model.js') + +class LicenceVersionModel extends WaterBaseModel { + static get tableName () { + return 'licenceVersions' + } + + static get idColumn () { + return 'licenceVersionId' + } + + static get translations () { + return [ + { database: 'dateCreated', model: 'createdAt' }, + { database: 'dateUpdated', model: 'updatedAt' } + ] + } + + static get relationMappings () { + return { + licence: { + relation: Model.BelongsToOneRelation, + modelClass: 'licence.model', + join: { + from: 'licenceVersions.licenceId', + to: 'licences.licenceId' + } + } + } + } +} + +module.exports = LicenceVersionModel diff --git a/app/models/water/licence.model.js b/app/models/water/licence.model.js index 7c0cf25af4..04eb18b864 100644 --- a/app/models/water/licence.model.js +++ b/app/models/water/licence.model.js @@ -58,6 +58,14 @@ class LicenceModel extends WaterBaseModel { from: 'licences.licenceId', to: 'chargeVersionWorkflows.licenceId' } + }, + licenceVersions: { + relation: Model.HasManyRelation, + modelClass: 'licence-version.model', + join: { + from: 'licences.licenceId', + to: 'licenceVersions.licenceId' + } } } } diff --git a/db/migrations/20231009155523_create-water-licence-versions.js b/db/migrations/20231009155523_create-water-licence-versions.js new file mode 100644 index 0000000000..00699ff1e4 --- /dev/null +++ b/db/migrations/20231009155523_create-water-licence-versions.js @@ -0,0 +1,34 @@ +'use strict' + +const tableName = 'licence_versions' + +exports.up = function (knex) { + return knex + .schema + .withSchema('water') + .createTable(tableName, (table) => { + // Primary Key + table.uuid('licence_version_id').primary().defaultTo(knex.raw('gen_random_uuid()')) + + // Data + table.uuid('licence_id').notNullable() + table.integer('issue').notNullable() + table.integer('increment').notNullable() + table.string('status').notNullable() + table.date('start_date').notNullable() + table.date('end_date') + table.string('external_id').notNullable() + table.boolean('is_test').notNullable().defaultTo(false) + + // Legacy timestamps + table.timestamp('date_created', { useTz: false }).notNullable() + table.timestamp('date_updated', { useTz: false }).notNullable() + }) +} + +exports.down = function (knex) { + return knex + .schema + .withSchema('water') + .dropTableIfExists(tableName) +} diff --git a/test/models/water/licence-version.model.test.js b/test/models/water/licence-version.model.test.js new file mode 100644 index 0000000000..9e5ddd6de3 --- /dev/null +++ b/test/models/water/licence-version.model.test.js @@ -0,0 +1,68 @@ +'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 DatabaseHelper = require('../../support/helpers/database.helper.js') +const LicenceHelper = require('../../support/helpers/water/licence.helper.js') +const LicenceModel = require('../../../app/models/water/licence.model.js') +const LicenceVersionHelper = require('../../support/helpers/water/licence-version.helper.js') + +// Thing under test +const LicenceVersionModel = require('../../../app/models/water/licence-version.model.js') + +describe('Licence Version model', () => { + let testRecord + + beforeEach(async () => { + await DatabaseHelper.clean() + + testRecord = await LicenceVersionHelper.add() + }) + + describe('Basic query', () => { + it('can successfully run a basic query', async () => { + const result = await LicenceVersionModel.query().findById(testRecord.licenceVersionId) + + expect(result).to.be.an.instanceOf(LicenceVersionModel) + expect(result.licenceVersionId).to.equal(testRecord.licenceVersionId) + }) + }) + + describe('Relationships', () => { + describe('when linking to licence', () => { + let testLicence + + beforeEach(async () => { + testLicence = await LicenceHelper.add() + + const { licenceId } = testLicence + testRecord = await LicenceVersionHelper.add({ licenceId }) + }) + + it('can successfully run a related query', async () => { + const query = await LicenceVersionModel.query() + .innerJoinRelated('licence') + + expect(query).to.exist() + }) + + it('can eager load the licence', async () => { + const result = await LicenceVersionModel.query() + .findById(testRecord.licenceVersionId) + .withGraphFetched('licence') + + expect(result).to.be.instanceOf(LicenceVersionModel) + expect(result.licenceVersionId).to.equal(testRecord.licenceVersionId) + + expect(result.licence).to.be.an.instanceOf(LicenceModel) + expect(result.licence).to.equal(testLicence) + }) + }) + }) +}) diff --git a/test/models/water/licence.model.test.js b/test/models/water/licence.model.test.js index 1bd0611809..75351c6392 100644 --- a/test/models/water/licence.model.test.js +++ b/test/models/water/licence.model.test.js @@ -14,6 +14,8 @@ const ChargeVersionHelper = require('../../support/helpers/water/charge-version. const ChargeVersionModel = require('../../../app/models/water/charge-version.model.js') const DatabaseHelper = require('../../support/helpers/database.helper.js') const LicenceHelper = require('../../support/helpers/water/licence.helper.js') +const LicenceVersionHelper = require('../../support/helpers/water/licence-version.helper.js') +const LicenceVersionModel = require('../../../app/models/water/licence-version.model.js') const RegionHelper = require('../../support/helpers/water/region.helper.js') const RegionModel = require('../../../app/models/water/region.model.js') const WorkflowHelper = require('../../support/helpers/water/workflow.helper.js') @@ -175,5 +177,40 @@ describe('Licence model', () => { expect(result.workflows).to.include(testWorkflows[1]) }) }) + + describe('when linking to licence versions', () => { + let testLicenceVersions + + beforeEach(async () => { + const { licenceId } = testRecord + + testLicenceVersions = [] + for (let i = 0; i < 2; i++) { + const licenceVersion = await LicenceVersionHelper.add({ licenceId }) + testLicenceVersions.push(licenceVersion) + } + }) + + it('can successfully run a related query', async () => { + const query = await LicenceModel.query() + .innerJoinRelated('licenceVersions') + + expect(query).to.exist() + }) + + it('can eager load the licence versions', async () => { + const result = await LicenceModel.query() + .findById(testRecord.licenceId) + .withGraphFetched('licenceVersions') + + expect(result).to.be.instanceOf(LicenceModel) + expect(result.licenceId).to.equal(testRecord.licenceId) + + expect(result.licenceVersions).to.be.an.array() + expect(result.licenceVersions[0]).to.be.an.instanceOf(LicenceVersionModel) + expect(result.licenceVersions).to.include(testLicenceVersions[0]) + expect(result.licenceVersions).to.include(testLicenceVersions[1]) + }) + }) }) }) diff --git a/test/support/helpers/water/licence-version.helper.js b/test/support/helpers/water/licence-version.helper.js new file mode 100644 index 0000000000..59cd617266 --- /dev/null +++ b/test/support/helpers/water/licence-version.helper.js @@ -0,0 +1,68 @@ +'use strict' + +/** + * @module LicenceVersionHelper + */ + +const { generateUUID, timestampForPostgres } = require('../../../../app/lib/general.lib.js') +const { randomInteger } = require('../general.helper.js') +const LicenceVersionModel = require('../../../../app/models/water/licence-version.model.js') + +/** + * Add a new licence version + * + * If no `data` is provided, default values will be used. These are + * + * - `licenceId` - [random UUID] + * - `issue` - 1 + * - `increment` - 0 + * - `status` - 'current' + * - `startDate` - new Date('2022-01-01') + * - `externalId` - [randomly generated - 9:99999:1:0] + * - `createdAt` - new Date() + * - `updatedAt` - new Date() + * + * @param {Object} [data] Any data you want to use instead of the defaults used here or in the database + * + * @returns {module:LicenceVersionModel} The instance of the newly created record + */ +async function add (data = {}) { + const insertData = defaults(data) + + return LicenceVersionModel.query() + .insert({ ...insertData }) + .returning('*') +} + +/** + * Returns the defaults used + * + * It will override or append to them any data provided. Mainly used by the `add()` method, we make it available + * for use in tests to avoid having to duplicate values. + * + * @param {Object} [data] Any data you want to use instead of the defaults used here or in the database + */ +function defaults (data = {}) { + const timestamp = timestampForPostgres() + + const defaults = { + licenceId: generateUUID(), + issue: 1, + increment: 0, + status: 'current', + startDate: new Date('2022-01-01'), + externalId: `9:${randomInteger(10000, 99999)}:1:0`, + createdAt: timestamp, + updatedAt: timestamp + } + + return { + ...defaults, + ...data + } +} + +module.exports = { + add, + defaults +}