From d57ae4b9bb74ad9349bff5515839971cab8d2008 Mon Sep 17 00:00:00 2001 From: Tristan Slater <1631008+trslater@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:38:36 -0800 Subject: [PATCH] Convert pub app search view entity to use query builder --- .../public-application-search-view.entity.ts | 160 ++++++++++-------- ...e_query_builder_for_pub_app_search_view.ts | 85 ++++++++++ 2 files changed, 176 insertions(+), 69 deletions(-) create mode 100644 services/apps/alcs/src/providers/typeorm/migrations/1709669266230-use_query_builder_for_pub_app_search_view.ts diff --git a/services/apps/alcs/src/portal/public/search/application/public-application-search-view.entity.ts b/services/apps/alcs/src/portal/public/search/application/public-application-search-view.entity.ts index 195b7dbfad..9fc0826b1f 100644 --- a/services/apps/alcs/src/portal/public/search/application/public-application-search-view.entity.ts +++ b/services/apps/alcs/src/portal/public/search/application/public-application-search-view.entity.ts @@ -1,75 +1,97 @@ -import { PrimaryColumn, ViewColumn, ViewEntity } from 'typeorm'; +import { DataSource, PrimaryColumn, ViewColumn, ViewEntity } from 'typeorm'; +import { ApplicationDecision } from '../../../../alcs/application-decision/application-decision.entity'; +import { SUBMISSION_STATUS } from '../../../../alcs/application/application-submission-status/submission-status.dto'; +import { ApplicationSubmissionToSubmissionStatus } from '../../../../alcs/application/application-submission-status/submission-status.entity'; +import { Application } from '../../../../alcs/application/application.entity'; +import { ApplicationType } from '../../../../alcs/code/application-code/application-type/application-type.entity'; +import { LocalGovernment } from '../../../../alcs/local-government/local-government.entity'; +import { ApplicationSubmission } from '../../../application-submission/application-submission.entity'; import { LinkedStatusType } from '../public-search.dto'; @ViewEntity({ - expression: ` - SELECT - app_sub.uuid, - app_sub.applicant, - app.uuid AS application_uuid, - "localGovernment".name AS local_government_name, - app_sub.file_number, - app_sub.local_government_uuid, - app_sub.type_code AS application_type_code, - app.date_submitted_to_alc, - app.decision_date, - decision_date.outcome, - decision_date.dest_rank, - app.region_code AS application_region_code, - GREATEST(status_link.effective_date, decision_date.date) AS last_update, - alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid) AS status - FROM - alcs.application_submission app_sub - JOIN alcs.application app ON app.file_number :: text = app_sub.file_number :: text - AND app.hide_from_portal = false - 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 - LEFT JOIN ( - SELECT - max(status_link_1.effective_date) AS effective_date, - status_link_1.submission_uuid - FROM - alcs.application_submission_to_submission_status status_link_1 - GROUP BY - status_link_1.submission_uuid - ) status_link ON status_link.submission_uuid = app_sub.uuid - LEFT JOIN ( - SELECT - DISTINCT ON (decisions.applicationuuid) decisions.decisiondate AS date, - decisions.outcome, - decisions.dest_rank, - decisions.applicationuuid AS application_uuid - FROM - ( - SELECT - decision.outcome_code AS outcome, - decision.date AS decisiondate, - decision.application_uuid AS applicationuuid, - rank() OVER ( - PARTITION BY decision.application_uuid - ORDER BY - decision.date DESC, - decision.audit_created_at DESC - ) AS dest_rank - FROM - alcs.application_decision decision - WHERE - decision.is_draft = false - AND decision.audit_deleted_date_at IS NULL - ) decisions - WHERE - decisions.dest_rank = 1 - ) decision_date ON decision_date.application_uuid = app.uuid - WHERE - app_sub.is_draft = false - AND app.date_received_all_items IS NOT NULL - AND app.date_received_all_items <= now() - AND ( - alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid) ->> 'status_type_code' :: text - ) <> 'CANC' :: text - AND app_sub.audit_deleted_date_at IS NULL; - `, + expression: (datasource: DataSource) => + datasource + .createQueryBuilder() + .select('app_sub.uuid', 'uuid') + .addSelect('app_sub.file_number', 'file_number') + .addSelect('app_sub.applicant', 'applicant') + .addSelect('app_sub.local_government_uuid', 'local_government_uuid') + .addSelect('localGovernment.name', 'local_government_name') + .addSelect('app_sub.type_code', 'application_type_code') + .addSelect('app.date_submitted_to_alc', 'date_submitted_to_alc') + .addSelect('app.decision_date', 'decision_date') + .addSelect('decision_date.outcome', 'outcome') + .addSelect('decision_date.dest_rank', 'dest_rank') + .addSelect('app.uuid', 'application_uuid') + .addSelect('app.region_code', 'application_region_code') + .addSelect( + 'GREATEST(status_link.effective_date, decision_date.date)', + 'last_update', + ) + .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 AND app.hide_from_portal = FALSE', + ) + .innerJoinAndSelect( + ApplicationType, + 'applicationType', + 'app_sub.type_code = applicationType.code', + ) + .leftJoin( + LocalGovernment, + 'localGovernment', + 'app_sub.local_government_uuid = localGovernment.uuid', + ) + .leftJoin( + (qb) => + qb + .from(ApplicationSubmissionToSubmissionStatus, 'status_link') + .select('MAX("effective_date")', 'effective_date') + .addSelect('submission_uuid', 'submission_uuid') + .groupBy('submission_uuid'), + 'status_link', + 'status_link."submission_uuid" = app_sub.uuid', + ) + .leftJoin( + (qb) => + qb + .select('decisiondate', 'date') + .addSelect('outcome', 'outcome') + .addSelect('dest_rank', 'dest_rank') + .distinctOn(['application_uuid']) + .addSelect('applicationuuid', 'application_uuid') + .from( + qb + .subQuery() + .select('outcome_code', 'outcome') + .addSelect('date', 'decisiondate') + .addSelect('application_uuid', 'applicationuuid') + .addSelect( + 'RANK() OVER (PARTITION BY application_uuid ORDER BY date DESC, audit_created_at DESC)', + 'dest_rank', + ) + .where('is_draft = FALSE') + .from(ApplicationDecision, 'decision') + .getQuery(), + 'decisions', + ) + .where('dest_rank = 1'), + 'decision_date', + 'decision_date."application_uuid" = app.uuid', + ) + .where('app_sub.is_draft = FALSE') + .andWhere( + '(app.date_received_all_items IS NOT NULL AND app.date_received_all_items <= NOW())', + ) + .andWhere( + `alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid)->>'status_type_code' != '${SUBMISSION_STATUS.CANCELLED}'`, + ), }) export class PublicApplicationSubmissionSearchView { @ViewColumn() diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1709669266230-use_query_builder_for_pub_app_search_view.ts b/services/apps/alcs/src/providers/typeorm/migrations/1709669266230-use_query_builder_for_pub_app_search_view.ts new file mode 100644 index 0000000000..b9f5129c7a --- /dev/null +++ b/services/apps/alcs/src/providers/typeorm/migrations/1709669266230-use_query_builder_for_pub_app_search_view.ts @@ -0,0 +1,85 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UseQueryBuilderForPubAppSearchView1709669266230 implements MigrationInterface { + name = 'UseQueryBuilderForPubAppSearchView1709669266230' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","public_application_submission_search_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."public_application_submission_search_view"`); + await queryRunner.query(`CREATE VIEW "alcs"."public_application_submission_search_view" AS SELECT "app_sub"."uuid" AS "uuid", "app_sub"."applicant" AS "applicant", "app"."uuid" AS "application_uuid", "applicationType"."audit_deleted_date_at" AS "applicationType_audit_deleted_date_at", "applicationType"."audit_created_at" AS "applicationType_audit_created_at", "applicationType"."audit_updated_at" AS "applicationType_audit_updated_at", "applicationType"."audit_created_by" AS "applicationType_audit_created_by", "applicationType"."audit_updated_by" AS "applicationType_audit_updated_by", "applicationType"."label" AS "applicationType_label", "applicationType"."code" AS "applicationType_code", "applicationType"."description" AS "applicationType_description", "applicationType"."short_label" AS "applicationType_short_label", "applicationType"."background_color" AS "applicationType_background_color", "applicationType"."text_color" AS "applicationType_text_color", "applicationType"."html_description" AS "applicationType_html_description", "applicationType"."portal_label" AS "applicationType_portal_label", "applicationType"."portal_order" AS "applicationType_portal_order", "applicationType"."requires_government_review" AS "applicationType_requires_government_review", "applicationType"."alc_fee_amount" AS "applicationType_alc_fee_amount", "applicationType"."government_fee_amount" AS "applicationType_government_fee_amount", "localGovernment"."name" AS "local_government_name", "app_sub"."file_number" AS "file_number", "app_sub"."local_government_uuid" AS "local_government_uuid", "app_sub"."type_code" AS "application_type_code", "app"."date_submitted_to_alc" AS "date_submitted_to_alc", "app"."decision_date" AS "decision_date", decision_date.outcome AS "outcome", decision_date.dest_rank AS "dest_rank", "app"."region_code" AS "application_region_code", GREATEST(status_link.effective_date, decision_date.date) AS "last_update", 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"."hide_from_portal" = FALSE AND "app"."audit_deleted_date_at" IS NULL INNER JOIN "alcs"."application_type" "applicationType" ON "app_sub"."type_code" = "applicationType"."code" AND "applicationType"."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 LEFT JOIN (SELECT MAX("effective_date") AS "effective_date", submission_uuid AS "submission_uuid" FROM "alcs"."application_submission_to_submission_status" "status_link" GROUP BY submission_uuid) "status_link" ON status_link."submission_uuid" = "app_sub"."uuid" LEFT JOIN (SELECT DISTINCT ON (application_uuid) decisiondate AS "date", outcome AS "outcome", dest_rank AS "dest_rank", applicationuuid AS "application_uuid" FROM (SELECT outcome_code AS "outcome", date AS "decisiondate", application_uuid AS "applicationuuid", RANK() OVER (PARTITION BY application_uuid ORDER BY date DESC, audit_created_at DESC) AS "dest_rank" FROM "alcs"."application_decision" "decision" WHERE ( is_draft = FALSE ) AND ( "decision"."audit_deleted_date_at" IS NULL )) "decisions" WHERE dest_rank = 1) "decision_date" ON decision_date."application_uuid" = "app"."uuid" WHERE ( "app_sub"."is_draft" = FALSE AND ("app"."date_received_all_items" IS NOT NULL AND "app"."date_received_all_items" <= NOW()) AND alcs.get_current_status_for_application_submission_by_uuid("app_sub"."uuid")->>'status_type_code' != 'CANC' ) 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","public_application_submission_search_view","SELECT \"app_sub\".\"uuid\" AS \"uuid\", \"app_sub\".\"applicant\" AS \"applicant\", \"app\".\"uuid\" AS \"application_uuid\", \"applicationType\".\"audit_deleted_date_at\" AS \"applicationType_audit_deleted_date_at\", \"applicationType\".\"audit_created_at\" AS \"applicationType_audit_created_at\", \"applicationType\".\"audit_updated_at\" AS \"applicationType_audit_updated_at\", \"applicationType\".\"audit_created_by\" AS \"applicationType_audit_created_by\", \"applicationType\".\"audit_updated_by\" AS \"applicationType_audit_updated_by\", \"applicationType\".\"label\" AS \"applicationType_label\", \"applicationType\".\"code\" AS \"applicationType_code\", \"applicationType\".\"description\" AS \"applicationType_description\", \"applicationType\".\"short_label\" AS \"applicationType_short_label\", \"applicationType\".\"background_color\" AS \"applicationType_background_color\", \"applicationType\".\"text_color\" AS \"applicationType_text_color\", \"applicationType\".\"html_description\" AS \"applicationType_html_description\", \"applicationType\".\"portal_label\" AS \"applicationType_portal_label\", \"applicationType\".\"portal_order\" AS \"applicationType_portal_order\", \"applicationType\".\"requires_government_review\" AS \"applicationType_requires_government_review\", \"applicationType\".\"alc_fee_amount\" AS \"applicationType_alc_fee_amount\", \"applicationType\".\"government_fee_amount\" AS \"applicationType_government_fee_amount\", \"localGovernment\".\"name\" AS \"local_government_name\", \"app_sub\".\"file_number\" AS \"file_number\", \"app_sub\".\"local_government_uuid\" AS \"local_government_uuid\", \"app_sub\".\"type_code\" AS \"application_type_code\", \"app\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", \"app\".\"decision_date\" AS \"decision_date\", decision_date.outcome AS \"outcome\", decision_date.dest_rank AS \"dest_rank\", \"app\".\"region_code\" AS \"application_region_code\", GREATEST(status_link.effective_date, decision_date.date) AS \"last_update\", 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\".\"hide_from_portal\" = FALSE AND \"app\".\"audit_deleted_date_at\" IS NULL INNER JOIN \"alcs\".\"application_type\" \"applicationType\" ON \"app_sub\".\"type_code\" = \"applicationType\".\"code\" AND \"applicationType\".\"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 LEFT JOIN (SELECT MAX(\"effective_date\") AS \"effective_date\", submission_uuid AS \"submission_uuid\" FROM \"alcs\".\"application_submission_to_submission_status\" \"status_link\" GROUP BY submission_uuid) \"status_link\" ON status_link.\"submission_uuid\" = \"app_sub\".\"uuid\" LEFT JOIN (SELECT DISTINCT ON (application_uuid) decisiondate AS \"date\", outcome AS \"outcome\", dest_rank AS \"dest_rank\", applicationuuid AS \"application_uuid\" FROM (SELECT outcome_code AS \"outcome\", date AS \"decisiondate\", application_uuid AS \"applicationuuid\", RANK() OVER (PARTITION BY application_uuid ORDER BY date DESC, audit_created_at DESC) AS \"dest_rank\" FROM \"alcs\".\"application_decision\" \"decision\" WHERE ( is_draft = FALSE ) AND ( \"decision\".\"audit_deleted_date_at\" IS NULL )) \"decisions\" WHERE dest_rank = 1) \"decision_date\" ON decision_date.\"application_uuid\" = \"app\".\"uuid\" WHERE ( \"app_sub\".\"is_draft\" = FALSE AND (\"app\".\"date_received_all_items\" IS NOT NULL AND \"app\".\"date_received_all_items\" <= NOW()) AND alcs.get_current_status_for_application_submission_by_uuid(\"app_sub\".\"uuid\")->>'status_type_code' != 'CANC' ) 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","public_application_submission_search_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."public_application_submission_search_view"`); + await queryRunner.query(`CREATE VIEW "alcs"."public_application_submission_search_view" AS SELECT + app_sub.uuid, + app_sub.applicant, + app.uuid AS application_uuid, + "localGovernment".name AS local_government_name, + app_sub.file_number, + app_sub.local_government_uuid, + app_sub.type_code AS application_type_code, + app.date_submitted_to_alc, + app.decision_date, + decision_date.outcome, + decision_date.dest_rank, + app.region_code AS application_region_code, + GREATEST(status_link.effective_date, decision_date.date) AS last_update, + alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid) AS status + FROM + alcs.application_submission app_sub + JOIN alcs.application app ON app.file_number :: text = app_sub.file_number :: text + AND app.hide_from_portal = false + 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 + LEFT JOIN ( + SELECT + max(status_link_1.effective_date) AS effective_date, + status_link_1.submission_uuid + FROM + alcs.application_submission_to_submission_status status_link_1 + GROUP BY + status_link_1.submission_uuid + ) status_link ON status_link.submission_uuid = app_sub.uuid + LEFT JOIN ( + SELECT + DISTINCT ON (decisions.applicationuuid) decisions.decisiondate AS date, + decisions.outcome, + decisions.dest_rank, + decisions.applicationuuid AS application_uuid + FROM + ( + SELECT + decision.outcome_code AS outcome, + decision.date AS decisiondate, + decision.application_uuid AS applicationuuid, + rank() OVER ( + PARTITION BY decision.application_uuid + ORDER BY + decision.date DESC, + decision.audit_created_at DESC + ) AS dest_rank + FROM + alcs.application_decision decision + WHERE + decision.is_draft = false + AND decision.audit_deleted_date_at IS NULL + ) decisions + WHERE + decisions.dest_rank = 1 + ) decision_date ON decision_date.application_uuid = app.uuid + WHERE + app_sub.is_draft = false + AND app.date_received_all_items IS NOT NULL + AND app.date_received_all_items <= now() + AND ( + alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid) ->> 'status_type_code' :: text + ) <> 'CANC' :: text + 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","public_application_submission_search_view","SELECT\n app_sub.uuid,\n app_sub.applicant,\n app.uuid AS application_uuid,\n \"localGovernment\".name AS local_government_name,\n app_sub.file_number,\n app_sub.local_government_uuid,\n app_sub.type_code AS application_type_code,\n app.date_submitted_to_alc,\n app.decision_date,\n decision_date.outcome,\n decision_date.dest_rank,\n app.region_code AS application_region_code,\n GREATEST(status_link.effective_date, decision_date.date) AS last_update,\n alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid) AS status\n FROM\n alcs.application_submission app_sub\n JOIN alcs.application app ON app.file_number :: text = app_sub.file_number :: text\n AND app.hide_from_portal = false\n AND app.audit_deleted_date_at IS NULL\n LEFT JOIN alcs.local_government \"localGovernment\" ON app_sub.local_government_uuid = \"localGovernment\".uuid\n AND \"localGovernment\".audit_deleted_date_at IS NULL\n LEFT JOIN (\n SELECT\n max(status_link_1.effective_date) AS effective_date,\n status_link_1.submission_uuid\n FROM\n alcs.application_submission_to_submission_status status_link_1\n GROUP BY\n status_link_1.submission_uuid\n ) status_link ON status_link.submission_uuid = app_sub.uuid\n LEFT JOIN (\n SELECT\n DISTINCT ON (decisions.applicationuuid) decisions.decisiondate AS date,\n decisions.outcome,\n decisions.dest_rank,\n decisions.applicationuuid AS application_uuid\n FROM\n (\n SELECT\n decision.outcome_code AS outcome,\n decision.date AS decisiondate,\n decision.application_uuid AS applicationuuid,\n rank() OVER (\n PARTITION BY decision.application_uuid\n ORDER BY\n decision.date DESC,\n decision.audit_created_at DESC\n ) AS dest_rank\n FROM\n alcs.application_decision decision\n WHERE\n decision.is_draft = false\n AND decision.audit_deleted_date_at IS NULL\n ) decisions\n WHERE\n decisions.dest_rank = 1\n ) decision_date ON decision_date.application_uuid = app.uuid\n WHERE\n app_sub.is_draft = false\n AND app.date_received_all_items IS NOT NULL\n AND app.date_received_all_items <= now()\n AND (\n alcs.get_current_status_for_application_submission_by_uuid(app_sub.uuid) ->> 'status_type_code' :: text\n ) <> 'CANC' :: text\n AND app_sub.audit_deleted_date_at IS NULL;"]); + } + +}