feat(db): add property.marked_for_deletion soft-delete flag

Add a NOT NULL DEFAULT false `marked_for_deletion` boolean to the
`property` table. Hard deletes are expensive (cascading child rows,
indexes), so a row is flagged here and a separate cron job performs the
physical delete later; reads can filter on the flag in the interim.

A constant default makes this a metadata-only ALTER on Postgres 11+ (no
table rewrite); existing rows backfill to false.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jun-te Kim 2026-06-25 12:18:32 +00:00
parent 4b0133ac5c
commit 752ffe1935
4 changed files with 11519 additions and 0 deletions

View file

@ -0,0 +1 @@
ALTER TABLE "property" ADD COLUMN "marked_for_deletion" boolean DEFAULT false NOT NULL;

File diff suppressed because it is too large Load diff

View file

@ -1702,6 +1702,13 @@
"when": 1782313328071,
"tag": "0243_oval_pestilence",
"breakpoints": true
},
{
"idx": 244,
"version": "7",
"when": 1782387040698,
"tag": "0244_unknown_puck",
"breakpoints": true
}
]
}

View file

@ -155,6 +155,12 @@ export const property = pgTable(
// lodged data
lodgedSapPoints: real("lodged_sap_points"),
lodgedEpcRating: epcEnum("lodged_epc_rating"),
// Soft-delete marker. Hard deletes on `property` are expensive (cascading
// child rows, indexes), so callers flag a row here and reads filter it out;
// a separate cron job performs the physical delete later. NOT NULL so reads
// never deal with a tri-state — every live row is explicitly `false`.
markedForDeletion: boolean("marked_for_deletion").notNull().default(false),
},
(table) => [
uniqueIndex("uq_property_portfolio_uprn")