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 2ee164f4c6..c6e17a4846 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,13 +46,14 @@
-
+
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 a45e8128e3..ae4c2cf1a7 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;
+ status?: ApplicationSubmissionStatusPill | null;
}
@Component({
@@ -42,7 +42,7 @@ export class ApplicationSearchTableComponent {
@Output() tableChange = new EventEmitter();
- displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'portalStatus'];
+ displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'status'];
dataSource: SearchResult[] = [];
itemsPerPage = 20;
total = 0;
@@ -88,24 +88,22 @@ 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: {
- backgroundColor: status?.portalBackgroundColor ?? defaultStatusBackgroundColour,
- textColor: status?.portalColor ?? defaultStatusColour,
- borderColor: status?.portalBackgroundColor,
- label: status?.label,
- shortLabel: status?.label,
- },
+ status: status ? {
+ backgroundColor: status.portalBackgroundColor ?? defaultStatusBackgroundColour,
+ textColor: status.portalColor ?? defaultStatusColour,
+ borderColor: status.portalBackgroundColor,
+ label: status.label,
+ shortLabel: status.label,
+ } : null,
};
});
}
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 ef901b754b..38f446c755 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,13 +46,14 @@
-
+
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 b32404ce25..b6cdd0a68b 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;
+ status?: ApplicationSubmissionStatusPill | null;
}
@Component({
@@ -41,7 +41,7 @@ export class NoticeOfIntentSearchTableComponent {
@Output() tableChange = new EventEmitter();
- displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'portalStatus'];
+ displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'status'];
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 fae38aa644..885029dc2f 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,13 +46,14 @@
-
+
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 040428f3f2..8cece56bf5 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;
+ status?: ApplicationSubmissionStatusPill | null;
}
@Component({
@@ -41,7 +41,7 @@ export class NotificationSearchTableComponent {
@Output() tableChange = new EventEmitter();
- displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'portalStatus'];
+ displayedColumns = ['fileId', 'dateSubmitted', 'ownerName', 'type', 'government', 'status'];
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 051424f118..de78eb202a 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 5484fb5684..ef3edde8d0 100644
--- a/alcs-frontend/src/app/features/search/search.module.ts
+++ b/alcs-frontend/src/app/features/search/search.module.ts
@@ -13,6 +13,7 @@ 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 = [
{
@@ -30,6 +31,7 @@ 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
new file mode 100644
index 0000000000..8110a6a901
--- /dev/null
+++ b/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.html
@@ -0,0 +1,3 @@
+
+
+
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
new file mode 100644
index 0000000000..51e336567d
--- /dev/null
+++ b/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.scss
@@ -0,0 +1,12 @@
+.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
new file mode 100644
index 0000000000..7a5e71245d
--- /dev/null
+++ b/alcs-frontend/src/app/features/search/spinner-status/spinner-status.component.ts
@@ -0,0 +1,8 @@
+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 c5f2d6ea8a..a99e3fe84a 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;
+ status?: string | null;
}
export interface NoticeOfIntentSearchResultDto extends ApplicationSearchResultDto {}
@@ -93,3 +93,8 @@ 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 9a019340bf..3e0dcd44a3 100644
--- a/alcs-frontend/src/app/services/search/search.service.ts
+++ b/alcs-frontend/src/app/services/search/search.service.ts
@@ -13,6 +13,7 @@ import {
PlanningReviewSearchResultDto,
SearchRequestDto,
SearchResultDto,
+ StatusUpdateSearchResultDto,
} from './search.dto';
@Injectable({
@@ -45,7 +46,7 @@ export class SearchService {
return undefined;
}
}
-
+
async advancedSearchApplicationsFetch(searchDto: SearchRequestDto) {
try {
return await firstValueFrom(
@@ -61,6 +62,51 @@ 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 a10a45509d..80a08ebe80 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,6 +13,7 @@ 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 {
@@ -62,13 +63,20 @@ 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();
@@ -94,8 +102,8 @@ export class ApplicationAdvancedSearchService {
case 'government':
return '"appSearch"."local_government_name"';
- case 'portalStatus':
- return `"appSearch"."status" ->> 'label' `;
+ case 'status':
+ return `"app_status"."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 e5657ecd3e..fb92d32959 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,17 +27,10 @@ export class SearchApplicationSubmissionStatusType {
.addSelect('app.decision_date', 'decision_date')
.addSelect('app.uuid', 'application_uuid')
.addSelect('app.region_code', 'application_region_code')
- .addSelect(
- 'alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid)',
- 'status',
- )
+ .addSelect('null', '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 da276d0ebf..1677d33c14 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,6 +13,7 @@ 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 {
@@ -63,13 +64,20 @@ 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();
@@ -95,8 +103,8 @@ export class NoticeOfIntentAdvancedSearchService {
case 'government':
return '"noiSearch"."local_government_name"';
- case 'portalStatus':
- return `"noiSearch"."status" ->> 'label' `;
+ case 'status':
+ return `"noi_status"."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 d65c2ca7c9..de5352a1af 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,11 +1,4 @@
-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';
@@ -38,23 +31,12 @@ 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(
- 'alcs.get_current_status_for_notice_of_intent_submission_by_uuid(nois.uuid)',
- 'status',
- )
+ .addSelect('null', '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 6e0c3b0b36..3f9c9a90a9 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,6 +12,7 @@ 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 {
@@ -45,11 +46,7 @@ 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) {
@@ -70,17 +67,20 @@ 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 'portalStatus':
- return `"notificationSearch"."status" ->> 'label' `;
+ case 'status':
+ return `"not_status"."status" ->> 'label' `;
default:
case 'dateSubmitted':
@@ -119,18 +119,12 @@ 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);
}
@@ -148,26 +142,17 @@ 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);
}
@@ -178,16 +163,11 @@ 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,
@@ -199,34 +179,19 @@ 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 33e8e61fd2..054593f98d 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,11 +1,4 @@
-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';
@@ -35,27 +28,12 @@ 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(
- 'alcs.get_current_status_for_notification_submission_by_uuid(noti_sub.uuid)',
- 'status',
- )
+ .addSelect('null', '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 c991110101..b947e09a6e 100644
--- a/services/apps/alcs/src/alcs/search/search.controller.spec.ts
+++ b/services/apps/alcs/src/alcs/search/search.controller.spec.ts
@@ -20,6 +20,7 @@ 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;
@@ -29,10 +30,22 @@ 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();
@@ -40,6 +53,7 @@ describe('SearchController', () => {
mockNotificationAdvancedSearchService = createMock();
mockPlanningReviewAdvancedSearchService = createMock();
mockInquiryAdvancedSearchService = createMock();
+ mockSearchStatusService = createMock();
mockDataSource = createMock();
mockAppTypeRepo = createMock();
@@ -74,6 +88,10 @@ describe('SearchController', () => {
provide: InquiryAdvancedSearchService,
useValue: mockInquiryAdvancedSearchService,
},
+ {
+ provide: SearchStatusService,
+ useValue: mockSearchStatusService,
+ },
{
provide: DataSource,
useValue: mockDataSource,
@@ -103,12 +121,10 @@ 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: [],
@@ -129,6 +145,10 @@ describe('SearchController', () => {
data: [],
total: 0,
});
+
+ mockSearchStatusService.searchApplicationStatus.mockResolvedValue(statusSearchMockedResult);
+ mockSearchStatusService.searchNoiStatus.mockResolvedValue(statusSearchMockedResult);
+ mockSearchStatusService.searchNotificationStatus.mockResolvedValue(statusSearchMockedResult);
});
it('should be defined', () => {
@@ -144,13 +164,9 @@ 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);
});
@@ -168,29 +184,21 @@ 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);
});
@@ -205,16 +213,11 @@ 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);
@@ -230,15 +233,13 @@ 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);
});
@@ -256,12 +257,8 @@ 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);
@@ -279,12 +276,11 @@ 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);
});
@@ -302,10 +298,7 @@ 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);
});
@@ -322,14 +315,36 @@ 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 be0a7b6549..475ff7cc19 100644
--- a/services/apps/alcs/src/alcs/search/search.controller.ts
+++ b/services/apps/alcs/src/alcs/search/search.controller.ts
@@ -40,8 +40,10 @@ 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)
@@ -54,6 +56,7 @@ export class SearchController {
private applicationSearchService: ApplicationAdvancedSearchService,
private notificationSearchService: NotificationAdvancedSearchService,
private planningReviewSearchService: PlanningReviewAdvancedSearchService,
+ private searchStatusService: SearchStatusService,
private inquirySearchService: InquiryAdvancedSearchService,
@InjectRepository(ApplicationType)
private appTypeRepo: Repository,
@@ -183,14 +186,18 @@ export class SearchController {
): Promise> {
const queryRunner = this.dataSource.createQueryRunner('slave');
- const noticeOfIntents = await this.noticeOfIntentSearchService.searchNoticeOfIntents(searchDto, queryRunner);
+ try {
+ 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,
- };
+ return {
+ total: mappedSearchResult.totalNoticeOfIntents,
+ data: mappedSearchResult.noticeOfIntents,
+ };
+ } finally {
+ await queryRunner.release();
+ }
}
@Post('/advanced/notifications')
@@ -200,14 +207,75 @@ export class SearchController {
): Promise> {
const queryRunner = this.dataSource.createQueryRunner('slave');
- const notifications = await this.notificationSearchService.search(searchDto, queryRunner);
+ try {
+ const notifications = await this.notificationSearchService.search(searchDto, queryRunner);
- const mappedSearchResult = await this.mapAdvancedSearchResults(null, null, null, notifications, null);
+ const mappedSearchResult = await this.mapAdvancedSearchResults(null, null, null, notifications, null);
- return {
- total: mappedSearchResult.totalNotifications,
- data: mappedSearchResult.notifications,
- };
+ 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();
+ }
+ }
+
+ @Post('/advanced/noi-status')
+ @UserRoles(...ROLES_ALLOWED_APPLICATIONS)
+ async advancedSearchNoiStatus(@Body() fileNumbers: string[]): Promise {
+ const queryRunner = this.dataSource.createQueryRunner('slave');
+
+ 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();
+ }
}
@Post('/advanced/planning-reviews')
@@ -217,14 +285,18 @@ export class SearchController {
): Promise> {
const queryRunner = this.dataSource.createQueryRunner('slave');
- const planningReviews = await this.planningReviewSearchService.search(searchDto, queryRunner);
+ try {
+ 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,
- };
+ return {
+ total: mappedSearchResult.totalPlanningReviews,
+ data: mappedSearchResult.planningReviews,
+ };
+ } finally {
+ await queryRunner.release();
+ }
}
@Post('/advanced/inquiries')
@@ -234,14 +306,18 @@ export class SearchController {
): Promise> {
const queryRunner = this.dataSource.createQueryRunner('slave');
- const inquiries = await this.inquirySearchService.search(searchDto, queryRunner);
+ try {
+ 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,
- };
+ return {
+ total: mappedSearchResult.totalInquiries,
+ data: mappedSearchResult.inquiries,
+ };
+ } finally {
+ await queryRunner.release();
+ }
}
private getEntitiesTypeToSearch(searchDto: SearchRequestDto) {
@@ -434,7 +510,7 @@ export class SearchController {
localGovernmentName: application.localGovernmentName,
ownerName: application.applicant,
class: 'APP',
- status: application.status.status_type_code,
+ status: application.status && application.status.status_type_code,
};
}
@@ -449,7 +525,7 @@ export class SearchController {
localGovernmentName: noi.localGovernmentName,
ownerName: noi.applicant,
class: 'NOI',
- status: noi.status.status_type_code,
+ status: noi.status && noi.status.status_type_code,
};
}
@@ -464,7 +540,7 @@ export class SearchController {
localGovernmentName: notification.localGovernmentName,
ownerName: notification.applicant,
class: 'NOTI',
- status: notification.status.status_type_code,
+ status: notification.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 842eb1418f..401dcf8ac6 100644
--- a/services/apps/alcs/src/alcs/search/search.dto.ts
+++ b/services/apps/alcs/src/alcs/search/search.dto.ts
@@ -1,10 +1,4 @@
-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';
@@ -19,13 +13,7 @@ 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;
@@ -34,7 +22,7 @@ export class ApplicationSearchResultDto {
localGovernmentName?: string;
fileNumber: string;
boardCode?: string;
- status: string;
+ status?: string;
dateSubmitted?: number;
class: SearchEntityClass;
}
@@ -46,7 +34,7 @@ export class NoticeOfIntentSearchResultDto {
localGovernmentName?: string;
fileNumber: string;
boardCode?: string;
- status: string;
+ status?: string;
dateSubmitted?: number;
class: SearchEntityClass;
}
@@ -69,7 +57,7 @@ export class NotificationSearchResultDto {
localGovernmentName?: string;
fileNumber: string;
boardCode?: string;
- status: string;
+ status?: string;
dateSubmitted?: number;
class: SearchEntityClass;
}
@@ -100,6 +88,11 @@ 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 70b12f1261..f26630bb8f 100644
--- a/services/apps/alcs/src/alcs/search/search.module.ts
+++ b/services/apps/alcs/src/alcs/search/search.module.ts
@@ -23,6 +23,10 @@ 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: [
@@ -42,6 +46,9 @@ import { SearchService } from './search.service';
Inquiry,
InquirySearchView,
LocalGovernment,
+ ApplicationSubmissionStatusSearchView,
+ NoiSubmissionStatusSearchView,
+ NotificationSubmissionStatusSearchView,
]),
],
providers: [
@@ -52,6 +59,7 @@ import { SearchService } from './search.service';
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
new file mode 100644
index 0000000000..ed315f9183
--- /dev/null
+++ b/services/apps/alcs/src/alcs/search/status/application-search-status-view.entity.ts
@@ -0,0 +1,30 @@
+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
new file mode 100644
index 0000000000..ec8e74aa7c
--- /dev/null
+++ b/services/apps/alcs/src/alcs/search/status/noi-search-status-view.entity.ts
@@ -0,0 +1,30 @@
+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
new file mode 100644
index 0000000000..ea5ef33bdb
--- /dev/null
+++ b/services/apps/alcs/src/alcs/search/status/notification-search-status-view.entity.ts
@@ -0,0 +1,29 @@
+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
new file mode 100644
index 0000000000..fe16bf9783
--- /dev/null
+++ b/services/apps/alcs/src/alcs/search/status/search-status.service.spec.ts
@@ -0,0 +1,89 @@
+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
new file mode 100644
index 0000000000..37fc08dde1
--- /dev/null
+++ b/services/apps/alcs/src/alcs/search/status/search-status.service.ts
@@ -0,0 +1,91 @@
+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
new file mode 100644
index 0000000000..6326731c03
--- /dev/null
+++ b/services/apps/alcs/src/providers/typeorm/migrations/1731103073215-application_status_update.ts
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 0000000000..f233f3ab24
--- /dev/null
+++ b/services/apps/alcs/src/providers/typeorm/migrations/1731441606374-noi_status_update.ts
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 0000000000..c52857577a
--- /dev/null
+++ b/services/apps/alcs/src/providers/typeorm/migrations/1731444339841-remove_app_noi_status.ts
@@ -0,0 +1,64 @@
+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
new file mode 100644
index 0000000000..7978f73c73
--- /dev/null
+++ b/services/apps/alcs/src/providers/typeorm/migrations/1731453091938-notification_status_changes.ts
@@ -0,0 +1,24 @@
+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\""]);
+ }
+
+}