From 18b53ba6bb6f5329b094cf653abf0987094f370f Mon Sep 17 00:00:00 2001 From: Mazdak Atighi Date: Thu, 10 Aug 2023 23:03:04 -0500 Subject: [PATCH 01/78] populating --- .github/workflows/deploy-app-to-env.yml | 11 +- .github/workflows/deploy.yml | 10 +- .github/workflows/promote.yml | 2 +- .github/workflows/sechub-jira-sync.yml | 2 +- .images/aws-console-lambda-config.png | Bin 0 -> 122320 bytes .images/verbose-logs-example.png | Bin 0 -> 50843 bytes .vscode/launch.json | 15 +- README.md | 2 +- dev_tool/src/serverless.ts | 2 +- docs/Architecture.md | 3 + docs/README.md | 13 + .../contract-rate-refactor-relationships.md | 174 + docs/technical-design/database-diagram.md | 81 + docs/technical-design/howto-migrations.md | 49 + .../howto-update-state-programs.md | 7 +- .../launch-darkly-feature-flag-lifecycles.md | 18 +- .../launch-darkly-testing-approach.md | 4 +- ...> technical-design-discussion-template.md} | 0 .../technical-design-howto-template.md | 19 + package.json | 2 +- scripts/add_cypress_test_users.ts | 10 +- scripts/destroy_stage.ts | 84 +- services/app-api/jest.config.ts | 2 +- services/app-api/package.json | 14 +- .../migration.sql | 133 + .../migration.sql | 4 + .../migration.sql | 18 + .../migration.sql | 7 + .../migration.sql | 262 + .../migration.sql | 30 + .../migration.sql | 10 + services/app-api/prisma/schema.prisma | 298 +- .../app-api/scripts/invoke-migrate-lambda.sh | 5 +- services/app-api/serverless.yml | 22 + services/app-api/src/authn/authn.ts | 6 +- .../app-api/src/authn/cognitoAuthn.test.ts | 21 +- services/app-api/src/authn/cognitoAuthn.ts | 22 +- services/app-api/src/authn/index.ts | 2 +- services/app-api/src/authn/localAuthn.ts | 8 +- .../domain-models/HealthPlanPackageType.d.ts | 4 +- .../src/domain-models/QuestionResponseType.ts | 2 +- .../src/domain-models/QuestionsType.ts | 6 +- .../app-api/src/domain-models/UserType.d.ts | 22 +- .../contractAndRates/contractTypes.ts | 100 + .../domain-models/contractAndRates/index.ts | 22 + .../contractAndRates/rateTypes.ts | 71 + .../contractAndRates/updateInfoType.ts | 15 + .../app-api/src/domain-models/division.ts | 2 +- .../domain-models/healthPlanPackage.test.ts | 2 +- .../src/domain-models/healthPlanPackage.ts | 148 +- services/app-api/src/domain-models/index.ts | 1 + services/app-api/src/domain-models/user.ts | 25 +- services/app-api/src/emailer/awsSES.ts | 7 +- services/app-api/src/emailer/emailer.ts | 4 +- .../newPackageCMSEmail.test.ts.snap | 2 +- .../newPackageStateEmail.test.ts.snap | 2 +- .../resubmitPackageCMSEmail.test.ts.snap | 4 +- .../unlockPackageStateEmail.test.ts.snap | 4 +- .../emailer/emails/newPackageCMSEmail.test.ts | 20 +- .../src/emailer/emails/newPackageCMSEmail.ts | 10 +- .../emails/newPackageStateEmail.test.ts | 12 +- .../emailer/emails/newPackageStateEmail.ts | 10 +- .../emails/resubmitPackageCMSEmail.test.ts | 2 +- .../emailer/emails/resubmitPackageCMSEmail.ts | 8 +- .../emails/resubmitPackageStateEmail.test.ts | 2 +- .../emails/resubmitPackageStateEmail.ts | 8 +- .../emails/unlockPackageCMSEmail.test.ts | 10 +- .../emailer/emails/unlockPackageCMSEmail.ts | 8 +- .../emails/unlockPackageStateEmail.test.ts | 2 +- .../emailer/emails/unlockPackageStateEmail.ts | 8 +- .../src/emailer/templateHelpers.test.ts | 4 +- .../app-api/src/emailer/templateHelpers.ts | 6 +- services/app-api/src/handlers/add_sha.test.ts | 10 +- services/app-api/src/handlers/add_sha.ts | 85 +- services/app-api/src/handlers/apollo_gql.ts | 26 +- .../app-api/src/handlers/bulk_download.ts | 4 +- services/app-api/src/handlers/cleanup.ts | 6 +- .../app-api/src/handlers/configuration.ts | 2 +- services/app-api/src/handlers/email_submit.ts | 2 +- services/app-api/src/handlers/global.d.ts | 2 +- services/app-api/src/handlers/health_check.ts | 2 +- .../handlers/migrate_rate_documents.test.ts | 430 ++ .../src/handlers/migrate_rate_documents.ts | 215 + services/app-api/src/handlers/otel_proxy.ts | 2 +- .../app-api/src/handlers/postgres_migrate.ts | 2 +- services/app-api/src/handlers/proto_to_db.ts | 204 + services/app-api/src/handlers/reports.ts | 46 +- .../app-api/src/launchDarkly/launchDarkly.ts | 23 +- services/app-api/src/otel/otel_handler.ts | 3 +- .../emailParameterStore.ts | 2 +- .../emailParameterStore/helpers.ts | 2 +- .../getStateAnalystsSettings.ts | 6 +- .../findContractWithHistory.test.ts | 659 ++ .../findContractWithHistory.ts | 67 + .../findDraftContract.test.ts | 271 + .../contractAndRates/findDraftContract.ts | 32 + .../contractAndRates/findDraftRate.test.ts | 28 + .../contractAndRates/findDraftRate.ts | 81 + .../findRateWithHistory.test.ts | 252 + .../contractAndRates/findRateWithHistory.ts | 165 + .../src/postgres/contractAndRates/index.ts | 8 + .../contractAndRates/insertContract.test.ts | 88 + .../contractAndRates/insertContract.ts | 70 + .../postgres/contractAndRates/insertRate.ts | 158 + .../parseContractAndRates.test.ts | 212 + .../parseContractWithHistory.ts | 159 + .../contractAndRates/parseDraftContract.ts | 53 + .../prismaDraftContractHelpers.ts | 103 + .../prismaSharedContractRateHelpers.ts | 264 + .../prismaSubmittedContractHelpers.ts | 15 + .../prismaToDomainModel.test.ts | 157 + .../proto_to_db_ContractId.ts | 50 + .../proto_to_db_ContractRevisions.ts | 111 + .../contractAndRates/proto_to_db_Documents.ts | 178 + .../contractAndRates/proto_to_db_JoinTable.ts | 55 + .../proto_to_db_RateRevisions.ts | 134 + .../proto_to_db_UpdateInfoTable.ts | 38 + .../contractAndRates/submitContract.test.ts | 233 + .../contractAndRates/submitContract.ts | 160 + .../postgres/contractAndRates/submitRate.ts | 152 + .../contractAndRates/unlockContract.test.ts | 425 ++ .../contractAndRates/unlockContract.ts | 101 + .../postgres/contractAndRates/unlockRate.ts | 99 + .../contractAndRates/updateDraftContract.ts | 77 + .../contractAndRates/updateDraftRate.ts | 56 + .../findAllHealthPlanPackagesByState.ts | 13 +- .../findAllHealthPlanPackagesBySubmittedAt.ts | 14 +- .../healthPlanPackage/findAllRevisions.ts | 9 +- .../findHealthPlanPackage.ts | 17 +- .../healthPlanPackageHelpers.ts | 9 +- .../src/postgres/healthPlanPackage/index.ts | 6 +- .../insertHealthPlanPackage.test.ts | 10 +- .../insertHealthPlanPackage.ts | 17 +- .../insertHealthPlanRevision.ts | 9 +- .../updateHealthPlanRevision.ts | 19 +- services/app-api/src/postgres/index.ts | 10 +- .../app-api/src/postgres/postgresStore.ts | 51 +- services/app-api/src/postgres/prismaTypes.ts | 9 + .../findAllQuestionsByHealthPlanPackage.ts | 7 +- .../questionResponse/insertQuestion.ts | 7 +- .../insertQuestionResponse.ts | 7 +- .../postgres/state/findAllSupportedStates.ts | 7 +- .../src/postgres/state/findPrograms.ts | 2 +- .../src/postgres/state/findStatePrograms.ts | 2 +- .../app-api/src/postgres/storeError.test.ts | 2 +- services/app-api/src/postgres/storeError.ts | 23 +- .../app-api/src/postgres/user/findAllUsers.ts | 7 +- .../app-api/src/postgres/user/findUser.ts | 7 +- services/app-api/src/postgres/user/index.ts | 3 +- .../src/postgres/user/insertManyUsers.ts | 10 +- .../app-api/src/postgres/user/insertUser.ts | 8 +- .../src/postgres/user/prismaDomainUser.ts | 15 +- .../postgres/user/updateCmsUserProperties.ts | 14 +- .../app-api/src/resolvers/attributeHelper.ts | 2 +- .../src/resolvers/configureResolvers.ts | 21 +- .../src/resolvers/email/fetchEmailSettings.ts | 17 +- .../createHealthPlanPackage.test.ts | 179 +- .../createHealthPlanPackage.ts | 88 +- .../fetchHealthPlanPackage.test.ts | 100 +- .../fetchHealthPlanPackage.ts | 154 +- .../healthPlanPackageResolver.ts | 5 +- .../indexHealthPlanPackages.test.ts | 5 +- .../indexHealthPlanPackages.ts | 22 +- .../submitHealthPlanPackage.test.ts | 9 +- .../submitHealthPlanPackage.ts | 43 +- .../unlockHealthPlanPackage.test.ts | 4 +- .../unlockHealthPlanPackage.ts | 14 +- .../updateHealthPlanFormData.ts | 19 +- .../questionResponse/createQuestion.ts | 5 +- .../createQuestionResponse.test.ts | 2 +- .../createQuestionResponse.ts | 5 +- .../questionResponse/indexQuestions.ts | 5 +- .../resolvers/user/fetchCurrentUser.test.ts | 2 +- .../src/resolvers/user/fetchCurrentUser.ts | 2 +- .../src/resolvers/user/indexUsers.test.ts | 9 +- .../app-api/src/resolvers/user/indexUsers.ts | 11 +- .../src/resolvers/user/updateCMSUser.test.ts | 12 +- .../src/resolvers/user/updateCMSUser.ts | 16 +- .../src/resolvers/user/userResolver.ts | 2 +- services/app-api/src/secrets/index.ts | 3 +- services/app-api/src/secrets/secrets.ts | 5 +- .../app-api/src/testHelpers/awsSESHelpers.ts | 4 +- .../contractAndRates/contractHelpers.ts | 184 + .../app-api/src/testHelpers/emailerHelpers.ts | 8 +- .../app-api/src/testHelpers/errorHelpers.ts | 16 + .../app-api/src/testHelpers/gqlAssertions.ts | 4 +- .../app-api/src/testHelpers/gqlHelpers.ts | 25 +- .../testHelpers/healthPlanPackageHelpers.ts | 4 +- services/app-api/src/testHelpers/index.ts | 10 + .../src/testHelpers/launchDarklyHelpers.ts | 6 +- .../src/testHelpers/parameterStoreHelpers.ts | 2 +- .../app-api/src/testHelpers/storeHelpers.ts | 20 +- .../app-api/src/testHelpers/userHelpers.ts | 5 +- services/app-api/tsconfig.json | 5 +- .../src/queries/fetchCurrentUser.graphql | 7 + services/app-graphql/src/schema.graphql | 16 +- services/app-web/package.json | 4 +- services/app-web/src/assets/images/appa.png | Bin 0 -> 69312 bytes .../src/common-code/featureFlags/flags.ts | 19 +- .../healthPlanFormData.ts | 14 +- .../healthPlanFormData.ts | 5 +- ...ithALittleBitOfEverything-2023-07-17.proto | Bin 0 -> 941 bytes .../healthPlanFormDataProto/zodSchemas.ts | 17 +- .../GenericApiErrorBanner.tsx | 16 +- .../UserAccountWarningBanner.stories.tsx | 18 +- .../UserAccountWarningBanner.tsx | 2 +- .../src/components/ErrorAlert/ErrorAlert.tsx | 7 +- .../ErrorAlert/ErrorAlertFailedRequest.tsx | 4 +- .../FileUpload/FileUpload.stories.tsx | 12 +- .../src/components/FileUpload/FileUpload.tsx | 11 +- .../src/components/FileUpload/helpers.ts | 57 + .../src/components/FileUpload/index.ts | 6 + .../app-web/src/components/Footer/Footer.tsx | 7 +- .../Form/ErrorSummary/ErrorSummary.tsx | 86 +- .../FieldCheckbox/FieldCheckbox.stories.tsx | 2 +- .../FieldDropdown/FieldDropdown.stories.tsx | 2 +- .../Form/FieldRadio/FieldRadio.stories.tsx | 2 +- .../FieldTextInput/FieldTextInput.stories.tsx | 2 +- .../FieldTextarea/FieldTextarea.stories.tsx | 2 +- .../Form/FieldTextarea/FieldTextarea.tsx | 4 +- .../components/Form/FieldYesNo/FieldYesNo.tsx | 8 +- .../Header/PageHeadingRow/PageHeadingRow.tsx | 13 +- .../UserLoginInfo/UserLoginInfo.test.tsx | 16 +- .../Header/UserLoginInfo/UserLoginInfo.tsx | 8 +- .../PoliteErrorMessage/PoliteErrorMessage.tsx | 50 +- .../PackageSelect/PackageSelect.test.tsx | 93 +- .../Select/PackageSelect/PackageSelect.tsx | 16 +- .../ProgramSelect/ProgramSelect.stories.tsx | 4 - .../ProgramSelect/ProgramSelect.test.tsx | 57 +- .../Select/ProgramSelect/ProgramSelect.tsx | 20 +- .../ContractDetailsSummarySection.test.tsx | 42 +- .../ContractDetailsSummarySection.tsx | 21 +- .../RateDetailsSummarySection.test.tsx | 21 + .../RateDetailsSummarySection.tsx | 84 +- .../SubmissionTypeSummarySection.test.tsx | 7 +- .../SubmissionTypeSummarySection.tsx | 32 +- .../UploadedDocumentsTable.test.tsx | 144 +- .../UploadedDocumentsTable.tsx | 176 +- services/app-web/src/constants/errors.ts | 4 +- services/app-web/src/constants/index.ts | 2 +- services/app-web/src/contexts/S3Context.tsx | 6 +- .../src/documentHelpers/getAllDocuments.ts | 14 + .../src/documentHelpers/getDocumentKey.ts | 6 +- services/app-web/src/documentHelpers/index.ts | 3 + .../makeDocumentDateLookupTable.test.ts | 107 +- .../makeDocumentDateLookupTable.ts | 95 +- .../makeDocumentKeyLookupList.test.ts | 115 +- .../makeDocumentKeyLookupList.ts | 100 +- .../app-web/src/formHelpers/formatters.ts | 97 + services/app-web/src/formHelpers/index.ts | 1 + .../app-web/src/formHelpers/validators.ts | 37 +- .../fetchHealthPlanPackageWrapper.ts | 104 +- services/app-web/src/hooks/useDocument.tsx | 7 +- .../app-web/src/hooks/useStringConstants.ts | 15 + services/app-web/src/localAuth/LocalLogin.tsx | 11 + .../app-web/src/localAuth/LocalUserType.ts | 17 +- services/app-web/src/pages/Auth/Auth.test.tsx | 8 +- .../src/pages/Errors/GenericErrorPage.tsx | 17 +- .../QuestionResponse/QATable/QATable.tsx | 6 +- .../QuestionResponse/QuestionResponse.tsx | 14 +- .../app-web/src/pages/Settings/Settings.tsx | 5 +- .../Contacts/ActuaryContactFields.tsx | 19 +- .../StateSubmission/Documents/Documents.tsx | 2 +- .../New/NewStateSubmissionForm.test.tsx | 3 + .../PackagesWithSharedRates.tsx | 191 + .../RateDetails/RateDetails.test.tsx | 137 +- .../RateDetails/RateDetails.tsx | 1477 +--- .../RateDetails/RateDetailsSchema.ts | 5 + .../SingleRateCert/SingleRateCert.tsx | 547 ++ .../ReviewSubmit/ReviewSubmit.test.tsx | 6 + .../ReviewSubmit/ReviewSubmit.tsx | 4 +- .../StateSubmissionForm.module.scss | 7 +- .../StateSubmissionForm.test.tsx | 2 +- .../StateSubmission/StateSubmissionForm.tsx | 32 +- .../SubmissionType/SubmissionType.test.tsx | 532 +- .../SubmissionType/SubmissionType.tsx | 209 +- .../SubmissionType/SubmissionTypeSchema.ts | 10 +- .../SubmissionRevisionSummary.test.tsx | 7 +- .../SubmissionRevisionSummary.tsx | 17 +- .../SubmissionSideNav.test.tsx | 2 +- .../SubmissionSideNav/SubmissionSideNav.tsx | 34 +- .../SubmissionSummary.test.tsx | 66 +- .../SubmissionSummary/SubmissionSummary.tsx | 8 +- services/app-web/src/s3/s3Amplify.ts | 3 +- .../apolloMocks/healthPlanPackageGQLMock.ts | 82 +- .../apolloMocks/questionResponseGQLMock.ts | 16 +- .../questionResponse/questionResponse.spec.ts | 1 - .../stateSubmissionForm/rateDetails.spec.ts | 81 +- .../cypress/support/launchDarklyCommands.ts | 1 - .../support/stateSubmissionFormCommands.ts | 19 +- services/github-oidc/serverless.yml | 6 +- services/infra-api/serverless.yml | 3 + services/output.sh | 2 +- services/uploads/package.json | 4 +- yarn.lock | 6354 +++++++++-------- 295 files changed, 14685 insertions(+), 6207 deletions(-) create mode 100644 .images/aws-console-lambda-config.png create mode 100644 .images/verbose-logs-example.png create mode 100644 docs/Architecture.md create mode 100644 docs/README.md create mode 100644 docs/technical-design/contract-rate-refactor-relationships.md create mode 100644 docs/technical-design/howto-migrations.md rename docs/templates/{technical-design-template.md => technical-design-discussion-template.md} (100%) create mode 100644 docs/templates/technical-design-howto-template.md create mode 100644 services/app-api/prisma/migrations/20230510150748_add_contract_and_rate_tables/migration.sql create mode 100644 services/app-api/prisma/migrations/20230606210829_add_isremoval_flag/migration.sql create mode 100644 services/app-api/prisma/migrations/20230612222743_remove_invalided_by/migration.sql create mode 100644 services/app-api/prisma/migrations/20230705214915_add_helpdesk_user/migration.sql create mode 100644 services/app-api/prisma/migrations/20230707032003_add_form_data_fields_to_contract_and_rate_revision_tables/migration.sql create mode 100644 services/app-api/prisma/migrations/20230713173904_move_addtl_actuary_and_comm_preference_to_rate_revision/migration.sql create mode 100644 services/app-api/prisma/migrations/20230808082415_drop_rate_name/migration.sql create mode 100644 services/app-api/src/domain-models/contractAndRates/contractTypes.ts create mode 100644 services/app-api/src/domain-models/contractAndRates/index.ts create mode 100644 services/app-api/src/domain-models/contractAndRates/rateTypes.ts create mode 100644 services/app-api/src/domain-models/contractAndRates/updateInfoType.ts create mode 100644 services/app-api/src/handlers/migrate_rate_documents.test.ts create mode 100644 services/app-api/src/handlers/migrate_rate_documents.ts create mode 100644 services/app-api/src/handlers/proto_to_db.ts create mode 100644 services/app-api/src/postgres/contractAndRates/findContractWithHistory.test.ts create mode 100644 services/app-api/src/postgres/contractAndRates/findContractWithHistory.ts create mode 100644 services/app-api/src/postgres/contractAndRates/findDraftContract.test.ts create mode 100644 services/app-api/src/postgres/contractAndRates/findDraftContract.ts create mode 100644 services/app-api/src/postgres/contractAndRates/findDraftRate.test.ts create mode 100644 services/app-api/src/postgres/contractAndRates/findDraftRate.ts create mode 100644 services/app-api/src/postgres/contractAndRates/findRateWithHistory.test.ts create mode 100644 services/app-api/src/postgres/contractAndRates/findRateWithHistory.ts create mode 100644 services/app-api/src/postgres/contractAndRates/index.ts create mode 100644 services/app-api/src/postgres/contractAndRates/insertContract.test.ts create mode 100644 services/app-api/src/postgres/contractAndRates/insertContract.ts create mode 100644 services/app-api/src/postgres/contractAndRates/insertRate.ts create mode 100644 services/app-api/src/postgres/contractAndRates/parseContractAndRates.test.ts create mode 100644 services/app-api/src/postgres/contractAndRates/parseContractWithHistory.ts create mode 100644 services/app-api/src/postgres/contractAndRates/parseDraftContract.ts create mode 100644 services/app-api/src/postgres/contractAndRates/prismaDraftContractHelpers.ts create mode 100644 services/app-api/src/postgres/contractAndRates/prismaSharedContractRateHelpers.ts create mode 100644 services/app-api/src/postgres/contractAndRates/prismaSubmittedContractHelpers.ts create mode 100644 services/app-api/src/postgres/contractAndRates/prismaToDomainModel.test.ts create mode 100644 services/app-api/src/postgres/contractAndRates/proto_to_db_ContractId.ts create mode 100644 services/app-api/src/postgres/contractAndRates/proto_to_db_ContractRevisions.ts create mode 100644 services/app-api/src/postgres/contractAndRates/proto_to_db_Documents.ts create mode 100644 services/app-api/src/postgres/contractAndRates/proto_to_db_JoinTable.ts create mode 100644 services/app-api/src/postgres/contractAndRates/proto_to_db_RateRevisions.ts create mode 100644 services/app-api/src/postgres/contractAndRates/proto_to_db_UpdateInfoTable.ts create mode 100644 services/app-api/src/postgres/contractAndRates/submitContract.test.ts create mode 100644 services/app-api/src/postgres/contractAndRates/submitContract.ts create mode 100644 services/app-api/src/postgres/contractAndRates/submitRate.ts create mode 100644 services/app-api/src/postgres/contractAndRates/unlockContract.test.ts create mode 100644 services/app-api/src/postgres/contractAndRates/unlockContract.ts create mode 100644 services/app-api/src/postgres/contractAndRates/unlockRate.ts create mode 100644 services/app-api/src/postgres/contractAndRates/updateDraftContract.ts create mode 100644 services/app-api/src/postgres/contractAndRates/updateDraftRate.ts create mode 100644 services/app-api/src/postgres/prismaTypes.ts create mode 100644 services/app-api/src/testHelpers/contractAndRates/contractHelpers.ts create mode 100644 services/app-api/src/testHelpers/errorHelpers.ts create mode 100644 services/app-web/src/assets/images/appa.png create mode 100644 services/app-web/src/common-code/proto/healthPlanFormDataProto/testData/unlockedWithALittleBitOfEverything-2023-07-17.proto create mode 100644 services/app-web/src/components/FileUpload/helpers.ts create mode 100644 services/app-web/src/documentHelpers/getAllDocuments.ts create mode 100644 services/app-web/src/documentHelpers/index.ts create mode 100644 services/app-web/src/hooks/useStringConstants.ts create mode 100644 services/app-web/src/pages/StateSubmission/RateDetails/PackagesWithSharedRates/PackagesWithSharedRates.tsx create mode 100644 services/app-web/src/pages/StateSubmission/RateDetails/SingleRateCert/SingleRateCert.tsx diff --git a/.github/workflows/deploy-app-to-env.yml b/.github/workflows/deploy-app-to-env.yml index 3eab0a04bf..7c2a8d177b 100644 --- a/.github/workflows/deploy-app-to-env.yml +++ b/.github/workflows/deploy-app-to-env.yml @@ -135,4 +135,13 @@ jobs: env: STAGE_NAME: ${{ inputs.stage_name }} run: | - ./scripts/invoke-migrate-lambda.sh app-api-$STAGE_NAME-migrate + ./scripts/invoke-migrate-lambda.sh app-api-$STAGE_NAME-migrate \$LATEST "Migration of the database failed." + + - name: invoke proto_to_db lambda -- (rates refactor migrate) + id: invoke-proto_to_db + working-directory: services/app-api + continue-on-error: true + env: + STAGE_NAME: ${{ inputs.stage_name }} + run: | + ./scripts/invoke-migrate-lambda.sh app-api-$STAGE_NAME-proto_to_db \$LATEST "Migration of the protos to the database failed." diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 098c575913..583395812b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -127,7 +127,7 @@ jobs: path: ./services/app-web/coverage/coverage-final.json - name: publish code coverage - uses: paambaati/codeclimate-action@v4.0.0 + uses: paambaati/codeclimate-action@v5.0.0 continue-on-error: true env: CC_TEST_REPORTER_ID: f7474ffe9522492f5380eb86189480f352c841718c1fe6a63f169353c7cee243 @@ -179,7 +179,9 @@ jobs: - name: API Unit Tests env: + stage: ${steps.stage-name.outputs.stage-name-for-branch} NODE_OPTIONS: --max_old_space_size=6000 + REACT_APP_OTEL_COLLECTOR_URL: ${{vars.REACT_APP_OTEL_COLLECTOR_URL}} REACT_APP_AUTH_MODE: AWS_COGNITO DATABASE_URL: postgresql://postgres:shhhsecret@localhost:5432/postgres?schema=public&connection_limit=5 #pragma: allowlist secret working-directory: services/app-api @@ -193,7 +195,7 @@ jobs: path: ./services/app-api/coverage/coverage-final.json - name: publish code coverage - uses: paambaati/codeclimate-action@v4.0.0 + uses: paambaati/codeclimate-action@v5.0.0 continue-on-error: true env: CC_TEST_REPORTER_ID: f7474ffe9522492f5380eb86189480f352c841718c1fe6a63f169353c7cee243 @@ -275,7 +277,7 @@ jobs: needs.api-unit-tests.result == 'success' && needs.build-prisma-client-lambda-layer.result == 'success' && needs.begin-deployment.result == 'success' - uses: Enterprise-CMCS/managed-care-review/.github/workflows/deploy-app-to-env.yml@main + uses: Enterprise-CMCS/managed-care-review/.github/workflows/deploy-app-to-env.yml@ma_3212_migration_lambda with: environment: dev stage_name: ${{ needs.begin-deployment.outputs.stage-name }} @@ -534,7 +536,7 @@ jobs: path: ./coverage-cypress/coverage-final.json - name: publish code coverage - uses: paambaati/codeclimate-action@v4.0.0 + uses: paambaati/codeclimate-action@v5.0.0 continue-on-error: true env: CC_TEST_REPORTER_ID: f7474ffe9522492f5380eb86189480f352c841718c1fe6a63f169353c7cee243 diff --git a/.github/workflows/promote.yml b/.github/workflows/promote.yml index 12fd9516fb..38cc26b690 100644 --- a/.github/workflows/promote.yml +++ b/.github/workflows/promote.yml @@ -64,7 +64,7 @@ jobs: run: ./dev test --unit - name: publish code coverage - uses: paambaati/codeclimate-action@v4.0.0 + uses: paambaati/codeclimate-action@v5.0.0 continue-on-error: true env: CC_TEST_REPORTER_ID: f7474ffe9522492f5380eb86189480f352c841718c1fe6a63f169353c7cee243 diff --git a/.github/workflows/sechub-jira-sync.yml b/.github/workflows/sechub-jira-sync.yml index 5c11056382..5759902d58 100644 --- a/.github/workflows/sechub-jira-sync.yml +++ b/.github/workflows/sechub-jira-sync.yml @@ -25,7 +25,7 @@ jobs: stage-name: prod - name: Sync Security Hub and Jira - uses: Enterprise-CMCS/security-hub-visibility@v1.0.1 + uses: Enterprise-CMCS/mac-fc-security-hub-visibility@v1.0.2 with: jira-token: ${{ secrets.JIRA_TOKEN }} jira-username: ${{ secrets.JIRA_USERNAME }} diff --git a/.images/aws-console-lambda-config.png b/.images/aws-console-lambda-config.png new file mode 100644 index 0000000000000000000000000000000000000000..fa0c21fa023ba60214e41b06ee17542c94bb489c GIT binary patch literal 122320 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 A.0 + 1.0 -> B.0 +2020-01-03: + 1.0 -> A.1 + 1.0 -> B.0 +``` + +This join table strategy allows us to maintain a fully versioned history of revisions to contracts, rate, and the associations between them. + +Continuing the above example, let’s say we resubmit contract B and remove the link to rate 1. + +We’ll have new entries for the rates, including the one removed: + +``` +B.1, 1.0, 2020-01-04, 2020-01-04, true +B.1, 3.0, 2020-01-04, null, false +``` +And we’ll update the old relations to be invalid + +``` +B.0, 1.0, 2020-01-01, 2020-01-04, false +B.0, 3.0, 2020-01-02, 2020-01-04, false +``` + +This will give us a new entry in our rate 1 history, and we can attribute it to the correct submission because we have the isRemoved bit: +``` +2020-01-01: – initial submit of rate 1 + 1.0 -> A.0 + 1.0 -> B.0 +2020-01-03: – contract A resubmitted + 1.0 -> A.1 + 1.0 -> B.0 +2020-01-04: – contract B resubmitted + 1.0 -> A.1 +``` + +## Migration plan summary + +Existing `HealthPlanPackage` submissions will be converted into Contract and Rates in the db. Since we will be working on the migration work behind a feature flag, we can write a migrator that runs repeatedly, taking the old protobuf encoded FormData and moving that data into our new `Contract[Revision]` and `Rate[Revision]` tables. This way we can test and refine our migration before we actually switch over to using the new data. + +After the migration is complete and we switch the API to using the new tables, we will delete the old HealthPlanPackage tables completely and rely on the new Contract and Rate tables going forward. diff --git a/docs/technical-design/database-diagram.md b/docs/technical-design/database-diagram.md index e731aba529..5a94c1cf9a 100644 --- a/docs/technical-design/database-diagram.md +++ b/docs/technical-design/database-diagram.md @@ -76,3 +76,84 @@ Question ||--o{ QuestionReponse: questionID QuestionReponse ||--o{ QuestionResponseDocument: questionResponseID User }o--o{ State : "" ``` + + +## Contract & Rates DB + +This is the db diagram for the contracts and rates work, still disconnected from the rest of the db. + +```mermaid +erDiagram + +ContractTable { + String id +} +ContractRevisionTable { + String id + String contractID + DateTime createdAt + DateTime updatedAt + + String unlockInfoID + String submitInfoID + + String name +} + +RateTable { + String id +} +RateRevisionTable { + String id + String rateID + DateTime createdAt + DateTime updatedAt + + String unlockInfoID + String submitInfoID + + String name +} + +RateRevisionsOnContractRevisionsTable { + String rateRevisionID + String contractRevisionID + + DateTime validAfter + DateTime validUntil + Boolean isRemoval + +} + +UpdateInfoTable { + String id + + DateTime updatedAt + String updatedByID + String updatedReason +} + +ContractTable ||--|{ ContractRevisionTable : contract +ContractTable ||--|{ RateRevisionTable: draftContracts +RateTable ||--|{ RateRevisionTable : rate +ContractRevisionTable }|--|{ RateRevisionsOnContractRevisionsTable : contractRevisions +RateTable ||--|{ ContractRevisionTable: draftRates +RateRevisionTable }|--|{ RateRevisionsOnContractRevisionsTable : rateRevisions + + +ContractRevisionTable ||--|{ UpdateInfoTable: unlock-submit +RateRevisionTable ||--|{ UpdateInfoTable: unlock-submit + +UpdateInfoTable }|--|{ User: updatedBy + +User { + String givenName + String familyName + String email + Role role + String stateCode + String id +} + + +``` diff --git a/docs/technical-design/howto-migrations.md b/docs/technical-design/howto-migrations.md new file mode 100644 index 0000000000..185dbdfdd8 --- /dev/null +++ b/docs/technical-design/howto-migrations.md @@ -0,0 +1,49 @@ +# How to complete migrations + +## Background +Migrations are a controlled way to change existing records in the database or else change the shape of tables/relationships. They are necessary when fields are added, removed, or when the meaning behind fields and their relationships change. + +## General Guidance +- Prioritize testing in environments that have data similar to production. If you are testing on a review app, you should pre-populate data through using the deployed app as a user or via Cypress runs to have a diversity of test data available. +- Run in all deployed environments and validate for each environment. +- Write migrations that can be tested repeatedly. Include logic to skip or handle data that has already been changed or doesn't need to be migrated, so repeated runs of the lambda don't result in bad data. +- Avoid making migrations directly dependent on a specific feature being available in production. + +## Data Migrations +Currently data migrations change existing records in the database. They are run as standalone lambdas that developers must manually trigger by environment. + +### Steps +1. Prepare for manual testing in lower environments. + - Build a PR review app off `main` to start out. Try to populate with submissions similar to what is in production (For example, populate submissions via Cypress and if there are specific submissions types you know you will need to test, make sure add them). +1. Write the migration with verbose logs. + - The migration will be written as a [Node lambda](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html) and live in `app-api/src/handlers`. Make sure you use ES6 async await. + - Console statements are essential because there are line numbers in Cloudwatch when the migration fails or does not apply correctly. There is little additional context about why a run execution paused or failed. + - Here is an example of verbose debug console statements wrapping a loop: + ![debug consoles in data migration script](../../.images/verbose-logs-example.png) +1. Write unit tests. + - Consider including a test for `migration can be run repeatedly without data loss or unexpected results". Using repeatable migrations (when possible) makes it easier on developers and easier to unwind work. +1. Manually test the migration in your review app. + - Log into [AWS Lambda Console](https://console.aws.amazon.com/lambda/home) and find the lambda. This means choosing `app-api-` lambda with your branch name and migration name included. + - Click the Test tab and the `Test` button. Use the generic hello world event. + - All output will appear inline on the same page as the lambda run. All consoles appear there as well. You can also click into a link from there into Cloudwatch to be able to see the entire output of logs around the lambda execution. + - If you need to debug quickly, without waiting for redeploy in review app use the severless CLI script. + - `serverless deploy function --function name_of_migration --stage my_branch && echo "DEPLOYED" && serverless logs --function name_of_migration --stage my_branch --tail` can be run in your `app-api` directory. This script deploys your local handler code directly to AWS, without going through our normal CI build process. `my_branch`is the name of your deployed Github branch and `name_of_migration` is the name of the migration file mind the file path. + - If this is to be run in DEV (`main`) you will have to reshape your `envrc.local` to imitate configuration on that stage. See AWS console for Lambda to reference the shape of config. + ![lambda configuration panel in aws](../../.images/aws-console-lambda-config.png) + - Command line serverless scripts should not be used on PROD. Ideally do not use in VAL either. Running a migration via the AWS lambda console web interface is preferred because it is guaranteed to build off merged code and use similar configuration to how our application is deployed in CI. +1. Define clear acceptance criteria, this will be re-used. + - How do you know migration applied? What will be checked either in the app, via api request, or in the reports CSV? + - Developers will have to verify that the change worked multiple times, basically each time the migration is run on a new environment since the data could be quite different. + - If verification involves looking into reports and comparing fields, consider using a CSV tool like [CSVKit](https://csvkit.readthedocs.io/en/latest/index.html) if the comparisons seem involved. +1. After the PR merges and promotes,run in higher environments. + - Start with DEV. Follow similar steps Step #4 but now using the `main` lambda for your migration. + - Run the migration DEV > VAL > PROD in order, verifying in the application (or via reporting output) after each run. + + +## Schema Migrations +We use Prisma to perform schema migrations. Right now the developer process for schema migrations is described a bit [here](../../README.md#updating-the-database). More detailed steps forthcoming. + +## Proto migrations +The [proto migrations approach](../../services/app-proto/README.md#adding-a-new-migration) is no longer recommended - we are moving off protos. + + diff --git a/docs/technical-design/howto-update-state-programs.md b/docs/technical-design/howto-update-state-programs.md index 8cfae5e917..24a33b1b3b 100644 --- a/docs/technical-design/howto-update-state-programs.md +++ b/docs/technical-design/howto-update-state-programs.md @@ -1,10 +1,13 @@ # How to update state programs -State programs are an important set of data in MC-Review. Currently, all submissions must have a program. Programs are also used in submission and rate names in communication. +## Background +State programs are an important set of data in MC-Review. Currently, all submissions must have a program. Programs are also used in submission and rate names in communication. Right now developers are manually managing updates to the state programs list. For pilot rollout of MC-Review, state programs are stored in a JSON file `stateProgram.json`. The state programs json is referenced both client-side, to display the program dropdowns, and server-side in API requests that include program data. -The source of truth for that file comes from a CSV maintained by product and design. It is titled "State programs, population, and nicknames" in Google Drive. When that team adds or updates programs and would like the changes reflected in MC-Review, the dev team needs update our stored JSON using `scripts/import-programs.ts`. Steps to update are: +The source of truth for that file comes from a CSV maintained by product and design. It is titled "State programs, population, and nicknames" in Google Drive. When that team adds or updates programs and would like the changes reflected in MC-Review, the dev team needs update our stored JSON using `scripts/import-programs.ts`. Steps to update this list follows below. + +## Steps 1. Download the latest version of csv from google docs when prompted by product/design. 2. Run the script following the command listed in the `import-programs.ts`. diff --git a/docs/technical-design/launch-darkly-feature-flag-lifecycles.md b/docs/technical-design/launch-darkly-feature-flag-lifecycles.md index 13197c3486..9ff322f58e 100644 --- a/docs/technical-design/launch-darkly-feature-flag-lifecycles.md +++ b/docs/technical-design/launch-darkly-feature-flag-lifecycles.md @@ -1,6 +1,12 @@ -# Feature Flag Lifecycles +# How to Manage Feature Flag Lifecycles -## Criteria for when a feature should be behind a flag +## Background + +We use Launch Darkly to manage feature flags in the application. Without guidelines around when flags are added or removed from a codebase, feature flags can becomes a source of tech maintenance and confusion about when/if certain features are turned on. This document outlines how to add and remove feature flags. + +## General Guidance + +### Criteria for when a feature should be behind a flag A feature typically can be added behind a flag if: @@ -18,7 +24,8 @@ A feature typically can be added behind a flag if: - A/B testing of a feature -## How to add a flag to the codebase +## Steps +### Add a flag to the codebase Flags are first added to Launch Darkly via their UI. As an authenticated Launch Darkly user, navigate to our feature flags and click “create flag”. Choose a human readable flag name and a ‘-’ delimited flag key. The flag key is what we use inside our code. Make sure to mark the flag as client side if it is meant to be user visible (rather than API only). If the flag is permanent, mark this as well. @@ -50,10 +57,13 @@ import { featureFlags } from '../../common-code/featureFlags' ) ``` -## Removing a flag from the codebase +### Remove flag from the codebase Launch Darkly offers [code monitoring tools](https://docs.launchdarkly.com/home/code/code-references) to make removal of unused flags easier. Unfortunately, these are only offered to Enterprise plan subscribers, so this leaves flag monitoring [up to our team](https://docs.launchdarkly.com/guides/best-practices/technical-debt). We should schedule regular flag reviews as part of our sprint cadence to make sure we’re not keeping flags around that are no longer needed. To remove an unused flag, first remove it from the `common-code/featureFlags` file. You should now be able to use your editor/IDE (or build errors) to find the place(s) that the variation call should be removed. Once the flag has been removed from code, you’ll need to archive it in the Launch Darkly UI. This can be found under ‘Feature Flags > $flag-name > Settings` in the UI. + +## Related documentation +- Setup steps for testing with Launch Darkly locally can be found in [testing approach documentation](./launch-darkly-feature-flag-lifecycles.md) \ No newline at end of file diff --git a/docs/technical-design/launch-darkly-testing-approach.md b/docs/technical-design/launch-darkly-testing-approach.md index 16a3549177..f697fb47ed 100644 --- a/docs/technical-design/launch-darkly-testing-approach.md +++ b/docs/technical-design/launch-darkly-testing-approach.md @@ -13,10 +13,10 @@ export REACT_APP_LD_CLIENT_ID='Place Launch Darkly ID here' export LD_SDK_KEY='Place Launch Darkly SDK key here' ``` - **Getting LaunchDarkly Client-side ID and SDK keys**: - - Log into [LaunchDarkly](https://app.launchdarkly.com/login). + - Log into [LaunchDarkly](https://app.launchdarkly.us). To login use trussworks email (e.g. `@teamtrussworks.com`) and any password, which will redirect you to CMS SSO login. - On the dashboard page click on `Account settings` tab form the side navigation. - Then, on the `Account settings` page, click on the `Projects` tab. - - You should see a `Projects` table. Select the project 'MC Review' from the table. + - You should see a `Projects` table. Select the project 'macpro-mc-review' from the table. - Finally, you should see a `Environments` table . - The keys for `Local` environment are the ones needed for local testing. diff --git a/docs/templates/technical-design-template.md b/docs/templates/technical-design-discussion-template.md similarity index 100% rename from docs/templates/technical-design-template.md rename to docs/templates/technical-design-discussion-template.md diff --git a/docs/templates/technical-design-howto-template.md b/docs/templates/technical-design-howto-template.md new file mode 100644 index 0000000000..ac7d0ff32c --- /dev/null +++ b/docs/templates/technical-design-howto-template.md @@ -0,0 +1,19 @@ +--- +title: Technical Design How-to Guide Template +--- + +# Title of How To +e.g. "How to update the state programs list" or "How to create and test endpoints" + +## Background +One paragraph about why and when a developer need to follow this. + +## General Guidance +Any general technical considerations, advice, or tradeoffs to consider before completing the steps. + +## Steps +The sequential steps to complete this task. Most likely this will take the form of list. + +## Related Documentation +- Often we have how tos that relate to other how tos or other documentation. +- They can be listed here. \ No newline at end of file diff --git a/package.json b/package.json index d24775c21d..3071ed67e4 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "devDependencies": { "@bahmutov/cypress-esbuild-preprocessor": "^2.2.0", "@cypress-audit/pa11y": "^1.3.0", - "chromedriver": "^106.0.1", + "chromedriver": "^114.0.2", "cypress": "^12.16.0", "cypress-pipe": "^2.0.0", "danger": "^11.2.6", diff --git a/scripts/add_cypress_test_users.ts b/scripts/add_cypress_test_users.ts index 1e21a264ca..18e1ffe3d2 100644 --- a/scripts/add_cypress_test_users.ts +++ b/scripts/add_cypress_test_users.ts @@ -39,7 +39,7 @@ async function getUserPoolID(stageName: string): Promise { return userPoolID } -type UserRole = 'CMS_USER' | 'STATE_USER' | 'UNKNOWN_USER' | 'ADMIN_USER' +type UserRole = 'CMS_USER' | 'STATE_USER' | 'UNKNOWN_USER' | 'ADMIN_USER' | 'HELPDESK_USER' // these are the exact roles as they are set by IDM function IDMRole(role: UserRole): string { @@ -50,6 +50,8 @@ function IDMRole(role: UserRole): string { return 'macmcrrs-state-user' case 'ADMIN_USER': return 'macmcrrs-approver' + case 'HELPDESK_USER': + return 'macmcrrs-helpdesk' case 'UNKNOWN_USER': return 'foo-bar-user' } @@ -211,6 +213,12 @@ async function main() { role: 'ADMIN_USER' as const, state: undefined, }, + { + name: 'Appa', + email: 'appa@example.com', + role: 'HELPDESK_USER' as const, + state: undefined, + }, ] for (const user of testUsers) { diff --git a/scripts/destroy_stage.ts b/scripts/destroy_stage.ts index fd23f223e6..1488444603 100644 --- a/scripts/destroy_stage.ts +++ b/scripts/destroy_stage.ts @@ -49,49 +49,50 @@ async function main() { process.exit(1) } - const stacksToDestroy = await getStacksFromStage(stage) - console.info(`debug: ${stacksToDestroy}`) - if (process.env.CI === 'true' && stacksToDestroy.length === 0) { - console.warn( - `We're in CI and there are no stacks to destroy. Alerting.` - ) - process.exit(1) - } - if (stacksToDestroy.length === 0) { - console.info(`No stacks to destroy. Skipping destroy.`) - process.exit(0) - } - - // AWS can rate limit us if we go too fast. Using a regular - // for construct to wait on async to slow us down a bit. - for (const stack of stacksToDestroy) { - if (stack instanceof Error) { - console.error(`Could not delete stack: ${stack}`) + try { + const stacksToDestroy = await getStacksFromStage(stage) + if (process.env.CI === 'true' && stacksToDestroy.length === 0) { + console.warn( + `We're in CI and there are no stacks to destroy. Alerting.` + ) process.exit(1) } - console.info(`Destroying stack: ${stack}`) - - const clearBucketOutput = await clearServerlessDeployBucket(stack) - if (clearBucketOutput instanceof Error) { - // We don't process.exit(1) here because sometimes buckets in a stack - // have already been removed. We can still delete the stack. - console.info(`Could not clear buckets in ${stack}`) + if (stacksToDestroy.length === 0) { + console.info(`No stacks to destroy. Skipping destroy.`) + process.exit(0) } - const deleteStackOutput = await deleteStack(stack) - if (deleteStackOutput instanceof Error) { - console.info(`Could not delete ${stack}. ${deleteStackOutput}`) - process.exit(1) - } + console.info( + `Getting ready to remove the following stacks: ${stacksToDestroy}` + ) - console.info(`Destroy successful: ${stack}`) + // AWS can rate limit us if we go too fast. Using a regular + // for construct to wait on async to slow us down a bit. + for (const stack of stacksToDestroy) { + console.info(`Destroying stack: ${stack}`) + + const clearBucketOutput = await clearServerlessDeployBucket(stack) + if (clearBucketOutput instanceof Error) { + // We don't process.exit(1) here because sometimes buckets in a stack + // have already been removed. We can still delete the stack. + console.info(`Could not clear buckets in ${stack}`) + } + + const deleteStackOutput = await deleteStack(stack) + if (deleteStackOutput instanceof Error) { + console.info(`Could not delete ${stack}. ${deleteStackOutput}`) + continue + } + + console.info(`Destroy successful: ${stack}`) + } + } catch (err) { + console.error(`Destroy was not successful: ${err}`) + process.exit(1) } } -async function getStacksFromStage( - stageName: string -): Promise { - let errors: Error[] = [] +async function getStacksFromStage(stageName: string): Promise { let stacksToDestroy: string[] = [] for (const prefix of stackPrefixes) { const stackName = `${prefix}-${stageName}` @@ -100,10 +101,9 @@ async function getStacksFromStage( StackName: stackName, }) const stacks = await cf.send(commandDescribeStacks) - - if (!stacks.Stacks) { - console.info(`Stack ${stackName} does not exist. Skipping.`) - return [] + if (stacks.Stacks == undefined) { + console.info(`Stack ${stackName} was not found. Skipping`) + continue } // type guard @@ -117,13 +117,9 @@ async function getStacksFromStage( stacksToDestroy.push(...types) } catch (err) { - const error = new Error(err) - errors.push(error) + console.error(`getStacksFromStage ${err}. Skipping.`) } } - if (errors.length != 0) { - return errors - } return stacksToDestroy } diff --git a/services/app-api/jest.config.ts b/services/app-api/jest.config.ts index 762638bbfd..73cfd9712f 100644 --- a/services/app-api/jest.config.ts +++ b/services/app-api/jest.config.ts @@ -2,7 +2,7 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', transform: { - '\\.graphql$': 'jest-raw-loader', + '\\.(gql|graphql)$': '@graphql-tools/jest-transform', }, coverageReporters: [ [ diff --git a/services/app-api/package.json b/services/app-api/package.json index 24addcd574..ab9475702f 100644 --- a/services/app-api/package.json +++ b/services/app-api/package.json @@ -36,6 +36,7 @@ "@aws-sdk/client-ses": "^3.226.0", "@aws-sdk/client-ssm": "^3.226.0", "@aws-sdk/lib-storage": "^3.226.0", + "@launchdarkly/node-server-sdk": "8.1.1", "@opentelemetry/api": "^1.3.0", "@opentelemetry/core": "^1.9.1", "@opentelemetry/exporter-trace-otlp-http": "^0.35.1", @@ -55,7 +56,6 @@ "graphql": "^16.2.0", "graphql-scalars": "^1.11.1", "json2csv": "^5.0.7", - "launchdarkly-node-server-sdk": "7.0.1", "neverthrow": "^6.0.0", "path-to-regexp": "^6.2.1", "protobufjs": "^6.11.2", @@ -64,7 +64,8 @@ "zod": "^3.11.6" }, "devDependencies": { - "@prisma/client": "^4.6.1", + "@graphql-tools/jest-transform": "^2.0.0", + "@prisma/client": "^4.6", "@types/archiver": "^5.1.1", "@types/aws-lambda": "^8.10.83", "@types/glob": "^8.0.0", @@ -81,11 +82,10 @@ "eslint-plugin-jest": "^27.0.1", "eslint-plugin-prettier": "^4.0.0", "graphql-tag": "^2.12.5", - "jest": "^27.5.1", - "jest-raw-loader": "^1.0.1", + "jest": "^29.6.2", "lint-staged": "^13.0.1", "prettier": "^2.4.1", - "prisma": "^4.6.1", + "prisma": "^4.6", "serverless": "^3.27.0", "serverless-associate-waf": "^1.2.1", "serverless-iam-helper": "CMSgov/serverless-iam-helper", @@ -94,9 +94,9 @@ "serverless-offline-ssm": "^6.2.0", "serverless-s3-bucket-helper": "CMSgov/serverless-s3-bucket-helper", "serverless-stack-termination-protection": "^2.0.2", - "serverless-webpack": "^5.11.0", + "serverless-webpack": "^5.12.0", "slugify": "^1.6.5", - "ts-jest": "^27.1.4", + "ts-jest": "^29.1.1", "ts-loader": "^9.2.8", "tsconfig-paths-webpack-plugin": "^4.0.0", "typescript": "4.9.5", diff --git a/services/app-api/prisma/migrations/20230510150748_add_contract_and_rate_tables/migration.sql b/services/app-api/prisma/migrations/20230510150748_add_contract_and_rate_tables/migration.sql new file mode 100644 index 0000000000..c256ab7553 --- /dev/null +++ b/services/app-api/prisma/migrations/20230510150748_add_contract_and_rate_tables/migration.sql @@ -0,0 +1,133 @@ +BEGIN; +-- CreateTable +CREATE TABLE "ContractTable" ( + "id" TEXT NOT NULL, + + CONSTRAINT "ContractTable_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RateTable" ( + "id" TEXT NOT NULL, + + CONSTRAINT "RateTable_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ContractRevisionTable" ( + "id" TEXT NOT NULL, + "contractID" TEXT NOT NULL, + "unlockInfoID" TEXT, + "submitInfoID" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" TEXT NOT NULL, + + CONSTRAINT "ContractRevisionTable_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RateRevisionTable" ( + "id" TEXT NOT NULL, + "rateID" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "unlockInfoID" TEXT, + "submitInfoID" TEXT, + "name" TEXT NOT NULL, + + CONSTRAINT "RateRevisionTable_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RateRevisionsOnContractRevisionsTable" ( + "rateRevisionID" TEXT NOT NULL, + "contractRevisionID" TEXT NOT NULL, + "validAfter" TIMESTAMP(3) NOT NULL, + "validUntil" TIMESTAMP(3), + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "invalidatedByContractRevisionID" TEXT, + "invalidatedByRateRevisionID" TEXT, + + CONSTRAINT "RateRevisionsOnContractRevisionsTable_pkey" PRIMARY KEY ("rateRevisionID","contractRevisionID","validAfter") +); + +-- CreateTable +CREATE TABLE "UpdateInfoTable" ( + "id" TEXT NOT NULL, + "updatedAt" TIMESTAMP(3) NOT NULL, + "updatedByID" TEXT NOT NULL, + "updatedReason" TEXT NOT NULL, + + CONSTRAINT "UpdateInfoTable_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_ContractTableToRateRevisionTable" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_ContractRevisionTableToRateTable" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "_ContractTableToRateRevisionTable_AB_unique" ON "_ContractTableToRateRevisionTable"("A", "B"); + +-- CreateIndex +CREATE INDEX "_ContractTableToRateRevisionTable_B_index" ON "_ContractTableToRateRevisionTable"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_ContractRevisionTableToRateTable_AB_unique" ON "_ContractRevisionTableToRateTable"("A", "B"); + +-- CreateIndex +CREATE INDEX "_ContractRevisionTableToRateTable_B_index" ON "_ContractRevisionTableToRateTable"("B"); + +-- AddForeignKey +ALTER TABLE "ContractRevisionTable" ADD CONSTRAINT "ContractRevisionTable_contractID_fkey" FOREIGN KEY ("contractID") REFERENCES "ContractTable"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ContractRevisionTable" ADD CONSTRAINT "ContractRevisionTable_unlockInfoID_fkey" FOREIGN KEY ("unlockInfoID") REFERENCES "UpdateInfoTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ContractRevisionTable" ADD CONSTRAINT "ContractRevisionTable_submitInfoID_fkey" FOREIGN KEY ("submitInfoID") REFERENCES "UpdateInfoTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateRevisionTable" ADD CONSTRAINT "RateRevisionTable_rateID_fkey" FOREIGN KEY ("rateID") REFERENCES "RateTable"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateRevisionTable" ADD CONSTRAINT "RateRevisionTable_unlockInfoID_fkey" FOREIGN KEY ("unlockInfoID") REFERENCES "UpdateInfoTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateRevisionTable" ADD CONSTRAINT "RateRevisionTable_submitInfoID_fkey" FOREIGN KEY ("submitInfoID") REFERENCES "UpdateInfoTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateRevisionsOnContractRevisionsTable" ADD CONSTRAINT "RateRevisionsOnContractRevisionsTable_rateRevisionID_fkey" FOREIGN KEY ("rateRevisionID") REFERENCES "RateRevisionTable"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateRevisionsOnContractRevisionsTable" ADD CONSTRAINT "RateRevisionsOnContractRevisionsTable_contractRevisionID_fkey" FOREIGN KEY ("contractRevisionID") REFERENCES "ContractRevisionTable"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateRevisionsOnContractRevisionsTable" ADD CONSTRAINT "RateRevisionsOnContractRevisionsTable_invalidatedByContrac_fkey" FOREIGN KEY ("invalidatedByContractRevisionID") REFERENCES "ContractRevisionTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateRevisionsOnContractRevisionsTable" ADD CONSTRAINT "RateRevisionsOnContractRevisionsTable_invalidatedByRateRev_fkey" FOREIGN KEY ("invalidatedByRateRevisionID") REFERENCES "RateRevisionTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UpdateInfoTable" ADD CONSTRAINT "UpdateInfoTable_updatedByID_fkey" FOREIGN KEY ("updatedByID") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_ContractTableToRateRevisionTable" ADD CONSTRAINT "_ContractTableToRateRevisionTable_A_fkey" FOREIGN KEY ("A") REFERENCES "ContractTable"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_ContractTableToRateRevisionTable" ADD CONSTRAINT "_ContractTableToRateRevisionTable_B_fkey" FOREIGN KEY ("B") REFERENCES "RateRevisionTable"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_ContractRevisionTableToRateTable" ADD CONSTRAINT "_ContractRevisionTableToRateTable_A_fkey" FOREIGN KEY ("A") REFERENCES "ContractRevisionTable"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_ContractRevisionTableToRateTable" ADD CONSTRAINT "_ContractRevisionTableToRateTable_B_fkey" FOREIGN KEY ("B") REFERENCES "RateTable"("id") ON DELETE CASCADE ON UPDATE CASCADE; +COMMIT; diff --git a/services/app-api/prisma/migrations/20230606210829_add_isremoval_flag/migration.sql b/services/app-api/prisma/migrations/20230606210829_add_isremoval_flag/migration.sql new file mode 100644 index 0000000000..51bf8dcd93 --- /dev/null +++ b/services/app-api/prisma/migrations/20230606210829_add_isremoval_flag/migration.sql @@ -0,0 +1,4 @@ +BEGIN; +-- AlterTable +ALTER TABLE "RateRevisionsOnContractRevisionsTable" ADD COLUMN "isRemoval" BOOLEAN NOT NULL DEFAULT false; +COMMIT; diff --git a/services/app-api/prisma/migrations/20230612222743_remove_invalided_by/migration.sql b/services/app-api/prisma/migrations/20230612222743_remove_invalided_by/migration.sql new file mode 100644 index 0000000000..f62a86f04c --- /dev/null +++ b/services/app-api/prisma/migrations/20230612222743_remove_invalided_by/migration.sql @@ -0,0 +1,18 @@ +BEGIN; +/* + Warnings: + + - You are about to drop the column `invalidatedByContractRevisionID` on the `RateRevisionsOnContractRevisionsTable` table. All the data in the column will be lost. + - You are about to drop the column `invalidatedByRateRevisionID` on the `RateRevisionsOnContractRevisionsTable` table. All the data in the column will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "RateRevisionsOnContractRevisionsTable" DROP CONSTRAINT "RateRevisionsOnContractRevisionsTable_invalidatedByContrac_fkey"; + +-- DropForeignKey +ALTER TABLE "RateRevisionsOnContractRevisionsTable" DROP CONSTRAINT "RateRevisionsOnContractRevisionsTable_invalidatedByRateRev_fkey"; + +-- AlterTable +ALTER TABLE "RateRevisionsOnContractRevisionsTable" DROP COLUMN "invalidatedByContractRevisionID", +DROP COLUMN "invalidatedByRateRevisionID"; +COMMIT; diff --git a/services/app-api/prisma/migrations/20230705214915_add_helpdesk_user/migration.sql b/services/app-api/prisma/migrations/20230705214915_add_helpdesk_user/migration.sql new file mode 100644 index 0000000000..e2cfa38c38 --- /dev/null +++ b/services/app-api/prisma/migrations/20230705214915_add_helpdesk_user/migration.sql @@ -0,0 +1,7 @@ +BEGIN; +-- AlterEnum +ALTER TYPE "Role" ADD VALUE 'HELPDESK_USER'; + +-- AlterTable +ALTER TABLE "UserAudit" ALTER COLUMN "updatedAt" DROP DEFAULT; +COMMIT; diff --git a/services/app-api/prisma/migrations/20230707032003_add_form_data_fields_to_contract_and_rate_revision_tables/migration.sql b/services/app-api/prisma/migrations/20230707032003_add_form_data_fields_to_contract_and_rate_revision_tables/migration.sql new file mode 100644 index 0000000000..81180ebf11 --- /dev/null +++ b/services/app-api/prisma/migrations/20230707032003_add_form_data_fields_to_contract_and_rate_revision_tables/migration.sql @@ -0,0 +1,262 @@ +BEGIN; +/* + Warnings: + + - You are about to drop the column `name` on the `ContractRevisionTable` table. All the data in the column will be lost. + - Added the required column `contractType` to the `ContractRevisionTable` table without a default value. This is not possible if the table is not empty. + - Added the required column `submissionDescription` to the `ContractRevisionTable` table without a default value. This is not possible if the table is not empty. + - Added the required column `submissionType` to the `ContractRevisionTable` table without a default value. This is not possible if the table is not empty. + - Added the required column `stateCode` to the `ContractTable` table without a default value. This is not possible if the table is not empty. + - Added the required column `stateNumber` to the `ContractTable` table without a default value. This is not possible if the table is not empty. + - Added the required column `stateCode` to the `RateTable` table without a default value. This is not possible if the table is not empty. + - Added the required column `stateNumber` to the `RateTable` table without a default value. This is not possible if the table is not empty. + +*/ +-- CreateEnum +CREATE TYPE "RateType" AS ENUM ('NEW', 'AMENDMENT'); + +-- CreateEnum +CREATE TYPE "RateCapitationType" AS ENUM ('RATE_CELL', 'RATE_RANGE'); + +-- CreateEnum +CREATE TYPE "ManagedCareEntity" AS ENUM ('MCO', 'PIHP', 'PAHP', 'PCCM'); + +-- CreateEnum +CREATE TYPE "FederalAuthority" AS ENUM ('STATE_PLAN', 'WAIVER_1915B', 'WAIVER_1115', 'VOLUNTARY', 'BENCHMARK', 'TITLE_XXI'); + +-- CreateEnum +CREATE TYPE "ContractExecutionStatus" AS ENUM ('EXECUTED', 'UNEXECUTED'); + +-- CreateEnum +CREATE TYPE "ContractType" AS ENUM ('BASE', 'AMENDMENT'); + +-- CreateEnum +CREATE TYPE "DocumentCategory" AS ENUM ('CONTRACT', 'RATES', 'CONTRACT_RELATED', 'RATES_RELATED'); + +-- CreateEnum +CREATE TYPE "ActuaryCommunication" AS ENUM ('OACT_TO_ACTUARY', 'OACT_TO_STATE'); + +-- CreateEnum +CREATE TYPE "ActuarialFirm" AS ENUM ('MERCER', 'MILLIMAN', 'OPTUMAS', 'GUIDEHOUSE', 'DELOITTE', 'STATE_IN_HOUSE', 'OTHER'); + +-- CreateEnum +CREATE TYPE "PopulationCoverageType" AS ENUM ('MEDICAID', 'CHIP', 'MEDICAID_AND_CHIP'); + +-- CreateEnum +CREATE TYPE "SubmissionType" AS ENUM ('CONTRACT_ONLY', 'CONTRACT_AND_RATES'); + +-- AlterTable +ALTER TABLE "ContractRevisionTable" DROP COLUMN "name", +ADD COLUMN "addtlActuaryCommunicationPreference" "ActuaryCommunication", +ADD COLUMN "contractDateEnd" DATE, +ADD COLUMN "contractDateStart" DATE, +ADD COLUMN "contractExecutionStatus" "ContractExecutionStatus", +ADD COLUMN "contractType" "ContractType" NOT NULL, +ADD COLUMN "federalAuthorities" "FederalAuthority"[], +ADD COLUMN "inLieuServicesAndSettings" BOOLEAN, +ADD COLUMN "managedCareEntities" "ManagedCareEntity"[], +ADD COLUMN "modifiedBenefitsProvided" BOOLEAN, +ADD COLUMN "modifiedEnrollmentProcess" BOOLEAN, +ADD COLUMN "modifiedGeoAreaServed" BOOLEAN, +ADD COLUMN "modifiedGrevienceAndAppeal" BOOLEAN, +ADD COLUMN "modifiedIncentiveArrangements" BOOLEAN, +ADD COLUMN "modifiedLengthOfContract" BOOLEAN, +ADD COLUMN "modifiedMedicaidBeneficiaries" BOOLEAN, +ADD COLUMN "modifiedMedicalLossRatioStandards" BOOLEAN, +ADD COLUMN "modifiedNetworkAdequacyStandards" BOOLEAN, +ADD COLUMN "modifiedNonRiskPaymentArrangements" BOOLEAN, +ADD COLUMN "modifiedOtherFinancialPaymentIncentive" BOOLEAN, +ADD COLUMN "modifiedPassThroughPayments" BOOLEAN, +ADD COLUMN "modifiedPaymentsForMentalDiseaseInstitutions" BOOLEAN, +ADD COLUMN "modifiedRiskSharingStrategy" BOOLEAN, +ADD COLUMN "modifiedStateDirectedPayments" BOOLEAN, +ADD COLUMN "modifiedWitholdAgreements" BOOLEAN, +ADD COLUMN "populationCovered" "PopulationCoverageType", +ADD COLUMN "programIDs" TEXT[], +ADD COLUMN "riskBasedContract" BOOLEAN, +ADD COLUMN "submissionDescription" TEXT NOT NULL, +ADD COLUMN "submissionType" "SubmissionType" NOT NULL; + +-- AlterTable +ALTER TABLE "ContractTable" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "stateCode" TEXT NOT NULL, +ADD COLUMN "stateNumber" INTEGER NOT NULL, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; + +-- AlterTable +ALTER TABLE "RateRevisionTable" ADD COLUMN "actuaryCommunicationPreference" "ActuaryCommunication", +ADD COLUMN "amendmentEffectiveDateEnd" DATE, +ADD COLUMN "amendmentEffectiveDateStart" DATE, +ADD COLUMN "rateCapitationType" "RateCapitationType", +ADD COLUMN "rateCertificationName" TEXT, +ADD COLUMN "rateDateCertified" DATE, +ADD COLUMN "rateDateEnd" DATE, +ADD COLUMN "rateDateStart" DATE, +ADD COLUMN "rateProgramIDs" TEXT[], +ADD COLUMN "rateType" "RateType"; + +-- AlterTable +ALTER TABLE "RateTable" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "stateCode" TEXT NOT NULL, +ADD COLUMN "stateNumber" INTEGER NOT NULL, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; + +-- AlterTable +ALTER TABLE "State" ADD COLUMN "latestStateRateCertNumber" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "UserAudit" ALTER COLUMN "updatedAt" DROP DEFAULT; + +-- CreateTable +CREATE TABLE "SharedRateCertifications" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "SharedRateCertifications_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ActuaryContact" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" TEXT NOT NULL, + "titleRole" TEXT NOT NULL, + "email" TEXT NOT NULL, + "actuarialFirm" "ActuarialFirm" NOT NULL, + "actuarialFirmOther" TEXT, + "contractRevisionID" TEXT, + "rateRevisionID" TEXT, + + CONSTRAINT "ActuaryContact_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ContractDocument" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" TEXT NOT NULL, + "s3URL" TEXT NOT NULL, + "sha256" TEXT, + "contractRevisionID" TEXT NOT NULL, + + CONSTRAINT "ContractDocument_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ContractSupportingDocument" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" TEXT NOT NULL, + "s3URL" TEXT NOT NULL, + "sha256" TEXT, + "contractRevisionID" TEXT NOT NULL, + + CONSTRAINT "ContractSupportingDocument_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RateDocument" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" TEXT NOT NULL, + "s3URL" TEXT NOT NULL, + "sha256" TEXT, + "rateRevisionID" TEXT NOT NULL, + + CONSTRAINT "RateDocument_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RateSupportingDocument" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" TEXT NOT NULL, + "s3URL" TEXT NOT NULL, + "sha256" TEXT, + "rateRevisionID" TEXT NOT NULL, + + CONSTRAINT "RateSupportingDocument_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "StateContact" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" TEXT NOT NULL, + "titleRole" TEXT NOT NULL, + "email" TEXT NOT NULL, + "contractRevisionID" TEXT NOT NULL, + + CONSTRAINT "StateContact_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_ContractRevisionTableToSharedRateCertifications" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_RateRevisionTableToSharedRateCertifications" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "_ContractRevisionTableToSharedRateCertifications_AB_unique" ON "_ContractRevisionTableToSharedRateCertifications"("A", "B"); + +-- CreateIndex +CREATE INDEX "_ContractRevisionTableToSharedRateCertifications_B_index" ON "_ContractRevisionTableToSharedRateCertifications"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_RateRevisionTableToSharedRateCertifications_AB_unique" ON "_RateRevisionTableToSharedRateCertifications"("A", "B"); + +-- CreateIndex +CREATE INDEX "_RateRevisionTableToSharedRateCertifications_B_index" ON "_RateRevisionTableToSharedRateCertifications"("B"); + +-- AddForeignKey +ALTER TABLE "ContractTable" ADD CONSTRAINT "ContractTable_stateCode_fkey" FOREIGN KEY ("stateCode") REFERENCES "State"("stateCode") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateTable" ADD CONSTRAINT "RateTable_stateCode_fkey" FOREIGN KEY ("stateCode") REFERENCES "State"("stateCode") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ActuaryContact" ADD CONSTRAINT "ActuaryContact_contractRevisionID_fkey" FOREIGN KEY ("contractRevisionID") REFERENCES "ContractRevisionTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ActuaryContact" ADD CONSTRAINT "ActuaryContact_rateRevisionID_fkey" FOREIGN KEY ("rateRevisionID") REFERENCES "RateRevisionTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ContractDocument" ADD CONSTRAINT "ContractDocument_contractRevisionID_fkey" FOREIGN KEY ("contractRevisionID") REFERENCES "ContractRevisionTable"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ContractSupportingDocument" ADD CONSTRAINT "ContractSupportingDocument_contractRevisionID_fkey" FOREIGN KEY ("contractRevisionID") REFERENCES "ContractRevisionTable"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateDocument" ADD CONSTRAINT "RateDocument_rateRevisionID_fkey" FOREIGN KEY ("rateRevisionID") REFERENCES "RateRevisionTable"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RateSupportingDocument" ADD CONSTRAINT "RateSupportingDocument_rateRevisionID_fkey" FOREIGN KEY ("rateRevisionID") REFERENCES "RateRevisionTable"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "StateContact" ADD CONSTRAINT "StateContact_contractRevisionID_fkey" FOREIGN KEY ("contractRevisionID") REFERENCES "ContractRevisionTable"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_ContractRevisionTableToSharedRateCertifications" ADD CONSTRAINT "_ContractRevisionTableToSharedRateCertifications_A_fkey" FOREIGN KEY ("A") REFERENCES "ContractRevisionTable"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_ContractRevisionTableToSharedRateCertifications" ADD CONSTRAINT "_ContractRevisionTableToSharedRateCertifications_B_fkey" FOREIGN KEY ("B") REFERENCES "SharedRateCertifications"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_RateRevisionTableToSharedRateCertifications" ADD CONSTRAINT "_RateRevisionTableToSharedRateCertifications_A_fkey" FOREIGN KEY ("A") REFERENCES "RateRevisionTable"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_RateRevisionTableToSharedRateCertifications" ADD CONSTRAINT "_RateRevisionTableToSharedRateCertifications_B_fkey" FOREIGN KEY ("B") REFERENCES "SharedRateCertifications"("id") ON DELETE CASCADE ON UPDATE CASCADE; +COMMIT; diff --git a/services/app-api/prisma/migrations/20230713173904_move_addtl_actuary_and_comm_preference_to_rate_revision/migration.sql b/services/app-api/prisma/migrations/20230713173904_move_addtl_actuary_and_comm_preference_to_rate_revision/migration.sql new file mode 100644 index 0000000000..a4042373da --- /dev/null +++ b/services/app-api/prisma/migrations/20230713173904_move_addtl_actuary_and_comm_preference_to_rate_revision/migration.sql @@ -0,0 +1,30 @@ +BEGIN; +/* + Warnings: + + - You are about to drop the column `contractRevisionID` on the `ActuaryContact` table. All the data in the column will be lost. + - You are about to drop the column `rateRevisionID` on the `ActuaryContact` table. All the data in the column will be lost. + - You are about to drop the column `addtlActuaryCommunicationPreference` on the `ContractRevisionTable` table. All the data in the column will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "ActuaryContact" DROP CONSTRAINT "ActuaryContact_contractRevisionID_fkey"; + +-- DropForeignKey +ALTER TABLE "ActuaryContact" DROP CONSTRAINT "ActuaryContact_rateRevisionID_fkey"; + +-- AlterTable +ALTER TABLE "ActuaryContact" DROP COLUMN "contractRevisionID", +DROP COLUMN "rateRevisionID", +ADD COLUMN "rateWithAddtlActuaryID" TEXT, +ADD COLUMN "rateWithCertifyingActuaryID" TEXT; + +-- AlterTable +ALTER TABLE "ContractRevisionTable" DROP COLUMN "addtlActuaryCommunicationPreference"; + +-- AddForeignKey +ALTER TABLE "ActuaryContact" ADD CONSTRAINT "ActuaryContact_rateWithCertifyingActuaryID_fkey" FOREIGN KEY ("rateWithCertifyingActuaryID") REFERENCES "RateRevisionTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ActuaryContact" ADD CONSTRAINT "ActuaryContact_rateWithAddtlActuaryID_fkey" FOREIGN KEY ("rateWithAddtlActuaryID") REFERENCES "RateRevisionTable"("id") ON DELETE SET NULL ON UPDATE CASCADE; +COMMIT; diff --git a/services/app-api/prisma/migrations/20230808082415_drop_rate_name/migration.sql b/services/app-api/prisma/migrations/20230808082415_drop_rate_name/migration.sql new file mode 100644 index 0000000000..eb9271b7d8 --- /dev/null +++ b/services/app-api/prisma/migrations/20230808082415_drop_rate_name/migration.sql @@ -0,0 +1,10 @@ +BEGIN; +/* + Warnings: + + - You are about to drop the column `name` on the `RateRevisionTable` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "RateRevisionTable" DROP COLUMN "name"; +COMMIT; diff --git a/services/app-api/prisma/schema.prisma b/services/app-api/prisma/schema.prisma index 441e56d323..e5c84804ed 100644 --- a/services/app-api/prisma/schema.prisma +++ b/services/app-api/prisma/schema.prisma @@ -34,16 +34,229 @@ model HealthPlanRevisionTable { pkg HealthPlanPackageTable @relation(fields: [pkgID], references: [id]) } +model ContractTable { + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + stateCode String + state State @relation(fields: [stateCode], references: [stateCode]) + stateNumber Int + + revisions ContractRevisionTable[] + draftRateRevisions RateRevisionTable[] +} + +model RateTable { + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + stateCode String + state State @relation(fields: [stateCode], references: [stateCode]) + stateNumber Int + + revisions RateRevisionTable[] + draftContractRevisions ContractRevisionTable[] +} + +model ContractRevisionTable { + id String @id @default(uuid()) + contractID String + contract ContractTable @relation(fields: [contractID], references: [id]) + + rateRevisions RateRevisionsOnContractRevisionsTable[] + sharedRateRevisions SharedRateCertifications[] + draftRates RateTable[] + + unlockInfoID String? + unlockInfo UpdateInfoTable? @relation("unlockContractInfo", fields: [unlockInfoID], references: [id]) + submitInfoID String? + submitInfo UpdateInfoTable? @relation("submitContractInfo", fields: [submitInfoID], references: [id]) + + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + submissionType SubmissionType + submissionDescription String + programIDs String[] + populationCovered PopulationCoverageType? + riskBasedContract Boolean? + stateContacts StateContact[] + supportingDocuments ContractSupportingDocument[] + contractType ContractType + contractExecutionStatus ContractExecutionStatus? + contractDocuments ContractDocument[] + contractDateStart DateTime? @db.Date + contractDateEnd DateTime? @db.Date + managedCareEntities ManagedCareEntity[] + federalAuthorities FederalAuthority[] + modifiedBenefitsProvided Boolean? + modifiedGeoAreaServed Boolean? + modifiedMedicaidBeneficiaries Boolean? + modifiedRiskSharingStrategy Boolean? + modifiedIncentiveArrangements Boolean? + modifiedWitholdAgreements Boolean? + modifiedStateDirectedPayments Boolean? + modifiedPassThroughPayments Boolean? + modifiedPaymentsForMentalDiseaseInstitutions Boolean? + modifiedMedicalLossRatioStandards Boolean? + modifiedOtherFinancialPaymentIncentive Boolean? + modifiedEnrollmentProcess Boolean? + modifiedGrevienceAndAppeal Boolean? + modifiedNetworkAdequacyStandards Boolean? + modifiedLengthOfContract Boolean? + modifiedNonRiskPaymentArrangements Boolean? + inLieuServicesAndSettings Boolean? +} + +model RateRevisionTable { + id String @id @default(uuid()) + rateID String + rate RateTable @relation(fields: [rateID], references: [id]) + contractRevisions RateRevisionsOnContractRevisionsTable[] + draftContracts ContractTable[] + + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + unlockInfoID String? + unlockInfo UpdateInfoTable? @relation("unlockRateInfo", fields: [unlockInfoID], references: [id]) + submitInfoID String? + submitInfo UpdateInfoTable? @relation("submitRateInfo", fields: [submitInfoID], references: [id]) + + rateType RateType? + rateCapitationType RateCapitationType? + rateDocuments RateDocument[] + supportingDocuments RateSupportingDocument[] + rateDateStart DateTime? @db.Date + rateDateEnd DateTime? @db.Date + rateDateCertified DateTime? @db.Date + amendmentEffectiveDateStart DateTime? @db.Date + amendmentEffectiveDateEnd DateTime? @db.Date + rateProgramIDs String[] + rateCertificationName String? + certifyingActuaryContacts ActuaryContact[] @relation(name: "CertifyingActuaryOnRateRevision") + addtlActuaryContacts ActuaryContact[] @relation(name: "AddtlActuaryOnRateRevision") + actuaryCommunicationPreference ActuaryCommunication? + packagesWithSharedRateCerts SharedRateCertifications[] +} + +model RateRevisionsOnContractRevisionsTable { + rateRevisionID String + rateRevision RateRevisionTable @relation(fields: [rateRevisionID], references: [id]) + contractRevisionID String + contractRevision ContractRevisionTable @relation(fields: [contractRevisionID], references: [id]) + validAfter DateTime + validUntil DateTime? + updatedAt DateTime @default(now()) @updatedAt + isRemoval Boolean @default(false) + + @@id([rateRevisionID, contractRevisionID, validAfter]) +} + +model UpdateInfoTable { + id String @id @default(uuid()) + updatedAt DateTime + updatedByID String + updatedBy User @relation(fields: [updatedByID], references: [id]) + updatedReason String + unlockedContracts ContractRevisionTable[] @relation("unlockContractInfo") + submittedContracts ContractRevisionTable[] @relation("submitContractInfo") + unlockedRates RateRevisionTable[] @relation("unlockRateInfo") + submittedRates RateRevisionTable[] @relation("submitRateInfo") +} + +model SharedRateCertifications { + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + contract ContractRevisionTable[] + rateRevision RateRevisionTable[] +} + +model ActuaryContact { + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + name String + titleRole String + email String + actuarialFirm ActuarialFirm + actuarialFirmOther String? + rateWithCertifyingActuaryID String? + rateWithAddtlActuaryID String? + rateActuaryCertifying RateRevisionTable? @relation(name: "CertifyingActuaryOnRateRevision", fields: [ rateWithCertifyingActuaryID ], references: [id]) + rateActuaryAddtl RateRevisionTable? @relation(name: "AddtlActuaryOnRateRevision", fields: [ rateWithAddtlActuaryID ], references: [id]) +} + +model ContractDocument { + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + name String + s3URL String + sha256 String? + contractRevisionID String + contractRevision ContractRevisionTable @relation(fields: [contractRevisionID], references: [id]) +} + +model ContractSupportingDocument { + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + name String + s3URL String + sha256 String? + contractRevisionID String + contractRevision ContractRevisionTable @relation(fields: [contractRevisionID], references: [id]) +} + +model RateDocument { + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + name String + s3URL String + sha256 String? + rateRevisionID String + rateRevision RateRevisionTable @relation(fields: [rateRevisionID], references: [id]) +} + +model RateSupportingDocument { + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + name String + s3URL String + sha256 String? + rateRevisionID String + rateRevision RateRevisionTable @relation(fields: [rateRevisionID], references: [id]) +} + +model StateContact { + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + name String + titleRole String + email String + contractRevisionID String + contractRevision ContractRevisionTable @relation(fields: [contractRevisionID], references: [id]) +} + model State { - stateCode String @id + stateCode String @id @default(uuid()) name String latestStateSubmissionNumber Int @default(0) + latestStateRateCertNumber Int @default(0) statePackages HealthPlanPackageTable[] users User[] + contracts ContractTable[] + rates RateTable[] } model User { - id String @id + id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt givenName String @@ -51,12 +264,13 @@ model User { email String role Role divisionAssignment Division? - stateAssignments State[] stateCode String? + stateAssignments State[] questions Question[] responses QuestionResponse[] audits UserAudit[] updatedByAuditEntries UserAudit[] @relation("UpdatedBy") + updateInfos UpdateInfoTable[] } model UserAudit { @@ -73,7 +287,7 @@ model UserAudit { } model Question { - id String @id + id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt pkgID String @@ -86,7 +300,7 @@ model Question { } model QuestionDocument { - id String @id + id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt name String @@ -96,7 +310,7 @@ model QuestionDocument { } model QuestionResponseDocument { - id String @id + id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt response QuestionResponse @relation(fields: [responseID], references: [id]) @@ -106,7 +320,7 @@ model QuestionResponseDocument { } model QuestionResponse { - id String @id + id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt question Question @relation(fields: [questionID], references: [id]) @@ -126,9 +340,79 @@ enum Role { CMS_USER STATE_USER ADMIN_USER + HELPDESK_USER } enum AuditAction { CHANGED_STATE_ASSIGNMENT CHANGED_DIVISION_ASSIGNMENT } + +enum RateType { + NEW + AMENDMENT +} + +enum RateCapitationType { + RATE_CELL + RATE_RANGE +} + +enum ManagedCareEntity { + MCO + PIHP + PAHP + PCCM +} + +enum FederalAuthority { + STATE_PLAN + WAIVER_1915B + WAIVER_1115 + VOLUNTARY + BENCHMARK + TITLE_XXI +} + +enum ContractExecutionStatus { + EXECUTED + UNEXECUTED +} + +enum ContractType { + BASE + AMENDMENT +} + +enum DocumentCategory { + CONTRACT + RATES + CONTRACT_RELATED + RATES_RELATED +} + +enum ActuaryCommunication { + OACT_TO_ACTUARY + OACT_TO_STATE +} + +enum ActuarialFirm { + MERCER + MILLIMAN + OPTUMAS + GUIDEHOUSE + DELOITTE + STATE_IN_HOUSE + OTHER +} + +enum PopulationCoverageType { + MEDICAID + CHIP + MEDICAID_AND_CHIP +} + +enum SubmissionType { + CONTRACT_ONLY + CONTRACT_AND_RATES +} diff --git a/services/app-api/scripts/invoke-migrate-lambda.sh b/services/app-api/scripts/invoke-migrate-lambda.sh index 65aa5791ce..176baecd75 100755 --- a/services/app-api/scripts/invoke-migrate-lambda.sh +++ b/services/app-api/scripts/invoke-migrate-lambda.sh @@ -3,6 +3,7 @@ set -u function_name="$1" lambda_version="${2:-\$LATEST}" +error_message="${3:-}" cli_read_timeout=240 @@ -10,9 +11,9 @@ if (set -x ; aws lambda invoke --qualifier "$lambda_version" --cli-read-timeout exitCode="$(jq '.statusCode' < lambda_response.json)" if [[ "$exitCode" != 200 ]] ; then cat lambda_response.json - echo "Migration of the database failed." 1>&2 + echo "$error_message" 1>&2 exit 1 fi else exit -fi \ No newline at end of file +fi diff --git a/services/app-api/serverless.yml b/services/app-api/serverless.yml index d2ab9dc408..da368f62a2 100644 --- a/services/app-api/serverless.yml +++ b/services/app-api/serverless.yml @@ -163,6 +163,28 @@ functions: - ${self:custom.sgId} subnetIds: ${self:custom.privateSubnets} + proto_to_db: + handler: src/handlers/proto_to_db.main + layers: + - !Ref PrismaClientEngineLambdaLayer + - arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1 + timeout: 300 + vpc: + securityGroupIds: + - ${self:custom.sgId} + subnetIds: ${self:custom.privateSubnets} + + migrate_rate_documents: + handler: src/handlers/migrate_rate_documents.main + layers: + - !Ref PrismaClientEngineLambdaLayer + - arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1 + timeout: 300 + vpc: + securityGroupIds: + - ${self:custom.sgId} + subnetIds: ${self:custom.privateSubnets} + health: handler: src/handlers/health_check.main events: diff --git a/services/app-api/src/authn/authn.ts b/services/app-api/src/authn/authn.ts index 6655d4b27f..9efb168192 100644 --- a/services/app-api/src/authn/authn.ts +++ b/services/app-api/src/authn/authn.ts @@ -1,6 +1,6 @@ -import { Result } from 'neverthrow' -import { UserType } from '../domain-models' -import { Store } from '../postgres' +import type { Result } from 'neverthrow' +import type { UserType } from '../domain-models' +import type { Store } from '../postgres' export type userFromAuthProvider = ( authProvider: string, diff --git a/services/app-api/src/authn/cognitoAuthn.test.ts b/services/app-api/src/authn/cognitoAuthn.test.ts index 2c14214bc2..c4c3c92b8a 100644 --- a/services/app-api/src/authn/cognitoAuthn.test.ts +++ b/services/app-api/src/authn/cognitoAuthn.test.ts @@ -1,6 +1,7 @@ -import { Result, ok, err } from 'neverthrow' +import type { Result } from 'neverthrow' +import { ok, err } from 'neverthrow' import { parseAuthProvider, userTypeFromAttributes } from './cognitoAuthn' -import { UserType } from '../domain-models' +import type { UserType } from '../domain-models' describe('cognitoAuthn', () => { describe('parseAuthProvider', () => { @@ -97,6 +98,22 @@ describe('cognitoAuthn', () => { stateAssignments: [], }), }, + { + attributes: { + 'custom:role': 'macmcrrs-helpdesk', + given_name: 'Generic', + family_name: 'Person', + email: 'gp@example.com', + }, + expectedResult: ok({ + id: testID, + role: 'HELPDESK_USER', + email: 'gp@example.com', + familyName: 'Person', + givenName: 'Generic', + stateAssignments: [], + }), + }, { attributes: { 'custom:role': diff --git a/services/app-api/src/authn/cognitoAuthn.ts b/services/app-api/src/authn/cognitoAuthn.ts index 31acb20410..208d4b6b31 100644 --- a/services/app-api/src/authn/cognitoAuthn.ts +++ b/services/app-api/src/authn/cognitoAuthn.ts @@ -1,13 +1,15 @@ -import { Result, ok, err } from 'neverthrow' +import type { Result } from 'neverthrow' +import { ok, err } from 'neverthrow' +import type { UserType as CognitoUserType } from '@aws-sdk/client-cognito-identity-provider' import { CognitoIdentityProviderClient, ListUsersCommand, - UserType as CognitoUserType, } from '@aws-sdk/client-cognito-identity-provider' -import { UserType } from '../domain-models' +import type { UserType } from '../domain-models' import { performance } from 'perf_hooks' -import { Store, InsertUserArgsType, isStoreError } from '../postgres' +import type { Store, InsertUserArgsType } from '../postgres' +import { isStoreError } from '../postgres' import { isValidCmsDivison } from '../domain-models' export function parseAuthProvider( @@ -82,6 +84,7 @@ async function fetchUserFromCognito( const CMS_ROLE_ATTRIBUTE = 'macmcrrs-cms-user' const STATE_ROLE_ATTRIBUTE = 'macmcrrs-state-user' const ADMIN_ROLE_ATTRIBUTE = 'macmcrrs-approver' +const HELPDESK_ROLE_ATTRIBUTE = 'macmcrrs-helpdesk' export function userTypeFromAttributes( id: string, @@ -156,6 +159,17 @@ export function userTypeFromAttributes( }) } + if (roles.includes(HELPDESK_ROLE_ATTRIBUTE)) { + return ok({ + id, + role: 'HELPDESK_USER', + email: attributes.email, + givenName: attributes.given_name, + familyName: attributes.family_name, + stateAssignments: [], + }) + } + return err(new Error('Unsupported user role: ' + roleAttribute)) } diff --git a/services/app-api/src/authn/index.ts b/services/app-api/src/authn/index.ts index cf6e2c7a29..485ebb656a 100644 --- a/services/app-api/src/authn/index.ts +++ b/services/app-api/src/authn/index.ts @@ -1,4 +1,4 @@ -export { userFromAuthProvider } from './authn' +export type { userFromAuthProvider } from './authn' export { userFromCognitoAuthProvider, lookupUserAurora } from './cognitoAuthn' diff --git a/services/app-api/src/authn/localAuthn.ts b/services/app-api/src/authn/localAuthn.ts index 5a9e0d547b..b0ccbc66fb 100644 --- a/services/app-api/src/authn/localAuthn.ts +++ b/services/app-api/src/authn/localAuthn.ts @@ -1,6 +1,8 @@ -import { Result, ok, err } from 'neverthrow' -import { UserType } from '../domain-models/index' -import { Store, InsertUserArgsType, isStoreError } from '../postgres' +import type { Result } from 'neverthrow' +import { ok, err } from 'neverthrow' +import type { UserType } from '../domain-models/index' +import type { Store, InsertUserArgsType } from '../postgres' +import { isStoreError } from '../postgres' import { lookupUserAurora } from './cognitoAuthn' export async function userFromLocalAuthProvider( diff --git a/services/app-api/src/domain-models/HealthPlanPackageType.d.ts b/services/app-api/src/domain-models/HealthPlanPackageType.d.ts index f6c33bf170..283ed1d008 100644 --- a/services/app-api/src/domain-models/HealthPlanPackageType.d.ts +++ b/services/app-api/src/domain-models/HealthPlanPackageType.d.ts @@ -1,4 +1,4 @@ -import { IndexQuestionsPayload } from './QuestionsType' +import type { IndexQuestionsPayload } from './QuestionsType' type HealthPlanPackageStatusType = | 'DRAFT' @@ -27,7 +27,7 @@ type HealthPlanRevisionType = { formDataProto: Uint8Array } -export { +export type { HealthPlanPackageStatusType, HealthPlanPackageType, UpdateInfoType, diff --git a/services/app-api/src/domain-models/QuestionResponseType.ts b/services/app-api/src/domain-models/QuestionResponseType.ts index dc4127c4eb..6faa2de340 100644 --- a/services/app-api/src/domain-models/QuestionResponseType.ts +++ b/services/app-api/src/domain-models/QuestionResponseType.ts @@ -1,4 +1,4 @@ -import { StateUserType } from './UserType' +import type { StateUserType } from './UserType' type QuestionResponseDocument = { name: string diff --git a/services/app-api/src/domain-models/QuestionsType.ts b/services/app-api/src/domain-models/QuestionsType.ts index 93df247ff0..7849aca2ee 100644 --- a/services/app-api/src/domain-models/QuestionsType.ts +++ b/services/app-api/src/domain-models/QuestionsType.ts @@ -1,6 +1,6 @@ -import { CMSUserType } from './UserType' -import { QuestionResponseType } from './QuestionResponseType' -import { DivisionType } from './DivisionType' +import type { CMSUserType } from './UserType' +import type { QuestionResponseType } from './QuestionResponseType' +import type { DivisionType } from './DivisionType' type Document = { name: string diff --git a/services/app-api/src/domain-models/UserType.d.ts b/services/app-api/src/domain-models/UserType.d.ts index 13618e7ae2..3af2242568 100644 --- a/services/app-api/src/domain-models/UserType.d.ts +++ b/services/app-api/src/domain-models/UserType.d.ts @@ -1,7 +1,7 @@ -import { StateType } from './StateType' -import { DivisionType } from './DivisionType' +import type { StateType } from './StateType' +import type { DivisionType } from './DivisionType' -type UserType = StateUserType | CMSUserType | AdminUserType +type UserType = StateUserType | CMSUserType | AdminUserType | HelpdeskUserType type StateUserType = { id: string @@ -30,4 +30,18 @@ type AdminUserType = { familyName: string } -export type { CMSUserType, StateUserType, AdminUserType, UserType } +type HelpdeskUserType = { + id: string + role: 'HELPDESK_USER' + email: string + givenName: string + familyName: string +} + +export type { + CMSUserType, + StateUserType, + AdminUserType, + HelpdeskUserType, + UserType, +} diff --git a/services/app-api/src/domain-models/contractAndRates/contractTypes.ts b/services/app-api/src/domain-models/contractAndRates/contractTypes.ts new file mode 100644 index 0000000000..1b251072b8 --- /dev/null +++ b/services/app-api/src/domain-models/contractAndRates/contractTypes.ts @@ -0,0 +1,100 @@ +import { z } from 'zod' +import { + contractExecutionStatusSchema, + contractTypeSchema, + federalAuthoritySchema, + populationCoveredSchema, + stateContactSchema, + submissionDocumentSchema, + submissionTypeSchema, +} from '../../../../app-web/src/common-code/proto/healthPlanFormDataProto/zodSchemas' +import { ratesRevisionSchema } from './rateTypes' +import { updateInfoSchema } from './updateInfoType' + +const contractFormDataSchema = z.object({ + programIDs: z.array(z.string()), + populationCovered: populationCoveredSchema.optional(), + submissionType: submissionTypeSchema, + riskBasedContract: z.boolean().optional(), + submissionDescription: z.string(), + stateContacts: z.array(stateContactSchema), + supportingDocuments: z.array(submissionDocumentSchema), + contractType: contractTypeSchema, + contractExecutionStatus: contractExecutionStatusSchema.optional(), + contractDocuments: z.array(submissionDocumentSchema), + contractDateStart: z.date().optional(), + contractDateEnd: z.date().optional(), + managedCareEntities: z.array(z.string()), + federalAuthorities: z.array(federalAuthoritySchema), + inLieuServicesAndSettings: z.boolean().optional(), + modifiedBenefitsProvided: z.boolean().optional(), + modifiedGeoAreaServed: z.boolean().optional(), + modifiedMedicaidBeneficiaries: z.boolean().optional(), + modifiedRiskSharingStrategy: z.boolean().optional(), + modifiedIncentiveArrangements: z.boolean().optional(), + modifiedWitholdAgreements: z.boolean().optional(), + modifiedStateDirectedPayments: z.boolean().optional(), + modifiedPassThroughPayments: z.boolean().optional(), + modifiedPaymentsForMentalDiseaseInstitutions: z.boolean().optional(), + modifiedMedicalLossRatioStandards: z.boolean().optional(), + modifiedOtherFinancialPaymentIncentive: z.boolean().optional(), + modifiedEnrollmentProcess: z.boolean().optional(), + modifiedGrevienceAndAppeal: z.boolean().optional(), + modifiedNetworkAdequacyStandards: z.boolean().optional(), + modifiedLengthOfContract: z.boolean().optional(), + modifiedNonRiskPaymentArrangements: z.boolean().optional(), +}) + +const contractRevisionSchema = z.object({ + id: z.string().uuid(), + submitInfo: updateInfoSchema.optional(), + unlockInfo: updateInfoSchema.optional(), + createdAt: z.date(), + updatedAt: z.date(), + formData: contractFormDataSchema, +}) + +// ContractRevision has all the information in a single submission of this contract. +// If a revision has been submitted it will have submitInfo (otherwise it will be a draft) +// if a revision was unlocked, it will have unlock info, otherwise it was an initial submission +// The set of rateRevisions hold exactly what rate data was present at the time this contract was submitted. +const contractRevisionWithRatesSchema = contractRevisionSchema.extend({ + rateRevisions: z.array(ratesRevisionSchema), +}) + +// Contract represents the contract specific information in a submission package +// All that data is contained in revisions, each revision represents the data in a single submission +// submissions are kept intact here across time +const contractSchema = z.object({ + id: z.string().uuid(), + status: z.union([z.literal('SUBMITTED'), z.literal('DRAFT')]), + stateCode: z.string(), + stateNumber: z.number().min(1), + revisions: z.array(contractRevisionWithRatesSchema), +}) + +const draftContractSchema = contractSchema.extend({ + status: z.literal('DRAFT'), + revisions: z.array(contractRevisionWithRatesSchema).min(1), +}) + +type ContractType = z.infer +type ContractRevisionType = z.infer +type ContractRevisionWithRatesType = z.infer< + typeof contractRevisionWithRatesSchema +> +type ContractFormDataType = z.infer + +export { + contractRevisionSchema, + contractRevisionWithRatesSchema, + draftContractSchema, + contractSchema, +} + +export type { + ContractType, + ContractRevisionType, + ContractRevisionWithRatesType, + ContractFormDataType, +} diff --git a/services/app-api/src/domain-models/contractAndRates/index.ts b/services/app-api/src/domain-models/contractAndRates/index.ts new file mode 100644 index 0000000000..df42044686 --- /dev/null +++ b/services/app-api/src/domain-models/contractAndRates/index.ts @@ -0,0 +1,22 @@ +export type { + RateType, + RateRevisionType, + RateRevisionWithContractsType, + RateFormDataType, +} from './rateTypes' + +export { + contractSchema, + contractRevisionSchema, + contractRevisionWithRatesSchema, + draftContractSchema, +} from './contractTypes' + +export type { + ContractType, + ContractRevisionType, + ContractRevisionWithRatesType, + ContractFormDataType, +} from './contractTypes' + +export type { ContractStatusType, UpdateInfoType } from './updateInfoType' diff --git a/services/app-api/src/domain-models/contractAndRates/rateTypes.ts b/services/app-api/src/domain-models/contractAndRates/rateTypes.ts new file mode 100644 index 0000000000..be99af0add --- /dev/null +++ b/services/app-api/src/domain-models/contractAndRates/rateTypes.ts @@ -0,0 +1,71 @@ +import { z } from 'zod' +import { + actuaryCommunicationTypeSchema, + actuaryContactSchema, + rateCapitationTypeSchema, + rateTypeSchema, + sharedRateCertDisplay, + submissionDocumentSchema, +} from '../../../../app-web/src/common-code/proto/healthPlanFormDataProto/zodSchemas' +import { contractRevisionSchema } from './contractTypes' +import { updateInfoSchema } from './updateInfoType' + +// The rate form data is the form filled out by state users submitting rates for review +const rateFormDataSchema = z.object({ + id: z.string().optional(), + rateType: rateTypeSchema.optional(), + rateCapitationType: rateCapitationTypeSchema.optional(), + rateDocuments: z.array(submissionDocumentSchema).optional(), + supportingDocuments: z.array(submissionDocumentSchema).optional(), + rateDateStart: z.date().optional(), + rateDateEnd: z.date().optional(), + rateDateCertified: z.date().optional(), + amendmentEffectiveDateStart: z.date().optional(), + amendmentEffectiveDateEnd: z.date().optional(), + rateProgramIDs: z.array(z.string()).optional(), + rateCertificationName: z.string().optional(), + certifyingActuaryContacts: z.array(actuaryContactSchema).optional(), + addtlActuaryContacts: z.array(actuaryContactSchema).optional(), + actuaryCommunicationPreference: actuaryCommunicationTypeSchema.optional(), + packagesWithSharedRateCerts: z.array(sharedRateCertDisplay).optional(), +}) + +// A Rate represents all the data associated with a single rate certification over time. +// The rate's revisions field hold the array of rate revisions that show change history of specific rate data +// The first revision (array index 0) is the current revision +const ratesRevisionSchema = z.object({ + id: z.string().uuid(), + submitInfo: updateInfoSchema.optional(), + unlockInfo: updateInfoSchema.optional(), + createdAt: z.date(), + updatedAt: z.date(), + formData: rateFormDataSchema, +}) + +const rateRevisionWithContractsSchema = ratesRevisionSchema.extend({ + contractRevisions: z.array(contractRevisionSchema), +}) + +const rateSchema = z.object({ + id: z.string().uuid(), + status: z.union([z.literal('SUBMITTED'), z.literal('DRAFT')]), + stateCode: z.string(), + stateNumber: z.number().min(1), + revisions: z.array(rateRevisionWithContractsSchema), +}) + +type RateType = z.infer +type RateRevisionType = z.infer +type RateRevisionWithContractsType = z.infer< + typeof rateRevisionWithContractsSchema +> +type RateFormDataType = z.infer + +export { ratesRevisionSchema } + +export type { + RateType, + RateRevisionType, + RateRevisionWithContractsType, + RateFormDataType, +} diff --git a/services/app-api/src/domain-models/contractAndRates/updateInfoType.ts b/services/app-api/src/domain-models/contractAndRates/updateInfoType.ts new file mode 100644 index 0000000000..5dff83667e --- /dev/null +++ b/services/app-api/src/domain-models/contractAndRates/updateInfoType.ts @@ -0,0 +1,15 @@ +import { z } from 'zod' +import type { contractSchema } from './contractTypes' + +const updateInfoSchema = z.object({ + updatedAt: z.date(), + updatedBy: z.string().email(), + updatedReason: z.string(), +}) + +type UpdateInfoType = z.infer +type ContractStatusType = z.infer + +export type { ContractStatusType, UpdateInfoType } + +export { updateInfoSchema } diff --git a/services/app-api/src/domain-models/division.ts b/services/app-api/src/domain-models/division.ts index af052c26c0..856c7845bd 100644 --- a/services/app-api/src/domain-models/division.ts +++ b/services/app-api/src/domain-models/division.ts @@ -1,4 +1,4 @@ -import { DivisionType } from './DivisionType' +import type { DivisionType } from './DivisionType' function isValidCmsDivison(division: string): division is DivisionType { return ['DMCO', 'DMCP', 'OACT'].includes(division) diff --git a/services/app-api/src/domain-models/healthPlanPackage.test.ts b/services/app-api/src/domain-models/healthPlanPackage.test.ts index 511cee5e6a..8b48fdef43 100644 --- a/services/app-api/src/domain-models/healthPlanPackage.test.ts +++ b/services/app-api/src/domain-models/healthPlanPackage.test.ts @@ -3,7 +3,7 @@ import { packageSubmittedAt, packageSubmitters, } from './healthPlanPackage' -import { +import type { HealthPlanPackageStatusType, HealthPlanPackageType, } from './HealthPlanPackageType' diff --git a/services/app-api/src/domain-models/healthPlanPackage.ts b/services/app-api/src/domain-models/healthPlanPackage.ts index f4a3b817b9..9af6d3301c 100644 --- a/services/app-api/src/domain-models/healthPlanPackage.ts +++ b/services/app-api/src/domain-models/healthPlanPackage.ts @@ -1,9 +1,18 @@ -import { +import type { HealthPlanRevisionType, HealthPlanPackageStatusType, HealthPlanPackageType, } from './HealthPlanPackageType' import { pruneDuplicateEmails } from '../emailer/formatters' +import type { ContractType } from './contractAndRates' +import type { + SubmissionDocument, + UnlockedHealthPlanFormDataType, +} from '../../../app-web/src/common-code/healthPlanFormDataType' +import { + toProtoBuffer, + toDomain, +} from '../../../app-web/src/common-code/proto/healthPlanFormDataProto' // submissionStatus computes the current status of the submission based on // the submit/unlock info on its revisions. @@ -60,9 +69,146 @@ function packageSubmitters(pkg: HealthPlanPackageType): string[] { return pruneDuplicateEmails(submitters) } +function convertContractToUnlockedHealthPlanPackage( + contract: ContractType +): HealthPlanPackageType | Error { + console.info('Attempting to convert contract to health plan package') + + const healthPlanRevisions = + convertContractRevisionToHealthPlanRevision(contract) + + if (healthPlanRevisions instanceof Error) { + return healthPlanRevisions + } + + return { + id: contract.id, + stateCode: contract.stateCode, + revisions: healthPlanRevisions, + } +} + +function convertContractRevisionToHealthPlanRevision( + contract: ContractType +): HealthPlanRevisionType[] | Error { + if (contract.status !== 'DRAFT') { + return new Error( + `Contract with ID: ${contract.id} status is not "DRAFT". Cannot convert to unlocked health plan package` + ) + } + + let healthPlanRevisions: HealthPlanRevisionType[] | Error = [] + for (const contractRev of contract.revisions) { + const unlockedHealthPlanFormData: UnlockedHealthPlanFormDataType = { + id: contractRev.id, + createdAt: contractRev.createdAt, + updatedAt: contractRev.updatedAt, + status: contract.status, + stateCode: contract.stateCode, + stateNumber: contract.stateNumber, + programIDs: contractRev.formData.programIDs, + populationCovered: contractRev.formData.populationCovered, + submissionType: contractRev.formData.submissionType, + riskBasedContract: contractRev.formData.riskBasedContract, + submissionDescription: contractRev.formData.submissionDescription, + stateContacts: contractRev.formData.stateContacts, + addtlActuaryCommunicationPreference: undefined, + addtlActuaryContacts: [], + documents: contractRev.formData.supportingDocuments.map((doc) => ({ + ...doc, + documentCategories: doc.documentCategories.filter( + (category) => category !== undefined + ), + })) as SubmissionDocument[], + contractType: contractRev.formData.contractType, + contractExecutionStatus: + contractRev.formData.contractExecutionStatus, + contractDocuments: contractRev.formData.contractDocuments.map( + (doc) => ({ + ...doc, + documentCategories: doc.documentCategories.filter( + (category) => category !== undefined + ), + }) + ) as SubmissionDocument[], + contractDateStart: contractRev.formData.contractDateStart, + contractDateEnd: contractRev.formData.contractDateEnd, + managedCareEntities: contractRev.formData.managedCareEntities, + federalAuthorities: contractRev.formData.federalAuthorities, + contractAmendmentInfo: { + modifiedProvisions: { + inLieuServicesAndSettings: + contractRev.formData.inLieuServicesAndSettings, + modifiedBenefitsProvided: + contractRev.formData.modifiedBenefitsProvided, + modifiedGeoAreaServed: + contractRev.formData.modifiedGeoAreaServed, + modifiedMedicaidBeneficiaries: + contractRev.formData.modifiedMedicaidBeneficiaries, + modifiedRiskSharingStrategy: + contractRev.formData.modifiedRiskSharingStrategy, + modifiedIncentiveArrangements: + contractRev.formData.modifiedIncentiveArrangements, + modifiedWitholdAgreements: + contractRev.formData.modifiedWitholdAgreements, + modifiedStateDirectedPayments: + contractRev.formData.modifiedStateDirectedPayments, + modifiedPassThroughPayments: + contractRev.formData.modifiedPassThroughPayments, + modifiedPaymentsForMentalDiseaseInstitutions: + contractRev.formData + .modifiedPaymentsForMentalDiseaseInstitutions, + modifiedMedicalLossRatioStandards: + contractRev.formData.modifiedMedicalLossRatioStandards, + modifiedOtherFinancialPaymentIncentive: + contractRev.formData + .modifiedOtherFinancialPaymentIncentive, + modifiedEnrollmentProcess: + contractRev.formData.modifiedEnrollmentProcess, + modifiedGrevienceAndAppeal: + contractRev.formData.modifiedGrevienceAndAppeal, + modifiedNetworkAdequacyStandards: + contractRev.formData.modifiedNetworkAdequacyStandards, + modifiedLengthOfContract: + contractRev.formData.modifiedLengthOfContract, + modifiedNonRiskPaymentArrangements: + contractRev.formData.modifiedNonRiskPaymentArrangements, + }, + }, + rateInfos: [], + } + + const formDataProto = toProtoBuffer(unlockedHealthPlanFormData) + + // check that we can encode then decode with no issues + const domainData = toDomain(formDataProto) + + // If any revision has en error in decoding we break the loop and return an error + if (domainData instanceof Error) { + healthPlanRevisions = new Error( + `Could not convert contract revision with ID: ${contractRev.id} to health plan package revision: ${domainData}` + ) + break + } + + const healthPlanRevision: HealthPlanRevisionType = { + id: contractRev.id, + unlockInfo: contractRev.unlockInfo, + submitInfo: contractRev.submitInfo, + createdAt: contractRev.createdAt, + formDataProto, + } + + healthPlanRevisions.push(healthPlanRevision) + } + + return healthPlanRevisions +} + export { packageCurrentRevision, packageStatus, packageSubmittedAt, packageSubmitters, + convertContractToUnlockedHealthPlanPackage, } diff --git a/services/app-api/src/domain-models/index.ts b/services/app-api/src/domain-models/index.ts index d13cbfe951..a911f6aff2 100644 --- a/services/app-api/src/domain-models/index.ts +++ b/services/app-api/src/domain-models/index.ts @@ -23,6 +23,7 @@ export { packageStatus, packageSubmittedAt, packageSubmitters, + convertContractToUnlockedHealthPlanPackage, } from './healthPlanPackage' export type { diff --git a/services/app-api/src/domain-models/user.ts b/services/app-api/src/domain-models/user.ts index 786b8a27f4..9da6f2973c 100644 --- a/services/app-api/src/domain-models/user.ts +++ b/services/app-api/src/domain-models/user.ts @@ -1,5 +1,11 @@ -import { StateUserType, CMSUserType, UserType, AdminUserType } from './UserType' -import { User as PrismaUser } from '@prisma/client' +import type { + StateUserType, + CMSUserType, + UserType, + AdminUserType, + HelpdeskUserType, +} from './UserType' +import type { User as PrismaUser } from '@prisma/client' function isUser(user: unknown): user is UserType { if (user && typeof user === 'object') { @@ -31,10 +37,16 @@ function isAdminUser(user: UserType): user is AdminUserType { return user.role === 'ADMIN_USER' } +function isHelpdeskUser(user: UserType): user is HelpdeskUserType { + return user.role === 'HELPDESK_USER' +} + function toDomainUser(user: PrismaUser): UserType { switch (user.role) { case 'ADMIN_USER': return user as AdminUserType + case 'HELPDESK_USER': + return user as HelpdeskUserType case 'CMS_USER': return { id: user.id, @@ -50,4 +62,11 @@ function toDomainUser(user: PrismaUser): UserType { } } -export { isUser, isCMSUser, isStateUser, isAdminUser, toDomainUser } +export { + isUser, + isCMSUser, + isStateUser, + isAdminUser, + toDomainUser, + isHelpdeskUser, +} diff --git a/services/app-api/src/emailer/awsSES.ts b/services/app-api/src/emailer/awsSES.ts index 474c66ab06..c7f4d8ed49 100644 --- a/services/app-api/src/emailer/awsSES.ts +++ b/services/app-api/src/emailer/awsSES.ts @@ -1,11 +1,10 @@ -import { - SESClient, +import type { SESServiceException, SendEmailRequest, SendEmailResponse, - SendEmailCommand, } from '@aws-sdk/client-ses' -import { EmailData } from './' +import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses' +import type { EmailData } from './' const ses = new SESClient({ region: 'us-east-1' }) diff --git a/services/app-api/src/emailer/emailer.ts b/services/app-api/src/emailer/emailer.ts index cf4ba47553..696206d713 100644 --- a/services/app-api/src/emailer/emailer.ts +++ b/services/app-api/src/emailer/emailer.ts @@ -9,11 +9,11 @@ import { resubmitPackageStateEmail, resubmitPackageCMSEmail, } from './' -import { +import type { LockedHealthPlanFormDataType, UnlockedHealthPlanFormDataType, } from '../../../app-web/src/common-code/healthPlanFormDataType' -import { UpdateInfoType, ProgramType } from '../domain-models' +import type { UpdateInfoType, ProgramType } from '../domain-models' import { SESServiceException } from '@aws-sdk/client-ses' // See more discussion of configuration in docs/Configuration.md diff --git a/services/app-api/src/emailer/emails/__snapshots__/newPackageCMSEmail.test.ts.snap b/services/app-api/src/emailer/emails/__snapshots__/newPackageCMSEmail.test.ts.snap index 4d57d403fe..4fda6c5afa 100644 --- a/services/app-api/src/emailer/emails/__snapshots__/newPackageCMSEmail.test.ts.snap +++ b/services/app-api/src/emailer/emails/__snapshots__/newPackageCMSEmail.test.ts.snap @@ -14,6 +14,6 @@ exports[`renders overall email as expected 1`] = `
Submission description: A submitted submission

