feat(berths): add per-berth pricing + last_imported_at columns

Adds the 5 pricing columns surfaced by the per-berth PDFs (Phase 6b
will populate them via the OCR parser) and the last_imported_at marker
the NocoDB import script (Phase 0c) uses to detect human edits and
skip overwriting them.

- weekly_rate_high_usd / weekly_rate_low_usd
- daily_rate_high_usd  / daily_rate_low_usd
- pricing_valid_until (date) - drives the "stale pricing" chip on
  the berth detail page when older than today
- last_imported_at - compared against updated_at so re-running the
  import preserves CRM-side overrides

tenure_type comment widens to include 'fee_simple' and 'strata_lot'
to match the per-berth PDF tenure model; the column is plain text
so no DB-level enum change is required.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt Ciaccio
2026-05-05 02:00:46 +02:00
parent 05be89ec6f
commit 61e2fbb2db
4 changed files with 10703 additions and 1 deletions

View File

@@ -0,0 +1,6 @@
ALTER TABLE "berths" ADD COLUMN "weekly_rate_high_usd" numeric;--> statement-breakpoint
ALTER TABLE "berths" ADD COLUMN "weekly_rate_low_usd" numeric;--> statement-breakpoint
ALTER TABLE "berths" ADD COLUMN "daily_rate_high_usd" numeric;--> statement-breakpoint
ALTER TABLE "berths" ADD COLUMN "daily_rate_low_usd" numeric;--> statement-breakpoint
ALTER TABLE "berths" ADD COLUMN "pricing_valid_until" date;--> statement-breakpoint
ALTER TABLE "berths" ADD COLUMN "last_imported_at" timestamp with time zone;

File diff suppressed because it is too large Load Diff

View File

@@ -176,6 +176,13 @@
"when": 1777938954111,
"tag": "0024_normalize_mooring_numbers",
"breakpoints": true
},
{
"idx": 25,
"version": "7",
"when": 1777939212954,
"tag": "0025_berth_pricing_columns",
"breakpoints": true
}
]
}

View File

@@ -50,9 +50,19 @@ export const berths = pgTable(
access: text('access'),
price: numeric('price'),
priceCurrency: text('price_currency').notNull().default('USD'),
// Lease/rental rates surfaced by the per-berth PDFs (Phase 6b). Null
// until reps upload PDFs; rendered on the berth detail page with a
// "Pricing data may be stale" chip when pricing_valid_until < today().
weeklyRateHighUsd: numeric('weekly_rate_high_usd'),
weeklyRateLowUsd: numeric('weekly_rate_low_usd'),
dailyRateHighUsd: numeric('daily_rate_high_usd'),
dailyRateLowUsd: numeric('daily_rate_low_usd'),
pricingValidUntil: date('pricing_valid_until'),
bowFacing: text('bow_facing'),
berthApproved: boolean('berth_approved').default(false),
tenureType: text('tenure_type').notNull().default('permanent'), // permanent, fixed_term
// permanent, fixed_term, fee_simple, strata_lot (the last two map to
// the Fee Simple / Strata Lot tenures shown in the per-berth PDFs).
tenureType: text('tenure_type').notNull().default('permanent'),
tenureYears: integer('tenure_years'),
tenureStartDate: date('tenure_start_date'),
tenureEndDate: date('tenure_end_date'),
@@ -62,6 +72,10 @@ export const berths = pgTable(
// Optional override flag carried over from NocoDB ("auto" or null in legacy data).
// Reserved for future "manual override" semantics; not surfaced in the UI today.
statusOverrideMode: text('status_override_mode'),
// Set by scripts/import-berths-from-nocodb.ts. The import compares this
// against updated_at to detect human edits made after the last import,
// so re-running the import doesn't clobber CRM-side overrides.
lastImportedAt: timestamp('last_imported_at', { withTimezone: true }),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
},