From 7d265a26cf0469caa46d19ca3b31c61e58002dac Mon Sep 17 00:00:00 2001 From: pearl-truss <67110378+pearl-truss@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:39:17 -0500 Subject: [PATCH] MCR-4826: add round number to Question object (#3092) * add round number to Question object * move add round number logic to resolver chain * fix mocks * Add resolver test, clean up resolver * remove change to domain model --- .../src/apollo/contractPackageDataMock.ts | 10 +++ .../src/apollo/questionResponseDataMocks.ts | 4 + .../src/resolvers/configureResolvers.ts | 2 + .../src/resolvers/questionResponse/index.ts | 1 + .../questionResponse/questionResolver.test.ts | 80 +++++++++++++++++++ .../questionResponse/questionResolver.ts | 46 +++++++++++ .../fragments/questionsEdgeFragment.graphql | 1 + services/app-graphql/src/schema.graphql | 1 + 8 files changed, 145 insertions(+) create mode 100644 services/app-api/src/resolvers/questionResponse/questionResolver.test.ts create mode 100644 services/app-api/src/resolvers/questionResponse/questionResolver.ts diff --git a/packages/mocks/src/apollo/contractPackageDataMock.ts b/packages/mocks/src/apollo/contractPackageDataMock.ts index cb224bb2b4..6fcd9c0b91 100644 --- a/packages/mocks/src/apollo/contractPackageDataMock.ts +++ b/packages/mocks/src/apollo/contractPackageDataMock.ts @@ -511,6 +511,7 @@ function mockContractPackageSubmittedWithQuestions( __typename: 'ContractQuestion' as const, id: 'dmco-question-1-id', contractID, + round: 1, createdAt: new Date('2022-12-16'), addedBy: mockValidCMSUser({ divisionAssignment: null, @@ -549,6 +550,7 @@ function mockContractPackageSubmittedWithQuestions( contractID, createdAt: new Date('2022-12-18'), addedBy: mockValidCMSUser() as CmsUser, + round: 1, documents: [ { s3URL: 's3://bucketname/key/dmco-question-2-document-1', @@ -577,6 +579,7 @@ function mockContractPackageSubmittedWithQuestions( id: 'dmcp-question-1-id', contractID, createdAt: new Date('2022-12-15'), + round: 1, addedBy: mockValidCMSUser({ divisionAssignment: 'DMCP', }) as CmsUser, @@ -618,6 +621,7 @@ function mockContractPackageSubmittedWithQuestions( id: 'oact-question-1-id', contractID, createdAt: new Date('2022-12-14'), + round: 1, addedBy: mockValidCMSUser({ divisionAssignment: 'OACT', }) as CmsUser, @@ -657,6 +661,7 @@ function mockContractPackageSubmittedWithQuestions( addedBy: mockValidCMSUser({ divisionAssignment: 'OACT', }) as CmsUser, + round: 2, documents: [ { s3URL: 's3://bucketname/key/oact-question-1-document-1', @@ -1509,6 +1514,7 @@ function mockContractPackageApprovedWithQuestions( addedBy: mockValidCMSUser({ divisionAssignment: null, }) as CmsUser, + round: 1, documents: [ { s3URL: 's3://bucketname/key/dmco-question-1-document-1', @@ -1543,6 +1549,7 @@ function mockContractPackageApprovedWithQuestions( contractID, createdAt: new Date('2022-12-18'), addedBy: mockValidCMSUser() as CmsUser, + round: 2, documents: [ { s3URL: 's3://bucketname/key/dmco-question-2-document-1', @@ -1571,6 +1578,7 @@ function mockContractPackageApprovedWithQuestions( id: 'dmcp-question-1-id', contractID, createdAt: new Date('2022-12-15'), + round: 1, addedBy: mockValidCMSUser({ divisionAssignment: 'DMCP', }) as CmsUser, @@ -1615,6 +1623,7 @@ function mockContractPackageApprovedWithQuestions( addedBy: mockValidCMSUser({ divisionAssignment: 'OACT', }) as CmsUser, + round: 1, documents: [ { s3URL: 's3://bucketname/key/oact-question-1-document-1', @@ -1648,6 +1657,7 @@ function mockContractPackageApprovedWithQuestions( id: 'oact-question-2-id', contractID: 'test-abc-123', createdAt: new Date('2022-12-17'), + round: 2, addedBy: mockValidCMSUser({ divisionAssignment: 'OACT', }) as CmsUser, diff --git a/packages/mocks/src/apollo/questionResponseDataMocks.ts b/packages/mocks/src/apollo/questionResponseDataMocks.ts index 0d4b057848..c55bba8a09 100644 --- a/packages/mocks/src/apollo/questionResponseDataMocks.ts +++ b/packages/mocks/src/apollo/questionResponseDataMocks.ts @@ -29,6 +29,7 @@ function mockQuestionsPayload( downloadURL: expect.any(String), }, ], + round: 1, division: 'DMCO', responses: [ { @@ -56,6 +57,7 @@ function mockQuestionsPayload( contractID, createdAt: new Date('2022-12-18'), addedBy: mockValidCMSUser() as CmsUser, + round: 1, documents: [ { s3URL: 's3://bucketname/key/dmco-question-2-document-1', @@ -110,6 +112,7 @@ function mockQuestionsPayload( }, ], division: 'DMCP', + round: 1, responses: [ { __typename: 'QuestionResponse' as const, @@ -143,6 +146,7 @@ function mockQuestionsPayload( addedBy: mockValidCMSUser({ divisionAssignment: 'OACT', }) as CmsUser, + round: 1, documents: [ { s3URL: 's3://bucketname/key/oact-question-1-document-1', diff --git a/services/app-api/src/resolvers/configureResolvers.ts b/services/app-api/src/resolvers/configureResolvers.ts index 4c13ad653c..265603dfe4 100644 --- a/services/app-api/src/resolvers/configureResolvers.ts +++ b/services/app-api/src/resolvers/configureResolvers.ts @@ -17,6 +17,7 @@ import { questionResponseDocumentResolver, createRateQuestionResolver, createRateQuestionResponseResolver, + questionResolver, } from './questionResponse' import { fetchCurrentUserResolver, @@ -171,6 +172,7 @@ export function configureResolvers( Rate: rateResolver(store, applicationEndpoint), RateRevision: rateRevisionResolver(store), RateFormData: rateFormDataResolver(), + ContractQuestion: questionResolver(store), Contract: contractResolver(store, applicationEndpoint), UnlockedContract: unlockedContractResolver(store, applicationEndpoint), ContractRevision: contractRevisionResolver(store), diff --git a/services/app-api/src/resolvers/questionResponse/index.ts b/services/app-api/src/resolvers/questionResponse/index.ts index 231774af57..2962b676f8 100644 --- a/services/app-api/src/resolvers/questionResponse/index.ts +++ b/services/app-api/src/resolvers/questionResponse/index.ts @@ -3,3 +3,4 @@ export { createContractQuestionResponseResolver } from './createContractQuestion export { questionResponseDocumentResolver } from './questionResponseDocumentResolver' export { createRateQuestionResolver } from './createRateQuestion' export { createRateQuestionResponseResolver } from './createRateQuestionResponse' +export { questionResolver } from './questionResolver' diff --git a/services/app-api/src/resolvers/questionResponse/questionResolver.test.ts b/services/app-api/src/resolvers/questionResponse/questionResolver.test.ts new file mode 100644 index 0000000000..13d8b706d7 --- /dev/null +++ b/services/app-api/src/resolvers/questionResponse/questionResolver.test.ts @@ -0,0 +1,80 @@ +import { + constructTestPostgresServer, + createTestQuestion, +} from '../../testHelpers/gqlHelpers' +import { + testCMSUser, + createDBUsersWithFullData, +} from '../../testHelpers/userHelpers' +import { testS3Client } from '../../testHelpers/s3Helpers' +import { + createAndSubmitTestContract, + fetchTestContractWithQuestions, +} from '../../testHelpers' + +describe(`questionResolver`, () => { + const mockS3 = testS3Client() + const dmcpCMSUser = testCMSUser({ + divisionAssignment: 'DMCP', + }) + + beforeAll(async () => { + //Inserting a new CMS user, with division assigned, in postgres in order to create the question to user relationship. + await createDBUsersWithFullData([dmcpCMSUser]) + }) + + it('populates a round number on fetch', async () => { + const stateServer = await constructTestPostgresServer() + + const dmcpCMSServer = await constructTestPostgresServer({ + context: { + user: dmcpCMSUser, + }, + s3Client: mockS3, + }) + + const contract = await createAndSubmitTestContract(stateServer) + + const createdDMCPQuestion = await createTestQuestion( + dmcpCMSServer, + contract.id, + { + documents: [ + { + name: 'Test Question 2', + s3URL: 's3://bucketname/key/test12', + }, + ], + } + ) + + const createdDMCPQuestion2 = await createTestQuestion( + dmcpCMSServer, + contract.id, + { + documents: [ + { + name: 'Test Question 2', + s3URL: 's3://bucketname/key/test12', + }, + ], + } + ) + + const contractWithQuestions = await fetchTestContractWithQuestions( + stateServer, + contract.id + ) + const indexQuestionsResult = contractWithQuestions.questions + const firstDMCPQuestion = + indexQuestionsResult?.DMCPQuestions.edges.find( + (q) => q.node.id === createdDMCPQuestion.question.id + ) + const secondDMCPQuestion = + indexQuestionsResult?.DMCPQuestions.edges.find( + (q) => q.node.id === createdDMCPQuestion2.question.id + ) + expect(firstDMCPQuestion?.node.round).toBe(1) + expect(secondDMCPQuestion?.node.round).toBe(2) + }) +}) diff --git a/services/app-api/src/resolvers/questionResponse/questionResolver.ts b/services/app-api/src/resolvers/questionResponse/questionResolver.ts new file mode 100644 index 0000000000..6fa77bf94a --- /dev/null +++ b/services/app-api/src/resolvers/questionResponse/questionResolver.ts @@ -0,0 +1,46 @@ +import type { Resolvers } from '../../gen/gqlServer' + +import type { ContractQuestionType } from '../../domain-models' +import type { Store } from '../../postgres' +import { GraphQLError } from 'graphql' + +export function questionResolver(store: Store): Resolvers['QuestionResolver'] { + return { + round: async (parent: ContractQuestionType) => { + const questions = await store.findAllQuestionsByContract( + parent.contractID + ) + if (!questions) { + throw new Error( + `Questions not found for contract: ${parent.contractID}` + ) + } + if (questions instanceof Error) { + const errMessage = `Issue return questions for contract message: ${questions.message}` + + throw new GraphQLError(errMessage, { + extensions: { + code: 'INTERNAL_SERVER_ERROR', + cause: 'DB_ERROR', + }, + }) + } + + const divisionQuestions = questions + .filter((q) => q.division === parent.division) + .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()) + + const matchingQuestion = divisionQuestions.find( + (question) => question.id == parent.id + ) + + if (!matchingQuestion) { + return 0 + } else { + return divisionQuestions.indexOf(matchingQuestion) !== undefined + ? divisionQuestions.indexOf(matchingQuestion) + 1 + : 0 + } + }, + } +} diff --git a/services/app-graphql/src/fragments/questionsEdgeFragment.graphql b/services/app-graphql/src/fragments/questionsEdgeFragment.graphql index 28a06b9b6c..84db054cde 100644 --- a/services/app-graphql/src/fragments/questionsEdgeFragment.graphql +++ b/services/app-graphql/src/fragments/questionsEdgeFragment.graphql @@ -12,6 +12,7 @@ fragment contractQuestionEdgeFragment on ContractQuestionEdge { } } division + round documents { s3URL name diff --git a/services/app-graphql/src/schema.graphql b/services/app-graphql/src/schema.graphql index 62964efb1d..10c0257206 100644 --- a/services/app-graphql/src/schema.graphql +++ b/services/app-graphql/src/schema.graphql @@ -1239,6 +1239,7 @@ type ContractQuestion { addedBy: CMSUsersUnion! documents: [Document!]! division: Division! + round: Int! # noteText: String # dueDate: Date # rateIDs: [String!]