@foundrynorth/compass-schema 1.0.19 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +4 -3
- package/dist/schema.d.ts +2088 -47
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +183 -3
- package/dist/schema.js.map +1 -1
- package/dist/types/activity-feed.d.ts +37 -0
- package/dist/types/activity-feed.d.ts.map +1 -0
- package/dist/types/activity-feed.js +63 -0
- package/dist/types/activity-feed.js.map +1 -0
- package/package.json +2 -2
- package/src/schema.ts +297 -4
- package/src/types/activity-feed.ts +97 -0
package/dist/schema.js
CHANGED
|
@@ -86,6 +86,7 @@ import { sql } from "drizzle-orm";
|
|
|
86
86
|
import { pgTable, text, varchar, integer, jsonb, timestamp, doublePrecision, serial, numeric, uuid, date, index, boolean, pgEnum, unique, uniqueIndex, } from "drizzle-orm/pg-core";
|
|
87
87
|
import { createInsertSchema } from "drizzle-zod";
|
|
88
88
|
import { z } from "zod";
|
|
89
|
+
import { ACTIVITY_EVENT_TYPES, ACTIVITY_SEVERITIES, ACTIVITY_SOURCE_SYSTEMS, PENDING_ACTION_TYPES, } from "./types/activity-feed.js";
|
|
89
90
|
export const users = pgTable("users", {
|
|
90
91
|
id: varchar("id")
|
|
91
92
|
.primaryKey()
|
|
@@ -98,6 +99,21 @@ export const insertUserSchema = createInsertSchema(users).pick({
|
|
|
98
99
|
password: true,
|
|
99
100
|
});
|
|
100
101
|
export const avatarRequestStatusEnum = pgEnum("avatar_request_status", ["pending", "processed", "rejected"]);
|
|
102
|
+
// Activity feed enums (order activity feed + pending actions)
|
|
103
|
+
export const activityEventTypeEnum = pgEnum("activity_event_type", ACTIVITY_EVENT_TYPES);
|
|
104
|
+
export const activitySeverityEnum = pgEnum("activity_severity", ACTIVITY_SEVERITIES);
|
|
105
|
+
export const activitySourceSystemEnum = pgEnum("activity_source_system", ACTIVITY_SOURCE_SYSTEMS);
|
|
106
|
+
export const pendingActionTypeEnum = pgEnum("pending_action_type", PENDING_ACTION_TYPES);
|
|
107
|
+
export const amendmentReasonEnum = pgEnum("amendment_reason", [
|
|
108
|
+
"budget_adjustment",
|
|
109
|
+
"flight_date_change",
|
|
110
|
+
"product_swap",
|
|
111
|
+
"add_line_items",
|
|
112
|
+
"remove_line_items",
|
|
113
|
+
"rate_renegotiation",
|
|
114
|
+
"client_request",
|
|
115
|
+
"other",
|
|
116
|
+
]);
|
|
101
117
|
// Vendor enums (must be declared before clerkUsers which references them)
|
|
102
118
|
export const vendorFulfillmentStatusEnum = pgEnum("vendor_fulfillment_status", [
|
|
103
119
|
"assigned",
|
|
@@ -167,6 +183,19 @@ export const userProfiles = pgTable("user_profiles", {
|
|
|
167
183
|
photoUrl: text("photo_url"), // Profile photo (can sync from Clerk or custom upload)
|
|
168
184
|
agencyAvatarUrl: text("agency_avatar_url"), // Hand-sketched avatar for proposals (Fal.ai)
|
|
169
185
|
lastAvatarGeneratedAt: timestamp("last_avatar_generated_at"), // Rate limiting: non-admins can only generate 1/day
|
|
186
|
+
proposalPortraitRenderUrl: text("proposal_portrait_render_url"),
|
|
187
|
+
proposalPortraitCutoutUrl: text("proposal_portrait_cutout_url"),
|
|
188
|
+
proposalPortraitStatus: text("proposal_portrait_status"),
|
|
189
|
+
proposalPortraitPromptVersion: text("proposal_portrait_prompt_version"),
|
|
190
|
+
proposalPortraitSeed: integer("proposal_portrait_seed"),
|
|
191
|
+
proposalPortraitGeneratedAt: timestamp("proposal_portrait_generated_at"),
|
|
192
|
+
proposalPortraitSourcePhotoHash: text("proposal_portrait_source_photo_hash"),
|
|
193
|
+
proposalPortraitPreviewRenderUrl: text("proposal_portrait_preview_render_url"),
|
|
194
|
+
proposalPortraitPreviewCutoutUrl: text("proposal_portrait_preview_cutout_url"),
|
|
195
|
+
proposalPortraitPreviewPromptVersion: text("proposal_portrait_preview_prompt_version"),
|
|
196
|
+
proposalPortraitPreviewSeed: integer("proposal_portrait_preview_seed"),
|
|
197
|
+
proposalPortraitPreviewGeneratedAt: timestamp("proposal_portrait_preview_generated_at"),
|
|
198
|
+
proposalPortraitPreviewSourcePhotoHash: text("proposal_portrait_preview_source_photo_hash"),
|
|
170
199
|
// Active Market Preference (overrides partner default)
|
|
171
200
|
preferredMarketId: varchar("preferred_market_id"), // User's preferred market for planning
|
|
172
201
|
// Digital Business Card
|
|
@@ -195,6 +224,19 @@ export const externalTeamMembers = pgTable("external_team_members", {
|
|
|
195
224
|
title: text("title"),
|
|
196
225
|
photoUrl: text("photo_url"),
|
|
197
226
|
agencyAvatarUrl: text("agency_avatar_url"),
|
|
227
|
+
proposalPortraitRenderUrl: text("proposal_portrait_render_url"),
|
|
228
|
+
proposalPortraitCutoutUrl: text("proposal_portrait_cutout_url"),
|
|
229
|
+
proposalPortraitStatus: text("proposal_portrait_status"),
|
|
230
|
+
proposalPortraitPromptVersion: text("proposal_portrait_prompt_version"),
|
|
231
|
+
proposalPortraitSeed: integer("proposal_portrait_seed"),
|
|
232
|
+
proposalPortraitGeneratedAt: timestamp("proposal_portrait_generated_at"),
|
|
233
|
+
proposalPortraitSourcePhotoHash: text("proposal_portrait_source_photo_hash"),
|
|
234
|
+
proposalPortraitPreviewRenderUrl: text("proposal_portrait_preview_render_url"),
|
|
235
|
+
proposalPortraitPreviewCutoutUrl: text("proposal_portrait_preview_cutout_url"),
|
|
236
|
+
proposalPortraitPreviewPromptVersion: text("proposal_portrait_preview_prompt_version"),
|
|
237
|
+
proposalPortraitPreviewSeed: integer("proposal_portrait_preview_seed"),
|
|
238
|
+
proposalPortraitPreviewGeneratedAt: timestamp("proposal_portrait_preview_generated_at"),
|
|
239
|
+
proposalPortraitPreviewSourcePhotoHash: text("proposal_portrait_preview_source_photo_hash"),
|
|
198
240
|
linkedinUrl: text("linkedin_url"),
|
|
199
241
|
displayOrder: integer("display_order").default(0),
|
|
200
242
|
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
@@ -855,7 +897,7 @@ export const plans = pgTable("plans", {
|
|
|
855
897
|
selectedOptionId: varchar("selected_option_id"), // FK → plan_options.id (nullable during migration)
|
|
856
898
|
contractId: uuid("contract_id"), // FK → contracts.id (nullable — links to annual contract)
|
|
857
899
|
// Workflow mode: determines which UI sections and features are available
|
|
858
|
-
// 'research_backed' =
|
|
900
|
+
// 'research_backed' = discovery mode — creates plan, runs analysis in background
|
|
859
901
|
// 'direct_config' = configure products directly without research
|
|
860
902
|
// 'aor_pitch' = agency-of-record pitch with proposal focus
|
|
861
903
|
// 'io_entry' = direct insertion order entry from client PDF/XLSX
|
|
@@ -1414,6 +1456,7 @@ export const clerkUsers = pgTable("clerk_users", {
|
|
|
1414
1456
|
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
1415
1457
|
approvedAt: timestamp("approved_at"),
|
|
1416
1458
|
approvedBy: text("approved_by"), // Admin who approved
|
|
1459
|
+
compassVoiceWarmth: numeric("compass_voice_warmth").default("0.6"),
|
|
1417
1460
|
});
|
|
1418
1461
|
export const insertClerkUserSchema = createInsertSchema(clerkUsers).omit({
|
|
1419
1462
|
createdAt: true,
|
|
@@ -3268,6 +3311,28 @@ export const mediaOrderStatusEnum = pgEnum("media_order_status", [
|
|
|
3268
3311
|
"active",
|
|
3269
3312
|
"completed",
|
|
3270
3313
|
]);
|
|
3314
|
+
export const salesInitiatives = pgTable("sales_initiatives", {
|
|
3315
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
3316
|
+
code: varchar("code").notNull().unique(),
|
|
3317
|
+
name: varchar("name").notNull(),
|
|
3318
|
+
description: text("description"),
|
|
3319
|
+
hubspotValue: varchar("hubspot_value").notNull().unique(),
|
|
3320
|
+
displayOrder: integer("display_order").notNull().default(0),
|
|
3321
|
+
startsAt: date("starts_at"),
|
|
3322
|
+
endsAt: date("ends_at"),
|
|
3323
|
+
isActive: boolean("is_active").notNull().default(true),
|
|
3324
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
3325
|
+
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
3326
|
+
}, (table) => [
|
|
3327
|
+
index("sales_initiatives_active_idx").on(table.isActive),
|
|
3328
|
+
index("sales_initiatives_display_order_idx").on(table.displayOrder),
|
|
3329
|
+
]);
|
|
3330
|
+
export const insertSalesInitiativeSchema = createInsertSchema(salesInitiatives).omit({
|
|
3331
|
+
id: true,
|
|
3332
|
+
createdAt: true,
|
|
3333
|
+
updatedAt: true,
|
|
3334
|
+
});
|
|
3335
|
+
export const updateSalesInitiativeSchema = insertSalesInitiativeSchema.partial();
|
|
3271
3336
|
export const mediaOrders = pgTable("media_orders", {
|
|
3272
3337
|
id: varchar("id")
|
|
3273
3338
|
.primaryKey()
|
|
@@ -3281,6 +3346,7 @@ export const mediaOrders = pgTable("media_orders", {
|
|
|
3281
3346
|
hubspotDealId: text("hubspot_deal_id"),
|
|
3282
3347
|
hubspotCompanyId: text("hubspot_company_id"),
|
|
3283
3348
|
parentHubspotCompanyId: text("parent_hubspot_company_id"),
|
|
3349
|
+
initiativeCode: varchar("initiative_code"),
|
|
3284
3350
|
// Client header
|
|
3285
3351
|
clientName: text("client_name").notNull(),
|
|
3286
3352
|
clientContactName: text("client_contact_name"),
|
|
@@ -3304,6 +3370,8 @@ export const mediaOrders = pgTable("media_orders", {
|
|
|
3304
3370
|
activatedAt: timestamp("activated_at"),
|
|
3305
3371
|
completedAt: timestamp("completed_at"),
|
|
3306
3372
|
returnReason: text("return_reason"),
|
|
3373
|
+
amendmentReason: amendmentReasonEnum("amendment_reason"),
|
|
3374
|
+
amendmentNotes: text("amendment_notes"),
|
|
3307
3375
|
slaHold: boolean("sla_hold").default(false),
|
|
3308
3376
|
clientTier: text("client_tier"),
|
|
3309
3377
|
// Share link
|
|
@@ -3329,8 +3397,6 @@ export const mediaOrders = pgTable("media_orders", {
|
|
|
3329
3397
|
defaultPromoting: text("default_promoting"),
|
|
3330
3398
|
// Order-level notes
|
|
3331
3399
|
orderNotes: text("order_notes"),
|
|
3332
|
-
// Sales initiative (links to sales_initiatives table)
|
|
3333
|
-
initiativeCode: varchar("initiative_code"),
|
|
3334
3400
|
// Billing fields
|
|
3335
3401
|
navigaAdvertiserId: text("naviga_advertiser_id"),
|
|
3336
3402
|
purchaseOrderNumber: text("purchase_order_number"),
|
|
@@ -3378,6 +3444,7 @@ export const mediaOrders = pgTable("media_orders", {
|
|
|
3378
3444
|
index("media_orders_engagement_id_idx").on(table.engagementId),
|
|
3379
3445
|
index("media_orders_partner_id_idx").on(table.partnerId),
|
|
3380
3446
|
index("media_orders_hubspot_company_id_idx").on(table.hubspotCompanyId),
|
|
3447
|
+
index("media_orders_hubspot_deal_id_idx").on(table.hubspotDealId),
|
|
3381
3448
|
index("media_orders_status_idx").on(table.status),
|
|
3382
3449
|
index("media_orders_vendor_id_idx").on(table.vendorId),
|
|
3383
3450
|
index("media_orders_vendor_fulfillment_status_idx").on(table.vendorFulfillmentStatus),
|
|
@@ -3476,6 +3543,7 @@ export const mediaOrderLineItems = pgTable("media_order_line_items", {
|
|
|
3476
3543
|
// Fulfillment details (product-specific fields for HubSpot sync)
|
|
3477
3544
|
fulfillmentDetails: jsonb("fulfillment_details"),
|
|
3478
3545
|
creativeSource: varchar("creative_source"),
|
|
3546
|
+
initiativeCode: varchar("initiative_code"),
|
|
3479
3547
|
// Ad trafficking reference key (auto-generated naming convention)
|
|
3480
3548
|
trafficKey: text("traffic_key"),
|
|
3481
3549
|
// Canonical tracking fields for DSP/reporting consistency
|
|
@@ -3485,9 +3553,11 @@ export const mediaOrderLineItems = pgTable("media_order_line_items", {
|
|
|
3485
3553
|
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
3486
3554
|
}, (table) => [
|
|
3487
3555
|
index("media_order_line_items_section_id_idx").on(table.sectionId),
|
|
3556
|
+
index("media_order_line_items_sync_status_idx").on(table.syncStatus),
|
|
3488
3557
|
index("idx_line_items_parent").on(table.parentLineItemId),
|
|
3489
3558
|
index("media_order_line_items_location_id_idx").on(table.locationId),
|
|
3490
3559
|
index("media_order_line_items_tracking_key_idx").on(table.trackingKey),
|
|
3560
|
+
index("media_order_line_items_initiative_code_idx").on(table.initiativeCode),
|
|
3491
3561
|
]);
|
|
3492
3562
|
export const insertMediaOrderLineItemSchema = createInsertSchema(mediaOrderLineItems).omit({
|
|
3493
3563
|
id: true,
|
|
@@ -3625,6 +3695,7 @@ export const stribProducts = pgTable("strib_products", {
|
|
|
3625
3695
|
strengths: text("strengths").array(), // Product strengths (High CTR, Cost Effective, etc.)
|
|
3626
3696
|
kpis: text("kpis").array(), // Relevant KPIs (CPM, CTR, CVR, etc.)
|
|
3627
3697
|
descriptionLong: text("description_long"), // Long-form product description
|
|
3698
|
+
talkingPoints: text("talking_points").array(), // Top 3 sales talking points per product
|
|
3628
3699
|
disclaimer: text("disclaimer"), // Product disclaimers or fine print
|
|
3629
3700
|
minimumBudget: numeric("minimum_budget", { precision: 10, scale: 2 }), // Minimum budget required
|
|
3630
3701
|
minimumCommitmentMonths: integer("minimum_commitment_months"), // Minimum commitment period
|
|
@@ -3651,6 +3722,20 @@ export const insertStribProductSchema = createInsertSchema(stribProducts).omit({
|
|
|
3651
3722
|
updatedAt: true,
|
|
3652
3723
|
});
|
|
3653
3724
|
export const updateStribProductSchema = insertStribProductSchema.partial();
|
|
3725
|
+
export const salesInitiativeProducts = pgTable("sales_initiative_products", {
|
|
3726
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
3727
|
+
initiativeCode: varchar("initiative_code").notNull(),
|
|
3728
|
+
stribProductId: uuid("strib_product_id")
|
|
3729
|
+
.notNull()
|
|
3730
|
+
.references(() => stribProducts.id, { onDelete: "cascade" }),
|
|
3731
|
+
displayOrder: integer("display_order").notNull().default(0),
|
|
3732
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
3733
|
+
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
3734
|
+
}, (table) => [
|
|
3735
|
+
uniqueIndex("sales_initiative_products_unique_idx").on(table.initiativeCode, table.stribProductId),
|
|
3736
|
+
index("sales_initiative_products_code_idx").on(table.initiativeCode),
|
|
3737
|
+
index("sales_initiative_products_product_idx").on(table.stribProductId),
|
|
3738
|
+
]);
|
|
3654
3739
|
/**
|
|
3655
3740
|
* strib_product_rates — tier-based pricing per product.
|
|
3656
3741
|
* Different tiers depending on family: Digital uses open/advocacy/tier_1/tier_2/tier_3;
|
|
@@ -3914,6 +3999,7 @@ export const rateExceptionRequests = pgTable("rate_exception_requests", {
|
|
|
3914
3999
|
escalationHistory: jsonb("escalation_history"), // Array of {level, at, by, reason}
|
|
3915
4000
|
expiresAt: timestamp("expires_at"),
|
|
3916
4001
|
approvalScope: varchar("approval_scope").notNull().default("request"), // "request" = affects this exception only; "catalog" = also updates global product rate
|
|
4002
|
+
batchId: uuid("batch_id"), // Groups bulk rate exception requests submitted together
|
|
3917
4003
|
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
3918
4004
|
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
3919
4005
|
}, (table) => [
|
|
@@ -3921,6 +4007,8 @@ export const rateExceptionRequests = pgTable("rate_exception_requests", {
|
|
|
3921
4007
|
index("rate_exception_status_idx").on(table.status),
|
|
3922
4008
|
index("rate_exception_requester_idx").on(table.requestedByUserId),
|
|
3923
4009
|
index("rate_exception_plan_idx").on(table.planId),
|
|
4010
|
+
index("rate_exception_batch_idx").on(table.batchId),
|
|
4011
|
+
index("rate_exception_order_status_idx").on(table.mediaOrderId, table.status),
|
|
3924
4012
|
]);
|
|
3925
4013
|
// ─── Lead Time Rules ──────────────────────────────────────────────────────────
|
|
3926
4014
|
export const leadTimeRules = pgTable("lead_time_rules", {
|
|
@@ -3967,6 +4055,31 @@ export const slaConfig = pgTable("sla_config", {
|
|
|
3967
4055
|
createdAt: timestamp("created_at").defaultNow(),
|
|
3968
4056
|
updatedAt: timestamp("updated_at").defaultNow(),
|
|
3969
4057
|
});
|
|
4058
|
+
// ─── SLA Snapshots ───────────────────────────────────────────────────────────
|
|
4059
|
+
/**
|
|
4060
|
+
* sla_snapshots — Point-in-time SLA state from fn-flux evaluations.
|
|
4061
|
+
* Each row captures the hold status, deadline, milestones, and profile
|
|
4062
|
+
* for a given media order + fulfillment ticket pair.
|
|
4063
|
+
*/
|
|
4064
|
+
export const slaHoldStatusEnum = pgEnum("sla_hold_status", ["clear", "hold", "override"]);
|
|
4065
|
+
export const slaSnapshots = pgTable("sla_snapshots", {
|
|
4066
|
+
id: serial("id").primaryKey(),
|
|
4067
|
+
mediaOrderId: text("media_order_id").notNull().references(() => mediaOrders.id),
|
|
4068
|
+
ticketId: text("ticket_id").notNull(),
|
|
4069
|
+
holdStatus: slaHoldStatusEnum("hold_status").notNull().default("clear"),
|
|
4070
|
+
holdReason: text("hold_reason"),
|
|
4071
|
+
slaDays: integer("sla_days").notNull(),
|
|
4072
|
+
availableDays: numeric("available_days"),
|
|
4073
|
+
slaDeadline: timestamp("sla_deadline"),
|
|
4074
|
+
campaignStartDate: date("campaign_start_date"),
|
|
4075
|
+
milestones: jsonb("milestones"),
|
|
4076
|
+
profileName: text("profile_name"),
|
|
4077
|
+
lastUpdatedAt: timestamp("last_updated_at").defaultNow(),
|
|
4078
|
+
}, (table) => [
|
|
4079
|
+
index("sla_snapshots_media_order_id_idx").on(table.mediaOrderId),
|
|
4080
|
+
index("sla_snapshots_ticket_id_idx").on(table.ticketId),
|
|
4081
|
+
uniqueIndex("sla_snapshots_order_ticket_uniq").on(table.mediaOrderId, table.ticketId),
|
|
4082
|
+
]);
|
|
3970
4083
|
// ─── Inventory Sync Audit Trail ─────────────────────────────────────────────
|
|
3971
4084
|
/**
|
|
3972
4085
|
* inventory_sync_log — Audit trail for external inventory syncs (GAM, Sailthru, Naviga).
|
|
@@ -5966,4 +6079,71 @@ export const creativeDeliveries = pgTable("creative_deliveries", {
|
|
|
5966
6079
|
assetCount: integer("asset_count").notNull().default(0),
|
|
5967
6080
|
receivedAt: timestamp("received_at").defaultNow().notNull(),
|
|
5968
6081
|
});
|
|
6082
|
+
// ─── Order Activity Feed ────────────────────────────────────────────────────
|
|
6083
|
+
export const orderActivityFeed = pgTable("order_activity_feed", {
|
|
6084
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
6085
|
+
mediaOrderId: varchar("media_order_id")
|
|
6086
|
+
.notNull()
|
|
6087
|
+
.references(() => mediaOrders.id),
|
|
6088
|
+
lineItemId: varchar("line_item_id").references(() => mediaOrderLineItems.id),
|
|
6089
|
+
eventType: activityEventTypeEnum("event_type").notNull(),
|
|
6090
|
+
title: text("title").notNull(),
|
|
6091
|
+
detail: text("detail"),
|
|
6092
|
+
severity: activitySeverityEnum("severity").notNull(),
|
|
6093
|
+
sourceSystem: activitySourceSystemEnum("source_system").notNull(),
|
|
6094
|
+
externalId: text("external_id").notNull().unique(), // idempotency key — prevents duplicate event ingestion
|
|
6095
|
+
status: text("status"), // intentionally untyped — values vary by eventType (creative vs fulfillment vs contract)
|
|
6096
|
+
occurredAt: timestamp("occurred_at").notNull(),
|
|
6097
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
6098
|
+
metadata: jsonb("metadata").$type(),
|
|
6099
|
+
}, (table) => [
|
|
6100
|
+
index("order_activity_feed_order_occurred_idx").on(table.mediaOrderId, table.occurredAt),
|
|
6101
|
+
index("order_activity_feed_line_item_idx").on(table.lineItemId),
|
|
6102
|
+
]);
|
|
6103
|
+
// ─── Pending Actions ────────────────────────────────────────────────────────
|
|
6104
|
+
export const pendingActions = pgTable("pending_actions", {
|
|
6105
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
6106
|
+
mediaOrderId: varchar("media_order_id")
|
|
6107
|
+
.notNull()
|
|
6108
|
+
.references(() => mediaOrders.id),
|
|
6109
|
+
lineItemId: varchar("line_item_id").references(() => mediaOrderLineItems.id),
|
|
6110
|
+
actionType: pendingActionTypeEnum("action_type").notNull(),
|
|
6111
|
+
message: text("message").notNull(),
|
|
6112
|
+
activityFeedId: uuid("activity_feed_id")
|
|
6113
|
+
.notNull()
|
|
6114
|
+
.references(() => orderActivityFeed.id),
|
|
6115
|
+
resolvedAt: timestamp("resolved_at"),
|
|
6116
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
6117
|
+
}, (table) => [
|
|
6118
|
+
index("pending_actions_order_idx").on(table.mediaOrderId),
|
|
6119
|
+
index("pending_actions_unresolved_idx").on(table.mediaOrderId).where(sql `resolved_at IS NULL`),
|
|
6120
|
+
]);
|
|
6121
|
+
// ─── Order Version Snapshots ────────────────────────────────────────────────
|
|
6122
|
+
export const orderVersionSnapshots = pgTable("order_version_snapshots", {
|
|
6123
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
6124
|
+
mediaOrderId: varchar("media_order_id")
|
|
6125
|
+
.notNull()
|
|
6126
|
+
.references(() => mediaOrders.id),
|
|
6127
|
+
version: integer("version").notNull(),
|
|
6128
|
+
amendmentReason: text("amendment_reason"),
|
|
6129
|
+
amendmentNotes: text("amendment_notes"),
|
|
6130
|
+
amendedBy: varchar("amended_by"),
|
|
6131
|
+
snapshot: jsonb("snapshot").notNull().$type(),
|
|
6132
|
+
netInvestment: numeric("net_investment", { precision: 12, scale: 2 }),
|
|
6133
|
+
lineItemCount: integer("line_item_count"),
|
|
6134
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
6135
|
+
}, (table) => [
|
|
6136
|
+
index("order_version_snapshots_order_version_idx").on(table.mediaOrderId, table.version),
|
|
6137
|
+
]);
|
|
6138
|
+
// ─── User Milestones ────────────────────────────────────────────────────────
|
|
6139
|
+
export const userMilestones = pgTable("user_milestones", {
|
|
6140
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
6141
|
+
userId: varchar("user_id").notNull(),
|
|
6142
|
+
milestoneKey: text("milestone_key").notNull(),
|
|
6143
|
+
shownAt: timestamp("shown_at").notNull().defaultNow(),
|
|
6144
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
6145
|
+
}, (table) => [
|
|
6146
|
+
index("user_milestones_user_id_idx").on(table.userId),
|
|
6147
|
+
unique("user_milestones_user_key_unique").on(table.userId, table.milestoneKey),
|
|
6148
|
+
]);
|
|
5969
6149
|
//# sourceMappingURL=schema.js.map
|