@foundrynorth/compass-schema 1.0.21 → 1.0.23
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/dist/schema.d.ts +2198 -324
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +145 -6
- package/dist/schema.js.map +1 -1
- package/dist/types/activity-feed.d.ts +2 -2
- package/dist/types/activity-feed.d.ts.map +1 -1
- package/dist/types/activity-feed.js +8 -0
- package/dist/types/activity-feed.js.map +1 -1
- package/package.json +1 -1
- package/src/schema.ts +204 -6
- package/src/types/activity-feed.ts +8 -0
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
* post-submission visibility (contract alerts, fulfillment status,
|
|
4
4
|
* creative status, amendments, rate exception resolution).
|
|
5
5
|
*/
|
|
6
|
-
export declare const ACTIVITY_EVENT_TYPES: readonly ["fulfillment_stage_changed", "creative_status_changed", "creative_delivered", "signing_progress", "drawdown_alert", "renewal_reminder", "amendment_submitted", "rate_exception_resolved", "sla_hold_set", "sla_hold_cleared", "sla_milestone_at_risk", "sla_milestone_breached", "sla_evaluated"];
|
|
6
|
+
export declare const ACTIVITY_EVENT_TYPES: readonly ["fulfillment_stage_changed", "creative_status_changed", "creative_delivered", "signing_progress", "drawdown_alert", "renewal_reminder", "amendment_submitted", "rate_exception_resolved", "sla_hold_set", "sla_hold_cleared", "sla_milestone_at_risk", "sla_milestone_breached", "sla_evaluated", "mid_campaign_change_applied", "mid_campaign_task_state_changed", "mid_campaign_change_verified"];
|
|
7
7
|
export type ActivityEventType = (typeof ACTIVITY_EVENT_TYPES)[number];
|
|
8
8
|
export declare const ACTIVITY_SEVERITIES: readonly ["info", "success", "warning", "action_needed"];
|
|
9
9
|
export type ActivitySeverity = (typeof ACTIVITY_SEVERITIES)[number];
|
|
10
10
|
export declare const ACTIVITY_SOURCE_SYSTEMS: readonly ["flux", "forge", "hubspot", "compass"];
|
|
11
11
|
export type ActivitySourceSystem = (typeof ACTIVITY_SOURCE_SYSTEMS)[number];
|
|
12
|
-
export declare const PENDING_ACTION_TYPES: readonly ["creative_revision_needed", "creative_rejected", "fulfillment_blocked", "rate_exception_pending", "sla_hold_active"];
|
|
12
|
+
export declare const PENDING_ACTION_TYPES: readonly ["creative_revision_needed", "creative_rejected", "fulfillment_blocked", "rate_exception_pending", "sla_hold_active", "mid_campaign_tasks_pending"];
|
|
13
13
|
export type PendingActionType = (typeof PENDING_ACTION_TYPES)[number];
|
|
14
14
|
/** The event envelope fn-flux sends to fn-legacy */
|
|
15
15
|
export interface CompassStatusEvent {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-feed.d.ts","sourceRoot":"","sources":["../../src/types/activity-feed.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"activity-feed.d.ts","sourceRoot":"","sources":["../../src/types/activity-feed.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,oBAAoB,+YAiBvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,eAAO,MAAM,mBAAmB,0DAKtB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,eAAO,MAAM,uBAAuB,kDAK1B,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,eAAO,MAAM,oBAAoB,8JAOvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QACP,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,QAAQ,EAAE,gBAAgB,CAAC;QAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;KAC3C,CAAC;CACH;AAED,mEAAmE;AACnE,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAChD,iBAAiB,EACjB;IAAE,mBAAmB,EAAE,iBAAiB,CAAC;IAAC,kBAAkB,EAAE,MAAM,EAAE,CAAA;CAAE,CA0BzE,CAAC"}
|
|
@@ -17,6 +17,9 @@ export const ACTIVITY_EVENT_TYPES = [
|
|
|
17
17
|
"sla_milestone_at_risk",
|
|
18
18
|
"sla_milestone_breached",
|
|
19
19
|
"sla_evaluated",
|
|
20
|
+
"mid_campaign_change_applied",
|
|
21
|
+
"mid_campaign_task_state_changed",
|
|
22
|
+
"mid_campaign_change_verified",
|
|
20
23
|
];
|
|
21
24
|
export const ACTIVITY_SEVERITIES = [
|
|
22
25
|
"info",
|
|
@@ -36,6 +39,7 @@ export const PENDING_ACTION_TYPES = [
|
|
|
36
39
|
"fulfillment_blocked",
|
|
37
40
|
"rate_exception_pending",
|
|
38
41
|
"sla_hold_active",
|
|
42
|
+
"mid_campaign_tasks_pending",
|
|
39
43
|
];
|
|
40
44
|
/** Resolution mapping: which events clear which pending actions */
|
|
41
45
|
export const PENDING_ACTION_RESOLUTION_MAP = {
|
|
@@ -59,5 +63,9 @@ export const PENDING_ACTION_RESOLUTION_MAP = {
|
|
|
59
63
|
resolvedByEventType: "sla_hold_cleared",
|
|
60
64
|
resolvedByStatuses: ["clear"],
|
|
61
65
|
},
|
|
66
|
+
mid_campaign_tasks_pending: {
|
|
67
|
+
resolvedByEventType: "mid_campaign_change_verified",
|
|
68
|
+
resolvedByStatuses: ["verified"],
|
|
69
|
+
},
|
|
62
70
|
};
|
|
63
71
|
//# sourceMappingURL=activity-feed.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-feed.js","sourceRoot":"","sources":["../../src/types/activity-feed.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,2BAA2B;IAC3B,yBAAyB;IACzB,oBAAoB;IACpB,kBAAkB;IAClB,gBAAgB;IAChB,kBAAkB;IAClB,qBAAqB;IACrB,yBAAyB;IACzB,cAAc;IACd,kBAAkB;IAClB,uBAAuB;IACvB,wBAAwB;IACxB,eAAe;
|
|
1
|
+
{"version":3,"file":"activity-feed.js","sourceRoot":"","sources":["../../src/types/activity-feed.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,2BAA2B;IAC3B,yBAAyB;IACzB,oBAAoB;IACpB,kBAAkB;IAClB,gBAAgB;IAChB,kBAAkB;IAClB,qBAAqB;IACrB,yBAAyB;IACzB,cAAc;IACd,kBAAkB;IAClB,uBAAuB;IACvB,wBAAwB;IACxB,eAAe;IACf,6BAA6B;IAC7B,iCAAiC;IACjC,8BAA8B;CACtB,CAAC;AAIX,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,MAAM;IACN,SAAS;IACT,SAAS;IACT,eAAe;CACP,CAAC;AAIX,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,MAAM;IACN,OAAO;IACP,SAAS;IACT,SAAS;CACD,CAAC;AAIX,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,0BAA0B;IAC1B,mBAAmB;IACnB,qBAAqB;IACrB,wBAAwB;IACxB,iBAAiB;IACjB,4BAA4B;CACpB,CAAC;AAuBX,mEAAmE;AACnE,MAAM,CAAC,MAAM,6BAA6B,GAGtC;IACF,wBAAwB,EAAE;QACxB,mBAAmB,EAAE,yBAAyB;QAC9C,kBAAkB,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC;KAC9C;IACD,iBAAiB,EAAE;QACjB,mBAAmB,EAAE,yBAAyB;QAC9C,kBAAkB,EAAE,CAAC,UAAU,CAAC;KACjC;IACD,mBAAmB,EAAE;QACnB,mBAAmB,EAAE,2BAA2B;QAChD,kBAAkB,EAAE,CAAC,qBAAqB,EAAE,SAAS,EAAE,WAAW,CAAC;KACpE;IACD,sBAAsB,EAAE;QACtB,mBAAmB,EAAE,yBAAyB;QAC9C,kBAAkB,EAAE,CAAC,UAAU,EAAE,eAAe,EAAE,UAAU,CAAC;KAC9D;IACD,eAAe,EAAE;QACf,mBAAmB,EAAE,kBAAkB;QACvC,kBAAkB,EAAE,CAAC,OAAO,CAAC;KAC9B;IACD,0BAA0B,EAAE;QAC1B,mBAAmB,EAAE,8BAA8B;QACnD,kBAAkB,EAAE,CAAC,UAAU,CAAC;KACjC;CACF,CAAC"}
|
package/package.json
CHANGED
package/src/schema.ts
CHANGED
|
@@ -598,6 +598,35 @@ export const competitorSchema = z.object({
|
|
|
598
598
|
lng: z.number(),
|
|
599
599
|
})
|
|
600
600
|
.optional(), // Detailed location information
|
|
601
|
+
|
|
602
|
+
// Ad library data from Apify deep enrichment
|
|
603
|
+
ads: z
|
|
604
|
+
.object({
|
|
605
|
+
facebook: z
|
|
606
|
+
.array(
|
|
607
|
+
z.object({
|
|
608
|
+
adImage: z.string().optional(),
|
|
609
|
+
headline: z.string().optional(),
|
|
610
|
+
adCopy: z.string().optional(),
|
|
611
|
+
callToAction: z.string().optional(),
|
|
612
|
+
publisherPlatforms: z.array(z.string()).optional(),
|
|
613
|
+
startDate: z.string().optional(),
|
|
614
|
+
})
|
|
615
|
+
)
|
|
616
|
+
.optional(),
|
|
617
|
+
google: z
|
|
618
|
+
.array(
|
|
619
|
+
z.object({
|
|
620
|
+
headline: z.string().optional(),
|
|
621
|
+
description: z.string().optional(),
|
|
622
|
+
landingPage: z.string().optional(),
|
|
623
|
+
adType: z.string().optional(),
|
|
624
|
+
imageUrl: z.string().optional(),
|
|
625
|
+
})
|
|
626
|
+
)
|
|
627
|
+
.optional(),
|
|
628
|
+
})
|
|
629
|
+
.optional(),
|
|
601
630
|
});
|
|
602
631
|
|
|
603
632
|
export type Competitor = z.infer<typeof competitorSchema>;
|
|
@@ -1244,6 +1273,7 @@ export const plans = pgTable("plans", {
|
|
|
1244
1273
|
defaultTargeting: text("default_targeting"),
|
|
1245
1274
|
defaultAudience: text("default_audience"),
|
|
1246
1275
|
defaultPromoting: text("default_promoting"),
|
|
1276
|
+
defaultCreativeSource: varchar("default_creative_source"),
|
|
1247
1277
|
defaultFlightStart: date("default_flight_start"),
|
|
1248
1278
|
defaultFlightEnd: date("default_flight_end"),
|
|
1249
1279
|
|
|
@@ -1315,8 +1345,12 @@ export const proposals = pgTable(
|
|
|
1315
1345
|
.default(sql`gen_random_uuid()`),
|
|
1316
1346
|
|
|
1317
1347
|
// Optional plan reference (nullable — can be standalone)
|
|
1318
|
-
planId: varchar("plan_id"),
|
|
1319
|
-
|
|
1348
|
+
planId: varchar("plan_id").references(() => plans.id, {
|
|
1349
|
+
onDelete: "set null",
|
|
1350
|
+
}),
|
|
1351
|
+
engagementId: varchar("engagement_id").references(() => engagements.id, {
|
|
1352
|
+
onDelete: "set null",
|
|
1353
|
+
}), // nullable during transition
|
|
1320
1354
|
|
|
1321
1355
|
// Configuration references (which plan_configurations to include)
|
|
1322
1356
|
configurationIds: jsonb("configuration_ids").$type<string[]>(),
|
|
@@ -1387,6 +1421,41 @@ export const insertPlanSchema = createInsertSchema(plans).omit({
|
|
|
1387
1421
|
createdAt: true,
|
|
1388
1422
|
} as any);
|
|
1389
1423
|
|
|
1424
|
+
// ============================================================================
|
|
1425
|
+
// Proposal Engagement Tracking
|
|
1426
|
+
// ============================================================================
|
|
1427
|
+
|
|
1428
|
+
export const proposalEngagement = pgTable(
|
|
1429
|
+
"proposal_engagement",
|
|
1430
|
+
{
|
|
1431
|
+
id: varchar("id")
|
|
1432
|
+
.primaryKey()
|
|
1433
|
+
.default(sql`gen_random_uuid()`),
|
|
1434
|
+
proposalId: varchar("proposal_id"), // FK → proposals.id (nullable for legacy plan-based shares)
|
|
1435
|
+
planId: varchar("plan_id"), // FK → plans.id (fallback for legacy shares)
|
|
1436
|
+
shareToken: text("share_token").notNull(), // The share token used to access
|
|
1437
|
+
sessionId: text("session_id").notNull(), // Anonymous session ID (crypto.randomUUID on client)
|
|
1438
|
+
// Engagement data
|
|
1439
|
+
events: jsonb("events").notNull().default(sql`'[]'::jsonb`), // Array of engagement events
|
|
1440
|
+
engagementScore: integer("engagement_score").default(0), // Computed 0-100 score
|
|
1441
|
+
summary: text("summary"), // AI-generated follow-up brief
|
|
1442
|
+
// Device context
|
|
1443
|
+
device: text("device"), // "desktop" | "mobile" | "tablet"
|
|
1444
|
+
referrer: text("referrer"), // HTTP referrer
|
|
1445
|
+
userAgent: text("user_agent"),
|
|
1446
|
+
// Timestamps
|
|
1447
|
+
firstSeenAt: timestamp("first_seen_at").notNull().defaultNow(),
|
|
1448
|
+
lastSeenAt: timestamp("last_seen_at").notNull().defaultNow(),
|
|
1449
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
1450
|
+
},
|
|
1451
|
+
(table) => [
|
|
1452
|
+
index("proposal_engagement_proposal_id_idx").on(table.proposalId),
|
|
1453
|
+
index("proposal_engagement_plan_id_idx").on(table.planId),
|
|
1454
|
+
index("proposal_engagement_share_token_idx").on(table.shareToken),
|
|
1455
|
+
index("proposal_engagement_token_session_idx").on(table.shareToken, table.sessionId),
|
|
1456
|
+
]
|
|
1457
|
+
);
|
|
1458
|
+
|
|
1390
1459
|
export type InsertPlan = z.infer<typeof insertPlanSchema>;
|
|
1391
1460
|
export type Plan = typeof plans.$inferSelect;
|
|
1392
1461
|
|
|
@@ -4805,22 +4874,134 @@ export type SalesInitiative = typeof salesInitiatives.$inferSelect;
|
|
|
4805
4874
|
export type InsertSalesInitiative = z.infer<typeof insertSalesInitiativeSchema>;
|
|
4806
4875
|
export type UpdateSalesInitiative = z.infer<typeof updateSalesInitiativeSchema>;
|
|
4807
4876
|
|
|
4877
|
+
export const salesPackages = pgTable(
|
|
4878
|
+
"sales_packages",
|
|
4879
|
+
{
|
|
4880
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
4881
|
+
code: varchar("code").notNull().unique(),
|
|
4882
|
+
name: varchar("name").notNull(),
|
|
4883
|
+
description: text("description"),
|
|
4884
|
+
initiativeCode: varchar("initiative_code"),
|
|
4885
|
+
sellerSummary: text("seller_summary"),
|
|
4886
|
+
packagePrice: numeric("package_price", { precision: 12, scale: 2 }),
|
|
4887
|
+
discountPercent: numeric("discount_percent", { precision: 5, scale: 2 }),
|
|
4888
|
+
addedValueAmount: numeric("added_value_amount", { precision: 12, scale: 2 }),
|
|
4889
|
+
addedValueDescription: varchar("added_value_description", { length: 255 }),
|
|
4890
|
+
hubspotPackageValue: varchar("hubspot_package_value").notNull().unique(),
|
|
4891
|
+
startsAt: date("starts_at"),
|
|
4892
|
+
endsAt: date("ends_at"),
|
|
4893
|
+
status: varchar("status").notNull().default("draft"),
|
|
4894
|
+
recommendationMode: varchar("recommendation_mode").notNull().default("both"),
|
|
4895
|
+
recommendationPriority: integer("recommendation_priority").notNull().default(0),
|
|
4896
|
+
eligibilityRules: jsonb("eligibility_rules").$type<{
|
|
4897
|
+
goals?: string[];
|
|
4898
|
+
industries?: string[];
|
|
4899
|
+
geographyTags?: string[];
|
|
4900
|
+
minBudget?: number | null;
|
|
4901
|
+
maxBudget?: number | null;
|
|
4902
|
+
requireActiveWindow?: boolean;
|
|
4903
|
+
minProductOverlap?: number | null;
|
|
4904
|
+
allowSubsetMatch?: boolean;
|
|
4905
|
+
allowNearMatch?: boolean;
|
|
4906
|
+
compareSignals?: string[];
|
|
4907
|
+
}>(),
|
|
4908
|
+
assistantHints: jsonb("assistant_hints").$type<{
|
|
4909
|
+
recommendedWhen?: string[];
|
|
4910
|
+
upsellMessage?: string | null;
|
|
4911
|
+
compareHeadline?: string | null;
|
|
4912
|
+
compareBody?: string | null;
|
|
4913
|
+
}>(),
|
|
4914
|
+
taskTemplateMode: varchar("task_template_mode").notNull().default("standard"),
|
|
4915
|
+
displayOrder: integer("display_order").notNull().default(0),
|
|
4916
|
+
isActive: boolean("is_active").notNull().default(true),
|
|
4917
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
4918
|
+
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
4919
|
+
},
|
|
4920
|
+
(table) => [
|
|
4921
|
+
index("sales_packages_active_idx").on(table.isActive),
|
|
4922
|
+
index("sales_packages_status_idx").on(table.status),
|
|
4923
|
+
index("sales_packages_display_order_idx").on(table.displayOrder),
|
|
4924
|
+
index("sales_packages_initiative_code_idx").on(table.initiativeCode),
|
|
4925
|
+
],
|
|
4926
|
+
);
|
|
4927
|
+
|
|
4928
|
+
export const insertSalesPackageSchema = createInsertSchema(salesPackages).omit({
|
|
4929
|
+
id: true,
|
|
4930
|
+
createdAt: true,
|
|
4931
|
+
updatedAt: true,
|
|
4932
|
+
});
|
|
4933
|
+
export const updateSalesPackageSchema = insertSalesPackageSchema.partial();
|
|
4934
|
+
export type SalesPackage = typeof salesPackages.$inferSelect;
|
|
4935
|
+
export type InsertSalesPackage = z.infer<typeof insertSalesPackageSchema>;
|
|
4936
|
+
export type UpdateSalesPackage = z.infer<typeof updateSalesPackageSchema>;
|
|
4937
|
+
|
|
4938
|
+
export const salesPackageProducts = pgTable(
|
|
4939
|
+
"sales_package_products",
|
|
4940
|
+
{
|
|
4941
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
4942
|
+
salesPackageCode: varchar("sales_package_code").notNull(),
|
|
4943
|
+
stribProductId: uuid("strib_product_id")
|
|
4944
|
+
.notNull()
|
|
4945
|
+
.references(() => stribProducts.id, { onDelete: "cascade" }),
|
|
4946
|
+
displayOrder: integer("display_order").notNull().default(0),
|
|
4947
|
+
approvedUnitRate: numeric("approved_unit_rate", { precision: 12, scale: 4 }),
|
|
4948
|
+
approvedRateType: varchar("approved_rate_type"),
|
|
4949
|
+
allocationMode: varchar("allocation_mode").notNull().default("percent"),
|
|
4950
|
+
allocationValue: numeric("allocation_value", { precision: 12, scale: 4 }),
|
|
4951
|
+
required: boolean("required").notNull().default(true),
|
|
4952
|
+
defaultFulfillmentDetails: jsonb("default_fulfillment_details"),
|
|
4953
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
4954
|
+
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
4955
|
+
},
|
|
4956
|
+
(table) => [
|
|
4957
|
+
uniqueIndex("sales_package_products_unique_idx").on(
|
|
4958
|
+
table.salesPackageCode,
|
|
4959
|
+
table.stribProductId,
|
|
4960
|
+
),
|
|
4961
|
+
index("sales_package_products_code_idx").on(table.salesPackageCode),
|
|
4962
|
+
index("sales_package_products_product_idx").on(table.stribProductId),
|
|
4963
|
+
],
|
|
4964
|
+
);
|
|
4965
|
+
|
|
4966
|
+
export type SalesPackageProduct = typeof salesPackageProducts.$inferSelect;
|
|
4967
|
+
|
|
4808
4968
|
export const mediaOrders = pgTable(
|
|
4809
4969
|
"media_orders",
|
|
4810
4970
|
{
|
|
4811
4971
|
id: varchar("id")
|
|
4812
4972
|
.primaryKey()
|
|
4813
4973
|
.default(sql`gen_random_uuid()`),
|
|
4814
|
-
planId: varchar("plan_id")
|
|
4815
|
-
|
|
4974
|
+
planId: varchar("plan_id").references(() => plans.id, {
|
|
4975
|
+
onDelete: "set null",
|
|
4976
|
+
}), // nullable — can exist without a plan
|
|
4977
|
+
engagementId: varchar("engagement_id").references(() => engagements.id, {
|
|
4978
|
+
onDelete: "set null",
|
|
4979
|
+
}), // nullable during transition
|
|
4816
4980
|
configurationId: varchar("configuration_id"), // FK → plan_configurations.id (named product mix)
|
|
4817
4981
|
optionId: varchar("option_id"), // FK → plan_options.id (canonical selected option)
|
|
4818
|
-
contractId: uuid("contract_id")
|
|
4982
|
+
contractId: uuid("contract_id").references(() => contracts.id, {
|
|
4983
|
+
onDelete: "set null",
|
|
4984
|
+
}), // nullable — links to annual contract
|
|
4819
4985
|
partnerId: varchar("partner_id"),
|
|
4820
4986
|
hubspotDealId: text("hubspot_deal_id"),
|
|
4821
4987
|
hubspotCompanyId: text("hubspot_company_id"),
|
|
4822
4988
|
parentHubspotCompanyId: text("parent_hubspot_company_id"),
|
|
4823
4989
|
initiativeCode: varchar("initiative_code"),
|
|
4990
|
+
salesPackageCode: varchar("sales_package_code"),
|
|
4991
|
+
salesPackageSnapshot: jsonb("sales_package_snapshot").$type<Array<{
|
|
4992
|
+
code: string;
|
|
4993
|
+
name: string;
|
|
4994
|
+
packagePrice: number | null;
|
|
4995
|
+
initiativeCode: string | null;
|
|
4996
|
+
componentCount: number;
|
|
4997
|
+
appliedAt: string;
|
|
4998
|
+
packageSource: "direct_package" | "upgrade_from_selection" | "manual_products";
|
|
4999
|
+
compareSignals?: string[];
|
|
5000
|
+
sellerSummary?: string | null;
|
|
5001
|
+
discountPercent?: number | null;
|
|
5002
|
+
addedValueAmount?: number | null;
|
|
5003
|
+
addedValueDescription?: string | null;
|
|
5004
|
+
}>>(),
|
|
4824
5005
|
|
|
4825
5006
|
// Client header
|
|
4826
5007
|
clientName: text("client_name").notNull(),
|
|
@@ -4944,6 +5125,7 @@ export const mediaOrders = pgTable(
|
|
|
4944
5125
|
index("media_orders_parent_company_idx").on(table.parentHubspotCompanyId),
|
|
4945
5126
|
index("media_orders_contract_id_idx").on(table.contractId),
|
|
4946
5127
|
index("media_orders_initiative_code_idx").on(table.initiativeCode),
|
|
5128
|
+
index("media_orders_sales_package_code_idx").on(table.salesPackageCode),
|
|
4947
5129
|
]
|
|
4948
5130
|
);
|
|
4949
5131
|
|
|
@@ -5073,6 +5255,10 @@ export const mediaOrderLineItems = pgTable(
|
|
|
5073
5255
|
fulfillmentDetails: jsonb("fulfillment_details"),
|
|
5074
5256
|
creativeSource: varchar("creative_source"),
|
|
5075
5257
|
initiativeCode: varchar("initiative_code"),
|
|
5258
|
+
salesPackageCode: varchar("sales_package_code"),
|
|
5259
|
+
salesPackageComponentRef: varchar("sales_package_component_ref"),
|
|
5260
|
+
isPackageDerived: boolean("is_package_derived").notNull().default(false),
|
|
5261
|
+
packagePricingSource: varchar("package_pricing_source"),
|
|
5076
5262
|
|
|
5077
5263
|
// Ad trafficking reference key (auto-generated naming convention)
|
|
5078
5264
|
trafficKey: text("traffic_key"),
|
|
@@ -5099,6 +5285,7 @@ export const mediaOrderLineItems = pgTable(
|
|
|
5099
5285
|
index("media_order_line_items_location_id_idx").on(table.locationId),
|
|
5100
5286
|
index("media_order_line_items_tracking_key_idx").on(table.trackingKey),
|
|
5101
5287
|
index("media_order_line_items_initiative_code_idx").on(table.initiativeCode),
|
|
5288
|
+
index("media_order_line_items_sales_package_code_idx").on(table.salesPackageCode),
|
|
5102
5289
|
]
|
|
5103
5290
|
);
|
|
5104
5291
|
|
|
@@ -8316,11 +8503,20 @@ export type SemCampaignRecord = typeof semCampaigns.$inferSelect;
|
|
|
8316
8503
|
export type InsertSemCampaign = typeof semCampaigns.$inferInsert;
|
|
8317
8504
|
|
|
8318
8505
|
// =============================================================================
|
|
8319
|
-
// COMPASS EVENT OUTBOX (
|
|
8506
|
+
// COMPASS EVENT OUTBOX (durable outbox for cross-system writes)
|
|
8507
|
+
//
|
|
8508
|
+
// Generic claim/retry/DLQ pattern used by multiple producers. Events are
|
|
8509
|
+
// namespaced by `eventType` prefix so multiple workers can drain the same
|
|
8510
|
+
// table without contention:
|
|
8511
|
+
// • "flux.*" — fn-flux webhook delivery to external consumers
|
|
8512
|
+
// • "hubspot.*" — HubSpot ticket / Campaign Task writes from fn-legacy
|
|
8513
|
+
// (drained by fn-v2 hubspot-outbox-worker)
|
|
8514
|
+
// Workers filter on `event_type LIKE '{namespace}.%'` in their claim query.
|
|
8320
8515
|
// =============================================================================
|
|
8321
8516
|
|
|
8322
8517
|
export const compassEventOutboxStatusEnum = pgEnum("compass_event_outbox_status", [
|
|
8323
8518
|
"pending",
|
|
8519
|
+
"processing",
|
|
8324
8520
|
"failed",
|
|
8325
8521
|
"delivered",
|
|
8326
8522
|
"dead_letter",
|
|
@@ -8422,6 +8618,8 @@ export const pendingActions = pgTable(
|
|
|
8422
8618
|
},
|
|
8423
8619
|
(table) => [
|
|
8424
8620
|
index("pending_actions_order_idx").on(table.mediaOrderId),
|
|
8621
|
+
index("pending_actions_line_item_idx").on(table.lineItemId),
|
|
8622
|
+
index("pending_actions_activity_feed_idx").on(table.activityFeedId),
|
|
8425
8623
|
index("pending_actions_unresolved_idx").on(table.mediaOrderId).where(
|
|
8426
8624
|
sql`resolved_at IS NULL`,
|
|
8427
8625
|
),
|
|
@@ -18,6 +18,9 @@ export const ACTIVITY_EVENT_TYPES = [
|
|
|
18
18
|
"sla_milestone_at_risk",
|
|
19
19
|
"sla_milestone_breached",
|
|
20
20
|
"sla_evaluated",
|
|
21
|
+
"mid_campaign_change_applied",
|
|
22
|
+
"mid_campaign_task_state_changed",
|
|
23
|
+
"mid_campaign_change_verified",
|
|
21
24
|
] as const;
|
|
22
25
|
|
|
23
26
|
export type ActivityEventType = (typeof ACTIVITY_EVENT_TYPES)[number];
|
|
@@ -46,6 +49,7 @@ export const PENDING_ACTION_TYPES = [
|
|
|
46
49
|
"fulfillment_blocked",
|
|
47
50
|
"rate_exception_pending",
|
|
48
51
|
"sla_hold_active",
|
|
52
|
+
"mid_campaign_tasks_pending",
|
|
49
53
|
] as const;
|
|
50
54
|
|
|
51
55
|
export type PendingActionType = (typeof PENDING_ACTION_TYPES)[number];
|
|
@@ -94,4 +98,8 @@ export const PENDING_ACTION_RESOLUTION_MAP: Record<
|
|
|
94
98
|
resolvedByEventType: "sla_hold_cleared",
|
|
95
99
|
resolvedByStatuses: ["clear"],
|
|
96
100
|
},
|
|
101
|
+
mid_campaign_tasks_pending: {
|
|
102
|
+
resolvedByEventType: "mid_campaign_change_verified",
|
|
103
|
+
resolvedByStatuses: ["verified"],
|
|
104
|
+
},
|
|
97
105
|
};
|