Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

18640 Incremental amalgamating businesses validations, etc #590

Merged
merged 3 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "business-create-ui",
"version": "5.6.9",
"version": "5.6.10",
"private": true,
"appName": "Create UI",
"sbcName": "SBC Common Components",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"serve": "vite preview --port 8080",
"lint": "eslint . --ext .js,.ts,.vue",
"test:unit": "vitest run",
"test:coverage": "vitest run --coverage"
Expand Down
40 changes: 22 additions & 18 deletions src/components/Amalgamation/AmalgamatingBusinesses.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
<ul>
Amalgamating Businesses: <br><br>
<li
v-for="(business, index) in amalgamatingBusinesses"
v-for="(business, index) in getAmalgamatingBusinesses"
:key="index"
>
<template v-if="business.foundingDate">
Expand All @@ -127,8 +127,6 @@
</ul>
</v-row> -->

<!-- FOR DEBUGGING -->
<!-- <pre>getAmalgamatingBusinesses={{ getAmalgamatingBusinesses }}</pre> -->
<BusinessTable
class="mt-8"
:class="{ 'invalid-section': getShowErrors && !businessTableValid }"
Expand All @@ -138,7 +136,7 @@
</template>

<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import { Component, Mixins, Watch } from 'vue-property-decorator'
import { Action, Getter } from 'pinia-class'
import { useStore } from '@/store/store'
import { CommonMixin } from '@/mixins'
Expand All @@ -161,12 +159,10 @@ export default class AmalgamatingBusinesses extends Mixins(CommonMixin) {
@Getter(useStore) isAmalgamationFilingHorizontal!: boolean
@Getter(useStore) isRoleStaff!: boolean

@Action(useStore) setAmalgamatingBusinesses!: (x: Array<any>) => void
@Action(useStore) setAmalgamatingBusinesses!: (x: Array<AmalgamatingBusinessIF>) => void
@Action(useStore) setAmalgamatingBusinessesValid!: (x: boolean) => void

// Local properties
amalgamatingBusinessesValid = false
amalgamatingBusinesses = []
initialBusinessLookupObject = EmptyBusinessLookup
businessTableValid = false

Expand All @@ -176,11 +172,6 @@ export default class AmalgamatingBusinesses extends Mixins(CommonMixin) {

readonly BusinessLookupServices = BusinessLookupServices

// If continuing a draft, initialize the amalgamatingBusinesses array as the previously saved one.
mounted (): void {
if (this.getAmalgamatingBusinesses) this.amalgamatingBusinesses = this.getAmalgamatingBusinesses
}

// Cancel button in "Add an Amalgamating Business" is pressed.
addAmalgamatingBusinessCancel (): void {
this.isAddingAmalgamatingBusiness = false
Expand Down Expand Up @@ -224,6 +215,8 @@ export default class AmalgamatingBusinesses extends Mixins(CommonMixin) {
// If the amalgamating businesses array is not empty, check if identifier already exists.
// If identifier already exists, don't add the business to the array.
if (business) {
const amalgamatingBusinesses = this.getAmalgamatingBusinesses

const tingBusiness = {
type: 'lear',
role: AmlRoles.AMALGAMATING,
Expand All @@ -235,18 +228,30 @@ export default class AmalgamatingBusinesses extends Mixins(CommonMixin) {
goodStanding: business.goodStanding
} as AmalgamatingBusinessIF

if (!this.amalgamatingBusinesses.find(b => b.identifier === business.identifier)) {
this.amalgamatingBusinesses.push(tingBusiness)
if (!amalgamatingBusinesses.find((b: any) => b.identifier === business.identifier)) {
severinbeauvais marked this conversation as resolved.
Show resolved Hide resolved
amalgamatingBusinesses.push(tingBusiness)

// Set the new amalgamated businesses array in the store.
this.setAmalgamatingBusinesses(amalgamatingBusinesses)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other way we could have done this is with an action that pushes the new business into the array right in the store, but I think this is OK.

}
}

// Set the amalgamated businesses array in the store.
this.setAmalgamatingBusinesses(this.amalgamatingBusinesses)

// Close the "Add an Amalgamating Business" Panel.
this.isAddingAmalgamatingBusiness = false
this.setAmalgamatingBusinessesValid(true)
}

/** Sets validity according to various flags. */
@Watch('businessTableValid')
@Watch('isAddingAmalgamatingBusiness')
@Watch('isAddingAmalgamatingForeignBusiness')
private onBusinessTableValid (): void {
this.setAmalgamatingBusinessesValid(
this.businessTableValid &&
!this.isAddingAmalgamatingBusiness &&
!this.isAddingAmalgamatingForeignBusiness
)
}
}
</script>

Expand All @@ -256,5 +261,4 @@ export default class AmalgamatingBusinesses extends Mixins(CommonMixin) {
.v-btn:not(.v-btn--round).v-size--default {
height: 44px;
}

</style>
80 changes: 19 additions & 61 deletions src/components/Amalgamation/BusinessTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,91 +69,49 @@
</template>

<script lang="ts">
import { Component, Emit, Vue, Watch } from 'vue-property-decorator'
import { Getter, Action } from 'pinia-class'
import { Component, Emit, Mixins, Watch } from 'vue-property-decorator'
import { Action } from 'pinia-class'
import { getName } from 'country-list'
import { useStore } from '@/store/store'
import { AmalgamatingStatuses, AmlRoles } from '@/enums'
import { AmalgamatingBusinessIF } from '@/interfaces'
import { BaseAddress } from '@bcrs-shared-components/base-address'
import BusinessStatus from './BusinessStatus.vue'
import { CorpTypeCd, GetCorpFullDescription } from '@bcrs-shared-components/corp-type-module'
import { GetCorpFullDescription } from '@bcrs-shared-components/corp-type-module'
import { AmalgamationMixin } from '@/mixins'

@Component({
components: {
BaseAddress,
BusinessStatus
}
})
export default class BusinessTable extends Vue {
export default class BusinessTable extends Mixins(AmalgamationMixin) {
readonly AmlRoles = AmlRoles
readonly GetCorpFullDescription = GetCorpFullDescription

@Getter(useStore) getAmalgamatingBusinesses!: AmalgamatingBusinessIF[]
@Getter(useStore) isRoleStaff!: boolean
@Getter(useStore) isTypeBcCcc!: boolean
@Getter(useStore) isTypeBcUlcCompany!: boolean

@Action(useStore) setAmalgamatingBusinesses!: (x: AmalgamatingBusinessIF[]) => void
@Action(useStore) setDefineCompanyStepValidity!: (x: boolean) => void

// *** I'M STILL WONDERING IF I WANT TO USE THESE
// readonly isLear = (item: AmalgamatingBusinessIF): boolean => (item?.type === 'lear')
// readonly isForeign = (item: AmalgamatingBusinessIF): boolean => (item?.type === 'foreign')

/** True if there a limited company in the table. */
get isAnyLimited (): boolean {
return this.businesses.some(business =>
(business.type === 'lear' && business.legalType === CorpTypeCd.BC_COMPANY)
)
}

/**
* This is the list of amalgamating businesses with computed statuses.
* In other words, these are the business rules.
* In other words, this is where the business rules are evaluated.
*/
get businesses (): AmalgamatingBusinessIF[] {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One architecture/design thing I wanted to mention:

This is a computed value (local getter), which is reactive to the variables used in it, in particular getAmalgamatingBusinesses, so it is evaluated (and cached) accordingly.

Also, as a computed, it needs to be used somewhere (otherwise it is not evaluated). In this component, it's used both to display the table items (line 17) and is watched to emit whether the table is valid (line 166).

Another way to do this would be to simply watch getAmalgamatingBusinesses and then compute the statuses when it has changed. If the getter approach didn't work (eg, reactivity didn't work) then I would have changed to this approach, otherwise I see no reason to change working code :)

return this.getAmalgamatingBusinesses.map(business => {
/* eslint-disable brace-style */

// disallow foreign altogether if not staff
// (could happen if staff added it and regular user resumes draft)
if (business.type === 'foreign' && !this.isRoleStaff) {
business.status = AmalgamatingStatuses.ERROR_FOREIGN
}

// disallow foreign into ULC if there is also a limited
else if (business.type === 'foreign' && this.isTypeBcUlcCompany && this.isAnyLimited) {
business.status = AmalgamatingStatuses.ERROR_FOREIGN
}

// assume business is not affiliated if we don't have address (non-staff only)
else if (business.type === 'lear' && !business.address && !this.isRoleStaff) {
business.status = AmalgamatingStatuses.ERROR_AFFILIATION
}

// identify CCC mismatch
else if (business.type === 'lear' && business.legalType === CorpTypeCd.BC_CCC && !this.isTypeBcCcc) {
business.status = AmalgamatingStatuses.ERROR_CCC_MISMATCH
}

// disallow NIGS if not staff
else if (business.type === 'lear' && !business.goodStanding && !this.isRoleStaff) {
business.status = AmalgamatingStatuses.ERROR_NIGS
}

// check if limited restoration
// *** TODO

// check for future effective filing
// *** TODO

// otherwise, status is OK
else {
business.status = AmalgamatingStatuses.OK
}
/* eslint-enable brace-style */

// evaluate the rules for the current business
// assign the value of the first failed rule (if any) else OK
business.status = this.rules.reduce(
(status: AmalgamatingStatuses, rule: (business: AmalgamatingBusinessIF) => AmalgamatingStatuses) => {
// if we already failed a rule, don't check the rest of the rules
if (status) return status
// return the value of the current rule (may be null)
return rule(business)
},
null
) || AmalgamatingStatuses.OK

// return updated business object
return business
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export type AmalgamatingBusinessIF = AmalgamatingLearIF | AmalgamatingForeignIF
/** State interface for amalgamation-specific data. */
export interface AmalgamationStateIF {
amalgamatingBusinesses: Array<AmalgamatingBusinessIF>
courtApproval: boolean
amalgamatingBusinessesValid: boolean
courtApproval: boolean
type: AmalgamationTypes
}
114 changes: 114 additions & 0 deletions src/mixins/amalgamation-mixin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { Component, Vue } from 'vue-property-decorator'
import { Getter } from 'pinia-class'
import { useStore } from '@/store/store'
import { AmalgamatingStatuses } from '@/enums'
import { AmalgamatingBusinessIF } from '@/interfaces'
import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module'

/**
* Mixin that provides amalgamation rules, etc.
*/
@Component({})
export default class AmalgamationMixin extends Vue {
@Getter(useStore) getAmalgamatingBusinesses!: AmalgamatingBusinessIF[]
@Getter(useStore) isRoleStaff!: boolean
@Getter(useStore) isTypeBcCcc!: boolean
@Getter(useStore) isTypeBcUlcCompany!: boolean

// *** TODO: finish this, maybe name them something recognizable...
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WIP but some functionality is in and usable. I will pick away at this but I am no longer blocking anyone.

/** Iterable array of rule functions, sorted by importance. */
readonly rules = [
this.rule1,
this.rule2,
this.rule3,
this.rule4,
this.rule5,
this.rule6
]

// *** I'M STILL WONDERING IF I WANT TO USE THESE
// readonly isLear = (item: AmalgamatingBusinessIF): boolean => (item?.type === 'lear')
// readonly isForeign = (item: AmalgamatingBusinessIF): boolean => (item?.type === 'foreign')

/** True if there a limited company in the table. */
get isAnyLimited (): boolean {
return this.getAmalgamatingBusinesses.some(business =>
(business.type === 'lear' && business.legalType === CorpTypeCd.BC_COMPANY)
)
}

/** True if there an unlimited company in the table in Alberta, Nova Scotia or USA. */
get isAnyUnlimitedAbNsUsa (): boolean {
return this.getAmalgamatingBusinesses.some(business =>
(business.type === 'lear' && business.legalType === CorpTypeCd.BC_COMPANY)
)
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've requested access to the document.


// readonly amalgamationRules = [
// {
// id: 0,
// rule: (v: any) => !!v || 'Required',
// status: AmalgamatingStatuses.ERROR_FOREIGN
// }
// ]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More WIP. Just assume everything in here is WIP, except for the basic architecture and design :)


// A BC Company cannot amalgamate with an existing Unlimited Liability Company from Alberta,
// Nova Scotia, or the USA to form a BC Unlimited Liability Company.

// disallow foreign into ULC if there is also a limited
rule1 (business: AmalgamatingBusinessIF): AmalgamatingStatuses {
if (business.type === 'foreign' && this.isTypeBcUlcCompany && this.isAnyLimited) {
return AmalgamatingStatuses.ERROR_FOREIGN
}
return null
}

// disallow foreign altogether if not staff
// (could happen if staff added it and regular user resumes draft)
rule2 (business: AmalgamatingBusinessIF): AmalgamatingStatuses {
if (business.type === 'foreign' && !this.isRoleStaff) {
return AmalgamatingStatuses.ERROR_FOREIGN
}
return null
}

// disallow foreign into ULC if there is also a limited
rule3 (business: AmalgamatingBusinessIF): AmalgamatingStatuses {
if (business.type === 'foreign' && this.isTypeBcUlcCompany && this.isAnyLimited) {
return AmalgamatingStatuses.ERROR_FOREIGN
}
return null
}

// assume business is not affiliated if we don't have address (non-staff only)
rule4 (business: AmalgamatingBusinessIF): AmalgamatingStatuses {
// *** TODO: revert staff check
if (business.type === 'lear' && !business.address /* && !this.isRoleStaff */) {
return AmalgamatingStatuses.ERROR_AFFILIATION
}
return null
}

// identify CCC mismatch
rule5 (business: AmalgamatingBusinessIF): AmalgamatingStatuses {
if (business.type === 'lear' && business.legalType === CorpTypeCd.BC_CCC && !this.isTypeBcCcc) {
return AmalgamatingStatuses.ERROR_CCC_MISMATCH
}
return null
}

// disallow NIGS if not staff
rule6 (business: AmalgamatingBusinessIF): AmalgamatingStatuses {
// *** TODO: revert staff check
if (business.type === 'lear' && !business.goodStanding /* && !this.isRoleStaff */) {
return AmalgamatingStatuses.ERROR_NIGS
}
return null
}

// check if limited restoration
// *** TODO

// check for future effective filing
// *** TODO
}
1 change: 1 addition & 0 deletions src/mixins/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { default as AddEditOrgPersonMixin } from './add-edit-org-person-mixin'
export { default as AmalgamationMixin } from './amalgamation-mixin'
export { default as CommonMixin } from './common-mixin'
export { default as CurrencyLookupMixin } from '@/mixins/currency-lookup-mixin'
export { default as DateMixin } from './date-mixin'
Expand Down
9 changes: 7 additions & 2 deletions src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,13 @@ export const useStore = defineStore('store', {

/** Whether all the amalgamation (regular) steps are valid. */
isAmalgamationRegularValid (): boolean {
// *** TODO: implement this
return false
// *** TODO: add checks for review page components
return (
this.getAmalgamatingBusinessesValid &&
this.getDefineCompanyStep.valid &&
this.getAddPeopleAndRoleStep.valid &&
this.getCreateShareStructureStep.valid
)
},

/** Whether all the incorporation steps are valid. */
Expand Down
Loading
Loading