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

[MCR-2614] Add mccrsID to backend and frontend #1951

Closed
wants to merge 12 commits into from
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
Warnings:

- You are about to drop the column `mccrsID` on the `ContractRevisionTable` table. All the data in the column will be lost.

*/
-- AlterTable
ALTER TABLE "ContractRevisionTable" DROP COLUMN "mccrsID";

-- AlterTable
ALTER TABLE "ContractTable" ADD COLUMN "mccrsID" TEXT;
1 change: 1 addition & 0 deletions services/app-api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ model ContractTable {
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt

mccrsID String?
stateCode String
state State @relation(fields: [stateCode], references: [stateCode])
stateNumber Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type HealthPlanPackageStatusType =
type HealthPlanPackageType = {
id: string
stateCode: string
mccrsID?: string
revisions: HealthPlanRevisionType[]
questions?: IndexQuestionsPayload
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const contractSchema = z.object({
z.literal('RESUBMITTED'),
]),
stateCode: z.string(),
mccrsID: z.string().optional(),
stateNumber: z.number().min(1),
// If this contract is in a DRAFT or UNLOCKED status, there will be a draftRevision
draftRevision: contractRevisionWithRatesSchema.optional(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ function convertContractWithRatesToUnlockedHPP(
return {
id: contract.id,
stateCode: contract.stateCode,
mccrsID: contract.mccrsID,
revisions: healthPlanRevisions,
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ async function findContractWithHistory(
where: {
id: contractID,
},
include: includeFullContract,
include: {
...includeFullContract,
},
})

if (!contract) {
Expand Down
2 changes: 2 additions & 0 deletions services/app-api/src/postgres/contractAndRates/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
export type { InsertContractArgsType } from './insertContract'
export type { UpdateContractArgsType } from './updateDraftContractWithRates'
export type { UpdateMCCRSIDArgsType } from './updateMCCRSID'
export type { SubmitContractArgsType } from './submitContract'
export type { SubmitRateArgsType } from './submitRate'
export { submitContract } from './submitContract'
export { submitRate } from './submitRate'
export { insertDraftContract } from './insertContract'
export { findContractWithHistory } from './findContractWithHistory'
export { updateDraftContractWithRates } from './updateDraftContractWithRates'
export { updateMCCRSID } from './updateMCCRSID'
export { findAllContractsWithHistoryByState } from './findAllContractsWithHistoryByState'
export { findAllContractsWithHistoryBySubmitInfo } from './findAllContractsWithHistoryBySubmitInfo'
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ function parseContractWithHistory(
contract: ContractTableFullPayload
): ContractType | Error {
const contractWithHistory = contractWithHistoryToDomainModel(contract)

if (contractWithHistory instanceof Error) {
console.warn(
`ERROR: attempting to parse prisma contract with history failed: ${contractWithHistory.message}`
Expand All @@ -35,7 +34,6 @@ function parseContractWithHistory(
}

const parseContract = contractSchema.safeParse(contractWithHistory)

if (!parseContract.success) {
const error = `ERROR: attempting to parse prisma contract with history failed: ${parseContract.error}`
console.warn(error)
Expand Down Expand Up @@ -201,6 +199,7 @@ function contractWithHistoryToDomainModel(

return {
id: contract.id,
mccrsID: contract.mccrsID || undefined,
status: getContractRateStatus(contract.revisions),
stateCode: contract.stateCode,
stateNumber: contract.stateNumber,
Expand Down
50 changes: 50 additions & 0 deletions services/app-api/src/postgres/contractAndRates/updateMCCRSID.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { findContractWithHistory } from './findContractWithHistory'
import { NotFoundError } from '../storeError'
import type { PrismaClient } from '@prisma/client'
import type { ContractType } from '../../domain-models/contractAndRates'

type UpdateMCCRSIDArgsType = {
contractID: string
mccrsID?: string
}

// Update the MCCRS record number
async function updateMCCRSID(
client: PrismaClient,
args: UpdateMCCRSIDArgsType
): Promise<ContractType | NotFoundError | Error> {
const { contractID, mccrsID } = args

try {
return await client.$transaction(async (tx) => {
// Get the Contract associated with this given contract ID
const currentContract = await tx.contractTable.findFirst({
where: {
id: contractID,
},
})
if (!currentContract) {
const err = `PRISMA ERROR: Cannot find the current contract to update with contract id: ${contractID}`
console.error(err)
return new NotFoundError(err)
}
await tx.contractTable.update({
data: {
mccrsID,
},
where: {
id: contractID,
},
})
const contract = findContractWithHistory(tx, contractID)

return contract
})
} catch (err) {
console.error('Prisma error updating contract', err)
return err
}
}

export { updateMCCRSID }
export type { UpdateMCCRSIDArgsType }
7 changes: 7 additions & 0 deletions services/app-api/src/postgres/postgresStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
insertDraftContract,
findContractWithHistory,
updateDraftContractWithRates,
updateMCCRSID,
findAllContractsWithHistoryByState,
findAllContractsWithHistoryBySubmitInfo,
submitContract,
Expand All @@ -63,6 +64,7 @@ import type {
SubmitRateArgsType,
InsertContractArgsType,
UpdateContractArgsType,
UpdateMCCRSIDArgsType,
} from './contractAndRates'
import type { ContractOrErrorArrayType } from './contractAndRates/findAllContractsWithHistoryByState'
import { unlockContract } from './contractAndRates/unlockContract'
Expand Down Expand Up @@ -154,6 +156,10 @@ type Store = {
contractID: string
) => Promise<ContractType | Error>

updateMCCRSID: (
args: UpdateMCCRSIDArgsType
) => Promise<ContractType | Error>

updateDraftContractWithRates: (
args: UpdateContractArgsType
) => Promise<ContractType | Error>
Expand Down Expand Up @@ -239,6 +245,7 @@ function NewPostgresStore(client: PrismaClient): Store {
findContractWithHistory(client, args),
updateDraftContractWithRates: (args) =>
updateDraftContractWithRates(client, args),
updateMCCRSID: (args) => updateMCCRSID(client, args),
findAllContractsWithHistoryByState: (args) =>
findAllContractsWithHistoryByState(client, args),
findAllContractsWithHistoryBySubmitInfo: () =>
Expand Down
2 changes: 2 additions & 0 deletions services/app-api/src/resolvers/configureResolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import type { EmailParameterStore } from '../parameterStore'
import type { LDService } from '../launchDarkly/launchDarkly'
import { fetchEmailSettingsResolver } from './email/fetchEmailSettings'
import { updateContractResolver } from './contractResolvers/updateContractResolver'

export function configureResolvers(
store: Store,
Expand Down Expand Up @@ -75,6 +76,7 @@ export function configureResolvers(
emailParameterStore,
launchDarkly
),
updateContract: updateContractResolver(store, launchDarkly),
updateCMSUser: updateCMSUserResolver(store),
createQuestion: createQuestionResolver(store),
createQuestionResponse: createQuestionResponseResolver(store),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import UPDATE_CONTRACT_MUTATION from '../../../../app-graphql/src/mutations/updateContract.graphql'
import {
constructTestPostgresServer,
createAndSubmitTestHealthPlanPackage,
createTestHealthPlanPackage,
} from '../../testHelpers/gqlHelpers'
import { testCMSUser } from '../../testHelpers/userHelpers'
import { testLDService } from '../../testHelpers/launchDarklyHelpers'

describe('updateContract', () => {
const cmsUser = testCMSUser()
const mockLDService = testLDService({ ['rates-db-refactor']: true })

it('updates the contract', async () => {
const stateServer = await constructTestPostgresServer({
ldService: mockLDService,
})

// First, create a new submitted submission
const stateSubmission = await createAndSubmitTestHealthPlanPackage(
stateServer
)

const cmsServer = await constructTestPostgresServer({
ldService: mockLDService,
context: {
user: cmsUser,
},
})

// Update
const updateResult = await cmsServer.executeOperation({
query: UPDATE_CONTRACT_MUTATION,
variables: {
input: {
id: stateSubmission.id,
mccrsID: '1234',
},
},
})

expect(updateResult.errors).toBeUndefined()
const updatedSub = updateResult?.data?.updateContract.pkg
expect(updatedSub.mccrsID).toBe('1234')
})

it('errors if the contract is not submitted', async () => {
const stateServer = await constructTestPostgresServer({
ldService: mockLDService,
})

// First, create a draft submission
const draftSubmission = await createTestHealthPlanPackage(stateServer)
const cmsServer = await constructTestPostgresServer({
ldService: mockLDService,
context: {
user: cmsUser,
},
})

// Attempt update
const updateResult = await cmsServer.executeOperation({
query: UPDATE_CONTRACT_MUTATION,
variables: {
input: {
id: draftSubmission.id,
mccrsID: '1234',
},
},
})
expect(updateResult.errors).toBeDefined()
if (updateResult.errors === undefined) {
throw new Error('type narrow')
}

expect(updateResult.errors[0].extensions?.code).toBe('BAD_USER_INPUT')
expect(updateResult.errors[0].message).toBe(
`Can not update a contract has not been submitted. Fails for contract with ID: ${draftSubmission.id}`
)
})

it('errors if a CMS user calls it', async () => {
const stateServer = await constructTestPostgresServer({
ldService: mockLDService,
})

// First, create a new submitted submission
const stateSubmission = await createAndSubmitTestHealthPlanPackage(
stateServer
)
// Update
const updateResult = await stateServer.executeOperation({
query: UPDATE_CONTRACT_MUTATION,
variables: {
input: {
id: stateSubmission.id,
mccrsID: '1234',
},
},
})
expect(updateResult.errors).toBeDefined()
if (updateResult.errors === undefined) {
throw new Error('type narrow')
}

expect(updateResult.errors[0].extensions?.code).toBe('FORBIDDEN')
expect(updateResult.errors[0].message).toBe(
'user not authorized to update contract'
)
})
})
Loading
Loading