diff --git a/package-lock.json b/package-lock.json index 587c28ca6..18f51d5d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "business-create-ui", - "version": "5.6.34", + "version": "5.6.35", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "business-create-ui", - "version": "5.6.34", + "version": "5.6.35", "dependencies": { "@babel/compat-data": "^7.21.5", "@bcrs-shared-components/approval-type": "1.0.19", diff --git a/package.json b/package.json index 9e91d8502..a772803c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "business-create-ui", - "version": "5.6.34", + "version": "5.6.35", "private": true, "appName": "Create UI", "sbcName": "SBC Common Components", diff --git a/src/components/Amalgamation/AmalgamatingBusinesses.vue b/src/components/Amalgamation/AmalgamatingBusinesses.vue index 86af45ddd..b9ae58b0f 100644 --- a/src/components/Amalgamation/AmalgamatingBusinesses.vue +++ b/src/components/Amalgamation/AmalgamatingBusinesses.vue @@ -192,7 +192,7 @@ import { BusinessLookup } from '@bcrs-shared-components/business-lookup' import { Jurisdiction } from '@bcrs-shared-components/jurisdiction' import { CanJurisdictions, MrasJurisdictions } from '@bcrs-shared-components/jurisdiction/list-data' import { AmalgamatingBusinessIF, BusinessLookupResultIF, EmptyBusinessLookup } from '@/interfaces' -import { AmlRoles, AmlTypes, EntityStates, FilingStatus } from '@/enums' +import { AmlRoles, AmlTypes, EntityStates } from '@/enums' import { JurisdictionLocation } from '@bcrs-shared-components/enums' import BusinessTable from '@/components/Amalgamation/BusinessTable.vue' import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module' @@ -366,12 +366,6 @@ export default class AmalgamatingBusinesses extends Mixins(AmalgamationMixin, Co return } - const isFutureEffective = ( - business.firstFiling.isFutureEffective === true && - business.firstFiling.status !== FilingStatus.COMPLETED && - business.firstFiling.status !== FilingStatus.CORRECTED - ) - // Create amalgamating business object. const tingBusiness: AmalgamatingBusinessIF = { type: AmlTypes.LEAR, @@ -382,7 +376,8 @@ export default class AmalgamatingBusinesses extends Mixins(AmalgamationMixin, Co legalType: business.businessInfo.legalType, address: business.addresses.registeredOffice.mailingAddress, isNotInGoodStanding: (business.businessInfo.goodStanding === false), - isFutureEffective, + isFutureEffective: this.isFutureEffective(business), + isPendingDissolution: this.isPendingDissolution(business), isLimitedRestoration: await this.isLimitedRestoration(business), isHistorical: (business.businessInfo.state === EntityStates.HISTORICAL) } diff --git a/src/components/Amalgamation/BusinessStatus.vue b/src/components/Amalgamation/BusinessStatus.vue index 5c97c48a0..6afe00bb9 100644 --- a/src/components/Amalgamation/BusinessStatus.vue +++ b/src/components/Amalgamation/BusinessStatus.vue @@ -90,6 +90,9 @@ export default class BusinessStatus extends Vue { return 'This business is not in good standing. This filing cannot be submitted until all ' + 'businesses are in good standing.' + case AmlStatuses.ERROR_PENDING_DISSOLUTION_FILING: + return 'This business has a pending dissolution filing. It cannot be part of an amalgamation.' + case AmlStatuses.ERROR_XPRO_ULC_CCC: return 'An Extraprovincial Company cannot amalgamate to form a new BC Unlimited Liability ' + 'Company or a new BC Community Contribution Company.' diff --git a/src/enums/amalgamationEnums.ts b/src/enums/amalgamationEnums.ts index 8d2d5123a..cfc7b674e 100644 --- a/src/enums/amalgamationEnums.ts +++ b/src/enums/amalgamationEnums.ts @@ -12,6 +12,7 @@ export enum AmlStatuses { ERROR_NEED_BC_COMPANY, ERROR_NOT_AFFILIATED, ERROR_NOT_IN_GOOD_STANDING, + ERROR_PENDING_DISSOLUTION_FILING, ERROR_XPRO_ULC_CCC, } diff --git a/src/interfaces/store-interfaces/state-interfaces/amalgamation-state-interface.ts b/src/interfaces/store-interfaces/state-interfaces/amalgamation-state-interface.ts index bcedc3519..7f0342a29 100644 --- a/src/interfaces/store-interfaces/state-interfaces/amalgamation-state-interface.ts +++ b/src/interfaces/store-interfaces/state-interfaces/amalgamation-state-interface.ts @@ -17,7 +17,8 @@ interface AmalgamatingLearIF { address?: AddressIF status?: AmlStatuses // computed status (base on business rules) isNotInGoodStanding?: boolean // whether business is in good standing - isFutureEffective?: boolean // whether business has a FE filing + isFutureEffective?: boolean // whether business has a future effective filing + isPendingDissolution?: boolean // whether business has a pending dissolution filing isLimitedRestoration?: boolean // whether business is in limited restoration isHistorical?: boolean // whether business is historical } diff --git a/src/mixins/amalgamation-mixin.ts b/src/mixins/amalgamation-mixin.ts index 76bb0571c..940b40422 100644 --- a/src/mixins/amalgamation-mixin.ts +++ b/src/mixins/amalgamation-mixin.ts @@ -1,7 +1,7 @@ import { Component, Vue } from 'vue-property-decorator' import { Action, Getter } from 'pinia-class' import { useStore } from '@/store/store' -import { AmlRoles, AmlStatuses, AmlTypes, EntityStates, RestorationTypes } from '@/enums' +import { AmlRoles, AmlStatuses, AmlTypes, EntityStates, FilingStatus, FilingTypes, RestorationTypes } from '@/enums' import { AmalgamatingBusinessIF } from '@/interfaces' import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module' import { AuthServices, LegalServices } from '@/services' @@ -28,6 +28,7 @@ export default class AmalgamationMixin extends Vue { this.notInGoodStanding, this.limitedRestoration, this.futureEffectiveFiling, + this.pendingDissolutionFiling, this.foreign, this.foreignUnlimited, this.cccMismatch, @@ -81,6 +82,14 @@ export default class AmalgamationMixin extends Vue { return null } + /** Disallow if a pending dissolution filing exists. */ + pendingDissolutionFiling (business: AmalgamatingBusinessIF): AmlStatuses { + if (business.type === AmlTypes.LEAR && business.isPendingDissolution) { + return AmlStatuses.ERROR_PENDING_DISSOLUTION_FILING + } + return null + } + /** * Disallow altogether if foreign or extra-pro (except for staff). * (Could happen if staff added it and regular user resumes draft.) @@ -166,20 +175,16 @@ export default class AmalgamationMixin extends Vue { */ async fetchAmalgamatingBusinessInfo (item: any): Promise { // Get the auth info, business info, addresses and filings concurrently. - // Return data array; if any call failed, that item will be null. - const data = await Promise.allSettled([ - AuthServices.fetchAuthInfo(item.identifier), - LegalServices.fetchBusinessInfo(item.identifier), - LegalServices.fetchAddresses(item.identifier), - LegalServices.fetchFirstOrOnlyFiling(item.identifier) - ]).then(results => results.map((result: any) => result.value || null)) + // NB - if any call failed, that item will be null. + const [ authInfo, businessInfo, addresses, firstFiling ] = + await Promise.allSettled([ + AuthServices.fetchAuthInfo(item.identifier), + LegalServices.fetchBusinessInfo(item.identifier), + LegalServices.fetchAddresses(item.identifier), + LegalServices.fetchFirstOrOnlyFiling(item.identifier) + ]).then(results => results.map((result: any) => result.value || null)) - return { - authInfo: data[0], - businessInfo: data[1], - addresses: data[2], - firstFiling: data[3] - } + return { authInfo, businessInfo, addresses, firstFiling } } /** @@ -200,9 +205,35 @@ export default class AmalgamationMixin extends Vue { ) } + /** + * This business is future effective if the first filing in the ledger is future effective and is still + * not complete or corrected (ie, it's paid or pending). + * @param business The business to check if is Future Effective or not. + */ + isFutureEffective (business: any): boolean { + return ( + business.firstFiling?.isFutureEffective === true && + business.firstFiling?.status !== FilingStatus.COMPLETED && + business.firstFiling?.status !== FilingStatus.CORRECTED + ) + } + + /** + * This business is pending dissolution if the first filing in the ledger is a dissolution filing that + * is still not complete or corrected (ie, it's paid or pending). + * @param business The business to check if is Pending Dissolution or not. + */ + isPendingDissolution (business: any): boolean { + return ( + business.firstFiling?.name === FilingTypes.DISSOLUTION && + business.firstFiling?.status !== FilingStatus.COMPLETED && + business.firstFiling?.status !== FilingStatus.CORRECTED + ) + } + /** * Re-fetch the draft amalgamating businesses information and set in the store. - * Need to do that because the businesses might have changed from last draft save. + * Need to do that because the businesses might have changed since last draft save. */ async refetchAmalgamatingBusinessesInfo (): Promise { const fetchTingInfo = async (item: any): Promise => { @@ -222,11 +253,12 @@ export default class AmalgamationMixin extends Vue { role: AmlRoles.AMALGAMATING, identifier: tingBusiness.businessInfo.identifier, name: tingBusiness.businessInfo.legalName, - email: tingBusiness.authInfo?.contacts[0].email || null, + email: tingBusiness.authInfo?.contacts[0].email, legalType: tingBusiness.businessInfo.legalType, - address: tingBusiness.addresses?.registeredOffice.mailingAddress || null, + address: tingBusiness.addresses?.registeredOffice.mailingAddress, isNotInGoodStanding: (tingBusiness.businessInfo.goodStanding === false), - isFutureEffective: (tingBusiness.firstFiling.isFutureEffective === true), + isFutureEffective: this.isFutureEffective(tingBusiness), + isPendingDissolution: this.isPendingDissolution(tingBusiness), isLimitedRestoration: await this.isLimitedRestoration(tingBusiness), isHistorical: (tingBusiness.businessInfo.state === EntityStates.HISTORICAL) } as AmalgamatingBusinessIF diff --git a/tests/unit/BusinessStatus.spec.ts b/tests/unit/BusinessStatus.spec.ts index 7a082eb03..4d758ffd6 100644 --- a/tests/unit/BusinessStatus.spec.ts +++ b/tests/unit/BusinessStatus.spec.ts @@ -69,6 +69,11 @@ describe('Business Status', () => { status: AmlStatuses.ERROR_NOT_IN_GOOD_STANDING, tooltip: 'This business is not in good standing. This filing cannot be submitted until all' }, + { + label: 'Error Pending Dissolition Filing', + status: AmlStatuses.ERROR_PENDING_DISSOLUTION_FILING, + tooltip: 'This business has a pending dissolution filing. It cannot be part of an amalgamation.' + }, { label: 'Error XPRO ULC CCC', status: AmlStatuses.ERROR_XPRO_ULC_CCC, @@ -77,7 +82,7 @@ describe('Business Status', () => { ] it('has the expected number of tests', () => { - expect(tests.length).toBe(14) + expect(tests.length).toBe(1 + 14) // OK + 14 errors }) for (const test of tests) { diff --git a/tests/unit/BusinessTable.spec.ts b/tests/unit/BusinessTable.spec.ts index 6dfa1dcbe..0b3ef693a 100644 --- a/tests/unit/BusinessTable.spec.ts +++ b/tests/unit/BusinessTable.spec.ts @@ -182,11 +182,13 @@ describe.skip('Business Table - rule evaluation', () => { { methodName: 'notInGoodStanding', error: AmlStatuses.ERROR_NOT_IN_GOOD_STANDING }, { methodName: 'limitedRestoration', error: AmlStatuses.ERROR_LIMITED_RESTORATION }, { methodName: 'futureEffectiveFiling', error: AmlStatuses.ERROR_FUTURE_EFFECTIVE_FILING }, + { methodName: 'pendingDissolutionFiling', error: AmlStatuses.ERROR_PENDING_DISSOLUTION_FILING }, { methodName: 'foreign', error: AmlStatuses.ERROR_FOREIGN }, { methodName: 'foreignUnlimited', error: AmlStatuses.ERROR_FOREIGN_UNLIMITED }, { methodName: 'cccMismatch', error: AmlStatuses.ERROR_CCC_MISMATCH }, { methodName: 'foreignUnlimited2', error: AmlStatuses.ERROR_FOREIGN_UNLIMITED2 }, { methodName: 'xproUlcCcc', error: AmlStatuses.ERROR_XPRO_ULC_CCC }, + { methodName: 'foreignUnlimited3', error: AmlStatuses.ERROR_FOREIGN_UNLIMITED3 }, { methodName: 'needBcCompany', error: AmlStatuses.ERROR_NEED_BC_COMPANY }, { methodName: 'foreignHorizontal', error: AmlStatuses.ERROR_FOREIGN_HORIZONTAL } ] @@ -219,7 +221,8 @@ describe.skip('Business Table - rule evaluation', () => { }) it('has the expected number of rules', () => { - expect(wrapper.vm.rules.length).toBe(rules.length) + expect(rules.length).toBe(14) + expect(wrapper.vm.rules.length).toBe(14) }) // check each rule sequentially diff --git a/tests/unit/amalgamation-mixin.spec.ts b/tests/unit/amalgamation-mixin.spec.ts index 043c58538..333cbf17b 100644 --- a/tests/unit/amalgamation-mixin.spec.ts +++ b/tests/unit/amalgamation-mixin.spec.ts @@ -20,6 +20,10 @@ describe('Amalgamation Mixin - rules', () => { wrapper.destroy() }) + it('has the expected number of rules', () => { + expect(wrapper.vm.rules.length).toBe(14) + }) + it('correctly evaluates "notAffiliated" rule', () => { // init store.setKeycloakRoles([]) @@ -99,6 +103,17 @@ describe('Amalgamation Mixin - rules', () => { expect(wrapper.vm.futureEffectiveFiling({ type: AmlTypes.LEAR, isFutureEffective: false })).toBeNull() }) + it('correctly evaluates "pendingDissolutionFiling" rule', () => { + // verify rule + expect(wrapper.vm.pendingDissolutionFiling({ type: AmlTypes.LEAR, isPendingDissolution: true })).toBe(AmlStatuses.ERROR_PENDING_DISSOLUTION_FILING) + + // verify not LEAR only + expect(wrapper.vm.pendingDissolutionFiling({ type: AmlTypes.FOREIGN, isPendingDissolution: true })).toBeNull() + + // verify not pending dissolution only + expect(wrapper.vm.pendingDissolutionFiling({ type: AmlTypes.LEAR, isPendingDissolution: false })).toBeNull() + }) + it('correctly evaluates "foreign" rule', () => { // init store.setKeycloakRoles([])