@foundrynorth/flux-schema 1.17.4 → 1.18.1
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 +2787 -4010
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +298 -232
- package/dist/schema.js.map +1 -1
- package/package.json +1 -1
package/dist/schema.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* CRITICAL: No stubs. All tables are real and will be created on migration.
|
|
8
8
|
*/
|
|
9
|
-
import { pgTable, varchar, text, boolean, timestamp, date, jsonb, integer, bigint, numeric, uuid, real, serial, time, pgEnum, uniqueIndex, index, customType, } from "drizzle-orm/pg-core";
|
|
9
|
+
import { pgTable, varchar, text, boolean, timestamp, date, jsonb, integer, bigint, bigserial, numeric, uuid, real, serial, time, pgEnum, uniqueIndex, index, customType, } from "drizzle-orm/pg-core";
|
|
10
10
|
import { relations, sql } from "drizzle-orm";
|
|
11
11
|
/**
|
|
12
12
|
* Custom pgvector type for embedding columns.
|
|
@@ -2571,6 +2571,20 @@ export const fluxFulfillmentTickets = pgTable("flux_fulfillment_tickets", {
|
|
|
2571
2571
|
dealOrderTotal: numeric("deal_order_total", { precision: 12, scale: 2 }),
|
|
2572
2572
|
/** Compass order status (e.g., "signed", "draft", "amended") */
|
|
2573
2573
|
compassOrderStatus: text("compass_order_status"),
|
|
2574
|
+
/** Human-readable product family name derived from Compass context */
|
|
2575
|
+
familyName: text("family_name"),
|
|
2576
|
+
/** Requested creative sizes from Compass / HubSpot line item context */
|
|
2577
|
+
adSizes: jsonb("ad_sizes").$type(),
|
|
2578
|
+
/** Product / offer description for stronger creative briefs */
|
|
2579
|
+
productDescription: text("product_description"),
|
|
2580
|
+
/** Product KPIs / use cases carried from upstream when available */
|
|
2581
|
+
productKpis: jsonb("product_kpis").$type(),
|
|
2582
|
+
/** Creative refresh cadence inherited from upstream order defaults */
|
|
2583
|
+
creativeRefreshCadence: text("creative_refresh_cadence"),
|
|
2584
|
+
/** Company domain used for landing page and brand context */
|
|
2585
|
+
companyDomain: text("company_domain"),
|
|
2586
|
+
/** Company industry used for briefing and brand alignment */
|
|
2587
|
+
companyIndustry: text("company_industry"),
|
|
2574
2588
|
// -- Native HubSpot SLA --
|
|
2575
2589
|
/** HubSpot SLA status for first response (Overdue, Due Soon, Active SLA, etc.) */
|
|
2576
2590
|
hubspotSlaFirstResponse: varchar("hubspot_sla_first_response"),
|
|
@@ -4047,26 +4061,46 @@ export const fluxSlaAuditLog = pgTable("flux_sla_audit_log", {
|
|
|
4047
4061
|
// Agreement Tracking
|
|
4048
4062
|
// ============================================================================
|
|
4049
4063
|
/**
|
|
4050
|
-
* Agreement tier
|
|
4064
|
+
* Agreement tier discriminator. Contracts are the umbrella commitment,
|
|
4065
|
+
* IOs are tactical executions (usually under a parent contract), NDAs
|
|
4066
|
+
* are non-disclosure documents with no commitment.
|
|
4051
4067
|
*/
|
|
4052
|
-
export const
|
|
4068
|
+
export const fluxAgreementTier = pgEnum("flux_agreement_tier", [
|
|
4053
4069
|
"contract",
|
|
4054
4070
|
"io",
|
|
4055
|
-
"
|
|
4071
|
+
"nda",
|
|
4056
4072
|
]);
|
|
4057
4073
|
/**
|
|
4058
|
-
*
|
|
4074
|
+
* Signing workflow state machine (pre-execution).
|
|
4059
4075
|
*/
|
|
4060
|
-
export const
|
|
4076
|
+
export const fluxSigningStatus = pgEnum("flux_signing_status", [
|
|
4061
4077
|
"draft",
|
|
4062
4078
|
"pending_internal",
|
|
4063
4079
|
"pending_client",
|
|
4064
4080
|
"pending_countersign",
|
|
4065
|
-
"
|
|
4081
|
+
"signed",
|
|
4082
|
+
"voided",
|
|
4083
|
+
]);
|
|
4084
|
+
/**
|
|
4085
|
+
* Post-signing lifecycle state machine. Separate from signing_status so
|
|
4086
|
+
* the two concerns don't interleave in a single enum.
|
|
4087
|
+
*/
|
|
4088
|
+
export const fluxLifecycleStatus = pgEnum("flux_lifecycle_status", [
|
|
4089
|
+
"pre_active",
|
|
4066
4090
|
"active",
|
|
4067
|
-
"
|
|
4091
|
+
"expiring_soon",
|
|
4068
4092
|
"expired",
|
|
4069
|
-
"
|
|
4093
|
+
"renewed",
|
|
4094
|
+
"terminated_early",
|
|
4095
|
+
]);
|
|
4096
|
+
/**
|
|
4097
|
+
* Relationship between a version chain entry and its predecessor.
|
|
4098
|
+
* NULL = original (not a revision). 'amendment' = revision of the same
|
|
4099
|
+
* commitment period. 'renewal' = sequential new commitment period.
|
|
4100
|
+
*/
|
|
4101
|
+
export const fluxRelationType = pgEnum("flux_relation_type", [
|
|
4102
|
+
"amendment",
|
|
4103
|
+
"renewal",
|
|
4070
4104
|
]);
|
|
4071
4105
|
/**
|
|
4072
4106
|
* Signer role in the signing workflow
|
|
@@ -4086,29 +4120,69 @@ export const fluxSignerStatusEnum = pgEnum("flux_signer_status", [
|
|
|
4086
4120
|
"delegated",
|
|
4087
4121
|
]);
|
|
4088
4122
|
/**
|
|
4089
|
-
* Agreements —
|
|
4090
|
-
*
|
|
4123
|
+
* Agreements — unified table for contracts, insertion orders, and NDAs.
|
|
4124
|
+
* Discriminated by `tier`. fn-flux is the system of record for this
|
|
4125
|
+
* entity; Compass keeps shadow rows in its own `contracts` table via
|
|
4126
|
+
* the `fluxAgreementId` back-reference.
|
|
4127
|
+
*
|
|
4128
|
+
* See docs/superpowers/specs/2026-04-10-contract-agreement-p0-design.md
|
|
4129
|
+
* for the full design rationale.
|
|
4091
4130
|
*/
|
|
4092
4131
|
export const fluxAgreements = pgTable("flux_agreements", {
|
|
4132
|
+
// ─── Identity + discriminator ─────────────────────────────────────
|
|
4093
4133
|
id: text("id").primaryKey().default(sql `gen_random_uuid()::text`),
|
|
4094
|
-
tier:
|
|
4095
|
-
|
|
4134
|
+
tier: fluxAgreementTier("tier").notNull(),
|
|
4135
|
+
version: integer("version").notNull().default(1),
|
|
4136
|
+
previousVersionId: text("previous_version_id").references(() => fluxAgreements.id),
|
|
4137
|
+
relationType: fluxRelationType("relation_type"),
|
|
4138
|
+
// ─── Two status state machines ─────────────────────────────────────
|
|
4139
|
+
signingStatus: fluxSigningStatus("signing_status")
|
|
4140
|
+
.notNull()
|
|
4141
|
+
.default("draft"),
|
|
4142
|
+
lifecycleStatus: fluxLifecycleStatus("lifecycle_status"),
|
|
4143
|
+
// ─── Counterparty (canonical: hubspot_company_id) ─────────────────
|
|
4144
|
+
hubspotCompanyId: text("hubspot_company_id"),
|
|
4145
|
+
counterpartyName: text("counterparty_name"),
|
|
4096
4146
|
projectId: text("project_id").references(() => fluxProjects.id),
|
|
4097
|
-
dealId: text("deal_id").references(() => fluxDealPipeline.id),
|
|
4098
4147
|
hubspotDealId: text("hubspot_deal_id"),
|
|
4099
|
-
|
|
4148
|
+
// ─── Hierarchy ─────────────────────────────────────────────────────
|
|
4149
|
+
parentAgreementId: text("parent_agreement_id").references(() => fluxAgreements.id),
|
|
4150
|
+
pendingCompassContractIdHint: text("pending_compass_contract_id_hint"),
|
|
4151
|
+
standaloneConfirmedAt: timestamp("standalone_confirmed_at", {
|
|
4152
|
+
withTimezone: true,
|
|
4153
|
+
}),
|
|
4154
|
+
standaloneConfirmedByUserId: text("standalone_confirmed_by_user_id").references(() => fluxUsers.id),
|
|
4155
|
+
// ─── Cross-system identity ─────────────────────────────────────────
|
|
4100
4156
|
compassContractId: text("compass_contract_id"),
|
|
4101
4157
|
compassOrderId: text("compass_order_id"),
|
|
4158
|
+
fulfillmentTicketId: text("fulfillment_ticket_id").references(() => fluxFulfillmentTickets.id),
|
|
4159
|
+
// ─── Terms ─────────────────────────────────────────────────────────
|
|
4102
4160
|
title: text("title").notNull(),
|
|
4103
4161
|
description: text("description"),
|
|
4104
|
-
commitmentAmount: numeric("commitment_amount", { precision: 14, scale: 2 }),
|
|
4105
|
-
tierCode: text("tier_code"),
|
|
4106
|
-
currency: text("currency").default("USD"),
|
|
4107
4162
|
effectiveDate: date("effective_date"),
|
|
4108
4163
|
expirationDate: date("expiration_date"),
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4164
|
+
currency: text("currency").notNull().default("USD"),
|
|
4165
|
+
entitlementTierCode: text("entitlement_tier_code"),
|
|
4166
|
+
// ─── Commitment + 3-stage drawdown (contract-tier only) ───────────
|
|
4167
|
+
commitmentAmount: numeric("commitment_amount", { precision: 14, scale: 2 }),
|
|
4168
|
+
committedAmount: numeric("committed_amount", { precision: 14, scale: 2 }),
|
|
4169
|
+
allocatedAmount: numeric("allocated_amount", { precision: 14, scale: 2 }),
|
|
4170
|
+
billedAmount: numeric("billed_amount", { precision: 14, scale: 2 }),
|
|
4171
|
+
remainingAmount: numeric("remaining_amount", { precision: 14, scale: 2 }),
|
|
4172
|
+
// ─── Margin (contract-tier only) ──────────────────────────────────
|
|
4173
|
+
projectedMarginPct: numeric("projected_margin_pct", { precision: 5, scale: 2 }),
|
|
4174
|
+
projectedMarginDollars: numeric("projected_margin_dollars", { precision: 14, scale: 2 }),
|
|
4175
|
+
actualMarginPct: numeric("actual_margin_pct", { precision: 5, scale: 2 }),
|
|
4176
|
+
actualMarginDollars: numeric("actual_margin_dollars", { precision: 14, scale: 2 }),
|
|
4177
|
+
// ─── Value-add, rate card, product mix (contract-tier only) ───────
|
|
4178
|
+
valueAddTotal: numeric("value_add_total", { precision: 14, scale: 2 }),
|
|
4179
|
+
rateCard: jsonb("rate_card"),
|
|
4180
|
+
productAllocations: jsonb("product_allocations"),
|
|
4181
|
+
// ─── Renewal terms (contract-tier only) ───────────────────────────
|
|
4182
|
+
autorenew: boolean("autorenew").notNull().default(false),
|
|
4183
|
+
renewalTermMonths: integer("renewal_term_months"),
|
|
4184
|
+
noticeDeadline: date("notice_deadline"),
|
|
4185
|
+
// ─── E-sign + document (all tiers) ────────────────────────────────
|
|
4112
4186
|
documentUrl: text("document_url"),
|
|
4113
4187
|
documentFingerprint: text("document_fingerprint"),
|
|
4114
4188
|
documentFileName: text("document_file_name"),
|
|
@@ -4116,31 +4190,19 @@ export const fluxAgreements = pgTable("flux_agreements", {
|
|
|
4116
4190
|
esignEnvelopeId: text("esign_envelope_id"),
|
|
4117
4191
|
esignCallbackUrl: text("esign_callback_url"),
|
|
4118
4192
|
esignStatus: text("esign_status"),
|
|
4119
|
-
|
|
4120
|
-
withTimezone: true,
|
|
4121
|
-
}),
|
|
4122
|
-
slackChannelId: text("slack_channel_id"),
|
|
4123
|
-
slackMessageTs: text("slack_message_ts"),
|
|
4193
|
+
// ─── Health / risk / compliance (feeds P4) ────────────────────────
|
|
4124
4194
|
healthScore: integer("health_score"),
|
|
4125
|
-
complianceStatus: text("compliance_status"),
|
|
4126
|
-
riskIndicators: jsonb("risk_indicators").default([]),
|
|
4127
|
-
parentContractId: text("parent_contract_id").references(() => fluxMasterContracts.id),
|
|
4128
|
-
metadata: jsonb("metadata").default({}),
|
|
4129
|
-
// --- Workspace columns (graduated from metadata JSONB) ---
|
|
4130
|
-
priority: text("priority").default("medium"),
|
|
4131
|
-
workspaceStatus: text("workspace_status"),
|
|
4132
|
-
counterpartyName: text("counterparty_name"),
|
|
4133
|
-
currentModule: text("current_module"),
|
|
4134
|
-
receivedAt: timestamp("received_at", { withTimezone: true }),
|
|
4135
|
-
requestedBy: text("requested_by"),
|
|
4136
|
-
ownerName: text("owner_name"),
|
|
4137
|
-
needsBy: text("needs_by"),
|
|
4138
|
-
autorenew: boolean("autorenew"),
|
|
4139
|
-
renewalTermMonths: integer("renewal_term_months"),
|
|
4140
|
-
noticeDeadline: text("notice_deadline"),
|
|
4141
|
-
packageType: jsonb("package_type").default([]),
|
|
4142
|
-
tags: jsonb("tags").default([]),
|
|
4143
4195
|
riskScore: integer("risk_score"),
|
|
4196
|
+
complianceStatus: text("compliance_status"),
|
|
4197
|
+
riskIndicators: jsonb("risk_indicators").notNull().default([]),
|
|
4198
|
+
// ─── Operational ──────────────────────────────────────────────────
|
|
4199
|
+
priority: text("priority").notNull().default("medium"),
|
|
4200
|
+
slackChannelId: text("slack_channel_id"),
|
|
4201
|
+
slackMessageTs: text("slack_message_ts"),
|
|
4202
|
+
tags: jsonb("tags").notNull().default([]),
|
|
4203
|
+
amendmentReason: text("amendment_reason"),
|
|
4204
|
+
metadata: jsonb("metadata").notNull().default({}),
|
|
4205
|
+
// ─── Audit ────────────────────────────────────────────────────────
|
|
4144
4206
|
createdById: text("created_by_id").references(() => fluxUsers.id),
|
|
4145
4207
|
createdAt: timestamp("created_at", { withTimezone: true })
|
|
4146
4208
|
.notNull()
|
|
@@ -4148,25 +4210,52 @@ export const fluxAgreements = pgTable("flux_agreements", {
|
|
|
4148
4210
|
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
4149
4211
|
.notNull()
|
|
4150
4212
|
.defaultNow(),
|
|
4213
|
+
hubspotPropertySyncedAt: timestamp("hubspot_property_synced_at", {
|
|
4214
|
+
withTimezone: true,
|
|
4215
|
+
}),
|
|
4151
4216
|
}, (table) => ({
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4217
|
+
idxTierLifecycle: index("idx_flux_agreements_tier_lifecycle")
|
|
4218
|
+
.on(table.tier, table.lifecycleStatus)
|
|
4219
|
+
.where(sql `${table.lifecycleStatus} IS NOT NULL`),
|
|
4220
|
+
idxHubspotCompany: index("idx_flux_agreements_hubspot_company")
|
|
4221
|
+
.on(table.hubspotCompanyId)
|
|
4222
|
+
.where(sql `${table.hubspotCompanyId} IS NOT NULL`),
|
|
4223
|
+
idxParent: index("idx_flux_agreements_parent")
|
|
4224
|
+
.on(table.parentAgreementId)
|
|
4225
|
+
.where(sql `${table.parentAgreementId} IS NOT NULL`),
|
|
4226
|
+
idxCompassContract: index("idx_flux_agreements_compass_contract")
|
|
4227
|
+
.on(table.compassContractId)
|
|
4228
|
+
.where(sql `${table.compassContractId} IS NOT NULL`),
|
|
4229
|
+
idxCompassOrder: index("idx_flux_agreements_compass_order")
|
|
4230
|
+
.on(table.compassOrderId)
|
|
4231
|
+
.where(sql `${table.compassOrderId} IS NOT NULL`),
|
|
4232
|
+
idxSigningPending: index("idx_flux_agreements_signing_pending")
|
|
4233
|
+
.on(table.signingStatus)
|
|
4234
|
+
.where(sql `${table.signingStatus} IN ('pending_internal', 'pending_client', 'pending_countersign')`),
|
|
4235
|
+
idxExpiring: index("idx_flux_agreements_expiring")
|
|
4236
|
+
.on(table.expirationDate)
|
|
4237
|
+
.where(sql `${table.lifecycleStatus} IN ('active', 'expiring_soon')`),
|
|
4238
|
+
idxVersionChain: index("idx_flux_agreements_version_chain")
|
|
4239
|
+
.on(table.previousVersionId)
|
|
4240
|
+
.where(sql `${table.previousVersionId} IS NOT NULL`),
|
|
4241
|
+
idxUnlinkedIos: index("idx_flux_agreements_unlinked_ios")
|
|
4242
|
+
.on(table.tier, table.signingStatus, table.createdAt)
|
|
4243
|
+
.where(sql `${table.tier} = 'io' AND ${table.parentAgreementId} IS NULL AND ${table.standaloneConfirmedAt} IS NULL`),
|
|
4244
|
+
idxPendingHint: index("idx_flux_agreements_pending_hint")
|
|
4245
|
+
.on(table.pendingCompassContractIdHint)
|
|
4246
|
+
.where(sql `${table.pendingCompassContractIdHint} IS NOT NULL`),
|
|
4247
|
+
uqCompassContract: uniqueIndex("uq_flux_agreements_compass_contract")
|
|
4248
|
+
.on(table.compassContractId)
|
|
4249
|
+
.where(sql `${table.compassContractId} IS NOT NULL`),
|
|
4250
|
+
uqCompassOrder: uniqueIndex("uq_flux_agreements_compass_order")
|
|
4251
|
+
.on(table.compassOrderId)
|
|
4252
|
+
.where(sql `${table.compassOrderId} IS NOT NULL`),
|
|
4160
4253
|
}));
|
|
4161
4254
|
export const fluxAgreementsRelations = relations(fluxAgreements, ({ one, many }) => ({
|
|
4162
4255
|
project: one(fluxProjects, {
|
|
4163
4256
|
fields: [fluxAgreements.projectId],
|
|
4164
4257
|
references: [fluxProjects.id],
|
|
4165
4258
|
}),
|
|
4166
|
-
deal: one(fluxDealPipeline, {
|
|
4167
|
-
fields: [fluxAgreements.dealId],
|
|
4168
|
-
references: [fluxDealPipeline.id],
|
|
4169
|
-
}),
|
|
4170
4259
|
fulfillmentTicket: one(fluxFulfillmentTickets, {
|
|
4171
4260
|
fields: [fluxAgreements.fulfillmentTicketId],
|
|
4172
4261
|
references: [fluxFulfillmentTickets.id],
|
|
@@ -4174,15 +4263,24 @@ export const fluxAgreementsRelations = relations(fluxAgreements, ({ one, many })
|
|
|
4174
4263
|
previousVersion: one(fluxAgreements, {
|
|
4175
4264
|
fields: [fluxAgreements.previousVersionId],
|
|
4176
4265
|
references: [fluxAgreements.id],
|
|
4266
|
+
relationName: "versionChain",
|
|
4267
|
+
}),
|
|
4268
|
+
parentAgreement: one(fluxAgreements, {
|
|
4269
|
+
fields: [fluxAgreements.parentAgreementId],
|
|
4270
|
+
references: [fluxAgreements.id],
|
|
4271
|
+
relationName: "parentChild",
|
|
4177
4272
|
}),
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
references: [fluxMasterContracts.id],
|
|
4273
|
+
childAgreements: many(fluxAgreements, {
|
|
4274
|
+
relationName: "parentChild",
|
|
4181
4275
|
}),
|
|
4182
4276
|
createdBy: one(fluxUsers, {
|
|
4183
4277
|
fields: [fluxAgreements.createdById],
|
|
4184
4278
|
references: [fluxUsers.id],
|
|
4185
4279
|
}),
|
|
4280
|
+
standaloneConfirmedBy: one(fluxUsers, {
|
|
4281
|
+
fields: [fluxAgreements.standaloneConfirmedByUserId],
|
|
4282
|
+
references: [fluxUsers.id],
|
|
4283
|
+
}),
|
|
4186
4284
|
signers: many(fluxAgreementSigners),
|
|
4187
4285
|
activity: many(fluxAgreementActivity),
|
|
4188
4286
|
comments: many(fluxAgreementComments),
|
|
@@ -4191,6 +4289,7 @@ export const fluxAgreementsRelations = relations(fluxAgreements, ({ one, many })
|
|
|
4191
4289
|
approvalRuns: many(fluxAgreementApprovalRuns),
|
|
4192
4290
|
esignRuns: many(fluxAgreementEsignRuns),
|
|
4193
4291
|
lifecycleEvents: many(fluxAgreementLifecycleEvents),
|
|
4292
|
+
agreementEvents: many(fluxAgreementEvents),
|
|
4194
4293
|
}));
|
|
4195
4294
|
/**
|
|
4196
4295
|
* Agreement signers — tracks each signer in the signing workflow.
|
|
@@ -4276,7 +4375,7 @@ export const fluxAgreementActivityRelations = relations(fluxAgreementActivity, (
|
|
|
4276
4375
|
*/
|
|
4277
4376
|
export const fluxEsignConfig = pgTable("flux_esign_config", {
|
|
4278
4377
|
id: text("id").primaryKey().default(sql `gen_random_uuid()::text`),
|
|
4279
|
-
tier:
|
|
4378
|
+
tier: fluxAgreementTier("tier").notNull().unique(),
|
|
4280
4379
|
firmaTemplateId: text("firma_template_id"),
|
|
4281
4380
|
defaultVpSignerIds: text("default_vp_signer_ids")
|
|
4282
4381
|
.array()
|
|
@@ -4558,6 +4657,40 @@ export const fluxTapclicksPacing = pgTable("flux_tapclicks_pacing", {
|
|
|
4558
4657
|
clientNameIdx: index("flux_tapclicks_pacing_client_idx").on(table.clientName),
|
|
4559
4658
|
endDateIdx: index("flux_tapclicks_pacing_end_date_idx").on(table.endDate),
|
|
4560
4659
|
}));
|
|
4660
|
+
/**
|
|
4661
|
+
* TapClicks Full Order Archive — Complete raw snapshots of every order
|
|
4662
|
+
* including nested line_items, attributes, flights, and task_attributes.
|
|
4663
|
+
* Used as migration reference for Compass and historical audit trail.
|
|
4664
|
+
* Key fields extracted for indexing; full detail preserved in raw_json.
|
|
4665
|
+
*/
|
|
4666
|
+
export const fluxTapclicksArchive = pgTable("flux_tapclicks_archive", {
|
|
4667
|
+
id: serial("id").primaryKey(),
|
|
4668
|
+
tapId: integer("tap_id").notNull(),
|
|
4669
|
+
orderName: text("order_name"),
|
|
4670
|
+
clientName: text("client_name"),
|
|
4671
|
+
clientTapId: integer("client_tap_id"),
|
|
4672
|
+
salesRep: text("sales_rep"),
|
|
4673
|
+
status: text("status"),
|
|
4674
|
+
workflowStep: text("workflow_step"),
|
|
4675
|
+
orderType: text("order_type"),
|
|
4676
|
+
totalBudget: numeric("total_budget", { precision: 12, scale: 2 }),
|
|
4677
|
+
startDate: date("start_date"),
|
|
4678
|
+
endDate: date("end_date"),
|
|
4679
|
+
lineItemCount: integer("line_item_count"),
|
|
4680
|
+
dfpOrderId: text("dfp_order_id"),
|
|
4681
|
+
rawJson: jsonb("raw_json").notNull(),
|
|
4682
|
+
tapCreatedAt: timestamp("tap_created_at", { withTimezone: true }),
|
|
4683
|
+
tapUpdatedAt: timestamp("tap_updated_at", { withTimezone: true }),
|
|
4684
|
+
archivedAt: timestamp("archived_at", { withTimezone: true })
|
|
4685
|
+
.notNull()
|
|
4686
|
+
.defaultNow(),
|
|
4687
|
+
}, (table) => ({
|
|
4688
|
+
tapIdIdx: uniqueIndex("flux_tapclicks_archive_tap_id_idx").on(table.tapId),
|
|
4689
|
+
statusIdx: index("flux_tapclicks_archive_status_idx").on(table.status),
|
|
4690
|
+
clientNameIdx: index("flux_tapclicks_archive_client_idx").on(table.clientName),
|
|
4691
|
+
startDateIdx: index("flux_tapclicks_archive_start_date_idx").on(table.startDate),
|
|
4692
|
+
workflowStepIdx: index("flux_tapclicks_archive_workflow_idx").on(table.workflowStep),
|
|
4693
|
+
}));
|
|
4561
4694
|
// =============================================================================
|
|
4562
4695
|
// CREATIVE–DELIVERY CORRELATION (Initiative 5: True North Intelligence)
|
|
4563
4696
|
// =============================================================================
|
|
@@ -4772,118 +4905,114 @@ export const fluxSimplifiPacing = pgTable("flux_simplifi_pacing", {
|
|
|
4772
4905
|
endDateIdx: index("flux_simplifi_pacing_end_date_idx").on(table.endDate),
|
|
4773
4906
|
}));
|
|
4774
4907
|
// ============================================================================
|
|
4775
|
-
//
|
|
4908
|
+
// AGREEMENT SUPPORTING TABLES — Events, Inbound Dedupe, Versions, Chunks
|
|
4776
4909
|
// ============================================================================
|
|
4777
4910
|
/**
|
|
4778
|
-
*
|
|
4911
|
+
* flux_agreement_events — Internal audit log of every state change on a
|
|
4912
|
+
* flux_agreements row. Written within the same transaction as the
|
|
4913
|
+
* mutation via the agreement repository. Consumed by P4 risk scoring
|
|
4914
|
+
* and P5 alerting.
|
|
4779
4915
|
*/
|
|
4780
|
-
export const
|
|
4781
|
-
"
|
|
4782
|
-
"
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
"
|
|
4786
|
-
"
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4916
|
+
export const fluxAgreementEvents = pgTable("flux_agreement_events", {
|
|
4917
|
+
id: bigserial("id", { mode: "number" }).primaryKey(),
|
|
4918
|
+
agreementId: text("agreement_id")
|
|
4919
|
+
.notNull()
|
|
4920
|
+
.references(() => fluxAgreements.id),
|
|
4921
|
+
eventType: text("event_type").notNull(),
|
|
4922
|
+
previousValue: text("previous_value"),
|
|
4923
|
+
newValue: text("new_value"),
|
|
4924
|
+
actorUserId: text("actor_user_id").references(() => fluxUsers.id),
|
|
4925
|
+
reason: text("reason"),
|
|
4926
|
+
emittedAt: timestamp("emitted_at", { withTimezone: true })
|
|
4927
|
+
.notNull()
|
|
4928
|
+
.defaultNow(),
|
|
4929
|
+
}, (table) => ({
|
|
4930
|
+
byAgreementIdx: index("idx_flux_agreement_events_by_agreement").on(table.agreementId, table.emittedAt),
|
|
4931
|
+
byTypeIdx: index("idx_flux_agreement_events_by_type").on(table.eventType, table.emittedAt),
|
|
4932
|
+
}));
|
|
4933
|
+
export const fluxAgreementEventsRelations = relations(fluxAgreementEvents, ({ one }) => ({
|
|
4934
|
+
agreement: one(fluxAgreements, {
|
|
4935
|
+
fields: [fluxAgreementEvents.agreementId],
|
|
4936
|
+
references: [fluxAgreements.id],
|
|
4937
|
+
}),
|
|
4938
|
+
actor: one(fluxUsers, {
|
|
4939
|
+
fields: [fluxAgreementEvents.actorUserId],
|
|
4940
|
+
references: [fluxUsers.id],
|
|
4941
|
+
}),
|
|
4942
|
+
}));
|
|
4792
4943
|
/**
|
|
4793
|
-
*
|
|
4944
|
+
* flux_inbound_events — Dedupe log for events received from external
|
|
4945
|
+
* sources (Compass). Used by the legacy-event-ingest handlers to
|
|
4946
|
+
* gracefully skip retried events without double-processing. 30-day
|
|
4947
|
+
* retention via a prune cron (not in this schema; lives in fn-flux).
|
|
4794
4948
|
*/
|
|
4795
|
-
export const
|
|
4796
|
-
"
|
|
4797
|
-
"
|
|
4798
|
-
|
|
4949
|
+
export const fluxInboundEvents = pgTable("flux_inbound_events", {
|
|
4950
|
+
eventId: text("event_id").primaryKey(),
|
|
4951
|
+
source: text("source").notNull(),
|
|
4952
|
+
eventType: text("event_type").notNull(),
|
|
4953
|
+
receivedAt: timestamp("received_at", { withTimezone: true })
|
|
4954
|
+
.notNull()
|
|
4955
|
+
.defaultNow(),
|
|
4956
|
+
processingResult: text("processing_result").notNull().default("pending"),
|
|
4957
|
+
processingError: text("processing_error"),
|
|
4958
|
+
});
|
|
4799
4959
|
/**
|
|
4800
|
-
*
|
|
4801
|
-
*
|
|
4960
|
+
* flux_outbound_events — Outbox for events Flux sends to external systems
|
|
4961
|
+
* (currently only Compass at POST /flux-contract-events). The agreement
|
|
4962
|
+
* repository enqueues rows in the same transaction as the state mutation,
|
|
4963
|
+
* and a cron worker delivers them with exponential backoff + HMAC signing.
|
|
4964
|
+
*
|
|
4965
|
+
* Design goals:
|
|
4966
|
+
* - At-least-once delivery (cron retries until success or max attempts)
|
|
4967
|
+
* - Transactional consistency with the underlying mutation (if the tx rolls
|
|
4968
|
+
* back, the outbox row rolls back too — no phantom events)
|
|
4969
|
+
* - Idempotent on the receiver side via the stable event_id
|
|
4970
|
+
* - Observable: last_error + attempts for operator debugging
|
|
4971
|
+
*
|
|
4972
|
+
* Retention: delivered rows older than 7 days are pruned by a cron;
|
|
4973
|
+
* failed rows are kept indefinitely for forensic investigation.
|
|
4802
4974
|
*/
|
|
4803
|
-
export const
|
|
4975
|
+
export const fluxOutboundEvents = pgTable("flux_outbound_events", {
|
|
4804
4976
|
id: text("id").primaryKey().default(sql `gen_random_uuid()::text`),
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
status: fluxMasterContractStatusEnum("status").notNull().default("draft"),
|
|
4817
|
-
tags: text("tags")
|
|
4818
|
-
.array()
|
|
4819
|
-
.default(sql `'{}'::text[]`),
|
|
4820
|
-
customFields: jsonb("custom_fields").default({}),
|
|
4821
|
-
notes: text("notes"),
|
|
4822
|
-
documentUrl: text("document_url"),
|
|
4823
|
-
documentFileName: text("document_file_name"),
|
|
4824
|
-
documentStorageKey: text("document_storage_key"),
|
|
4825
|
-
riskScore: integer("risk_score"),
|
|
4826
|
-
riskIndicators: jsonb("risk_indicators").default([]),
|
|
4827
|
-
// Financial fields — Phase: Contract Financial Alignment
|
|
4828
|
-
tierCode: text("tier_code"), // tier_1 | tier_2 | tier_3 | open
|
|
4829
|
-
rateCard: jsonb("rate_card"), // [{ stribProductId?, familyCode?, categoryCode?, rate, rateNotes? }]
|
|
4830
|
-
productAllocations: jsonb("product_allocations"), // [{ familyCode, familyName, planned, notes? }]
|
|
4831
|
-
billingCadence: text("billing_cadence"), // monthly | quarterly | annual
|
|
4832
|
-
termsUrl: text("terms_url"),
|
|
4833
|
-
termsAddendum: text("terms_addendum"),
|
|
4834
|
-
allocatedAmount: numeric("allocated_amount", { precision: 14, scale: 2 }),
|
|
4835
|
-
remainingAmount: numeric("remaining_amount", { precision: 14, scale: 2 }),
|
|
4836
|
-
projectedMarginPct: real("projected_margin_pct"),
|
|
4837
|
-
projectedMarginDollars: numeric("projected_margin_dollars", { precision: 14, scale: 2 }),
|
|
4838
|
-
actualMarginPct: real("actual_margin_pct"),
|
|
4839
|
-
actualMarginDollars: numeric("actual_margin_dollars", { precision: 14, scale: 2 }),
|
|
4840
|
-
valueAddTotal: numeric("value_add_total", { precision: 14, scale: 2 }),
|
|
4841
|
-
fluxVelocityProfileId: text("flux_velocity_profile_id"),
|
|
4842
|
-
customSlaDays: integer("custom_sla_days"),
|
|
4843
|
-
customWarnDays: integer("custom_warn_days"),
|
|
4844
|
-
customBlockDays: integer("custom_block_days"),
|
|
4845
|
-
orderCount: integer("order_count"),
|
|
4846
|
-
createdById: text("created_by_id").references(() => fluxUsers.id),
|
|
4847
|
-
projectId: text("project_id").references(() => fluxProjects.id),
|
|
4848
|
-
hubspotCompanyId: text("hubspot_company_id"),
|
|
4977
|
+
/** Stable event identifier used by the receiver for dedupe */
|
|
4978
|
+
eventId: text("event_id").notNull().unique(),
|
|
4979
|
+
/** 'compass' | 'hubspot' | future destinations */
|
|
4980
|
+
destination: text("destination").notNull(),
|
|
4981
|
+
/** Event type (e.g. 'contract.created', 'contract.updated') */
|
|
4982
|
+
eventType: text("event_type").notNull(),
|
|
4983
|
+
/** Optional FK-ish link to the agreement that triggered the event */
|
|
4984
|
+
fluxAgreementId: text("flux_agreement_id"),
|
|
4985
|
+
/** Full JSON payload posted to the receiver */
|
|
4986
|
+
payload: jsonb("payload").notNull(),
|
|
4987
|
+
/** When the row was created (same tx as the state mutation) */
|
|
4849
4988
|
createdAt: timestamp("created_at", { withTimezone: true })
|
|
4850
4989
|
.notNull()
|
|
4851
4990
|
.defaultNow(),
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4991
|
+
/** When the event was successfully delivered (NULL until confirmed 2xx) */
|
|
4992
|
+
deliveredAt: timestamp("delivered_at", { withTimezone: true }),
|
|
4993
|
+
/** Delivery attempt count — used for exponential backoff */
|
|
4994
|
+
attempts: integer("attempts").notNull().default(0),
|
|
4995
|
+
/** Last error string from a failed delivery attempt */
|
|
4996
|
+
lastError: text("last_error"),
|
|
4997
|
+
/** When the next retry should fire (NULL = ready now, past = retry overdue) */
|
|
4998
|
+
nextRetryAt: timestamp("next_retry_at", { withTimezone: true }),
|
|
4855
4999
|
}, (table) => ({
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
})
|
|
4862
|
-
export const fluxMasterContractsRelations = relations(fluxMasterContracts, ({ one, many }) => ({
|
|
4863
|
-
createdBy: one(fluxUsers, {
|
|
4864
|
-
fields: [fluxMasterContracts.createdById],
|
|
4865
|
-
references: [fluxUsers.id],
|
|
4866
|
-
}),
|
|
4867
|
-
project: one(fluxProjects, {
|
|
4868
|
-
fields: [fluxMasterContracts.projectId],
|
|
4869
|
-
references: [fluxProjects.id],
|
|
4870
|
-
}),
|
|
4871
|
-
childAgreements: many(fluxAgreements),
|
|
4872
|
-
versions: many(fluxContractVersions),
|
|
4873
|
-
pacing: many(fluxContractPacing),
|
|
4874
|
-
comments: many(fluxAgreementComments),
|
|
5000
|
+
pendingIdx: index("idx_flux_outbound_events_pending")
|
|
5001
|
+
.on(table.destination, table.nextRetryAt)
|
|
5002
|
+
.where(sql `${table.deliveredAt} IS NULL`),
|
|
5003
|
+
agreementIdx: index("idx_flux_outbound_events_agreement")
|
|
5004
|
+
.on(table.fluxAgreementId)
|
|
5005
|
+
.where(sql `${table.fluxAgreementId} IS NOT NULL`),
|
|
4875
5006
|
}));
|
|
4876
5007
|
/**
|
|
4877
|
-
* flux_contract_versions — Document version history for
|
|
5008
|
+
* flux_contract_versions — Document version history for agreements.
|
|
4878
5009
|
* Each revision stored as a separate R2 key with version number.
|
|
4879
5010
|
*/
|
|
4880
5011
|
export const fluxContractVersions = pgTable("flux_contract_versions", {
|
|
4881
5012
|
id: text("id").primaryKey().default(sql `gen_random_uuid()::text`),
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
contractId: text("contract_id").notNull(),
|
|
4886
|
-
contractType: fluxContractSourceTypeEnum("contract_type").notNull(),
|
|
5013
|
+
agreementId: text("agreement_id")
|
|
5014
|
+
.notNull()
|
|
5015
|
+
.references(() => fluxAgreements.id, { onDelete: "cascade" }),
|
|
4887
5016
|
version: integer("version").notNull(),
|
|
4888
5017
|
storageKey: text("storage_key").notNull(),
|
|
4889
5018
|
fileName: text("file_name").notNull(),
|
|
@@ -4893,25 +5022,28 @@ export const fluxContractVersions = pgTable("flux_contract_versions", {
|
|
|
4893
5022
|
.notNull()
|
|
4894
5023
|
.defaultNow(),
|
|
4895
5024
|
}, (table) => ({
|
|
4896
|
-
contractIdx: index("flux_contract_versions_contract_idx").on(table.
|
|
4897
|
-
versionIdx: uniqueIndex("flux_contract_versions_unique_idx").on(table.
|
|
5025
|
+
contractIdx: index("flux_contract_versions_contract_idx").on(table.agreementId),
|
|
5026
|
+
versionIdx: uniqueIndex("flux_contract_versions_unique_idx").on(table.agreementId, table.version),
|
|
4898
5027
|
}));
|
|
4899
5028
|
export const fluxContractVersionsRelations = relations(fluxContractVersions, ({ one }) => ({
|
|
5029
|
+
agreement: one(fluxAgreements, {
|
|
5030
|
+
fields: [fluxContractVersions.agreementId],
|
|
5031
|
+
references: [fluxAgreements.id],
|
|
5032
|
+
}),
|
|
4900
5033
|
uploadedBy: one(fluxUsers, {
|
|
4901
5034
|
fields: [fluxContractVersions.uploadedById],
|
|
4902
5035
|
references: [fluxUsers.id],
|
|
4903
5036
|
}),
|
|
4904
5037
|
}));
|
|
4905
5038
|
/**
|
|
4906
|
-
* flux_agreement_comments — Threaded comments on agreements
|
|
5039
|
+
* flux_agreement_comments — Threaded comments on agreements.
|
|
4907
5040
|
* Supports clause references (page, paragraph, quote) for negotiation tracking.
|
|
4908
5041
|
*/
|
|
4909
5042
|
export const fluxAgreementComments = pgTable("flux_agreement_comments", {
|
|
4910
5043
|
id: text("id").primaryKey().default(sql `gen_random_uuid()::text`),
|
|
4911
|
-
agreementId: text("agreement_id")
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
contractId: text("contract_id").references(() => fluxMasterContracts.id, {
|
|
5044
|
+
agreementId: text("agreement_id")
|
|
5045
|
+
.notNull()
|
|
5046
|
+
.references(() => fluxAgreements.id, {
|
|
4915
5047
|
onDelete: "cascade",
|
|
4916
5048
|
}),
|
|
4917
5049
|
authorId: text("author_id").references(() => fluxUsers.id),
|
|
@@ -4924,7 +5056,6 @@ export const fluxAgreementComments = pgTable("flux_agreement_comments", {
|
|
|
4924
5056
|
.defaultNow(),
|
|
4925
5057
|
}, (table) => ({
|
|
4926
5058
|
agreementIdx: index("flux_agreement_comments_agreement_idx").on(table.agreementId),
|
|
4927
|
-
contractIdx: index("flux_agreement_comments_contract_idx").on(table.contractId),
|
|
4928
5059
|
parentIdx: index("flux_agreement_comments_parent_idx").on(table.parentCommentId),
|
|
4929
5060
|
}));
|
|
4930
5061
|
export const fluxAgreementCommentsRelations = relations(fluxAgreementComments, ({ one, many }) => ({
|
|
@@ -4932,10 +5063,6 @@ export const fluxAgreementCommentsRelations = relations(fluxAgreementComments, (
|
|
|
4932
5063
|
fields: [fluxAgreementComments.agreementId],
|
|
4933
5064
|
references: [fluxAgreements.id],
|
|
4934
5065
|
}),
|
|
4935
|
-
contract: one(fluxMasterContracts, {
|
|
4936
|
-
fields: [fluxAgreementComments.contractId],
|
|
4937
|
-
references: [fluxMasterContracts.id],
|
|
4938
|
-
}),
|
|
4939
5066
|
author: one(fluxUsers, {
|
|
4940
5067
|
fields: [fluxAgreementComments.authorId],
|
|
4941
5068
|
references: [fluxUsers.id],
|
|
@@ -4950,14 +5077,15 @@ export const fluxAgreementCommentsRelations = relations(fluxAgreementComments, (
|
|
|
4950
5077
|
}),
|
|
4951
5078
|
}));
|
|
4952
5079
|
/**
|
|
4953
|
-
* flux_contract_chunks — pgvector-indexed
|
|
5080
|
+
* flux_contract_chunks — pgvector-indexed agreement content for AI search.
|
|
4954
5081
|
* Embeddings via OpenAI text-embedding-3-large (1536 dimensions).
|
|
4955
5082
|
* Hybrid search: vector cosine + FTS via websearch_to_tsquery.
|
|
4956
5083
|
*/
|
|
4957
5084
|
export const fluxContractChunks = pgTable("flux_contract_chunks", {
|
|
4958
5085
|
id: text("id").primaryKey().default(sql `gen_random_uuid()::text`),
|
|
4959
|
-
|
|
4960
|
-
|
|
5086
|
+
agreementId: text("agreement_id")
|
|
5087
|
+
.notNull()
|
|
5088
|
+
.references(() => fluxAgreements.id, { onDelete: "cascade" }),
|
|
4961
5089
|
chunkIndex: integer("chunk_index").notNull(),
|
|
4962
5090
|
chunkText: text("chunk_text").notNull(),
|
|
4963
5091
|
embedding: vector("embedding", { dimensions: 1536 }),
|
|
@@ -4966,7 +5094,7 @@ export const fluxContractChunks = pgTable("flux_contract_chunks", {
|
|
|
4966
5094
|
.notNull()
|
|
4967
5095
|
.defaultNow(),
|
|
4968
5096
|
}, (table) => ({
|
|
4969
|
-
contractIdx: index("flux_contract_chunks_contract_idx").on(table.
|
|
5097
|
+
contractIdx: index("flux_contract_chunks_contract_idx").on(table.agreementId),
|
|
4970
5098
|
metadataIdx: index("flux_contract_chunks_metadata_idx")
|
|
4971
5099
|
.using("gin", table.metadata),
|
|
4972
5100
|
}));
|
|
@@ -4988,68 +5116,6 @@ export const fluxContractPolicyChunks = pgTable("flux_contract_policy_chunks", {
|
|
|
4988
5116
|
}, (table) => ({
|
|
4989
5117
|
policyIdx: index("flux_contract_policy_chunks_policy_idx").on(table.policyName),
|
|
4990
5118
|
}));
|
|
4991
|
-
/**
|
|
4992
|
-
* flux_contract_pacing — Computed drawdown pacing per active master contract.
|
|
4993
|
-
* Mirrors flux_tapclicks_pacing pattern: velocity, trend, anomaly, status.
|
|
4994
|
-
*/
|
|
4995
|
-
export const fluxContractPacing = pgTable("flux_contract_pacing", {
|
|
4996
|
-
id: text("id").primaryKey().default(sql `gen_random_uuid()::text`),
|
|
4997
|
-
contractId: text("contract_id")
|
|
4998
|
-
.notNull()
|
|
4999
|
-
.references(() => fluxMasterContracts.id),
|
|
5000
|
-
pacingStatus: text("pacing_status").notNull(),
|
|
5001
|
-
pacingPercent: numeric("pacing_percent", { precision: 8, scale: 2 }),
|
|
5002
|
-
dailyVelocity: numeric("daily_velocity", { precision: 14, scale: 2 }),
|
|
5003
|
-
velocityTrend: text("velocity_trend"),
|
|
5004
|
-
totalDrawnDown: numeric("total_drawn_down", { precision: 14, scale: 2 }),
|
|
5005
|
-
remainingCapacity: numeric("remaining_capacity", {
|
|
5006
|
-
precision: 14,
|
|
5007
|
-
scale: 2,
|
|
5008
|
-
}),
|
|
5009
|
-
projectedEndSpend: numeric("projected_end_spend", {
|
|
5010
|
-
precision: 14,
|
|
5011
|
-
scale: 2,
|
|
5012
|
-
}),
|
|
5013
|
-
runwayDays: integer("runway_days"),
|
|
5014
|
-
anomalies: jsonb("anomalies").default([]),
|
|
5015
|
-
// ── Contract remainder forecast columns (populated by pacing cron) ──
|
|
5016
|
-
/** Extrapolated margin for unordered remainder (actualMargin - decay) */
|
|
5017
|
-
extrapolatedMarginPct: real("extrapolated_margin_pct"),
|
|
5018
|
-
/** Contract-level confidence score for remainder */
|
|
5019
|
-
forecastConfidence: real("forecast_confidence"),
|
|
5020
|
-
/** Confidence tier for remainder: commit/likely/upside/longshot */
|
|
5021
|
-
forecastConfidenceTier: text("forecast_confidence_tier"),
|
|
5022
|
-
/** Remainder revenue forecasts by window */
|
|
5023
|
-
remainderForecast30d: numeric("remainder_forecast_30d", { precision: 14, scale: 2 }),
|
|
5024
|
-
remainderForecast60d: numeric("remainder_forecast_60d", { precision: 14, scale: 2 }),
|
|
5025
|
-
remainderForecast90d: numeric("remainder_forecast_90d", { precision: 14, scale: 2 }),
|
|
5026
|
-
/** Remainder margin forecasts by window */
|
|
5027
|
-
remainderMarginForecast30d: numeric("remainder_margin_forecast_30d", { precision: 14, scale: 2 }),
|
|
5028
|
-
remainderMarginForecast60d: numeric("remainder_margin_forecast_60d", { precision: 14, scale: 2 }),
|
|
5029
|
-
remainderMarginForecast90d: numeric("remainder_margin_forecast_90d", { precision: 14, scale: 2 }),
|
|
5030
|
-
/** Periods until next expected IO */
|
|
5031
|
-
periodDistance: integer("period_distance"),
|
|
5032
|
-
/** Periods remaining on contract */
|
|
5033
|
-
periodsRemaining: integer("periods_remaining"),
|
|
5034
|
-
computedAt: timestamp("computed_at", { withTimezone: true })
|
|
5035
|
-
.notNull()
|
|
5036
|
-
.defaultNow(),
|
|
5037
|
-
createdAt: timestamp("created_at", { withTimezone: true })
|
|
5038
|
-
.notNull()
|
|
5039
|
-
.defaultNow(),
|
|
5040
|
-
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
5041
|
-
.notNull()
|
|
5042
|
-
.defaultNow(),
|
|
5043
|
-
}, (table) => ({
|
|
5044
|
-
contractIdx: uniqueIndex("flux_contract_pacing_contract_idx").on(table.contractId),
|
|
5045
|
-
statusIdx: index("flux_contract_pacing_status_idx").on(table.pacingStatus),
|
|
5046
|
-
}));
|
|
5047
|
-
export const fluxContractPacingRelations = relations(fluxContractPacing, ({ one }) => ({
|
|
5048
|
-
contract: one(fluxMasterContracts, {
|
|
5049
|
-
fields: [fluxContractPacing.contractId],
|
|
5050
|
-
references: [fluxMasterContracts.id],
|
|
5051
|
-
}),
|
|
5052
|
-
}));
|
|
5053
5119
|
// ---------------------------------------------------------------------------
|
|
5054
5120
|
// Agreement Workspace Tables — graduated from metadata JSONB
|
|
5055
5121
|
// ---------------------------------------------------------------------------
|