Skip to content

Commit

Permalink
19209 Pre-populate TING business + error handling (#609)
Browse files Browse the repository at this point in the history
- app version = 7.0.36
- fixed some getLegalType types
- added generic Technical Error Dialog (per Yui)
- added amalgamation enums
- refactored Legal Service function for better result and error handling
- added dialog to Amalgamation Selection component
- refactored Amalgamation Selection for error handling and to pre-populate TING business
- added test suite for new dialog

Co-authored-by: Severin Beauvais <severin.beauvais@gov.bc.ca>
  • Loading branch information
severinbeauvais and Severin Beauvais committed Jan 17, 2024
1 parent 66f651e commit 53ab148
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 36 deletions.
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.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "business-filings-ui",
"version": "7.0.35",
"version": "7.0.36",
"private": true,
"appName": "Filings UI",
"sbcName": "SBC Common Components",
Expand Down
3 changes: 2 additions & 1 deletion src/components/dialogs/AddStaffNotationDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ import { FormIF } from '@/interfaces'
import { EffectOfOrderTypes, FilingSubTypes, FilingTypes, PageSizes } from '@/enums'
import { EnumUtilities, LegalServices } from '@/services'
import { useAuthenticationStore, useBusinessStore, useRootStore } from '@/stores'
import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module'
@Component({
components: {
Expand Down Expand Up @@ -198,7 +199,7 @@ export default class AddStaffNotationDialog extends Mixins(DateMixin) {
@Getter(useRootStore) getCurrentDate!: string
@Getter(useBusinessStore) getFoundingDate!: Date
@Getter(useBusinessStore) getLegalName!: string
@Getter(useBusinessStore) getLegalType!: string
@Getter(useBusinessStore) getLegalType!: CorpTypeCd
@Getter(useBusinessStore) getIdentifier!: string
@Getter(useAuthenticationStore) getKeycloakGuid!: string
@Getter(useBusinessStore) isAdminFrozen!: boolean
Expand Down
3 changes: 2 additions & 1 deletion src/components/dialogs/ConfirmDissolutionDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import { Component, Prop, Emit, Vue } from 'vue-property-decorator'
import { Getter } from 'pinia-class'
import { DissolutionConfirmationResourceIF } from '@/interfaces'
import { useBusinessStore, useRootStore } from '@/stores'
import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module'
@Component({})
export default class ConfirmDissolutionDialog extends Vue {
Expand All @@ -99,7 +100,7 @@ export default class ConfirmDissolutionDialog extends Vue {
// Global getters
@Getter(useRootStore) getDissolutionConfirmationResource!: DissolutionConfirmationResourceIF
@Getter(useBusinessStore) getLegalName!: string
@Getter(useBusinessStore) getLegalType!: string
@Getter(useBusinessStore) getLegalType!: CorpTypeCd
/** The entity title to display. */
get entityTitle (): string {
Expand Down
64 changes: 64 additions & 0 deletions src/components/dialogs/TechnicalErrorDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<template>
<v-dialog
v-model="dialog"
width="45rem"
persistent
:attach="attach"
content-class="technical-error-dialog"
>
<v-card>
<v-card-title>Error</v-card-title>

<v-card-text>
<p class="font-15">
We could not process your action due to a technical issue. Try again in a few minutes.
</p>

<template v-if="!isRoleStaff">
<p class="font-15">
If this error persists, please contact BC Registries staff:
</p>
<ContactInfo class="mt-5" />
</template>
</v-card-text>

<v-divider class="my-0" />

<v-card-actions>
<v-spacer />
<v-btn
id="dialog-close-button"
color="primary"
text
@click="close()"
>
Close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>

<script lang="ts">
import { Component, Prop, Emit, Vue } from 'vue-property-decorator'
import { Getter } from 'pinia-class'
import { ContactInfo } from '@/components/common'
import { useRootStore } from '@/stores'
@Component({
components: { ContactInfo }
})
export default class TechnicalErrorDialog extends Vue {
// Getter to check if logged in user is Staff.
@Getter(useRootStore) isRoleStaff!: boolean
/** Prop to display the dialog. */
@Prop({ default: false }) readonly dialog!: boolean
/** Prop to provide attachment selector. */
@Prop({ default: '' }) readonly attach!: string
// Pass click event to parent.
@Emit() close () {}
}
</script>
4 changes: 3 additions & 1 deletion src/components/dialogs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import PaymentErrorDialog from './PaymentErrorDialog.vue'
import ResumeErrorDialog from './ResumeErrorDialog.vue'
import SaveErrorDialog from './SaveErrorDialog.vue'
import StaffPaymentDialog from './StaffPaymentDialog.vue'
import TechnicalErrorDialog from './TechnicalErrorDialog.vue'

export {
AddCommentDialog,
Expand All @@ -41,5 +42,6 @@ export {
PaymentErrorDialog,
ResumeErrorDialog,
SaveErrorDialog,
StaffPaymentDialog
StaffPaymentDialog,
TechnicalErrorDialog
}
9 changes: 9 additions & 0 deletions src/enums/amalgamationEnums.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export enum AmlRoles {
AMALGAMATING = 'amalgamating',
HOLDING = 'holding'
}

export enum AmlTypes {
LEAR = 'lear',
FOREIGN = 'foreign'
}
1 change: 1 addition & 0 deletions src/enums/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './actions'
export * from './allowableActions'
export * from './amalgamationEnums'
export * from './applicationTypes'
export * from './correctionTypes'
export * from './effectOfOrderTypes'
Expand Down
20 changes: 16 additions & 4 deletions src/services/legal-services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ export default class LegalServices {
if (isDraft) {
url += '?draft=true'
}

return axios.post(url, { filing })
.then(response => {
const filing = response?.data?.filing
Expand All @@ -168,13 +169,23 @@ export default class LegalServices {
}

/**
* Creates (posts) a draft (temporary) business record.
* Must be logged in to use this.
* Throws an exception on error.
* Creates (posts) a draft business record, which is used to bootstrap a new business.
* @param businessRequest the object body of the request
* @returns the filing object associated with the temporary business
*/
static async createBusiness (businessRequest: any): Promise<any> {
static async createDraftBusiness (businessRequest: any): Promise<any> {
const url = `businesses?draft=true`

return axios.post(url, businessRequest)
.then(response => {
const filing = response?.data?.filing
if (!filing) {
// eslint-disable-next-line no-console
console.log('createDraftBusiness() error - invalid response =', response)
throw new Error('Invalid filing')
}
return filing
})
}

/**
Expand All @@ -190,6 +201,7 @@ export default class LegalServices {
if (isDraft) {
url += '?draft=true'
}

return axios.put(url, { filing })
.then(response => {
const filing = response?.data?.filing
Expand Down
77 changes: 52 additions & 25 deletions src/views/AmalgamationSelection.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<template>
<div id="amalgamation-selection">
<TechnicalErrorDialog
:dialog="showErrorDialog"
attach="#amalgamation-selection"
@close="showErrorDialog = false"
/>

<!-- Main Body -->
<v-container class="view-container">
<v-row>
Expand Down Expand Up @@ -145,22 +151,29 @@ import { Action, Getter } from 'pinia-class'
import { Component, Vue } from 'vue-property-decorator'
import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module'
import { AmalgamationTypes, FilingTypes } from '@bcrs-shared-components/enums'
import { Routes } from '@/enums'
import { AmlRoles, AmlTypes, Routes } from '@/enums'
import { LegalServices } from '@/services'
import { navigate } from '@/utils'
import { TechnicalErrorDialog } from '@/components/dialogs'
@Component({})
@Component({
components: {
TechnicalErrorDialog
}
})
export default class AmalgamationSelection extends Vue {
@Getter(useConfigurationStore) getCreateUrl!: string
@Getter(useBusinessStore) getIdentifier!: string
@Getter(useBusinessStore) getLegalType!: string
@Getter(useBusinessStore) getLegalType!: CorpTypeCd
@Getter(useBusinessStore) isBComp!: boolean
@Getter(useBusinessStore) isBcCompany!: boolean
@Getter(useBusinessStore) isCcc!: boolean
@Getter(useBusinessStore) isUlc!: boolean
@Action(useRootStore) setStartingAmalgamationSpinner!: (x: boolean) => void
showErrorDialog = false
/** Called when component is created. */
created (): void {
const filingId = +this.$route.params.filingId // id param of this selection panel route, must be 0
Expand All @@ -171,63 +184,77 @@ export default class AmalgamationSelection extends Vue {
}
}
/** Get the amalmagated company result name depending on the type. */
/** The amalmagated company result name depending on the type. */
getRegularAmalgamationText (): string {
if (this.isBComp || this.isBcCompany) return 'BC limited company'
if (this.isCcc) return 'BC community contribution company'
if (this.isUlc) return 'BC unlimited liability company'
return 'Unknown'
}
/** Start Regular Long-form button pressed. */
/** Called when Start Regular Long-form button is clicked. */
async startRegularAmalgamation (): Promise<any> {
const legalType = this.getLegalType as CorpTypeCd
// Create a draft amalgamation and redirect to Create UI
// Create a draft amalgamation application then redirect to Create UI.
try {
// show spinner since this is a network call
this.setStartingAmalgamationSpinner(true)
const accountId = +JSON.parse(sessionStorage.getItem('CURRENT_ACCOUNT'))?.id || 0
const businessId = await this.createBusinessAA(accountId, legalType, AmalgamationTypes.REGULAR)
const businessId = await this.createBusinessAA(AmalgamationTypes.REGULAR)
const amalgamationUrl = `${this.getCreateUrl}?id=${businessId}`
navigate(amalgamationUrl)
return
} catch (error) {
console.log('Error: unable to amalgamate now =', error)
this.setStartingAmalgamationSpinner(false)
throw new Error('Unable to Amalgamate Now ' + error)
this.showErrorDialog = true
}
}
/**
* Create a draft amalgamation application based on selected business type.
* @param accountId Account ID of logged in user.
* @param legalType The legal type of the amalgamated business
* Creates a draft amalgamation application.
* @param type the type of amalgamation to create
* @returns the business identifier of the newly created amalgamation application
*/
async createBusinessAA (accountId: number, legalType: CorpTypeCd, type: AmalgamationTypes): Promise<string> {
const businessRequest = {
private async createBusinessAA (type: AmalgamationTypes): Promise<string> {
const accountId = +JSON.parse(sessionStorage.getItem('CURRENT_ACCOUNT'))?.id || 0
const legalType = this.getLegalType
const draftAmalgamationApplication = {
filing: {
header: {
name: FilingTypes.AMALGAMATION_APPLICATION,
accountId: accountId
accountId
},
business: {
legalType: legalType
legalType
},
amalgamationApplication: {
nameRequest: {
legalType: legalType
legalType
},
type: type
type
}
}
} as any
const createBusinessResponse =
await LegalServices.createBusiness(businessRequest).catch(error => {
throw new Error('Unable to create new Amalgamation Draft ' + error)
})
// if this is a regular amalgamation, pre-populate the current business as a TING
if (type === AmalgamationTypes.REGULAR) {
draftAmalgamationApplication.filing.amalgamationApplication.amalgamatingBusinesses = [
{
type: AmlTypes.LEAR,
role: AmlRoles.AMALGAMATING,
identifier: this.getIdentifier
}
]
}
// create the draft business record
// (throws an exception on error, which startRegularAmalgamation() will handle)
const filing = await LegalServices.createDraftBusiness(draftAmalgamationApplication)
return createBusinessResponse.data?.filing?.business?.identifier as string
// validate and return the identifier
const identifier = filing?.business?.identifier as string
if (!identifier) throw new Error('Invalid business identifier')
return identifier
}
}
</script>
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/AmalgamationSelection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('AmalgamationSelection', () => {
})

it('start regular long-form button clicked', async () => {
const createFiling = vi.spyOn((LegalServices as any), 'createBusiness')
const createFiling = vi.spyOn((LegalServices as any), 'createDraftBusiness')
const button = wrapper.find('#regular-long-form-btn')
await button.trigger('click')

Expand Down
43 changes: 43 additions & 0 deletions tests/unit/TechnicalErrorDialog.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import Vue from 'vue'
import Vuetify from 'vuetify'
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { useRootStore } from '@/stores'
import TechnicalErrorDialog from '@/components/dialogs/TechnicalErrorDialog.vue'
import { ContactInfo } from '@/components/common'

Vue.use(Vuetify)

const vuetify = new Vuetify({})
setActivePinia(createPinia())
const rootStore = useRootStore()

describe('TechnicalErrorDialog', () => {
it('displays everything for normal users', () => {
// init store
rootStore.keycloakRoles = ['']

const wrapper = mount(TechnicalErrorDialog, { propsData: { dialog: true }, vuetify })

expect(wrapper.find('.v-card__title').text()).toBe('Error')
expect(wrapper.find('.v-card__text').text())
.toContain('We could not process your action due to a technical issue.')
expect(wrapper.find('.v-card__text').text())
.toContain('If this error persists, please contact BC Registries staff:')
expect(wrapper.findComponent(ContactInfo).exists()).toBe(true)
expect(wrapper.find('.v-card__actions').text()).toBe('Close')

wrapper.destroy()
})

it('does not display contact info for staff users', () => {
// init store
rootStore.keycloakRoles = ['staff']

const wrapper = mount(TechnicalErrorDialog, { propsData: { dialog: true }, vuetify })

expect(wrapper.findComponent(ContactInfo).exists()).toBe(false)

wrapper.destroy()
})
})

0 comments on commit 53ab148

Please sign in to comment.