Skip to content
This repository has been archived by the owner on Feb 7, 2025. It is now read-only.

SFI-2323 Get calculation data for statement constructor object #19

Merged
Show file tree
Hide file tree
Changes from 6 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
6 changes: 6 additions & 0 deletions app/processing/calculation/calculation-schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const Joi = require('joi')

module.exports = Joi.object({
sbi: Joi.number().integer().required(),
calculationDate: Joi.date().required()
}).required()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const db = require('../../data')

const getCalculationByPaymentRequestId = async (paymentRequestId) => {
return db.calculation.findOne({
attributes: [
'sbi',
'calculationDate'
],
where: {
paymentRequestId
},
raw: true
})
}

module.exports = getCalculationByPaymentRequestId
21 changes: 21 additions & 0 deletions app/processing/calculation/get-calculation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const schema = require('./calculation-schema')

const getCalculationByPaymentRequestId = require('./get-calculation-by-payment-request-id')

const getCalculation = async (paymentRequestId) => {
const calculation = await getCalculationByPaymentRequestId(paymentRequestId)
const result = schema.validate(calculation, {
abortEarly: false
})

if (result.error) {
throw new Error(`Payment request with paymentRequestId: ${paymentRequestId} does not have the required Calculation data: ${result.error.message}`)
}

return {
sbi: calculation.sbi,
calculated: calculation.calculationDate
}
}

module.exports = getCalculation
3 changes: 3 additions & 0 deletions app/processing/calculation/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const getCalculation = require('./get-calculation')

