From e3395b8139338c217901c3280654a5d63c894569 Mon Sep 17 00:00:00 2001 From: Eric McGarry <46828798+mcgarrye@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:04:38 -0400 Subject: [PATCH] feat: record of listing copy (#4375) * feat: add copyOf column to db and export * feat: address questions --- .../18_copy_of_reference/migration.sql | 5 + api/prisma/schema.prisma | 12 +- .../services/listing-csv-export.service.ts | 15 +++ api/src/services/listing.service.ts | 31 +++-- api/test/integration/listing.e2e-spec.ts | 8 ++ .../unit/services/listing.service.spec.ts | 123 ++++++++++++++++++ 6 files changed, 179 insertions(+), 15 deletions(-) create mode 100644 api/prisma/migrations/18_copy_of_reference/migration.sql diff --git a/api/prisma/migrations/18_copy_of_reference/migration.sql b/api/prisma/migrations/18_copy_of_reference/migration.sql new file mode 100644 index 0000000000..1c89183878 --- /dev/null +++ b/api/prisma/migrations/18_copy_of_reference/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "listings" ADD COLUMN "copy_of_id" UUID; + +-- AddForeignKey +ALTER TABLE "listings" ADD CONSTRAINT "listings_copy_of_id_fkey" FOREIGN KEY ("copy_of_id") REFERENCES "listings"("id") ON DELETE SET NULL ON UPDATE NO ACTION; diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index d03b7641b7..386002a966 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -146,8 +146,8 @@ model ApplicationFlaggedSet { listings Listings @relation(fields: [listingId], references: [id], onDelete: Cascade, onUpdate: NoAction) applications Applications[] - @@index([listingId]) @@unique([ruleKey, listingId]) + @@index([listingId]) @@map("application_flagged_set") } @@ -543,7 +543,7 @@ model Listings { closedAt DateTime? @map("closed_at") @db.Timestamptz(6) afsLastRunAt DateTime? @default(dbgenerated("'1970-01-01 00:00:00-07'::timestamp with time zone")) @map("afs_last_run_at") @db.Timestamptz(6) lastApplicationUpdateAt DateTime? @default(dbgenerated("'1970-01-01 00:00:00-07'::timestamp with time zone")) @map("last_application_update_at") @db.Timestamptz(6) - lotteryLastPublishedAt DateTime? @map("lottery_last_published_at") @db.Timestamptz(6) + lotteryLastPublishedAt DateTime? @map("lottery_last_published_at") @db.Timestamptz(6) lotteryLastRunAt DateTime? @map("lottery_last_run_at") @db.Timestamptz(6) lotteryStatus LotteryStatusEnum? @map("lottery_status") buildingAddressId String? @map("building_address_id") @db.Uuid @@ -551,6 +551,7 @@ model Listings { applicationDropOffAddressId String? @map("application_drop_off_address_id") @db.Uuid applicationMailingAddressId String? @map("application_mailing_address_id") @db.Uuid buildingSelectionCriteriaFileId String? @map("building_selection_criteria_file_id") @db.Uuid + copyOfId String? @map("copy_of_id") @db.Uuid jurisdictionId String? @map("jurisdiction_id") @db.Uuid leasingAgentAddressId String? @map("leasing_agent_address_id") @db.Uuid reservedCommunityTypeId String? @map("reserved_community_type_id") @db.Uuid @@ -606,6 +607,9 @@ model Listings { requestedChangesUser UserAccounts? @relation("requested_changes_user", fields: [requestedChangesUserId], references: [id], onDelete: NoAction, onUpdate: NoAction) applicationLotteryPositions ApplicationLotteryPositions[] applicationLotteryTotals ApplicationLotteryTotal[] + copyOf Listings? @relation("copy_of", fields: [copyOfId], references: [id]) + Listings Listings[] @relation("copy_of") + @@index([jurisdictionId]) @@map("listings") } @@ -931,8 +935,8 @@ model ScriptRuns { view ApplicationFlaggedSetPossibilities { key String - listingId String @map("listing_id") @db.Uuid - applicationId String @map("application_id") @db.Uuid + listingId String @map("listing_id") @db.Uuid + applicationId String @map("application_id") @db.Uuid type String @@id([key, applicationId]) diff --git a/api/src/services/listing-csv-export.service.ts b/api/src/services/listing-csv-export.service.ts index f5f08ac9ad..447ff368e7 100644 --- a/api/src/services/listing-csv-export.service.ts +++ b/api/src/services/listing-csv-export.service.ts @@ -37,6 +37,11 @@ import { ListingMultiselectQuestion } from '../dtos/listings/listing-multiselect views.csv = { ...views.details, + copyOf: { + select: { + id: true, + }, + }, userAccounts: true, }; @@ -348,6 +353,16 @@ export class ListingCsvExporterService implements CsvExporterServiceInterface { format: (val: string): string => formatLocalDate(val, this.dateFormat, this.timeZone), }, + { + path: 'copyOf', + label: 'Copy or Original', + format: (val: Listing): string => (val ? 'Copy' : 'Original'), + }, + { + path: 'copyOfId', + label: 'Copied From', + format: (val: string): string => val, + }, { path: 'developer', label: 'Developer', diff --git a/api/src/services/listing.service.ts b/api/src/services/listing.service.ts index c2c9d07c84..ebc619a5e2 100644 --- a/api/src/services/listing.service.ts +++ b/api/src/services/listing.service.ts @@ -133,12 +133,6 @@ views.details = { ...views.full, }; -views.csv = { - ...views.base, - ...views.full, - userAccounts: true, -}; - const LISTING_CRON_JOB_NAME = 'LISTING_CRON_JOB'; /* this is the service for listings @@ -645,7 +639,11 @@ export class ListingService implements OnModuleInit { /* creates a listing */ - async create(dto: ListingCreate, requestingUser: User): Promise