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

Import contact data for a licence #1317

Merged
merged 33 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
ca447bd
Import company contact data for a licence
jonathangoulding Sep 9, 2024
226d12f
fix: use contacts instead of company contacts
jonathangoulding Sep 9, 2024
1398770
fix: a contact must be from the licence version and not an organisation
jonathangoulding Sep 9, 2024
20e8a10
test: persist logic for contacts
jonathangoulding Sep 9, 2024
6a37dac
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 10, 2024
e621958
chore: pr fixes
jonathangoulding Sep 10, 2024
9898b07
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 10, 2024
c626408
fix: datasource for contact
jonathangoulding Sep 10, 2024
3378985
fix: process licence test
jonathangoulding Sep 10, 2024
2969407
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 12, 2024
79e01ef
fix: sql query to get licence role party id's for a contact
jonathangoulding Sep 13, 2024
2657684
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 13, 2024
da29f3d
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 18, 2024
d1b5abb
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 18, 2024
d7dd16d
feat: add company contact
jonathangoulding Sep 19, 2024
cdb8a58
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 19, 2024
53043ed
test: update import contacts tests to use company contacts
jonathangoulding Sep 20, 2024
184d9a0
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 20, 2024
6e9460c
feat: add company contacts to persist
jonathangoulding Sep 20, 2024
e5f483e
feat: add company contacts to persist test
jonathangoulding Sep 20, 2024
6217f29
fix: failing persist company contact test
jonathangoulding Sep 23, 2024
46668cf
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 23, 2024
8a316d3
chore: pre pr checks
jonathangoulding Sep 23, 2024
2407f67
chore: pre pr checks
jonathangoulding Sep 23, 2024
2156b50
Update app/presenters/import/legacy/company-contact.presenter.js
jonathangoulding Sep 23, 2024
965c794
Update app/services/import/legacy/fetch-contacts.service.js
jonathangoulding Sep 23, 2024
da6de67
Update app/services/import/legacy/transform-contacts.service.js
jonathangoulding Sep 23, 2024
028aceb
Update app/services/import/legacy/transform-contacts.service.js
jonathangoulding Sep 23, 2024
1ee1505
Update app/services/import/legacy/transform-contacts.service.js
jonathangoulding Sep 23, 2024
04fd0ac
chore: fix pr issues
jonathangoulding Sep 24, 2024
66871d4
chore: fix pr issues
jonathangoulding Sep 24, 2024
ac80374
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 24, 2024
8943841
Merge branch 'main' into import-company-contact-for-licence
jonathangoulding Sep 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions app/presenters/import/legacy/contact.presenter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict'

/**
* Maps the legacy NALD contact data to the WRLS format
* @module ContactPresenter
*/

/**
* Maps the legacy NALD contact data to the WRLS format
*
* @param {ImportLegacyContactType} contact - the legacy NALD contact
*
* @returns {object} the NALD contact data transformed into the WRLS format for a contact
* ready for validation and persisting
*/
function go (contact) {
return {
externalId: contact.external_id,
salutation: contact.salutation,
initials: contact.initials,
firstName: contact.first_name,
lastName: contact.last_name
}
}

