Skip to content

Commit

Permalink
handle child rates correctly and get current data
Browse files Browse the repository at this point in the history
  • Loading branch information
macrael committed Apr 19, 2024
1 parent 1d9d9b4 commit a4be8f7
Show file tree
Hide file tree
Showing 16 changed files with 514 additions and 67 deletions.
53 changes: 48 additions & 5 deletions services/app-web/src/gqlHelpers/contractsAndRates.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,57 @@
/*
These helpers help you access nested data from the Contract and Rate Apollo Client types
If the data doesn't exist, returs undefined reliably
If the data doesn't exist, returns undefined reliably
*/

import { Contract, ContractFormData, ContractPackageSubmission, Rate } from "../gen/gqlClient"
import { Contract, ContractFormData, ContractPackageSubmission, Rate, RateRevision } from "../gen/gqlClient"


function getVisibleLatestRateRevisions(contract: Contract, isEditing: boolean): RateRevision[] | undefined {
if (isEditing) {
if (!contract.draftRates) {
console.error('Programming Error: on the rate details page with no draft rates')
return undefined
}
const rateRevs = []
for (const rate of contract.draftRates) {
// if this is a child rate, return draft revision
if (rate.parentContractID === contract.id) {
if (!rate.draftRevision) {
// TODO: this error will likely no longer apply once we have Unlock/Submit Rate
// child rates will no longer be assumed to be unlocked with their parent contracts
console.error('Programming Error: A child rate is not a draft')
return undefined
}
rateRevs.push(rate.draftRevision)
} else {
// otherwise return the latest revision submitted.
const lastRateSubmission = rate.revisions[0]
if (!lastRateSubmission) {
console.error('Programming Error: non-child rate was not previously submitted')
return undefined
}
rateRevs.push(lastRateSubmission)
}
}
return rateRevs
} else {
const lastContractSubmission = getLastContractSubmission(contract)
if (!lastContractSubmission) {
console.error('Programming Error: no contract submission for a contract were not editing')
return undefined
}
return lastContractSubmission.rateRevisions
}
}

