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

Revert "Removed the metadata middleware" #6724

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 17 additions & 0 deletions src/apps/api/controllers/__test__/postcode-lookup.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ describe('postcodeLookupHandler', () => {
'../services': {
lookupAddress: (postcode) => this.lookupAddressStub(postcode),
},
'../../../lib/metadata': {
countryOptions: [
{
id: '1234',
name: 'United Kingdom',
},
],
},
})
})

context('when the external api service returns successful response', () => {
beforeEach(async () => {
await this.controller.postcodeLookupHandler(this.req, this.resMock)
})
it('should return postcode response', () => {
expect(this.resMock.json).to.be.calledWith([{ country: '1234' }])
})
})

Expand Down
14 changes: 13 additions & 1 deletion src/apps/api/controllers/postcode-lookup.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
const { assign } = require('lodash')

const { lookupAddress } = require('../services')
const metadata = require('../../../lib/metadata')

async function postcodeLookupHandler(req, res) {
try {
res.json(await lookupAddress(req.params.postcode))
const postcode = req.params.postcode
const addresses = await lookupAddress(postcode)
const unitedKingdomCountryId = metadata.countryOptions.find(
(country) => country.name.toLowerCase() === 'united kingdom'
).id
const augmentedAddresses = addresses.map((address) => {
return assign({}, address, { country: unitedKingdomCountryId })
})

res.json(augmentedAddresses)
} catch (error) {
res.status(error.statusCode || 500).json({ message: error.message })
}
Expand Down
59 changes: 57 additions & 2 deletions src/apps/investments/middleware/__test__/shared.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const { merge } = require('lodash')
const { merge, cloneDeep } = require('lodash')
const proxyquire = require('proxyquire')

const paths = require('../../paths')
const investmentData = require('../../../../../test/unit/data/investment/investment-data.json')
const investmentProjectStages = require('../../../../../test/unit/data/investment/investment-project-stages.json')

const companyData = {
id: '6c388e5b-a098-e211-a939-e4115bead28a',
Expand Down Expand Up @@ -65,7 +66,12 @@ const getInvestmentData = (ukCompanyId, clientRelationshipManagerId) => {
})
}

const createMiddleware = (investmentData, adviserData, companyData) => {
const createMiddleware = (
investmentData,
adviserData,
companyData,
stages = investmentProjectStages
) => {
return proxyquire('../shared', {
'../repos': {
getInvestment: sinon.stub().resolves(investmentData),
Expand All @@ -76,6 +82,9 @@ const createMiddleware = (investmentData, adviserData, companyData) => {
'../../companies/repos': {
getDitCompany: sinon.stub().resolves(companyData),
},
'../../../lib/metadata': {
investmentProjectStage: stages,
},
})
}

Expand Down Expand Up @@ -146,6 +155,15 @@ describe('Investment shared middleware', () => {
expectedEquityCompany
)
})
it('should set investment project stages on locals', () => {
expect(resMock.locals.investmentProjectStages).to.deep.equal([
'Prospect',
'Assign PM',
'Active',
'Verify win',
'Won',
])
})
it('should set investment status on locals', () => {
expect(resMock.locals.investmentStatus).to.deep.equal(investmentStatus)
})
Expand Down Expand Up @@ -290,5 +308,42 @@ describe('Investment shared middleware', () => {
expect(nextSpy).to.have.been.called
})
})

context(
'when the streamlined-investment-flow feature flag is set to true',
() => {
before(async () => {
const stages = cloneDeep(investmentProjectStages)

// Exclude the Assign PM stage.
stages[1].exclude_from_investment_flow = true

resMock = {
breadcrumb: sinon.stub().returnsThis(),
locals: {
features: {
'streamlined-investment-flow': true,
},
},
}
const middleware = createMiddleware(
getInvestmentData(2, null),
adviserData,
companyData,
stages
)

await middleware.getInvestmentDetails(reqMock, resMock, nextSpy)
})
it('should remove the Assign PM stage from the investmentProjectStages array on locals', () => {
expect(resMock.locals.investmentProjectStages).to.deep.equal([
'Prospect',
'Active',
'Verify win',
'Won',
])
})
}
)
})
})
16 changes: 16 additions & 0 deletions src/apps/investments/middleware/shared.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { get, upperFirst } = require('lodash')

const metadata = require('../../../lib/metadata')
const { isValidGuid } = require('../../../lib/controller-utils')
const { getDitCompany } = require('../../companies/repos')
const { getAdviser } = require('../../adviser/repos')
Expand All @@ -16,6 +17,15 @@ function getCompanyDetails(req, res, next) {
.catch(next)
}

function getInvestmentProjectStages(features) {
if (features && features['streamlined-investment-flow']) {
return metadata.investmentProjectStage.filter(
(stage) => stage.exclude_from_investment_flow !== true
)
}
return metadata.investmentProjectStage
}

