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

Submission Summary V2 with FetchContract #2350

Merged
merged 58 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
f8fc4e2
initial commit of resolvers working
macrael Apr 1, 2024
b355084
submitContract can only be called by state user
mojotalantikite Apr 1, 2024
ce369d7
create submissionsummaryv2
pearl-truss Apr 2, 2024
3e45343
create and use v2 version of contract details summary section component
pearl-truss Apr 2, 2024
5836518
temp comment out reviewsubmitv2 for testing
pearl-truss Apr 2, 2024
e2dd1b0
get submitContract working
macrael Apr 2, 2024
a36eb52
add test helpers for contracts, test single linked rate
macrael Apr 3, 2024
0cd849c
fix after linting
macrael Apr 3, 2024
a42ea4b
fix some bugs
macrael Apr 4, 2024
1686aa9
get setup of scenario working
macrael Apr 4, 2024
8201ea0
Wip with handling submit
pearl-truss Apr 4, 2024
0696cae
fix some of the api test
pearl-truss Apr 4, 2024
aa2e7c9
Remove console logs
pearl-truss Apr 4, 2024
ec4cd34
unlock child rates
macrael Apr 4, 2024
609af02
fix linting to deploy review app
pearl-truss Apr 5, 2024
ff4d5b9
add 90% of jason's diagram to test
mojotalantikite Apr 5, 2024
24f8970
get parentContractID into rate and check it
macrael Apr 6, 2024
1b05f8d
Merge branch 'wml-db-history' of https://github.com/Enterprise-CMCS/m…
macrael Apr 6, 2024
c66526b
Create graphql for submitContract and new fetchSubmittedContract
pearl-truss Apr 8, 2024
8dd9b62
remove changes to submitContract postgres func
pearl-truss Apr 8, 2024
c5a1653
remove unneeded changes for this pr
pearl-truss Apr 8, 2024
8a5ca31
remove submitContract graphql from this pr
pearl-truss Apr 8, 2024
9cd0a58
remove submitContract.graphql
pearl-truss Apr 8, 2024
ec9bbc0
fix unlockRate
mojotalantikite Apr 8, 2024
c6ef2c9
assert length
mojotalantikite Apr 8, 2024
cc74d8c
cleaning up tests, adds asserts
mojotalantikite Apr 8, 2024
c342a11
remove fetchSubmittedContract
pearl-truss Apr 9, 2024
5aee09a
Merge branch 'wml-db-history' of https://github.com/Enterprise-CMCS/m…
pearl-truss Apr 9, 2024
c6516bf
add loading and error states
pearl-truss Apr 9, 2024
b37f87f
Merge branch 'main' into wml-db-history
macrael Apr 10, 2024
5b28925
migrate to new draftRates
macrael Apr 10, 2024
8d26735
Merge branch 'wml-db-history' of https://github.com/Enterprise-CMCS/m…
pearl-truss Apr 15, 2024
7ebbba6
wow everything passes
macrael Apr 15, 2024
f589287
Merge branch 'wml-db-history' of https://github.com/Enterprise-CMCS/m…
pearl-truss Apr 15, 2024
4fe6252
code clean up
pearl-truss Apr 15, 2024
dc11a52
fix import
macrael Apr 15, 2024
af49041
comments and fix a hidden build issue
macrael Apr 15, 2024
745da54
skip unmigrated rates
mojotalantikite Apr 16, 2024
23eb6ff
reimplmeent submit
macrael Apr 18, 2024
9f83988
Merge branch 'wml-db-history' of https://github.com/Enterprise-CMCS/m…
macrael Apr 18, 2024
acc5249
rate data mocks
macrael Apr 18, 2024
1d96a2d
add mccrsID to fetchContract query
pearl-truss Apr 18, 2024
78dc953
update v2 unlocksubmit modal to work with unlock contract
pearl-truss Apr 18, 2024
c82d4dc
create changeHistory V2 to use fetchContract, resolve errors
pearl-truss Apr 18, 2024
18043fc
Merge branch 'main' of https://github.com/Enterprise-CMCS/managed-car…
pearl-truss Apr 18, 2024
c456132
Merge branch 'wml-db-history' of https://github.com/Enterprise-CMCS/m…
pearl-truss Apr 18, 2024
3b6ac15
get submit working on ReviewSubmit page
pearl-truss Apr 18, 2024
57e2b4a
update contractPackageDataMock
pearl-truss Apr 18, 2024
37c9b04
remove references to packages in unlockSubmitModalV2
pearl-truss Apr 18, 2024
2252971
remove access optioinal chanining
pearl-truss Apr 18, 2024
e3ae827
update changehistoryv2 language and logic
pearl-truss Apr 18, 2024
7ee8429
add submissionsummartV2 for cmsRoutes
pearl-truss Apr 18, 2024
8b09893
fix reviewsubmit test
pearl-truss Apr 18, 2024
7784374
Merge branch 'main' of https://github.com/Enterprise-CMCS/managed-car…
pearl-truss Apr 18, 2024
f555a3b
pr updates
pearl-truss Apr 18, 2024
11d0268
restrict change history to contract actions for now
pearl-truss Apr 18, 2024
5bc2584
fix resubmit
pearl-truss Apr 18, 2024
d9c1df9
add reverse
pearl-truss Apr 18, 2024
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
Expand Up @@ -40,7 +40,7 @@ const contractFormDataSchema = z.object({
submissionDescription: z.string(),
stateContacts: z.array(stateContactSchema),
supportingDocuments: z.array(documentSchema),
contractType: contractTypeSchema,
contractType: contractTypeSchema.optional(),
contractExecutionStatus: contractExecutionStatusSchema.optional(),
contractDocuments: z.array(documentSchema),
contractDateStart: z.date().optional(),
Expand Down
29 changes: 23 additions & 6 deletions services/app-api/src/postgres/contractAndRates/submitContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import { findContractWithHistory } from './findContractWithHistory'
import { NotFoundError } from '../postgresErrors'
import type { UpdateInfoType } from '../../domain-models'
import { includeDraftRates } from './prismaDraftContractHelpers'
import type { ContractFormDataType } from '../../domain-models'

export type SubmitContractArgsType = {
contractID: string // revision ID
contractRevisionID?: string // this is a hack that should not outlive protobuf. rateID should be there and be required after we remove protos
formData?: ContractFormDataType
submittedByUserID: UpdateInfoType['updatedBy']
submittedReason: UpdateInfoType['updatedReason']
}
Expand All @@ -17,17 +20,29 @@ export async function submitContract(
client: PrismaClient,
args: SubmitContractArgsType
): Promise<ContractType | NotFoundError | Error> {
const { contractID, submittedByUserID, submittedReason } = args
const { contractID, submittedByUserID, contractRevisionID, submittedReason } = args
const currentDateTime = new Date()

console.log('in postgress', args)
try {
return await client.$transaction(async (tx) => {
if (!contractID && !contractRevisionID) {
return new Error(
'Either contractID or contractRevisionID must be supplied. both are blank'
)
}
// find the current contract with related rates
const findWhere = contractRevisionID
? {
id: contractRevisionID,
submitInfoID: null,
}
: {
contractID,
submitInfoID: null,
}
console.log(findWhere, 'findwhere')
const currentRev = await client.contractRevisionTable.findFirst({
where: {
contractID: contractID,
submitInfoID: null,
},
where: findWhere,
include: {
draftRates: {
include: includeDraftRates,
Expand All @@ -38,6 +53,7 @@ export async function submitContract(
if (!currentRev) {
const err = `PRISMA ERROR: Cannot find the current rev to submit with contract id: ${contractID}`
console.error(err)
console.log(err, 'err')
return new NotFoundError(err)
}

Expand Down Expand Up @@ -171,6 +187,7 @@ export async function submitContract(
return await findContractWithHistory(tx, contractID)
})
} catch (err) {
console.log('ultimate error', err)
const error = new Error(`Error submitting contract ${err}`)
return error
}
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 @@ -31,6 +31,7 @@ import { indexRatesResolver } from './rate/indexRates'
import { rateResolver } from './rate/rateResolver'
import { fetchRateResolver } from './rate/fetchRate'
import { updateContract } from './contract/updateContract'
import { submitContract } from './contract/submitContract'
import { createAPIKeyResolver } from './APIKey'
import { unlockRate } from './rate/unlockRate'
import { submitRate } from './rate/submitRate'
Expand Down Expand Up @@ -97,6 +98,7 @@ export function configureResolvers(
createAPIKey: createAPIKeyResolver(jwt),
unlockRate: unlockRate(store),
submitRate: submitRate(store, launchDarkly),
submitContract: submitContract(store, launchDarkly),
},
User: {
// resolveType is required to differentiate Unions
Expand Down
182 changes: 182 additions & 0 deletions services/app-api/src/resolvers/contract/submitContract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import type { Store } from '../../postgres'
import type { MutationResolvers } from '../../gen/gqlServer'
import {
setErrorAttributesOnActiveSpan,
setResolverDetailsOnActiveSpan,
} from '../attributeHelper'
import { isStateUser } from '../../domain-models'
import { logError } from '../../logger'
import { ForbiddenError, UserInputError } from 'apollo-server-lambda'
import { NotFoundError } from '../../postgres'
import { GraphQLError } from 'graphql/index'
import type { LDService } from '../../launchDarkly/launchDarkly'
import { generateRateCertificationName } from '../rate/generateRateCertificationName'
import { findStatePrograms } from '../../../../app-web/src/common-code/healthPlanFormDataType/findStatePrograms'
import { nullsToUndefined } from '../../domain-models/nullstoUndefined'

/*
Submit rate will change a draft revision to submitted and generate a rate name if one is missing
Also, if form data is passed in (such as on standalone rate edits) the form data itself will be updated
*/
export function submitContract(
store: Store,
launchDarkly: LDService
): MutationResolvers['submitContract'] {
return async (_parent, { input }, context) => {
console.log('in resolver')
const { user, span } = context
const { contractID, submittedReason, formData } = input
const featureFlags = await launchDarkly.allFlags(context)
setResolverDetailsOnActiveSpan('submitContract', user, span)
span?.setAttribute('mcreview.contract_id', contractID)

// throw error if the feature flag is off
if (!featureFlags?.['rate-edit-unlock']) {
const errMessage = `Not authorized to edit and submit a rate independently, the feature is disabled`
logError('submitContract', errMessage)
throw new ForbiddenError(errMessage, {
message: errMessage,
})
}

// This resolver is only callable by State users
if (!isStateUser(user)) {
const errMessage = 'user not authorized to submit rate'
logError('submitContract', errMessage)
setErrorAttributesOnActiveSpan(errMessage, span)
throw new ForbiddenError(errMessage)
}

// find the contract to submit
const unsubmittedContract = await store.findContractWithHistory(contractID)
console.log(unsubmittedContract, 'contract to submit')
if (unsubmittedContract instanceof Error) {
if (unsubmittedContract instanceof NotFoundError) {
const errMessage = `A rate must exist to be submitted: ${contractID}`
logError('submitContract', errMessage)
console.log(errMessage, 'errMessage')
setErrorAttributesOnActiveSpan(errMessage, span)
throw new UserInputError(errMessage, {
argumentName: 'contractID',
})
}

logError('submitContract', unsubmittedContract.message)
setErrorAttributesOnActiveSpan(unsubmittedContract.message, span)
throw new GraphQLError(unsubmittedContract.message, {
extensions: {
code: 'INTERNAL_SERVER_ERROR',
cause: 'DB_ERROR',
},
})
}

// const draftRevision = unsubmittedContract.draftRevision

// if (!draftRevision) {
// throw new Error(
// 'PROGRAMMING ERROR: Status should not be submittable without a draft rate revision'
// )
// }

// make sure it is draft or unlocked
if (
unsubmittedContract.status === 'SUBMITTED' ||
unsubmittedContract.status === 'RESUBMITTED'
) {
const errMessage = `Attempted to submit a rate that is already submitted`
logError('submitContract', errMessage)
setErrorAttributesOnActiveSpan(errMessage, span)
throw new UserInputError(errMessage, {
argumentName: 'contractID',
cause: 'INVALID_PACKAGE_STATUS',
})
}

// prepare to generate rate cert name - either use new form data coming down on submit or unsubmitted submission data already in database
const stateCode = unsubmittedContract.stateCode
const stateNumber = unsubmittedContract.stateNumber
const statePrograms = findStatePrograms(stateCode)
// const generatedRateCertName = formData
// ? generateRateCertificationName(
// nullsToUndefined(formData),
// stateCode,
// stateNumber,
// statePrograms
// )
// : generateRateCertificationName(
// draftRevision.formData,
// stateCode,
// stateNumber,
// statePrograms
// )

// combine existing db draft data with any form data added on submit
// call submit contract handler
const submittedContract = await store.submitContract({
contractID,
submittedByUserID: user.id,
submittedReason: submittedReason ?? 'Initial submission',
formData: formData
? {
contractType: formData.contractType ?? undefined,
programIDs: formData.programIDs ?? undefined,
populationCovered: formData.populationCovered ?? undefined,
submissionType: formData.submissionType ?? undefined,
riskBasedContract: formData.riskBasedContract ?? undefined,
submissionDescription: formData.submissionDescription ?? undefined,
stateContacts: [
{
name: 'Test Person',
titleRole: 'A Role',
email: 'test+state+contact@example.com',
},
],
supportingDocuments: formData.supportingDocuments ?? undefined,
contractExecutionStatus: formData.contractExecutionStatus ?? undefined,
contractDocuments: formData.contractDocuments ?? undefined,
contractDateStart: formData.contractDateStart ?? undefined,
contractDateEnd: formData.contractDateEnd ?? undefined,
managedCareEntities: formData.managedCareEntities ?? undefined,
federalAuthorities: formData.federalAuthorities ?? undefined,
inLieuServicesAndSettings: formData.inLieuServicesAndSettings ?? undefined,
modifiedBenefitsProvided: formData.modifiedBenefitsProvided ?? undefined,
modifiedGeoAreaServed: formData.modifiedGeoAreaServed ?? undefined,
modifiedMedicaidBeneficiaries: formData.modifiedMedicaidBeneficiaries ?? undefined,
modifiedRiskSharingStrategy: formData.modifiedRiskSharingStrategy ?? undefined,
modifiedIncentiveArrangements: formData.modifiedIncentiveArrangements ?? undefined,
modifiedWitholdAgreements: formData.modifiedWitholdAgreements ?? undefined,
modifiedStateDirectedPayments: formData.modifiedStateDirectedPayments ?? undefined,
modifiedPassThroughPayments: formData.modifiedPassThroughPayments ?? undefined,
modifiedPaymentsForMentalDiseaseInstitutions: formData.modifiedPaymentsForMentalDiseaseInstitutions ?? undefined,
modifiedMedicalLossRatioStandards: formData.modifiedMedicalLossRatioStandards ?? undefined,
modifiedOtherFinancialPaymentIncentive: formData.modifiedOtherFinancialPaymentIncentive ?? undefined,
modifiedEnrollmentProcess: formData.modifiedEnrollmentProcess ?? undefined,
modifiedGrevienceAndAppeal: formData.modifiedGrevienceAndAppeal ?? undefined,
modifiedNetworkAdequacyStandards: formData.modifiedNetworkAdequacyStandards ?? undefined,
modifiedLengthOfContract: formData.modifiedLengthOfContract ?? undefined,
modifiedNonRiskPaymentArrangements: formData.modifiedNonRiskPaymentArrangements ?? undefined,
statutoryRegulatoryAttestation: formData.statutoryRegulatoryAttestation ?? undefined,
statutoryRegulatoryAttestationDescription: formData.statutoryRegulatoryAttestationDescription ?? undefined,
} : undefined,
})

console.log(submittedContract, 'submitted contract in resolver')

if (submittedContract instanceof Error) {
const errMessage = `Failed to submit rate with ID: ${contractID}; ${submittedContract.message}`
logError('submitContract', errMessage)
setErrorAttributesOnActiveSpan(errMessage, span)
throw new GraphQLError(errMessage, {
extensions: {
code: 'INTERNAL_SERVER_ERROR',
cause: 'DB_ERROR',
},
})
}

return {
contract: submittedContract,
}
}
}
Loading
Loading