diff --git a/alcs-frontend/src/app/features/search/application-search-table/application-search-table.component.html b/alcs-frontend/src/app/features/search/application-search-table/application-search-table.component.html index c6e17a4846..2ee164f4c6 100644 --- a/alcs-frontend/src/app/features/search/application-search-table/application-search-table.component.html +++ b/alcs-frontend/src/app/features/search/application-search-table/application-search-table.component.html @@ -46,14 +46,13 @@ - + Portal Status - diff --git a/alcs-frontend/src/app/features/search/application-search-table/application-search-table.component.ts b/alcs-frontend/src/app/features/search/application-search-table/application-search-table.component.ts index ae4c2cf1a7..a45e8128e3 100644 --- a/alcs-frontend/src/app/features/search/application-search-table/application-search-table.component.ts +++ b/alcs-frontend/src/app/features/search/application-search-table/application-search-table.component.ts @@ -19,7 +19,7 @@ interface SearchResult { referenceId: string; board?: string; class: string; - status?: ApplicationSubmissionStatusPill | null; + status?: ApplicationSubmissionStatusPill; } @Component({ @@ -42,7 +42,7 @@ export class ApplicationSearchTableComponent { @Output() tableChange = new EventEmitter(); - displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'status']; + displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'portalStatus']; dataSource: SearchResult[] = []; itemsPerPage = 20; total = 0; @@ -88,22 +88,24 @@ export class ApplicationSearchTableComponent { private mapApplications(applications: ApplicationSearchResultDto[]): SearchResult[] { return applications.map((e) => { const status = this.statuses.find((st) => st.code === e.status); + return { fileNumber: e.fileNumber, dateSubmitted: e.dateSubmitted, ownerName: e.ownerName, type: e.type, localGovernmentName: e.localGovernmentName, + portalStatus: e.portalStatus, referenceId: e.referenceId, board: e.boardCode, class: e.class, - status: status ? { - backgroundColor: status.portalBackgroundColor ?? defaultStatusBackgroundColour, - textColor: status.portalColor ?? defaultStatusColour, - borderColor: status.portalBackgroundColor, - label: status.label, - shortLabel: status.label, - } : null, + status: { + backgroundColor: status?.portalBackgroundColor ?? defaultStatusBackgroundColour, + textColor: status?.portalColor ?? defaultStatusColour, + borderColor: status?.portalBackgroundColor, + label: status?.label, + shortLabel: status?.label, + }, }; }); } diff --git a/alcs-frontend/src/app/features/search/notice-of-intent-search-table/notice-of-intent-search-table.component.html b/alcs-frontend/src/app/features/search/notice-of-intent-search-table/notice-of-intent-search-table.component.html index 38f446c755..ef901b754b 100644 --- a/alcs-frontend/src/app/features/search/notice-of-intent-search-table/notice-of-intent-search-table.component.html +++ b/alcs-frontend/src/app/features/search/notice-of-intent-search-table/notice-of-intent-search-table.component.html @@ -46,14 +46,13 @@ - + Portal Status - diff --git a/alcs-frontend/src/app/features/search/notice-of-intent-search-table/notice-of-intent-search-table.component.ts b/alcs-frontend/src/app/features/search/notice-of-intent-search-table/notice-of-intent-search-table.component.ts index b6cdd0a68b..b32404ce25 100644 --- a/alcs-frontend/src/app/features/search/notice-of-intent-search-table/notice-of-intent-search-table.component.ts +++ b/alcs-frontend/src/app/features/search/notice-of-intent-search-table/notice-of-intent-search-table.component.ts @@ -19,7 +19,7 @@ interface SearchResult { referenceId: string; board?: string; class: string; - status?: ApplicationSubmissionStatusPill | null; + status?: ApplicationSubmissionStatusPill; } @Component({ @@ -41,7 +41,7 @@ export class NoticeOfIntentSearchTableComponent { @Output() tableChange = new EventEmitter(); - displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'status']; + displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'portalStatus']; dataSource: SearchResult[] = []; itemsPerPage = 20; @@ -98,13 +98,13 @@ export class NoticeOfIntentSearchTableComponent { referenceId: e.referenceId, board: e.boardCode, class: e.class, - status: status ? { + status: { backgroundColor: status!.alcsBackgroundColor, textColor: status!.alcsColor, borderColor: status!.alcsBackgroundColor, label: status!.label, shortLabel: status!.label, - } : null, + }, }; }); } diff --git a/alcs-frontend/src/app/features/search/notification-search-table/notification-search-table.component.html b/alcs-frontend/src/app/features/search/notification-search-table/notification-search-table.component.html index 885029dc2f..fae38aa644 100644 --- a/alcs-frontend/src/app/features/search/notification-search-table/notification-search-table.component.html +++ b/alcs-frontend/src/app/features/search/notification-search-table/notification-search-table.component.html @@ -46,14 +46,13 @@ - + Portal Status - diff --git a/alcs-frontend/src/app/features/search/notification-search-table/notification-search-table.component.ts b/alcs-frontend/src/app/features/search/notification-search-table/notification-search-table.component.ts index 8cece56bf5..040428f3f2 100644 --- a/alcs-frontend/src/app/features/search/notification-search-table/notification-search-table.component.ts +++ b/alcs-frontend/src/app/features/search/notification-search-table/notification-search-table.component.ts @@ -18,7 +18,7 @@ interface SearchResult { referenceId: string; board?: string; class: string; - status?: ApplicationSubmissionStatusPill | null; + status?: ApplicationSubmissionStatusPill; } @Component({ @@ -41,7 +41,7 @@ export class NotificationSearchTableComponent { @Output() tableChange = new EventEmitter(); - displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'status']; + displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'portalStatus']; dataSource: SearchResult[] = []; itemsPerPage = 20; total = 0; @@ -97,13 +97,13 @@ export class NotificationSearchTableComponent { referenceId: e.referenceId, board: e.boardCode, class: e.class, - status: status ? { + status: { backgroundColor: status ? status!.alcsBackgroundColor : '', textColor: status ? status!.alcsColor : '', borderColor: status ? status!.alcsBackgroundColor : '', label: status ? status!.label : '', shortLabel: status ? status!.label : '', - } : null, + }, }; }); } diff --git a/alcs-frontend/src/app/features/search/search.component.html b/alcs-frontend/src/app/features/search/search.component.html index de78eb202a..051424f118 100644 --- a/alcs-frontend/src/app/features/search/search.component.html +++ b/alcs-frontend/src/app/features/search/search.component.html @@ -331,7 +331,7 @@

Date Range

Search Results:

