diff --git a/ppr-ui/package-lock.json b/ppr-ui/package-lock.json index bc48d0dae..f6c92a39e 100644 --- a/ppr-ui/package-lock.json +++ b/ppr-ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "ppr-ui", - "version": "3.2.32", + "version": "3.2.33", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ppr-ui", - "version": "3.2.32", + "version": "3.2.33", "dependencies": { "@bcrs-shared-components/input-field-date-picker": "^1.0.0", "@lemoncode/fonk": "^1.5.1", diff --git a/ppr-ui/package.json b/ppr-ui/package.json index a4270ac90..3bc4acf8c 100644 --- a/ppr-ui/package.json +++ b/ppr-ui/package.json @@ -1,6 +1,6 @@ { "name": "ppr-ui", - "version": "3.2.32", + "version": "3.2.33", "private": true, "appName": "Assets UI", "sbcName": "SBC Common Components", diff --git a/ppr-ui/src/assets/styles/base.scss b/ppr-ui/src/assets/styles/base.scss index 6a5e76be5..749777cf4 100644 --- a/ppr-ui/src/assets/styles/base.scss +++ b/ppr-ui/src/assets/styles/base.scss @@ -168,6 +168,9 @@ a { .error-text { color: $error !important; } +.gray7 { + color: $gray7; +} .disabled-text { opacity: 0.4; diff --git a/ppr-ui/src/components/common/SimpleTable.vue b/ppr-ui/src/components/common/SimpleTable.vue index b8edf11a7..78a57dd34 100644 --- a/ppr-ui/src/components/common/SimpleTable.vue +++ b/ppr-ui/src/components/common/SimpleTable.vue @@ -20,8 +20,13 @@ + - {{ getItemValue(item, header.value) }} + + | string): string diff --git a/ppr-ui/src/components/mhrHistory/index.ts b/ppr-ui/src/components/mhrHistory/index.ts index 01fd81275..93f4a8e54 100644 --- a/ppr-ui/src/components/mhrHistory/index.ts +++ b/ppr-ui/src/components/mhrHistory/index.ts @@ -1,2 +1,3 @@ export { default as MhrHistoryDescription } from './MhrHistoryDescription.vue' export { default as MhrHistoryLocations } from './MhrHistoryLocations.vue' +export { default as MhrHistoryOwners } from './MhrHistoryOwners.vue' diff --git a/ppr-ui/src/composables/mhrInformation/useTransferOwners.ts b/ppr-ui/src/composables/mhrInformation/useTransferOwners.ts index b585e7c14..9972ef278 100644 --- a/ppr-ui/src/composables/mhrInformation/useTransferOwners.ts +++ b/ppr-ui/src/composables/mhrInformation/useTransferOwners.ts @@ -427,18 +427,28 @@ export const useTransferOwners = (enableAllActions: boolean = false) => { if (getMhrTransferType.value?.transferType === ApiTransferTypes.SALE_OR_GIFT && getMhrInformation.value.statusType === MhApiStatusTypes.FROZEN && !QSLockedStateUnitNoteTypes.includes(getMhrInformation.value?.frozenDocumentType)) { - // Find ExecutorAdministrator group - // Updated to restrict to the last group in the structure, as that is always the recently added executors group - const isExecutorOrAdministratorOwnerGroup = getMhrTransferHomeOwnerGroups.value.find(group => group.groupId === - getMhrTransferHomeOwnerGroups.value.length && group.groupId === owner.groupId)?.owners.some(owner => { - return owner.partyType === HomeOwnerPartyTypes.EXECUTOR || owner.partyType === HomeOwnerPartyTypes.ADMINISTRATOR - }) - - return !isExecutorOrAdministratorOwnerGroup + const mostRecentExecutorOrAdmin = getMostRecentExecutorOrAdmin(getMhrTransferHomeOwnerGroups.value) + return mostRecentExecutorOrAdmin.groupId !== owner.groupId } return false } + /** + * Retrieves the executor or administrator with the highest ownerId from a list of owner groups. + * + * @param {Array} ownerGroups - The list of owner groups to search through. + * @returns {MhrRegistrationHomeOwnerIF} - The executor or administrator with the highest ownerId. + */ + const getMostRecentExecutorOrAdmin = (ownerGroups: Array): MhrRegistrationHomeOwnerIF => { + return ownerGroups + .flatMap(group => group.owners) // Combine all owners into a single array + .filter(owner => owner.partyType === HomeOwnerPartyTypes.EXECUTOR || + owner.partyType === HomeOwnerPartyTypes.ADMINISTRATOR) // Keep only executors or admins + .reduce((highest: any, owner: any) => { + return owner.ownerId > highest.ownerId ? owner : highest + }, { ownerId: -Infinity }) // Find the executor with the highest ownerId + } + /** * Return true if there is a deceased or modified owner outside the specified owners group * in Surviving Joint Tenants @@ -1001,6 +1011,7 @@ export const useTransferOwners = (enableAllActions: boolean = false) => { hasCurrentGroupChanges, moveCurrentOwnersToPreviousOwners, hasMinOneExecOrAdminInGroup, + getMostRecentExecutorOrAdmin, ...toRefs(localState) } } diff --git a/ppr-ui/src/composables/mhrRegistration/useHomeOwners.ts b/ppr-ui/src/composables/mhrRegistration/useHomeOwners.ts index 63dafc2ef..54b79e24e 100644 --- a/ppr-ui/src/composables/mhrRegistration/useHomeOwners.ts +++ b/ppr-ui/src/composables/mhrRegistration/useHomeOwners.ts @@ -9,7 +9,7 @@ import { import { useStore } from '@/store/store' import { ActionTypes, ApiTransferTypes, HomeOwnerPartyTypes, HomeTenancyTypes, MhApiStatusTypes } from '@/enums' import { MhrCompVal, MhrSectVal } from '@/composables/mhrRegistration/enums' -import { useMhrValidations } from '@/composables' +import { useMhrValidations, useTransferOwners } from '@/composables' import { find, findIndex, remove, set, uniq } from 'lodash' import { storeToRefs } from 'pinia' import { deepChangesComparison } from '@/utils' @@ -302,7 +302,8 @@ export function useHomeOwners (isMhrTransfer: boolean = false, isMhrCorrection: // Try to find a group to add the owner // If frozen Sale or Gift Transfer: Add Owner to the last ownership group with recently added Executor const groupToUpdate = isFrozenSoGTransfer - ? homeOwnerGroups[homeOwnerGroups?.length -1] + ? homeOwnerGroups.find(group => group.groupId === + useTransferOwners().getMostRecentExecutorOrAdmin(homeOwnerGroups)?.groupId) : homeOwnerGroups.find( (group: MhrRegistrationHomeOwnerGroupIF) => group.groupId === (groupId || fallBackId) ) || ({} as MhrRegistrationHomeOwnerGroupIF) diff --git a/ppr-ui/src/interfaces/mhr-api-interfaces/MhrHistoryIF.ts b/ppr-ui/src/interfaces/mhr-api-interfaces/MhrHistoryIF.ts index d2ed19f88..2174cb9f1 100644 --- a/ppr-ui/src/interfaces/mhr-api-interfaces/MhrHistoryIF.ts +++ b/ppr-ui/src/interfaces/mhr-api-interfaces/MhrHistoryIF.ts @@ -1,4 +1,5 @@ import { AddressIF, MhrLocationInfoIF } from '@/interfaces' +import { HomeOwnerPartyTypes } from '@/enums' export interface DescriptionIF { baseInformation?: { @@ -62,8 +63,10 @@ export interface IndividualNameIF { export interface OwnerIF { address?: AddressIF createDateTime?: string + description?: string documentId?: string documentRegistrationNumber?: string + emailAddress?: string endDateTime?: string endRegistrationDescription?: string groupCount?: number @@ -75,8 +78,10 @@ export interface OwnerIF { interestDenominator?: number interestNumerator?: number ownerId?: number - partyType?: string + organizationName?: string + partyType?: HomeOwnerPartyTypes phoneNumber?: string + phoneExtension?: number registrationDescription?: string status?: string type?: string diff --git a/ppr-ui/src/resources/mhr-history/mhHistoryTableHeaders.ts b/ppr-ui/src/resources/mhr-history/mhHistoryTableHeaders.ts index 22812df55..75db60f67 100644 --- a/ppr-ui/src/resources/mhr-history/mhHistoryTableHeaders.ts +++ b/ppr-ui/src/resources/mhr-history/mhHistoryTableHeaders.ts @@ -64,7 +64,7 @@ export const homeOwnerHeaders: Array = [ }, { name: 'Owner Name', - value: ['individualName.first', 'individualName.middle', 'individualName.last'], + value: ['individualName.first', 'individualName.middle', 'individualName.last', 'organizationName'], class: 'col-22-5' }, { diff --git a/ppr-ui/src/views/mhrInformation/MhrHistory.vue b/ppr-ui/src/views/mhrInformation/MhrHistory.vue index fceaa2180..3f803cf77 100644 --- a/ppr-ui/src/views/mhrInformation/MhrHistory.vue +++ b/ppr-ui/src/views/mhrInformation/MhrHistory.vue @@ -64,10 +64,31 @@ @@ -114,7 +135,9 @@ import { homeOwnerHeaders, mhHistoryTabConfig } from '@/resources/mhr-history' -import { MhrHistoryDescription, MhrHistoryLocations } from '@/components/mhrHistory' +import { MhrHistoryDescription, MhrHistoryLocations, MhrHistoryOwners } from '@/components/mhrHistory' +import { ApiHomeTenancyTypes, HomeOwnerPartyTypes, HomeTenancyTypes } from '@/enums' +import { OwnerIF } from '@/interfaces' /** Composables **/ const { isAuthenticated } = useAuth() @@ -148,9 +171,96 @@ onMounted(async (): Promise => { loading.value = false }) +const getHomeOwnerIcon = (partyType: HomeOwnerPartyTypes, isBusiness = false): string => { + const uniqueRoleIcon = isBusiness + ? 'custom:ExecutorBusinessIcon' + : 'custom:ExecutorPersonIcon' + const ownerIcon = isBusiness + ? 'mdi-domain' + : 'mdi-account' + + switch (partyType) { + case HomeOwnerPartyTypes.EXECUTOR: + case HomeOwnerPartyTypes.ADMINISTRATOR: + case HomeOwnerPartyTypes.TRUSTEE: + return uniqueRoleIcon + case HomeOwnerPartyTypes.OWNER_IND: + case HomeOwnerPartyTypes.OWNER_BUS: + return ownerIcon + } +} + +/** + * Maps an API home tenancy type to a UI home tenancy type. + * + * @param {ApiHomeTenancyTypes} apiType - The API home tenancy type to map. + * @returns {HomeTenancyTypes} The corresponding UI home tenancy type. + */ +function mapApiToUiTenancyType(apiType: ApiHomeTenancyTypes): HomeTenancyTypes { + switch (apiType) { + case ApiHomeTenancyTypes.JOINT: + return HomeTenancyTypes.JOINT + case ApiHomeTenancyTypes.SOLE: + return HomeTenancyTypes.SOLE + case ApiHomeTenancyTypes.COMMON: + return HomeTenancyTypes.COMMON + case ApiHomeTenancyTypes.NA: + return HomeTenancyTypes.NA + default: + throw new Error(`Unknown API tenancy type: ${apiType}`) + } +} + +/** + * Maps an API status to a UI status. + * + * @param {string} status - The API status to map. + * @returns {string} The corresponding UI status. + */ +function mapApiToUiStatus(status: string): string { + switch (status) { + case 'ACTIVE': + return 'Active' + case 'PREVIOUS': + return 'Historical' + default: + return status + } +} + +/** + * Maps the `type` and `groupTenancyType` properties in each owner object to the UI tenancy types. + * + * @param {Array} owners - The array of owner objects. + * @returns {Array} The new array with updated tenancy types. + */ +function mapOwnersApiToUi(owners: Array): Array { + return owners.map(owner => ({ + ...owner, + type: mapApiToUiTenancyType(owner.type), + groupTenancyType: owner.groupTenancyType ? mapApiToUiTenancyType(owner.groupTenancyType) : undefined, + status: mapApiToUiStatus(owner.status) + })) +} +