@lead-routing/cli 0.2.0 → 0.4.0

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.
@@ -0,0 +1,2 @@
1
+ -- AlterTable: make assignmentType nullable on routing_branches (allows saving unconfigured branches)
2
+ ALTER TABLE "routing_branches" ALTER COLUMN "assignmentType" DROP NOT NULL;
@@ -0,0 +1,6 @@
1
+ -- AlterTable
2
+ ALTER TABLE "organizations" ADD COLUMN "packageDeployedAt" TIMESTAMP(3);
3
+ ALTER TABLE "organizations" ADD COLUMN "packageDeployId" TEXT;
4
+ ALTER TABLE "organizations" ADD COLUMN "packageVersion" TEXT;
5
+ ALTER TABLE "organizations" ADD COLUMN "objectConfig" JSONB;
6
+ ALTER TABLE "organizations" ADD COLUMN "fieldsSyncedAt" TIMESTAMP(3);
@@ -0,0 +1,20 @@
1
+ -- CreateTable
2
+ CREATE TABLE "trigger_conditions" (
3
+ "id" TEXT NOT NULL,
4
+ "ruleId" TEXT NOT NULL,
5
+ "groupId" TEXT NOT NULL,
6
+ "fieldName" TEXT NOT NULL,
7
+ "fieldType" TEXT NOT NULL DEFAULT 'TEXT',
8
+ "operator" TEXT NOT NULL,
9
+ "value" TEXT,
10
+ "sortOrder" INTEGER NOT NULL DEFAULT 0,
11
+
12
+ CONSTRAINT "trigger_conditions_pkey" PRIMARY KEY ("id")
13
+ );
14
+
15
+ -- AddForeignKey
16
+ ALTER TABLE "trigger_conditions" ADD CONSTRAINT "trigger_conditions_ruleId_fkey" FOREIGN KEY ("ruleId") REFERENCES "routing_rules"("id") ON DELETE CASCADE ON UPDATE CASCADE;
17
+
18
+ -- AlterTable: add criteriaSyncedAt and triggerName to routing_rules
19
+ ALTER TABLE "routing_rules" ADD COLUMN "criteriaSyncedAt" TIMESTAMP(3);
20
+ ALTER TABLE "routing_rules" ADD COLUMN "triggerName" TEXT NOT NULL DEFAULT '';
@@ -0,0 +1,7 @@
1
+ -- AlterTable
2
+ ALTER TABLE "organizations" ADD COLUMN "aiProvider" TEXT;
3
+ ALTER TABLE "organizations" ADD COLUMN "aiApiKey" TEXT;
4
+ ALTER TABLE "organizations" ADD COLUMN "aiModelName" TEXT;
5
+ ALTER TABLE "organizations" ADD COLUMN "aiBaseUrl" TEXT;
6
+ ALTER TABLE "organizations" ADD COLUMN "aiCustomHeaders" JSONB;
7
+ ALTER TABLE "organizations" ADD COLUMN "aiChatCount" INTEGER NOT NULL DEFAULT 0;
@@ -0,0 +1,26 @@
1
+ -- AlterTable: add fuzzy matching columns to route_match_configs
2
+ ALTER TABLE "route_match_configs" ADD COLUMN "matchCompanyName" BOOLEAN NOT NULL DEFAULT false;
3
+ ALTER TABLE "route_match_configs" ADD COLUMN "fuzzyMatchMode" TEXT NOT NULL DEFAULT 'STRICT';
4
+
5
+ -- CreateTable: company_aliases for caching AI similarity results
6
+ CREATE TABLE "company_aliases" (
7
+ "id" TEXT NOT NULL,
8
+ "orgId" TEXT NOT NULL,
9
+ "nameA" TEXT NOT NULL,
10
+ "nameB" TEXT NOT NULL,
11
+ "isSimilar" BOOLEAN NOT NULL,
12
+ "confidence" DOUBLE PRECISION,
13
+ "source" TEXT NOT NULL DEFAULT 'AI',
14
+ "hitCount" INTEGER NOT NULL DEFAULT 1,
15
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
16
+ "updatedAt" TIMESTAMP(3) NOT NULL,
17
+ CONSTRAINT "company_aliases_pkey" PRIMARY KEY ("id")
18
+ );
19
+
20
+ -- CreateIndex
21
+ CREATE UNIQUE INDEX "company_aliases_orgId_nameA_nameB_key" ON "company_aliases"("orgId", "nameA", "nameB");
22
+ CREATE INDEX "company_aliases_orgId_nameA_idx" ON "company_aliases"("orgId", "nameA");
23
+ CREATE INDEX "company_aliases_orgId_nameB_idx" ON "company_aliases"("orgId", "nameB");
24
+
25
+ -- AddForeignKey
26
+ ALTER TABLE "company_aliases" ADD CONSTRAINT "company_aliases_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,3 @@
1
+ # Please do not edit this file manually
2
+ # It should be added in your version-control system (i.e. Git)
3
+ provider = "postgresql"
@@ -78,6 +78,12 @@ model Organization {
78
78
  oauthAccessToken String? // null until CRM is connected
79
79
  oauthRefreshToken String? // null until CRM is connected
80
80
  webhookSecret String // HMAC secret for verifying Apex trigger payloads
81
+ // Integration / package deploy tracking
82
+ packageDeployedAt DateTime?
83
+ packageDeployId String?
84
+ packageVersion String?
85
+ objectConfig Json? // e.g. { "Lead": { enabled: true }, "Contact": { enabled: true } }
86
+ fieldsSyncedAt DateTime?
81
87
  plan Plan @default(FREE)
82
88
  isActive Boolean @default(true)
83
89
  seatsPurchased Int @default(5)
@@ -86,6 +92,13 @@ model Organization {
86
92
  quotaResetAt DateTime @default(now())
87
93
  onboardingDone Boolean @default(false)
88
94
  notificationWebhookUrl String?
95
+ // AI Assistant (Pro feature)
96
+ aiProvider String? // "claude" | "openai" | "gemini" | "custom"
97
+ aiApiKey String? // AES-256-GCM encrypted
98
+ aiModelName String? // e.g. "claude-sonnet-4-5-20250514", "gpt-4o"
99
+ aiBaseUrl String? // custom endpoint URL (null = default)
100
+ aiCustomHeaders Json? // custom headers for self-hosted proxies
101
+ aiChatCount Int @default(0)
89
102
  createdAt DateTime @default(now())
90
103
  updatedAt DateTime @updatedAt
91
104
 
@@ -101,6 +114,7 @@ model Organization {
101
114
  billingInfo BillingInfo?
102
115
  routingDailyAggregates RoutingDailyAggregate[]
103
116
  conversionTracking ConversionTracking[]
117
+ companyAliases CompanyAlias[]
104
118
 
105
119
  @@map("organizations")
106
120
  }
@@ -152,8 +166,10 @@ model User {
152
166
  createdAt DateTime @default(now())
153
167
  updatedAt DateTime @updatedAt
154
168
 
155
- org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
156
- teamMemberships TeamMember[]
169
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
170
+ teamMemberships TeamMember[]
171
+ branchAssignments RoutingBranch[] @relation("BranchAssigneeUser")
172
+ defaultOwnerRules RoutingRule[] @relation("DefaultOwnerUser")
157
173
 
158
174
  @@unique([orgId, sfdcUserId])
159
175
  @@map("users")
@@ -168,9 +184,11 @@ model RoundRobinTeam {
168
184
  createdAt DateTime @default(now())
169
185
  updatedAt DateTime @updatedAt
170
186
 
171
- org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
172
- members TeamMember[]
173
- routingRules RoutingRule[] @relation("TeamRules")
187
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
188
+ members TeamMember[]
189
+ routingRules RoutingRule[] @relation("TeamRules")
190
+ branchAssignments RoutingBranch[] @relation("BranchAssigneeTeam")
191
+ defaultOwnerRules RoutingRule[] @relation("DefaultOwnerTeam")
174
192
 
175
193
  @@map("round_robin_teams")
176
194
  }
@@ -206,6 +224,8 @@ model RoutingRule {
206
224
  assigneeTeamId String? // references RoundRobinTeam.id
207
225
  assigneeQueueId String? // references SfdcQueue.id
208
226
  isDryRun Boolean @default(false)
227
+ triggerName String @default("")
228
+ criteriaSyncedAt DateTime?
209
229
  // Default owner: absolute catch-all for new Route Builder routes
210
230
  defaultOwnerType AssignmentType?
211
231
  defaultOwnerUserId String?
@@ -214,12 +234,16 @@ model RoutingRule {
214
234
  createdAt DateTime @default(now())
215
235
  updatedAt DateTime @updatedAt
216
236
 
217
- org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
218
- team RoundRobinTeam? @relation("TeamRules", fields: [assigneeTeamId], references: [id])
219
- queue SfdcQueue? @relation(fields: [assigneeQueueId], references: [id])
237
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
238
+ team RoundRobinTeam? @relation("TeamRules", fields: [assigneeTeamId], references: [id])
239
+ queue SfdcQueue? @relation(fields: [assigneeQueueId], references: [id])
240
+ defaultOwnerUser User? @relation("DefaultOwnerUser", fields: [defaultOwnerUserId], references: [id])
241
+ defaultOwnerTeam RoundRobinTeam? @relation("DefaultOwnerTeam", fields: [defaultOwnerTeamId], references: [id])
242
+ defaultOwnerQueue SfdcQueue? @relation("DefaultOwnerQueue", fields: [defaultOwnerQueueId], references: [id])
220
243
  conditions RuleCondition[] // legacy conditions (old-style rules)
221
244
  branches RoutingBranch[] // new Route Builder paths
222
245
  matchConfig RouteMatchConfig?
246
+ triggerConditions TriggerCondition[]
223
247
 
224
248
  @@map("routing_rules")
225
249
  }
@@ -230,10 +254,13 @@ model RoutingBranch {
230
254
  rule RoutingRule @relation(fields: [ruleId], references: [id], onDelete: Cascade)
231
255
  label String?
232
256
  priority Int @default(0)
233
- assignmentType AssignmentType
257
+ assignmentType AssignmentType?
234
258
  assigneeUserId String?
259
+ assigneeUser User? @relation("BranchAssigneeUser", fields: [assigneeUserId], references: [id])
235
260
  assigneeTeamId String?
261
+ assigneeTeam RoundRobinTeam? @relation("BranchAssigneeTeam", fields: [assigneeTeamId], references: [id])
236
262
  assigneeQueueId String?
263
+ assigneeQueue SfdcQueue? @relation("BranchAssigneeQueue", fields: [assigneeQueueId], references: [id])
237
264
  createdAt DateTime @default(now())
238
265
  updatedAt DateTime @updatedAt
239
266
 
@@ -257,6 +284,20 @@ model BranchCondition {
257
284
  @@map("branch_conditions")
258
285
  }
259
286
 
287
+ model TriggerCondition {
288
+ id String @id @default(cuid())
289
+ ruleId String
290
+ rule RoutingRule @relation(fields: [ruleId], references: [id], onDelete: Cascade)
291
+ groupId String
292
+ fieldName String
293
+ fieldType String @default("TEXT")
294
+ operator String
295
+ value String?
296
+ sortOrder Int @default(0)
297
+
298
+ @@map("trigger_conditions")
299
+ }
300
+
260
301
  model RouteMatchConfig {
261
302
  id String @id @default(cuid())
262
303
  ruleId String @unique
@@ -271,6 +312,8 @@ model RouteMatchConfig {
271
312
  matchEmail Boolean @default(true)
272
313
  matchPhone Boolean @default(false)
273
314
  matchDomain Boolean @default(false)
315
+ matchCompanyName Boolean @default(false)
316
+ fuzzyMatchMode String @default("STRICT") // "STRICT" | "FUZZY" | "AI_SMART"
274
317
 
275
318
  // Lead match outcome
276
319
  onLeadMatch LeadMatchAction @default(SFDC_MERGE)
@@ -373,8 +416,10 @@ model SfdcQueue {
373
416
  name String
374
417
  syncedAt DateTime @default(now())
375
418
 
376
- org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
377
- routingRules RoutingRule[]
419
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
420
+ routingRules RoutingRule[]
421
+ branchAssignments RoutingBranch[] @relation("BranchAssigneeQueue")
422
+ defaultOwnerRules RoutingRule[] @relation("DefaultOwnerQueue")
378
423
 
379
424
  @@unique([orgId, sfdcQueueId])
380
425
  @@map("sfdc_queues")
@@ -484,3 +529,23 @@ model ConversionTracking {
484
529
  @@index([orgId, sfdcLeadId])
485
530
  @@map("conversion_tracking")
486
531
  }
532
+
533
+ model CompanyAlias {
534
+ id String @id @default(cuid())
535
+ orgId String
536
+ nameA String // normalized company name A (alphabetically first)
537
+ nameB String // normalized company name B
538
+ isSimilar Boolean // LLM determination
539
+ confidence Float? // LLM confidence score (0-1)
540
+ source String @default("AI") // "AI" | "MANUAL" | "DICTIONARY"
541
+ hitCount Int @default(1)
542
+ createdAt DateTime @default(now())
543
+ updatedAt DateTime @updatedAt
544
+
545
+ org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
546
+
547
+ @@unique([orgId, nameA, nameB])
548
+ @@index([orgId, nameA])
549
+ @@index([orgId, nameB])
550
+ @@map("company_aliases")
551
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lead-routing/cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Self-hosted deployment CLI for Lead Routing",
5
5
  "homepage": "https://github.com/lead-routing/lead-routing",
6
6
  "keywords": [