module.exports = {
go
}
25 changes: 1 addition & 24 deletions app/services/import/legacy/fetch-company.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,6 @@ function _query () {
return `
SELECT DISTINCT ON (np."ID")
(concat_ws(':', np."FGAC_REGION_CODE", np."ID")) AS external_id,
(
CASE np."SALUTATION"
WHEN 'null' THEN NULL
ELSE np."SALUTATION"
END
) AS salutation,
(
CASE np."FORENAME"
WHEN 'null' THEN NULL
ELSE np."FORENAME"
END
) AS firstName,
(
CASE np."NAME"
WHEN 'null' THEN NULL
ELSE np."NAME"
END
) AS lastName,
jonathangoulding marked this conversation as resolved.
Show resolved Hide resolved
(
CASE np."APAR_TYPE"
WHEN 'PER' THEN 'person'
Expand All @@ -72,8 +54,7 @@ function _query () {
END
)
END
)) AS name,
np."ID" as id
)) AS name
FROM import."NALD_PARTIES" np
LEFT JOIN import."NALD_ABS_LIC_VERSIONS" nalv
ON nalv."ACON_APAR_ID" = np."ID"
Expand All @@ -95,10 +76,6 @@ module.exports = {
/**
* @typedef {object} ImportLegacyCompanyType
*
* @property {string} - The party id
* @property {string|null} salutation - The salutation of the person, or null if not applicable.
* @property {string|null} firstName - The first name of the person, or null if not applicable.
* @property {string|null} lastName - The last name of the person, or null if not applicable.
* @property {string} type - Indicates whether the entry is a 'person' or an 'organisation'.
* @property {string|null} name - The full name, concatenated from salutation, forename/initials, and name.
* @property {string} external_id - The external ID, formatted as 'FGAC_REGION_CODE:ID'.
Expand Down
86 changes: 86 additions & 0 deletions app/services/import/legacy/fetch-contacts.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
'use strict'

/**
* Fetches the company data from the import.NALD_PARTIES table for the licence ref
jonathangoulding marked this conversation as resolved.
Show resolved Hide resolved
* @module FetchContactsService
*/

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

/**
* Fetches the licence data from the import.NALD_PARTIES table for the licence ref
*
* When a company has at least one licence version and the type of contact is not an organisation.
* Then it will have a contact.
*
* @param {string} regionCode - The NALD region code
* @param {string} licenceId - The NALD licence ID
*
* @returns {Promise<ImportLegacyContactType[]>}
*/
async function go (regionCode, licenceId) {
const query = _query()

const { rows } = await db.raw(query, [regionCode, licenceId, regionCode, licenceId])

return rows
}

function _query () {
return `
SELECT DISTINCT ON (np."ID")
(concat_ws(':', np."FGAC_REGION_CODE", np."ID")) AS external_id,
(
CASE np."SALUTATION"
WHEN 'null' THEN NULL
ELSE np."SALUTATION"
END
) AS salutation,
(
CASE np."INITIALS"
WHEN 'null' THEN NULL
ELSE np."INITIALS"
END
) AS initials,
(
CASE np."FORENAME"
WHEN 'null' THEN NULL
ELSE np."FORENAME"
END
) AS first_name,
(
CASE np."NAME"
WHEN 'null' THEN NULL
ELSE np."NAME"
END
) AS last_name
FROM import."NALD_PARTIES" np
LEFT JOIN import."NALD_ABS_LIC_VERSIONS" nalv
ON nalv."ACON_APAR_ID" = np."ID"
AND nalv."FGAC_REGION_CODE" = np."FGAC_REGION_CODE"
LEFT JOIN import."NALD_LIC_ROLES" nlr
jonathangoulding marked this conversation as resolved.
Show resolved Hide resolved
ON nlr."ACON_APAR_ID" = np."ID"
AND nlr."FGAC_REGION_CODE" = np."FGAC_REGION_CODE"
WHERE np."APAR_TYPE" != 'ORG'
jonathangoulding marked this conversation as resolved.
Show resolved Hide resolved
AND (
(nalv."FGAC_REGION_CODE" = ? AND nalv."AABL_ID" = ?)
OR
(nlr."FGAC_REGION_CODE" = ? AND nlr."AABL_ID" = ?)
);
`
}

module.exports = {
go
}

/**
* @typedef {object} ImportLegacyContactType
*
* @property {string|null} salutation - The salutation of the person, or null if not applicable.
* @property {string|null} initials - The initials of the person, or null if not applicable.
* @property {string|null} firstName - The first name of the person, or null if not applicable.
* @property {string|null} lastName - The last name of the person, or null if not applicable.
* @property {string} external_id - The external ID, formatted as 'FGAC_REGION_CODE:ID'.
*
*/
4 changes: 4 additions & 0 deletions app/services/import/legacy/process-licence.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const LicenceStructureValidator = require('../../../validators/import/licence-st
const PersistLicenceService = require('../persist-licence.service.js')
const ProcessLicenceReturnLogsService = require('../../jobs/return-logs/process-licence-return-logs.service.js')
const TransformCompaniesService = require('./transform-companies.service.js')
const TransformContactsService = require('./transform-contacts.service.js')
const TransformLicenceService = require('./transform-licence.service.js')
const TransformLicenceVersionPurposeConditionsService = require('./transform-licence-version-purpose-conditions.service.js')
const TransformLicenceVersionPurposesService = require('./transform-licence-version-purposes.service.js')
Expand Down Expand Up @@ -38,6 +39,9 @@ async function go (licenceRef) {
// Transform the company data
const { transformedCompanies } = await TransformCompaniesService.go(regionCode, naldLicenceId)

// Pass the transformed companies through each transformation step, building the company as we go
await TransformContactsService.go(regionCode, naldLicenceId, transformedCompanies)

// Ensure the built licence has all the valid child records we require
LicenceStructureValidator.go(transformedLicence)

Expand Down
44 changes: 44 additions & 0 deletions app/services/import/legacy/transform-contacts.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict'

/**
* Transforms NALD company data into a valid object that matches the WRLS structure
jonathangoulding marked this conversation as resolved.
Show resolved Hide resolved
* @module ImportLegacyTransformContactsService
*/

const FetchContactsService = require('./fetch-contacts.service.js')
const ContactPresenter = require('../../../presenters/import/legacy/contact.presenter.js')
const ImportContactValidator = require('../../../validators/import/contact.validator.js')

/**
* Transforms NALD company data into a validated object that matches the WRLS structure
jonathangoulding marked this conversation as resolved.
Show resolved Hide resolved
*
* @param {string} regionCode - The NALD region code
* @param {string} licenceId - The NALD licence ID
* @param {object[]} transformedCompanies
*
* @returns {Promise<object>} an object representing an array of valid WRLS transformed companies and
* an array of companies from the db
jonathangoulding marked this conversation as resolved.
Show resolved Hide resolved
*/
async function go (regionCode, licenceId, transformedCompanies) {
const naldContacts = await FetchContactsService.go(regionCode, licenceId)

naldContacts.forEach((naldContact) => {
const matchingCompany = _matchingCompany(transformedCompanies, naldContact)

const transformedContact = ContactPresenter.go(naldContact)

ImportContactValidator.go(transformedContact)

matchingCompany.contact = { ...transformedContact, dataSource: 'nald' }
})
}

function _matchingCompany (transformedCompanies, naldContact) {
return transformedCompanies.find((company) => {
return company.externalId === naldContact.external_id
})
}

module.exports = {
go
}
26 changes: 22 additions & 4 deletions app/services/import/persist-licence.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
* @module PersistLicenceService
*/

const { timestampForPostgres } = require('../../lib/general.lib.js')
const CompanyModel = require('../../models/company.model.js')
const ContactModel = require('../../models/contact.model.js')
const LicenceModel = require('../../models/licence.model.js')
const LicenceVersionModel = require('../../models/licence-version.model.js')
const LicenceVersionPurposeModel = require('../../models/licence-version-purpose.model.js')
const LicenceVersionPurposeConditionModel = require('../../models/licence-version-purpose-condition.model.js')
const CompanyModel = require('../../models/company.model.js')
const LicenceVersionPurposeModel = require('../../models/licence-version-purpose.model.js')
const { timestampForPostgres } = require('../../lib/general.lib.js')

/**
* Creates or updates an imported licence and its child entities that have been transformed and validated
Expand Down Expand Up @@ -140,11 +141,15 @@ async function _persistLicenceVersionPurposeCondition (
async function _persistCompanies (trx, updatedAt, companies) {
for (const company of companies) {
await _persistCompany(trx, updatedAt, company)

if (company.contact) {
await _persistContact(trx, updatedAt, company.contact)
}
}
}

async function _persistCompany (trx, updatedAt, company) {
const { ...propertiesToPersist } = company
const { contact, ...propertiesToPersist } = company

return CompanyModel.query(trx)
.insert({ ...propertiesToPersist, updatedAt })
Expand All @@ -156,6 +161,19 @@ async function _persistCompany (trx, updatedAt, company) {
])
}

async function _persistContact (trx, updatedAt, contact) {
return ContactModel.query(trx)
.insert({ ...contact, updatedAt })
.onConflict('externalId')
.merge([
'salutation',
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this update the data source to nald ? what if this has changed in wrls. Might be a none issue as the test helper sets this as wrls.

'initials',
'firstName',
'lastName',
'updatedAt'
])
}

module.exports = {
go
}
34 changes: 34 additions & 0 deletions app/validators/import/contact.validator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict'

/**
* @module ImportContactValidator
*/

const Joi = require('joi')

/**
* Checks that the imported contact data has been transformed and is valid for persisting to WRLS
*
* @param {object} contact - The transformed contact data
*
* @throws {Joi.ValidationError} - throws a Joi validation error if the validation fails
*/
function go (contact) {
const schema = Joi.object({
salutation: Joi.string().allow(null),
initials: Joi.string().allow(null),
firstName: Joi.string().allow(null),
lastName: Joi.string().allow(null),
externalId: Joi.string().required()
})

const result = schema.validate(contact, { convert: false })

if (result.error) {
throw result.error
}
}

module.exports = {
go
}
41 changes: 41 additions & 0 deletions test/presenters/import/legacy/contact.presenter.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'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

// Thing under test
const ContactPresenter = require('../../../../app/presenters/import/legacy/contact.presenter.js')

describe('Import Legacy Contact presenter', () => {
let legacyContact

beforeEach(() => {
legacyContact = _legacyContact()
})

it('correctly transforms the data', () => {
const result = ContactPresenter.go(legacyContact)

expect(result).to.equal({
salutation: 'Mr',
initials: 'H',
firstName: 'James',
lastName: 'Bond',
externalId: '1:007'
})
})
})

function _legacyContact () {
return {
salutation: 'Mr',
initials: 'H',
first_name: 'James',
last_name: 'Bond',
external_id: '1:007'
}
}
2 changes: 2 additions & 0 deletions test/services/import/legacy/process-licence.service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const TransformLicenceVersionsService = require('../../../../app/services/import
const TransformLicenceVersionPurposesService = require('../../../../app/services/import/legacy/transform-licence-version-purposes.service.js')
const TransformLicenceVersionPurposeConditionsService = require('../../../../app/services/import/legacy/transform-licence-version-purpose-conditions.service.js')
const TransformCompaniesService = require('../../../../app/services/import/legacy/transform-companies.service.js')
const TransformContactsService = require('../../../../app/services/import/legacy/transform-contacts.service.js')

// Thing under test
const ProcessLicenceService = require('../../../../app/services/import/legacy/process-licence.service.js')
Expand Down Expand Up @@ -47,6 +48,7 @@ describe('Import Legacy Process Licence service', () => {
Sinon.stub(TransformLicenceVersionPurposesService, 'go').resolves(transformedLicence)
Sinon.stub(TransformLicenceVersionPurposeConditionsService, 'go').resolves(transformedLicence)
Sinon.stub(TransformCompaniesService, 'go').resolves({ company: [], transformedCompany: [] })
Sinon.stub(TransformContactsService, 'go').resolves()

// BaseRequest depends on the GlobalNotifier to have been set. This happens in app/plugins/global-notifier.plugin.js
// when the app starts up and the plugin is registered. As we're not creating an instance of Hapi server in this
Expand Down
Loading
Loading