offer_statusCREATE TYPE "public"."offer_status" AS ENUM(
'PENDING',
'ACCEPTED',
'REJECTED',
'COUNTERED'
);
offers| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | text | NOT NULL | nanoid() | Primary key |
seller_account_id | text | NOT NULL | — | FK to account.id (seller) |
buyer_account_id | text | NOT NULL | — | FK to account.id (buyer) |
campaign_description | text | NOT NULL | — | Free-text campaign description |
campaign_types | text[] | NOT NULL | '{}' | Chip selections (e.g. Radio ads, Billboards) |
script_text | text | NULL | — | Radio ad script (if applicable) |
usage_types | text[] | NOT NULL | '{}' | Where content will be used |
custom_usage | text | NULL | — | Free-text custom usage |
wants_sharing | boolean | NULL | — | Whether buyer wants social sharing bundle |
sharing_description | text | NULL | — | Sharing bundle details |
offer_amount_cent | integer | NOT NULL | — | Price offered in cents |
counter_amount_cent | integer | NULL | — | Seller's counter price (when COUNTERED) |
counter_note | text | NULL | — | Seller's counter message |
status | offer_status | NOT NULL | 'PENDING' | Current status |
deleted_at | timestamptz | NULL | — | Soft delete |
created_at | timestamptz | NOT NULL | now() | Creation time |
updated_at | timestamptz | NOT NULL | now() | Last update |
offers_seller_idx on seller_account_idoffers_buyer_idx on buyer_account_idoffers_status_idx on statusseller_account_id → account.idbuyer_account_id → account.idpackages/db/drizzle/0016_moaning_risque.sql — Initial offers tablepackages/db/drizzle/0017_offers_buyer_account.sql — Replace buyer_email/buyer_name with buyer_account_idGenerate new migrations with:
cd packages/db && npx drizzle-kit generate
Apply migrations with:
cd packages/db && pnpm db:migrate
(Do not use db:push per project rules.)