async function getInvestmentDetails(req, res, next) {
const investmentId = req.params.investmentId

Expand All @@ -34,6 +44,9 @@ async function getInvestmentDetails(req, res, next) {
'client_relationship_manager.id'
)
const stageName = investment.stage.name
const investmentProjectStages = getInvestmentProjectStages(
res.locals.features
)

investment.investor_company = Object.assign(
{},
Expand All @@ -60,6 +73,9 @@ async function getInvestmentDetails(req, res, next) {

res.locals.investment = investment
res.locals.equityCompany = investment.investor_company
res.locals.investmentProjectStages = investmentProjectStages.map(
(stage) => stage.name
)

res.locals.investmentStatus = {
id: investment.id,
Expand Down
2 changes: 2 additions & 0 deletions src/client/components/Form/elements/FieldAddress/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ const FieldAddress = ({
setFieldValue('address2', address.address2)
setFieldValue('city', address.city)
setFieldValue('county', address.county)
setFieldValue('country', isCountrySelectable ? address.country : country.id)
setFieldValue('country', country.id)

if (onSelectUKAddress) {
onSelectUKAddress(address)
Expand Down
42 changes: 42 additions & 0 deletions src/lib/__test__/metadata.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const rewire = require('rewire')

const config = require('../../config')

const modulePath = '../metadata'

describe('metadata', () => {
let metadata
let hawkRequest
beforeEach(() => {
metadata = rewire(modulePath)
})
afterEach(() => {
expect(hawkRequest).to.have.been.calledOnceWith(
`${config.apiRoot}/v4/metadata/fake`
)
})
describe('#getMetadata', () => {
beforeEach(() => {
metadata.__set__('redisClient', null)
})
it('gets metadata from URL', async () => {
const getMetadata = metadata.__get__('getMetadata')

hawkRequest = sinon.stub().resolves({ fake: 'metadata' })
metadata.__set__('hawkRequest', hawkRequest)
await getMetadata('fake', 'fakeOptions')
const { fakeOptions } = metadata.__get__('exports')
expect(fakeOptions).to.deep.equal({ fake: 'metadata' })
})

it('fails to get metadata if request cannot be made', async () => {
const getMetadata = metadata.__get__('getMetadata')

hawkRequest = sinon.stub().rejects()
metadata.__set__('hawkRequest', hawkRequest)
await expect(getMetadata('fake', 'fakeOptions')).to.be.rejectedWith(Error)
const { fakeOptions } = metadata.__get__('exports')
expect(fakeOptions).to.deep.equal(undefined)
})
})
})
86 changes: 86 additions & 0 deletions src/lib/metadata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const config = require('../config')
const logger = require('../config/logger')
const hawkRequest = require('./hawk-request')

let redisClient

function getMetadata(path, key) {
const url = `${config.apiRoot}/v4/metadata/${path}`

if (redisClient) {
return new Promise((resolve, reject) => {
const ttl = config.redis.metadataTtl

redisClient.get(url, (err, data) => {
if (!err && data) {
data = JSON.parse(data)
module.exports[key] = data
resolve(data)
} else {
hawkRequest(url)
.then((responseData) => {
module.exports[key] = responseData
redisClient.setex(url, ttl, JSON.stringify(responseData))
resolve(responseData)
})
.catch((reponseError) => {
logger.error('Error fetching metadataRepository for url: %s', url)
reject(reponseError)
throw reponseError
})
}
})
})
}

return hawkRequest(url)
.then((responseData) => {
module.exports[key] = responseData
return responseData
})
.catch((err) => {
logger.error('Error fetching metadataRepository for url: %s', url)
throw err
})
}

const metadataItems = [
['country', 'countryOptions'],
['investment-project-stage', 'investmentProjectStage'],
]

// TODO: Get rid of this
module.exports.fetchAll = (cb) => {
// todo
// refactor to create an array of jobs to do and then use promise all
// before returning back via a promise.

let caughtErrors
let totalRequests = 0
let completeRequests = 0

function checkResults() {
completeRequests += 1
if (completeRequests === totalRequests) {
logger.info('All metadataRepository requests complete')
cb(caughtErrors)
}
}

for (const item of metadataItems) {
totalRequests += 1
getMetadata(item[0], item[1])
.then((data) => {
if (item[2]) {
item[2](data)
}

checkResults()
})
.catch((err) => {
caughtErrors = caughtErrors || []
caughtErrors.push(err)
checkResults()
})
}
}
15 changes: 13 additions & 2 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const nunjucks = require('./config/nunjucks')
const headers = require('./middleware/headers')
const locals = require('./middleware/locals')
const userLocals = require('./middleware/user-locals')
const metadata = require('./lib/metadata')
const user = require('./middleware/user')
const auth = require('./middleware/auth')
const store = require('./middleware/store')
Expand Down Expand Up @@ -158,6 +159,16 @@ app.use(errors.notFound)
app.use(errors.badRequest)
app.use(errors.catchAll)

app.listen(config.port, () => {
logger.info(`app listening on port ${config.port}`)
metadata.fetchAll((errors) => {
if (errors) {
logger.error('Unable to load all metadataRepository, cannot start app')

for (const err of errors) {
throw err
}
} else {
app.listen(config.port, () => {
logger.info(`app listening on port ${config.port}`)
})
}
})
32 changes: 32 additions & 0 deletions test/unit/data/investment/investment-project-stages.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[
{
"id": "8a320cc9-ae2e-443e-9d26-2f36452c2ced",
"name": "Prospect",
"disabled_on": null,
"exclude_from_investment_flow": false
},
{
"id": "c9864359-fb1a-4646-a4c1-97d10189fc03",
"name": "Assign PM",
"disabled_on": null,
"exclude_from_investment_flow": false
},
{
"id": "7606cc19-20da-4b74-aba1-2cec0d753ad8",
"name": "Active",
"disabled_on": null,
"exclude_from_investment_flow": false
},
{
"id": "49b8f6f3-0c50-4150-a965-2c974f3149e3",
"name": "Verify win",
"disabled_on": null,
"exclude_from_investment_flow": false
},
{
"id": "945ea6d1-eee3-4f5b-9144-84a75b71b8e6",
"name": "Won",
"disabled_on": null,
"exclude_from_investment_flow": false
}
]
Loading