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-3772 MCR-3771 Edit and submit standalone rate #2238

Merged
merged 28 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a4e2445
Start to add RateDetailsV2
haworku Jan 29, 2024
0b73291
wip
haworku Jan 30, 2024
8b74cd0
wip
haworku Jan 30, 2024
492de9f
add flag to side nav
haworku Jan 30, 2024
a1120f8
wip
haworku Jan 30, 2024
d8388bf
Add nx to gitignore
haworku Jan 31, 2024
d661aa9
Fix up types
haworku Jan 31, 2024
0a01796
Workaround actuary contacts types
haworku Feb 1, 2024
9423fc2
Fix React console error about bad setState call in RateSummary
haworku Feb 1, 2024
9ff2174
Wip to show what I'm doing
haworku Feb 1, 2024
d711b76
Page finally loading - can see a few broken fields to address next
haworku Feb 2, 2024
5c021ff
cleanup
haworku Feb 2, 2024
bb20c3d
Set up page action buttons properly, updateRate not available yet
haworku Feb 6, 2024
e8f23fd
cleanup
haworku Feb 6, 2024
3c3f417
cleanup
haworku Feb 6, 2024
860ea5a
Pass rateID not revision id to submit. Fix cacheing
haworku Feb 6, 2024
6dad58b
Move file nesting to combine all V2 in one folder
haworku Feb 6, 2024
9a6e986
Add basic test and todos for all the untested paths
haworku Feb 6, 2024
93997e6
Merge remote-tracking branch 'origin/main' into MCR-3777-single-rate
haworku Feb 6, 2024
6b20930
Cleanup app-web tests
haworku Feb 6, 2024
fa8f498
app-api tests passing
haworku Feb 6, 2024
a1b3769
Merge remote-tracking branch 'origin/main' into MCR-3777-single-rate
haworku Feb 6, 2024
13c4d03
cypress re-run
haworku Feb 6, 2024
0dfda94
Fix test id and help cypress out
haworku Feb 6, 2024
cc64ae6
Address @macrael code review
haworku Feb 9, 2024
7a8a24d
Think I can remove null-coalescing work now as well
haworku Feb 9, 2024
24c9f5a
Start generating rate names for standalone rate submits
haworku Feb 12, 2024
e4d0c01
Fixup app-api tests, don't mess with id-only submit log path
haworku Feb 12, 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ tsconfig.tsbuildinfo
.serverless
.eslintcache
/.env
.nx
tests_output
*.log
coverage/
Expand Down
8 changes: 6 additions & 2 deletions services/app-api/src/resolvers/rate/submitRate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export function submitRate(
const submittedRate = await store.submitRate({
rateID,
submittedByUserID: user.id,
submitReason,
submitReason: submitReason ?? 'Initial submission',
formData: formData
? {
rateType: (formData.rateType ??
Expand Down Expand Up @@ -140,7 +140,11 @@ export function submitRate(
actuaryCommunicationPreference:
formData.actuaryCommunicationPreference ?? undefined,
packagesWithSharedRateCerts:
formData.packagesWithSharedRateCerts ?? [],
formData.packagesWithSharedRateCerts.map((pkg) => ({
packageName: pkg.packageName ?? undefined,
packageId: pkg.packageId ?? undefined,
packageStatus: pkg.packageStatus ?? undefined,
})),
}
: undefined,
})
Expand Down
2 changes: 2 additions & 0 deletions services/app-api/src/testHelpers/gqlHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ const createAndUpdateTestHealthPlanPackage = async (
rateProgramIDs: [ratePrograms.reverse()[0].id],
actuaryContacts: [
{
id: '123-abc',
name: 'test name',
titleRole: 'test title',
email: 'email@example.com',
Expand All @@ -275,6 +276,7 @@ const createAndUpdateTestHealthPlanPackage = async (
]
draft.addtlActuaryContacts = [
{
id: '123-addtl-abv',
name: 'test name',
titleRole: 'test title',
email: 'email@example.com',
Expand Down
2 changes: 2 additions & 0 deletions services/app-graphql/src/mutations/submitRate.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ mutation submitRate($input: SubmitRateInput!) {
rateProgramIDs,
rateCertificationName,
certifyingActuaryContacts {
id
name
titleRole
email
actuarialFirm
actuarialFirmOther
},
addtlActuaryContacts {
id
name
titleRole
email
Expand Down
2 changes: 2 additions & 0 deletions services/app-graphql/src/mutations/unlockRate.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ fragment rateRevisionFragment on RateRevision {
rateProgramIDs,
rateCertificationName,
certifyingActuaryContacts {
id
name
titleRole
email
actuarialFirm
actuarialFirmOther
},
addtlActuaryContacts {
id
name
titleRole
email
Expand Down
2 changes: 2 additions & 0 deletions services/app-graphql/src/queries/fetchRate.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ fragment rateRevisionFragment on RateRevision {
rateProgramIDs,
rateCertificationName,
certifyingActuaryContacts {
id
name
titleRole
email
actuarialFirm
actuarialFirmOther
},
addtlActuaryContacts {
id
name
titleRole
email
Expand Down
12 changes: 7 additions & 5 deletions services/app-graphql/src/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,7 @@ enum ActuarialFirm {

"Contact information for the certifying or additional state actuary"
type ActuaryContact {
id: ID
name: String
titleRole: String
email: String
Expand All @@ -1022,6 +1023,7 @@ type ActuaryContact {

"Contact information input for the certifying or additional state actuary"
input ActuaryContactInput {
id: ID
name: String
titleRole: String
email: String
Expand All @@ -1037,13 +1039,13 @@ It's used as a part of RateFormData
type PackageWithSameRate {
packageName: String!
packageId: String!
packageStatus: String
packageStatus: HealthPlanPackageStatus
}

input PackageWithSameRateInput {
packageName: String!
packageId: String!
packageStatus: HealthPlanPackageStatus!
packageStatus: HealthPlanPackageStatus
}

"""
Expand Down Expand Up @@ -1327,7 +1329,7 @@ input RateFormDataInput {
An array of additional ActuaryContacts
Each element includes the the name, title/role and email
"""
addtlActuaryContacts: [ActuaryContactInput!]!
addtlActuaryContacts: [ActuaryContactInput!]
"""
Is either OACT_TO_ACTUARY or OACT_TO_STATE
It specifies whether the state wants CMS to reach out to their actuaries
Expand All @@ -1345,8 +1347,8 @@ input RateFormDataInput {

input SubmitRateInput {
rateID: ID!
"User given submission description"
submitReason: String!
"User given submission description - defaults to Initial submission if left blank"
submitReason: String
"Rate related form data to be updated with submission"
formData: RateFormDataInput
}
1 change: 1 addition & 0 deletions services/app-proto/src/health_plan_form_data.proto
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ message Contact {
optional string name = 1;
optional string title_role = 2;
optional string email = 3;
optional string id = 4;
}

// ContractInfo subtypes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ const stateContactSchema = z.object({
})

const actuaryContactSchema = z.object({
id: z.string().optional(),
name: z.string().optional(),
titleRole: z.string().optional(),
email: z.string().optional(),
Expand Down
109 changes: 84 additions & 25 deletions services/app-web/src/formHelpers/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ActuaryContact,
} from '../common-code/healthPlanFormDataType'
import { FileItemT } from '../components'
import { GenericDocument, ActuaryContact as GQLActuaryContact } from '../gen/gqlClient'
import { S3ClientT } from '../s3'
import { v4 as uuidv4 } from 'uuid'

Expand All @@ -21,18 +22,6 @@ const formatForApi = (attribute: string): string | null => {
return attribute
}

const formatYesNoForProto = (
attribute: string | undefined
): boolean | undefined => {
if (attribute === 'YES') {
return true
}
if (attribute === 'NO') {
return false
}
return undefined
}

// Convert api data for use in form. Form fields must be a string.
// Empty values as an empty string, dates in date picker as YYYY-MM-DD, boolean as "Yes" "No" values
const formatForForm = (
Expand All @@ -49,9 +38,19 @@ const formatForForm = (
}
}

const formatActuaryContactsForForm = (actuaryContacts?: ActuaryContact[]) => {
return actuaryContacts && actuaryContacts.length > 0
? actuaryContacts
// This function can be cleaned up when we move off domain types and only use graphql
const formatActuaryContactsForForm = (actuaryContacts?: ActuaryContact[] | GQLActuaryContact[]) : ActuaryContact[] => {
return actuaryContacts && actuaryContacts.length > 0
? actuaryContacts.map( (contact) => {
const {name, titleRole,email,actuarialFirm, actuarialFirmOther} = contact
return {
name: name ?? '',
titleRole: titleRole ?? '',
email: email ?? '',
actuarialFirmOther: actuarialFirmOther ?? undefined,
actuarialFirm: actuarialFirm ?? undefined,
}
})
: [
{
name: '',
Expand All @@ -63,16 +62,15 @@ const formatActuaryContactsForForm = (actuaryContacts?: ActuaryContact[]) => {
]
}

const formatFormDateForDomain = (attribute: string): Date | undefined => {
if (attribute === '') {
return undefined
}
return dayjs.utc(attribute).toDate()


const formatFormDateForGQL = (attribute: string): string | undefined => {
return (attribute === '') ? undefined : attribute
}

const formatDocumentsForDomain = (
const formatDocumentsForGQL = (
fileItems: FileItemT[]
): SubmissionDocument[] => {
): GenericDocument[] => {
return fileItems.reduce((cleanedFileItems, fileItem) => {
if (fileItem.status === 'UPLOAD_ERROR') {
console.info(
Expand Down Expand Up @@ -102,14 +100,14 @@ const formatDocumentsForDomain = (
})
}
return cleanedFileItems
}, [] as SubmissionDocument[])
}, [] as GenericDocument[])
}

const formatDocumentsForForm = ({
documents,
getKey,
}: {
documents?: SubmissionDocument[]
documents?: SubmissionDocument[] | GenericDocument[]
getKey: S3ClientT['getKey'] // S3 function to call when formatting to double check we have valid documents, probably the backend should be doing this to reduce client async errors handling with bad data
}): FileItemT[] => {
if (!documents) return []
Expand All @@ -134,13 +132,72 @@ const formatDocumentsForForm = ({
name: doc.name,
key: key,
s3URL: doc.s3URL,
sha256: doc.sha256,
sha256: doc.sha256 ?? undefined,
haworku marked this conversation as resolved.
Show resolved Hide resolved
status: 'UPLOAD_COMPLETE',
}
}) || []
)
}

// DEPRECATED
// Domain helpers are for HPP code. We are migrating off this in favor of directly using GQL utilities

const formatFormDateForDomain = (attribute: string): Date | undefined => {
if (attribute === '') {
return undefined
}
return dayjs.utc(attribute).toDate()
}



const formatDocumentsForDomain = (
fileItems: FileItemT[]
): SubmissionDocument[] => {
return fileItems.reduce((cleanedFileItems, fileItem) => {
if (fileItem.status === 'UPLOAD_ERROR') {
console.info(
'Attempting to save files that failed upload, discarding invalid files'
)
} else if (fileItem.status === 'SCANNING_ERROR') {
console.info(
'Attempting to save files that failed scanning, discarding invalid files'
)
} else if (fileItem.status === 'DUPLICATE_NAME_ERROR') {
console.info(
'Attempting to save files that are duplicate names, discarding duplicate'
)
} else if (!fileItem.s3URL) {
console.info(
'Attempting to save a seemingly valid file item is not yet uploaded to S3, this should not happen on form submit. Discarding file.'
)
} else if (!fileItem.sha256) {
console.info(
'Attempting to save a seemingly valid file item does not have a sha256 yet. this should not happen on form submit. Discarding file.'
)
} else {
cleanedFileItems.push({
name: fileItem.name,
s3URL: fileItem.s3URL,
sha256: fileItem.sha256,
})
}
return cleanedFileItems
}, [] as SubmissionDocument[])
}

const formatYesNoForProto = (
attribute: string | undefined
): boolean | undefined => {
if (attribute === 'YES') {
return true
}
if (attribute === 'NO') {
return false
}
return undefined
}

export {
formatForApi,
formatForForm,
Expand All @@ -150,4 +207,6 @@ export {
formatDocumentsForDomain,
formatDocumentsForForm,
formatActuaryContactsForForm,
formatDocumentsForGQL,
formatFormDateForGQL
}
22 changes: 11 additions & 11 deletions services/app-web/src/pages/App/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
UploadQuestions,
} from '../QuestionResponse'
import { GraphQLExplorer } from '../GraphQLExplorer/GraphQLExplorer'
import { RateSummary } from '../SubmissionSummary/RateSummary'
import { RateSummary } from '../RateSummary'
import { RateEdit } from '../RateEdit/RateEdit'
import { APIAccess } from '../APIAccess/APIAccess'

Expand Down Expand Up @@ -109,16 +109,16 @@ const StateUserRoutes = ({
element={<NewStateSubmissionForm />}
/>
{showRatePages && (
<Route
path={RoutesRecord.RATE_EDIT}
element={<RateEdit />}
/>
)}
{showRatePages && (
<Route
path={RoutesRecord.RATES_SUMMARY}
element={<RateSummary />}
/>
<>
<Route
path={RoutesRecord.RATES_SUMMARY}
element={<RateSummary />}
/>
<Route
path={RoutesRecord.RATE_EDIT}
element={<RateEdit />}
/>
</>
)}
<Route element={<SubmissionSideNav />}>
{showQuestionResponse && (
Expand Down
5 changes: 4 additions & 1 deletion services/app-web/src/pages/RateEdit/RateEdit.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { screen, waitFor } from '@testing-library/react'

import { renderWithProviders } from '../../testHelpers'
import { RateEdit } from './RateEdit'
import {
Expand Down Expand Up @@ -44,7 +45,9 @@ describe('RateEdit', () => {
})

await waitFor(() => {
expect(screen.queryByTestId('rate-edit')).toBeInTheDocument()
expect(
screen.queryByTestId('single-rate-edit')
).toBeInTheDocument()
})
})
})
Expand Down
Loading
Loading