diff --git a/services/app-api/src/domain-models/contractAndRates/convertHPPtoContractWithRates.ts b/services/app-api/src/domain-models/contractAndRates/convertHPPtoContractWithRates.ts new file mode 100644 index 0000000000..ffb47e66ec --- /dev/null +++ b/services/app-api/src/domain-models/contractAndRates/convertHPPtoContractWithRates.ts @@ -0,0 +1,108 @@ +import type { UnlockedHealthPlanFormDataType } from 'app-web/src/common-code/healthPlanFormDataType' +import type { ContractFormData, RateFormData } from '../../gen/gqlServer' + +// interim solution -this file was made to deal with test helpers that may expect contract rates when we only have HPP coming from another test helper + +// Take a HPP domain model and return form datas we can use in contract or rate test helpers +// if there are no rates on this contract, return null +const convertUnlockedHPPToContractAndRates = ( + pkg: UnlockedHealthPlanFormDataType +): [ContractFormData, RateFormData[]] => { + const { + submissionType, + submissionDescription, + stateContacts, + contractType, + contractExecutionStatus, + contractDateStart, + contractDateEnd, + contractDocuments, + managedCareEntities, + federalAuthorities, + populationCovered, + statutoryRegulatoryAttestation, + statutoryRegulatoryAttestationDescription, + programIDs, + documents, + } = pkg + + const contractFormData: ContractFormData = { + submissionType, + submissionDescription, + stateContacts, + contractType, + contractExecutionStatus, + contractDateStart, + contractDateEnd, + programIDs, + contractDocuments, + supportingDocuments: documents, + managedCareEntities, + federalAuthorities, + populationCovered, + inLieuServicesAndSettings: + pkg.contractAmendmentInfo?.modifiedProvisions + .inLieuServicesAndSettings, + modifiedRiskSharingStrategy: + pkg.contractAmendmentInfo?.modifiedProvisions + .modifiedRiskSharingStrategy, + modifiedIncentiveArrangements: + pkg.contractAmendmentInfo?.modifiedProvisions + .modifiedIncentiveArrangements, + modifiedWitholdAgreements: + pkg.contractAmendmentInfo?.modifiedProvisions + .modifiedWitholdAgreements, + modifiedStateDirectedPayments: + pkg.contractAmendmentInfo?.modifiedProvisions + .modifiedStateDirectedPayments, + modifiedPassThroughPayments: + pkg.contractAmendmentInfo?.modifiedProvisions + .modifiedPassThroughPayments, + modifiedPaymentsForMentalDiseaseInstitutions: + pkg.contractAmendmentInfo?.modifiedProvisions + .modifiedPaymentsForMentalDiseaseInstitutions, + modifiedNonRiskPaymentArrangements: + pkg.contractAmendmentInfo?.modifiedProvisions + .modifiedNonRiskPaymentArrangements, + statutoryRegulatoryAttestation, + statutoryRegulatoryAttestationDescription, + } + const rateFormDatas: RateFormData[] = pkg.rateInfos.map( + (rateInfo): RateFormData => { + const { + rateType, + rateCapitationType, + rateCertificationName, + rateDateCertified, + rateDateEnd, + rateDateStart, + rateDocuments = [], + supportingDocuments = [], + rateProgramIDs = [], + addtlActuaryContacts = [], + actuaryCommunicationPreference, + } = rateInfo + + return { + rateType, + rateCapitationType, + rateCertificationName, + rateDateCertified, + rateDateEnd, + rateDateStart, + rateDocuments, + supportingDocuments, + rateProgramIDs, + certifyingActuaryContacts: [rateInfo.actuaryContacts[0]], + deprecatedRateProgramIDs: [], //ignore this deprecated field + packagesWithSharedRateCerts: [], // ignore this depårecated field + addtlActuaryContacts, + actuaryCommunicationPreference, + } + } + ) + + return [contractFormData, rateFormDatas] +} + +export { convertUnlockedHPPToContractAndRates } diff --git a/services/app-api/src/resolvers/healthPlanPackage/submitHealthPlanPackage.ts b/services/app-api/src/resolvers/healthPlanPackage/submitHealthPlanPackage.ts index 0fad32dc91..78a203f25e 100644 --- a/services/app-api/src/resolvers/healthPlanPackage/submitHealthPlanPackage.ts +++ b/services/app-api/src/resolvers/healthPlanPackage/submitHealthPlanPackage.ts @@ -132,7 +132,6 @@ export function parseAndSubmit( : draft.statutoryRegulatoryAttestation || (draft.statutoryRegulatoryAttestation === false && draft.statutoryRegulatoryAttestationDescription) - if ( isValidAndCurrentLockedHealthPlanFormData(maybeStateSubmission) && hasValid438Attestation diff --git a/services/app-api/src/testHelpers/gqlContractHelpers.ts b/services/app-api/src/testHelpers/gqlContractHelpers.ts index a5159cdf1f..5bbe62d0cd 100644 --- a/services/app-api/src/testHelpers/gqlContractHelpers.ts +++ b/services/app-api/src/testHelpers/gqlContractHelpers.ts @@ -14,14 +14,11 @@ import { mockInsertContractArgs, mockContractData } from './contractDataMocks' import { sharedTestPrismaClient } from './storeHelpers' import { insertDraftContract } from '../postgres/contractAndRates/insertContract' -import type { ContractType } from '../domain-models' +import { type ContractType } from '../domain-models' import type { ApolloServer } from 'apollo-server-lambda' -import type { Contract, RateFormData } from '../gen/gqlServer' +import type { Contract, ContractFormData, RateFormData } from '../gen/gqlServer' import { latestFormData } from './healthPlanPackageHelpers' -import type { - StateCodeType, - UnlockedHealthPlanFormDataType, -} from 'app-web/src/common-code/healthPlanFormDataType' +import type { StateCodeType } from 'app-web/src/common-code/healthPlanFormDataType' import { addNewRateToTestContract } from './gqlRateHelpers' const createAndSubmitTestContract = async ( @@ -149,7 +146,7 @@ async function createAndUpdateTestContractWithRate( const createAndUpdateTestContractWithoutRates = async ( server: ApolloServer, stateCode?: StateCodeType, - contractFormDataOverrides?: Partial + contractFormDataOverrides?: Partial ): Promise => { const pkg = await createTestHealthPlanPackage(server, stateCode) const draft = latestFormData(pkg) @@ -200,11 +197,12 @@ const createAndUpdateTestContractWithoutRates = async ( return updatedContract } -const linkRateToDraftContract = async ( server: ApolloServer, +const linkRateToDraftContract = async ( + server: ApolloServer, contractID: string, - linkedRateID: string) => { - - const updatedContract = await server.executeOperation({ + linkedRateID: string +) => { + const updatedContract = await server.executeOperation({ query: UPDATE_DRAFT_CONTRACT_RATES, variables: { input: { @@ -221,18 +219,16 @@ const linkRateToDraftContract = async ( server: ApolloServer, return updatedContract } -const clearRatesOnDraftContract = async ( server: ApolloServer, - contractID: string, - ) => { - - const updatedContract = await server.executeOperation({ +const clearRatesOnDraftContract = async ( + server: ApolloServer, + contractID: string +) => { + const updatedContract = await server.executeOperation({ query: UPDATE_DRAFT_CONTRACT_RATES, variables: { input: { contractID: contractID, - updatedRates: [ - - ], + updatedRates: [], }, }, }) @@ -243,10 +239,9 @@ const updateRateOnDraftContract = async ( server: ApolloServer, contractID: string, rateID: string, - rateData: Partial, -) : Promise => { - - const updatedContract = await server.executeOperation({ + rateData: Partial +): Promise => { + const updatedContract = await server.executeOperation({ query: UPDATE_DRAFT_CONTRACT_RATES, variables: { input: { @@ -255,7 +250,7 @@ const updateRateOnDraftContract = async ( { type: 'UPDATE', formData: rateData, - rateID: rateID + rateID: rateID, }, ], }, @@ -263,11 +258,11 @@ const updateRateOnDraftContract = async ( }) must(updatedContract) const contractData = updatedContract.data?.updateDraftContractRates.contract - if (!contractData)throw Error (`malformatted response: ${updatedContract.data}` ) + if (!contractData) + throw Error(`malformatted response: ${updatedContract.data}`) return updatedContract.data?.contract } - export { createTestContract, submitTestContract, @@ -278,5 +273,5 @@ export { createAndSubmitTestContractWithRate, linkRateToDraftContract, updateRateOnDraftContract, - clearRatesOnDraftContract + clearRatesOnDraftContract, } diff --git a/services/app-api/src/testHelpers/gqlHelpers.ts b/services/app-api/src/testHelpers/gqlHelpers.ts index 2c5c168a2a..6296a6d6ba 100644 --- a/services/app-api/src/testHelpers/gqlHelpers.ts +++ b/services/app-api/src/testHelpers/gqlHelpers.ts @@ -45,6 +45,9 @@ import { findStatePrograms } from '../postgres' import { must } from './assertionHelpers' import { newJWTLib } from '../jwt' import type { JWTLib } from '../jwt' +import { convertUnlockedHPPToContractAndRates } from '../domain-models/contractAndRates/convertHPPtoContractWithRates' +import { createAndUpdateTestContractWithoutRates } from './gqlContractHelpers' +import { addNewRateToTestContract } from './gqlRateHelpers' // Since our programs are checked into source code, we have a program we // use as our default @@ -229,97 +232,111 @@ const createAndUpdateTestHealthPlanPackage = async ( partialUpdates?: Partial, stateCode?: StateCodeType ): Promise => { - const pkg = await createTestHealthPlanPackage(server, stateCode) - const draft = latestFormData(pkg) - const ratePrograms = stateCode ? [must(findStatePrograms(stateCode))[0]] : [defaultFloridaRateProgram()] - ;(draft.submissionType = 'CONTRACT_AND_RATES' as const), - (draft.submissionDescription = 'An updated submission') - draft.stateContacts = [ - { - name: 'test name', - titleRole: 'test title', - email: 'email@example.com', - }, - ] - draft.rateInfos = [ - { - id: uuidv4(), - rateType: 'NEW' as const, - rateDateStart: new Date(Date.UTC(2025, 5, 1)), - rateDateEnd: new Date(Date.UTC(2026, 4, 30)), - rateDateCertified: new Date(Date.UTC(2025, 3, 15)), - rateDocuments: [ - { - name: 'rateDocument.pdf', - s3URL: 'fakeS3URL', - sha256: 'fakesha', - }, - ], - supportingDocuments: [], - //We only want one rate ID and use last program in list to differentiate from programID if possible. - rateProgramIDs: [ratePrograms.reverse()[0].id], - actuaryContacts: [ - { - id: '123-abc', - name: 'test name', - titleRole: 'test title', - email: 'email@example.com', - actuarialFirm: 'MERCER' as const, - actuarialFirmOther: '', - }, - ], - actuaryCommunicationPreference: 'OACT_TO_ACTUARY' as const, - packagesWithSharedRateCerts: [], - }, - ] - draft.addtlActuaryContacts = [ - { - id: '123-addtl-abv', - name: 'test name', - titleRole: 'test title', - email: 'email@example.com', - actuarialFirm: 'MERCER' as const, - actuarialFirmOther: '', - }, - ] - ;(draft.addtlActuaryCommunicationPreference = 'OACT_TO_ACTUARY' as const), - (draft.contractType = 'BASE' as const) - draft.contractExecutionStatus = 'EXECUTED' as const - draft.contractDateStart = new Date(Date.UTC(2025, 5, 1)) - draft.contractDateEnd = new Date(Date.UTC(2026, 4, 30)) - draft.contractDocuments = [ - { - name: 'contractDocument.pdf', - s3URL: 'fakeS3URL', - sha256: 'fakesha', - }, - ] - draft.managedCareEntities = ['MCO'] - draft.federalAuthorities = ['STATE_PLAN' as const] - draft.populationCovered = 'MEDICAID' as const - draft.contractAmendmentInfo = { - modifiedProvisions: { - inLieuServicesAndSettings: true, - modifiedRiskSharingStrategy: false, - modifiedIncentiveArrangements: false, - modifiedWitholdAgreements: false, - modifiedStateDirectedPayments: true, - modifiedPassThroughPayments: true, - modifiedPaymentsForMentalDiseaseInstitutions: true, - modifiedNonRiskPaymentArrangements: true, + const draft: Partial = { + submissionType: 'CONTRACT_AND_RATES' as const, + submissionDescription: 'An updated submission', + stateContacts: [ + { + name: 'test name', + titleRole: 'test title', + email: 'email@example.com', + }, + ], + rateInfos: [ + { + id: uuidv4(), + rateType: 'NEW' as const, + rateDateStart: new Date(Date.UTC(2025, 5, 1)), + rateDateEnd: new Date(Date.UTC(2026, 4, 30)), + rateDateCertified: new Date(Date.UTC(2025, 3, 15)), + rateDocuments: [ + { + name: 'rateDocument.pdf', + s3URL: 'fakeS3URL', + sha256: 'fakesha', + }, + ], + supportingDocuments: [], + //We only want one rate ID and use last program in list to differentiate from programID if possible. + rateProgramIDs: [ratePrograms.reverse()[0].id], + actuaryContacts: [ + { + id: '123-abc', + name: 'test name', + titleRole: 'test title', + email: 'email@example.com', + actuarialFirm: 'MERCER' as const, + actuarialFirmOther: '', + }, + ], + actuaryCommunicationPreference: 'OACT_TO_ACTUARY' as const, + packagesWithSharedRateCerts: [], + }, + ], + addtlActuaryContacts: [ + { + id: '123-addtl-abv', + name: 'test name', + titleRole: 'test title', + email: 'email@example.com', + actuarialFirm: 'MERCER' as const, + actuarialFirmOther: '', + }, + ], + addtlActuaryCommunicationPreference: 'OACT_TO_ACTUARY' as const, + contractType: 'BASE' as const, + contractExecutionStatus: 'EXECUTED' as const, + contractDateStart: new Date(Date.UTC(2025, 5, 1)), + contractDateEnd: new Date(Date.UTC(2026, 4, 30)), + contractDocuments: [ + { + name: 'contractDocument.pdf', + s3URL: 'fakeS3URL', + sha256: 'fakesha', + }, + ], + managedCareEntities: ['MCO'], + federalAuthorities: ['STATE_PLAN' as const], + populationCovered: 'MEDICAID' as const, + contractAmendmentInfo: { + modifiedProvisions: { + inLieuServicesAndSettings: true, + modifiedRiskSharingStrategy: false, + modifiedIncentiveArrangements: false, + modifiedWitholdAgreements: false, + modifiedStateDirectedPayments: true, + modifiedPassThroughPayments: true, + modifiedPaymentsForMentalDiseaseInstitutions: true, + modifiedNonRiskPaymentArrangements: true, + }, }, + statutoryRegulatoryAttestation: false, + statutoryRegulatoryAttestationDescription: 'No compliance', } - draft.statutoryRegulatoryAttestation = false - draft.statutoryRegulatoryAttestationDescription = 'No compliance' Object.assign(draft, partialUpdates) - - const updatedDraft = await updateTestHealthPlanFormData(server, draft) - + const [contractFormData, rateFormDatas] = + convertUnlockedHPPToContractAndRates( + draft as UnlockedHealthPlanFormDataType + ) + const contract = await createAndUpdateTestContractWithoutRates( + server, + stateCode, + contractFormData + ) + if (rateFormDatas.length > 0) { + rateFormDatas.forEach(async (rateData) => { + await addNewRateToTestContract(server, contract, rateData) + }) + } + const updatedDraft = await fetchTestHealthPlanPackageById( + server, + contract.id + ) return updatedDraft } @@ -331,6 +348,7 @@ const createAndSubmitTestHealthPlanPackage = async ( server, partialUpdates ) + return await submitTestHealthPlanPackage(server, pkg.id) }