// returns draft form data for unlocked and draft, and last package submission data for submitted or resubmitted
const getLatestContractFormData = (contract: Contract): ContractFormData | undefined =>{
return contract.draftRevision?.formData ||
// only state users get to see draft data.
const getVisibleLatestContractFormData = (contract: Contract, isStateUser: boolean): ContractFormData | undefined =>{
if (isStateUser) {
return contract.draftRevision?.formData ||
getLastContractSubmission(contract)?.contractRevision.formData
}
return getLastContractSubmission(contract)?.contractRevision.formData
}

const getLastContractSubmission = (contract: Contract): ContractPackageSubmission | undefined => {
Expand All @@ -19,4 +62,4 @@ const getDraftRates = (contract: Contract): Rate[] | undefined => {
return (contract.draftRates && contract.draftRates[0]) ? contract.draftRates : undefined
}

export {getDraftRates, getLastContractSubmission, getLatestContractFormData}
export {getDraftRates, getLastContractSubmission, getVisibleLatestContractFormData, getVisibleLatestRateRevisions}
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ export const LinkRateSelect = ({
) => {
if (action === 'select-option') {
const linkedRateID = newValue.value
// const linkedRateName = newValue.label
const linkedRate = rates.find((rate) => rate.id === linkedRateID)
const linkedRateForm: FormikRateForm = convertGQLRateToRateForm(
getKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ describe('RateDetailsv2', () => {
})

it('display rest of the form when linked rates question is answered', async () => {
renderWithProviders(
const { user } = renderWithProviders(
<Routes>
<Route
path={RoutesRecord.SUBMISSIONS_RATE_DETAILS}
Expand All @@ -315,11 +315,8 @@ describe('RateDetailsv2', () => {
contract: {
...mockContractWithLinkedRateDraft(),
id: 'test-abc-123',
},
}),
updateDraftContractRatesMockSuccess({
contract: {
id: 'test-abc-123',
// clean draft rates for this test.
draftRates: []
},
}),
],
Expand All @@ -340,16 +337,17 @@ describe('RateDetailsv2', () => {
'No, this rate certification was not included with any other submissions'
)
)

const input = screen.getByLabelText(
'Upload one rate certification document'
)
await expect(input).toBeInTheDocument()
expect(input).toBeInTheDocument()
const submitButton = screen.getByRole('button', {
name: 'Continue',
})

// trigger validations
await submitButton.click()
await user.click(submitButton)
await waitFor(() => {
expect(
screen.getByText('Rate certification 1')
Expand Down Expand Up @@ -458,7 +456,7 @@ describe('RateDetailsv2', () => {
})
})
it('cannot continue with partially filled out second rate', async () => {
renderWithProviders(
const { user } = renderWithProviders(
<Routes>
<Route
path={RoutesRecord.SUBMISSIONS_RATE_DETAILS}
Expand Down Expand Up @@ -495,15 +493,14 @@ describe('RateDetailsv2', () => {
await screen.findByText('Rate Details')
const rateCertsOnLoad = rateCertifications(screen)
expect(rateCertsOnLoad).toHaveLength(1)
await fillOutIndexRate(screen, 0)

await clickAddNewRate(screen)
const submitButton = screen.getByRole('button', {
name: 'Continue',
})

// trigger validations
await submitButton.click()
await user.click(submitButton)
await waitFor(() => {
expect(
screen.getByText('Rate certification 1')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ const RateDetailsV2 = ({
const [submitRate, { error: submitRateError }] = useSubmitRateMutation()

// Set up data for form. Either based on contract API (for multi rate) or rates API (for edit and submit of standalone rate)
const ratesFromContract =
fetchContractData?.fetchContract.contract.draftRates
const contract = fetchContractData?.fetchContract.contract
const ratesFromContract = contract?.draftRates
const initialRequestLoading = fetchContractLoading || fetchRateLoading
const initialRequestError = fetchContractError || fetchRateError
const submitRequestError = updateContractError || submitRateError
Expand All @@ -188,7 +188,7 @@ const RateDetailsV2 = ({
rateForms:
initialRates.length > 0
? initialRates.map((rate) =>
convertGQLRateToRateForm(getKey, rate)
convertGQLRateToRateForm(getKey, rate, contract?.id)
)
: [convertGQLRateToRateForm(getKey)],
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ const convertRateFormToGQLRateFormData = (
// Convert from GQL Rate to FormikRateForm object used in the form
// if rate is not passed in, return an empty RateForm // we need to pass in the s3 handler because 3 urls generated client-side
// useLatestSubmission means to pull the latest submitted info rather than the draft info
const convertGQLRateToRateForm = (getKey: S3ClientT['getKey'], rate?: Rate): FormikRateForm => {
const handleAsLinkedRate = rate?.status && rate.status !== 'DRAFT' && rate.status !== 'UNLOCKED' // TODO: Make this a more sophisticated check for child-rates
const convertGQLRateToRateForm = (getKey: S3ClientT['getKey'], rate?: Rate, parentContractID?: string): FormikRateForm => {
const handleAsLinkedRate = rate && rate.parentContractID !== parentContractID // TODO: Make this a more sophisticated check for child-rates
const rateRev = handleAsLinkedRate ? rate?.revisions[0] : rate?.draftRevision
const rateForm = rateRev?.formData
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ describe('ContractDetailsSummarySection', () => {
<ContractDetailsSummarySection
contract={mockContractPackageDraft()}
submissionName="MN-PMAP-0001"
editNavigateTo='/contract-details'
/>,
{
apolloProvider: defaultApolloMocks,
Expand Down Expand Up @@ -268,6 +269,7 @@ describe('ContractDetailsSummarySection', () => {
<ContractDetailsSummarySection
contract={contract}
submissionName="MN-PMAP-0001"
editNavigateTo='/contract-details'
/>,
{
apolloProvider: defaultApolloMocks,
Expand Down Expand Up @@ -365,6 +367,7 @@ describe('ContractDetailsSummarySection', () => {
<ContractDetailsSummarySection
contract={contract}
submissionName="MN-PMAP-0001"
editNavigateTo='/contract-details'
/>,
{
apolloProvider: defaultApolloMocks,
Expand Down Expand Up @@ -408,6 +411,7 @@ describe('ContractDetailsSummarySection', () => {
<ContractDetailsSummarySection
contract={contract}
submissionName="MN-PMAP-0001"
editNavigateTo='/contract-details'
/>,
{
apolloProvider: defaultApolloMocks,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import { SectionCard } from '../../../../../components/SectionCard'
import { Contract } from '../../../../../gen/gqlClient'
import {
getLastContractSubmission,
getLatestContractFormData,
getVisibleLatestContractFormData,
} from '../../../../../gqlHelpers/contractsAndRates'

export type ContractDetailsSummarySectionV2Props = {
Expand Down Expand Up @@ -84,8 +84,9 @@ export const ContractDetailsSummarySectionV2 = ({
string | undefined | Error
>(undefined)
const ldClient = useLDClient()
const isEditing = !isSubmitted(contract) && editNavigateTo !== undefined

const contractFormData = getLatestContractFormData(contract)
const contractFormData = getVisibleLatestContractFormData(contract, isEditing)
const contract438Attestation = ldClient?.variation(
featureFlags.CONTRACT_438_ATTESTATION.flag,
featureFlags.CONTRACT_438_ATTESTATION.defaultValue
Expand All @@ -96,7 +97,6 @@ export const ContractDetailsSummarySectionV2 = ({
booleanAsYesNoFormValue(contractFormData.statutoryRegulatoryAttestation)

const contractSupportingDocuments = contractFormData?.supportingDocuments
const isEditing = !isSubmitted(contract) && editNavigateTo !== undefined
const applicableFederalAuthorities = isCHIPOnly(contract)
? contractFormData?.federalAuthorities.filter((authority) =>
federalAuthorityKeysForCHIP.includes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('RateDetailsSummarySection', () => {
state: mockMNState(),
stateCode: 'MN',
stateNumber: 5,
parentContractID: 'fake-id',
parentContractID: 'test-abc-123',
revisions: [],
draftRevision: {
id: '1234',
Expand Down Expand Up @@ -74,7 +74,7 @@ describe('RateDetailsSummarySection', () => {
state: mockMNState(),
stateCode: 'MN',
stateNumber: 5,
parentContractID: 'fake-id',
parentContractID: 'test-abc-123',
revisions: [],
draftRevision: {
id: '1234',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
RateFormData,
HealthPlanPackageStatus,
} from '../../../../../gen/gqlClient'
import { getLastContractSubmission } from '../../../../../gqlHelpers/contractsAndRates'
import { getLastContractSubmission, getVisibleLatestRateRevisions } from '../../../../../gqlHelpers/contractsAndRates'

export type RateDetailsSummarySectionV2Props = {
contract: Contract
Expand Down Expand Up @@ -74,12 +74,10 @@ export const RateDetailsSummarySectionV2 = ({
const isSubmitted = contract.status === 'SUBMITTED'
const isEditing = !isSubmitted && editNavigateTo !== undefined
const isPreviousSubmission = usePreviousSubmission()
const contractFormData =
contract.draftRevision?.formData ||
const contractFormData = isEditing ?
contract.draftRevision?.formData :
getLastContractSubmission(contract)?.contractRevision.formData
const rates = isEditing
? contract.draftRates
: getLastContractSubmission(contract)?.rateRevisions
const rates = getVisibleLatestRateRevisions(contract, isEditing)
const lastSubmittedDate =
getLastContractSubmission(contract)?.submitInfo.updatedAt

Expand Down Expand Up @@ -224,6 +222,7 @@ export const RateDetailsSummarySectionV2 = ({
isSubmitted,
isPreviousSubmission,
])

return (
<SectionCard id="rateDetails" className={styles.summarySection}>
<SectionHeader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { ReviewSubmitV2 } from './ReviewSubmitV2'
import {
fetchCurrentUserMock,
fetchContractMockSuccess,
mockValidStateUser,
} from '../../../../../testHelpers/apolloMocks'
import { Route, Routes } from 'react-router-dom'
import { RoutesRecord } from '../../../../../constants'
import { mockContractPackageUnlocked } from '../../../../../testHelpers/apolloMocks/contractPackageDataMock'

describe('ReviewSubmit', () => {
it('renders without errors', async () => {
Expand Down Expand Up @@ -175,7 +177,7 @@ describe('ReviewSubmit', () => {
})

it('displays back, save as draft, and submit buttons', async () => {
renderWithProviders(
const { user } = renderWithProviders(
<Routes>
<Route
path={RoutesRecord.SUBMISSIONS_REVIEW_SUBMIT}
Expand Down Expand Up @@ -210,6 +212,42 @@ describe('ReviewSubmit', () => {

expect(screen.getByTestId('form-submit')).toBeDefined()
expect(screen.getAllByText('Submit')).toHaveLength(2)
await screen.getAllByText('Submit')[0].click()
await user.click(screen.getAllByText('Submit')[0])
})

it('pulls the right version of UNLOCKED data for state users', async () => {
renderWithProviders(
<Routes>
<Route
path={RoutesRecord.SUBMISSIONS_REVIEW_SUBMIT}
element={<ReviewSubmitV2 />}
/>
</Routes>,
{
apolloProvider: {
mocks: [
fetchCurrentUserMock({
statusCode: 200,
user: mockValidStateUser(),
}),
fetchContractMockSuccess({
contract: mockContractPackageUnlocked(),
}),
],
},
routerProvider: {
route: '/submissions/test-abc-123/edit/review-and-submit',
},
featureFlags: {
'link-rates': true,
},
}
)

const description = await screen.findByLabelText('Submission description')
expect(description).toHaveTextContent('An updated submission')
const ratingPeriod = await screen.findByLabelText('Rating period of original rate certification')
expect(ratingPeriod).toHaveTextContent('02/02/2020 to 02/02/2021')

})
})
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
STATE_SUBMISSION_FORM_ROUTES,
} from '../../../../../constants'
import { UnlockSubmitModalV2 } from '../../../../../components/Modal/V2/UnlockSubmitModalV2'
import { getLatestContractFormData } from '../../../../../gqlHelpers/contractsAndRates'
import { getVisibleLatestContractFormData } from '../../../../../gqlHelpers/contractsAndRates'
import { useAuth } from '../../../../../contexts/AuthContext'
import { RateDetailsSummarySectionV2 } from './RateDetailsSummarySectionV2'
import { ContactsSummarySection } from './ContactsSummarySectionV2'
Expand Down Expand Up @@ -75,7 +75,8 @@ export const ReviewSubmitV2 = (): React.ReactElement => {
}
}

const contractFormData = getLatestContractFormData(contract)
const isStateUser = loggedInUser?.role === 'STATE_USER'
const contractFormData = getVisibleLatestContractFormData(contract, isStateUser)
if (!contractFormData) return <GenericErrorPage />

const isContractActionAndRateCertification =
Expand Down Expand Up @@ -113,6 +114,7 @@ export const ReviewSubmitV2 = (): React.ReactElement => {
submissionName={submissionName}
editNavigateTo="../type"
statePrograms={statePrograms}
isStateUser={isStateUser}
/>
<ContractDetailsSummarySectionV2
contract={contract}
Expand Down
Loading

0 comments on commit a4be8f7

Please sign in to comment.