diff --git a/auth-web/package-lock.json b/auth-web/package-lock.json index 4c98344ba..15ebf66e2 100644 --- a/auth-web/package-lock.json +++ b/auth-web/package-lock.json @@ -1,12 +1,12 @@ { "name": "auth-web", - "version": "2.6.126", + "version": "2.6.127", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "auth-web", - "version": "2.6.126", + "version": "2.6.127", "dependencies": { "@bcrs-shared-components/base-address": "2.0.3", "@bcrs-shared-components/bread-crumb": "1.0.8", diff --git a/auth-web/package.json b/auth-web/package.json index 8a241e2ab..2e4eff78c 100644 --- a/auth-web/package.json +++ b/auth-web/package.json @@ -1,6 +1,6 @@ { "name": "auth-web", - "version": "2.6.126", + "version": "2.6.127", "appName": "Auth Web", "sbcName": "SBC Common Components", "private": true, diff --git a/auth-web/src/services/business.services.ts b/auth-web/src/services/business.services.ts index e1c888755..012567b80 100644 --- a/auth-web/src/services/business.services.ts +++ b/auth-web/src/services/business.services.ts @@ -48,6 +48,10 @@ export default class BusinessService { return axios.get(`${ConfigHelper.getLegalAPIV2Url()}/businesses/${businessRegNumber}/filings`) } + static async searchFiling (filingID: string): Promise> { + return axios.get(`${ConfigHelper.getLegalAPIV2Url()}/businesses/filings/search/${filingID}`) + } + static async updateFolioNumber (folioNumber: FolioNumberload): Promise> { return axios.patch(`${ConfigHelper.getAuthAPIUrl()}/entities/${folioNumber.businessIdentifier}`, folioNumber) } diff --git a/auth-web/src/stores/business.ts b/auth-web/src/stores/business.ts index 0697192ff..1086a6527 100644 --- a/auth-web/src/stores/business.ts +++ b/auth-web/src/stores/business.ts @@ -37,7 +37,8 @@ export const useBusinessStore = defineStore('business', () => { const state = reactive({ currentBusiness: undefined as Business, businesses: [] as Business[], - removeExistingAffiliationInvitation: false + removeExistingAffiliationInvitation: false, + filingID: '' }) function $reset () { @@ -268,6 +269,26 @@ export const useBusinessStore = defineStore('business', () => { } } + async function loadFiling () { + const filingID = ConfigHelper.getFromSession(SessionStorageKeys.FilingIdentifierKey) + state.filingID = filingID + const response = await BusinessService.searchFiling(filingID).catch(() => null) + if (response?.status === 200) { + const businessIdentifier = response?.data.filing.business.identifier + ConfigHelper.addToSession(SessionStorageKeys.BusinessIdentifierKey, businessIdentifier) + + if (!state.currentBusiness) { + state.currentBusiness = {} as Business + } + + state.currentBusiness.businessIdentifier = businessIdentifier + } else if (response?.status === 404) { + throw Error('No match found for Filing Number') + } else { + throw Error('Search failed') + } + } + async function addBusiness (payload: LoginPayload) { const requestBody: CreateAffiliationRequestBody = { businessIdentifier: payload.businessIdentifier, @@ -558,6 +579,11 @@ export const useBusinessStore = defineStore('business', () => { ConfigHelper.removeFromSession(SessionStorageKeys.BusinessIdentifierKey) } + function resetFilingID (): void { + state.filingID = '' + ConfigHelper.removeFromSession(SessionStorageKeys.FilingIdentifierKey) + } + async function resetBusinessPasscode (passCodeResetLoad: PasscodeResetLoad) { await BusinessService.resetBusinessPasscode(passCodeResetLoad) } @@ -571,6 +597,7 @@ export const useBusinessStore = defineStore('business', () => { currentOrganization, syncBusinesses, loadBusiness, + loadFiling, addBusiness, addNameRequest, createNamedBusiness, @@ -589,6 +616,7 @@ export const useBusinessStore = defineStore('business', () => { saveContact, updateFolioNumber, resetCurrentBusiness, + resetFilingID, resetBusinessPasscode, searchNRIndex, setRemoveExistingAffiliationInvitation, diff --git a/auth-web/src/util/constants.ts b/auth-web/src/util/constants.ts index 510dc6878..68ba64a55 100644 --- a/auth-web/src/util/constants.ts +++ b/auth-web/src/util/constants.ts @@ -3,6 +3,7 @@ export enum SessionStorageKeys { KeyCloakToken = 'KEYCLOAK_TOKEN', ApiConfigKey = 'AUTH_API_CONFIG', BusinessIdentifierKey = 'BUSINESS_ID', + FilingIdentifierKey = 'FILING_ID', CurrentAccount = 'CURRENT_ACCOUNT', LaunchDarklyFlags = 'LD_FLAGS', ExtraProvincialUser = 'EXTRAPROVINCIAL_USER', diff --git a/auth-web/src/views/auth/staff/IncorporationSearchResultView.vue b/auth-web/src/views/auth/staff/IncorporationSearchResultView.vue index bb4da6200..459d51fdc 100644 --- a/auth-web/src/views/auth/staff/IncorporationSearchResultView.vue +++ b/auth-web/src/views/auth/staff/IncorporationSearchResultView.vue @@ -83,6 +83,7 @@ export default class IncorporationSearchResultView extends Vue { @Action(useOrgStore) readonly syncMembership!: (affiliatedOrganizationId: number) => Promise @Action(useOrgStore) readonly setCurrentAccountSettings!: (accountSettings: AccountSettings) => void @State(useBusinessStore) currentBusiness!: Business + @State(useBusinessStore) filingID!: string @Prop({ default: false }) isVisible: boolean @Prop() affiliatedOrg: Organization @@ -94,9 +95,9 @@ export default class IncorporationSearchResultView extends Vue { get actions (): object[] { if (this.isThereAnAffiliatedAccount) { return [ - { title: 'Entity Dashboard', + { title: 'Manage Business', icon: 'mdi-view-dashboard', - event: this.entityDashboardEvent + event: this.manageBusinessEvent }, { title: 'Manage Account', icon: 'mdi-domain', @@ -105,9 +106,9 @@ export default class IncorporationSearchResultView extends Vue { ] } else { return [ - { title: 'Entity Dashboard', + { title: 'Manage Business', icon: 'mdi-view-dashboard', - event: this.entityDashboardEvent + event: this.manageBusinessEvent }, { title: 'Generate Passcode', icon: 'mdi-lock-outline', @@ -122,7 +123,7 @@ export default class IncorporationSearchResultView extends Vue { name: this.currentBusiness?.name, orgType: this.affiliatedOrg?.orgType, account: this.affiliatedOrg?.name || 'No Affiliation', - businessIdentifier: this.currentBusiness?.businessIdentifier, + businessIdentifier: this.filingID || this.currentBusiness?.businessIdentifier, businessNumber: this.currentBusiness?.businessNumber, accessType: this.affiliatedOrg?.accessType, statusCode: this.affiliatedOrg?.statusCode @@ -137,7 +138,7 @@ export default class IncorporationSearchResultView extends Vue { width: '25%' }, { - text: 'Entity#', + text: 'Number', align: 'left', sortable: false, value: 'businessIdentifier', @@ -176,8 +177,17 @@ export default class IncorporationSearchResultView extends Vue { return orgTypeDisplay } - async entityDashboardEvent () { - window.location.href = `${ConfigHelper.getBusinessURL()}${this.currentBusiness.businessIdentifier}` + async manageBusinessEvent () { + const businessIdentifier = this.currentBusiness.businessIdentifier + const filingId = this.filingID + + let url = `${ConfigHelper.getBusinessURL()}${businessIdentifier}` + + if (filingId) { + url += `?filing_id=${filingId}` + } + + window.location.href = url } async manageAccountEvent () { @@ -188,7 +198,7 @@ export default class IncorporationSearchResultView extends Vue { this.$router.push(`/account/${this.currentOrganization.id}/business`) } catch (error) { // eslint-disable-next-line no-console - console.log('Error during entity dashboard click event!') + console.log('Error during manage business click event!') } } diff --git a/auth-web/src/views/auth/staff/StaffDashboardView.vue b/auth-web/src/views/auth/staff/StaffDashboardView.vue index 1e3447e76..b519ce446 100644 --- a/auth-web/src/views/auth/staff/StaffDashboardView.vue +++ b/auth-web/src/views/auth/staff/StaffDashboardView.vue @@ -70,7 +70,7 @@

- Find an existing business to manage: + Find a business or filing number:

@@ -81,28 +81,28 @@ icon="mdi-alert-circle" class="mb-0" > - {{ errorMessage }} {{ searchedBusinessNumber }} + {{ errorMessage }} {{ searchedIdentifierNumber }} @@ -323,8 +323,8 @@ import { useUserStore } from '@/stores/user' // FUTURE: remove after vue 3 upgrade interface StaffDashboardViewI { - businessIdentifier: string - searchedBusinessNumber: string + searchIdentifier: string + searchedIdentifierNumber: string searchActive: boolean errorMessage: string canViewIncorporationSearchResult: boolean @@ -354,7 +354,7 @@ export default defineComponent({ Transactions }, setup (props, { root }) { - const searchBusinessForm: Ref = ref(null) + const searchIdentifierForm: Ref = ref(null) const emailToAdd = ref(null) const safeEmailView = ref(null) const businessStore = useBusinessStore() @@ -363,14 +363,14 @@ export default defineComponent({ const currentOrganization = computed(() => orgStore.currentOrganization) const currentUser = computed(() => userStore.currentUser) - const businessIdentifierRules = [ - v => !!v || 'Incorporation Number or Registration Number is required', - v => CommonUtils.validateIncorporationNumber(v) || 'Incorporation Number or Registration Number is not valid' + const searchIdentifierRules = [ + v => !!v || 'Incorporation, registration or filing number is required', + v => CommonUtils.validateIncorporationNumber(v) || 'Incorporation, registration or filing number is not valid' ] const localVars = (reactive({ affiliatedOrg: {}, - businessIdentifier: '', + searchIdentifier: '', canSearchFAS: computed((): boolean => currentUser.value?.roles?.includes(Role.FasSearch)), canViewAccounts: computed((): boolean => currentUser.value?.roles?.includes(Role.StaffViewAccounts)), canViewAllTransactions: computed((): boolean => currentUser.value?.roles?.includes(Role.ViewAllTransactions)), @@ -382,14 +382,14 @@ export default defineComponent({ registrySearchUrl: computed((): string => ConfigHelper.getRegistrySearchUrl()), documentsUiUrl: computed((): string => ConfigHelper.getBcrosDocumentsUiURL()), searchActive: false, - searchedBusinessNumber: '', + searchedIdentifierNumber: '', showBusSearchlink: computed((): boolean => true), showInvoluntaryDissolutionTile: computed((): boolean => LaunchDarklyService.getFlag(LDFlags.EnableInvoluntaryDissolution) || false), showDrsTile: computed((): boolean => LaunchDarklyService.getFlag(LDFlags.EnableDRSLookup) || false) }) as unknown) as StaffDashboardViewI - const isFormValid = () => localVars.businessIdentifier && searchBusinessForm.value?.validate() + const isFormValid = () => localVars.searchIdentifier && searchIdentifierForm.value?.validate() const goToInvoluntaryDissolution = () => root.$router.push(`/staff/involuntary-dissolution`) @@ -415,6 +415,20 @@ export default defineComponent({ } ] + const isFilingID = (identifier: string) => { + // Check if the identifier contains only numeric characters + return /^\d+$/.test(identifier) + } + + const isTempBusiness = (identifier: string) => { + return identifier.charAt(0).toUpperCase() === 'T' + } + + const resetSearchState = () => { + businessStore.resetCurrentBusiness() + businessStore.resetFilingID() + } + const updateCurrentBusiness = async () => { try { // Search for business, action will set session storage @@ -428,20 +442,44 @@ export default defineComponent({ } } + const fetchFiling = async () => { + try { + await businessStore.loadFiling() + localVars.affiliatedOrg = await orgStore.getOrganizationForAffiliate() + localVars.canViewIncorporationSearchResult = true + } catch (exception) { + localVars.errorMessage = exception?.message + localVars.canViewIncorporationSearchResult = false + businessStore.resetFilingID() + } + } + const search = async () => { + resetSearchState() + if (isFormValid()) { localVars.searchActive = true try { - ConfigHelper.addToSession(SessionStorageKeys.BusinessIdentifierKey, localVars.businessIdentifier) localVars.errorMessage = '' - await updateCurrentBusiness() + + if (isFilingID(localVars.searchIdentifier)) { + ConfigHelper.addToSession(SessionStorageKeys.FilingIdentifierKey, localVars.searchIdentifier) + await fetchFiling() + } else { + ConfigHelper.addToSession(SessionStorageKeys.BusinessIdentifierKey, localVars.searchIdentifier) + } + + const businessIdentifier = ConfigHelper.getFromSession(SessionStorageKeys.BusinessIdentifierKey) + if (!isTempBusiness(businessIdentifier)) { + await updateCurrentBusiness() + } } catch (exception) { - localVars.searchedBusinessNumber = localVars.businessIdentifier + localVars.searchedIdentifierNumber = localVars.searchIdentifier businessStore.resetCurrentBusiness() // FUTURE: get this from t(noIncorporationNumberFound) // having trouble with composition version of $t in the build. - localVars.errorMessage = 'No match found for Incorporation Number' + localVars.errorMessage = 'No match found for business, registration or filing number' localVars.canViewIncorporationSearchResult = false } finally { localVars.searchActive = false @@ -455,9 +493,10 @@ export default defineComponent({ window.location.href.includes('test.account') ) - const formatBusinessIdentifier = () => { - localVars.businessIdentifier = - CommonUtils.formatIncorporationNumber(localVars.businessIdentifier) + const formatSearchIdentifier = () => { + if (!isFilingID(localVars.searchIdentifier)) { + localVars.searchIdentifier = CommonUtils.formatIncorporationNumber(localVars.searchIdentifier) + } } async function addEmail () { @@ -483,15 +522,16 @@ export default defineComponent({ } return { - businessIdentifierRules, - formatBusinessIdentifier, + searchIdentifierRules, + formatSearchIdentifier, goToInvoluntaryDissolution, goToManageBusiness, isDevOrTest, safeEmailView, isFormValid, + isFilingID, search, - searchBusinessForm, + searchIdentifierForm, emailToAdd, addEmail, launchTileConfig, diff --git a/auth-web/tests/unit/views/StaffDashboard/SearchBusinessView.spec.ts b/auth-web/tests/unit/views/StaffDashboard/SearchBusinessView.spec.ts index 7ea9dc232..64b7dac71 100644 --- a/auth-web/tests/unit/views/StaffDashboard/SearchBusinessView.spec.ts +++ b/auth-web/tests/unit/views/StaffDashboard/SearchBusinessView.spec.ts @@ -55,7 +55,7 @@ describe('StaffDashboardView.vue', () => { vuetify, mocks: { isFormValid } }) - cmp.setData({ businessIdentifier: 'CP0000000' }) + cmp.setData({ searchIdentifier: 'CP0000000' }) vi.resetModules() vi.clearAllMocks() @@ -66,7 +66,7 @@ describe('StaffDashboardView.vue', () => { }) it('incorporation number is not empty', () => { - expect(cmp.vm.businessIdentifier).toBe('CP0000000') + expect(cmp.vm.searchIdentifier).toBe('CP0000000') }) it('enter button click invokes isFormValid method', async () => {