diff --git a/express-api/package.json b/express-api/package.json index d7e69bad35..889bc3cf37 100644 --- a/express-api/package.json +++ b/express-api/package.json @@ -36,7 +36,7 @@ "pg": "8.11.3", "reflect-metadata": "0.2.1", "swagger-ui-express": "5.0.0", - "typeorm": "0.3.17", + "typeorm": "0.3.20", "typeorm-naming-strategies": "4.1.0", "winston": "3.12.0", "zod": "3.22.4" diff --git a/express-api/src/controllers/buildings/IBuilding.ts b/express-api/src/controllers/buildings/IBuilding.ts deleted file mode 100644 index 3b503c1f91..0000000000 --- a/express-api/src/controllers/buildings/IBuilding.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { IBaseEntity } from '@/controllers/common/IBaseEntity'; -export interface IAddress extends IBaseEntity { - rowVersion: string; - id: number; - line1: string; - line2: string; - administrativeArea: string; - provinceId: string; - province: string; - postal: string; -} - -export interface IEvaluation extends IBaseEntity { - rowVersion: string; - parcelId: number; - date: string; - key: string; - value: number; - note: string; - firm: string; -} - -export interface IFiscal extends IBaseEntity { - rowVersion: string; - parcelId: number; - fiscalYear: number; - effectiveDate: string; - key: string; - value: number; - note: string; -} - -export interface IBuilding extends IBaseEntity { - rowVersion: string; - id: number; - propertyTypeId: number; - projectNumbers: string[]; - projectWorkflow: string; - projectStatus: string; - name: string; - description: string; - classificationId: number; - classification: string; - encumbranceReason: string; - agencyId: number; - subAgency: string; - agency: string; - subAgencyFullName: string; - agencyFullName: string; - address: IAddress; - latitude: number; - longitude: number; - isSensitive: boolean; - isVisibleToOtherAgencies: boolean; - parcelId: number; - buildingConstructionTypeId: number; - buildingConstructionType: string; - buildingFloorCount: number; - buildingPredominateUseId: number; - buildingPredominateUse: string; - buildingOccupantTypeId: number; - buildingOccupantType: string; - leaseExpiry: string; - occupantName: string; - transferLeaseOnSale: boolean; - buildingTenancy: string; - rentableArea: number; - evaluations: IEvaluation[]; - fiscals: IFiscal[]; -} diff --git a/express-api/src/controllers/parcels/IParcel.ts b/express-api/src/controllers/parcels/IParcel.ts deleted file mode 100644 index 402c9e61dd..0000000000 --- a/express-api/src/controllers/parcels/IParcel.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { IProperty } from '@/controllers/properties/IProperty'; -import { IBaseEntity } from '@/controllers/common/IBaseEntity'; -/** - * Some of these can probably be separated out elsewhere later, but I think this is fine for now. - * Was uncertain whether ISubdivision or ISubParcel are meant to be just a selection from IParcel or their own interfaces. - */ - -interface IAddress extends IBaseEntity { - id: number; - line1: string; - line2: string; - administrativeArea: string; - provinceId: string; - province: string; - postal: string; -} - -interface IEvaluation extends IBaseEntity { - parcelId: number; - date: string; - key: string; - value: number; - note: string; - firm: string; -} - -interface IFiscal extends IBaseEntity { - parcelId: number; - fiscalYear: number; - effectiveDate: string; - key: string; - value: number; - note: string; -} - -interface IBuilding extends IBaseEntity { - id: number; - propertyTypeId: number; - projectNumbers: string[]; - projectWorkflow: string; - projectStatus: string; - name: string; - description: string; - classificationId: number; - classification: string; - encumbranceReason: string; - agencyId: number; - subAgency: string; - agency: string; - subAgencyFullName: string; - agencyFullName: string; - address: IAddress; - latitude: number; - longitude: number; - isSensitive: boolean; - isVisibleToOtherAgencies: boolean; - parcelId: number; - buildingConstructionTypeId: number; - buildingConstructionType: string; - buildingFloorCount: number; - buildingPredominateUseId: number; - buildingPredominateUse: string; - buildingOccupantTypeId: number; - buildingOccupantType: string; - leaseExpiry: string; - occupantName: string; - transferLeaseOnSale: boolean; - buildingTenancy: string; - rentableArea: number; - evaluations: IEvaluation[]; - fiscals: IFiscal[]; -} - -interface ISubParcel extends IBaseEntity { - id: number; - pid: string; - pin: number; -} - -interface ISubdivision extends IBaseEntity { - id: number; - pid: string; - pin: number; -} - -interface IParcel extends IProperty, IBaseEntity { - projectWorkflow: string; - projectStatus: string; - classification: string; - subAgency: string; - agency: string; - subAgencyFullName: string; - agencyFullName: string; - address: IAddress; - latitude: number; - longitude: number; - isSensitive: boolean; - isVisibleToOtherAgencies: boolean; - pid: string; - pin: number; - landArea: number; - landLegalDescription: string; - zoning: string; - zoningPotential: string; - evaluations: IEvaluation[]; - fiscals: IFiscal[]; - buildings: IBuilding[]; - parcels: ISubParcel[]; - subdivisions: ISubdivision[]; -} - -export { IParcel }; diff --git a/express-api/src/controllers/properties/IProperty.ts b/express-api/src/controllers/properties/IProperty.ts deleted file mode 100644 index bb11f54730..0000000000 --- a/express-api/src/controllers/properties/IProperty.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Geometry, Point } from 'typeorm'; - -export interface IProperty { - id: number; - propertyType: string; - propertyTypeId: number; - projectNumbers: string[]; - name: string; - description: string; - classificationId: number; - encumbranceReason: string; - agencyId?: number | null; - addressId: number; - location: Point; - boundary?: Geometry; - isSensitive: boolean; - isVisibleToOtherAgencies: boolean; -} diff --git a/express-api/src/typeorm/Entities/AccessRequest.ts b/express-api/src/typeorm/Entities/AccessRequest.ts deleted file mode 100644 index fab2a42373..0000000000 --- a/express-api/src/typeorm/Entities/AccessRequest.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { BaseEntity } from '@/typeorm/Entities/abstractEntities/BaseEntity'; -import { User } from '@/typeorm/Entities/User'; -import { Role } from '@/typeorm/Entities/Role'; -import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, Index, JoinColumn } from 'typeorm'; -import { Agency } from './Agency'; -import { UUID } from 'crypto'; - -@Entity() -export class AccessRequest extends BaseEntity { - @PrimaryGeneratedColumn() - Id: number; - - // User Relations - @Column({ name: 'user_id', type: 'uuid' }) - UserId: UUID; - - @ManyToOne(() => User, (User) => User.Id) - @JoinColumn({ name: 'user_id' }) - @Index() - User: User; - - @Column({ type: 'character varying', length: 1000, nullable: true }) - Note: string; - - @Column({ type: 'int' }) - @Index() - Status: number; - - // Role Relations - @Column({ name: 'role_id', type: 'uuid' }) - RoleId: UUID; - - @ManyToOne(() => Role, (Role) => Role.Id) - @JoinColumn({ name: 'role_id' }) - Role: Role; - - // Agency Relations - @Column({ name: 'agency_id', type: 'int' }) - AgencyId: number; - - @ManyToOne(() => Agency, (Agency) => Agency.Id) - @JoinColumn({ name: 'agency_id' }) - Agency: Agency; -} diff --git a/express-api/src/typeorm/Entities/Agency.ts b/express-api/src/typeorm/Entities/Agency.ts index e0d06ba70f..1a0461f107 100644 --- a/express-api/src/typeorm/Entities/Agency.ts +++ b/express-api/src/typeorm/Entities/Agency.ts @@ -1,12 +1,12 @@ import { Entity, Index, - PrimaryColumn, Column, ManyToOne, JoinColumn, OneToMany, Relation, + PrimaryGeneratedColumn, } from 'typeorm'; import { BaseEntity } from '@/typeorm/Entities/abstractEntities/BaseEntity'; import { User } from '@/typeorm/Entities/User'; @@ -14,7 +14,7 @@ import { User } from '@/typeorm/Entities/User'; @Entity() @Index(['ParentId', 'IsDisabled', 'Id', 'Name', 'SortOrder']) // I'm not sure this index is needed. How often do we search by this group? export class Agency extends BaseEntity { - @PrimaryColumn({ type: 'int' }) + @PrimaryGeneratedColumn({ type: 'int' }) Id: number; @Column({ type: 'character varying', length: 150 }) diff --git a/express-api/src/typeorm/Entities/Building.ts b/express-api/src/typeorm/Entities/Building.ts index 563ffb3a58..73ed448f06 100644 --- a/express-api/src/typeorm/Entities/Building.ts +++ b/express-api/src/typeorm/Entities/Building.ts @@ -1,14 +1,16 @@ import { BuildingConstructionType } from '@/typeorm/Entities/BuildingConstructionType'; import { BuildingOccupantType } from '@/typeorm/Entities/BuildingOccupantType'; import { BuildingPredominateUse } from '@/typeorm/Entities/BuildingPredominateUse'; -import { Entity, Column, ManyToOne, Index, JoinColumn } from 'typeorm'; +import { Entity, Column, ManyToOne, Index, JoinColumn, OneToMany } from 'typeorm'; import { Property } from '@/typeorm/Entities/abstractEntities/Property'; +import { BuildingFiscal } from '@/typeorm/Entities/BuildingFiscal'; +import { BuildingEvaluation } from '@/typeorm/Entities/BuildingEvaluation'; // Should the occupant information (OccupantTypeId, OccupantName, and BuildingTenancyUpdatedOn) be a separate table? // This may change over time and we wouldn't be able to track previous occupants by storing it in this table. -// Can Buildings and Parcels share a base Properties entity? @Entity() +@Index(['PID', 'PIN'], { unique: false }) export class Building extends Property { // Construction Type Relations @Column({ name: 'building_construction_type_id', type: 'int' }) @@ -67,4 +69,10 @@ export class Building extends Property { @Column({ type: 'real' }) TotalArea: number; + + @OneToMany(() => BuildingFiscal, (Fiscal) => Fiscal.BuildingId, { nullable: true }) + Fiscals: BuildingFiscal[]; + + @OneToMany(() => BuildingEvaluation, (Evaluation) => Evaluation.BuildingId, { nullable: true }) + Evaluations: BuildingEvaluation[]; } diff --git a/express-api/src/typeorm/Entities/Parcel.ts b/express-api/src/typeorm/Entities/Parcel.ts index f256b8e19c..ff31a6ad20 100644 --- a/express-api/src/typeorm/Entities/Parcel.ts +++ b/express-api/src/typeorm/Entities/Parcel.ts @@ -1,15 +1,11 @@ -import { Entity, Column, Index, ManyToOne, JoinColumn } from 'typeorm'; +import { Entity, Column, Index, ManyToOne, JoinColumn, OneToMany } from 'typeorm'; import { Property } from '@/typeorm/Entities/abstractEntities/Property'; +import { ParcelFiscal } from '@/typeorm/Entities/ParcelFiscal'; +import { ParcelEvaluation } from '@/typeorm/Entities/ParcelEvaluation'; @Entity() @Index(['PID', 'PIN'], { unique: true }) export class Parcel extends Property { - @Column({ type: 'int' }) - PID: number; - - @Column({ type: 'int', nullable: true }) - PIN: number; - @Column({ type: 'real', nullable: true }) LandArea: number; @@ -31,4 +27,10 @@ export class Parcel extends Property { @ManyToOne(() => Parcel, (Parcel) => Parcel.Id) @JoinColumn({ name: 'parent_parcel_id' }) ParentParcel: Parcel; + + @OneToMany(() => ParcelFiscal, (Fiscal) => Fiscal.ParcelId, { nullable: true }) + Fiscals: ParcelFiscal[]; + + @OneToMany(() => ParcelEvaluation, (Evaluation) => Evaluation.ParcelId, { nullable: true }) + Evaluations: ParcelEvaluation[]; } diff --git a/express-api/src/typeorm/Entities/ParcelBuilding.ts b/express-api/src/typeorm/Entities/ParcelBuilding.ts deleted file mode 100644 index 1f4b8c771d..0000000000 --- a/express-api/src/typeorm/Entities/ParcelBuilding.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { BaseEntity } from '@/typeorm/Entities/abstractEntities/BaseEntity'; -import { Entity, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm'; -import { Parcel } from '@/typeorm/Entities/Parcel'; -import { Building } from '@/typeorm/Entities/Building'; - -@Entity() -export class ParcelBuilding extends BaseEntity { - @PrimaryColumn({ name: 'parcel_id', type: 'int' }) - ParcelId: number; - - @ManyToOne(() => Parcel, (Parcel) => Parcel.Id) - @JoinColumn({ name: 'parcel_id' }) - Parcel: Parcel; - - @PrimaryColumn({ name: 'building_id', type: 'int' }) - BuildingId: number; - - @ManyToOne(() => Building, (Building) => Building.Id) - @JoinColumn({ name: 'building_id' }) - Building: Building; -} diff --git a/express-api/src/typeorm/Entities/abstractEntities/BaseEntity.ts b/express-api/src/typeorm/Entities/abstractEntities/BaseEntity.ts index 61e1334413..52ac73477c 100644 --- a/express-api/src/typeorm/Entities/abstractEntities/BaseEntity.ts +++ b/express-api/src/typeorm/Entities/abstractEntities/BaseEntity.ts @@ -1,6 +1,14 @@ import type { User } from '@/typeorm/Entities/User'; import { UUID } from 'crypto'; -import { Column, CreateDateColumn, ManyToOne, JoinColumn, Index, Relation } from 'typeorm'; +import { + Column, + CreateDateColumn, + ManyToOne, + JoinColumn, + Index, + Relation, + UpdateDateColumn, +} from 'typeorm'; export abstract class BaseEntity { @Column({ name: 'created_by_id' }) @@ -22,6 +30,6 @@ export abstract class BaseEntity { @Index() UpdatedBy: Relation; - @Column({ type: 'timestamp', nullable: true }) + @UpdateDateColumn({ type: 'timestamp', nullable: true }) UpdatedOn: Date; } diff --git a/express-api/src/typeorm/Entities/abstractEntities/Property.ts b/express-api/src/typeorm/Entities/abstractEntities/Property.ts index 02c5c65d6b..e88dead20d 100644 --- a/express-api/src/typeorm/Entities/abstractEntities/Property.ts +++ b/express-api/src/typeorm/Entities/abstractEntities/Property.ts @@ -85,6 +85,12 @@ export abstract class Property extends BaseEntity { @Column({ type: 'character varying', length: 6, nullable: true }) Postal: string; + @Column({ type: 'int', nullable: true }) + PID: number; + + @Column({ type: 'int', nullable: true }) + PIN: number; + // Including this for quick geocoder lookup. @Column({ type: 'character varying', nullable: true }) SiteId: string; diff --git a/express-api/src/typeorm/Entities/views/PropertyView.ts b/express-api/src/typeorm/Entities/views/PropertyView.ts new file mode 100644 index 0000000000..fac893f30d --- /dev/null +++ b/express-api/src/typeorm/Entities/views/PropertyView.ts @@ -0,0 +1,24 @@ +import { ViewColumn, ViewEntity } from 'typeorm'; + +@ViewEntity({ + materialized: true, + expression: ` + SELECT b.id AS "building_id", b.pid, b.pin, p.id as "parcel_id" + FROM building b + LEFT OUTER JOIN parcel p + ON b.pid = p.pid OR b.pin = p.pin; + `, +}) +export class BuildingRelations { + @ViewColumn({ name: 'building_id' }) + BuildingId: number; + + @ViewColumn({ name: 'parcel_id' }) + ParcelId: number; + + @ViewColumn({ name: 'pid' }) + PID: number; + + @ViewColumn({ name: 'pin' }) + PIN: number; +} diff --git a/express-api/src/typeorm/Migrations/1710178740326-ParcelBuildingChange.ts b/express-api/src/typeorm/Migrations/1710178740326-ParcelBuildingChange.ts new file mode 100644 index 0000000000..acbb095488 --- /dev/null +++ b/express-api/src/typeorm/Migrations/1710178740326-ParcelBuildingChange.ts @@ -0,0 +1,251 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class ParcelBuildingChange1710178740326 implements MigrationInterface { + name = 'ParcelBuildingChange1710178740326'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "building" ADD "pid" integer`); + await queryRunner.query(`ALTER TABLE "building" ADD "pin" integer`); + await queryRunner.query(`ALTER TABLE "user" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query(`ALTER TABLE "user" ALTER COLUMN "id" SET DEFAULT uuid_generate_v4()`); + await queryRunner.query( + `ALTER TABLE "regional_district" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query(`ALTER TABLE "province" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query( + `ALTER TABLE "administrative_area" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query(`ALTER TABLE "role" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query(`DROP INDEX "public"."IDX_648ccf166d25060756fd37857a"`); + await queryRunner.query(`ALTER TABLE "agency" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query(`CREATE SEQUENCE IF NOT EXISTS "agency_id_seq" OWNED BY "agency"."id"`); + await queryRunner.query( + `ALTER TABLE "agency" ALTER COLUMN "id" SET DEFAULT nextval('"agency_id_seq"')`, + ); + await queryRunner.query( + `ALTER TABLE "building_construction_type" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "building_occupant_type" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "building_predominate_use" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "property_classification" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "property_type" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query(`ALTER TABLE "building" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query( + `ALTER TABLE "evaluation_key" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "building_evaluation" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query(`ALTER TABLE "fiscal_key" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query( + `ALTER TABLE "building_fiscal" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_status" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query(`ALTER TABLE "workflow" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query(`ALTER TABLE "tier_level" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query( + `ALTER TABLE "project_risk" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query(`ALTER TABLE "project" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query( + `ALTER TABLE "notification_template" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "notification_queue" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query(`DROP INDEX "public"."IDX_b2b62506b1c247926530b027c8"`); + await queryRunner.query(`ALTER TABLE "parcel" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query(`ALTER TABLE "parcel" ALTER COLUMN "pid" DROP NOT NULL`); + await queryRunner.query( + `ALTER TABLE "parcel_evaluation" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "parcel_fiscal" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_agency_response" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_note" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_number" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_property" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "report_type" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_report" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_snapshot" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_status_history" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_status_notification" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_status_transition" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query(`ALTER TABLE "task" ALTER COLUMN "updated_on" SET DEFAULT now()`); + await queryRunner.query( + `ALTER TABLE "project_task" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "project_type" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `ALTER TABLE "workflow_project_status" ALTER COLUMN "updated_on" SET DEFAULT now()`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_648ccf166d25060756fd37857a" ON "agency" ("parent_id", "is_disabled", "id", "name", "sort_order") `, + ); + await queryRunner.query( + `CREATE INDEX "IDX_cac35fff060f2e78760a4f77af" ON "building" ("pid", "pin") `, + ); + await queryRunner.query( + `CREATE UNIQUE INDEX "IDX_b2b62506b1c247926530b027c8" ON "parcel" ("pid", "pin") `, + ); + await queryRunner.query( + `ALTER TABLE "parcel_building" DROP CONSTRAINT "FK_470344017e1808fe014bb928ceb"`, + ); + await queryRunner.query( + `ALTER TABLE "parcel_building" DROP CONSTRAINT "FK_4082fbe646622fd7b9060dedc0a"`, + ); + await queryRunner.query( + `ALTER TABLE "parcel_building" DROP CONSTRAINT "FK_5430f31be522f210ae8ceb5d8ee"`, + ); + await queryRunner.query( + `ALTER TABLE "parcel_building" DROP CONSTRAINT "FK_ab453e13084937c4f6bc93981d7"`, + ); + await queryRunner.query(`DROP TABLE "parcel_building"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "public"."IDX_b2b62506b1c247926530b027c8"`); + await queryRunner.query(`DROP INDEX "public"."IDX_cac35fff060f2e78760a4f77af"`); + await queryRunner.query(`DROP INDEX "public"."IDX_648ccf166d25060756fd37857a"`); + await queryRunner.query( + `ALTER TABLE "workflow_project_status" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "project_type" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "project_task" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "task" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `ALTER TABLE "project_status_transition" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "project_status_notification" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "project_status_history" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "project_snapshot" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "project_report" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "report_type" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `ALTER TABLE "project_property" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "project_number" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "project_note" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `ALTER TABLE "project_agency_response" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "parcel_fiscal" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `ALTER TABLE "parcel_evaluation" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "parcel" ALTER COLUMN "pid" SET NOT NULL`); + await queryRunner.query(`ALTER TABLE "parcel" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `CREATE UNIQUE INDEX "IDX_b2b62506b1c247926530b027c8" ON "parcel" ("pid", "pin") `, + ); + await queryRunner.query( + `ALTER TABLE "notification_queue" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "notification_template" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "project" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "project_risk" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "tier_level" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "workflow" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "project_status" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "building_fiscal" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "fiscal_key" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `ALTER TABLE "building_evaluation" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "evaluation_key" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "building" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "property_type" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `ALTER TABLE "property_classification" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "building_predominate_use" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "building_occupant_type" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query( + `ALTER TABLE "building_construction_type" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "agency" ALTER COLUMN "id" DROP DEFAULT`); + await queryRunner.query(`DROP SEQUENCE "agency_id_seq"`); + await queryRunner.query(`ALTER TABLE "agency" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `CREATE INDEX "IDX_648ccf166d25060756fd37857a" ON "agency" ("id", "name", "is_disabled", "sort_order", "parent_id") `, + ); + await queryRunner.query(`ALTER TABLE "user" ALTER COLUMN "id" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "user" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "role" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `ALTER TABLE "administrative_area" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "province" ALTER COLUMN "updated_on" DROP DEFAULT`); + await queryRunner.query( + `ALTER TABLE "regional_district" ALTER COLUMN "updated_on" DROP DEFAULT`, + ); + await queryRunner.query(`ALTER TABLE "building" DROP COLUMN "pin"`); + await queryRunner.query(`ALTER TABLE "building" DROP COLUMN "pid"`); + await queryRunner.query( + `CREATE TABLE "parcel_building" ("created_by_id" uuid NOT NULL, "created_on" TIMESTAMP NOT NULL DEFAULT now(), "updated_by_id" uuid, "updated_on" TIMESTAMP, "parcel_id" integer NOT NULL, "building_id" integer NOT NULL, CONSTRAINT "PK_f35c567f4d2df1c5528181e59e7" PRIMARY KEY ("parcel_id", "building_id"))`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_ab453e13084937c4f6bc93981d" ON "parcel_building" ("created_by_id") `, + ); + await queryRunner.query( + `CREATE INDEX "IDX_5430f31be522f210ae8ceb5d8e" ON "parcel_building" ("updated_by_id") `, + ); + await queryRunner.query( + `ALTER TABLE "parcel_building" ADD CONSTRAINT "FK_ab453e13084937c4f6bc93981d7" FOREIGN KEY ("created_by_id") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "parcel_building" ADD CONSTRAINT "FK_5430f31be522f210ae8ceb5d8ee" FOREIGN KEY ("updated_by_id") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "parcel_building" ADD CONSTRAINT "FK_4082fbe646622fd7b9060dedc0a" FOREIGN KEY ("parcel_id") REFERENCES "parcel"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "parcel_building" ADD CONSTRAINT "FK_470344017e1808fe014bb928ceb" FOREIGN KEY ("building_id") REFERENCES "building"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + } +} diff --git a/express-api/src/typeorm/Migrations/1710191053571-AddBuildingRelationsView.ts b/express-api/src/typeorm/Migrations/1710191053571-AddBuildingRelationsView.ts new file mode 100644 index 0000000000..78612ab22c --- /dev/null +++ b/express-api/src/typeorm/Migrations/1710191053571-AddBuildingRelationsView.ts @@ -0,0 +1,31 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddBuildingRelationsView1710191053571 implements MigrationInterface { + name = 'AddBuildingRelationsView1710191053571'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE MATERIALIZED VIEW "building_relations" AS + SELECT b.id AS "building_id", b.pid, b.pin, p.id as "parcel_id" + FROM building b + LEFT OUTER JOIN parcel p + ON b.pid = p.pid OR b.pin = p.pin; + `); + await queryRunner.query( + `INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, + [ + 'public', + 'MATERIALIZED_VIEW', + 'building_relations', + 'SELECT b.id AS "building_id", b.pid, b.pin, p.id as "parcel_id"\n FROM building b\n LEFT OUTER JOIN parcel p\n ON b.pid = p.pid OR b.pin = p.pin;', + ], + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, + ['MATERIALIZED_VIEW', 'building_relations', 'public'], + ); + await queryRunner.query(`DROP MATERIALIZED VIEW "building_relations"`); + } +} diff --git a/express-api/src/typeorm/entitiesIndex.ts b/express-api/src/typeorm/entitiesIndex.ts index df255d61b0..6fa300165a 100644 --- a/express-api/src/typeorm/entitiesIndex.ts +++ b/express-api/src/typeorm/entitiesIndex.ts @@ -11,7 +11,6 @@ import { FiscalKey } from '@/typeorm/Entities/FiscalKey'; import { NotificationQueue } from '@/typeorm/Entities/NotificationQueue'; import { NotificationTemplate } from '@/typeorm/Entities/NotificationTemplate'; import { Parcel } from '@/typeorm/Entities/Parcel'; -import { ParcelBuilding } from '@/typeorm/Entities/ParcelBuilding'; import { ParcelEvaluation } from '@/typeorm/Entities/ParcelEvaluation'; import { ParcelFiscal } from '@/typeorm/Entities/ParcelFiscal'; import { Project } from '@/typeorm/Entities/Project'; @@ -39,6 +38,9 @@ import { TierLevel } from '@/typeorm/Entities/TierLevel'; import { User } from '@/typeorm/Entities/User'; import { Workflow } from '@/typeorm/Entities/Workflow'; import { WorkflowProjectStatus } from '@/typeorm/Entities/WorkflowProjectStatus'; +import { BuildingRelations } from '@/typeorm/Entities/views/PropertyView'; + +const views = [BuildingRelations]; export default [ AdministrativeArea, @@ -54,7 +56,6 @@ export default [ NotificationQueue, NotificationTemplate, Parcel, - ParcelBuilding, ParcelEvaluation, ParcelFiscal, Project, @@ -82,4 +83,5 @@ export default [ User, Workflow, WorkflowProjectStatus, + ...views, ]; diff --git a/express-api/tests/integration/parcels/parcels.test.ts b/express-api/tests/integration/parcels/parcels.test.ts index ad25165953..6d481abc93 100644 --- a/express-api/tests/integration/parcels/parcels.test.ts +++ b/express-api/tests/integration/parcels/parcels.test.ts @@ -1,57 +1,40 @@ import supertest from 'supertest'; import app from '@/express'; import { faker } from '@faker-js/faker'; -import { IParcel } from '@/controllers/parcels/IParcel'; -import { Point } from 'typeorm'; import { UUID } from 'crypto'; +import { Parcel } from '@/typeorm/Entities/Parcel'; +import { GeoPoint } from '@/typeorm/Entities/abstractEntities/Property'; const request = supertest(app); const API_PATH = '/v2/properties/parcels'; -const mockPoint: Point = { - type: 'Point', - coordinates: [1.23, 4.56], +const mockPoint: GeoPoint = { + x: 1.23, + y: 4.56, }; -const mockParcel: IParcel = { - createdOn: faker.date.anytime().toLocaleString(), - updatedOn: faker.date.anytime().toLocaleString(), - updatedById: faker.string.uuid() as UUID, - createdById: faker.string.uuid() as UUID, - id: faker.number.int(), - propertyTypeId: 0, - propertyType: 'Land', - addressId: 1, - location: mockPoint, - projectNumbers: [], - projectWorkflow: 'Submit Surplus Property Process Project', - projectStatus: 'Draft', - name: faker.location.cardinalDirection() + faker.location.city(), - description: faker.string.alpha(), - classificationId: 0, - classification: 'Core Operational', - encumbranceReason: '', - agencyId: 0, - subAgency: 'BCHY', - agency: 'EMPR', - subAgencyFullName: 'BC Hydro', - agencyFullName: 'Energy, Mines & Petroleum Resources', - address: undefined, - latitude: faker.location.latitude(), - longitude: faker.location.longitude(), - isSensitive: false, - isVisibleToOtherAgencies: false, - pid: faker.string.numeric(), - pin: faker.number.int(), - landArea: 0, - landLegalDescription: faker.string.alpha(), - zoning: '', - zoningPotential: '', - evaluations: [], - fiscals: [], - buildings: [], - parcels: [], - subdivisions: [], +const mockParcel: Partial = { + CreatedOn: faker.date.anytime(), + UpdatedOn: faker.date.anytime(), + UpdatedById: faker.string.uuid() as UUID, + CreatedById: faker.string.uuid() as UUID, + Id: faker.number.int(), + PropertyTypeId: 0, + Location: mockPoint, + ProjectNumbers: '', + Name: faker.location.cardinalDirection() + faker.location.city(), + Description: faker.string.alpha(), + ClassificationId: 0, + AgencyId: 0, + IsSensitive: false, + IsVisibleToOtherAgencies: false, + PID: faker.number.int(), + PIN: faker.number.int(), + LandArea: 0, + LandLegalDescription: faker.string.alpha(), + Zoning: '', + ZoningPotential: '', + ParentParcelId: 1, }; describe('INTEGRATION - Parcels', () => { diff --git a/express-api/tests/testUtils/factories.ts b/express-api/tests/testUtils/factories.ts index a2763b6568..559dd415ee 100644 --- a/express-api/tests/testUtils/factories.ts +++ b/express-api/tests/testUtils/factories.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { AccessRequest } from '@/typeorm/Entities/AccessRequest'; import { Agency } from '@/typeorm/Entities/Agency'; import { User, UserStatus } from '@/typeorm/Entities/User'; import { faker } from '@faker-js/faker'; @@ -109,30 +108,6 @@ export const produceUser = (): User => { }; }; -export const produceRequest = (): AccessRequest => { - const agency = produceAgency(); - const role = produceRole(); - const user = produceUser(); - const request: AccessRequest = { - Id: faker.number.int(), - UserId: user.Id, - User: user, - Note: 'test', - Status: 0, - RoleId: role.Id, - Role: role, - Agency: agency, - AgencyId: agency.Id, - CreatedById: undefined, - CreatedBy: undefined, - CreatedOn: faker.date.anytime(), - UpdatedById: undefined, - UpdatedBy: undefined, - UpdatedOn: faker.date.anytime(), - }; - return request; -}; - export const produceAgency = (code?: string): Agency => { const agency: Agency = { Id: faker.number.int({ max: 10 }), @@ -228,5 +203,7 @@ export const produceParcel = (): Parcel => { CreatedBy: undefined, UpdatedById: undefined, UpdatedBy: undefined, + Fiscals: [], + Evaluations: [], }; }; diff --git a/express-api/tests/unit/controllers/buildings/buildingsController.test.ts b/express-api/tests/unit/controllers/buildings/buildingsController.test.ts index b3ce419ede..5a8f3a4069 100644 --- a/express-api/tests/unit/controllers/buildings/buildingsController.test.ts +++ b/express-api/tests/unit/controllers/buildings/buildingsController.test.ts @@ -1,52 +1,41 @@ -import { IBuilding } from '@/controllers/buildings/IBuilding'; import { faker } from '@faker-js/faker'; import { UUID } from 'crypto'; import controllers from '@/controllers'; import { Request, Response } from 'express'; import { MockReq, MockRes, getRequestHandlerMocks } from '../../../testUtils/factories'; +import { Building } from '@/typeorm/Entities/Building'; describe('UNIT - Buildings', () => { - const mockBuilding: IBuilding = { - createdOn: faker.date.anytime().toLocaleString(), - updatedOn: faker.date.anytime().toLocaleString(), - updatedById: faker.string.uuid() as UUID, - createdById: faker.string.uuid() as UUID, - rowVersion: faker.number.binary(), - id: faker.number.int(), - propertyTypeId: 0, - projectNumbers: [], - projectWorkflow: 'Submit Surplus Property Process Project', - projectStatus: 'Draft', - name: faker.location.cardinalDirection() + faker.location.city(), - description: faker.string.alpha(), - classificationId: 0, - classification: 'Core Operational', - encumbranceReason: '', - agencyId: 0, - subAgency: 'BCHY', - agency: 'EMPR', - subAgencyFullName: 'BC Hydro', - agencyFullName: 'Energy, Mines & Petroleum Resources', - address: undefined, - latitude: faker.location.latitude(), - longitude: faker.location.longitude(), - isSensitive: false, - isVisibleToOtherAgencies: false, - evaluations: [], - fiscals: [], - parcelId: faker.number.int(), - buildingConstructionTypeId: 0, - buildingConstructionType: '', - buildingFloorCount: 0, - buildingPredominateUseId: 0, - buildingPredominateUse: '', - buildingOccupantTypeId: 0, - buildingOccupantType: '', - leaseExpiry: '', - occupantName: '', - transferLeaseOnSale: false, - buildingTenancy: '', - rentableArea: 0, + const mockBuilding: Partial = { + CreatedOn: faker.date.anytime(), + UpdatedOn: faker.date.anytime(), + UpdatedById: faker.string.uuid() as UUID, + CreatedById: faker.string.uuid() as UUID, + Id: faker.number.int(), + PropertyTypeId: 0, + Name: faker.location.cardinalDirection() + faker.location.city(), + Description: faker.string.alpha(), + ClassificationId: 0, + EncumbranceReason: '', + AgencyId: 0, + Address1: '742 Evergreen Terrace', + Postal: 'V8A 3E8', + IsSensitive: false, + IsVisibleToOtherAgencies: false, + Evaluations: [], + Fiscals: [], + PID: faker.number.int(), + PIN: faker.number.int(), + BuildingConstructionTypeId: 0, + BuildingFloorCount: 0, + BuildingPredominateUseId: 0, + BuildingOccupantTypeId: 0, + LeaseExpiry: faker.date.anytime(), + OccupantName: '', + TransferLeaseOnSale: false, + BuildingTenancy: '', + BuildingTenancyUpdatedOn: faker.date.anytime(), + RentableArea: 0, }; let mockRequest: Request & MockReq, mockResponse: Response & MockRes; diff --git a/express-api/tests/unit/controllers/parcels/parcelsController.test.ts b/express-api/tests/unit/controllers/parcels/parcelsController.test.ts index d684b43e1c..43fa1fedc5 100644 --- a/express-api/tests/unit/controllers/parcels/parcelsController.test.ts +++ b/express-api/tests/unit/controllers/parcels/parcelsController.test.ts @@ -1,55 +1,41 @@ -import { IParcel } from '@/controllers/parcels/IParcel'; import { faker } from '@faker-js/faker'; import { UUID } from 'crypto'; import controllers from '@/controllers'; import { Request, Response } from 'express'; import { MockReq, MockRes, getRequestHandlerMocks } from '../../../testUtils/factories'; -import { Point } from 'typeorm'; +import { Parcel } from '@/typeorm/Entities/Parcel'; +import { GeoPoint } from '@/typeorm/Entities/abstractEntities/Property'; -const mockPoint: Point = { - type: 'Point', - coordinates: [1.23, 4.56], +const mockPoint: GeoPoint = { + x: 1.23, + y: 4.56, }; describe('UNIT - Parcels', () => { - const mockParcel: IParcel = { - createdOn: faker.date.anytime().toLocaleString(), - updatedOn: faker.date.anytime().toLocaleString(), - updatedById: faker.string.uuid() as UUID, - createdById: faker.string.uuid() as UUID, - id: faker.number.int(), - propertyTypeId: 0, - propertyType: 'Land', - addressId: 1, - location: mockPoint, - projectNumbers: [], - projectWorkflow: 'Submit Surplus Property Process Project', - projectStatus: 'Draft', - name: faker.location.cardinalDirection() + faker.location.city(), - description: faker.string.alpha(), - classificationId: 0, - classification: 'Core Operational', - encumbranceReason: '', - agencyId: 0, - subAgency: 'BCHY', - agency: 'EMPR', - subAgencyFullName: 'BC Hydro', - agencyFullName: 'Energy, Mines & Petroleum Resources', - address: undefined, - latitude: faker.location.latitude(), - longitude: faker.location.longitude(), - isSensitive: false, - isVisibleToOtherAgencies: false, - pid: faker.string.numeric(), - pin: faker.number.int(), - landArea: 0, - landLegalDescription: faker.string.alpha(), - zoning: '', - zoningPotential: '', - evaluations: [], - fiscals: [], - buildings: [], - parcels: [], - subdivisions: [], + const mockParcel: Partial = { + CreatedOn: faker.date.anytime(), + UpdatedOn: faker.date.anytime(), + UpdatedById: faker.string.uuid() as UUID, + CreatedById: faker.string.uuid() as UUID, + Id: faker.number.int(), + PropertyTypeId: 0, + Location: mockPoint, + ProjectNumbers: '', + Name: faker.location.cardinalDirection() + faker.location.city(), + Description: faker.string.alpha(), + ClassificationId: 0, + AgencyId: 0, + IsSensitive: false, + IsVisibleToOtherAgencies: false, + PID: faker.number.int(), + PIN: faker.number.int(), + LandArea: 0, + LandLegalDescription: faker.string.alpha(), + Zoning: '', + ZoningPotential: '', + ParentParcelId: 1, + AdministrativeAreaId: 2, + Address1: '742 Evergreen Terrace', + Postal: 'V8A 3E8', }; let mockRequest: Request & MockReq, mockResponse: Response & MockRes; diff --git a/express-api/tests/unit/controllers/users/usersController.test.ts b/express-api/tests/unit/controllers/users/usersController.test.ts index 30cb073093..35f85e9044 100644 --- a/express-api/tests/unit/controllers/users/usersController.test.ts +++ b/express-api/tests/unit/controllers/users/usersController.test.ts @@ -6,19 +6,13 @@ import { MockRes, getRequestHandlerMocks, produceKeycloak, - produceRequest, produceUser, } from '../../../testUtils/factories'; -import { IKeycloakUser } from '@/services/keycloak/IKeycloakUser'; -import { AccessRequest } from '@/typeorm/Entities/AccessRequest'; import { faker } from '@faker-js/faker'; import { KeycloakIdirUser, KeycloakUser } from '@bcgov/citz-imb-kc-express'; import { ErrorWithCode } from '@/utilities/customErrors/ErrorWithCode'; const _activateUser = jest.fn(); -const _getAccessRequest = jest.fn().mockImplementation(() => produceRequest()); -const _getAccessRequestById = jest.fn().mockImplementation(() => produceRequest()); -const _deleteAccessRequest = jest.fn().mockImplementation((req) => req); const _addKeycloakUserOnHold = jest .fn() .mockImplementation((kc: KeycloakUser, agencyId: string, position: string, note: string) => ({ @@ -37,12 +31,8 @@ const _normalizeKeycloakUser = jest.fn().mockImplementation(() => {}); jest.mock('@/services/users/usersServices', () => ({ activateUser: () => _activateUser(), - getAccessRequest: () => _getAccessRequest(), - getAccessRequestById: () => _getAccessRequestById(), - deleteAccessRequest: (request: AccessRequest) => _deleteAccessRequest(request), addKeycloakUserOnHold: (kc: KeycloakUser, agencyId: string, position: string, note: string) => _addKeycloakUserOnHold(kc, agencyId, position, note), - updateAccessRequest: (request: AccessRequest, _kc: KeycloakUser) => _updateAccessRequest(request), getAgencies: () => _getAgencies(), getAdministrators: () => _getAdministrators(), getUser: (guid: string) => _getUser(guid), diff --git a/express-api/tests/unit/services/users/usersServices.test.ts b/express-api/tests/unit/services/users/usersServices.test.ts index e46a7f63a5..c494b220ce 100644 --- a/express-api/tests/unit/services/users/usersServices.test.ts +++ b/express-api/tests/unit/services/users/usersServices.test.ts @@ -1,12 +1,11 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { AppDataSource } from '@/appDataSource'; import userServices from '@/services/users/usersServices'; -import { AccessRequest } from '@/typeorm/Entities/AccessRequest'; import { Agency } from '@/typeorm/Entities/Agency'; import { User } from '@/typeorm/Entities/User'; import { KeycloakUser } from '@bcgov/citz-imb-kc-express'; import { faker } from '@faker-js/faker'; -import { produceAgency, produceRequest, produceUser } from 'tests/testUtils/factories'; +import { produceAgency, produceUser } from 'tests/testUtils/factories'; const _usersFindOneBy = jest .spyOn(AppDataSource.getRepository(User), 'findOneBy') @@ -20,23 +19,6 @@ const _usersInsert = jest .spyOn(AppDataSource.getRepository(User), 'insert') .mockImplementation(async (_where) => ({ raw: {}, generatedMaps: [], identifiers: [] })); -const _requestInsert = jest - .spyOn(AppDataSource.getRepository(AccessRequest), 'insert') - .mockImplementation(async (req) => ({ raw: {}, generatedMaps: [{ ...req }], identifiers: [] })); - -const _requestUpdate = jest - .spyOn(AppDataSource.getRepository(AccessRequest), 'update') - .mockImplementation(async (id, req) => ({ - raw: {}, - generatedMaps: [req], - identifiers: [], - affected: 1, - })); - -const _requestRemove = jest - .spyOn(AppDataSource.getRepository(AccessRequest), 'remove') - .mockImplementation(async (req) => req); -const _requestQueryGetOne = jest.fn().mockImplementation(() => produceRequest()); // eslint-disable-next-line @typescript-eslint/no-explicit-any const _requestsCreateQueryBuilder: any = { select: () => _requestsCreateQueryBuilder, @@ -44,13 +26,8 @@ const _requestsCreateQueryBuilder: any = { where: () => _requestsCreateQueryBuilder, andWhere: () => _requestsCreateQueryBuilder, orderBy: () => _requestsCreateQueryBuilder, - getOne: () => _requestQueryGetOne(), }; -jest - .spyOn(AppDataSource.getRepository(AccessRequest), 'createQueryBuilder') - .mockImplementation(() => _requestsCreateQueryBuilder); - jest .spyOn(AppDataSource.getRepository(User), 'find') .mockImplementation(async () => [produceUser()]); @@ -63,14 +40,6 @@ jest .spyOn(AppDataSource.getRepository(User), 'findOneOrFail') .mockImplementation(async () => produceUser()); -jest - .spyOn(AppDataSource.getRepository(AccessRequest), 'findOne') - .mockImplementation(async () => produceRequest()); - -jest - .spyOn(AppDataSource.getRepository(AccessRequest), 'findOneOrFail') - .mockImplementation(async () => produceRequest()); - jest .spyOn(AppDataSource.getRepository(Agency), 'findOne') .mockImplementation(async () => produceAgency());