module.exports = getCalculation
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ffc-pay-statement-constructor",
"version": "0.6.0",
"version": "0.8.0",
"description": "Data construction for statement generation",
"homepage": "https://github.com/DEFRA/ffc-pay-statement-constructor",
"main": "app/index.js",
Expand All @@ -17,7 +17,8 @@
"contributors": [
"John Watson john.watson2@rpa.gov.uk",
"Marc Templeton m.templeton@kainos.com",
"Simon Dunn simon.dunn1@defra.gov.uk"
"Simon Dunn simon.dunn1@defra.gov.uk",
"Abidemi Adio abidemi.adio@defra.gov.uk"
],
"license": "OGL-UK-3.0",
"dependencies": {
Expand Down
75 changes: 75 additions & 0 deletions test/integration/processing/calculation/get-calculation.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const db = require('../../../../app/data')
const schemes = require('../../../../app/constants/schemes')
const { SFI_FIRST_PAYMENT: SFI_FIRST_PAYMENT_INVOICE_NUMBER } = require('../../../mock-components/mock-invoice-number')

const getCalculation = require('../../../../app/processing/calculation')

let rawCalculationData

describe('process get calculation object', () => {
beforeAll(async () => {
await db.sequelize.truncate({
cascade: true,
restartIdentity: true
})
})

beforeEach(async () => {
rawCalculationData = JSON.parse(JSON.stringify(require('../../../mock-objects/mock-calculation').rawCalculationData))

await db.scheme.bulkCreate(schemes)
await db.organisation.create({ sbi: rawCalculationData.sbi })
await db.invoiceNumber.create({ invoiceNumber: SFI_FIRST_PAYMENT_INVOICE_NUMBER })
await db.paymentRequest.create({
paymentRequestId: rawCalculationData.paymentRequestId,
schemeId: 1,
invoiceNumber: SFI_FIRST_PAYMENT_INVOICE_NUMBER
})
})

afterEach(async () => {
await db.sequelize.truncate({
cascade: true,
restartIdentity: true
})
})

afterAll(async () => {
await db.sequelize.close()
})

test('should throw error when no existing calculation data', async () => {
const wrapper = async () => { await getCalculation(rawCalculationData.paymentRequestId) }

expect(wrapper).rejects.toThrow()
})

test('should not throw error when there is existing calculation data with sbi and calculationDate', async () => {
await db.calculation.create(rawCalculationData)

const result = await getCalculation(rawCalculationData.paymentRequestId)

expect(result).toStrictEqual({
sbi: rawCalculationData.sbi,
calculated: new Date(rawCalculationData.calculationDate)
})
})

test('should throw error when there is existing calculation data with sbi but no calculationDate', async () => {
rawCalculationData.calculationDate = null
await db.calculation.create(rawCalculationData)

const wrapper = async () => { await getCalculation(rawCalculationData.paymentRequestId) }

expect(wrapper).rejects.toThrow()
})

test('should throw error when there is existing calculation data with calculationDate but no sbi', async () => {
rawCalculationData.calculationDate = null
await db.calculation.create(rawCalculationData)

const wrapper = async () => { await getCalculation(rawCalculationData.paymentRequestId) }

expect(wrapper).rejects.toThrow()
})
})
10 changes: 10 additions & 0 deletions test/mock-objects/mock-calculation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const rawCalculationData = {
calculationId: 1,
paymentRequestId: 1,
sbi: 657536,
calculationDate: '01/12/2022'
}

module.exports = {
rawCalculationData
}
140 changes: 140 additions & 0 deletions test/unit/processing/calculation/get-calculation.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
jest.mock('../../../../app/processing/calculation/calculation-schema')
const schema = require('../../../../app/processing/calculation/calculation-schema')

jest.mock('../../../../app/processing/calculation/get-calculation-by-payment-request-id')
const getCalculationByPaymentRequestId = require('../../../../app/processing/calculation/get-calculation-by-payment-request-id')

const getCalculation = require('../../../../app/processing/calculation/get-calculation')

let calculation
let rawCalculationData

describe('get and transform payment request information for building a statement object', () => {
beforeEach(() => {
const retrievedCalculationData = JSON.parse(JSON.stringify(require('../../../mock-objects/mock-calculation').rawCalculationData))

rawCalculationData = retrievedCalculationData
calculation = {
sbi: rawCalculationData.sbi,
calculated: new Date(rawCalculationData.calculationDate)
}

schema.validate.mockReturnValue({ value: calculation })
getCalculationByPaymentRequestId.mockResolvedValue(rawCalculationData)
})

afterEach(() => {
jest.clearAllMocks()
})

test('should call getCalculationByPaymentRequestId when a paymentRequestId is given', async () => {
const paymentRequestId = 1
await getCalculation(paymentRequestId)
expect(getCalculationByPaymentRequestId).toHaveBeenCalled()
})

test('should call getCompletedPaymentRequestByPaymentRequestId once when a paymentRequestId is given', async () => {
const paymentRequestId = 1
await getCalculation(paymentRequestId)
expect(getCalculationByPaymentRequestId).toHaveBeenCalledTimes(1)
})

test('should call getCalculationByPaymentRequestId with paymentRequestId when a paymentRequestId is given', async () => {
const paymentRequestId = 1
await getCalculation(paymentRequestId)
expect(getCalculationByPaymentRequestId).toHaveBeenCalledWith(paymentRequestId)
})

test('should call schema.validate when a paymentRequestId is given', async () => {
const paymentRequestId = 1
await getCalculation(paymentRequestId)
expect(schema.validate).toHaveBeenCalled()
})

test('should call schema.validate once when a paymentRequestId is given', async () => {
const paymentRequestId = 1
await getCalculation(paymentRequestId)
expect(schema.validate).toHaveBeenCalledTimes(1)
})

test('should call schema.validate with rawCalculationData and { abortEarly: false } when a paymentRequestId is given', async () => {
const paymentRequestId = 1
await getCalculation(paymentRequestId)
expect(schema.validate).toHaveBeenCalledWith(rawCalculationData, { abortEarly: false })
})

test('should throw when getCalculationByPaymentRequestId throws', async () => {
const paymentRequestId = 1
getCalculationByPaymentRequestId.mockRejectedValue(new Error('Database retrieval issue'))

const wrapper = async () => {
await getCalculation(paymentRequestId)
}

expect(wrapper).rejects.toThrow()
})

test('should throw Error when getCalculationByPaymentRequestId throws Error', async () => {
const paymentRequestId = 1
getCalculationByPaymentRequestId.mockRejectedValue(new Error('Database retrieval issue'))

const wrapper = async () => {
await getCalculation(paymentRequestId)
}

expect(wrapper).rejects.toThrow(Error)
})

test('should throw error with "Database retrieval issue" when getCalculationByPaymentRequestId throws error with "Database retrieval issue"', async () => {
const paymentRequestId = 1
getCalculationByPaymentRequestId.mockRejectedValue(new Error('Database retrieval issue'))

const wrapper = async () => {
await getCalculation(paymentRequestId)
}

expect(wrapper).rejects.toThrow(/^Database retrieval issue$/)
})

test('should not call schema.validate when getCalculationByPaymentRequestId throws', async () => {
const paymentRequestId = 1
getCalculationByPaymentRequestId.mockRejectedValue(new Error('Database retrieval issue'))

try { await getCalculation(paymentRequestId) } catch {}

expect(schema.validate).not.toHaveBeenCalled()
})

test('should throw when schema.validate returns with error key', async () => {
const paymentRequestId = 1
schema.validate.mockReturnValue({ error: 'Not a valid object' })

const wrapper = async () => {
await getCalculation(paymentRequestId)
}

expect(wrapper).rejects.toThrow()
})

test('should throw Error when schema.validate returns with error key', async () => {
const paymentRequestId = 1
schema.validate.mockReturnValue({ error: 'Not a valid object' })

const wrapper = async () => {
await getCalculation(paymentRequestId)
}

expect(wrapper).rejects.toThrow(Error)
})

test('should throw error which starts "Payment request with paymentRequestId: 1 does not have the required Calculation data" when schema.validate returns with error key of "Joi validation issue"', async () => {
const paymentRequestId = 1
schema.validate.mockReturnValue({ error: 'Not a valid object' })

const wrapper = async () => {
await getCalculation(paymentRequestId)
}

expect(wrapper).rejects.toThrow(/^Payment request with paymentRequestId: 1 does not have the required Calculation data/)
})
})