Two bugs in the catch-up migration that only manifest with real production data:
1. Company (4520 rows): uid was added as TEXT NOT NULL DEFAULT '' causing
all existing rows to get uid='' which makes the PRIMARY KEY constraint
fail with 'could not create unique index, Key (uid)=() is duplicated'.
Fix: add uid as nullable, UPDATE uid = id (copies the existing CUID text
PK into uid), then SET NOT NULL, then swap PK. Also populate the new
integer id column from cw_CompanyId (which is fully populated in prod).
2. UnifiSite (180 rows): old approach just dropped the text companyId and
added a null integer column, destroying all company relationships.
Fix: add companyId_int, UPDATE via JOIN on Company.uid (= old Company.id
text), drop old text column, rename integer column.
Also fix the P3009 handler in migrate-entrypoint.sh: Prisma may emit ANSI
color codes even without a TTY, wrapping backticks in escape sequences and
breaking the regex match. Fix: strip ANSI codes with sed before extracting
the migration name. Also simplify the regex from a rigid format match to a
simpler backtick-content grep.
Production DB manually unblocked (migrate resolve --rolled-back) so the
next deploy will cleanly apply the corrected migration.
All schema changes that were applied via 'prisma db push' over the past
several months were never captured in migration files. When the postgres
pod restarted just before the migration job ran, the database was rebuilt
from the 15 existing migrations -- creating an old schema that was missing
~20 tables and significant structural changes to User, Opportunity,
CatalogItem, and Company.
This migration bridges the gap idempotently:
- New enums: PhoneType, FaxType, BillingMethod, BillingType, GenderType,
USState, Country, OpportunityInterest
- User: add firstName/lastName/title/active/hidden/cwMemberId/updatedBy;
drop emailVerified/name; make userId nullable
- CatalogItem: TEXT id → INTEGER id + TEXT uid PK; restructure FK columns
- Company: TEXT id → INTEGER id + TEXT uid PK; drop old CW columns; add
dateDeleted/deleteFlag/phone/taxExempt/taxId/website/enteredById
- Opportunity: TEXT id → INTEGER id + TEXT uid PK; drop ~25 flat CW
columns; add typeId/statusId/contactId/siteId/locationId/departmentId/
closedById/primarySalesRepId/secondarySalesRepId/eneteredBy/updatedBy/
oppNarrative/taxCodeId/interest; drop cwDateEntered
- UnifiSite: companyId TEXT → INTEGER
- 20+ new tables: CorporateLocation, InternalDepartment, CompanyAddress,
Contact, CatalogItemType, CatalogCategory, CatalogSubcategory,
CatalogManufacturer, Warehouse, WarehouseBin, ProductInventory,
MinimumStockByWarehouse, ProductData, ServiceTicket, ServiceTicketNote,
ServiceTicketType, ServiceTicketBoard, ServiceTicketLocation,
ServiceTicketSource, ServiceTicketImpact, ServiceTicketPriority,
ServiceTicketServerity, ServiceTicketFinalData, OpportunityType,
OpportunityStatus, ScheduleStatus, ScheduleType, ScheduleSpan,
Schedule, TaxCode
Verified: all 16 migrations apply cleanly on a fresh DB and produce zero
schema drift (prisma migrate diff outputs '-- This is an empty migration.')
Fixes P2022 ColumnNotFound errors on login and all model queries.