- + Applications: {{ applicationTotal }} (a.label > b.label ? 1 : -1)); } - - private async updateApplicationStatuses() { - const needsUpdate = this.applications.filter((a) => a.status === null).length > 0; - if (!needsUpdate) return; - const statusUpdates = await this.searchService.advancedSearchApplicationStatusFetch( - this.applications.map((a) => a.fileNumber) - ); - this.applications = this.applications.map((a) => { - const updatedStatus = statusUpdates ? statusUpdates.find((s) => s.fileNumber === a.fileNumber) : null; - return { - ...a, - status: updatedStatus ? updatedStatus.status : '', - } - }); - } - - private async updateNoiStatuses() { - const needsUpdate = this.noticeOfIntents.filter((a) => a.status === null).length > 0; - if (!needsUpdate) return; - const statusUpdates = await this.searchService.advancedSearchNoiStatusFetch( - this.noticeOfIntents.map((a) => a.fileNumber) - ); - this.noticeOfIntents = this.noticeOfIntents.map((a) => { - const updatedStatus = statusUpdates ? statusUpdates.find((s) => s.fileNumber === a.fileNumber) : null; - return { - ...a, - status: updatedStatus ? updatedStatus.status : '', - } - }); - } - - private async updateNotificationStatuses() { - const needsUpdate = this.notifications.filter((a) => a.status === null).length > 0; - if (!needsUpdate) return; - const statusUpdates = await this.searchService.advancedSearchNotificationStatusFetch( - this.notifications.map((a) => a.fileNumber) - ); - this.notifications = this.notifications.map((a) => { - const updatedStatus = statusUpdates ? statusUpdates.find((s) => s.fileNumber === a.fileNumber) : null; - return { - ...a, - status: updatedStatus ? updatedStatus.status : '', - } - }); - } } diff --git a/alcs-frontend/src/app/features/search/search.module.ts b/alcs-frontend/src/app/features/search/search.module.ts index ef3edde8d0..5484fb5684 100644 --- a/alcs-frontend/src/app/features/search/search.module.ts +++ b/alcs-frontend/src/app/features/search/search.module.ts @@ -13,7 +13,6 @@ import { NotificationSearchTableComponent } from './notification-search-table/no import { SearchComponent } from './search.component'; import { InquirySearchTableComponent } from './inquiry-search-table/inquiry-search-table.component'; import { MatChipsModule } from '@angular/material/chips'; -import { SpinnerStatusComponent } from './spinner-status/spinner-status.component'; const routes: Routes = [ { @@ -31,7 +30,6 @@ const routes: Routes = [ NotificationSearchTableComponent, FileTypeFilterDropDownComponent, InquirySearchTableComponent, - SpinnerStatusComponent, ], imports: [ CommonModule, diff --git a/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.html b/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.html deleted file mode 100644 index 8110a6a901..0000000000 --- a/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.scss b/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.scss deleted file mode 100644 index 51e336567d..0000000000 --- a/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.scss +++ /dev/null @@ -1,12 +0,0 @@ -.spinner-container { - width: 25px; - height: 25px; - display: flex; - align-items: center; - justify-content: center; -} - -.spinner-overlay { - z-index: 2; - opacity: 0.4; -} diff --git a/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.ts b/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.ts deleted file mode 100644 index 7a5e71245d..0000000000 --- a/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-spinner-status', - templateUrl: './spinner-status.component.html', - styleUrls: ['./spinner-status.component.scss'], -}) -export class SpinnerStatusComponent {} diff --git a/alcs-frontend/src/app/services/search/search.dto.ts b/alcs-frontend/src/app/services/search/search.dto.ts index a99e3fe84a..c5f2d6ea8a 100644 --- a/alcs-frontend/src/app/services/search/search.dto.ts +++ b/alcs-frontend/src/app/services/search/search.dto.ts @@ -11,7 +11,7 @@ export interface ApplicationSearchResultDto { dateSubmitted: number; portalStatus?: string; class: string; - status?: string | null; + status: string; } export interface NoticeOfIntentSearchResultDto extends ApplicationSearchResultDto {} @@ -93,8 +93,3 @@ export interface SearchResultDto { boardCode?: string; label?: ApplicationTypeDto; } - -export interface StatusUpdateSearchResultDto { - fileNumber: string; - status: string; -} diff --git a/alcs-frontend/src/app/services/search/search.service.ts b/alcs-frontend/src/app/services/search/search.service.ts index 3e0dcd44a3..9a019340bf 100644 --- a/alcs-frontend/src/app/services/search/search.service.ts +++ b/alcs-frontend/src/app/services/search/search.service.ts @@ -13,7 +13,6 @@ import { PlanningReviewSearchResultDto, SearchRequestDto, SearchResultDto, - StatusUpdateSearchResultDto, } from './search.dto'; @Injectable({ @@ -46,7 +45,7 @@ export class SearchService { return undefined; } } - + async advancedSearchApplicationsFetch(searchDto: SearchRequestDto) { try { return await firstValueFrom( @@ -62,51 +61,6 @@ export class SearchService { } } - async advancedSearchApplicationStatusFetch(fileNumbers: string[]) { - try { - return await firstValueFrom( - this.http.post( - `${this.baseUrl}/advanced/application-status`, - fileNumbers, - ), - ); - } catch (e) { - console.error(e); - this.toastService.showErrorToast(`Application Status search failed. Please refresh the page and try again`); - return undefined; - } - } - - async advancedSearchNoiStatusFetch(fileNumbers: string[]) { - try { - return await firstValueFrom( - this.http.post( - `${this.baseUrl}/advanced/noi-status`, - fileNumbers, - ), - ); - } catch (e) { - console.error(e); - this.toastService.showErrorToast(`Notice of Intent search failed. Please refresh the page and try again`); - return undefined; - } - } - - async advancedSearchNotificationStatusFetch(fileNumbers: string[]) { - try { - return await firstValueFrom( - this.http.post( - `${this.baseUrl}/advanced/notification-status`, - fileNumbers, - ), - ); - } catch (e) { - console.error(e); - this.toastService.showErrorToast(`Notification search failed. Please refresh the page and try again`); - return undefined; - } - } - async advancedSearchNoticeOfIntentsFetch(searchDto: SearchRequestDto) { try { return await firstValueFrom( diff --git a/services/apps/alcs/src/alcs/search/application/application-advanced-search.service.ts b/services/apps/alcs/src/alcs/search/application/application-advanced-search.service.ts index 80a08ebe80..a10a45509d 100644 --- a/services/apps/alcs/src/alcs/search/application/application-advanced-search.service.ts +++ b/services/apps/alcs/src/alcs/search/application/application-advanced-search.service.ts @@ -13,7 +13,6 @@ import { LocalGovernment } from '../../local-government/local-government.entity' import { SEARCH_CACHE_TIME } from '../search.config'; import { AdvancedSearchResultDto, SearchRequestDto } from '../search.dto'; import { ApplicationSubmissionSearchView } from './application-search-view.entity'; -import { ApplicationSubmissionStatusSearchView } from '../status/application-search-status-view.entity'; @Injectable() export class ApplicationAdvancedSearchService { @@ -63,20 +62,13 @@ export class ApplicationAdvancedSearchService { fileNumbers: [...fileNumbers.values()], }); - if (searchDto.sortField === 'status') { - query = query.innerJoin( - ApplicationSubmissionStatusSearchView, - 'app_status', - 'app_status.file_number = "appSearch"."file_number"', - ); - } - const sortQuery = this.compileSortQuery(searchDto); query = query .orderBy(sortQuery, searchDto.sortDirection, searchDto.sortDirection === 'ASC' ? 'NULLS FIRST' : 'NULLS LAST') .offset((searchDto.page - 1) * searchDto.pageSize) .limit(searchDto.pageSize); + const t0 = performance.now(); const results = await Promise.all([query.getMany(), query.getCount()]); const t1 = performance.now(); @@ -102,8 +94,8 @@ export class ApplicationAdvancedSearchService { case 'government': return '"appSearch"."local_government_name"'; - case 'status': - return `"app_status"."status" ->> 'label' `; + case 'portalStatus': + return `"appSearch"."status" ->> 'label' `; default: case 'dateSubmitted': diff --git a/services/apps/alcs/src/alcs/search/application/application-search-view.entity.ts b/services/apps/alcs/src/alcs/search/application/application-search-view.entity.ts index fb92d32959..e5657ecd3e 100644 --- a/services/apps/alcs/src/alcs/search/application/application-search-view.entity.ts +++ b/services/apps/alcs/src/alcs/search/application/application-search-view.entity.ts @@ -27,10 +27,17 @@ export class SearchApplicationSubmissionStatusType { .addSelect('app.decision_date', 'decision_date') .addSelect('app.uuid', 'application_uuid') .addSelect('app.region_code', 'application_region_code') - .addSelect('null', 'status') + .addSelect( + 'alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid)', + 'status', + ) .from(ApplicationSubmission, 'app_sub') .innerJoin(Application, 'app', 'app.file_number = app_sub.file_number') - .leftJoin(LocalGovernment, 'localGovernment', 'app_sub.local_government_uuid = localGovernment.uuid') + .leftJoin( + LocalGovernment, + 'localGovernment', + 'app_sub.local_government_uuid = localGovernment.uuid', + ) .where(`app_sub.is_draft IS NOT TRUE`), }) export class ApplicationSubmissionSearchView { diff --git a/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-advanced-search.service.ts b/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-advanced-search.service.ts index 1677d33c14..da276d0ebf 100644 --- a/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-advanced-search.service.ts +++ b/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-advanced-search.service.ts @@ -13,7 +13,6 @@ import { NoticeOfIntent } from '../../notice-of-intent/notice-of-intent.entity'; import { SEARCH_CACHE_TIME } from '../search.config'; import { AdvancedSearchResultDto, SearchRequestDto } from '../search.dto'; import { NoticeOfIntentSubmissionSearchView } from './notice-of-intent-search-view.entity'; -import { NoiSubmissionStatusSearchView } from '../status/noi-search-status-view.entity'; @Injectable() export class NoticeOfIntentAdvancedSearchService { @@ -64,20 +63,13 @@ export class NoticeOfIntentAdvancedSearchService { fileNumbers: [...fileNumbers.values()], }); - if (searchDto.sortField === 'status') { - query = query.innerJoin( - NoiSubmissionStatusSearchView, - 'noi_status', - 'noi_status.file_number = "noiSearch"."file_number"', - ); - } - const sortQuery = this.compileSortQuery(searchDto); query = query .orderBy(sortQuery, searchDto.sortDirection, searchDto.sortDirection === 'ASC' ? 'NULLS FIRST' : 'NULLS LAST') .offset((searchDto.page - 1) * searchDto.pageSize) .limit(searchDto.pageSize); + const t0 = performance.now(); const results = await Promise.all([query.getMany(), query.getCount()]); const t1 = performance.now(); @@ -103,8 +95,8 @@ export class NoticeOfIntentAdvancedSearchService { case 'government': return '"noiSearch"."local_government_name"'; - case 'status': - return `"noi_status"."status" ->> 'label' `; + case 'portalStatus': + return `"noiSearch"."status" ->> 'label' `; default: case 'dateSubmitted': diff --git a/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-search-view.entity.ts b/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-search-view.entity.ts index de5352a1af..d65c2ca7c9 100644 --- a/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-search-view.entity.ts +++ b/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-search-view.entity.ts @@ -1,4 +1,11 @@ -import { DataSource, JoinColumn, ManyToOne, PrimaryColumn, ViewColumn, ViewEntity } from 'typeorm'; +import { + DataSource, + JoinColumn, + ManyToOne, + PrimaryColumn, + ViewColumn, + ViewEntity, +} from 'typeorm'; import { NoticeOfIntentSubmission } from '../../../portal/notice-of-intent-submission/notice-of-intent-submission.entity'; import { NoticeOfIntentType } from '../../notice-of-intent/notice-of-intent-type/notice-of-intent-type.entity'; import { LocalGovernment } from '../../local-government/local-government.entity'; @@ -31,12 +38,23 @@ export class SearchNoticeOfIntentSubmissionStatusType { .addSelect('noi.decision_date', 'decision_date') .addSelect('noi.uuid', 'notice_of_intent_uuid') .addSelect('noi.region_code', 'notice_of_intent_region_code') - .addSelect('null', 'status') + .addSelect( + 'alcs.get_current_status_for_notice_of_intent_submission_by_uuid(nois.uuid)', + 'status', + ) .from(NoticeOfIntentSubmission, 'nois') .innerJoin(NoticeOfIntent, 'noi', 'noi.file_number = nois.file_number') .withDeleted() - .innerJoinAndSelect(NoticeOfIntentType, 'noticeOfIntentType', 'nois.type_code = noticeOfIntentType.code') - .leftJoin(LocalGovernment, 'localGovernment', 'nois.local_government_uuid = localGovernment.uuid') + .innerJoinAndSelect( + NoticeOfIntentType, + 'noticeOfIntentType', + 'nois.type_code = noticeOfIntentType.code', + ) + .leftJoin( + LocalGovernment, + 'localGovernment', + 'nois.local_government_uuid = localGovernment.uuid', + ) .where(`nois.is_draft IS NOT TRUE`), }) export class NoticeOfIntentSubmissionSearchView { diff --git a/services/apps/alcs/src/alcs/search/notification/notification-advanced-search.service.ts b/services/apps/alcs/src/alcs/search/notification/notification-advanced-search.service.ts index 3f9c9a90a9..6e0c3b0b36 100644 --- a/services/apps/alcs/src/alcs/search/notification/notification-advanced-search.service.ts +++ b/services/apps/alcs/src/alcs/search/notification/notification-advanced-search.service.ts @@ -12,7 +12,6 @@ import { SEARCH_CACHE_TIME } from '../search.config'; import { AdvancedSearchResultDto, SearchRequestDto } from '../search.dto'; import { NotificationSubmissionSearchView } from './notification-search-view.entity'; import { getNextDayToPacific, getStartOfDayToPacific } from '../../../utils/pacific-date-time-helper'; -import { NotificationSubmissionStatusSearchView } from '../status/notification-search-status-view.entity'; @Injectable() export class NotificationAdvancedSearchService { @@ -46,7 +45,11 @@ export class NotificationAdvancedSearchService { fileNumbers = new Set(cachedNumbers); } else { fileNumbers = await this.searchForFileNumbers(searchDto); - await client.setEx(searchKey, SEARCH_CACHE_TIME, JSON.stringify([...fileNumbers.values()])); + await client.setEx( + searchKey, + SEARCH_CACHE_TIME, + JSON.stringify([...fileNumbers.values()]), + ); } if (fileNumbers.size === 0) { @@ -67,20 +70,17 @@ export class NotificationAdvancedSearchService { fileNumbers: [...fileNumbers.values()], }); - if (searchDto.sortField === 'status') { - query = query.innerJoin( - NotificationSubmissionStatusSearchView, - 'not_status', - 'not_status.file_number = "notificationSearch"."file_number"', - ); - } - const sortQuery = this.compileSortQuery(searchDto); query = query - .orderBy(sortQuery, searchDto.sortDirection, searchDto.sortDirection === 'ASC' ? 'NULLS FIRST' : 'NULLS LAST') + .orderBy( + sortQuery, + searchDto.sortDirection, + searchDto.sortDirection === 'ASC' ? 'NULLS FIRST' : 'NULLS LAST', + ) .offset((searchDto.page - 1) * searchDto.pageSize) .limit(searchDto.pageSize); + const t0 = performance.now(); const results = await Promise.all([query.getMany(), query.getCount()]); const t1 = performance.now(); @@ -106,8 +106,8 @@ export class NotificationAdvancedSearchService { case 'government': return '"notificationSearch"."local_government_name"'; - case 'status': - return `"not_status"."status" ->> 'label' `; + case 'portalStatus': + return `"notificationSearch"."status" ->> 'label' `; default: case 'dateSubmitted': @@ -119,12 +119,18 @@ export class NotificationAdvancedSearchService { const promises: Promise<{ fileNumber: string }[]>[] = []; if (searchDto.fileNumber) { - const promise = NOTIFICATION_SEARCH_FILTERS.addFileNumberResults(searchDto, this.notificationRepository); + const promise = NOTIFICATION_SEARCH_FILTERS.addFileNumberResults( + searchDto, + this.notificationRepository, + ); promises.push(promise); } if (searchDto.portalStatusCodes && searchDto.portalStatusCodes.length > 0) { - const promise = NOTIFICATION_SEARCH_FILTERS.addPortalStatusResults(searchDto, this.notificationSubRepository); + const promise = NOTIFICATION_SEARCH_FILTERS.addPortalStatusResults( + searchDto, + this.notificationSubRepository, + ); promises.push(promise); } @@ -142,17 +148,26 @@ export class NotificationAdvancedSearchService { } if (searchDto.name) { - const promise = NOTIFICATION_SEARCH_FILTERS.addNameResults(searchDto, this.notificationSubRepository); + const promise = NOTIFICATION_SEARCH_FILTERS.addNameResults( + searchDto, + this.notificationSubRepository, + ); promises.push(promise); } if (searchDto.pid || searchDto.civicAddress) { - const promise = NOTIFICATION_SEARCH_FILTERS.addParcelResults(searchDto, this.notificationSubRepository); + const promise = NOTIFICATION_SEARCH_FILTERS.addParcelResults( + searchDto, + this.notificationSubRepository, + ); promises.push(promise); } if (searchDto.fileTypes.includes('SRW')) { - const promise = NOTIFICATION_SEARCH_FILTERS.addFileTypeResults(searchDto, this.notificationRepository); + const promise = NOTIFICATION_SEARCH_FILTERS.addFileTypeResults( + searchDto, + this.notificationRepository, + ); promises.push(promise); } @@ -163,11 +178,16 @@ export class NotificationAdvancedSearchService { const t0 = performance.now(); const finalResult = await processSearchPromises(promises); const t1 = performance.now(); - this.logger.debug(`ALCS Application pre-search search took ${t1 - t0} milliseconds.`); + this.logger.debug( + `ALCS Application pre-search search took ${t1 - t0} milliseconds.`, + ); return finalResult; } - private addRegionResults(searchDto: SearchRequestDto, promises: Promise<{ fileNumber: string }[]>[]) { + private addRegionResults( + searchDto: SearchRequestDto, + promises: Promise<{ fileNumber: string }[]>[], + ) { const promise = this.notificationRepository.find({ where: { regionCode: searchDto.regionCode, @@ -179,19 +199,34 @@ export class NotificationAdvancedSearchService { promises.push(promise); } - private addSubmittedDateResults(searchDto: SearchRequestDto, promises: Promise<{ fileNumber: string }[]>[]) { - let query = this.notificationRepository.createQueryBuilder('notification').select('notification.fileNumber'); + private addSubmittedDateResults( + searchDto: SearchRequestDto, + promises: Promise<{ fileNumber: string }[]>[], + ) { + let query = this.notificationRepository + .createQueryBuilder('notification') + .select('notification.fileNumber'); if (searchDto.dateSubmittedFrom !== undefined) { - query = query.andWhere('notification.date_submitted_to_alc >= :date_submitted_from', { - date_submitted_from: getStartOfDayToPacific(searchDto.dateSubmittedFrom).toISOString(), - }); + query = query.andWhere( + 'notification.date_submitted_to_alc >= :date_submitted_from', + { + date_submitted_from: getStartOfDayToPacific( + searchDto.dateSubmittedFrom + ).toISOString(), + }, + ); } if (searchDto.dateSubmittedTo !== undefined) { - query = query.andWhere('notification.date_submitted_to_alc < :date_submitted_to', { - date_submitted_to: getNextDayToPacific(searchDto.dateSubmittedTo).toISOString(), - }); + query = query.andWhere( + 'notification.date_submitted_to_alc < :date_submitted_to', + { + date_submitted_to: getNextDayToPacific( + searchDto.dateSubmittedTo + ).toISOString(), + }, + ); } promises.push(query.getMany()); } diff --git a/services/apps/alcs/src/alcs/search/notification/notification-search-view.entity.ts b/services/apps/alcs/src/alcs/search/notification/notification-search-view.entity.ts index 054593f98d..33e8e61fd2 100644 --- a/services/apps/alcs/src/alcs/search/notification/notification-search-view.entity.ts +++ b/services/apps/alcs/src/alcs/search/notification/notification-search-view.entity.ts @@ -1,4 +1,11 @@ -import { DataSource, JoinColumn, ManyToOne, PrimaryColumn, ViewColumn, ViewEntity } from 'typeorm'; +import { + DataSource, + JoinColumn, + ManyToOne, + PrimaryColumn, + ViewColumn, + ViewEntity, +} from 'typeorm'; import { NotificationSubmission } from '../../../portal/notification-submission/notification-submission.entity'; import { LocalGovernment } from '../../local-government/local-government.entity'; import { NotificationType } from '../../notification/notification-type/notification-type.entity'; @@ -28,12 +35,27 @@ export class SearchNotificationSubmissionStatusType { .addSelect('noti.date_submitted_to_alc', 'date_submitted_to_alc') .addSelect('noti.uuid', 'notification_uuid') .addSelect('noti.region_code', 'notification_region_code') - .addSelect('null', 'status') + .addSelect( + 'alcs.get_current_status_for_notification_submission_by_uuid(noti_sub.uuid)', + 'status', + ) .from(NotificationSubmission, 'noti_sub') - .innerJoin(Notification, 'noti', 'noti.file_number = noti_sub.file_number') + .innerJoin( + Notification, + 'noti', + 'noti.file_number = noti_sub.file_number', + ) .withDeleted() - .innerJoinAndSelect(NotificationType, 'notificationType', 'noti_sub.type_code = notificationType.code') - .leftJoin(LocalGovernment, 'localGovernment', 'noti.local_government_uuid = localGovernment.uuid'), + .innerJoinAndSelect( + NotificationType, + 'notificationType', + 'noti_sub.type_code = notificationType.code', + ) + .leftJoin( + LocalGovernment, + 'localGovernment', + 'noti.local_government_uuid = localGovernment.uuid', + ), }) export class NotificationSubmissionSearchView { @ViewColumn() diff --git a/services/apps/alcs/src/alcs/search/search.controller.spec.ts b/services/apps/alcs/src/alcs/search/search.controller.spec.ts index b947e09a6e..c991110101 100644 --- a/services/apps/alcs/src/alcs/search/search.controller.spec.ts +++ b/services/apps/alcs/src/alcs/search/search.controller.spec.ts @@ -20,7 +20,6 @@ import { PlanningReviewAdvancedSearchService } from './planning-review/planning- import { SearchController } from './search.controller'; import { SearchRequestDto } from './search.dto'; import { SearchService } from './search.service'; -import { SearchStatusService } from './status/search-status.service'; describe('SearchController', () => { let controller: SearchController; @@ -30,22 +29,10 @@ describe('SearchController', () => { let mockNotificationAdvancedSearchService: DeepMocked; let mockPlanningReviewAdvancedSearchService: DeepMocked; let mockInquiryAdvancedSearchService: DeepMocked; - let mockSearchStatusService: DeepMocked; let mockDataSource: DeepMocked; let mockQueryRunner: DeepMocked; let mockAppTypeRepo: DeepMocked>; - const statusSearchMockedResult = [ - { - fileNumber: 'file1', - status: 'status', - }, - { - fileNumber: 'file2', - status: 'status', - }, - ]; - beforeEach(async () => { mockSearchService = createMock(); mockNoticeOfIntentAdvancedSearchService = createMock(); @@ -53,7 +40,6 @@ describe('SearchController', () => { mockNotificationAdvancedSearchService = createMock(); mockPlanningReviewAdvancedSearchService = createMock(); mockInquiryAdvancedSearchService = createMock(); - mockSearchStatusService = createMock(); mockDataSource = createMock(); mockAppTypeRepo = createMock(); @@ -88,10 +74,6 @@ describe('SearchController', () => { provide: InquiryAdvancedSearchService, useValue: mockInquiryAdvancedSearchService, }, - { - provide: SearchStatusService, - useValue: mockSearchStatusService, - }, { provide: DataSource, useValue: mockDataSource, @@ -121,10 +103,12 @@ describe('SearchController', () => { mockSearchService.getPlanningReview.mockResolvedValue(new PlanningReview()); mockSearchService.getInquiry.mockResolvedValue(new Inquiry()); - mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents.mockResolvedValue({ - data: [], - total: 0, - }); + mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents.mockResolvedValue( + { + data: [], + total: 0, + }, + ); mockApplicationAdvancedSearchService.searchApplications.mockResolvedValue({ data: [], @@ -145,10 +129,6 @@ describe('SearchController', () => { data: [], total: 0, }); - - mockSearchStatusService.searchApplicationStatus.mockResolvedValue(statusSearchMockedResult); - mockSearchStatusService.searchNoiStatus.mockResolvedValue(statusSearchMockedResult); - mockSearchStatusService.searchNotificationStatus.mockResolvedValue(statusSearchMockedResult); }); it('should be defined', () => { @@ -164,9 +144,13 @@ describe('SearchController', () => { expect(mockSearchService.getNoi).toHaveBeenCalledTimes(1); expect(mockSearchService.getNoi).toHaveBeenCalledWith(searchString); expect(mockSearchService.getPlanningReview).toHaveBeenCalledTimes(1); - expect(mockSearchService.getPlanningReview).toHaveBeenCalledWith(searchString); + expect(mockSearchService.getPlanningReview).toHaveBeenCalledWith( + searchString, + ); expect(mockSearchService.getNotification).toHaveBeenCalledTimes(1); - expect(mockSearchService.getNotification).toHaveBeenCalledWith(searchString); + expect(mockSearchService.getNotification).toHaveBeenCalledWith( + searchString, + ); expect(result).toBeDefined(); expect(result.length).toBe(5); }); @@ -184,21 +168,29 @@ describe('SearchController', () => { const result = await controller.advancedSearch(mockSearchRequestDto); - expect(mockApplicationAdvancedSearchService.searchApplications).toHaveBeenCalledTimes(1); - expect(mockApplicationAdvancedSearchService.searchApplications).toHaveBeenCalledWith(mockSearchRequestDto, {}); + expect( + mockApplicationAdvancedSearchService.searchApplications, + ).toHaveBeenCalledTimes(1); + expect( + mockApplicationAdvancedSearchService.searchApplications, + ).toHaveBeenCalledWith(mockSearchRequestDto, {}); expect(result.applications).toBeDefined(); expect(result.totalApplications).toBe(0); - expect(mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents).toHaveBeenCalledTimes(1); - expect(mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents).toHaveBeenCalledWith( - mockSearchRequestDto, - {}, - ); + expect( + mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents, + ).toHaveBeenCalledTimes(1); + expect( + mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents, + ).toHaveBeenCalledWith(mockSearchRequestDto, {}); expect(result.noticeOfIntents).toBeDefined(); expect(result.totalNoticeOfIntents).toBe(0); expect(mockInquiryAdvancedSearchService.search).toHaveBeenCalledTimes(1); - expect(mockInquiryAdvancedSearchService.search).toHaveBeenCalledWith(mockSearchRequestDto, {}); + expect(mockInquiryAdvancedSearchService.search).toHaveBeenCalledWith( + mockSearchRequestDto, + {}, + ); expect(result.noticeOfIntents).toBeDefined(); expect(result.totalNoticeOfIntents).toBe(0); }); @@ -213,11 +205,16 @@ describe('SearchController', () => { portalStatusCodes: [], }; - const result = await controller.advancedSearchApplications(mockSearchRequestDto); + const result = + await controller.advancedSearchApplications(mockSearchRequestDto); expect(mockDataSource.createQueryRunner).toHaveBeenCalledTimes(1); - expect(mockApplicationAdvancedSearchService.searchApplications).toHaveBeenCalledTimes(1); - expect(mockApplicationAdvancedSearchService.searchApplications).toHaveBeenCalledWith(mockSearchRequestDto, {}); + expect( + mockApplicationAdvancedSearchService.searchApplications, + ).toHaveBeenCalledTimes(1); + expect( + mockApplicationAdvancedSearchService.searchApplications, + ).toHaveBeenCalledWith(mockSearchRequestDto, {}); expect(result.data).toBeDefined(); expect(result.total).toBe(0); expect(mockQueryRunner.release).toHaveBeenCalledTimes(1); @@ -233,13 +230,15 @@ describe('SearchController', () => { portalStatusCodes: [], }; - const result = await controller.advancedSearchNoticeOfIntents(mockSearchRequestDto); + const result = + await controller.advancedSearchNoticeOfIntents(mockSearchRequestDto); - expect(mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents).toHaveBeenCalledTimes(1); - expect(mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents).toHaveBeenCalledWith( - mockSearchRequestDto, - {}, - ); + expect( + mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents, + ).toHaveBeenCalledTimes(1); + expect( + mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents, + ).toHaveBeenCalledWith(mockSearchRequestDto, {}); expect(result.data).toBeDefined(); expect(result.total).toBe(0); }); @@ -257,8 +256,12 @@ describe('SearchController', () => { const result = await controller.advancedSearch(mockSearchRequestDto); expect(mockDataSource.createQueryRunner).toHaveBeenCalledTimes(1); - expect(mockApplicationAdvancedSearchService.searchApplications).toHaveBeenCalledTimes(1); - expect(mockApplicationAdvancedSearchService.searchApplications).toHaveBeenCalledWith(mockSearchRequestDto, {}); + expect( + mockApplicationAdvancedSearchService.searchApplications, + ).toHaveBeenCalledTimes(1); + expect( + mockApplicationAdvancedSearchService.searchApplications, + ).toHaveBeenCalledWith(mockSearchRequestDto, {}); expect(result.applications).toBeDefined(); expect(result.totalApplications).toBe(0); expect(mockQueryRunner.release).toHaveBeenCalledTimes(1); @@ -276,11 +279,12 @@ describe('SearchController', () => { const result = await controller.advancedSearch(mockSearchRequestDto); - expect(mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents).toHaveBeenCalledTimes(1); - expect(mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents).toHaveBeenCalledWith( - mockSearchRequestDto, - {}, - ); + expect( + mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents, + ).toHaveBeenCalledTimes(1); + expect( + mockNoticeOfIntentAdvancedSearchService.searchNoticeOfIntents, + ).toHaveBeenCalledWith(mockSearchRequestDto, {}); expect(result.noticeOfIntents).toBeDefined(); expect(result.totalNoticeOfIntents).toBe(0); }); @@ -298,7 +302,10 @@ describe('SearchController', () => { const result = await controller.advancedSearch(mockSearchRequestDto); expect(mockInquiryAdvancedSearchService.search).toHaveBeenCalledTimes(1); - expect(mockInquiryAdvancedSearchService.search).toHaveBeenCalledWith(mockSearchRequestDto, {}); + expect(mockInquiryAdvancedSearchService.search).toHaveBeenCalledWith( + mockSearchRequestDto, + {}, + ); expect(result.inquiries).toBeDefined(); expect(result.totalInquiries).toBe(0); }); @@ -315,36 +322,14 @@ describe('SearchController', () => { const result = await controller.advancedSearch(mockSearchRequestDto); - expect(mockPlanningReviewAdvancedSearchService.search).toHaveBeenCalledTimes(1); - expect(mockPlanningReviewAdvancedSearchService.search).toHaveBeenCalledWith(mockSearchRequestDto, {}); + expect( + mockPlanningReviewAdvancedSearchService.search, + ).toHaveBeenCalledTimes(1); + expect(mockPlanningReviewAdvancedSearchService.search).toHaveBeenCalledWith( + mockSearchRequestDto, + {}, + ); expect(result.inquiries).toBeDefined(); expect(result.totalInquiries).toBe(0); }); - - it('should call application status search', async () => { - const fileNumbers = ['file1', 'file2']; - - const result = await controller.advancedSearchApplicationStatus(fileNumbers); - - expect(mockSearchStatusService.searchApplicationStatus).toHaveBeenCalledTimes(1); - expect(result).toBeDefined(); - }); - - it('should call noi status search', async () => { - const fileNumbers = ['file1', 'file2']; - - const result = await controller.advancedSearchNoiStatus(fileNumbers); - - expect(mockSearchStatusService.searchNoiStatus).toHaveBeenCalledTimes(1); - expect(result).toBeDefined(); - }); - - it('should call notification status search', async () => { - const fileNumbers = ['file1', 'file2']; - - const result = await controller.advancedSearchNotificationStatus(fileNumbers); - - expect(mockSearchStatusService.searchNotificationStatus).toHaveBeenCalledTimes(1); - expect(result).toBeDefined(); - }); }); diff --git a/services/apps/alcs/src/alcs/search/search.controller.ts b/services/apps/alcs/src/alcs/search/search.controller.ts index 475ff7cc19..be0a7b6549 100644 --- a/services/apps/alcs/src/alcs/search/search.controller.ts +++ b/services/apps/alcs/src/alcs/search/search.controller.ts @@ -40,10 +40,8 @@ import { PlanningReviewSearchResultDto, SearchRequestDto, SearchResultDto, - StatusUpdateSearchResultDto, } from './search.dto'; import { SearchService } from './search.service'; -import { SearchStatusService } from './status/search-status.service'; @ApiOAuth2(config.get('KEYCLOAK.SCOPES')) @UseGuards(RolesGuard) @@ -56,7 +54,6 @@ export class SearchController { private applicationSearchService: ApplicationAdvancedSearchService, private notificationSearchService: NotificationAdvancedSearchService, private planningReviewSearchService: PlanningReviewAdvancedSearchService, - private searchStatusService: SearchStatusService, private inquirySearchService: InquiryAdvancedSearchService, @InjectRepository(ApplicationType) private appTypeRepo: Repository, @@ -186,18 +183,14 @@ export class SearchController { ): Promise> { const queryRunner = this.dataSource.createQueryRunner('slave'); - try { - const noticeOfIntents = await this.noticeOfIntentSearchService.searchNoticeOfIntents(searchDto, queryRunner); + const noticeOfIntents = await this.noticeOfIntentSearchService.searchNoticeOfIntents(searchDto, queryRunner); - const mappedSearchResult = await this.mapAdvancedSearchResults(null, noticeOfIntents, null, null, null); + const mappedSearchResult = await this.mapAdvancedSearchResults(null, noticeOfIntents, null, null, null); - return { - total: mappedSearchResult.totalNoticeOfIntents, - data: mappedSearchResult.noticeOfIntents, - }; - } finally { - await queryRunner.release(); - } + return { + total: mappedSearchResult.totalNoticeOfIntents, + data: mappedSearchResult.noticeOfIntents, + }; } @Post('/advanced/notifications') @@ -207,75 +200,14 @@ export class SearchController { ): Promise> { const queryRunner = this.dataSource.createQueryRunner('slave'); - try { - const notifications = await this.notificationSearchService.search(searchDto, queryRunner); - - const mappedSearchResult = await this.mapAdvancedSearchResults(null, null, null, notifications, null); - - return { - total: mappedSearchResult.totalNotifications, - data: mappedSearchResult.notifications, - }; - } finally { - await queryRunner.release(); - } - } - - @Post('/advanced/application-status') - @UserRoles(...ROLES_ALLOWED_APPLICATIONS) - async advancedSearchApplicationStatus(@Body() fileNumbers: string[]): Promise { - const queryRunner = this.dataSource.createQueryRunner('slave'); - - try { - const statuses = await this.searchStatusService.searchApplicationStatus(fileNumbers, queryRunner); - - return statuses.map((s) => { - return { - fileNumber: s.fileNumber, - status: s.status, - }; - }); - } finally { - await queryRunner.release(); - } - } + const notifications = await this.notificationSearchService.search(searchDto, queryRunner); - @Post('/advanced/noi-status') - @UserRoles(...ROLES_ALLOWED_APPLICATIONS) - async advancedSearchNoiStatus(@Body() fileNumbers: string[]): Promise { - const queryRunner = this.dataSource.createQueryRunner('slave'); + const mappedSearchResult = await this.mapAdvancedSearchResults(null, null, null, notifications, null); - try { - const statuses = await this.searchStatusService.searchNoiStatus(fileNumbers, queryRunner); - - return statuses.map((s) => { - return { - fileNumber: s.fileNumber, - status: s.status, - }; - }); - } finally { - await queryRunner.release(); - } - } - - @Post('/advanced/notification-status') - @UserRoles(...ROLES_ALLOWED_APPLICATIONS) - async advancedSearchNotificationStatus(@Body() fileNumbers: string[]): Promise { - const queryRunner = this.dataSource.createQueryRunner('slave'); - - try { - const statuses = await this.searchStatusService.searchNotificationStatus(fileNumbers, queryRunner); - - return statuses.map((s) => { - return { - fileNumber: s.fileNumber, - status: s.status, - }; - }); - } finally { - await queryRunner.release(); - } + return { + total: mappedSearchResult.totalNotifications, + data: mappedSearchResult.notifications, + }; } @Post('/advanced/planning-reviews') @@ -285,18 +217,14 @@ export class SearchController { ): Promise> { const queryRunner = this.dataSource.createQueryRunner('slave'); - try { - const planningReviews = await this.planningReviewSearchService.search(searchDto, queryRunner); + const planningReviews = await this.planningReviewSearchService.search(searchDto, queryRunner); - const mappedSearchResult = await this.mapAdvancedSearchResults(null, null, planningReviews, null, null); + const mappedSearchResult = await this.mapAdvancedSearchResults(null, null, planningReviews, null, null); - return { - total: mappedSearchResult.totalPlanningReviews, - data: mappedSearchResult.planningReviews, - }; - } finally { - await queryRunner.release(); - } + return { + total: mappedSearchResult.totalPlanningReviews, + data: mappedSearchResult.planningReviews, + }; } @Post('/advanced/inquiries') @@ -306,18 +234,14 @@ export class SearchController { ): Promise> { const queryRunner = this.dataSource.createQueryRunner('slave'); - try { - const inquiries = await this.inquirySearchService.search(searchDto, queryRunner); + const inquiries = await this.inquirySearchService.search(searchDto, queryRunner); - const mappedSearchResult = await this.mapAdvancedSearchResults(null, null, null, null, inquiries); + const mappedSearchResult = await this.mapAdvancedSearchResults(null, null, null, null, inquiries); - return { - total: mappedSearchResult.totalInquiries, - data: mappedSearchResult.inquiries, - }; - } finally { - await queryRunner.release(); - } + return { + total: mappedSearchResult.totalInquiries, + data: mappedSearchResult.inquiries, + }; } private getEntitiesTypeToSearch(searchDto: SearchRequestDto) { @@ -510,7 +434,7 @@ export class SearchController { localGovernmentName: application.localGovernmentName, ownerName: application.applicant, class: 'APP', - status: application.status && application.status.status_type_code, + status: application.status.status_type_code, }; } @@ -525,7 +449,7 @@ export class SearchController { localGovernmentName: noi.localGovernmentName, ownerName: noi.applicant, class: 'NOI', - status: noi.status && noi.status.status_type_code, + status: noi.status.status_type_code, }; } @@ -540,7 +464,7 @@ export class SearchController { localGovernmentName: notification.localGovernmentName, ownerName: notification.applicant, class: 'NOTI', - status: notification.status && notification.status.status_type_code, + status: notification.status.status_type_code, }; } diff --git a/services/apps/alcs/src/alcs/search/search.dto.ts b/services/apps/alcs/src/alcs/search/search.dto.ts index 401dcf8ac6..842eb1418f 100644 --- a/services/apps/alcs/src/alcs/search/search.dto.ts +++ b/services/apps/alcs/src/alcs/search/search.dto.ts @@ -1,4 +1,10 @@ -import { IsArray, IsNumber, IsOptional, IsString, MinLength } from 'class-validator'; +import { + IsArray, + IsNumber, + IsOptional, + IsString, + MinLength, +} from 'class-validator'; import { ApplicationTypeDto } from '../code/application-code/application-type/application-type.dto'; import { InquiryTypeDto } from '../inquiry/inquiry.dto'; import { PlanningReviewTypeDto } from '../planning-review/planning-review.dto'; @@ -13,7 +19,13 @@ export class SearchResultDto { label?: ApplicationTypeDto; } -export type SearchEntityClass = 'APP' | 'NOI' | 'PLAN' | 'COV' | 'NOTI' | 'INQR'; +export type SearchEntityClass = + | 'APP' + | 'NOI' + | 'PLAN' + | 'COV' + | 'NOTI' + | 'INQR'; export class ApplicationSearchResultDto { type: ApplicationTypeDto; @@ -22,7 +34,7 @@ export class ApplicationSearchResultDto { localGovernmentName?: string; fileNumber: string; boardCode?: string; - status?: string; + status: string; dateSubmitted?: number; class: SearchEntityClass; } @@ -34,7 +46,7 @@ export class NoticeOfIntentSearchResultDto { localGovernmentName?: string; fileNumber: string; boardCode?: string; - status?: string; + status: string; dateSubmitted?: number; class: SearchEntityClass; } @@ -57,7 +69,7 @@ export class NotificationSearchResultDto { localGovernmentName?: string; fileNumber: string; boardCode?: string; - status?: string; + status: string; dateSubmitted?: number; class: SearchEntityClass; } @@ -88,11 +100,6 @@ export class AdvancedSearchResponseDto { totalInquiries: number; } -export class StatusUpdateSearchResultDto { - fileNumber: string; - status: string; -} - export class AdvancedSearchResultDto { data: T; total: number; diff --git a/services/apps/alcs/src/alcs/search/search.module.ts b/services/apps/alcs/src/alcs/search/search.module.ts index f26630bb8f..70b12f1261 100644 --- a/services/apps/alcs/src/alcs/search/search.module.ts +++ b/services/apps/alcs/src/alcs/search/search.module.ts @@ -23,10 +23,6 @@ import { PlanningReviewAdvancedSearchService } from './planning-review/planning- import { PlanningReviewSearchView } from './planning-review/planning-review-search-view.entity'; import { SearchController } from './search.controller'; import { SearchService } from './search.service'; -import { SearchStatusService } from './status/search-status.service'; -import { ApplicationSubmissionStatusSearchView } from './status/application-search-status-view.entity'; -import { NoiSubmissionStatusSearchView } from './status/noi-search-status-view.entity'; -import { NotificationSubmissionStatusSearchView } from './status/notification-search-status-view.entity'; @Module({ imports: [ @@ -46,9 +42,6 @@ import { NotificationSubmissionStatusSearchView } from './status/notification-se Inquiry, InquirySearchView, LocalGovernment, - ApplicationSubmissionStatusSearchView, - NoiSubmissionStatusSearchView, - NotificationSubmissionStatusSearchView, ]), ], providers: [ @@ -59,7 +52,6 @@ import { NotificationSubmissionStatusSearchView } from './status/notification-se NotificationAdvancedSearchService, PlanningReviewAdvancedSearchService, InquiryAdvancedSearchService, - SearchStatusService, ], controllers: [SearchController], }) diff --git a/services/apps/alcs/src/alcs/search/status/application-search-status-view.entity.ts b/services/apps/alcs/src/alcs/search/status/application-search-status-view.entity.ts deleted file mode 100644 index ed315f9183..0000000000 --- a/services/apps/alcs/src/alcs/search/status/application-search-status-view.entity.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { DataSource, ViewColumn, ViewEntity } from 'typeorm'; -import { ApplicationSubmission } from '../../../portal/application-submission/application-submission.entity'; - -// typeorm does not transform property names for the status -export class SearchApplicationSubmissionStatusType { - submission_uuid: string; - - status_type_code: string; - - effective_date: Date; - - label: string; -} - -@ViewEntity({ - expression: (datasource: DataSource) => - datasource - .createQueryBuilder() - .select('app_sub.file_number', 'file_number') - .addSelect('alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid)', 'status') - .from(ApplicationSubmission, 'app_sub') - .where(`app_sub.is_draft IS NOT TRUE`), -}) -export class ApplicationSubmissionStatusSearchView { - @ViewColumn() - fileNumber: string; - - @ViewColumn() - status: SearchApplicationSubmissionStatusType; -} diff --git a/services/apps/alcs/src/alcs/search/status/noi-search-status-view.entity.ts b/services/apps/alcs/src/alcs/search/status/noi-search-status-view.entity.ts deleted file mode 100644 index ec8e74aa7c..0000000000 --- a/services/apps/alcs/src/alcs/search/status/noi-search-status-view.entity.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { DataSource, ViewColumn, ViewEntity } from 'typeorm'; -import { NoticeOfIntentSubmission } from '../../../portal/notice-of-intent-submission/notice-of-intent-submission.entity'; - -// typeorm does not transform property names for the status -export class SearchNoiSubmissionStatusType { - submission_uuid: string; - - status_type_code: string; - - effective_date: Date; - - label: string; -} - -@ViewEntity({ - expression: (datasource: DataSource) => - datasource - .createQueryBuilder() - .select('noi_sub.file_number', 'file_number') - .addSelect('alcs.get_current_status_for_notice_of_intent_submission_by_uuid(noi_sub.uuid)', 'status') - .from(NoticeOfIntentSubmission, 'noi_sub') - .where(`noi_sub.is_draft IS NOT TRUE`), -}) -export class NoiSubmissionStatusSearchView { - @ViewColumn() - fileNumber: string; - - @ViewColumn() - status: SearchNoiSubmissionStatusType; -} diff --git a/services/apps/alcs/src/alcs/search/status/notification-search-status-view.entity.ts b/services/apps/alcs/src/alcs/search/status/notification-search-status-view.entity.ts deleted file mode 100644 index ea5ef33bdb..0000000000 --- a/services/apps/alcs/src/alcs/search/status/notification-search-status-view.entity.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { DataSource, ViewColumn, ViewEntity } from 'typeorm'; -import { NotificationSubmission } from '../../../portal/notification-submission/notification-submission.entity'; - -// typeorm does not transform property names for the status -export class SearchNotificationSubmissionStatusType { - submission_uuid: string; - - status_type_code: string; - - effective_date: Date; - - label: string; -} - -@ViewEntity({ - expression: (datasource: DataSource) => - datasource - .createQueryBuilder() - .select('not_sub.file_number', 'file_number') - .addSelect('alcs.get_current_status_for_notification_submission_by_uuid(not_sub.uuid)', 'status') - .from(NotificationSubmission, 'not_sub'), -}) -export class NotificationSubmissionStatusSearchView { - @ViewColumn() - fileNumber: string; - - @ViewColumn() - status: SearchNotificationSubmissionStatusType; -} diff --git a/services/apps/alcs/src/alcs/search/status/search-status.service.spec.ts b/services/apps/alcs/src/alcs/search/status/search-status.service.spec.ts deleted file mode 100644 index fe16bf9783..0000000000 --- a/services/apps/alcs/src/alcs/search/status/search-status.service.spec.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { createMock, DeepMocked } from '@golevelup/nestjs-testing'; -import { Test, TestingModule } from '@nestjs/testing'; -import { getRepositoryToken } from '@nestjs/typeorm'; -import { QueryRunner, Repository } from 'typeorm'; -import { SearchStatusService } from './search-status.service'; -import { ApplicationSubmissionStatusSearchView } from './application-search-status-view.entity'; -import { NoiSubmissionStatusSearchView } from './noi-search-status-view.entity'; -import { NotificationSubmissionStatusSearchView } from './notification-search-status-view.entity'; -import { createMockQuery } from '../../../../test/mocks/mockTypes'; - -describe('SearchStatusService', () => { - let service: SearchStatusService; - let mockApplicationRepository: DeepMocked>; - let mockNoiRepository: DeepMocked>; - let mockNotificationRepository: DeepMocked>; - - let mockQuery: any = {}; - - beforeEach(async () => { - mockApplicationRepository = createMock(); - mockNoiRepository = createMock(); - mockNotificationRepository = createMock(); - mockQuery = createMockQuery(); - - const module: TestingModule = await Test.createTestingModule({ - providers: [ - SearchStatusService, - { - provide: getRepositoryToken(ApplicationSubmissionStatusSearchView), - useValue: mockApplicationRepository, - }, - { - provide: getRepositoryToken(NoiSubmissionStatusSearchView), - useValue: mockNoiRepository, - }, - { - provide: getRepositoryToken(NotificationSubmissionStatusSearchView), - useValue: mockNotificationRepository, - }, - ], - }).compile(); - - service = module.get(SearchStatusService); - - mockApplicationRepository.createQueryBuilder.mockReturnValue(mockQuery as any); - mockNoiRepository.createQueryBuilder.mockReturnValue(mockQuery as any); - mockNotificationRepository.createQueryBuilder.mockReturnValue(mockQuery as any); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); - - it('should call repository to get aplication status', async () => { - mockApplicationRepository.createQueryBuilder.mockReturnValue(mockQuery); - - const mockQueryRunner = createMock(); - - const result = await service.searchApplicationStatus(['file1', 'file2'], mockQueryRunner); - - expect(result).toEqual([]); - expect(mockApplicationRepository.createQueryBuilder).toHaveBeenCalledTimes(1); - expect(mockQuery.andWhere).toHaveBeenCalledTimes(1); - }); - - it('should call repository to get noi status', async () => { - mockNoiRepository.createQueryBuilder.mockReturnValue(mockQuery); - - const mockQueryRunner = createMock(); - - const result = await service.searchNoiStatus(['file1', 'file2'], mockQueryRunner); - - expect(result).toEqual([]); - expect(mockNoiRepository.createQueryBuilder).toHaveBeenCalledTimes(1); - expect(mockQuery.andWhere).toHaveBeenCalledTimes(1); - }); - - it('should call repository to get notification status', async () => { - mockNotificationRepository.createQueryBuilder.mockReturnValue(mockQuery); - - const mockQueryRunner = createMock(); - - const result = await service.searchNotificationStatus(['file1', 'file2'], mockQueryRunner); - - expect(result).toEqual([]); - expect(mockNotificationRepository.createQueryBuilder).toHaveBeenCalledTimes(1); - expect(mockQuery.andWhere).toHaveBeenCalledTimes(1); - }); -}); diff --git a/services/apps/alcs/src/alcs/search/status/search-status.service.ts b/services/apps/alcs/src/alcs/search/status/search-status.service.ts deleted file mode 100644 index 37fc08dde1..0000000000 --- a/services/apps/alcs/src/alcs/search/status/search-status.service.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { QueryRunner, Repository } from 'typeorm'; -import { StatusUpdateSearchResultDto } from '../search.dto'; -import { ApplicationSubmissionStatusSearchView } from './application-search-status-view.entity'; -import { NoiSubmissionStatusSearchView } from './noi-search-status-view.entity'; -import { NotificationSubmissionStatusSearchView } from './notification-search-status-view.entity'; - -@Injectable() -export class SearchStatusService { - private logger: Logger = new Logger(SearchStatusService.name); - - constructor( - @InjectRepository(ApplicationSubmissionStatusSearchView) - private applicationStatusSearchRepository: Repository, - @InjectRepository(NoiSubmissionStatusSearchView) - private noiStatusSearchRepository: Repository, - @InjectRepository(NotificationSubmissionStatusSearchView) - private notificationStatusSearchRepository: Repository, - ) {} - - async searchApplicationStatus( - fileNumbers: string[], - queryRunner: QueryRunner, - ): Promise { - const query = this.applicationStatusSearchRepository - .createQueryBuilder('appSearch', queryRunner) - .andWhere('appSearch.fileNumber IN(:...fileNumbers)', { - fileNumbers: [...fileNumbers], - }); - - const t0 = performance.now(); - const results = await Promise.all([query.getMany()]); - const t1 = performance.now(); - this.logger.debug(`ALCS Application status search took ${t1 - t0} milliseconds.`); - - const statusArray: StatusUpdateSearchResultDto[] = results[0].map((r) => { - return { - fileNumber: r.fileNumber, - status: r.status.status_type_code, - }; - }); - - return statusArray; - } - - async searchNoiStatus(fileNumbers: string[], queryRunner: QueryRunner): Promise { - const query = this.noiStatusSearchRepository - .createQueryBuilder('noiSearch', queryRunner) - .andWhere('noiSearch.fileNumber IN(:...fileNumbers)', { - fileNumbers: [...fileNumbers], - }); - const t0 = performance.now(); - const results = await Promise.all([query.getMany()]); - const t1 = performance.now(); - this.logger.debug(`ALCS Noi status search took ${t1 - t0} milliseconds.`); - - const statusArray: StatusUpdateSearchResultDto[] = results[0].map((r) => { - return { - fileNumber: r.fileNumber, - status: r.status.status_type_code, - }; - }); - - return statusArray; - } - - async searchNotificationStatus( - fileNumbers: string[], - queryRunner: QueryRunner, - ): Promise { - const query = this.notificationStatusSearchRepository - .createQueryBuilder('notSearch', queryRunner) - .andWhere('notSearch.fileNumber IN(:...fileNumbers)', { - fileNumbers: [...fileNumbers], - }); - const t0 = performance.now(); - const results = await Promise.all([query.getMany()]); - const t1 = performance.now(); - this.logger.debug(`ALCS Notification status search took ${t1 - t0} milliseconds.`); - - const statusArray: StatusUpdateSearchResultDto[] = results[0].map((r) => { - return { - fileNumber: r.fileNumber, - status: r.status.status_type_code, - }; - }); - - return statusArray; - } -} diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1731103073215-application_status_update.ts b/services/apps/alcs/src/providers/typeorm/migrations/1731103073215-application_status_update.ts deleted file mode 100644 index 6326731c03..0000000000 --- a/services/apps/alcs/src/providers/typeorm/migrations/1731103073215-application_status_update.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class ApplicationStatusUpdate1731103073215 implements MigrationInterface { - name = 'ApplicationStatusUpdate1731103073215' - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`CREATE VIEW "alcs"."application_submission_status_search_view" AS SELECT "app_sub"."file_number" AS "file_number", alcs.get_current_status_for_application_submission_by_uuid("app_sub"."uuid") AS "status" FROM "alcs"."application_submission" "app_sub" WHERE ( "app_sub"."is_draft" IS NOT TRUE ) AND ( "app_sub"."audit_deleted_date_at" IS NULL )`); - await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","application_submission_status_search_view","SELECT \"app_sub\".\"file_number\" AS \"file_number\", alcs.get_current_status_for_application_submission_by_uuid(\"app_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"application_submission\" \"app_sub\" WHERE ( \"app_sub\".\"is_draft\" IS NOT TRUE ) AND ( \"app_sub\".\"audit_deleted_date_at\" IS NULL )"]); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","application_submission_status_search_view","alcs"]); - await queryRunner.query(`DROP VIEW "alcs"."application_submission_status_search_view"`); - } - -} diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1731441606374-noi_status_update.ts b/services/apps/alcs/src/providers/typeorm/migrations/1731441606374-noi_status_update.ts deleted file mode 100644 index f233f3ab24..0000000000 --- a/services/apps/alcs/src/providers/typeorm/migrations/1731441606374-noi_status_update.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class NoiStatusUpdate1731441606374 implements MigrationInterface { - name = 'NoiStatusUpdate1731441606374' - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`CREATE VIEW "alcs"."noi_submission_status_search_view" AS SELECT "noi_sub"."file_number" AS "file_number", alcs.get_current_status_for_notice_of_intent_submission_by_uuid("noi_sub"."uuid") AS "status" FROM "alcs"."notice_of_intent_submission" "noi_sub" WHERE ( "noi_sub"."is_draft" IS NOT TRUE ) AND ( "noi_sub"."audit_deleted_date_at" IS NULL )`); - await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","noi_submission_status_search_view","SELECT \"noi_sub\".\"file_number\" AS \"file_number\", alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"noi_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"notice_of_intent_submission\" \"noi_sub\" WHERE ( \"noi_sub\".\"is_draft\" IS NOT TRUE ) AND ( \"noi_sub\".\"audit_deleted_date_at\" IS NULL )"]); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","noi_submission_status_search_view","alcs"]); - await queryRunner.query(`DROP VIEW "alcs"."noi_submission_status_search_view"`); - } - -} diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1731444339841-remove_app_noi_status.ts b/services/apps/alcs/src/providers/typeorm/migrations/1731444339841-remove_app_noi_status.ts deleted file mode 100644 index c52857577a..0000000000 --- a/services/apps/alcs/src/providers/typeorm/migrations/1731444339841-remove_app_noi_status.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class RemoveAppNoiStatus1731444339841 implements MigrationInterface { - name = 'RemoveAppNoiStatus1731444339841' - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP FUNCTION IF EXISTS alcs.get_nois(character varying[]);`); - await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","application_submission_search_view","alcs"]); - await queryRunner.query(`DROP VIEW "alcs"."application_submission_search_view"`); - await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","notice_of_intent_submission_search_view","alcs"]); - await queryRunner.query(`DROP VIEW "alcs"."notice_of_intent_submission_search_view"`); - await queryRunner.query(`CREATE VIEW "alcs"."application_submission_search_view" AS SELECT "app_sub"."uuid" AS "uuid", "app_sub"."applicant" AS "applicant", "app"."uuid" AS "application_uuid", "localGovernment"."name" AS "local_government_name", "app_sub"."file_number" AS "file_number", "app"."type_code" AS "application_type_code", "app"."date_submitted_to_alc" AS "date_submitted_to_alc", "app"."decision_date" AS "decision_date", "app"."region_code" AS "application_region_code", null AS "status" FROM "alcs"."application_submission" "app_sub" INNER JOIN "alcs"."application" "app" ON "app"."file_number" = "app_sub"."file_number" AND "app"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."local_government" "localGovernment" ON "app_sub"."local_government_uuid" = "localGovernment"."uuid" AND "localGovernment"."audit_deleted_date_at" IS NULL WHERE ( "app_sub"."is_draft" IS NOT TRUE ) AND ( "app_sub"."audit_deleted_date_at" IS NULL )`); - await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","application_submission_search_view","SELECT \"app_sub\".\"uuid\" AS \"uuid\", \"app_sub\".\"applicant\" AS \"applicant\", \"app\".\"uuid\" AS \"application_uuid\", \"localGovernment\".\"name\" AS \"local_government_name\", \"app_sub\".\"file_number\" AS \"file_number\", \"app\".\"type_code\" AS \"application_type_code\", \"app\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", \"app\".\"decision_date\" AS \"decision_date\", \"app\".\"region_code\" AS \"application_region_code\", null AS \"status\" FROM \"alcs\".\"application_submission\" \"app_sub\" INNER JOIN \"alcs\".\"application\" \"app\" ON \"app\".\"file_number\" = \"app_sub\".\"file_number\" AND \"app\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"app_sub\".\"local_government_uuid\" = \"localGovernment\".\"uuid\" AND \"localGovernment\".\"audit_deleted_date_at\" IS NULL WHERE ( \"app_sub\".\"is_draft\" IS NOT TRUE ) AND ( \"app_sub\".\"audit_deleted_date_at\" IS NULL )"]); - await queryRunner.query(`CREATE VIEW "alcs"."notice_of_intent_submission_search_view" AS SELECT "nois"."uuid" AS "uuid", "nois"."applicant" AS "applicant", "noi"."uuid" AS "notice_of_intent_uuid", "noticeOfIntentType"."audit_deleted_date_at" AS "noticeOfIntentType_audit_deleted_date_at", "noticeOfIntentType"."audit_created_at" AS "noticeOfIntentType_audit_created_at", "noticeOfIntentType"."audit_updated_at" AS "noticeOfIntentType_audit_updated_at", "noticeOfIntentType"."audit_created_by" AS "noticeOfIntentType_audit_created_by", "noticeOfIntentType"."audit_updated_by" AS "noticeOfIntentType_audit_updated_by", "noticeOfIntentType"."label" AS "noticeOfIntentType_label", "noticeOfIntentType"."code" AS "noticeOfIntentType_code", "noticeOfIntentType"."description" AS "noticeOfIntentType_description", "noticeOfIntentType"."short_label" AS "noticeOfIntentType_short_label", "noticeOfIntentType"."background_color" AS "noticeOfIntentType_background_color", "noticeOfIntentType"."text_color" AS "noticeOfIntentType_text_color", "noticeOfIntentType"."html_description" AS "noticeOfIntentType_html_description", "noticeOfIntentType"."portal_label" AS "noticeOfIntentType_portal_label", "noticeOfIntentType"."alc_fee_amount" AS "noticeOfIntentType_alc_fee_amount", "noticeOfIntentType"."government_fee_amount" AS "noticeOfIntentType_government_fee_amount", "localGovernment"."name" AS "local_government_name", "nois"."file_number" AS "file_number", "nois"."local_government_uuid" AS "local_government_uuid", "nois"."type_code" AS "notice_of_intent_type_code", "nois"."is_draft" AS "is_draft", "noi"."date_submitted_to_alc" AS "date_submitted_to_alc", "noi"."legacy_id" AS "legacy_id", "noi"."decision_date" AS "decision_date", "noi"."region_code" AS "notice_of_intent_region_code", null AS "status" FROM "alcs"."notice_of_intent_submission" "nois" INNER JOIN "alcs"."notice_of_intent" "noi" ON "noi"."file_number" = "nois"."file_number" AND "noi"."audit_deleted_date_at" IS NULL INNER JOIN "alcs"."notice_of_intent_type" "noticeOfIntentType" ON "nois"."type_code" = "noticeOfIntentType"."code" LEFT JOIN "alcs"."local_government" "localGovernment" ON "nois"."local_government_uuid" = "localGovernment"."uuid" WHERE "nois"."is_draft" IS NOT TRUE`); - await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","notice_of_intent_submission_search_view","SELECT \"nois\".\"uuid\" AS \"uuid\", \"nois\".\"applicant\" AS \"applicant\", \"noi\".\"uuid\" AS \"notice_of_intent_uuid\", \"noticeOfIntentType\".\"audit_deleted_date_at\" AS \"noticeOfIntentType_audit_deleted_date_at\", \"noticeOfIntentType\".\"audit_created_at\" AS \"noticeOfIntentType_audit_created_at\", \"noticeOfIntentType\".\"audit_updated_at\" AS \"noticeOfIntentType_audit_updated_at\", \"noticeOfIntentType\".\"audit_created_by\" AS \"noticeOfIntentType_audit_created_by\", \"noticeOfIntentType\".\"audit_updated_by\" AS \"noticeOfIntentType_audit_updated_by\", \"noticeOfIntentType\".\"label\" AS \"noticeOfIntentType_label\", \"noticeOfIntentType\".\"code\" AS \"noticeOfIntentType_code\", \"noticeOfIntentType\".\"description\" AS \"noticeOfIntentType_description\", \"noticeOfIntentType\".\"short_label\" AS \"noticeOfIntentType_short_label\", \"noticeOfIntentType\".\"background_color\" AS \"noticeOfIntentType_background_color\", \"noticeOfIntentType\".\"text_color\" AS \"noticeOfIntentType_text_color\", \"noticeOfIntentType\".\"html_description\" AS \"noticeOfIntentType_html_description\", \"noticeOfIntentType\".\"portal_label\" AS \"noticeOfIntentType_portal_label\", \"noticeOfIntentType\".\"alc_fee_amount\" AS \"noticeOfIntentType_alc_fee_amount\", \"noticeOfIntentType\".\"government_fee_amount\" AS \"noticeOfIntentType_government_fee_amount\", \"localGovernment\".\"name\" AS \"local_government_name\", \"nois\".\"file_number\" AS \"file_number\", \"nois\".\"local_government_uuid\" AS \"local_government_uuid\", \"nois\".\"type_code\" AS \"notice_of_intent_type_code\", \"nois\".\"is_draft\" AS \"is_draft\", \"noi\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", \"noi\".\"legacy_id\" AS \"legacy_id\", \"noi\".\"decision_date\" AS \"decision_date\", \"noi\".\"region_code\" AS \"notice_of_intent_region_code\", null AS \"status\" FROM \"alcs\".\"notice_of_intent_submission\" \"nois\" INNER JOIN \"alcs\".\"notice_of_intent\" \"noi\" ON \"noi\".\"file_number\" = \"nois\".\"file_number\" AND \"noi\".\"audit_deleted_date_at\" IS NULL INNER JOIN \"alcs\".\"notice_of_intent_type\" \"noticeOfIntentType\" ON \"nois\".\"type_code\" = \"noticeOfIntentType\".\"code\" LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"nois\".\"local_government_uuid\" = \"localGovernment\".\"uuid\" WHERE \"nois\".\"is_draft\" IS NOT TRUE"]); - await queryRunner.query(` - CREATE OR REPLACE FUNCTION alcs.get_nois( - file_numbers_arr character varying[]) - RETURNS SETOF alcs.notice_of_intent_submission_search_view - LANGUAGE 'sql' - COST 100 - VOLATILE PARALLEL UNSAFE - ROWS 1000 - - AS $BODY$ - - SELECT "noi".* FROM "alcs"."notice_of_intent_submission_search_view" AS "noi" - JOIN unnest(file_numbers_arr) AS fnum ON "noi"."file_number" = fnum - $BODY$; - ALTER FUNCTION alcs.get_nois(character varying[]) - OWNER TO postgres; - `); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP FUNCTION IF EXISTS alcs.get_nois(character varying[]);`); - await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","notice_of_intent_submission_search_view","alcs"]); - await queryRunner.query(`DROP VIEW "alcs"."notice_of_intent_submission_search_view"`); - await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","application_submission_search_view","alcs"]); - await queryRunner.query(`DROP VIEW "alcs"."application_submission_search_view"`); - await queryRunner.query(`CREATE VIEW "alcs"."notice_of_intent_submission_search_view" AS SELECT "nois"."uuid" AS "uuid", "nois"."applicant" AS "applicant", "noi"."uuid" AS "notice_of_intent_uuid", "noticeOfIntentType"."audit_deleted_date_at" AS "noticeOfIntentType_audit_deleted_date_at", "noticeOfIntentType"."audit_created_at" AS "noticeOfIntentType_audit_created_at", "noticeOfIntentType"."audit_updated_at" AS "noticeOfIntentType_audit_updated_at", "noticeOfIntentType"."audit_created_by" AS "noticeOfIntentType_audit_created_by", "noticeOfIntentType"."audit_updated_by" AS "noticeOfIntentType_audit_updated_by", "noticeOfIntentType"."label" AS "noticeOfIntentType_label", "noticeOfIntentType"."code" AS "noticeOfIntentType_code", "noticeOfIntentType"."description" AS "noticeOfIntentType_description", "noticeOfIntentType"."short_label" AS "noticeOfIntentType_short_label", "noticeOfIntentType"."background_color" AS "noticeOfIntentType_background_color", "noticeOfIntentType"."text_color" AS "noticeOfIntentType_text_color", "noticeOfIntentType"."html_description" AS "noticeOfIntentType_html_description", "noticeOfIntentType"."portal_label" AS "noticeOfIntentType_portal_label", "noticeOfIntentType"."alc_fee_amount" AS "noticeOfIntentType_alc_fee_amount", "noticeOfIntentType"."government_fee_amount" AS "noticeOfIntentType_government_fee_amount", "localGovernment"."name" AS "local_government_name", "nois"."file_number" AS "file_number", "nois"."local_government_uuid" AS "local_government_uuid", "nois"."type_code" AS "notice_of_intent_type_code", "nois"."is_draft" AS "is_draft", "noi"."date_submitted_to_alc" AS "date_submitted_to_alc", "noi"."legacy_id" AS "legacy_id", "noi"."decision_date" AS "decision_date", "noi"."region_code" AS "notice_of_intent_region_code", alcs.get_current_status_for_notice_of_intent_submission_by_uuid("nois"."uuid") AS "status" FROM "alcs"."notice_of_intent_submission" "nois" INNER JOIN "alcs"."notice_of_intent" "noi" ON "noi"."file_number" = "nois"."file_number" AND "noi"."audit_deleted_date_at" IS NULL INNER JOIN "alcs"."notice_of_intent_type" "noticeOfIntentType" ON "nois"."type_code" = "noticeOfIntentType"."code" LEFT JOIN "alcs"."local_government" "localGovernment" ON "nois"."local_government_uuid" = "localGovernment"."uuid" WHERE "nois"."is_draft" IS NOT TRUE`); - await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","notice_of_intent_submission_search_view","SELECT \"nois\".\"uuid\" AS \"uuid\", \"nois\".\"applicant\" AS \"applicant\", \"noi\".\"uuid\" AS \"notice_of_intent_uuid\", \"noticeOfIntentType\".\"audit_deleted_date_at\" AS \"noticeOfIntentType_audit_deleted_date_at\", \"noticeOfIntentType\".\"audit_created_at\" AS \"noticeOfIntentType_audit_created_at\", \"noticeOfIntentType\".\"audit_updated_at\" AS \"noticeOfIntentType_audit_updated_at\", \"noticeOfIntentType\".\"audit_created_by\" AS \"noticeOfIntentType_audit_created_by\", \"noticeOfIntentType\".\"audit_updated_by\" AS \"noticeOfIntentType_audit_updated_by\", \"noticeOfIntentType\".\"label\" AS \"noticeOfIntentType_label\", \"noticeOfIntentType\".\"code\" AS \"noticeOfIntentType_code\", \"noticeOfIntentType\".\"description\" AS \"noticeOfIntentType_description\", \"noticeOfIntentType\".\"short_label\" AS \"noticeOfIntentType_short_label\", \"noticeOfIntentType\".\"background_color\" AS \"noticeOfIntentType_background_color\", \"noticeOfIntentType\".\"text_color\" AS \"noticeOfIntentType_text_color\", \"noticeOfIntentType\".\"html_description\" AS \"noticeOfIntentType_html_description\", \"noticeOfIntentType\".\"portal_label\" AS \"noticeOfIntentType_portal_label\", \"noticeOfIntentType\".\"alc_fee_amount\" AS \"noticeOfIntentType_alc_fee_amount\", \"noticeOfIntentType\".\"government_fee_amount\" AS \"noticeOfIntentType_government_fee_amount\", \"localGovernment\".\"name\" AS \"local_government_name\", \"nois\".\"file_number\" AS \"file_number\", \"nois\".\"local_government_uuid\" AS \"local_government_uuid\", \"nois\".\"type_code\" AS \"notice_of_intent_type_code\", \"nois\".\"is_draft\" AS \"is_draft\", \"noi\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", \"noi\".\"legacy_id\" AS \"legacy_id\", \"noi\".\"decision_date\" AS \"decision_date\", \"noi\".\"region_code\" AS \"notice_of_intent_region_code\", alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"nois\".\"uuid\") AS \"status\" FROM \"alcs\".\"notice_of_intent_submission\" \"nois\" INNER JOIN \"alcs\".\"notice_of_intent\" \"noi\" ON \"noi\".\"file_number\" = \"nois\".\"file_number\" AND \"noi\".\"audit_deleted_date_at\" IS NULL INNER JOIN \"alcs\".\"notice_of_intent_type\" \"noticeOfIntentType\" ON \"nois\".\"type_code\" = \"noticeOfIntentType\".\"code\" LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"nois\".\"local_government_uuid\" = \"localGovernment\".\"uuid\" WHERE \"nois\".\"is_draft\" IS NOT TRUE"]); - await queryRunner.query(`CREATE VIEW "alcs"."application_submission_search_view" AS SELECT "app_sub"."uuid" AS "uuid", "app_sub"."applicant" AS "applicant", "app"."uuid" AS "application_uuid", "localGovernment"."name" AS "local_government_name", "app_sub"."file_number" AS "file_number", "app"."type_code" AS "application_type_code", "app"."date_submitted_to_alc" AS "date_submitted_to_alc", "app"."decision_date" AS "decision_date", "app"."region_code" AS "application_region_code", alcs.get_current_status_for_application_submission_by_uuid("app_sub"."uuid") AS "status" FROM "alcs"."application_submission" "app_sub" INNER JOIN "alcs"."application" "app" ON "app"."file_number" = "app_sub"."file_number" AND "app"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."local_government" "localGovernment" ON "app_sub"."local_government_uuid" = "localGovernment"."uuid" AND "localGovernment"."audit_deleted_date_at" IS NULL WHERE ( "app_sub"."is_draft" IS NOT TRUE ) AND ( "app_sub"."audit_deleted_date_at" IS NULL )`); - await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","application_submission_search_view","SELECT \"app_sub\".\"uuid\" AS \"uuid\", \"app_sub\".\"applicant\" AS \"applicant\", \"app\".\"uuid\" AS \"application_uuid\", \"localGovernment\".\"name\" AS \"local_government_name\", \"app_sub\".\"file_number\" AS \"file_number\", \"app\".\"type_code\" AS \"application_type_code\", \"app\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", \"app\".\"decision_date\" AS \"decision_date\", \"app\".\"region_code\" AS \"application_region_code\", alcs.get_current_status_for_application_submission_by_uuid(\"app_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"application_submission\" \"app_sub\" INNER JOIN \"alcs\".\"application\" \"app\" ON \"app\".\"file_number\" = \"app_sub\".\"file_number\" AND \"app\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"app_sub\".\"local_government_uuid\" = \"localGovernment\".\"uuid\" AND \"localGovernment\".\"audit_deleted_date_at\" IS NULL WHERE ( \"app_sub\".\"is_draft\" IS NOT TRUE ) AND ( \"app_sub\".\"audit_deleted_date_at\" IS NULL )"]); - await queryRunner.query(` - CREATE OR REPLACE FUNCTION alcs.get_nois( - file_numbers_arr character varying[]) - RETURNS SETOF alcs.notice_of_intent_submission_search_view - LANGUAGE 'sql' - COST 100 - VOLATILE PARALLEL UNSAFE - ROWS 1000 - - AS $BODY$ - - SELECT "noi".* FROM "alcs"."notice_of_intent_submission_search_view" AS "noi" - JOIN unnest(file_numbers_arr) AS fnum ON "noi"."file_number" = fnum - $BODY$; - ALTER FUNCTION alcs.get_nois(character varying[]) - OWNER TO postgres; - `); - } - -} diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1731453091938-notification_status_changes.ts b/services/apps/alcs/src/providers/typeorm/migrations/1731453091938-notification_status_changes.ts deleted file mode 100644 index 7978f73c73..0000000000 --- a/services/apps/alcs/src/providers/typeorm/migrations/1731453091938-notification_status_changes.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class NotificationStatusChanges1731453091938 implements MigrationInterface { - name = 'NotificationStatusChanges1731453091938' - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","notification_submission_search_view","alcs"]); - await queryRunner.query(`DROP VIEW "alcs"."notification_submission_search_view"`); - await queryRunner.query(`CREATE VIEW "alcs"."notification_submission_status_search_view" AS SELECT "not_sub"."file_number" AS "file_number", alcs.get_current_status_for_notification_submission_by_uuid("not_sub"."uuid") AS "status" FROM "alcs"."notification_submission" "not_sub" WHERE "not_sub"."audit_deleted_date_at" IS NULL`); - await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","notification_submission_status_search_view","SELECT \"not_sub\".\"file_number\" AS \"file_number\", alcs.get_current_status_for_notification_submission_by_uuid(\"not_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"notification_submission\" \"not_sub\" WHERE \"not_sub\".\"audit_deleted_date_at\" IS NULL"]); - await queryRunner.query(`CREATE VIEW "alcs"."notification_submission_search_view" AS SELECT "noti_sub"."uuid" AS "uuid", "noti_sub"."applicant" AS "applicant", "noti"."uuid" AS "notification_uuid", "notificationType"."audit_deleted_date_at" AS "notificationType_audit_deleted_date_at", "notificationType"."audit_created_at" AS "notificationType_audit_created_at", "notificationType"."audit_updated_at" AS "notificationType_audit_updated_at", "notificationType"."audit_created_by" AS "notificationType_audit_created_by", "notificationType"."audit_updated_by" AS "notificationType_audit_updated_by", "notificationType"."label" AS "notificationType_label", "notificationType"."code" AS "notificationType_code", "notificationType"."description" AS "notificationType_description", "notificationType"."short_label" AS "notificationType_short_label", "notificationType"."background_color" AS "notificationType_background_color", "notificationType"."text_color" AS "notificationType_text_color", "notificationType"."html_description" AS "notificationType_html_description", "notificationType"."portal_label" AS "notificationType_portal_label", "localGovernment"."name" AS "local_government_name", "noti_sub"."file_number" AS "file_number", "noti_sub"."local_government_uuid" AS "local_government_uuid", "noti"."type_code" AS "notification_type_code", "noti"."date_submitted_to_alc" AS "date_submitted_to_alc", "noti"."region_code" AS "notification_region_code", null AS "status" FROM "alcs"."notification_submission" "noti_sub" INNER JOIN "alcs"."notification" "noti" ON "noti"."file_number" = "noti_sub"."file_number" AND "noti"."audit_deleted_date_at" IS NULL INNER JOIN "alcs"."notification_type" "notificationType" ON "noti_sub"."type_code" = "notificationType"."code" LEFT JOIN "alcs"."local_government" "localGovernment" ON "noti"."local_government_uuid" = "localGovernment"."uuid"`); - await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","notification_submission_search_view","SELECT \"noti_sub\".\"uuid\" AS \"uuid\", \"noti_sub\".\"applicant\" AS \"applicant\", \"noti\".\"uuid\" AS \"notification_uuid\", \"notificationType\".\"audit_deleted_date_at\" AS \"notificationType_audit_deleted_date_at\", \"notificationType\".\"audit_created_at\" AS \"notificationType_audit_created_at\", \"notificationType\".\"audit_updated_at\" AS \"notificationType_audit_updated_at\", \"notificationType\".\"audit_created_by\" AS \"notificationType_audit_created_by\", \"notificationType\".\"audit_updated_by\" AS \"notificationType_audit_updated_by\", \"notificationType\".\"label\" AS \"notificationType_label\", \"notificationType\".\"code\" AS \"notificationType_code\", \"notificationType\".\"description\" AS \"notificationType_description\", \"notificationType\".\"short_label\" AS \"notificationType_short_label\", \"notificationType\".\"background_color\" AS \"notificationType_background_color\", \"notificationType\".\"text_color\" AS \"notificationType_text_color\", \"notificationType\".\"html_description\" AS \"notificationType_html_description\", \"notificationType\".\"portal_label\" AS \"notificationType_portal_label\", \"localGovernment\".\"name\" AS \"local_government_name\", \"noti_sub\".\"file_number\" AS \"file_number\", \"noti_sub\".\"local_government_uuid\" AS \"local_government_uuid\", \"noti\".\"type_code\" AS \"notification_type_code\", \"noti\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", \"noti\".\"region_code\" AS \"notification_region_code\", null AS \"status\" FROM \"alcs\".\"notification_submission\" \"noti_sub\" INNER JOIN \"alcs\".\"notification\" \"noti\" ON \"noti\".\"file_number\" = \"noti_sub\".\"file_number\" AND \"noti\".\"audit_deleted_date_at\" IS NULL INNER JOIN \"alcs\".\"notification_type\" \"notificationType\" ON \"noti_sub\".\"type_code\" = \"notificationType\".\"code\" LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"noti\".\"local_government_uuid\" = \"localGovernment\".\"uuid\""]); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","notification_submission_search_view","alcs"]); - await queryRunner.query(`DROP VIEW "alcs"."notification_submission_search_view"`); - await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","notification_submission_status_search_view","alcs"]); - await queryRunner.query(`DROP VIEW "alcs"."notification_submission_status_search_view"`); - await queryRunner.query(`CREATE VIEW "alcs"."notification_submission_search_view" AS SELECT "noti_sub"."uuid" AS "uuid", "noti_sub"."applicant" AS "applicant", "noti"."uuid" AS "notification_uuid", "notificationType"."audit_deleted_date_at" AS "notificationType_audit_deleted_date_at", "notificationType"."audit_created_at" AS "notificationType_audit_created_at", "notificationType"."audit_updated_at" AS "notificationType_audit_updated_at", "notificationType"."audit_created_by" AS "notificationType_audit_created_by", "notificationType"."audit_updated_by" AS "notificationType_audit_updated_by", "notificationType"."label" AS "notificationType_label", "notificationType"."code" AS "notificationType_code", "notificationType"."description" AS "notificationType_description", "notificationType"."short_label" AS "notificationType_short_label", "notificationType"."background_color" AS "notificationType_background_color", "notificationType"."text_color" AS "notificationType_text_color", "notificationType"."html_description" AS "notificationType_html_description", "notificationType"."portal_label" AS "notificationType_portal_label", "localGovernment"."name" AS "local_government_name", "noti_sub"."file_number" AS "file_number", "noti_sub"."local_government_uuid" AS "local_government_uuid", "noti"."type_code" AS "notification_type_code", "noti"."date_submitted_to_alc" AS "date_submitted_to_alc", "noti"."region_code" AS "notification_region_code", alcs.get_current_status_for_notification_submission_by_uuid("noti_sub"."uuid") AS "status" FROM "alcs"."notification_submission" "noti_sub" INNER JOIN "alcs"."notification" "noti" ON "noti"."file_number" = "noti_sub"."file_number" AND "noti"."audit_deleted_date_at" IS NULL INNER JOIN "alcs"."notification_type" "notificationType" ON "noti_sub"."type_code" = "notificationType"."code" LEFT JOIN "alcs"."local_government" "localGovernment" ON "noti"."local_government_uuid" = "localGovernment"."uuid"`); - await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","notification_submission_search_view","SELECT \"noti_sub\".\"uuid\" AS \"uuid\", \"noti_sub\".\"applicant\" AS \"applicant\", \"noti\".\"uuid\" AS \"notification_uuid\", \"notificationType\".\"audit_deleted_date_at\" AS \"notificationType_audit_deleted_date_at\", \"notificationType\".\"audit_created_at\" AS \"notificationType_audit_created_at\", \"notificationType\".\"audit_updated_at\" AS \"notificationType_audit_updated_at\", \"notificationType\".\"audit_created_by\" AS \"notificationType_audit_created_by\", \"notificationType\".\"audit_updated_by\" AS \"notificationType_audit_updated_by\", \"notificationType\".\"label\" AS \"notificationType_label\", \"notificationType\".\"code\" AS \"notificationType_code\", \"notificationType\".\"description\" AS \"notificationType_description\", \"notificationType\".\"short_label\" AS \"notificationType_short_label\", \"notificationType\".\"background_color\" AS \"notificationType_background_color\", \"notificationType\".\"text_color\" AS \"notificationType_text_color\", \"notificationType\".\"html_description\" AS \"notificationType_html_description\", \"notificationType\".\"portal_label\" AS \"notificationType_portal_label\", \"localGovernment\".\"name\" AS \"local_government_name\", \"noti_sub\".\"file_number\" AS \"file_number\", \"noti_sub\".\"local_government_uuid\" AS \"local_government_uuid\", \"noti\".\"type_code\" AS \"notification_type_code\", \"noti\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", \"noti\".\"region_code\" AS \"notification_region_code\", alcs.get_current_status_for_notification_submission_by_uuid(\"noti_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"notification_submission\" \"noti_sub\" INNER JOIN \"alcs\".\"notification\" \"noti\" ON \"noti\".\"file_number\" = \"noti_sub\".\"file_number\" AND \"noti\".\"audit_deleted_date_at\" IS NULL INNER JOIN \"alcs\".\"notification_type\" \"notificationType\" ON \"noti_sub\".\"type_code\" = \"notificationType\".\"code\" LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"noti\".\"local_government_uuid\" = \"localGovernment\".\"uuid\""]); - } - -}