diff --git a/ppr-ui/src/components/common/ButtonFooter.vue b/ppr-ui/src/components/common/ButtonFooter.vue index ab2f39afb..3ed15a063 100644 --- a/ppr-ui/src/components/common/ButtonFooter.vue +++ b/ppr-ui/src/components/common/ButtonFooter.vue @@ -121,7 +121,7 @@ import { ButtonConfigIF, DialogOptionsIF, DraftIF, ErrorIF, FinancingStatementIF, RegTableNewItemI, StateModelIF } from '@/interfaces' import { unsavedChangesDialog } from '@/resources/dialogOptions' -import { useNavigation, useNewMhrRegistration } from '@/composables' +import { useMhrCorrections, useNavigation, useNewMhrRegistration } from '@/composables' import { storeToRefs } from 'pinia' export default defineComponent({ @@ -174,10 +174,13 @@ export default defineComponent({ hasUnsavedChanges, isRoleStaffBcol, isRoleStaffReg, - isRoleStaffSbc + isRoleStaffSbc, + getMhrInformation } = storeToRefs(useStore()) const { mhrDraftHandler } = useNewMhrRegistration() + const { isMhrCorrection } = useMhrCorrections() + const localState = reactive({ options: props.baseDialogOptions as DialogOptionsIF || unsavedChangesDialog, showCancelDialog: false, @@ -229,6 +232,7 @@ export default defineComponent({ const saveDraft = async (): Promise => { let draft let prevDraftId + localState.submitting = true if (props.isMhr) { draft = await mhrDraftHandler() @@ -248,7 +252,8 @@ export default defineComponent({ const newItem: RegTableNewItemI = { addedReg: draft.financingStatement?.documentId || draft.draftNumber, - addedRegParent: '', + // adding mhrNumber will scroll to draft mhr correction + addedRegParent: isMhrCorrection.value ? getMhrInformation.value.mhrNumber : '', addedRegSummary: null, prevDraft: prevDraftId } diff --git a/ppr-ui/src/components/common/RegistrationsWrapper.vue b/ppr-ui/src/components/common/RegistrationsWrapper.vue index 6e97cec11..fcf0be3b9 100644 --- a/ppr-ui/src/components/common/RegistrationsWrapper.vue +++ b/ppr-ui/src/components/common/RegistrationsWrapper.vue @@ -282,7 +282,7 @@ import { } from '@/resources/dialogOptions' import { StatusCodes } from 'http-status-codes' import { cloneDeep } from 'lodash' -import { useExemptions, useNavigation, useNewMhrRegistration } from '@/composables' +import { useExemptions, useMhrCorrections, useNavigation, useNewMhrRegistration } from '@/composables' export default defineComponent({ name: 'RegistrationsWrapper', @@ -338,6 +338,9 @@ export default defineComponent({ initNewManufacturerMhr, fetchMhRegistrations } = useNewMhrRegistration(true) + + const { initDraftMhrCorrection } = useMhrCorrections() + const { goToExemptions } = useExemptions() const localState = reactive({ @@ -705,6 +708,16 @@ export default defineComponent({ } openMhr(mhrInfo) break + case TableActions.OPEN_DRAFT_CORRECTION: + if (mhrInfo.outOfDate) { + // Handle stale drafts before opening the MHR when flagged as outOfDate + localState.staleDraftId = mhrInfo?.draftNumber + localState.mhrWithDraftId = mhrInfo?.mhrNumber + localState.staleDraftDialogDisplay = true + return + } + openDraftMhrCorrection(mhrInfo) + break case UnitNoteDocTypes.RESIDENTIAL_EXEMPTION_ORDER: case UnitNoteDocTypes.NON_RESIDENTIAL_EXEMPTION: openMhrExemption(mhrInfo, action) @@ -755,6 +768,12 @@ export default defineComponent({ await router.replace({ name: RouteNames.MHR_INFORMATION }) } + const openDraftMhrCorrection = async (draftMhrCorrection) => { + await initDraftMhrCorrection(draftMhrCorrection) + // Navigate to MHR Corrections home route + goToRoute(RouteNames.SUBMITTING_PARTY) + } + const openMhrExemption = async (mhrSummary: MhRegistrationSummaryIF, type: UnitNoteDocTypes): Promise => { await setMhrInformation(mhrSummary) await goToExemptions(type) diff --git a/ppr-ui/src/components/tables/common/TableRow.vue b/ppr-ui/src/components/tables/common/TableRow.vue index b45c581d2..71fa05b67 100644 --- a/ppr-ui/src/components/tables/common/TableRow.vue +++ b/ppr-ui/src/components/tables/common/TableRow.vue @@ -879,10 +879,22 @@ export default defineComponent({ } const openMhr = (item: MhRegistrationSummaryIF): void => { + let action: TableActions + + switch (item.registrationType) { + case APIMhrTypes.REGISTRY_STAFF_ADMIN: + action = TableActions.OPEN_DRAFT_CORRECTION + break + case APIMhrTypes.MANUFACTURED_HOME_REGISTRATION: + action = item.draftNumber ? TableActions.EDIT_NEW_MHR : TableActions.OPEN_MHR + break + default: + action = TableActions.OPEN_MHR + break + } + emit('action', { - action: (item.registrationType === APIMhrTypes.MANUFACTURED_HOME_REGISTRATION && item.draftNumber) - ? TableActions.EDIT_NEW_MHR - : TableActions.OPEN_MHR, + action: action, mhrInfo: item }) } diff --git a/ppr-ui/src/composables/mhrRegistration/useMhrCorrections.ts b/ppr-ui/src/composables/mhrRegistration/useMhrCorrections.ts index 60f23226c..a66f57382 100755 --- a/ppr-ui/src/composables/mhrRegistration/useMhrCorrections.ts +++ b/ppr-ui/src/composables/mhrRegistration/useMhrCorrections.ts @@ -6,7 +6,8 @@ import { deleteEmptyProperties, fetchMhRegistration, fromDisplayPhone, - getFeatureFlag + getFeatureFlag, + getMhrDraft } from '@/utils' import { ActionTypes, APIRegistrationTypes, HomeCertificationOptions, RouteNames } from '@/enums' import { useNavigation, useNewMhrRegistration } from '@/composables' @@ -18,11 +19,14 @@ import { UpdatedBadgeIF } from '@/interfaces' import { cloneDeep, omit } from 'lodash' +import { MhrCorrectionClient, MhrCorrectionStaff } from '@/resources/registrationTypes' export const useMhrCorrections = () => { const { setMhrBaseline, setRegistrationType, + setMhrDraftNumber, + setMhrStatusType } = useStore() const { getMhrStatusType, @@ -39,7 +43,7 @@ export const useMhrCorrections = () => { } = storeToRefs(useStore()) const { containsCurrentRoute, goToRoute } = useNavigation() - const { initDraftOrCurrentMhr } = useNewMhrRegistration(true) + // const { initDraftOrCurrentMhr } = useNewMhrRegistration(true) /** Returns true for staff when the feature flag is enabled **/ const isMhrChangesEnabled: ComputedRef = computed((): boolean => { @@ -217,9 +221,9 @@ export const useMhrCorrections = () => { // Fetch current MHR Data const { data } = await fetchMhRegistration(getMhrInformation.value.mhrNumber) - // Handle 'certificationOption' or 'noCertification' value mapping (because it's not returner in response) - const certificationOption = (data?.description?.csaNumber && HomeCertificationOptions.CSA) || - (data?.description?.engineerName && HomeCertificationOptions.ENGINEER_INSPECTION) || null + // Handle 'certificationOption' or 'noCertification' value mapping (because it's not returned in response) + const certificationOption = (data?.description?.csaNumber && HomeCertificationOptions.CSA) || + (data?.description?.engineerName && HomeCertificationOptions.ENGINEER_INSPECTION) || null // Preserve MHR snapshot await setMhrBaseline(cloneDeep({ @@ -233,12 +237,48 @@ export const useMhrCorrections = () => { })) // Set Current Registration to filing state - await initDraftOrCurrentMhr(data, true) + await useNewMhrRegistration(true).initDraftOrCurrentMhr(data, true) // Navigate to MHR home route await goToRoute(RouteNames.SUBMITTING_PARTY) } + const initDraftMhrCorrection = async (draftMhrCorrection): Promise => { + + const draftNumber = draftMhrCorrection.draftNumber + + // Fetch draft MHR Data + const { registration } = await getMhrDraft(draftNumber) + // Fetch original MHR Data (before the draft correction updates) + const { data } = await fetchMhRegistration(draftMhrCorrection.mhrNumber) + + const correctionType: RegistrationTypeIF = [MhrCorrectionStaff, MhrCorrectionClient] + .find((corr: RegistrationTypeIF) => corr.registrationTypeAPI === registration.documentType) + + setRegistrationType(correctionType) + setMhrDraftNumber(draftNumber) + + // Handle 'certificationOption' or 'noCertification' value mapping (because it's not returned in response) + const certificationOption = (data?.description?.csaNumber && HomeCertificationOptions.CSA) || + (data?.description?.engineerName && HomeCertificationOptions.ENGINEER_INSPECTION) || null + + // Set MHR data as baseline state + await setMhrBaseline(cloneDeep({ + ...data, + description: { + ...data.description, + certificationOption: certificationOption, + hasNoCertification: certificationOption === null, + }, + statusType: data?.status + })) + + await setMhrStatusType(data?.status) + + // Set draft registration as current state + await useNewMhrRegistration(true).initDraftOrCurrentMhr(registration) + } + /** * Corrects the details of a given home section. * This function modifies the `homeSectionToCorrect` object directly by adjusting its @@ -337,6 +377,7 @@ export const useMhrCorrections = () => { correctAmendLabel, hasMadeMhrCorrections, initMhrCorrection, + initDraftMhrCorrection, correctHomeSection, buildLocationChange, buildCorrectionPayload diff --git a/ppr-ui/src/composables/mhrRegistration/useNewMhrRegistration.ts b/ppr-ui/src/composables/mhrRegistration/useNewMhrRegistration.ts index 39fd8dadb..694058830 100644 --- a/ppr-ui/src/composables/mhrRegistration/useNewMhrRegistration.ts +++ b/ppr-ui/src/composables/mhrRegistration/useNewMhrRegistration.ts @@ -12,7 +12,13 @@ import { MhrDraftIF , StaffPaymentIF } from '@/interfaces' -import { APIMhrTypes, HomeTenancyTypes, HomeLocationTypes, MhApiStatusTypes, HomeCertificationOptions } from '@/enums' +import { + APIMhrTypes, + HomeTenancyTypes, + HomeLocationTypes, + MhApiStatusTypes, + HomeCertificationOptions +} from '@/enums' import { cleanEmpty, createMhrDraft, @@ -23,7 +29,7 @@ import { updateMhrDraft } from '@/utils' import { orderBy } from 'lodash' -import { useHomeOwners } from '@/composables' +import { useHomeOwners, useMhrCorrections } from '@/composables' export const useNewMhrRegistration = (isMhrCorrections: boolean = false) => { const { @@ -53,13 +59,17 @@ export const useNewMhrRegistration = (isMhrCorrections: boolean = false) => { getMhrRegistrationHomeOwnerGroups, getMhrRegistrationOwnLand, getStaffPayment, - getMhrDraftNumber + getMhrDraftNumber, + getRegistrationType, + getMhrInformation } = storeToRefs(useStore()) const { setShowGroups, getHomeTenancyType } = useHomeOwners(false, isMhrCorrections) + const { isMhrCorrection } = useMhrCorrections() + const initNewMhr = (): MhrRegistrationIF => { return { draftNumber: '', @@ -181,7 +191,7 @@ export const useNewMhrRegistration = (isMhrCorrections: boolean = false) => { // Set description for (const [key, val] of Object.entries(initNewMhr().description)) { - mhrData.description[key] + mhrData?.description[key] ? setMhrHomeDescription({ key, value: mhrData.description[key] }) : setMhrHomeDescription({ key, value: val }) // set missing description values to default } @@ -347,6 +357,12 @@ export const useNewMhrRegistration = (isMhrCorrections: boolean = false) => { data.draftNumber = getMhrDraftNumber.value } + // add additional props to payload for Mhr Corrections + if (isMhrCorrection.value) { + data.documentType = getRegistrationType.value?.registrationTypeAPI + data.mhrNumber = getMhrInformation.value.mhrNumber + } + return data } @@ -358,9 +374,14 @@ export const useNewMhrRegistration = (isMhrCorrections: boolean = false) => { } const mhrDraftHandler = async (): Promise => { + + const draftType = isMhrCorrection.value + ? APIMhrTypes.REGISTRY_STAFF_ADMIN + : APIMhrTypes.MANUFACTURED_HOME_REGISTRATION + const draft = getMhrDraftNumber.value - ? await updateMhrDraft(getMhrDraftNumber.value, APIMhrTypes.MANUFACTURED_HOME_REGISTRATION, buildApiData()) - : await createMhrDraft(APIMhrTypes.MANUFACTURED_HOME_REGISTRATION, buildApiData()) + ? await updateMhrDraft(getMhrDraftNumber.value, draftType, buildApiData()) + : await createMhrDraft(draftType, buildApiData()) // Set draftNumber to state to prevent duplicate drafts if (draft) setMhrDraftNumber(draft.draftNumber) @@ -380,7 +401,8 @@ export const useNewMhrRegistration = (isMhrCorrections: boolean = false) => { if (!sortOptions?.status || sortOptions?.status === MhApiStatusTypes.DRAFT) { mhRegDrafts = mhrDrafts?.filter(draft => - !draft.mhrNumber && draft.registrationType === APIMhrTypes.MANUFACTURED_HOME_REGISTRATION + !draft.mhrNumber && [APIMhrTypes.MANUFACTURED_HOME_REGISTRATION, APIMhrTypes.REGISTRY_STAFF_ADMIN] + .includes(draft.registrationType as APIMhrTypes) ) } @@ -415,6 +437,7 @@ export const useNewMhrRegistration = (isMhrCorrections: boolean = false) => { clientReferenceId: transfer.clientReferenceId, createDateTime: draft.createDateTime, error: draft.error, + registrationType: draft.registrationType, registrationDescription: draft.registrationDescription, hasDraft: false, ownerNames: '', diff --git a/ppr-ui/src/enums/errorCategories.ts b/ppr-ui/src/enums/errorCategories.ts index b825c5ff8..72f0b9a3a 100644 --- a/ppr-ui/src/enums/errorCategories.ts +++ b/ppr-ui/src/enums/errorCategories.ts @@ -7,6 +7,7 @@ export enum ErrorCategories { DOCUMENT_ID = 'document-id', DRAFT_DELETE = 'draft-delete', DRAFT_LOAD = 'draft-load', + DRAFT_OUT_OF_DATE = 'draft-stale', ENTITY_BASIC = 'entity-basic', FEE_INFO = 'fee-info', HISTORY_REGISTRATIONS = 'history-registrations', diff --git a/ppr-ui/src/enums/tableActions.ts b/ppr-ui/src/enums/tableActions.ts index 42eb69ec5..685036c2d 100644 --- a/ppr-ui/src/enums/tableActions.ts +++ b/ppr-ui/src/enums/tableActions.ts @@ -9,4 +9,5 @@ export enum TableActions { REMOVE_TRANSFER_DRAFT = 'removeTransferDraft', OPEN_MHR = 'openMhr', EDIT_NEW_MHR = 'editMhr', + OPEN_DRAFT_CORRECTION = 'openDraftCorrection' } diff --git a/ppr-ui/src/interfaces/mhr-registration-interfaces/MhrRegistrationIF.ts b/ppr-ui/src/interfaces/mhr-registration-interfaces/MhrRegistrationIF.ts index 5ac00c909..43e84698b 100644 --- a/ppr-ui/src/interfaces/mhr-registration-interfaces/MhrRegistrationIF.ts +++ b/ppr-ui/src/interfaces/mhr-registration-interfaces/MhrRegistrationIF.ts @@ -24,6 +24,9 @@ export interface MhrRegistrationIF { export interface NewMhrRegistrationApiIF { draftNumber?: string documentId?: string + documentType?: string + mhrNumber?: string + registrationType?: APIRegistrationTypes, clientReferenceId?: string declaredValue?: string submittingParty: SubmittingPartyIF, diff --git a/ppr-ui/src/resources/buttonFooterConfig.ts b/ppr-ui/src/resources/buttonFooterConfig.ts index d223f34f0..1e8b40119 100644 --- a/ppr-ui/src/resources/buttonFooterConfig.ts +++ b/ppr-ui/src/resources/buttonFooterConfig.ts @@ -62,8 +62,8 @@ export const MHRCorrectionButtonFooterConfig: Array = [ { stepName: RouteNames.SUBMITTING_PARTY, showCancel: true, - showSave: false, - showSaveResume: false, + showSave: true, + showSaveResume: true, showBack: false, showNext: true, backRouteName: '', @@ -73,8 +73,8 @@ export const MHRCorrectionButtonFooterConfig: Array = [ { stepName: RouteNames.YOUR_HOME, showCancel: true, - showSave: false, - showSaveResume: false, + showSave: true, + showSaveResume: true, showBack: true, showNext: true, backRouteName: RouteNames.SUBMITTING_PARTY, @@ -84,8 +84,8 @@ export const MHRCorrectionButtonFooterConfig: Array = [ { stepName: RouteNames.HOME_OWNERS, showCancel: true, - showSave: false, - showSaveResume: false, + showSave: true, + showSaveResume: true, showBack: true, showNext: true, backRouteName: RouteNames.YOUR_HOME, @@ -95,8 +95,8 @@ export const MHRCorrectionButtonFooterConfig: Array = [ { stepName: RouteNames.HOME_LOCATION, showCancel: true, - showSave: false, - showSaveResume: false, + showSave: true, + showSaveResume: true, showBack: true, showNext: true, backRouteName: RouteNames.HOME_OWNERS, @@ -106,8 +106,8 @@ export const MHRCorrectionButtonFooterConfig: Array = [ { stepName: RouteNames.MHR_REVIEW_CONFIRM, showCancel: true, - showSave: false, - showSaveResume: false, + showSave: true, + showSaveResume: true, showBack: true, showNext: true, backRouteName: RouteNames.HOME_LOCATION, diff --git a/ppr-ui/src/utils/mhr-api-helper.ts b/ppr-ui/src/utils/mhr-api-helper.ts index 134176188..3bfb272a0 100644 --- a/ppr-ui/src/utils/mhr-api-helper.ts +++ b/ppr-ui/src/utils/mhr-api-helper.ts @@ -457,7 +457,9 @@ export async function submitAdminRegistration ( } catch (error: any) { return { error: { - category: ErrorCategories.ADMIN_REGISTRATION, + category: new RegExp(ErrorRootCauses.OUT_OF_DATE_DRAFT).test(error?.response?.data?.rootCause) + ? ErrorCategories.DRAFT_OUT_OF_DATE + : ErrorCategories.ADMIN_REGISTRATION, statusCode: error?.response?.status || StatusCodes.BAD_REQUEST, message: error?.response?.data?.message || error?.errorMessage, detail: error?.response?.data?.rootCause?.detail || error?.rootCause, @@ -616,7 +618,9 @@ export async function createMhrDraft (type: APIMhrTypes, draft: any): Promise + +
@@ -27,7 +33,7 @@ class="pt-3 pb-3 soft-corners-top" > -

{{ getRegistrationType.text }}

+

{{ getRegistrationType.text }} {{ isDraft && ' - Draft' }}

{ switch(true) { case isStaffCorrection.value: @@ -218,6 +229,11 @@ export default defineComponent({ }) const emitError = (error: ErrorIF): void => { + // Intercept and handle out of date error (stale draft) + if (error.category === ErrorCategories.DRAFT_OUT_OF_DATE) { + localState.showOutOfDateDraftDialog = true + return + } context.emit('error', error) } @@ -309,6 +325,14 @@ export default defineComponent({ } } + const handleOutOfDateDialogResp = async (proceed: boolean) => { + if (proceed) { + await setDraft(null) + await goToRoute(RouteNames.MHR_INFORMATION) + } + localState.showOutOfDateDraftDialog = false + } + return { getMhrSteps, emitError, @@ -319,6 +343,9 @@ export default defineComponent({ getRegistrationType, resetAllValidations, getFooterButtonConfig, + getMhrInformation, + outOfDateOwnersDialogOptions, + handleOutOfDateDialogResp, ...toRefs(localState) } }