From f08cb7b53a954ada378870aa66ffb0f3dca619df Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Fri, 25 Aug 2023 13:59:35 +0100 Subject: [PATCH 1/6] Update new CRM_V2 models with relationships https://eaflood.atlassian.net/browse/WATER-4092 In the following PR's we added some new models for the `crm_v2` schema - [Add CRM_V2 address model](https://github.com/DEFRA/water-abstraction-system/pull/378) - [Add CRM_V2 contact model](https://github.com/DEFRA/water-abstraction-system/pull/379) - [Add CRM_V2 company model](https://github.com/DEFRA/water-abstraction-system/pull/380) - [Add CRM_V2 invoice account address model](https://github.com/DEFRA/water-abstraction-system/pull/381) To keep the changes to a minimum we omitted the relationships between them and the existing `InvoiceAccountModel`. This change adds those relationships in. From 0ed22cee0bdc9f0c56e80cce0e23ee6c43b8109f Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Fri, 25 Aug 2023 14:04:57 +0100 Subject: [PATCH 2/6] Add address model relationships --- app/models/crm-v2/address.model.js | 15 +++++++++ test/models/crm-v2/address.model.test.js | 40 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/app/models/crm-v2/address.model.js b/app/models/crm-v2/address.model.js index e413c0c174..60b0bbca1d 100644 --- a/app/models/crm-v2/address.model.js +++ b/app/models/crm-v2/address.model.js @@ -5,6 +5,8 @@ * @module AddressModel */ +const { Model } = require('objection') + const CrmV2BaseModel = require('./crm-v2-base.model.js') class AddressModel extends CrmV2BaseModel { @@ -22,6 +24,19 @@ class AddressModel extends CrmV2BaseModel { { database: 'dateUpdated', model: 'updatedAt' } ] } + + static get relationMappings () { + return { + invoiceAccountAddresses: { + relation: Model.HasManyRelation, + modelClass: 'invoice-account-address.model', + join: { + from: 'addresses.addressId', + to: 'invoiceAccountAddresses.addressId' + } + } + } + } } module.exports = AddressModel diff --git a/test/models/crm-v2/address.model.test.js b/test/models/crm-v2/address.model.test.js index 5cd99e9c97..8080654097 100644 --- a/test/models/crm-v2/address.model.test.js +++ b/test/models/crm-v2/address.model.test.js @@ -10,6 +10,8 @@ const { expect } = Code // Test helpers const AddressHelper = require('../../support/helpers/crm-v2/address.helper.js') const DatabaseHelper = require('../../support/helpers/database.helper.js') +const InvoiceAccountAddressHelper = require('../../support/helpers/crm-v2/invoice-account-address.helper.js') +const InvoiceAccountAddressModel = require('../../../app/models/crm-v2/invoice-account-address.model.js') // Thing under test const AddressModel = require('../../../app/models/crm-v2/address.model.js') @@ -31,4 +33,42 @@ describe('Address model', () => { expect(result.addressId).to.equal(testRecord.addressId) }) }) + + describe('Relationships', () => { + describe('when linking to invoice account addresses', () => { + let testInvoiceAccountAddresses + + beforeEach(async () => { + testRecord = await AddressHelper.add() + const { addressId } = testRecord + + testInvoiceAccountAddresses = [] + for (let i = 0; i < 2; i++) { + const invoiceAccountAddress = await InvoiceAccountAddressHelper.add({ addressId }) + testInvoiceAccountAddresses.push(invoiceAccountAddress) + } + }) + + it('can successfully run a related query', async () => { + const query = await AddressModel.query() + .innerJoinRelated('invoiceAccountAddresses') + + expect(query).to.exist() + }) + + it('can eager load the invoice account addresses', async () => { + const result = await AddressModel.query() + .findById(testRecord.addressId) + .withGraphFetched('invoiceAccountAddresses') + + expect(result).to.be.instanceOf(AddressModel) + expect(result.addressId).to.equal(testRecord.addressId) + + expect(result.invoiceAccountAddresses).to.be.an.array() + expect(result.invoiceAccountAddresses[0]).to.be.an.instanceOf(InvoiceAccountAddressModel) + expect(result.invoiceAccountAddresses).to.include(testInvoiceAccountAddresses[0]) + expect(result.invoiceAccountAddresses).to.include(testInvoiceAccountAddresses[1]) + }) + }) + }) }) From fa0ed13fecbe7d02916f24460f3073ad3094f7c8 Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Fri, 25 Aug 2023 14:06:17 +0100 Subject: [PATCH 3/6] Add contact model relationships --- app/models/crm-v2/contact.model.js | 15 +++++++++ test/models/crm-v2/contact.model.test.js | 40 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/app/models/crm-v2/contact.model.js b/app/models/crm-v2/contact.model.js index 4a2c2a3007..14052bfb15 100644 --- a/app/models/crm-v2/contact.model.js +++ b/app/models/crm-v2/contact.model.js @@ -5,6 +5,8 @@ * @module ContactModel */ +const { Model } = require('objection') + const CrmV2BaseModel = require('./crm-v2-base.model.js') class ContactModel extends CrmV2BaseModel { @@ -23,6 +25,19 @@ class ContactModel extends CrmV2BaseModel { ] } + static get relationMappings () { + return { + invoiceAccountAddresses: { + relation: Model.HasManyRelation, + modelClass: 'invoice-account-address.model', + join: { + from: 'contacts.contactId', + to: 'invoiceAccountAddresses.contactId' + } + } + } + } + /** * Returns the name for the contact derived from its various parts * diff --git a/test/models/crm-v2/contact.model.test.js b/test/models/crm-v2/contact.model.test.js index 2d2209e68a..b24cb60c54 100644 --- a/test/models/crm-v2/contact.model.test.js +++ b/test/models/crm-v2/contact.model.test.js @@ -10,6 +10,8 @@ const { expect } = Code // Test helpers const ContactHelper = require('../../support/helpers/crm-v2/contact.helper.js') const DatabaseHelper = require('../../support/helpers/database.helper.js') +const InvoiceAccountAddressHelper = require('../../support/helpers/crm-v2/invoice-account-address.helper.js') +const InvoiceAccountAddressModel = require('../../../app/models/crm-v2/invoice-account-address.model.js') // Thing under test const ContactModel = require('../../../app/models/crm-v2/contact.model.js') @@ -32,6 +34,44 @@ describe('Contact model', () => { }) }) + describe('Relationships', () => { + describe('when linking to invoice account addresses', () => { + let testInvoiceAccountAddresses + + beforeEach(async () => { + testRecord = await ContactHelper.add() + const { contactId } = testRecord + + testInvoiceAccountAddresses = [] + for (let i = 0; i < 2; i++) { + const invoiceAccountAddress = await InvoiceAccountAddressHelper.add({ contactId }) + testInvoiceAccountAddresses.push(invoiceAccountAddress) + } + }) + + it('can successfully run a related query', async () => { + const query = await ContactModel.query() + .innerJoinRelated('invoiceAccountAddresses') + + expect(query).to.exist() + }) + + it('can eager load the invoice account addresses', async () => { + const result = await ContactModel.query() + .findById(testRecord.contactId) + .withGraphFetched('invoiceAccountAddresses') + + expect(result).to.be.instanceOf(ContactModel) + expect(result.contactId).to.equal(testRecord.contactId) + + expect(result.invoiceAccountAddresses).to.be.an.array() + expect(result.invoiceAccountAddresses[0]).to.be.an.instanceOf(InvoiceAccountAddressModel) + expect(result.invoiceAccountAddresses).to.include(testInvoiceAccountAddresses[0]) + expect(result.invoiceAccountAddresses).to.include(testInvoiceAccountAddresses[1]) + }) + }) + }) + // NOTE: The test data we generate in these tests is in accordance with how a contact record could be populated. For // example, if the data source is 'wrls' and the contact type is 'person', then first name and last name is always // populated. We don't test what would happen if last name wasn't because analysis of the data confirms this would From 288dc3e630b2c7c8178070cf8a1ca21c2188d315 Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Fri, 25 Aug 2023 14:07:31 +0100 Subject: [PATCH 4/6] Add company relationships --- app/models/crm-v2/company.model.js | 23 ++++++++++++++ test/models/crm-v2/company.model.test.js | 40 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/app/models/crm-v2/company.model.js b/app/models/crm-v2/company.model.js index cc30064f5d..00ab10f6ca 100644 --- a/app/models/crm-v2/company.model.js +++ b/app/models/crm-v2/company.model.js @@ -5,6 +5,8 @@ * @module CompanyModel */ +const { Model } = require('objection') + const CrmV2BaseModel = require('./crm-v2-base.model.js') class CompanyModel extends CrmV2BaseModel { @@ -22,6 +24,27 @@ class CompanyModel extends CrmV2BaseModel { { database: 'dateUpdated', model: 'updatedAt' } ] } + + static get relationMappings () { + return { + invoiceAccounts: { + relation: Model.HasManyRelation, + modelClass: 'invoice-account.model', + join: { + from: 'companies.companyId', + to: 'invoiceAccounts.companyId' + } + }, + invoiceAccountAddresses: { + relation: Model.HasManyRelation, + modelClass: 'invoice-account-address.model', + join: { + from: 'companies.companyId', + to: 'invoiceAccountAddresses.agentCompanyId' + } + } + } + } } module.exports = CompanyModel diff --git a/test/models/crm-v2/company.model.test.js b/test/models/crm-v2/company.model.test.js index cf1279f687..7f979c1e56 100644 --- a/test/models/crm-v2/company.model.test.js +++ b/test/models/crm-v2/company.model.test.js @@ -10,6 +10,8 @@ const { expect } = Code // Test helpers const CompanyHelper = require('../../support/helpers/crm-v2/company.helper.js') const DatabaseHelper = require('../../support/helpers/database.helper.js') +const InvoiceAccountAddressHelper = require('../../support/helpers/crm-v2/invoice-account-address.helper.js') +const InvoiceAccountAddressModel = require('../../../app/models/crm-v2/invoice-account-address.model.js') // Thing under test const CompanyModel = require('../../../app/models/crm-v2/company.model.js') @@ -31,4 +33,42 @@ describe('Company model', () => { expect(result.companyId).to.equal(testRecord.companyId) }) }) + + describe('Relationships', () => { + describe('when linking to invoice account addresses', () => { + let testInvoiceAccountAddresses + + beforeEach(async () => { + testRecord = await CompanyHelper.add() + const { companyId: agentCompanyId } = testRecord + + testInvoiceAccountAddresses = [] + for (let i = 0; i < 2; i++) { + const invoiceAccountAddress = await InvoiceAccountAddressHelper.add({ agentCompanyId }) + testInvoiceAccountAddresses.push(invoiceAccountAddress) + } + }) + + it('can successfully run a related query', async () => { + const query = await CompanyModel.query() + .innerJoinRelated('invoiceAccountAddresses') + + expect(query).to.exist() + }) + + it('can eager load the invoice account addresses', async () => { + const result = await CompanyModel.query() + .findById(testRecord.companyId) + .withGraphFetched('invoiceAccountAddresses') + + expect(result).to.be.instanceOf(CompanyModel) + expect(result.companyId).to.equal(testRecord.companyId) + + expect(result.invoiceAccountAddresses).to.be.an.array() + expect(result.invoiceAccountAddresses[0]).to.be.an.instanceOf(InvoiceAccountAddressModel) + expect(result.invoiceAccountAddresses).to.include(testInvoiceAccountAddresses[0]) + expect(result.invoiceAccountAddresses).to.include(testInvoiceAccountAddresses[1]) + }) + }) + }) }) From 016cb97aeeae0b8ff14cb98a551d1c60443ec8dc Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Fri, 25 Aug 2023 14:08:33 +0100 Subject: [PATCH 5/6] Add invoice account address relationships --- .../crm-v2/invoice-account-address.model.js | 39 ++++++ .../invoice-account-address.model.test.js | 122 ++++++++++++++++++ 2 files changed, 161 insertions(+) diff --git a/app/models/crm-v2/invoice-account-address.model.js b/app/models/crm-v2/invoice-account-address.model.js index 21a1e7d797..c9f0797462 100644 --- a/app/models/crm-v2/invoice-account-address.model.js +++ b/app/models/crm-v2/invoice-account-address.model.js @@ -5,6 +5,8 @@ * @module InvoiceAccountAddressModel */ +const { Model } = require('objection') + const CrmV2BaseModel = require('./crm-v2-base.model.js') class InvoiceAccountAddressModel extends CrmV2BaseModel { @@ -22,6 +24,43 @@ class InvoiceAccountAddressModel extends CrmV2BaseModel { { database: 'dateUpdated', model: 'updatedAt' } ] } + + static get relationMappings () { + return { + address: { + relation: Model.BelongsToOneRelation, + modelClass: 'address.model', + join: { + from: 'invoiceAccountAddresses.addressId', + to: 'addresses.addressId' + } + }, + company: { + relation: Model.BelongsToOneRelation, + modelClass: 'company.model', + join: { + from: 'invoiceAccountAddresses.agentCompanyId', + to: 'companies.companyId' + } + }, + contact: { + relation: Model.BelongsToOneRelation, + modelClass: 'contact.model', + join: { + from: 'invoiceAccountAddresses.contactId', + to: 'contacts.contactId' + } + }, + invoiceAccount: { + relation: Model.BelongsToOneRelation, + modelClass: 'invoice-account.model', + join: { + from: 'invoiceAccountAddresses.invoiceAccountId', + to: 'invoiceAccounts.invoiceAccountId' + } + } + } + } } module.exports = InvoiceAccountAddressModel diff --git a/test/models/crm-v2/invoice-account-address.model.test.js b/test/models/crm-v2/invoice-account-address.model.test.js index a10027c7d3..3c82e68f3d 100644 --- a/test/models/crm-v2/invoice-account-address.model.test.js +++ b/test/models/crm-v2/invoice-account-address.model.test.js @@ -8,7 +8,15 @@ const { describe, it, beforeEach } = exports.lab = Lab.script() const { expect } = Code // Test helpers +const AddressHelper = require('../../support/helpers/crm-v2/address.helper.js') +const AddressModel = require('../../../app/models/crm-v2/address.model.js') +const CompanyHelper = require('../../support/helpers/crm-v2/company.helper.js') +const CompanyModel = require('../../../app/models/crm-v2/company.model.js') +const ContactHelper = require('../../support/helpers/crm-v2/contact.helper.js') +const ContactModel = require('../../../app/models/crm-v2/contact.model.js') const DatabaseHelper = require('../../support/helpers/database.helper.js') +const InvoiceAccountHelper = require('../../support/helpers/crm-v2/invoice-account.helper.js') +const InvoiceAccountModel = require('../../../app/models/crm-v2/invoice-account.model.js') const InvoiceAccountAddressHelper = require('../../support/helpers/crm-v2/invoice-account-address.helper.js') // Thing under test @@ -31,4 +39,118 @@ describe('Invoice Account Address model', () => { expect(result.invoiceAccountAddressId).to.equal(testRecord.invoiceAccountAddressId) }) }) + + describe('Relationships', () => { + describe('when linking to address', () => { + let testAddress + + beforeEach(async () => { + testAddress = await AddressHelper.add() + testRecord = await InvoiceAccountAddressHelper.add({ addressId: testAddress.addressId }) + }) + + it('can successfully run a related query', async () => { + const query = await InvoiceAccountAddressModel.query() + .innerJoinRelated('address') + + expect(query).to.exist() + }) + + it('can eager load the address', async () => { + const result = await InvoiceAccountAddressModel.query() + .findById(testRecord.invoiceAccountAddressId) + .withGraphFetched('address') + + expect(result).to.be.instanceOf(InvoiceAccountAddressModel) + expect(result.invoiceAccountAddressId).to.equal(testRecord.invoiceAccountAddressId) + + expect(result.address).to.be.an.instanceOf(AddressModel) + expect(result.address).to.equal(testAddress) + }) + }) + + describe('when linking to company', () => { + let testCompany + + beforeEach(async () => { + testCompany = await CompanyHelper.add() + testRecord = await InvoiceAccountAddressHelper.add({ agentCompanyId: testCompany.companyId }) + }) + + it('can successfully run a related query', async () => { + const query = await InvoiceAccountAddressModel.query() + .innerJoinRelated('company') + + expect(query).to.exist() + }) + + it('can eager load the company', async () => { + const result = await InvoiceAccountAddressModel.query() + .findById(testRecord.invoiceAccountAddressId) + .withGraphFetched('company') + + expect(result).to.be.instanceOf(InvoiceAccountAddressModel) + expect(result.invoiceAccountAddressId).to.equal(testRecord.invoiceAccountAddressId) + + expect(result.company).to.be.an.instanceOf(CompanyModel) + expect(result.company).to.equal(testCompany) + }) + }) + + describe('when linking to contact', () => { + let testContact + + beforeEach(async () => { + testContact = await ContactHelper.add() + testRecord = await InvoiceAccountAddressHelper.add({ contactId: testContact.contactId }) + }) + + it('can successfully run a related query', async () => { + const query = await InvoiceAccountAddressModel.query() + .innerJoinRelated('contact') + + expect(query).to.exist() + }) + + it('can eager load the contact', async () => { + const result = await InvoiceAccountAddressModel.query() + .findById(testRecord.invoiceAccountAddressId) + .withGraphFetched('contact') + + expect(result).to.be.instanceOf(InvoiceAccountAddressModel) + expect(result.invoiceAccountAddressId).to.equal(testRecord.invoiceAccountAddressId) + + expect(result.contact).to.be.an.instanceOf(ContactModel) + expect(result.contact).to.equal(testContact) + }) + }) + + describe('when linking to invoice account', () => { + let testInvoiceAccount + + beforeEach(async () => { + testInvoiceAccount = await InvoiceAccountHelper.add() + testRecord = await InvoiceAccountAddressHelper.add({ invoiceAccountId: testInvoiceAccount.invoiceAccountId }) + }) + + it('can successfully run a related query', async () => { + const query = await InvoiceAccountAddressModel.query() + .innerJoinRelated('invoiceAccount') + + expect(query).to.exist() + }) + + it('can eager load the region', async () => { + const result = await InvoiceAccountAddressModel.query() + .findById(testRecord.invoiceAccountAddressId) + .withGraphFetched('invoiceAccount') + + expect(result).to.be.instanceOf(InvoiceAccountAddressModel) + expect(result.invoiceAccountAddressId).to.equal(testRecord.invoiceAccountAddressId) + + expect(result.invoiceAccount).to.be.an.instanceOf(InvoiceAccountModel) + expect(result.invoiceAccount).to.equal(testInvoiceAccount) + }) + }) + }) }) From fa00e4d5f64e5d5214f1ac967615d89095541373 Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Fri, 25 Aug 2023 14:15:07 +0100 Subject: [PATCH 6/6] Update invoice account with relationships --- app/models/crm-v2/invoice-account.model.js | 23 ++++++ .../crm-v2/invoice-account.model.test.js | 70 +++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/app/models/crm-v2/invoice-account.model.js b/app/models/crm-v2/invoice-account.model.js index 9818d90bf6..5721dc58ba 100644 --- a/app/models/crm-v2/invoice-account.model.js +++ b/app/models/crm-v2/invoice-account.model.js @@ -5,6 +5,8 @@ * @module InvoiceAccountModel */ +const { Model } = require('objection') + const CrmV2BaseModel = require('./crm-v2-base.model.js') class InvoiceAccountModel extends CrmV2BaseModel { @@ -22,6 +24,27 @@ class InvoiceAccountModel extends CrmV2BaseModel { { database: 'dateUpdated', model: 'updatedAt' } ] } + + static get relationMappings () { + return { + company: { + relation: Model.BelongsToOneRelation, + modelClass: 'company.model', + join: { + from: 'invoiceAccounts.companyId', + to: 'companies.companyId' + } + }, + invoiceAccountAddresses: { + relation: Model.HasManyRelation, + modelClass: 'invoice-account-address.model', + join: { + from: 'invoiceAccounts.invoiceAccountId', + to: 'invoiceAccountAddresses.invoiceAccountId' + } + } + } + } } module.exports = InvoiceAccountModel diff --git a/test/models/crm-v2/invoice-account.model.test.js b/test/models/crm-v2/invoice-account.model.test.js index 7d76113ce0..741e49e04d 100644 --- a/test/models/crm-v2/invoice-account.model.test.js +++ b/test/models/crm-v2/invoice-account.model.test.js @@ -8,8 +8,12 @@ const { describe, it, beforeEach } = exports.lab = Lab.script() const { expect } = Code // Test helpers +const CompanyHelper = require('../../support/helpers/crm-v2/company.helper.js') +const CompanyModel = require('../../../app/models/crm-v2/company.model.js') const DatabaseHelper = require('../../support/helpers/database.helper.js') const InvoiceAccountHelper = require('../../support/helpers/crm-v2/invoice-account.helper.js') +const InvoiceAccountAddressHelper = require('../../support/helpers/crm-v2/invoice-account-address.helper.js') +const InvoiceAccountAddressModel = require('../../../app/models/crm-v2/invoice-account-address.model.js') // Thing under test const InvoiceAccountModel = require('../../../app/models/crm-v2/invoice-account.model.js') @@ -31,4 +35,70 @@ describe('Invoice Account model', () => { expect(result.invoiceAccountId).to.equal(testRecord.invoiceAccountId) }) }) + + describe('Relationships', () => { + describe('when linking to company', () => { + let testCompany + + beforeEach(async () => { + testCompany = await CompanyHelper.add() + testRecord = await InvoiceAccountHelper.add({ companyId: testCompany.companyId }) + }) + + it('can successfully run a related query', async () => { + const query = await InvoiceAccountModel.query() + .innerJoinRelated('company') + + expect(query).to.exist() + }) + + it('can eager load the company', async () => { + const result = await InvoiceAccountModel.query() + .findById(testRecord.invoiceAccountId) + .withGraphFetched('company') + + expect(result).to.be.instanceOf(InvoiceAccountModel) + expect(result.invoiceAccountId).to.equal(testRecord.invoiceAccountId) + + expect(result.company).to.be.an.instanceOf(CompanyModel) + expect(result.company).to.equal(testCompany) + }) + }) + + describe('when linking to invoice account addresses', () => { + let testInvoiceAccountAddresses + + beforeEach(async () => { + testRecord = await InvoiceAccountHelper.add() + const { invoiceAccountId } = testRecord + + testInvoiceAccountAddresses = [] + for (let i = 0; i < 2; i++) { + const invoiceAccountAddress = await InvoiceAccountAddressHelper.add({ invoiceAccountId }) + testInvoiceAccountAddresses.push(invoiceAccountAddress) + } + }) + + it('can successfully run a related query', async () => { + const query = await InvoiceAccountModel.query() + .innerJoinRelated('invoiceAccountAddresses') + + expect(query).to.exist() + }) + + it('can eager load the invoice account addresses', async () => { + const result = await InvoiceAccountModel.query() + .findById(testRecord.invoiceAccountId) + .withGraphFetched('invoiceAccountAddresses') + + expect(result).to.be.instanceOf(InvoiceAccountModel) + expect(result.invoiceAccountId).to.equal(testRecord.invoiceAccountId) + + expect(result.invoiceAccountAddresses).to.be.an.array() + expect(result.invoiceAccountAddresses[0]).to.be.an.instanceOf(InvoiceAccountAddressModel) + expect(result.invoiceAccountAddresses).to.include(testInvoiceAccountAddresses[0]) + expect(result.invoiceAccountAddresses).to.include(testInvoiceAccountAddresses[1]) + }) + }) + }) })