-
View submission +View submission " `; diff --git a/services/app-api/src/emailer/emails/__snapshots__/newPackageStateEmail.test.ts.snap b/services/app-api/src/emailer/emails/__snapshots__/newPackageStateEmail.test.ts.snap index 346471e872..5b1f7bae9d 100644 --- a/services/app-api/src/emailer/emails/__snapshots__/newPackageStateEmail.test.ts.snap +++ b/services/app-api/src/emailer/emails/__snapshots__/newPackageStateEmail.test.ts.snap @@ -11,7 +11,7 @@ exports[`renders overall email for a new package with a rate amendment as expect
Submission description: A submitted submission

-View submission +View submission

If you need to make any changes, please contact CMS.

diff --git a/services/app-api/src/emailer/emails/__snapshots__/resubmitPackageCMSEmail.test.ts.snap b/services/app-api/src/emailer/emails/__snapshots__/resubmitPackageCMSEmail.test.ts.snap index bf1a9de0c7..632d740277 100644 --- a/services/app-api/src/emailer/emails/__snapshots__/resubmitPackageCMSEmail.test.ts.snap +++ b/services/app-api/src/emailer/emails/__snapshots__/resubmitPackageCMSEmail.test.ts.snap @@ -7,11 +7,11 @@ exports[`renders overall email as expected 1`] = ` Updated on: 02/01/2022
Changes made: Added more contract details.
Rate names: -