Skip to content

Commit b1149f0

Browse files
feature/DF-861: Geospatial component (#468)
* Support Geospatial components in CSV download output * Add grid reference to the geospatial features * Add route to get submission record by reference * Remove duplicate imports * Bump forms-engine-plugin version * Add tests for getSubmissionRecordByReference * Fix linting * Move getSubmissionRecordByReference into new submission routes file
1 parent c902118 commit b1149f0

15 files changed

Lines changed: 23954 additions & 11303 deletions

package-lock.json

Lines changed: 23598 additions & 11281 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"@aws-sdk/client-s3": "^3.679.0",
4141
"@aws-sdk/client-sqs": "^3.982.0",
4242
"@aws-sdk/s3-request-presigner": "^3.679.0",
43-
"@defra/forms-engine-plugin": "^4.0.57",
43+
"@defra/forms-engine-plugin": "^4.4.0",
4444
"@defra/forms-model": "^3.0.638",
4545
"@defra/hapi-tracing": "^1.12.0",
4646
"@elastic/ecs-pino-format": "^1.5.0",

src/api/types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
*/
6161

6262
/**
63+
* @typedef {{ Params: { referenceNumber: string }}} GetSubmissionByReference
6364
* @typedef {{ Params: { dlq: string }}} DeadLetterQueueRequest
6465
*/
6566

src/models/form.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { formAdapterSubmissionMessagePayloadSchema } from '@defra/forms-engine-plugin/engine/types/schema.js'
12
import Joi from 'joi'
23

34
export const magicLinkSchema = Joi.string().uuid().required()
@@ -38,6 +39,7 @@ export const validateSavedLinkResponseSchema = Joi.object({
3839
export const generateFormSubmissionsFileResponseSchema = Joi.object({
3940
message: Joi.string().required()
4041
}).label('generateFormSubmissionsFileResponse')
42+
4143
export const generateFeedbackSubmissionsFileResponseSchema = Joi.object({
4244
message: Joi.string().required()
4345
}).label('generateFeedbackSubmissionsFileResponse')
@@ -47,6 +49,21 @@ export const resetSaveAndExitLinkResponseSchema = Joi.object({
4749
recordUpdated: Joi.boolean().required()
4850
}).label('resetSaveAndExitLinkResponseSchema')
4951

52+
/**
53+
* @type {Joi.ObjectSchema<FormSubmissionDocument>}
54+
*/
55+
export const getSubmissionByReferenceResponseSchema = Joi.object()
56+
.keys({
57+
_id: Joi.string().hex().required(),
58+
recordCreatedAt: Joi.string().isoDate().required(),
59+
expireAt: Joi.string().isoDate().required()
60+
})
61+
.concat(formAdapterSubmissionMessagePayloadSchema)
62+
.label('getSubmissionByReferenceResponseSchema')
63+
64+
/**
65+
* @import { FormSubmissionDocument } from '~/src/api/types.js'
66+
*/
5067
export const dqlSchema = Joi.string().valid('form-submissions', 'save-and-exit')
5168

5269
export const receiptHandleSchema = Joi.string()

src/repositories/__stubs__/submission.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { FormStatus } from '@defra/forms-model'
44
import { addDays } from '~/src/helpers/date-helper.js'
55

66
export const STUB_FORM_ID = '688131eeff67f889d52c66cc'
7+
export const STUB_SUBMISSION_REF = '365-DFR-C67'
78
export const STUB_SUBMISSION_RECORD_ID = '68d284ef5fa1a0fb2ede066a'
89

910
/**

src/repositories/submission-repository.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,35 @@ export async function createSubmissionRecord(document, session) {
6565
}
6666
}
6767

68+
/**
69+
* Gets a submission record based on reference number
70+
* @param {string} referenceNumber - the reference number
71+
* @returns { Promise<WithId<FormSubmissionDocument> | null> }
72+
*/
73+
export async function getSubmissionRecordByReference(referenceNumber) {
74+
logger.info('Reading submission record')
75+
76+
const coll = /** @type {Collection<FormSubmissionDocument>} */ (
77+
db.collection(SUBMISSIONS_COLLECTION_NAME)
78+
)
79+
80+
try {
81+
const result = await coll.findOne({
82+
'meta.referenceNumber': referenceNumber
83+
})
84+
85+
logger.info('Read submission record')
86+
87+
return result
88+
} catch (err) {
89+
logger.error(
90+
err,
91+
`Failed to read submission record - ${getErrorMessage(err)}`
92+
)
93+
throw err
94+
}
95+
}
96+
6897
/**
6998
* @import { ClientSession, ObjectId, WithId, Collection, FindCursor } from 'mongodb'
7099
* @import { FormSubmissionDocument } from '~/src/api/types.js'

src/repositories/submission-repository.test.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import { db } from '~/src/mongo.js'
22
import { buildMockCollection } from '~/src/repositories/__stubs__/mongo.js'
33
import {
44
STUB_FORM_ID,
5+
STUB_SUBMISSION_REF,
56
buildDbDocument
67
} from '~/src/repositories/__stubs__/submission.js'
78
import {
89
createSubmissionRecord,
10+
getSubmissionRecordByReference,
911
getSubmissionRecords
1012
} from '~/src/repositories/submission-repository.js'
1113

@@ -103,4 +105,25 @@ describe('submission repository', () => {
103105
).rejects.toThrow(new Error('Failed'))
104106
})
105107
})
108+
109+
describe('getSubmissionRecordByReference', () => {
110+
it('should get submission record', async () => {
111+
jest.mocked(
112+
mockCollection.findOne.mockResolvedValueOnce(submissionDocument)
113+
)
114+
const submissionRecord =
115+
await getSubmissionRecordByReference(STUB_SUBMISSION_REF)
116+
expect(submissionRecord).toEqual(submissionDocument)
117+
})
118+
119+
it('should handle get submission record failures', async () => {
120+
mockCollection.findOne.mockImplementation(() => {
121+
throw new Error('an error')
122+
})
123+
124+
await expect(
125+
getSubmissionRecordByReference(STUB_SUBMISSION_REF)
126+
).rejects.toThrow(new Error('an error'))
127+
})
128+
})
106129
})

src/routes/admin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,5 +218,5 @@ export default [
218218

219219
/**
220220
* @import { ServerRoute } from '@hapi/hapi'
221-
* @import { DeadLetterQueueRequest, DeadLetterQueueAndHandleRequest, GenerateFeedbackSubmissionsFile, GenerateFormSubmissionsFile, ResetSaveAndExit } from '~/src/api/types.js'
221+
* @import { DeadLetterQueueRequest, DeadLetterQueueAndHandleRequest, GenerateFeedbackSubmissionsFile, GenerateFormSubmissionsFile, GetSubmissionByReference, ResetSaveAndExit } from '~/src/api/types.js'
222222
*/

src/routes/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ import admin from '~/src/routes/admin.js'
22
import files from '~/src/routes/files.js'
33
import form from '~/src/routes/form.js'
44
import health from '~/src/routes/health.js'
5+
import submission from '~/src/routes/submission.js'
56

6-
export default [health, files, form, admin].flat()
7+
export default [health, files, form, submission, admin].flat()

src/routes/submission.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Scopes } from '@defra/forms-model'
2+
import Boom from '@hapi/boom'
3+
import Joi from 'joi'
4+
5+
import { getSubmissionByReferenceResponseSchema } from '~/src/models/form.js'
6+
import { getSubmissionRecordByReference } from '~/src/repositories/submission-repository.js'
7+
8+
export default [
9+
/**
10+
* @satisfies {ServerRoute<GetSubmissionByReference>}
11+
*/
12+
({
13+
method: 'GET',
14+
path: '/submission/{referenceNumber}',
15+
async handler(request) {
16+
const { params } = request
17+
const { referenceNumber } = params
18+
19+
const record = await getSubmissionRecordByReference(referenceNumber)
20+
21+
if (!record) {
22+
return Boom.notFound(
23+
`Submission record with reference ${referenceNumber} was not found`
24+
)
25+
}
26+
27+
return record
28+
},
29+
options: {
30+
tags: ['api'],
31+
auth: {
32+
scope: [`+${Scopes.FormRead}`]
33+
},
34+
validate: {
35+
params: Joi.object()
36+
.keys({
37+
referenceNumber: Joi.string().required()
38+
})
39+
.label('getSubmissionByReferenceParams')
40+
},
41+
response: {
42+
status: {
43+
200: getSubmissionByReferenceResponseSchema
44+
}
45+
}
46+
}
47+
})
48+
]
49+
50+
/**
51+
* @import { ServerRoute } from '@hapi/hapi'
52+
* @import { GetSubmissionByReference } from '~/src/api/types.js'
53+
*/

0 commit comments

Comments
 (0)