diff --git a/services/app-web/src/common-code/ContractType.ts b/services/app-web/src/common-code/ContractType.ts index 9c797a4952..4cb3bc6278 100644 --- a/services/app-web/src/common-code/ContractType.ts +++ b/services/app-web/src/common-code/ContractType.ts @@ -1,36 +1,37 @@ import { Contract, ContractRevision } from '../gen/gqlClient' +import { getLastContractSubmission } from '../gqlHelpers/contractsAndRates' -const getContractRev = (contract: Contract): ContractRevision => { +const getContractRev = (contract: Contract): ContractRevision | undefined => { if (contract.draftRevision) { return contract.draftRevision } else { - return contract.packageSubmissions[0].contractRevision + return getLastContractSubmission(contract)?.contractRevision } } const isContractOnly = (contract: Contract): boolean => { const contractRev = getContractRev(contract) - return contractRev.formData.submissionType === 'CONTRACT_ONLY' + return contractRev?.formData?.submissionType === 'CONTRACT_ONLY' } const isBaseContract = (contract: Contract): boolean => { const contractRev = getContractRev(contract) - return contractRev.formData.contractType === 'BASE' + return contractRev?.formData?.contractType === 'BASE' } const isContractAmendment = (contract: Contract): boolean => { const contractRev = getContractRev(contract) - return contractRev.formData.contractType === 'AMENDMENT' + return contractRev?.formData?.contractType === 'AMENDMENT' } const isCHIPOnly = (contract: Contract): boolean => { const contractRev = getContractRev(contract) - return contractRev.formData.populationCovered === 'CHIP' + return contractRev?.formData?.populationCovered === 'CHIP' } const isContractAndRates = (contract: Contract): boolean => { const contractRev = getContractRev(contract) - return contractRev.formData.submissionType === 'CONTRACT_AND_RATES' + return contractRev?.formData?.submissionType === 'CONTRACT_AND_RATES' } const isContractWithProvisions = (contract: Contract): boolean => diff --git a/services/app-web/src/common-code/ContractTypeProvisions.ts b/services/app-web/src/common-code/ContractTypeProvisions.ts index da16b3a56e..fb16078f6f 100644 --- a/services/app-web/src/common-code/ContractTypeProvisions.ts +++ b/services/app-web/src/common-code/ContractTypeProvisions.ts @@ -22,6 +22,7 @@ import { isContractAmendment, isContractWithProvisions, } from './ContractType' +import { getLastContractSubmission } from '../gqlHelpers/contractsAndRates' /* Each provision key represents a Yes/No question asked on Contract Details. @@ -84,27 +85,27 @@ const generateProvisionLabel = ( const sortModifiedProvisions = ( contract: Contract ): [GeneralizedProvisionType[], GeneralizedProvisionType[]] => { - const contractFormData = contract.draftRevision?.formData || contract.packageSubmissions[0].contractRevision.formData + const contractFormData = contract.draftRevision?.formData || getLastContractSubmission(contract)?.contractRevision.formData const initialProvisions = { - inLieuServicesAndSettings: contractFormData.inLieuServicesAndSettings, - modifiedBenefitsProvided: contractFormData.modifiedBenefitsProvided, - modifiedGeoAreaServed: contractFormData.modifiedGeoAreaServed, - modifiedMedicaidBeneficiaries: contractFormData.modifiedMedicaidBeneficiaries, - modifiedRiskSharingStrategy: contractFormData.modifiedRiskSharingStrategy, - modifiedIncentiveArrangements: contractFormData.modifiedIncentiveArrangements, - modifiedWitholdAgreements: contractFormData.modifiedWitholdAgreements, - modifiedStateDirectedPayments: contractFormData.modifiedStateDirectedPayments, - modifiedPassThroughPayments: contractFormData.modifiedPassThroughPayments, - modifiedPaymentsForMentalDiseaseInstitutions: contractFormData.modifiedPaymentsForMentalDiseaseInstitutions, - modifiedMedicalLossRatioStandards: contractFormData.modifiedMedicalLossRatioStandards, - modifiedOtherFinancialPaymentIncentive: contractFormData.modifiedOtherFinancialPaymentIncentive, - modifiedEnrollmentProcess: contractFormData.modifiedEnrollmentProcess, - modifiedGrevienceAndAppeal: contractFormData.modifiedGrevienceAndAppeal, - modifiedNetworkAdequacyStandards: contractFormData.modifiedNetworkAdequacyStandards, - modifiedLengthOfContract: contractFormData.modifiedLengthOfContract, - modifiedNonRiskPaymentArrangements: contractFormData.modifiedNonRiskPaymentArrangements, - statutoryRegulatoryAttestation: contractFormData.statutoryRegulatoryAttestation, - statutoryRegulatoryAttestationDescription: contractFormData.statutoryRegulatoryAttestationDescription + inLieuServicesAndSettings: contractFormData?.inLieuServicesAndSettings, + modifiedBenefitsProvided: contractFormData?.modifiedBenefitsProvided, + modifiedGeoAreaServed: contractFormData?.modifiedGeoAreaServed, + modifiedMedicaidBeneficiaries: contractFormData?.modifiedMedicaidBeneficiaries, + modifiedRiskSharingStrategy: contractFormData?.modifiedRiskSharingStrategy, + modifiedIncentiveArrangements: contractFormData?.modifiedIncentiveArrangements, + modifiedWitholdAgreements: contractFormData?.modifiedWitholdAgreements, + modifiedStateDirectedPayments: contractFormData?.modifiedStateDirectedPayments, + modifiedPassThroughPayments: contractFormData?.modifiedPassThroughPayments, + modifiedPaymentsForMentalDiseaseInstitutions: contractFormData?.modifiedPaymentsForMentalDiseaseInstitutions, + modifiedMedicalLossRatioStandards: contractFormData?.modifiedMedicalLossRatioStandards, + modifiedOtherFinancialPaymentIncentive: contractFormData?.modifiedOtherFinancialPaymentIncentive, + modifiedEnrollmentProcess: contractFormData?.modifiedEnrollmentProcess, + modifiedGrevienceAndAppeal: contractFormData?.modifiedGrevienceAndAppeal, + modifiedNetworkAdequacyStandards: contractFormData?.modifiedNetworkAdequacyStandards, + modifiedLengthOfContract: contractFormData?.modifiedLengthOfContract, + modifiedNonRiskPaymentArrangements: contractFormData?.modifiedNonRiskPaymentArrangements, + statutoryRegulatoryAttestation: contractFormData?.statutoryRegulatoryAttestation, + statutoryRegulatoryAttestationDescription: contractFormData?.statutoryRegulatoryAttestationDescription } const hasInitialProvisions = Object.values(initialProvisions).some((val) => val !== undefined) const modifiedProvisions: GeneralizedProvisionType[] = [] diff --git a/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ContactsSummarySectionV2.tsx b/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ContactsSummarySectionV2.tsx index fe731f2ffe..430e1a6eb3 100644 --- a/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ContactsSummarySectionV2.tsx +++ b/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ContactsSummarySectionV2.tsx @@ -46,11 +46,11 @@ export const ContactsSummarySection = ({ const isSubmitted = contract.status === 'SUBMITTED' const contractFormData = contract.draftRevision?.formData || - contract.packageSubmissions[0].contractRevision.formData + getLastContractSubmission(contract)?.contractRevision.formData let rateRev: RateRevision | undefined = undefined - if (contractFormData.submissionType === 'CONTRACT_AND_RATES') { + if (contractFormData?.submissionType === 'CONTRACT_AND_RATES') { // Find first rate associated with the contract to deal with rates info on contacts page // TODO move the fields using this data to rate details const draftRates = getDraftRates(contract) @@ -68,8 +68,8 @@ export const ContactsSummarySection = ({
- {contractFormData.stateContacts.length > 0 ? ( - contractFormData.stateContacts.map( + {contractFormData && contractFormData.stateContacts.length > 0 ? ( + contractFormData?.stateContacts.map( (stateContact, index) => ( - {contractFormData.submissionType === 'CONTRACT_AND_RATES' && ( + {contractFormData?.submissionType === 'CONTRACT_AND_RATES' && ( <> {rateRev?.formData?.addtlActuaryContacts !== undefined && rateRev.formData.addtlActuaryContacts.length > 0 && ( diff --git a/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ContractDetailsSummarySectionV2.tsx b/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ContractDetailsSummarySectionV2.tsx index 761c5d2e22..63b93b1d5f 100644 --- a/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ContractDetailsSummarySectionV2.tsx +++ b/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ContractDetailsSummarySectionV2.tsx @@ -87,20 +87,20 @@ export const ContractDetailsSummarySectionV2 = ({ const contractFormData = contract.draftRevision?.formData || - contract.packageSubmissions[0].contractRevision.formData + getLastContractSubmission(contract)?.contractRevision.formData const contract438Attestation = ldClient?.variation( featureFlags.CONTRACT_438_ATTESTATION.flag, featureFlags.CONTRACT_438_ATTESTATION.defaultValue ) const attestationYesNo = - contractFormData.statutoryRegulatoryAttestation != null && + contractFormData?.statutoryRegulatoryAttestation != null && booleanAsYesNoFormValue(contractFormData.statutoryRegulatoryAttestation) const contractSupportingDocuments = contractFormData?.supportingDocuments const isEditing = !isSubmitted(contract) && editNavigateTo !== undefined const applicableFederalAuthorities = isCHIPOnly(contract) - ? contractFormData.federalAuthorities.filter((authority) => + ? contractFormData?.federalAuthorities.filter((authority) => federalAuthorityKeysForCHIP.includes( authority as CHIPFederalAuthority ) @@ -116,7 +116,7 @@ export const ContractDetailsSummarySectionV2 = ({ // get all the keys for the documents we want to zip async function fetchZipUrl() { - const keysFromDocs = contractFormData.contractDocuments + const keysFromDocs = contractSupportingDocuments && contractFormData?.contractDocuments .concat(contractSupportingDocuments) .map((doc) => { const key = getKey(doc.s3URL) @@ -126,7 +126,7 @@ export const ContractDetailsSummarySectionV2 = ({ .filter((key) => key !== '') // call the lambda to zip the files and get the url - const zippedURL = await getBulkDlURL( + const zippedURL = keysFromDocs && await getBulkDlURL( keysFromDocs, submissionName + '-contract-details.zip', 'HEALTH_PLAN_DOCS' @@ -204,7 +204,7 @@ export const ContractDetailsSummarySectionV2 = ({ label="Non-compliance description" explainMissingData={!isSubmitted} children={ - contractFormData.statutoryRegulatoryAttestationDescription + contractFormData?.statutoryRegulatoryAttestationDescription } /> @@ -314,7 +314,7 @@ export const ContractDetailsSummarySectionV2 = ({ )}
- {contractFormData.contractDocuments && ( + {contractFormData?.contractDocuments && ( { - return rateFormData.packagesWithSharedRateCerts?.map( + return rateFormData?.packagesWithSharedRateCerts?.map( ({ packageId, packageName }) => { const refreshedName = packageId && @@ -118,8 +118,8 @@ export const RateDetailsSummarySectionV2 = ({ const rateCapitationType = (rate: Rate | RateRevision) => { const rateFormData = getRateFormData(rate) - return rateFormData.rateCapitationType - ? rateFormData.rateCapitationType === 'RATE_CELL' + return rateFormData?.rateCapitationType + ? rateFormData?.rateCapitationType === 'RATE_CELL' ? 'Certification of capitation rates specific to each rate cell' : 'Certification of rate ranges of capitation rates per rate cell' : '' @@ -131,10 +131,10 @@ export const RateDetailsSummarySectionV2 = ({ const rateFormData = getRateFormData(rate) if ( - rateFormData.rateProgramIDs && - rateFormData.rateProgramIDs.length > 0 + rateFormData?.rateProgramIDs && + rateFormData?.rateProgramIDs.length > 0 ) { - programIDs = rateFormData.rateProgramIDs + programIDs = rateFormData?.rateProgramIDs } else if ( contractFormData?.programIDs && contractFormData?.programIDs.length > 0 @@ -150,10 +150,10 @@ export const RateDetailsSummarySectionV2 = ({ const rateCertificationType = (rate: Rate | RateRevision) => { const rateFormData = getRateFormData(rate) - if (rateFormData.rateType === 'AMENDMENT') { + if (rateFormData?.rateType === 'AMENDMENT') { return 'Amendment to prior rate certification' } - if (rateFormData.rateType === 'NEW') { + if (rateFormData?.rateType === 'NEW') { return 'New rate certification' } } @@ -166,7 +166,7 @@ export const RateDetailsSummarySectionV2 = ({ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return rate.draftRevision!.formData } else { - return rate.revisions[0].formData + return rate.revisions[0]?.formData } } else { return rate.formData @@ -179,7 +179,7 @@ export const RateDetailsSummarySectionV2 = ({ // get all the keys for the documents we want to zip async function fetchZipUrl() { - const submittedRates = contract.packageSubmissions[0].rateRevisions + const submittedRates = getLastContractSubmission(contract)?.rateRevisions if (submittedRates !== undefined) { const keysFromDocs = submittedRates .flatMap((rateInfo) => @@ -246,7 +246,7 @@ export const RateDetailsSummarySectionV2 = ({ aria-label={`Rate ID: ${rateFormData?.rateCertificationName}`} className={styles.rateName} > - {rateFormData.rateCertificationName} + {rateFormData?.rateCertificationName}
@@ -267,15 +267,15 @@ export const RateDetailsSummarySectionV2 = ({ {rateFormData?.amendmentEffectiveDateStart ? ( @@ -304,14 +304,14 @@ export const RateDetailsSummarySectionV2 = ({ label="Rate amendment effective dates" explainMissingData={!isSubmitted} children={`${formatCalendarDate( - rateFormData.amendmentEffectiveDateStart + rateFormData?.amendmentEffectiveDateStart )} to ${formatCalendarDate( - rateFormData.amendmentEffectiveDateEnd + rateFormData?.amendmentEffectiveDateEnd )}`} /> ) : null} {rateFormData - .certifyingActuaryContacts[0] && ( + ?.certifyingActuaryContacts[0] && ( {rateFormData?.rateDocuments && ( { - return ( - - - } - /> - - ) -} - -describe.skip('ReviewSubmit', () => { - it.skip('renders without errors', async () => { - renderWithProviders(wrapInRoutes(), +describe('ReviewSubmit', () => { + it('renders without errors', async () => { + renderWithProviders( + + } + /> + , { apolloProvider: { mocks: [ fetchCurrentUserMock({ statusCode: 200 }), - fetchContractMockSuccess({ contract: { id: 'test-abc-123' } }), + fetchContractMockSuccess({ + contract: { + id: 'test-abc-123', + } + }), ], }, routerProvider: { route: '/submissions/test-abc-123/edit/review-and-submit', - } + }, + featureFlags: { + 'link-rates': true, + }, }) + await waitFor(() => { expect( screen.getByRole('heading', { name: 'Contract details' }) - ).toBeInTheDocument() + ).toBeInTheDocument() }) - }) - it.skip('displays edit buttons for every section', async () => { - renderWithProviders(, { - apolloProvider: { - mocks: [fetchCurrentUserMock({ statusCode: 200 })], - }, - }) + it('displays edit buttons for every section', async () => { + renderWithProviders( + + } + /> + , + { + apolloProvider: { + mocks: [ + fetchCurrentUserMock({ statusCode: 200 }), + fetchContractMockSuccess({ + contract: { + id: 'test-abc-123', + } + }), + ], + }, + routerProvider: { + route: '/submissions/test-abc-123/edit/review-and-submit', + }, + featureFlags: { + 'link-rates': true, + }, + }) await waitFor(() => { const sectionHeadings = screen.queryAllByRole('heading', { @@ -64,12 +83,32 @@ describe.skip('ReviewSubmit', () => { }) }) - it.skip('does not display zip download buttons', async () => { - renderWithProviders(, { - apolloProvider: { - mocks: [fetchCurrentUserMock({ statusCode: 200 })], - }, - }) + it('does not display zip download buttons', async () => { + renderWithProviders( + + } + /> + , + { + apolloProvider: { + mocks: [ + fetchCurrentUserMock({ statusCode: 200 }), + fetchContractMockSuccess({ + contract: { + id: 'test-abc-123', + } + }), + ], + }, + routerProvider: { + route: '/submissions/test-abc-123/edit/review-and-submit', + }, + featureFlags: { + 'link-rates': true, + }, + }) await waitFor(() => { const bulkDownloadButtons = screen.queryAllByRole('button', { @@ -79,12 +118,30 @@ describe.skip('ReviewSubmit', () => { }) }) - it.skip('renders info from a DraftSubmission', async () => { - renderWithProviders(, { - apolloProvider: { - mocks: [fetchCurrentUserMock({ statusCode: 200 })], - }, - }) + it('renders info from a draft contract', async () => { + renderWithProviders( + + } + /> + , + { + apolloProvider: { + mocks: [ + fetchCurrentUserMock({ statusCode: 200 }), + fetchContractMockSuccess({ + contract: {id: 'test-abc-123' } + }), + ], + }, + routerProvider: { + route: '/submissions/test-abc-123/edit/review-and-submit', + }, + featureFlags: { + 'link-rates': true, + }, + }) await waitFor(() => { expect( @@ -104,7 +161,7 @@ describe.skip('ReviewSubmit', () => { expect(sectionHeadings.length).toBeGreaterThanOrEqual( editButtons.length ) - + screen.debug() const submissionDescription = screen.queryByText('A real submission') expect(submissionDescription).toBeInTheDocument() diff --git a/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ReviewSubmitV2.tsx b/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ReviewSubmitV2.tsx index 52ae9ebef0..41f155a001 100644 --- a/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ReviewSubmitV2.tsx +++ b/services/app-web/src/pages/StateSubmission/ReviewSubmit/V2/ReviewSubmit/ReviewSubmitV2.tsx @@ -9,11 +9,14 @@ import { DynamicStepIndicator } from '../../../../../components' import { PageActionsContainer } from '../../../PageActions' import styles from '../../../ReviewSubmit/ReviewSubmit.module.scss' import { ActionButton } from '../../../../../components/ActionButton' -import { useStatePrograms } from '../../../../../hooks/useStatePrograms' +import { useStatePrograms } from '../../../../../hooks' import { RoutesRecord, STATE_SUBMISSION_FORM_ROUTES, } from '../../../../../constants' +import { + getLastContractSubmission, +} from '../../../../../gqlHelpers/contractsAndRates' import { useAuth } from '../../../../../contexts/AuthContext' import { RateDetailsSummarySectionV2 } from './RateDetailsSummarySectionV2' import { ContactsSummarySection } from './ContactsSummarySectionV2' @@ -46,7 +49,7 @@ export const ReviewSubmitV2 = (): React.ReactElement => { 'PROGRAMMING ERROR: id param not set in state submission form.' ) } - + const { data, loading, error } = useFetchContractQuery({ variables: { input: { @@ -57,7 +60,6 @@ export const ReviewSubmitV2 = (): React.ReactElement => { }) const contract = data?.fetchContract.contract - useEffect(() => { updateHeading({ customHeading: contract?.draftRevision?.contractName, @@ -93,18 +95,18 @@ export const ReviewSubmitV2 = (): React.ReactElement => { contract.draftRates && contract.draftRates.length > 0 const contractFormData = contract.draftRevision?.formData || - contract.packageSubmissions[0].contractRevision.formData - const programIDs = contractFormData.programIDs + getLastContractSubmission(contract)?.contractRevision.formData + const programIDs = contractFormData?.programIDs const programs = statePrograms.filter((program) => - programIDs.includes(program.id) + programIDs?.includes(program.id) ) - const submissionName = packageName( + const submissionName = contractFormData && packageName( contract.stateCode, contract.stateNumber, contractFormData.programIDs, programs - ) + ) || '' return ( <>
@@ -120,13 +122,14 @@ export const ReviewSubmitV2 = (): React.ReactElement => {
This is the V2 version of the Review Submit Page
- - + )} contractFormData.programIDs.includes(p.id)) + .filter((p) => contractFormData?.programIDs.includes(p.id)) .map((p) => p.name) const isSubmitted = contract.status === 'SUBMITTED' // const isRiskBasedContract = contractFormData.riskBasedContract === @@ -56,7 +59,6 @@ export const SubmissionTypeSummarySectionV2 = ({ > {headerChildComponent && headerChildComponent} -
{isSubmitted && !isPreviousSubmission && ( @@ -71,7 +73,6 @@ export const SubmissionTypeSummarySectionV2 = ({ } /> - <> )} @@ -81,7 +82,8 @@ export const SubmissionTypeSummarySectionV2 = ({ explainMissingData={!isSubmitted} children={programNames} /> - - - {contractFormData.riskBasedContract !== null && ( + )} + {contractFormData && contractFormData?.riskBasedContract !== null && ( )} - + )} - + )}