@classytic/crm 0.1.1 → 0.5.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.
- package/CHANGELOG.md +175 -0
- package/README.md +157 -255
- package/dist/events.d.ts +2 -0
- package/dist/events.js +716 -0
- package/dist/index.d.ts +1332 -1265
- package/dist/index.js +3476 -1606
- package/dist/index2.d.ts +746 -0
- package/dist/rolldown-runtime.js +13 -0
- package/package.json +19 -5
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,374 +1,425 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as mongoose1 from "mongoose";
|
|
2
|
+
import { Connection, Model, Schema, SchemaDefinitionProperty } from "mongoose";
|
|
3
|
+
import { PaginationConfig, PluginType, Repository } from "@classytic/mongokit";
|
|
4
|
+
import { DomainEvent, EventHandler, EventMeta, EventTransport } from "@classytic/primitives/events";
|
|
2
5
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
4
|
-
import { ContactInfo, PersonName } from "@classytic/primitives/person";
|
|
5
|
-
import { Money } from "@classytic/primitives/money";
|
|
6
|
+
import { OperationContext } from "@classytic/primitives/context";
|
|
6
7
|
|
|
7
|
-
//#region src/
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
8
|
+
//#region src/events/event-constants.d.ts
|
|
9
|
+
/** PACKAGE_RULES rule 12: `package:resource.verb`. */
|
|
10
|
+
declare const CRM_EVENTS: {
|
|
11
|
+
readonly LEAD_CREATED: "crm:lead.created";
|
|
12
|
+
readonly LEAD_STATUS_CHANGED: "crm:lead.status_changed";
|
|
13
|
+
readonly LEAD_SCORED: "crm:lead.scored";
|
|
14
|
+
readonly LEAD_CONVERTED: "crm:lead.converted";
|
|
15
|
+
readonly LEAD_DISQUALIFIED: "crm:lead.disqualified";
|
|
16
|
+
readonly ACCOUNT_CREATED: "crm:account.created";
|
|
17
|
+
readonly ACCOUNT_UPDATED: "crm:account.updated";
|
|
18
|
+
readonly CONTACT_CREATED: "crm:contact.created";
|
|
19
|
+
readonly CONTACT_UPDATED: "crm:contact.updated";
|
|
20
|
+
readonly OPPORTUNITY_CREATED: "crm:opportunity.created";
|
|
21
|
+
readonly OPPORTUNITY_STAGE_ADVANCED: "crm:opportunity.stage_advanced";
|
|
22
|
+
readonly OPPORTUNITY_STAGE_REGRESSED: "crm:opportunity.stage_regressed";
|
|
23
|
+
readonly OPPORTUNITY_WON: "crm:opportunity.won";
|
|
24
|
+
readonly OPPORTUNITY_LOST: "crm:opportunity.lost";
|
|
25
|
+
readonly OPPORTUNITY_ABANDONED: "crm:opportunity.abandoned";
|
|
26
|
+
readonly PIPELINE_CREATED: "crm:pipeline.created";
|
|
27
|
+
readonly PIPELINE_ARCHIVED: "crm:pipeline.archived";
|
|
28
|
+
readonly ACTIVITY_PLANNED: "crm:activity.planned";
|
|
29
|
+
readonly ACTIVITY_COMPLETED: "crm:activity.completed";
|
|
30
|
+
readonly ACTIVITY_CANCELLED: "crm:activity.cancelled";
|
|
31
|
+
readonly NOTE_ADDED: "crm:note.added";
|
|
32
|
+
readonly CAMPAIGN_CREATED: "crm:campaign.created";
|
|
33
|
+
readonly CAMPAIGN_ACTIVATED: "crm:campaign.activated";
|
|
34
|
+
readonly CAMPAIGN_PAUSED: "crm:campaign.paused";
|
|
35
|
+
readonly CAMPAIGN_RESUMED: "crm:campaign.resumed";
|
|
36
|
+
readonly CAMPAIGN_COMPLETED: "crm:campaign.completed";
|
|
37
|
+
readonly CAMPAIGN_ARCHIVED: "crm:campaign.archived";
|
|
38
|
+
readonly SUBSCRIPTION_CREATED: "crm:subscription.created";
|
|
39
|
+
readonly SUBSCRIPTION_CONFIRMED: "crm:subscription.confirmed";
|
|
40
|
+
readonly SUBSCRIPTION_UNSUBSCRIBED: "crm:subscription.unsubscribed";
|
|
41
|
+
readonly SUBSCRIPTION_BOUNCED: "crm:subscription.bounced";
|
|
42
|
+
readonly SUBSCRIPTION_COMPLAINED: "crm:subscription.complained";
|
|
43
|
+
readonly EMAIL_EVENT_OPENED: "crm:email_event.opened";
|
|
44
|
+
readonly EMAIL_EVENT_CLICKED: "crm:email_event.clicked";
|
|
45
|
+
readonly EMAIL_EVENT_BOUNCED: "crm:email_event.bounced";
|
|
46
|
+
readonly EMAIL_EVENT_COMPLAINED: "crm:email_event.complained";
|
|
47
|
+
readonly EMAIL_EVENT_UNSUBSCRIBED: "crm:email_event.unsubscribed";
|
|
48
|
+
readonly LEAD_ENRICHED: "crm:lead.enriched";
|
|
49
|
+
readonly LEAD_ASSIGNED: "crm:lead.assigned";
|
|
50
|
+
readonly CONTACT_ENRICHED: "crm:contact.enriched";
|
|
51
|
+
readonly CONTACT_ASSIGNED: "crm:contact.assigned";
|
|
52
|
+
readonly CONTACT_MERGED: "crm:contact.merged";
|
|
53
|
+
readonly ACCOUNT_ENRICHED: "crm:account.enriched";
|
|
54
|
+
readonly ACCOUNT_ASSIGNED: "crm:account.assigned";
|
|
55
|
+
readonly ACCOUNT_MERGED: "crm:account.merged";
|
|
56
|
+
readonly OPPORTUNITY_ASSIGNED: "crm:opportunity.assigned";
|
|
57
|
+
readonly OPPORTUNITY_AMOUNT_CHANGED: "crm:opportunity.amount_changed";
|
|
58
|
+
readonly OPPORTUNITY_EXTENDED: "crm:opportunity.extended";
|
|
59
|
+
readonly ACTIVITY_RESCHEDULED: "crm:activity.rescheduled";
|
|
60
|
+
readonly ACTIVITY_OUTCOME_RECORDED: "crm:activity.outcome_recorded";
|
|
61
|
+
readonly CONVERSATION_CREATED: "crm:conversation.created";
|
|
62
|
+
readonly CONVERSATION_ASSIGNED: "crm:conversation.assigned";
|
|
63
|
+
readonly CONVERSATION_RESOLVED: "crm:conversation.resolved";
|
|
64
|
+
readonly CONVERSATION_REOPENED: "crm:conversation.reopened";
|
|
65
|
+
readonly MESSAGE_RECEIVED: "crm:message.received";
|
|
66
|
+
readonly MESSAGE_SENT: "crm:message.sent";
|
|
67
|
+
};
|
|
68
|
+
type CrmEventName = (typeof CRM_EVENTS)[keyof typeof CRM_EVENTS];
|
|
46
69
|
//#endregion
|
|
47
|
-
//#region src/
|
|
48
|
-
|
|
49
|
-
|
|
70
|
+
//#region src/events/event-catalog.d.ts
|
|
71
|
+
|
|
72
|
+
/** JSON-Schema object produced by `z.toJSONSchema` — what arc's registry consumes. */
|
|
73
|
+
type CrmEventSchema = Record<string, unknown>;
|
|
74
|
+
/** Structurally identical to arc's `EventDefinitionOutput` — do NOT import arc. */
|
|
75
|
+
interface CrmEventDefinition<TSchema extends z.ZodType = z.ZodType> {
|
|
76
|
+
name: CrmEventName;
|
|
77
|
+
version: number;
|
|
78
|
+
description: string;
|
|
79
|
+
zodSchema: TSchema;
|
|
80
|
+
schema: CrmEventSchema;
|
|
81
|
+
create(payload: z.infer<TSchema>, meta?: Partial<EventMeta>): DomainEvent<z.infer<TSchema>>;
|
|
50
82
|
}
|
|
51
|
-
declare const
|
|
83
|
+
declare const LeadCreated: CrmEventDefinition<z.ZodObject<{
|
|
84
|
+
leadId: z.ZodString;
|
|
85
|
+
email: z.ZodOptional<z.ZodString>;
|
|
86
|
+
score: z.ZodNumber;
|
|
87
|
+
}, z.core.$strip>>;
|
|
88
|
+
declare const LeadStatusChanged: CrmEventDefinition<z.ZodObject<{
|
|
89
|
+
leadId: z.ZodString;
|
|
90
|
+
from: z.ZodString;
|
|
91
|
+
to: z.ZodString;
|
|
92
|
+
}, z.core.$strip>>;
|
|
93
|
+
declare const LeadScored: CrmEventDefinition<z.ZodObject<{
|
|
94
|
+
leadId: z.ZodString;
|
|
95
|
+
score: z.ZodNumber;
|
|
96
|
+
}, z.core.$strip>>;
|
|
97
|
+
declare const LeadConverted: CrmEventDefinition<z.ZodObject<{
|
|
98
|
+
leadId: z.ZodString;
|
|
99
|
+
contactId: z.ZodString;
|
|
100
|
+
accountId: z.ZodOptional<z.ZodString>;
|
|
101
|
+
opportunityId: z.ZodString;
|
|
102
|
+
}, z.core.$strip>>;
|
|
103
|
+
declare const LeadDisqualified: CrmEventDefinition<z.ZodObject<{
|
|
104
|
+
leadId: z.ZodString;
|
|
105
|
+
reason: z.ZodString;
|
|
106
|
+
}, z.core.$strip>>;
|
|
107
|
+
declare const LeadEnriched: CrmEventDefinition<z.ZodObject<{
|
|
108
|
+
leadId: z.ZodString;
|
|
109
|
+
fields: z.ZodArray<z.ZodString>;
|
|
110
|
+
provider: z.ZodOptional<z.ZodString>;
|
|
111
|
+
}, z.core.$strip>>;
|
|
112
|
+
declare const LeadAssigned: CrmEventDefinition<z.ZodObject<{
|
|
113
|
+
leadId: z.ZodString;
|
|
114
|
+
ownerId: z.ZodString;
|
|
115
|
+
previousOwnerId: z.ZodOptional<z.ZodString>;
|
|
116
|
+
}, z.core.$strip>>;
|
|
117
|
+
declare const AccountCreated: CrmEventDefinition<z.ZodObject<{
|
|
118
|
+
accountId: z.ZodString;
|
|
119
|
+
name: z.ZodString;
|
|
120
|
+
}, z.core.$strip>>;
|
|
121
|
+
declare const AccountUpdated: CrmEventDefinition<z.ZodObject<{
|
|
122
|
+
accountId: z.ZodString;
|
|
123
|
+
}, z.core.$strip>>;
|
|
124
|
+
declare const AccountEnriched: CrmEventDefinition<z.ZodObject<{
|
|
125
|
+
accountId: z.ZodString;
|
|
126
|
+
fields: z.ZodArray<z.ZodString>;
|
|
127
|
+
provider: z.ZodOptional<z.ZodString>;
|
|
128
|
+
}, z.core.$strip>>;
|
|
129
|
+
declare const AccountAssigned: CrmEventDefinition<z.ZodObject<{
|
|
130
|
+
accountId: z.ZodString;
|
|
131
|
+
ownerId: z.ZodString;
|
|
132
|
+
previousOwnerId: z.ZodOptional<z.ZodString>;
|
|
133
|
+
}, z.core.$strip>>;
|
|
134
|
+
declare const AccountMerged: CrmEventDefinition<z.ZodObject<{
|
|
135
|
+
primaryId: z.ZodString;
|
|
136
|
+
secondaryId: z.ZodString;
|
|
137
|
+
strategy: z.ZodEnum<{
|
|
138
|
+
preferPrimary: "preferPrimary";
|
|
139
|
+
preferSecondary: "preferSecondary";
|
|
140
|
+
}>;
|
|
141
|
+
}, z.core.$strip>>;
|
|
142
|
+
declare const ContactCreated: CrmEventDefinition<z.ZodObject<{
|
|
143
|
+
contactId: z.ZodString;
|
|
144
|
+
email: z.ZodOptional<z.ZodString>;
|
|
145
|
+
}, z.core.$strip>>;
|
|
146
|
+
declare const ContactUpdated: CrmEventDefinition<z.ZodObject<{
|
|
147
|
+
contactId: z.ZodString;
|
|
148
|
+
}, z.core.$strip>>;
|
|
149
|
+
declare const ContactEnriched: CrmEventDefinition<z.ZodObject<{
|
|
150
|
+
contactId: z.ZodString;
|
|
151
|
+
fields: z.ZodArray<z.ZodString>;
|
|
152
|
+
provider: z.ZodOptional<z.ZodString>;
|
|
153
|
+
}, z.core.$strip>>;
|
|
154
|
+
declare const ContactAssigned: CrmEventDefinition<z.ZodObject<{
|
|
155
|
+
contactId: z.ZodString;
|
|
156
|
+
ownerId: z.ZodString;
|
|
157
|
+
previousOwnerId: z.ZodOptional<z.ZodString>;
|
|
158
|
+
}, z.core.$strip>>;
|
|
159
|
+
declare const ContactMerged: CrmEventDefinition<z.ZodObject<{
|
|
160
|
+
primaryId: z.ZodString;
|
|
161
|
+
secondaryId: z.ZodString;
|
|
162
|
+
strategy: z.ZodEnum<{
|
|
163
|
+
preferPrimary: "preferPrimary";
|
|
164
|
+
preferSecondary: "preferSecondary";
|
|
165
|
+
}>;
|
|
166
|
+
}, z.core.$strip>>;
|
|
167
|
+
declare const OpportunityCreated: CrmEventDefinition<z.ZodObject<{
|
|
168
|
+
opportunityId: z.ZodString;
|
|
169
|
+
pipelineId: z.ZodString;
|
|
170
|
+
stageId: z.ZodString;
|
|
171
|
+
}, z.core.$strip>>;
|
|
172
|
+
declare const OpportunityStageAdvanced: CrmEventDefinition<z.ZodObject<{
|
|
173
|
+
opportunityId: z.ZodString;
|
|
174
|
+
from: z.ZodObject<{
|
|
175
|
+
stageId: z.ZodString;
|
|
176
|
+
sequence: z.ZodNumber;
|
|
177
|
+
}, z.core.$strip>;
|
|
178
|
+
to: z.ZodObject<{
|
|
179
|
+
stageId: z.ZodString;
|
|
180
|
+
sequence: z.ZodNumber;
|
|
181
|
+
}, z.core.$strip>;
|
|
182
|
+
}, z.core.$strip>>;
|
|
183
|
+
declare const OpportunityStageRegressed: CrmEventDefinition<z.ZodObject<{
|
|
184
|
+
opportunityId: z.ZodString;
|
|
185
|
+
from: z.ZodObject<{
|
|
186
|
+
stageId: z.ZodString;
|
|
187
|
+
sequence: z.ZodNumber;
|
|
188
|
+
}, z.core.$strip>;
|
|
189
|
+
to: z.ZodObject<{
|
|
190
|
+
stageId: z.ZodString;
|
|
191
|
+
sequence: z.ZodNumber;
|
|
192
|
+
}, z.core.$strip>;
|
|
193
|
+
}, z.core.$strip>>;
|
|
194
|
+
declare const OpportunityWon: CrmEventDefinition<z.ZodObject<{
|
|
195
|
+
opportunityId: z.ZodString;
|
|
196
|
+
amount: z.ZodOptional<z.ZodNumber>;
|
|
197
|
+
}, z.core.$strip>>;
|
|
198
|
+
declare const OpportunityLost: CrmEventDefinition<z.ZodObject<{
|
|
199
|
+
opportunityId: z.ZodString;
|
|
200
|
+
lostReasonId: z.ZodOptional<z.ZodString>;
|
|
201
|
+
}, z.core.$strip>>;
|
|
202
|
+
declare const OpportunityAbandoned: CrmEventDefinition<z.ZodObject<{
|
|
203
|
+
opportunityId: z.ZodString;
|
|
204
|
+
}, z.core.$strip>>;
|
|
205
|
+
declare const OpportunityAssigned: CrmEventDefinition<z.ZodObject<{
|
|
206
|
+
opportunityId: z.ZodString;
|
|
207
|
+
ownerId: z.ZodString;
|
|
208
|
+
previousOwnerId: z.ZodOptional<z.ZodString>;
|
|
209
|
+
}, z.core.$strip>>;
|
|
210
|
+
declare const OpportunityAmountChanged: CrmEventDefinition<z.ZodObject<{
|
|
211
|
+
opportunityId: z.ZodString;
|
|
212
|
+
amount: z.ZodNumber;
|
|
213
|
+
previousAmount: z.ZodOptional<z.ZodNumber>;
|
|
214
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
215
|
+
by: z.ZodOptional<z.ZodString>;
|
|
216
|
+
}, z.core.$strip>>;
|
|
217
|
+
declare const OpportunityExtended: CrmEventDefinition<z.ZodObject<{
|
|
218
|
+
opportunityId: z.ZodString;
|
|
219
|
+
expectedCloseAt: z.ZodISODateTime;
|
|
220
|
+
previousExpectedCloseAt: z.ZodOptional<z.ZodISODateTime>;
|
|
221
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
222
|
+
by: z.ZodOptional<z.ZodString>;
|
|
223
|
+
}, z.core.$strip>>;
|
|
224
|
+
declare const PipelineCreated: CrmEventDefinition<z.ZodObject<{
|
|
225
|
+
pipelineId: z.ZodString;
|
|
226
|
+
}, z.core.$strip>>;
|
|
227
|
+
declare const PipelineArchived: CrmEventDefinition<z.ZodObject<{
|
|
228
|
+
pipelineId: z.ZodString;
|
|
229
|
+
}, z.core.$strip>>;
|
|
230
|
+
declare const ActivityPlanned: CrmEventDefinition<z.ZodObject<{
|
|
231
|
+
activityId: z.ZodString;
|
|
232
|
+
type: z.ZodString;
|
|
233
|
+
subjectKind: z.ZodString;
|
|
234
|
+
subjectId: z.ZodString;
|
|
235
|
+
}, z.core.$strip>>;
|
|
236
|
+
declare const ActivityCompleted: CrmEventDefinition<z.ZodObject<{
|
|
237
|
+
activityId: z.ZodString;
|
|
238
|
+
completedAt: z.ZodISODateTime;
|
|
239
|
+
}, z.core.$strip>>;
|
|
240
|
+
declare const ActivityCancelled: CrmEventDefinition<z.ZodObject<{
|
|
241
|
+
activityId: z.ZodString;
|
|
242
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
243
|
+
}, z.core.$strip>>;
|
|
244
|
+
declare const ActivityRescheduled: CrmEventDefinition<z.ZodObject<{
|
|
245
|
+
activityId: z.ZodString;
|
|
246
|
+
dueDate: z.ZodISODateTime;
|
|
247
|
+
previousDueDate: z.ZodOptional<z.ZodISODateTime>;
|
|
248
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
249
|
+
by: z.ZodOptional<z.ZodString>;
|
|
250
|
+
}, z.core.$strip>>;
|
|
251
|
+
declare const ActivityOutcomeRecorded: CrmEventDefinition<z.ZodObject<{
|
|
252
|
+
activityId: z.ZodString;
|
|
253
|
+
outcome: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
254
|
+
}, z.core.$strip>>;
|
|
255
|
+
declare const NoteAdded: CrmEventDefinition<z.ZodObject<{
|
|
256
|
+
noteId: z.ZodString;
|
|
257
|
+
subjectKind: z.ZodString;
|
|
258
|
+
subjectId: z.ZodString;
|
|
259
|
+
}, z.core.$strip>>;
|
|
260
|
+
declare const CampaignCreated: CrmEventDefinition<z.ZodObject<{
|
|
261
|
+
campaignId: z.ZodString;
|
|
262
|
+
name: z.ZodString;
|
|
263
|
+
}, z.core.$strip>>;
|
|
264
|
+
declare const CampaignActivated: CrmEventDefinition<z.ZodObject<{
|
|
265
|
+
campaignId: z.ZodString;
|
|
266
|
+
}, z.core.$strip>>;
|
|
267
|
+
declare const CampaignPaused: CrmEventDefinition<z.ZodObject<{
|
|
268
|
+
campaignId: z.ZodString;
|
|
269
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
270
|
+
}, z.core.$strip>>;
|
|
271
|
+
declare const CampaignResumed: CrmEventDefinition<z.ZodObject<{
|
|
272
|
+
campaignId: z.ZodString;
|
|
273
|
+
}, z.core.$strip>>;
|
|
274
|
+
declare const CampaignCompleted: CrmEventDefinition<z.ZodObject<{
|
|
275
|
+
campaignId: z.ZodString;
|
|
276
|
+
actualRevenueAmount: z.ZodOptional<z.ZodNumber>;
|
|
277
|
+
}, z.core.$strip>>;
|
|
278
|
+
declare const CampaignArchived: CrmEventDefinition<z.ZodObject<{
|
|
279
|
+
campaignId: z.ZodString;
|
|
280
|
+
}, z.core.$strip>>;
|
|
281
|
+
declare const SubscriptionCreated: CrmEventDefinition<z.ZodObject<{
|
|
282
|
+
subscriptionId: z.ZodString;
|
|
283
|
+
contactId: z.ZodString;
|
|
284
|
+
campaignId: z.ZodString;
|
|
285
|
+
requiresConfirmation: z.ZodBoolean;
|
|
286
|
+
}, z.core.$strip>>;
|
|
287
|
+
declare const SubscriptionConfirmed: CrmEventDefinition<z.ZodObject<{
|
|
288
|
+
subscriptionId: z.ZodString;
|
|
289
|
+
contactId: z.ZodString;
|
|
290
|
+
campaignId: z.ZodString;
|
|
291
|
+
confirmedAt: z.ZodISODateTime;
|
|
292
|
+
}, z.core.$strip>>;
|
|
293
|
+
declare const SubscriptionUnsubscribed: CrmEventDefinition<z.ZodObject<{
|
|
294
|
+
subscriptionId: z.ZodString;
|
|
295
|
+
contactId: z.ZodString;
|
|
296
|
+
campaignId: z.ZodString;
|
|
297
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
298
|
+
}, z.core.$strip>>;
|
|
299
|
+
declare const SubscriptionBounced: CrmEventDefinition<z.ZodObject<{
|
|
300
|
+
subscriptionId: z.ZodString;
|
|
301
|
+
contactId: z.ZodString;
|
|
302
|
+
campaignId: z.ZodString;
|
|
303
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
304
|
+
}, z.core.$strip>>;
|
|
305
|
+
declare const SubscriptionComplained: CrmEventDefinition<z.ZodObject<{
|
|
306
|
+
subscriptionId: z.ZodString;
|
|
307
|
+
contactId: z.ZodString;
|
|
308
|
+
campaignId: z.ZodString;
|
|
309
|
+
}, z.core.$strip>>;
|
|
310
|
+
declare const EmailEventOpened: CrmEventDefinition<z.ZodObject<{
|
|
311
|
+
eventId: z.ZodString;
|
|
312
|
+
kind: z.ZodString;
|
|
313
|
+
subjectKind: z.ZodString;
|
|
314
|
+
subjectId: z.ZodString;
|
|
315
|
+
campaignId: z.ZodOptional<z.ZodString>;
|
|
316
|
+
}, z.core.$strip>>;
|
|
317
|
+
declare const EmailEventClicked: CrmEventDefinition<z.ZodObject<{
|
|
318
|
+
eventId: z.ZodString;
|
|
319
|
+
kind: z.ZodString;
|
|
320
|
+
subjectKind: z.ZodString;
|
|
321
|
+
subjectId: z.ZodString;
|
|
322
|
+
campaignId: z.ZodOptional<z.ZodString>;
|
|
323
|
+
}, z.core.$strip>>;
|
|
324
|
+
declare const EmailEventBounced: CrmEventDefinition<z.ZodObject<{
|
|
325
|
+
eventId: z.ZodString;
|
|
326
|
+
kind: z.ZodString;
|
|
327
|
+
subjectKind: z.ZodString;
|
|
328
|
+
subjectId: z.ZodString;
|
|
329
|
+
campaignId: z.ZodOptional<z.ZodString>;
|
|
330
|
+
}, z.core.$strip>>;
|
|
331
|
+
declare const EmailEventComplained: CrmEventDefinition<z.ZodObject<{
|
|
332
|
+
eventId: z.ZodString;
|
|
333
|
+
kind: z.ZodString;
|
|
334
|
+
subjectKind: z.ZodString;
|
|
335
|
+
subjectId: z.ZodString;
|
|
336
|
+
campaignId: z.ZodOptional<z.ZodString>;
|
|
337
|
+
}, z.core.$strip>>;
|
|
338
|
+
declare const EmailEventUnsubscribed: CrmEventDefinition<z.ZodObject<{
|
|
339
|
+
eventId: z.ZodString;
|
|
340
|
+
kind: z.ZodString;
|
|
341
|
+
subjectKind: z.ZodString;
|
|
342
|
+
subjectId: z.ZodString;
|
|
343
|
+
campaignId: z.ZodOptional<z.ZodString>;
|
|
344
|
+
}, z.core.$strip>>;
|
|
345
|
+
declare const ConversationCreated: CrmEventDefinition<z.ZodObject<{
|
|
346
|
+
conversationId: z.ZodString;
|
|
347
|
+
channel: z.ZodString;
|
|
348
|
+
participantKind: z.ZodString;
|
|
349
|
+
participantId: z.ZodString;
|
|
350
|
+
}, z.core.$strip>>;
|
|
351
|
+
declare const ConversationAssigned: CrmEventDefinition<z.ZodObject<{
|
|
352
|
+
conversationId: z.ZodString;
|
|
353
|
+
assigneeId: z.ZodString;
|
|
354
|
+
previousAssigneeId: z.ZodOptional<z.ZodString>;
|
|
355
|
+
}, z.core.$strip>>;
|
|
356
|
+
declare const ConversationResolved: CrmEventDefinition<z.ZodObject<{
|
|
357
|
+
conversationId: z.ZodString;
|
|
358
|
+
status: z.ZodString;
|
|
359
|
+
previousStatus: z.ZodString;
|
|
360
|
+
}, z.core.$strip>>;
|
|
361
|
+
declare const ConversationReopened: CrmEventDefinition<z.ZodObject<{
|
|
362
|
+
conversationId: z.ZodString;
|
|
363
|
+
status: z.ZodString;
|
|
364
|
+
previousStatus: z.ZodString;
|
|
365
|
+
}, z.core.$strip>>;
|
|
366
|
+
declare const MessageReceived: CrmEventDefinition<z.ZodObject<{
|
|
367
|
+
messageId: z.ZodString;
|
|
368
|
+
conversationId: z.ZodString;
|
|
369
|
+
direction: z.ZodString;
|
|
370
|
+
externalMessageId: z.ZodOptional<z.ZodString>;
|
|
371
|
+
}, z.core.$strip>>;
|
|
372
|
+
declare const MessageSent: CrmEventDefinition<z.ZodObject<{
|
|
373
|
+
messageId: z.ZodString;
|
|
374
|
+
conversationId: z.ZodString;
|
|
375
|
+
direction: z.ZodString;
|
|
376
|
+
externalMessageId: z.ZodOptional<z.ZodString>;
|
|
377
|
+
}, z.core.$strip>>;
|
|
378
|
+
declare const crmEventDefinitions: ReadonlyArray<CrmEventDefinition>;
|
|
52
379
|
//#endregion
|
|
53
|
-
//#region src/
|
|
54
|
-
|
|
55
|
-
|
|
380
|
+
//#region src/models/tenant-field.d.ts
|
|
381
|
+
type TenantFieldType = 'objectId' | 'string';
|
|
382
|
+
interface SchemaBuildConfig {
|
|
383
|
+
/** Schema type for the tenant column. Engine plumbs this everywhere. */
|
|
384
|
+
tenantFieldType: TenantFieldType;
|
|
56
385
|
}
|
|
57
|
-
//#endregion
|
|
58
|
-
//#region src/services/mutation-options.d.ts
|
|
59
386
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
387
|
+
* Tenant-column schema definition. Use this anywhere a model has
|
|
388
|
+
* `organizationId` — never write the raw type in a schema file.
|
|
62
389
|
*/
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* When `false`, skip event emission for this call. Useful for bulk seeds
|
|
66
|
-
* and when a higher-level orchestration verb composes several services
|
|
67
|
-
* and only wants the outer event to fire (see `LeadService.convert`).
|
|
68
|
-
*/
|
|
69
|
-
emitEvents?: boolean;
|
|
70
|
-
/**
|
|
71
|
-
* Host-provided DB transaction handle (mongoose `ClientSession`,
|
|
72
|
-
* Prisma tx, Postgres client with `BEGIN`, etc.). Typed as `unknown`
|
|
73
|
-
* to keep crm framework-agnostic.
|
|
74
|
-
*
|
|
75
|
-
* Forwarded to:
|
|
76
|
-
* - The host's repository adapter (if it reads `options.session`) so
|
|
77
|
-
* the business write joins the transaction.
|
|
78
|
-
* - `outbox.save(event, { session })` so the outbox row commits
|
|
79
|
-
* atomically with the business write — PACKAGE_RULES §5.5 + P8's
|
|
80
|
-
* session-bound dispatch pattern.
|
|
81
|
-
*
|
|
82
|
-
* Wrap the CRM service call in your own transaction:
|
|
83
|
-
*
|
|
84
|
-
* ```ts
|
|
85
|
-
* const session = await mongoose.connection.startSession();
|
|
86
|
-
* try {
|
|
87
|
-
* await session.withTransaction(async () => {
|
|
88
|
-
* await accountService.create({ name: 'Acme' }, { session });
|
|
89
|
-
* });
|
|
90
|
-
* } finally {
|
|
91
|
-
* await session.endSession();
|
|
92
|
-
* }
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
session?: unknown;
|
|
96
|
-
}
|
|
390
|
+
declare function tenantFieldDef(config: SchemaBuildConfig): SchemaDefinitionProperty;
|
|
97
391
|
//#endregion
|
|
98
|
-
//#region src/
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Optional host-owned outbox. See `emitCrmEvent` for the dispatch contract:
|
|
104
|
-
* outbox save (session-bound when `options.session` is passed) is issued
|
|
105
|
-
* before the transport publish so durable at-least-once delivery works
|
|
106
|
-
* even when the transport is down.
|
|
107
|
-
*/
|
|
108
|
-
outbox?: OutboxStore | undefined;
|
|
109
|
-
clock?: Clock;
|
|
110
|
-
ids?: IdGenerator;
|
|
111
|
-
}
|
|
112
|
-
interface CreateAccountInput {
|
|
392
|
+
//#region src/models/pipeline.schema.d.ts
|
|
393
|
+
/** Mongoose document shape for a single embedded stage. */
|
|
394
|
+
interface IStageDocument {
|
|
395
|
+
_id: mongoose1.Types.ObjectId;
|
|
113
396
|
name: string;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
};
|
|
121
|
-
ownerId?: string;
|
|
122
|
-
tags?: readonly string[];
|
|
123
|
-
metadata?: Record<string, unknown>;
|
|
124
|
-
}
|
|
125
|
-
declare class AccountService {
|
|
126
|
-
private readonly repo;
|
|
127
|
-
private readonly events;
|
|
128
|
-
private readonly outbox;
|
|
129
|
-
private readonly clock;
|
|
130
|
-
private readonly ids;
|
|
131
|
-
constructor(config: AccountServiceConfig);
|
|
132
|
-
create(input: CreateAccountInput, options?: MutationOptions): Promise<Account>;
|
|
133
|
-
update(id: string, patch: Partial<Account>, options?: MutationOptions): Promise<Account>;
|
|
134
|
-
delete(id: string): Promise<void>;
|
|
135
|
-
findById(id: string): Promise<Account | null>;
|
|
136
|
-
findByDomain(domain: string): Promise<Account | null>;
|
|
137
|
-
list(filter?: Parameters<AccountRepository['list']>[0]): Promise<Account[]>;
|
|
138
|
-
private _require;
|
|
139
|
-
private _emit;
|
|
140
|
-
}
|
|
141
|
-
//#endregion
|
|
142
|
-
//#region src/domain/enums/activity.d.ts
|
|
143
|
-
/**
|
|
144
|
-
* Activity type vocabulary. The package stores `type` as free-form
|
|
145
|
-
* string so hosts can extend; these constants cover the common
|
|
146
|
-
* channels that automation tooling typically keys off.
|
|
147
|
-
*/
|
|
148
|
-
declare const ACTIVITY_TYPES: readonly ["call", "email", "meeting", "task", "note", "sms", "social", "demo", "other"];
|
|
149
|
-
type ActivityType = (typeof ACTIVITY_TYPES)[number];
|
|
150
|
-
declare const ACTIVITY_STATUSES: readonly ["planned", "in_progress", "completed", "cancelled"];
|
|
151
|
-
type ActivityStatus = (typeof ACTIVITY_STATUSES)[number];
|
|
152
|
-
declare const ACTIVITY_TRANSITIONS: Record<ActivityStatus, readonly ActivityStatus[]>;
|
|
153
|
-
declare function canTransitionActivity(from: ActivityStatus, to: ActivityStatus): boolean;
|
|
154
|
-
/**
|
|
155
|
-
* Kinds of entity an Activity can reference. Polymorphic linking lets
|
|
156
|
-
* hosts log a call against a Lead, an Opportunity, a Contact, or a
|
|
157
|
-
* stand-alone Account.
|
|
158
|
-
*/
|
|
159
|
-
declare const SUBJECT_KINDS: readonly ["lead", "opportunity", "contact", "account"];
|
|
160
|
-
type SubjectKind = (typeof SUBJECT_KINDS)[number];
|
|
161
|
-
//#endregion
|
|
162
|
-
//#region src/domain/entities/activity.d.ts
|
|
163
|
-
/**
|
|
164
|
-
* An activity is a polymorphic record of outreach / task / event
|
|
165
|
-
* attached to any CRM entity. `subjectKind` + `subjectId` define the
|
|
166
|
-
* link — this is how hosts build automation atop the package (subscribe
|
|
167
|
-
* to `crm:activity.*` events, filter by `subjectKind`, react).
|
|
168
|
-
*/
|
|
169
|
-
interface Activity {
|
|
170
|
-
id: string;
|
|
171
|
-
type: ActivityType | string;
|
|
172
|
-
status: ActivityStatus;
|
|
173
|
-
subjectKind: SubjectKind;
|
|
174
|
-
subjectId: string;
|
|
175
|
-
subject?: string;
|
|
176
|
-
body?: string;
|
|
177
|
-
/** When the activity is / was scheduled to happen. */
|
|
178
|
-
scheduledAt?: Date;
|
|
179
|
-
completedAt?: Date;
|
|
180
|
-
cancelledAt?: Date;
|
|
181
|
-
/** User-level ownership (call made by / task assigned to). */
|
|
182
|
-
ownerId?: string;
|
|
183
|
-
participantIds?: readonly string[];
|
|
184
|
-
/**
|
|
185
|
-
* Optional external ref — e.g. Calendar event id, email thread id,
|
|
186
|
-
* call-recording url. Host-owned semantics.
|
|
187
|
-
*/
|
|
188
|
-
externalRef?: string;
|
|
189
|
-
metadata?: Record<string, unknown>;
|
|
190
|
-
createdAt: Date;
|
|
191
|
-
updatedAt: Date;
|
|
192
|
-
}
|
|
193
|
-
//#endregion
|
|
194
|
-
//#region src/domain/entities/note.d.ts
|
|
195
|
-
/**
|
|
196
|
-
* A free-text note on a CRM entity. Separate from Activity because
|
|
197
|
-
* notes aren't status-tracked — they're typed once and stay; they're
|
|
198
|
-
* also the cheapest "activity log" entry to create.
|
|
199
|
-
*/
|
|
200
|
-
interface Note {
|
|
201
|
-
id: string;
|
|
202
|
-
subjectKind: SubjectKind;
|
|
203
|
-
subjectId: string;
|
|
204
|
-
body: string;
|
|
205
|
-
authorId?: string;
|
|
206
|
-
/** Supports @-mentions, Markdown, etc. — host-interpreted. */
|
|
207
|
-
format?: 'plain' | 'markdown';
|
|
208
|
-
metadata?: Record<string, unknown>;
|
|
209
|
-
createdAt: Date;
|
|
210
|
-
updatedAt: Date;
|
|
211
|
-
}
|
|
212
|
-
//#endregion
|
|
213
|
-
//#region src/domain/ports/activity-repository.port.d.ts
|
|
214
|
-
interface ActivityFilter {
|
|
215
|
-
subjectKind?: SubjectKind;
|
|
216
|
-
subjectId?: string;
|
|
217
|
-
status?: ActivityStatus | readonly ActivityStatus[];
|
|
218
|
-
ownerId?: string;
|
|
219
|
-
scheduledBetween?: {
|
|
220
|
-
from: Date;
|
|
221
|
-
to: Date;
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
interface ActivityRepository {
|
|
225
|
-
findById(id: string): Promise<Activity | null>;
|
|
226
|
-
list(filter?: ActivityFilter): Promise<Activity[]>;
|
|
227
|
-
create(a: Omit<Activity, 'createdAt' | 'updatedAt'>): Promise<Activity>;
|
|
228
|
-
update(id: string, patch: Partial<Activity>): Promise<Activity>;
|
|
229
|
-
casStatus(id: string, expected: ActivityStatus, next: ActivityStatus, patch?: Partial<Activity>): Promise<Activity | null>;
|
|
230
|
-
}
|
|
231
|
-
//#endregion
|
|
232
|
-
//#region src/domain/ports/note-repository.port.d.ts
|
|
233
|
-
interface NoteRepository {
|
|
234
|
-
findById(id: string): Promise<Note | null>;
|
|
235
|
-
listBySubject(subjectKind: SubjectKind, subjectId: string): Promise<Note[]>;
|
|
236
|
-
create(n: Omit<Note, 'createdAt' | 'updatedAt'>): Promise<Note>;
|
|
237
|
-
update(id: string, patch: Partial<Note>): Promise<Note>;
|
|
238
|
-
delete(id: string): Promise<void>;
|
|
239
|
-
}
|
|
240
|
-
//#endregion
|
|
241
|
-
//#region src/services/activity.service.d.ts
|
|
242
|
-
interface ActivityServiceConfig {
|
|
243
|
-
repo: ActivityRepository;
|
|
244
|
-
notes: NoteRepository;
|
|
245
|
-
events?: EventTransport | undefined;
|
|
246
|
-
/** Optional host-owned outbox. See AccountServiceConfig.outbox. */
|
|
247
|
-
outbox?: OutboxStore | undefined;
|
|
248
|
-
clock?: Clock;
|
|
249
|
-
ids?: IdGenerator;
|
|
250
|
-
}
|
|
251
|
-
interface CreateActivityInput {
|
|
252
|
-
type: ActivityType | string;
|
|
253
|
-
subjectKind: SubjectKind;
|
|
254
|
-
subjectId: string;
|
|
255
|
-
subject?: string;
|
|
256
|
-
body?: string;
|
|
257
|
-
scheduledAt?: Date;
|
|
258
|
-
ownerId?: string;
|
|
259
|
-
participantIds?: readonly string[];
|
|
260
|
-
externalRef?: string;
|
|
261
|
-
metadata?: Record<string, unknown>;
|
|
262
|
-
}
|
|
263
|
-
interface CreateNoteInput {
|
|
264
|
-
subjectKind: SubjectKind;
|
|
265
|
-
subjectId: string;
|
|
266
|
-
body: string;
|
|
267
|
-
authorId?: string;
|
|
268
|
-
format?: 'plain' | 'markdown';
|
|
269
|
-
metadata?: Record<string, unknown>;
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Polymorphic activity / note service. Activities have a lifecycle
|
|
273
|
-
* (`planned → in_progress → completed | cancelled`); notes are
|
|
274
|
-
* immutable-ish (create + update body, no status).
|
|
275
|
-
*/
|
|
276
|
-
declare class ActivityService {
|
|
277
|
-
private readonly repo;
|
|
278
|
-
private readonly noteRepo;
|
|
279
|
-
private readonly events;
|
|
280
|
-
private readonly outbox;
|
|
281
|
-
private readonly clock;
|
|
282
|
-
private readonly ids;
|
|
283
|
-
constructor(config: ActivityServiceConfig);
|
|
284
|
-
plan(input: CreateActivityInput, options?: MutationOptions): Promise<Activity>;
|
|
285
|
-
start(id: string, options?: MutationOptions): Promise<Activity>;
|
|
286
|
-
complete(id: string, completedAt?: Date, options?: MutationOptions): Promise<Activity>;
|
|
287
|
-
cancel(id: string, reason?: string, options?: MutationOptions): Promise<Activity>;
|
|
288
|
-
addNote(input: CreateNoteInput, options?: MutationOptions): Promise<Note>;
|
|
289
|
-
listBySubject(subjectKind: SubjectKind, subjectId: string): Promise<Activity[]>;
|
|
290
|
-
listNotesBySubject(subjectKind: SubjectKind, subjectId: string): Promise<Note[]>;
|
|
291
|
-
findById(id: string): Promise<Activity | null>;
|
|
292
|
-
private _transition;
|
|
293
|
-
private _emit;
|
|
397
|
+
/** Ascending order in the pipeline. Treated as identifier on `moveToStage`. */
|
|
398
|
+
sequence: number;
|
|
399
|
+
/** Default win-probability assigned to opportunities entering this stage. */
|
|
400
|
+
defaultProbability: number;
|
|
401
|
+
color?: string;
|
|
402
|
+
description?: string;
|
|
294
403
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
*/
|
|
305
|
-
|
|
306
|
-
id: string;
|
|
307
|
-
name: PersonName;
|
|
308
|
-
contact: ContactInfo;
|
|
309
|
-
jobTitle?: string;
|
|
310
|
-
accountId?: string;
|
|
311
|
-
ownerId?: string;
|
|
312
|
-
/** Free-form tags for segmentation. */
|
|
313
|
-
tags?: readonly string[];
|
|
314
|
-
/** Host-owned arbitrary payload (social handles, custom fields, etc.). */
|
|
404
|
+
/** Mongoose document shape for a Pipeline. */
|
|
405
|
+
interface IPipelineDocument {
|
|
406
|
+
_id: mongoose1.Types.ObjectId;
|
|
407
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
408
|
+
name: string;
|
|
409
|
+
/** Deprecates the pipeline — existing opps still move, no new ones created. */
|
|
410
|
+
isArchived: boolean;
|
|
411
|
+
/** Embedded stages, kept ordered by `sequence`. */
|
|
412
|
+
stages: IStageDocument[];
|
|
413
|
+
/** Free-form label for the sales team / motion that owns this pipeline. */
|
|
414
|
+
teamRef?: string;
|
|
315
415
|
metadata?: Record<string, unknown>;
|
|
316
416
|
createdAt: Date;
|
|
317
417
|
updatedAt: Date;
|
|
318
418
|
}
|
|
419
|
+
declare function buildPipelineSchema(config: SchemaBuildConfig): Schema<IPipelineDocument>;
|
|
420
|
+
declare function createPipelineModel(connection: Connection, config: SchemaBuildConfig): Model<IPipelineDocument>;
|
|
319
421
|
//#endregion
|
|
320
|
-
//#region src/
|
|
321
|
-
interface ContactFilter {
|
|
322
|
-
accountId?: string;
|
|
323
|
-
ownerId?: string;
|
|
324
|
-
email?: string;
|
|
325
|
-
tags?: readonly string[];
|
|
326
|
-
}
|
|
327
|
-
interface ContactRepository {
|
|
328
|
-
findById(id: string): Promise<Contact | null>;
|
|
329
|
-
findByEmail(email: string): Promise<Contact | null>;
|
|
330
|
-
list(filter?: ContactFilter): Promise<Contact[]>;
|
|
331
|
-
create(c: Omit<Contact, 'createdAt' | 'updatedAt'>): Promise<Contact>;
|
|
332
|
-
update(id: string, patch: Partial<Contact>): Promise<Contact>;
|
|
333
|
-
delete(id: string): Promise<void>;
|
|
334
|
-
}
|
|
335
|
-
//#endregion
|
|
336
|
-
//#region src/services/contact.service.d.ts
|
|
337
|
-
interface ContactServiceConfig {
|
|
338
|
-
repo: ContactRepository;
|
|
339
|
-
events?: EventTransport | undefined;
|
|
340
|
-
/** Optional host-owned outbox. See AccountServiceConfig.outbox. */
|
|
341
|
-
outbox?: OutboxStore | undefined;
|
|
342
|
-
clock?: Clock;
|
|
343
|
-
ids?: IdGenerator;
|
|
344
|
-
}
|
|
345
|
-
interface CreateContactInput {
|
|
346
|
-
name: PersonName;
|
|
347
|
-
contact?: ContactInfo;
|
|
348
|
-
jobTitle?: string;
|
|
349
|
-
accountId?: string;
|
|
350
|
-
ownerId?: string;
|
|
351
|
-
tags?: readonly string[];
|
|
352
|
-
metadata?: Record<string, unknown>;
|
|
353
|
-
}
|
|
354
|
-
declare class ContactService {
|
|
355
|
-
private readonly repo;
|
|
356
|
-
private readonly events;
|
|
357
|
-
private readonly outbox;
|
|
358
|
-
private readonly clock;
|
|
359
|
-
private readonly ids;
|
|
360
|
-
constructor(config: ContactServiceConfig);
|
|
361
|
-
create(input: CreateContactInput, options?: MutationOptions): Promise<Contact>;
|
|
362
|
-
update(id: string, patch: Partial<Contact>, options?: MutationOptions): Promise<Contact>;
|
|
363
|
-
delete(id: string): Promise<void>;
|
|
364
|
-
findById(id: string): Promise<Contact | null>;
|
|
365
|
-
findByEmail(email: string): Promise<Contact | null>;
|
|
366
|
-
list(filter?: Parameters<ContactRepository['list']>[0]): Promise<Contact[]>;
|
|
367
|
-
private _require;
|
|
368
|
-
private _emit;
|
|
369
|
-
}
|
|
370
|
-
//#endregion
|
|
371
|
-
//#region src/domain/enums/lead-status.d.ts
|
|
422
|
+
//#region src/enums/lead-status.d.ts
|
|
372
423
|
/**
|
|
373
424
|
* Lead lifecycle — from initial inquiry through conversion.
|
|
374
425
|
*
|
|
@@ -384,56 +435,43 @@ type LeadStatus = (typeof LEAD_STATUSES)[number];
|
|
|
384
435
|
declare const LEAD_TRANSITIONS: Record<LeadStatus, readonly LeadStatus[]>;
|
|
385
436
|
declare function canTransitionLead(from: LeadStatus, to: LeadStatus): boolean;
|
|
386
437
|
//#endregion
|
|
387
|
-
//#region src/
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
interface
|
|
395
|
-
|
|
396
|
-
|
|
438
|
+
//#region src/models/lead.schema.d.ts
|
|
439
|
+
interface ILeadStatusEntry {
|
|
440
|
+
status: LeadStatus;
|
|
441
|
+
occurredAt: Date;
|
|
442
|
+
by?: string;
|
|
443
|
+
note?: string;
|
|
444
|
+
}
|
|
445
|
+
interface ILeadDocument {
|
|
446
|
+
_id: mongoose1.Types.ObjectId;
|
|
447
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
448
|
+
fullName: string;
|
|
397
449
|
firstName?: string;
|
|
398
450
|
lastName?: string;
|
|
399
|
-
fullName: string;
|
|
400
451
|
email?: string;
|
|
401
452
|
phone?: string;
|
|
402
453
|
companyName?: string;
|
|
403
454
|
jobTitle?: string;
|
|
404
|
-
/** How the lead arrived (`web-form`, `referral`, `event`, `ads`, …). */
|
|
405
455
|
source?: string;
|
|
406
|
-
/** Free-form campaign identifier — the host's campaign system owns its semantics. */
|
|
407
456
|
campaignRef?: string;
|
|
408
|
-
|
|
409
|
-
* Lead score — updated by `LeadService.recomputeScore(...)` whenever
|
|
410
|
-
* the score function decides. Stored on the record for indexing +
|
|
411
|
-
* routing. Raw score units; range is host-defined.
|
|
412
|
-
*/
|
|
413
|
-
score?: number;
|
|
457
|
+
score: number;
|
|
414
458
|
status: LeadStatus;
|
|
415
|
-
statusHistory:
|
|
459
|
+
statusHistory: ILeadStatusEntry[];
|
|
416
460
|
ownerId?: string;
|
|
417
|
-
tags
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
convertedOpportunityId?: string;
|
|
461
|
+
tags: string[];
|
|
462
|
+
convertedContactId?: mongoose1.Types.ObjectId | string;
|
|
463
|
+
convertedAccountId?: mongoose1.Types.ObjectId | string;
|
|
464
|
+
convertedOpportunityId?: mongoose1.Types.ObjectId | string;
|
|
422
465
|
convertedAt?: Date;
|
|
423
|
-
/** Disqualification detail. */
|
|
424
466
|
disqualifyReason?: string;
|
|
425
467
|
metadata?: Record<string, unknown>;
|
|
426
468
|
createdAt: Date;
|
|
427
469
|
updatedAt: Date;
|
|
428
470
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
occurredAt: Date;
|
|
432
|
-
by?: string;
|
|
433
|
-
note?: string;
|
|
434
|
-
}
|
|
471
|
+
declare function buildLeadSchema(config: SchemaBuildConfig): Schema<ILeadDocument>;
|
|
472
|
+
declare function createLeadModel(connection: Connection, config: SchemaBuildConfig): Model<ILeadDocument>;
|
|
435
473
|
//#endregion
|
|
436
|
-
//#region src/
|
|
474
|
+
//#region src/enums/opportunity-status.d.ts
|
|
437
475
|
/**
|
|
438
476
|
* Top-level opportunity status. Movement through pipeline STAGES
|
|
439
477
|
* happens while status is `open`; `won` / `lost` are terminal
|
|
@@ -446,975 +484,1004 @@ type OpportunityStatus = (typeof OPPORTUNITY_STATUSES)[number];
|
|
|
446
484
|
declare const OPPORTUNITY_TRANSITIONS: Record<OpportunityStatus, readonly OpportunityStatus[]>;
|
|
447
485
|
declare function canTransitionOpportunity(from: OpportunityStatus, to: OpportunityStatus): boolean;
|
|
448
486
|
//#endregion
|
|
449
|
-
//#region src/
|
|
487
|
+
//#region src/models/opportunity.schema.d.ts
|
|
488
|
+
interface IOpportunityStatusEntry {
|
|
489
|
+
status: OpportunityStatus;
|
|
490
|
+
stageId?: string;
|
|
491
|
+
occurredAt: Date;
|
|
492
|
+
by?: string;
|
|
493
|
+
note?: string;
|
|
494
|
+
}
|
|
495
|
+
interface IOpportunityDocument {
|
|
496
|
+
_id: mongoose1.Types.ObjectId;
|
|
497
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
498
|
+
name: string;
|
|
499
|
+
accountId?: mongoose1.Types.ObjectId | string;
|
|
500
|
+
primaryContactId?: mongoose1.Types.ObjectId | string;
|
|
501
|
+
pipelineId: mongoose1.Types.ObjectId | string;
|
|
502
|
+
stageId: string;
|
|
503
|
+
status: OpportunityStatus;
|
|
504
|
+
statusHistory: IOpportunityStatusEntry[];
|
|
505
|
+
amount?: number;
|
|
506
|
+
currency: string;
|
|
507
|
+
probability: number;
|
|
508
|
+
expectedCloseAt?: Date;
|
|
509
|
+
closedAt?: Date;
|
|
510
|
+
lostReasonId?: mongoose1.Types.ObjectId | string;
|
|
511
|
+
ownerId?: string;
|
|
512
|
+
sourceLeadId?: mongoose1.Types.ObjectId | string;
|
|
513
|
+
tags: string[];
|
|
514
|
+
metadata?: Record<string, unknown>;
|
|
515
|
+
createdAt: Date;
|
|
516
|
+
updatedAt: Date;
|
|
517
|
+
}
|
|
518
|
+
declare function buildOpportunitySchema(config: SchemaBuildConfig): Schema<IOpportunityDocument>;
|
|
519
|
+
declare function createOpportunityModel(connection: Connection, config: SchemaBuildConfig): Model<IOpportunityDocument>;
|
|
520
|
+
//#endregion
|
|
521
|
+
//#region src/models/contact.schema.d.ts
|
|
522
|
+
interface IContactName {
|
|
523
|
+
given: string;
|
|
524
|
+
family: string;
|
|
525
|
+
middle?: string;
|
|
526
|
+
prefix?: string;
|
|
527
|
+
suffix?: string;
|
|
528
|
+
preferred?: string;
|
|
529
|
+
}
|
|
530
|
+
interface IContactInfoEmbedded {
|
|
531
|
+
email?: string;
|
|
532
|
+
personalEmail?: string;
|
|
533
|
+
phone?: string;
|
|
534
|
+
alternatePhone?: string;
|
|
535
|
+
whatsapp?: string;
|
|
536
|
+
telegram?: string;
|
|
537
|
+
linkedin?: string;
|
|
538
|
+
instagram?: string;
|
|
539
|
+
}
|
|
540
|
+
interface IContactDocument {
|
|
541
|
+
_id: mongoose1.Types.ObjectId;
|
|
542
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
543
|
+
name: IContactName;
|
|
544
|
+
contact: IContactInfoEmbedded;
|
|
545
|
+
jobTitle?: string;
|
|
546
|
+
accountId?: mongoose1.Types.ObjectId | string;
|
|
547
|
+
ownerId?: string;
|
|
548
|
+
tags: string[];
|
|
549
|
+
metadata?: Record<string, unknown>;
|
|
550
|
+
createdAt: Date;
|
|
551
|
+
updatedAt: Date;
|
|
552
|
+
}
|
|
553
|
+
declare function buildContactSchema(config: SchemaBuildConfig): Schema<IContactDocument>;
|
|
554
|
+
declare function createContactModel(connection: Connection, config: SchemaBuildConfig): Model<IContactDocument>;
|
|
555
|
+
//#endregion
|
|
556
|
+
//#region src/models/account.schema.d.ts
|
|
557
|
+
interface IAccountDocument {
|
|
558
|
+
_id: mongoose1.Types.ObjectId;
|
|
559
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
560
|
+
name: string;
|
|
561
|
+
domain?: string;
|
|
562
|
+
industry?: string;
|
|
563
|
+
sizeBucket?: string;
|
|
564
|
+
annualRevenueAmount?: number;
|
|
565
|
+
annualRevenueCurrency: string;
|
|
566
|
+
ownerId?: string;
|
|
567
|
+
tags: string[];
|
|
568
|
+
metadata?: Record<string, unknown>;
|
|
569
|
+
createdAt: Date;
|
|
570
|
+
updatedAt: Date;
|
|
571
|
+
}
|
|
572
|
+
declare function buildAccountSchema(config: SchemaBuildConfig): Schema<IAccountDocument>;
|
|
573
|
+
declare function createAccountModel(connection: Connection, config: SchemaBuildConfig): Model<IAccountDocument>;
|
|
574
|
+
//#endregion
|
|
575
|
+
//#region src/enums/campaign-status.d.ts
|
|
450
576
|
/**
|
|
451
|
-
*
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
577
|
+
* Campaign lifecycle.
|
|
578
|
+
*
|
|
579
|
+
* draft — being built; not running, no sends, no UTM attribution counted
|
|
580
|
+
* active — running; participating in attribution + automation
|
|
581
|
+
* paused — temporarily halted; can be resumed; no sends fire
|
|
582
|
+
* completed — finished its run; preserved for historical attribution
|
|
583
|
+
* archived — soft-hidden from the default UI; still queryable
|
|
455
584
|
*/
|
|
456
|
-
|
|
457
|
-
|
|
585
|
+
declare const CAMPAIGN_STATUSES: readonly ["draft", "active", "paused", "completed", "archived"];
|
|
586
|
+
type CampaignStatus = (typeof CAMPAIGN_STATUSES)[number];
|
|
587
|
+
declare const CAMPAIGN_TRANSITIONS: Record<CampaignStatus, readonly CampaignStatus[]>;
|
|
588
|
+
declare function canTransitionCampaign(from: CampaignStatus, to: CampaignStatus): boolean;
|
|
589
|
+
//#endregion
|
|
590
|
+
//#region src/models/campaign.schema.d.ts
|
|
591
|
+
interface ICampaignStatusEntry {
|
|
592
|
+
status: CampaignStatus;
|
|
593
|
+
occurredAt: Date;
|
|
594
|
+
by?: string;
|
|
595
|
+
note?: string;
|
|
596
|
+
}
|
|
597
|
+
interface ICampaignDocument {
|
|
598
|
+
_id: mongoose1.Types.ObjectId;
|
|
599
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
458
600
|
name: string;
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
* every stage move; host can override for hand-tuned forecasts.
|
|
472
|
-
*/
|
|
473
|
-
probability: number;
|
|
474
|
-
/** When the deal is expected to close. Drives forecast grouping. */
|
|
475
|
-
expectedCloseAt?: Date;
|
|
476
|
-
/** Populated on win/lose. */
|
|
477
|
-
closedAt?: Date;
|
|
478
|
-
lostReasonId?: string;
|
|
601
|
+
description?: string;
|
|
602
|
+
status: CampaignStatus;
|
|
603
|
+
statusHistory: ICampaignStatusEntry[];
|
|
604
|
+
utmSource?: string;
|
|
605
|
+
utmMedium?: string;
|
|
606
|
+
utmCampaign?: string;
|
|
607
|
+
startDate?: Date;
|
|
608
|
+
endDate?: Date;
|
|
609
|
+
budgetAmount?: number;
|
|
610
|
+
expectedRevenueAmount?: number;
|
|
611
|
+
actualRevenueAmount?: number;
|
|
612
|
+
currency: string;
|
|
479
613
|
ownerId?: string;
|
|
480
|
-
|
|
481
|
-
tags?: readonly string[];
|
|
614
|
+
tags: string[];
|
|
482
615
|
metadata?: Record<string, unknown>;
|
|
483
616
|
createdAt: Date;
|
|
484
617
|
updatedAt: Date;
|
|
485
618
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
619
|
+
declare function buildCampaignSchema(config: SchemaBuildConfig): Schema<ICampaignDocument>;
|
|
620
|
+
declare function createCampaignModel(connection: Connection, config: SchemaBuildConfig): Model<ICampaignDocument>;
|
|
621
|
+
//#endregion
|
|
622
|
+
//#region src/enums/subscription-status.d.ts
|
|
623
|
+
/**
|
|
624
|
+
* Subscription lifecycle.
|
|
625
|
+
*
|
|
626
|
+
* pending — double-opt-in pending confirmation
|
|
627
|
+
* confirmed — actively subscribed; eligible to receive sends
|
|
628
|
+
* unsubscribed — user opted out via unsubscribe link (or operator action)
|
|
629
|
+
* bounced — provider reported hard bounce; permanent suppression
|
|
630
|
+
* complained — recipient hit "spam" / "report" in their email client;
|
|
631
|
+
* permanent suppression (CAN-SPAM + provider trust)
|
|
632
|
+
*
|
|
633
|
+
* All terminal states are non-reopenable. Re-subscribing creates a new
|
|
634
|
+
* Subscription row — the audit trail of unsubscribes/bounces is preserved.
|
|
635
|
+
*/
|
|
636
|
+
declare const SUBSCRIPTION_STATUSES: readonly ["pending", "confirmed", "unsubscribed", "bounced", "complained"];
|
|
637
|
+
type SubscriptionStatus = (typeof SUBSCRIPTION_STATUSES)[number];
|
|
638
|
+
declare const SUBSCRIPTION_TRANSITIONS: Record<SubscriptionStatus, readonly SubscriptionStatus[]>;
|
|
639
|
+
declare function canTransitionSubscription(from: SubscriptionStatus, to: SubscriptionStatus): boolean;
|
|
640
|
+
//#endregion
|
|
641
|
+
//#region src/models/subscription.schema.d.ts
|
|
642
|
+
interface ISubscriptionStatusEntry {
|
|
643
|
+
status: SubscriptionStatus;
|
|
489
644
|
occurredAt: Date;
|
|
490
645
|
by?: string;
|
|
491
646
|
note?: string;
|
|
492
647
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
648
|
+
interface ISubscriptionDocument {
|
|
649
|
+
_id: mongoose1.Types.ObjectId;
|
|
650
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
651
|
+
contactId: mongoose1.Types.ObjectId | string;
|
|
652
|
+
campaignId: mongoose1.Types.ObjectId | string;
|
|
653
|
+
status: SubscriptionStatus;
|
|
654
|
+
statusHistory: ISubscriptionStatusEntry[];
|
|
498
655
|
source?: string;
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
656
|
+
consentTimestamp: Date;
|
|
657
|
+
consentIpAddress?: string;
|
|
658
|
+
consentUserAgent?: string;
|
|
659
|
+
confirmationToken?: string;
|
|
660
|
+
unsubscribeToken: string;
|
|
661
|
+
/** Audit timestamps for compliance — set on the matching transition. */
|
|
662
|
+
confirmedAt?: Date;
|
|
663
|
+
unsubscribedAt?: Date;
|
|
664
|
+
unsubscribeReason?: string;
|
|
665
|
+
bouncedAt?: Date;
|
|
666
|
+
bounceReason?: string;
|
|
667
|
+
complainedAt?: Date;
|
|
668
|
+
metadata?: Record<string, unknown>;
|
|
669
|
+
createdAt: Date;
|
|
670
|
+
updatedAt: Date;
|
|
508
671
|
}
|
|
672
|
+
declare function buildSubscriptionSchema(config: SchemaBuildConfig): Schema<ISubscriptionDocument>;
|
|
673
|
+
declare function createSubscriptionModel(connection: Connection, config: SchemaBuildConfig): Model<ISubscriptionDocument>;
|
|
509
674
|
//#endregion
|
|
510
|
-
//#region src/
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
675
|
+
//#region src/enums/activity.d.ts
|
|
676
|
+
/**
|
|
677
|
+
* Activity type vocabulary. The package stores `type` as free-form
|
|
678
|
+
* string so hosts can extend; these constants cover the common
|
|
679
|
+
* channels that automation tooling typically keys off.
|
|
680
|
+
*/
|
|
681
|
+
declare const ACTIVITY_TYPES: readonly ["call", "email", "meeting", "task", "note", "sms", "social", "demo", "other"];
|
|
682
|
+
type ActivityType = (typeof ACTIVITY_TYPES)[number];
|
|
683
|
+
declare const ACTIVITY_STATUSES: readonly ["planned", "in_progress", "completed", "cancelled"];
|
|
684
|
+
type ActivityStatus = (typeof ACTIVITY_STATUSES)[number];
|
|
685
|
+
declare const ACTIVITY_TRANSITIONS: Record<ActivityStatus, readonly ActivityStatus[]>;
|
|
686
|
+
declare function canTransitionActivity(from: ActivityStatus, to: ActivityStatus): boolean;
|
|
687
|
+
/**
|
|
688
|
+
* Kinds of entity an Activity can reference. Polymorphic linking lets
|
|
689
|
+
* hosts log a call against a Lead, an Opportunity, a Contact, or a
|
|
690
|
+
* stand-alone Account.
|
|
691
|
+
*/
|
|
692
|
+
declare const SUBJECT_KINDS: readonly ["lead", "opportunity", "contact", "account"];
|
|
693
|
+
type SubjectKind = (typeof SUBJECT_KINDS)[number];
|
|
694
|
+
//#endregion
|
|
695
|
+
//#region src/models/activity.schema.d.ts
|
|
696
|
+
interface IActivityDocument {
|
|
697
|
+
_id: mongoose1.Types.ObjectId;
|
|
698
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
699
|
+
type: ActivityType;
|
|
700
|
+
status: ActivityStatus;
|
|
701
|
+
subjectKind: SubjectKind;
|
|
702
|
+
subjectId: mongoose1.Types.ObjectId | string;
|
|
703
|
+
title: string;
|
|
704
|
+
description?: string;
|
|
515
705
|
ownerId?: string;
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
findById(id: string): Promise<Opportunity | null>;
|
|
524
|
-
list(filter?: OpportunityFilter): Promise<Opportunity[]>;
|
|
525
|
-
create(o: Omit<Opportunity, 'createdAt' | 'updatedAt'>): Promise<Opportunity>;
|
|
526
|
-
update(id: string, patch: Partial<Opportunity>): Promise<Opportunity>;
|
|
527
|
-
delete(id: string): Promise<void>;
|
|
528
|
-
casStatus(id: string, expected: OpportunityStatus, next: OpportunityStatus, patch?: Partial<Opportunity>): Promise<Opportunity | null>;
|
|
529
|
-
casStage(id: string, expectedStageId: string, nextStageId: string, patch?: Partial<Opportunity>): Promise<Opportunity | null>;
|
|
706
|
+
participantIds: string[];
|
|
707
|
+
dueDate?: Date;
|
|
708
|
+
completedAt?: Date;
|
|
709
|
+
externalRef?: string;
|
|
710
|
+
metadata?: Record<string, unknown>;
|
|
711
|
+
createdAt: Date;
|
|
712
|
+
updatedAt: Date;
|
|
530
713
|
}
|
|
714
|
+
declare function buildActivitySchema(config: SchemaBuildConfig): Schema<IActivityDocument>;
|
|
715
|
+
declare function createActivityModel(connection: Connection, config: SchemaBuildConfig): Model<IActivityDocument>;
|
|
531
716
|
//#endregion
|
|
532
|
-
//#region src/
|
|
533
|
-
interface
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
}>;
|
|
545
|
-
getFirstStage(pipelineId: string): Promise<{
|
|
546
|
-
id: string;
|
|
547
|
-
sequence: number;
|
|
548
|
-
defaultProbability: number;
|
|
549
|
-
}>;
|
|
550
|
-
}
|
|
551
|
-
interface OpportunityServiceConfig {
|
|
552
|
-
repo: OpportunityRepository;
|
|
553
|
-
pipelines: OpportunityPipelinePort;
|
|
554
|
-
events?: EventTransport | undefined;
|
|
555
|
-
/** Optional host-owned outbox. See AccountServiceConfig.outbox. */
|
|
556
|
-
outbox?: OutboxStore | undefined;
|
|
557
|
-
clock?: Clock;
|
|
558
|
-
ids?: IdGenerator;
|
|
717
|
+
//#region src/models/note.schema.d.ts
|
|
718
|
+
interface INoteDocument {
|
|
719
|
+
_id: mongoose1.Types.ObjectId;
|
|
720
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
721
|
+
subjectKind: SubjectKind;
|
|
722
|
+
subjectId: mongoose1.Types.ObjectId | string;
|
|
723
|
+
body: string;
|
|
724
|
+
authorId?: string;
|
|
725
|
+
pinned: boolean;
|
|
726
|
+
metadata?: Record<string, unknown>;
|
|
727
|
+
createdAt: Date;
|
|
728
|
+
updatedAt: Date;
|
|
559
729
|
}
|
|
560
|
-
|
|
730
|
+
declare function buildNoteSchema(config: SchemaBuildConfig): Schema<INoteDocument>;
|
|
731
|
+
declare function createNoteModel(connection: Connection, config: SchemaBuildConfig): Model<INoteDocument>;
|
|
732
|
+
//#endregion
|
|
733
|
+
//#region src/models/loss-reason.schema.d.ts
|
|
734
|
+
interface ILossReasonDocument {
|
|
735
|
+
_id: mongoose1.Types.ObjectId;
|
|
736
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
561
737
|
name: string;
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
primaryContactId?: string;
|
|
567
|
-
sourceLeadId?: string;
|
|
568
|
-
amount?: Money;
|
|
569
|
-
/** Override the stage default. Defaults to the stage's `defaultProbability`. */
|
|
570
|
-
probability?: number;
|
|
571
|
-
expectedCloseAt?: Date;
|
|
572
|
-
ownerId?: string;
|
|
573
|
-
tags?: readonly string[];
|
|
738
|
+
description?: string;
|
|
739
|
+
isActive: boolean;
|
|
740
|
+
/** Display ordering in admin UIs. */
|
|
741
|
+
sequence: number;
|
|
574
742
|
metadata?: Record<string, unknown>;
|
|
743
|
+
createdAt: Date;
|
|
744
|
+
updatedAt: Date;
|
|
575
745
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
by?: string;
|
|
581
|
-
note?: string;
|
|
582
|
-
}
|
|
583
|
-
interface CloseInput {
|
|
584
|
-
amount?: Money;
|
|
585
|
-
closedAt?: Date;
|
|
586
|
-
by?: string;
|
|
587
|
-
note?: string;
|
|
588
|
-
}
|
|
589
|
-
interface LoseInput extends CloseInput {
|
|
590
|
-
lostReasonId?: string;
|
|
591
|
-
}
|
|
746
|
+
declare function buildLossReasonSchema(config: SchemaBuildConfig): Schema<ILossReasonDocument>;
|
|
747
|
+
declare function createLossReasonModel(connection: Connection, config: SchemaBuildConfig): Model<ILossReasonDocument>;
|
|
748
|
+
//#endregion
|
|
749
|
+
//#region src/enums/email-event-kind.d.ts
|
|
592
750
|
/**
|
|
593
|
-
*
|
|
594
|
-
*
|
|
595
|
-
*
|
|
596
|
-
*
|
|
751
|
+
* Email engagement event kinds, recorded against a Contact / Campaign /
|
|
752
|
+
* Subscription tuple as the recipient interacts with a sent message.
|
|
753
|
+
*
|
|
754
|
+
* open — recipient's mail client loaded the tracking pixel.
|
|
755
|
+
* Imperfect signal: image-block clients suppress it, some
|
|
756
|
+
* clients pre-fetch and inflate counts. Useful in aggregate.
|
|
757
|
+
*
|
|
758
|
+
* click — recipient followed a tracked link. High-signal: actual
|
|
759
|
+
* user action, not background fetch.
|
|
760
|
+
*
|
|
761
|
+
* bounce — provider reported delivery failed. Pair with the
|
|
762
|
+
* `bounce` status on Subscription for permanent suppression.
|
|
763
|
+
*
|
|
764
|
+
* complaint — recipient hit "spam" / "report" in their inbox. Pair
|
|
765
|
+
* with `complained` Subscription status.
|
|
766
|
+
*
|
|
767
|
+
* unsubscribe — recipient hit the unsubscribe link in the email. May
|
|
768
|
+
* fire BEFORE the Subscription itself is marked unsubscribed
|
|
769
|
+
* (the host can choose to confirm before flipping status).
|
|
770
|
+
*
|
|
771
|
+
* Open and click are "engagement signal"; bounce/complaint/unsubscribe are
|
|
772
|
+
* "suppression signal". The service exposes aggregates over both
|
|
773
|
+
* categories so consumers can compute open rate, click rate, bounce rate
|
|
774
|
+
* without filtering kind themselves.
|
|
597
775
|
*/
|
|
598
|
-
declare
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
776
|
+
declare const EMAIL_EVENT_KINDS: readonly ["open", "click", "bounce", "complaint", "unsubscribe"];
|
|
777
|
+
type EmailEventKind = (typeof EMAIL_EVENT_KINDS)[number];
|
|
778
|
+
/** Engagement (positive signal). */
|
|
779
|
+
//#endregion
|
|
780
|
+
//#region src/models/email-event.schema.d.ts
|
|
781
|
+
declare const EMAIL_EVENT_SUBJECT_KINDS: readonly ["contact", "subscription"];
|
|
782
|
+
type EmailEventSubjectKind = (typeof EMAIL_EVENT_SUBJECT_KINDS)[number];
|
|
783
|
+
interface IEmailEventDocument {
|
|
784
|
+
_id: mongoose1.Types.ObjectId;
|
|
785
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
786
|
+
kind: EmailEventKind;
|
|
787
|
+
subjectKind: EmailEventSubjectKind;
|
|
788
|
+
subjectId: mongoose1.Types.ObjectId | string;
|
|
789
|
+
campaignId?: mongoose1.Types.ObjectId | string;
|
|
790
|
+
messageId?: string;
|
|
791
|
+
url?: string;
|
|
792
|
+
userAgent?: string;
|
|
793
|
+
ip?: string;
|
|
794
|
+
metadata?: Record<string, unknown>;
|
|
795
|
+
createdAt: Date;
|
|
617
796
|
}
|
|
797
|
+
declare function buildEmailEventSchema(config: SchemaBuildConfig): Schema<IEmailEventDocument>;
|
|
798
|
+
declare function createEmailEventModel(connection: Connection, config: SchemaBuildConfig): Model<IEmailEventDocument>;
|
|
618
799
|
//#endregion
|
|
619
|
-
//#region src/
|
|
800
|
+
//#region src/enums/conversation.d.ts
|
|
620
801
|
/**
|
|
621
|
-
*
|
|
622
|
-
* firmographic model, in-app signals, ML prediction, external enrichment.
|
|
802
|
+
* Conversation / Message vocabulary.
|
|
623
803
|
*
|
|
624
|
-
*
|
|
625
|
-
*
|
|
626
|
-
*
|
|
804
|
+
* Conversations unify a contact's (or pre-conversion lead's) message
|
|
805
|
+
* thread across channels (WhatsApp / Telegram / Email / IG-DM / SMS).
|
|
806
|
+
* The host's webhook adapters write to this surface — the CRM does not
|
|
807
|
+
* dial outward.
|
|
627
808
|
*/
|
|
628
|
-
|
|
809
|
+
declare const CONVERSATION_CHANNELS: readonly ["whatsapp", "telegram", "email", "instagram_dm", "sms", "web_chat"];
|
|
810
|
+
type ConversationChannel = (typeof CONVERSATION_CHANNELS)[number];
|
|
811
|
+
declare const CONVERSATION_STATUSES: readonly ["open", "snoozed", "resolved"];
|
|
812
|
+
type ConversationStatus = (typeof CONVERSATION_STATUSES)[number];
|
|
813
|
+
/** Conversations attach to either a Contact or a (yet-unconverted) Lead. */
|
|
814
|
+
declare const CONVERSATION_PARTICIPANT_KINDS: readonly ["contact", "lead"];
|
|
815
|
+
type ConversationParticipantKind = (typeof CONVERSATION_PARTICIPANT_KINDS)[number];
|
|
816
|
+
declare const MESSAGE_DIRECTIONS: readonly ["inbound", "outbound"];
|
|
817
|
+
type MessageDirection = (typeof MESSAGE_DIRECTIONS)[number];
|
|
818
|
+
declare const MESSAGE_DELIVERY_STATUSES: readonly ["queued", "sent", "delivered", "read", "failed"];
|
|
819
|
+
type MessageDeliveryStatus = (typeof MESSAGE_DELIVERY_STATUSES)[number];
|
|
820
|
+
//#endregion
|
|
821
|
+
//#region src/models/conversation.schema.d.ts
|
|
822
|
+
interface IConversationDocument {
|
|
823
|
+
_id: mongoose1.Types.ObjectId;
|
|
824
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
825
|
+
channel: ConversationChannel;
|
|
826
|
+
participantKind: ConversationParticipantKind;
|
|
827
|
+
participantId: mongoose1.Types.ObjectId | string;
|
|
828
|
+
/** Channel-side identifier (e.g. WhatsApp wa_id, Telegram chat id). */
|
|
829
|
+
channelUserId?: string;
|
|
830
|
+
status: ConversationStatus;
|
|
831
|
+
/** Last message timestamp — surfaced for inbox sort + idle SLAs. */
|
|
832
|
+
lastMessageAt?: Date;
|
|
833
|
+
/** Unread inbound count. Reset to 0 on `markRead`. */
|
|
834
|
+
unreadCount: number;
|
|
835
|
+
/** Assignee. Stored as a string so hosts can use either userId or a queue id. */
|
|
836
|
+
assigneeId?: string;
|
|
837
|
+
/** Free-form bag — channel-specific settings (preview text, IMAP folder). */
|
|
838
|
+
metadata?: Record<string, unknown>;
|
|
839
|
+
createdAt: Date;
|
|
840
|
+
updatedAt: Date;
|
|
841
|
+
}
|
|
842
|
+
declare function buildConversationSchema(config: SchemaBuildConfig): Schema<IConversationDocument>;
|
|
843
|
+
declare function createConversationModel(connection: Connection, config: SchemaBuildConfig): Model<IConversationDocument>;
|
|
844
|
+
//#endregion
|
|
845
|
+
//#region src/models/message.schema.d.ts
|
|
846
|
+
interface IMessageAttachment {
|
|
847
|
+
type: string;
|
|
848
|
+
url: string;
|
|
849
|
+
name?: string;
|
|
850
|
+
size?: number;
|
|
851
|
+
mimeType?: string;
|
|
852
|
+
}
|
|
853
|
+
interface IMessageDocument {
|
|
854
|
+
_id: mongoose1.Types.ObjectId;
|
|
855
|
+
organizationId: mongoose1.Types.ObjectId | string;
|
|
856
|
+
conversationId: mongoose1.Types.ObjectId | string;
|
|
857
|
+
direction: MessageDirection;
|
|
858
|
+
body: string;
|
|
859
|
+
attachments: IMessageAttachment[];
|
|
860
|
+
/** Provider-side id — webhook dedup key. */
|
|
861
|
+
externalMessageId?: string;
|
|
862
|
+
status: MessageDeliveryStatus;
|
|
863
|
+
/** Channel id of the sender (phone number, email, telegram id). */
|
|
864
|
+
senderRef?: string;
|
|
865
|
+
/** Channel id of the recipient. */
|
|
866
|
+
recipientRef?: string;
|
|
867
|
+
/** When the wire said it left / arrived; falls back to createdAt. */
|
|
868
|
+
sentAt?: Date;
|
|
869
|
+
metadata?: Record<string, unknown>;
|
|
870
|
+
createdAt: Date;
|
|
871
|
+
updatedAt: Date;
|
|
872
|
+
}
|
|
873
|
+
declare function buildMessageSchema(config: SchemaBuildConfig): Schema<IMessageDocument>;
|
|
874
|
+
declare function createMessageModel(connection: Connection, config: SchemaBuildConfig): Model<IMessageDocument>;
|
|
875
|
+
//#endregion
|
|
876
|
+
//#region src/models/create-models.d.ts
|
|
877
|
+
interface CrmModels {
|
|
878
|
+
Pipeline: Model<IPipelineDocument>;
|
|
879
|
+
Lead: Model<ILeadDocument>;
|
|
880
|
+
Opportunity: Model<IOpportunityDocument>;
|
|
881
|
+
Contact: Model<IContactDocument>;
|
|
882
|
+
Account: Model<IAccountDocument>;
|
|
883
|
+
Campaign: Model<ICampaignDocument>;
|
|
884
|
+
Subscription: Model<ISubscriptionDocument>;
|
|
885
|
+
Activity: Model<IActivityDocument>;
|
|
886
|
+
Note: Model<INoteDocument>;
|
|
887
|
+
LossReason: Model<ILossReasonDocument>;
|
|
888
|
+
EmailEvent: Model<IEmailEventDocument>;
|
|
889
|
+
Conversation: Model<IConversationDocument>;
|
|
890
|
+
Message: Model<IMessageDocument>;
|
|
891
|
+
}
|
|
892
|
+
/** Mongoose model names this package registers — drives the §21 collision check. */
|
|
893
|
+
declare const CRM_MODEL_NAMES: readonly ["Pipeline", "Lead", "Opportunity", "Contact", "Account", "Campaign", "EmailSubscription", "Activity", "Note", "LossReason", "EmailEvent", "Conversation", "Message"];
|
|
894
|
+
interface CreateModelsOptions extends SchemaBuildConfig {
|
|
895
|
+
/**
|
|
896
|
+
* On a model-name collision: `false` (default) throws
|
|
897
|
+
* `CrmModelCollisionError`; `true` deletes + re-registers (test
|
|
898
|
+
* fixtures / hot reload only).
|
|
899
|
+
*/
|
|
900
|
+
forceRecreate?: boolean;
|
|
901
|
+
/** Mongoose auto-index builds. Default `true` (dev); `false` in prod. */
|
|
902
|
+
autoIndex?: boolean;
|
|
903
|
+
}
|
|
904
|
+
declare function createCrmModels(connection: Connection, config: CreateModelsOptions): CrmModels;
|
|
905
|
+
//#endregion
|
|
906
|
+
//#region src/repositories/pipeline.repository.d.ts
|
|
907
|
+
interface PipelineRepositoryDeps {
|
|
908
|
+
events: EventTransport;
|
|
909
|
+
}
|
|
910
|
+
declare class PipelineRepository extends Repository<IPipelineDocument> {
|
|
911
|
+
private readonly events;
|
|
912
|
+
constructor(model: Model<IPipelineDocument>, plugins: PluginType[], deps: PipelineRepositoryDeps, pagination?: PaginationConfig);
|
|
913
|
+
/**
|
|
914
|
+
* Read a single embedded stage. Used by Opportunity create / move to
|
|
915
|
+
* validate stage membership + pick up `defaultProbability`.
|
|
916
|
+
*/
|
|
917
|
+
getStage(pipelineId: string, stageId: string, ctx?: CrmContext): Promise<IStageDocument>;
|
|
918
|
+
/** First stage by `sequence` ascending. */
|
|
919
|
+
getFirstStage(pipelineId: string, ctx?: CrmContext): Promise<IStageDocument>;
|
|
920
|
+
/** Stage immediately after the given one. `null` at terminal stage. */
|
|
921
|
+
getNextStage(pipelineId: string, stageId: string, ctx?: CrmContext): Promise<IStageDocument | null>;
|
|
922
|
+
/** Soft-deprecate — existing opps still move; no new ones can be created. */
|
|
923
|
+
archive(id: string, ctx?: CrmContext): Promise<IPipelineDocument>;
|
|
924
|
+
}
|
|
925
|
+
//#endregion
|
|
926
|
+
//#region src/shared/calculators/scoring.d.ts
|
|
927
|
+
/** Minimal Lead shape the scorer reads. */
|
|
928
|
+
type LeadInput = Pick<ILeadDocument, 'email' | 'phone' | 'companyName' | 'tags' | 'jobTitle'>;
|
|
929
|
+
type LeadScorer = (lead: LeadInput) => number;
|
|
629
930
|
/**
|
|
630
|
-
* Reference implementation. Intentionally simple
|
|
631
|
-
*
|
|
931
|
+
* Reference implementation. Intentionally simple — hosts read it and
|
|
932
|
+
* replace it.
|
|
632
933
|
*
|
|
633
934
|
* +20 if email is present
|
|
634
935
|
* +20 if phone is present
|
|
635
936
|
* +20 if companyName is present
|
|
636
937
|
* +10 per populated tag up to 40
|
|
637
|
-
* +10 if jobTitle
|
|
638
|
-
*/
|
|
639
|
-
declare function defaultLeadScorer(lead: Lead): number;
|
|
640
|
-
/**
|
|
641
|
-
* Compose a scoring pipeline — each rule returns an increment
|
|
642
|
-
* (positive or negative). Useful when host logic is a bunch of
|
|
643
|
-
* small, testable rules.
|
|
644
|
-
*
|
|
645
|
-
* @example
|
|
646
|
-
* ```ts
|
|
647
|
-
* const scorer = composeScorers(
|
|
648
|
-
* (l) => (l.email ? 20 : 0),
|
|
649
|
-
* (l) => (l.source === 'referral' ? 30 : 0),
|
|
650
|
-
* (l) => (l.tags?.includes('enterprise') ? 50 : 0),
|
|
651
|
-
* );
|
|
652
|
-
* ```
|
|
938
|
+
* +10 if jobTitle hints senior (director / manager / head / chief / vp / founder)
|
|
653
939
|
*/
|
|
940
|
+
declare function defaultLeadScorer(lead: LeadInput): number;
|
|
941
|
+
/** Compose multiple small rules into one scorer. */
|
|
654
942
|
declare function composeScorers(...rules: readonly LeadScorer[]): LeadScorer;
|
|
655
943
|
//#endregion
|
|
656
|
-
//#region src/
|
|
657
|
-
interface
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
}
|
|
661
|
-
interface LeadContactWriter {
|
|
662
|
-
create(input: CreateContactInput, options?: MutationOptions): Promise<Contact>;
|
|
663
|
-
delete?(id: string): Promise<void>;
|
|
664
|
-
}
|
|
665
|
-
interface LeadOpportunityWriter {
|
|
666
|
-
create(input: CreateOpportunityInput, options?: MutationOptions): Promise<Opportunity>;
|
|
667
|
-
delete?(id: string): Promise<void>;
|
|
668
|
-
}
|
|
669
|
-
interface LeadServiceConfig {
|
|
670
|
-
repo: LeadRepository;
|
|
671
|
-
contacts: LeadContactWriter;
|
|
672
|
-
accounts: LeadAccountWriter;
|
|
673
|
-
opportunities: LeadOpportunityWriter;
|
|
674
|
-
events?: EventTransport | undefined;
|
|
675
|
-
/** Optional host-owned outbox. See AccountServiceConfig.outbox. */
|
|
676
|
-
outbox?: OutboxStore | undefined;
|
|
677
|
-
clock?: Clock;
|
|
678
|
-
ids?: IdGenerator;
|
|
679
|
-
/** Override the default scorer (`defaultLeadScorer`). */
|
|
944
|
+
//#region src/repositories/lead.repository.d.ts
|
|
945
|
+
interface LeadRepositoryDeps {
|
|
946
|
+
events: EventTransport;
|
|
947
|
+
/** Override the default lead scorer. */
|
|
680
948
|
scorer?: LeadScorer;
|
|
681
|
-
/**
|
|
949
|
+
/** Reject `create()` when an email already exists in-tenant (default true). */
|
|
682
950
|
rejectDuplicates?: boolean;
|
|
683
951
|
}
|
|
684
|
-
|
|
685
|
-
firstName?: string;
|
|
686
|
-
lastName?: string;
|
|
687
|
-
fullName?: string;
|
|
688
|
-
email?: string;
|
|
689
|
-
phone?: string;
|
|
690
|
-
companyName?: string;
|
|
691
|
-
jobTitle?: string;
|
|
692
|
-
source?: string;
|
|
693
|
-
campaignRef?: string;
|
|
694
|
-
ownerId?: string;
|
|
695
|
-
tags?: readonly string[];
|
|
696
|
-
metadata?: Record<string, unknown>;
|
|
697
|
-
}
|
|
698
|
-
interface ConvertLeadInput {
|
|
699
|
-
/** Pipeline the resulting opportunity enters. */
|
|
700
|
-
pipelineId: string;
|
|
701
|
-
/** Opportunity name. Defaults to `<lead.companyName> — <lead.fullName>`. */
|
|
702
|
-
opportunityName?: string;
|
|
703
|
-
/** Optional deal amount. */
|
|
704
|
-
amount?: Money;
|
|
705
|
-
expectedCloseAt?: Date;
|
|
952
|
+
type TransitionExtras = {
|
|
706
953
|
by?: string;
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
accountId?: string;
|
|
712
|
-
opportunityId: string;
|
|
713
|
-
}
|
|
714
|
-
/**
|
|
715
|
-
* Lead lifecycle + the crown-jewel `convert()` verb that atomically
|
|
716
|
-
* spawns a Contact + Account + Opportunity and transitions the lead
|
|
717
|
-
* to `converted`.
|
|
718
|
-
*/
|
|
719
|
-
declare class LeadService {
|
|
720
|
-
private readonly repo;
|
|
721
|
-
private readonly contacts;
|
|
722
|
-
private readonly accounts;
|
|
723
|
-
private readonly opportunities;
|
|
954
|
+
note?: string;
|
|
955
|
+
patch?: Partial<ILeadDocument>;
|
|
956
|
+
};
|
|
957
|
+
declare class LeadRepository extends Repository<ILeadDocument> {
|
|
724
958
|
private readonly events;
|
|
725
|
-
private readonly outbox;
|
|
726
|
-
private readonly clock;
|
|
727
|
-
private readonly ids;
|
|
728
959
|
private readonly scorer;
|
|
729
960
|
private readonly rejectDuplicates;
|
|
730
|
-
constructor(
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
961
|
+
constructor(model: Model<ILeadDocument>, plugins: PluginType[], deps: LeadRepositoryDeps, pagination?: PaginationConfig);
|
|
962
|
+
/**
|
|
963
|
+
* Create a Lead. Auto-scores on insert so hosts can route immediately.
|
|
964
|
+
* Rejects duplicate emails inside the same tenant unless
|
|
965
|
+
* `rejectDuplicates: false` was set at engine boot.
|
|
966
|
+
*/
|
|
967
|
+
createLead(input: Partial<ILeadDocument>, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
968
|
+
markContacted(id: string, extras?: TransitionExtras, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
969
|
+
qualify(id: string, extras?: TransitionExtras, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
970
|
+
disqualify(id: string, reason: string, extras?: Omit<TransitionExtras, 'patch'>, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
971
|
+
nurture(id: string, extras?: TransitionExtras, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
972
|
+
/**
|
|
973
|
+
* Merge enrichment payload (3rd-party provider response or manual
|
|
974
|
+
* patch) into the lead doc, then re-score. Emits `crm:lead.enriched`
|
|
975
|
+
* with the field set written so subscribers can fan out (e.g. push a
|
|
976
|
+
* `recompute_segment` job) without re-reading the doc.
|
|
977
|
+
*
|
|
978
|
+
* The `provider` tag flows into the event for attribution; the package
|
|
979
|
+
* is provider-agnostic so the actual enrichment call lives at the host.
|
|
980
|
+
*/
|
|
981
|
+
enrich(id: string, patch: Partial<ILeadDocument>, extras?: {
|
|
982
|
+
provider?: string;
|
|
983
|
+
}, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
984
|
+
/**
|
|
985
|
+
* Assign / re-assign the lead's owner. Emits `crm:lead.assigned` with
|
|
986
|
+
* the previous owner so audit consumers can compute hand-off chains.
|
|
987
|
+
*/
|
|
988
|
+
assign(id: string, ownerId: string, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
989
|
+
/**
|
|
990
|
+
* Recompute + persist the lead's score. Called from `createLead`
|
|
991
|
+
* automatically; hosts also call this after enrichment writes.
|
|
992
|
+
*/
|
|
993
|
+
recomputeScore(id: string, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
743
994
|
private _transition;
|
|
744
|
-
|
|
995
|
+
/**
|
|
996
|
+
* Count leads created on or after `since`. Used by dashboard KPI tiles.
|
|
997
|
+
* Goes through the inherited tenant-scoped `count()` — the plugin
|
|
998
|
+
* injects `organizationId` (never a manual `if (ctx)` filter, which
|
|
999
|
+
* silently reads ALL tenants when ctx is absent).
|
|
1000
|
+
*/
|
|
1001
|
+
countCreatedSince(since: Date, ctx?: CrmContext): Promise<number>;
|
|
1002
|
+
/** Latest `limit` leads — lightweight projection for the activity feed. */
|
|
1003
|
+
findRecentForFeed(limit: number, ctx?: CrmContext): Promise<ILeadDocument[]>;
|
|
745
1004
|
}
|
|
746
1005
|
//#endregion
|
|
747
|
-
//#region src/
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
*/
|
|
753
|
-
interface Stage {
|
|
754
|
-
id: string;
|
|
755
|
-
name: string;
|
|
756
|
-
sequence: number;
|
|
757
|
-
/** Default win probability (0-1) assigned to opportunities entering this stage. */
|
|
758
|
-
defaultProbability: number;
|
|
759
|
-
/** Optional UX hint for color-coded kanbans. */
|
|
760
|
-
color?: string;
|
|
761
|
-
/** Describes what "reaching this stage" means. */
|
|
762
|
-
description?: string;
|
|
1006
|
+
//#region src/repositories/opportunity.repository.d.ts
|
|
1007
|
+
interface OpportunityRepositoryDeps {
|
|
1008
|
+
events: EventTransport;
|
|
1009
|
+
/** Cross-repo reference: read embedded stages from Pipeline. */
|
|
1010
|
+
pipelines: PipelineRepository;
|
|
763
1011
|
}
|
|
764
|
-
|
|
765
|
-
* A Pipeline groups ordered Stages for a specific sales motion. Hosts
|
|
766
|
-
* typically have 1-N pipelines (e.g. `new-business`, `expansion`,
|
|
767
|
-
* `partnerships`, `renewals`). Opportunities pin to exactly one
|
|
768
|
-
* pipeline at create time.
|
|
769
|
-
*/
|
|
770
|
-
interface Pipeline {
|
|
771
|
-
id: string;
|
|
1012
|
+
interface OpenOpportunityInput {
|
|
772
1013
|
name: string;
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1014
|
+
pipelineId: string;
|
|
1015
|
+
/** When omitted, opp enters the pipeline's first stage. */
|
|
1016
|
+
stageId?: string;
|
|
1017
|
+
accountId?: string;
|
|
1018
|
+
primaryContactId?: string;
|
|
1019
|
+
sourceLeadId?: string;
|
|
1020
|
+
amount?: number;
|
|
1021
|
+
currency?: string;
|
|
1022
|
+
/** Override the stage's `defaultProbability`. */
|
|
1023
|
+
probability?: number;
|
|
1024
|
+
expectedCloseAt?: Date;
|
|
1025
|
+
ownerId?: string;
|
|
1026
|
+
tags?: readonly string[];
|
|
778
1027
|
metadata?: Record<string, unknown>;
|
|
779
|
-
createdAt: Date;
|
|
780
|
-
updatedAt: Date;
|
|
781
1028
|
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
update(id: string, patch: Partial<Pipeline>): Promise<Pipeline>;
|
|
1029
|
+
interface MoveStageInput {
|
|
1030
|
+
stageId: string;
|
|
1031
|
+
by?: string;
|
|
1032
|
+
note?: string;
|
|
1033
|
+
/** Override the target stage's `defaultProbability`. */
|
|
1034
|
+
probability?: number;
|
|
789
1035
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
outbox?: OutboxStore | undefined;
|
|
797
|
-
clock?: Clock;
|
|
798
|
-
ids?: IdGenerator;
|
|
799
|
-
}
|
|
800
|
-
interface CreatePipelineInput {
|
|
801
|
-
name: string;
|
|
802
|
-
stages: readonly Omit<Stage, 'id'>[];
|
|
803
|
-
teamRef?: string;
|
|
804
|
-
metadata?: Record<string, unknown>;
|
|
1036
|
+
interface CloseInput {
|
|
1037
|
+
by?: string;
|
|
1038
|
+
note?: string;
|
|
1039
|
+
closedAt?: Date;
|
|
1040
|
+
amount?: number;
|
|
1041
|
+
lostReasonId?: string;
|
|
805
1042
|
}
|
|
806
|
-
|
|
807
|
-
* Pipeline lifecycle + stage helpers. The service owns stage id
|
|
808
|
-
* generation so callers don't have to — create a pipeline with an
|
|
809
|
-
* array of stage seeds and the service hands back the persisted
|
|
810
|
-
* pipeline with ids assigned.
|
|
811
|
-
*/
|
|
812
|
-
declare class PipelineService {
|
|
813
|
-
private readonly repo;
|
|
1043
|
+
declare class OpportunityRepository extends Repository<IOpportunityDocument> {
|
|
814
1044
|
private readonly events;
|
|
815
|
-
private readonly
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
constructor(config: PipelineServiceConfig);
|
|
819
|
-
create(input: CreatePipelineInput, options?: MutationOptions): Promise<Pipeline>;
|
|
820
|
-
archive(id: string, options?: MutationOptions): Promise<Pipeline>;
|
|
821
|
-
getStage(pipelineId: string, stageId: string): Promise<Stage>;
|
|
822
|
-
/** First stage in the ordered pipeline (minimum `sequence`). */
|
|
823
|
-
getFirstStage(pipelineId: string): Promise<Stage>;
|
|
824
|
-
/** Next stage after `stageId` in the ordered pipeline, or `null` at the end. */
|
|
825
|
-
getNextStage(pipelineId: string, stageId: string): Promise<Stage | null>;
|
|
826
|
-
findById(id: string): Promise<Pipeline | null>;
|
|
827
|
-
list(includeArchived?: boolean): Promise<Pipeline[]>;
|
|
828
|
-
private _require;
|
|
829
|
-
private _emit;
|
|
830
|
-
}
|
|
831
|
-
//#endregion
|
|
832
|
-
//#region src/services/forecast.d.ts
|
|
833
|
-
interface ForecastRow {
|
|
834
|
-
/** Bucket key — typically ISO month `YYYY-MM` derived from `expectedCloseAt`. */
|
|
835
|
-
bucket: string;
|
|
836
|
-
/** Sum of unweighted `amount`. */
|
|
837
|
-
committed: number;
|
|
838
|
-
/** Sum of `amount × probability`. */
|
|
839
|
-
weighted: number;
|
|
840
|
-
/** Count of opportunities contributing. */
|
|
841
|
-
count: number;
|
|
842
|
-
currency: string;
|
|
843
|
-
}
|
|
844
|
-
interface ForecastOptions {
|
|
1045
|
+
private readonly pipelines;
|
|
1046
|
+
constructor(model: Model<IOpportunityDocument>, plugins: PluginType[], deps: OpportunityRepositoryDeps, pagination?: PaginationConfig);
|
|
1047
|
+
openOpportunity(input: OpenOpportunityInput, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
845
1048
|
/**
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
*
|
|
1049
|
+
* Atomic stage move. CAS on `(status='open', stageId=current)` so two
|
|
1050
|
+
* concurrent moves can't both win. Emits `stage_advanced` or
|
|
1051
|
+
* `stage_regressed` based on `sequence` ordering of the embedded stages.
|
|
849
1052
|
*/
|
|
850
|
-
|
|
1053
|
+
moveToStage(id: string, input: MoveStageInput, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
1054
|
+
win(id: string, input?: CloseInput, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
1055
|
+
lose(id: string, input?: CloseInput, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
851
1056
|
/**
|
|
852
|
-
*
|
|
853
|
-
* `
|
|
1057
|
+
* Re-assign opportunity owner. Mutates `ownerId` only; no status
|
|
1058
|
+
* transition. Emits `crm:opportunity.assigned` with the previous owner.
|
|
854
1059
|
*/
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1060
|
+
assign(id: string, ownerId: string, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
1061
|
+
/**
|
|
1062
|
+
* Adjust the deal amount on an open opportunity. Rejected after
|
|
1063
|
+
* win/lose/abandon — closed-deal amounts are immutable history.
|
|
1064
|
+
* Emits `crm:opportunity.amount_changed` with the delta so forecast
|
|
1065
|
+
* subscribers can re-bucket.
|
|
1066
|
+
*/
|
|
1067
|
+
updateAmount(id: string, amount: number, extras?: {
|
|
1068
|
+
reason?: string;
|
|
1069
|
+
by?: string;
|
|
1070
|
+
}, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
1071
|
+
/**
|
|
1072
|
+
* Push `expectedCloseAt` further out. Only valid on open opps —
|
|
1073
|
+
* extending a closed deal is meaningless. The new date must be later
|
|
1074
|
+
* than the current one; pulling the date in is silently accepted
|
|
1075
|
+
* (no event is meaningful there).
|
|
1076
|
+
*/
|
|
1077
|
+
extendCloseDate(id: string, newDate: Date, extras?: {
|
|
1078
|
+
reason?: string;
|
|
1079
|
+
by?: string;
|
|
1080
|
+
}, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
1081
|
+
abandon(id: string, by?: string, note?: string, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
1082
|
+
private _closeStatus;
|
|
1083
|
+
/** Count opportunities with status `open`. Used by dashboard KPI tiles. */
|
|
1084
|
+
countOpen(ctx?: CrmContext): Promise<number>;
|
|
1085
|
+
/**
|
|
1086
|
+
* Sum `amount` on won opportunities updated within `since`.
|
|
1087
|
+
* Goes through the tenant-scoped `findAll()` — the multiTenant plugin
|
|
1088
|
+
* injects `organizationId`, so a missing ctx can't leak other tenants'
|
|
1089
|
+
* revenue (a manual `if (ctx)` filter would).
|
|
1090
|
+
*/
|
|
1091
|
+
sumWonSince(since: Date, ctx?: CrmContext): Promise<{
|
|
1092
|
+
total: number;
|
|
1093
|
+
currency?: string;
|
|
1094
|
+
} | null>;
|
|
1095
|
+
/** Latest `limit` opportunities — lightweight projection for the activity feed. */
|
|
1096
|
+
findRecentForFeed(limit: number, ctx?: CrmContext): Promise<IOpportunityDocument[]>;
|
|
878
1097
|
}
|
|
879
|
-
declare function pipelineConversion(opportunities: readonly Opportunity[], stageIds: readonly string[]): ConversionRow[];
|
|
880
1098
|
//#endregion
|
|
881
|
-
//#region src/
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
createdAt: Date;
|
|
897
|
-
updatedAt: Date;
|
|
1099
|
+
//#region src/repositories/contact.repository.d.ts
|
|
1100
|
+
interface ContactRepositoryDeps {
|
|
1101
|
+
events: EventTransport;
|
|
1102
|
+
}
|
|
1103
|
+
interface MergeContactInput {
|
|
1104
|
+
/** Surviving contact id. Receives merged fields. */
|
|
1105
|
+
primaryId: string;
|
|
1106
|
+
/** Secondary contact id. Deleted after merge. */
|
|
1107
|
+
secondaryId: string;
|
|
1108
|
+
/**
|
|
1109
|
+
* Per-field strategy. Defaults to `'preferPrimary'` — primary's
|
|
1110
|
+
* non-empty fields win, secondary fills the gaps. Use `'preferSecondary'`
|
|
1111
|
+
* for the reverse. `tags` are always unioned.
|
|
1112
|
+
*/
|
|
1113
|
+
strategy?: 'preferPrimary' | 'preferSecondary';
|
|
898
1114
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1115
|
+
declare class ContactRepository extends Repository<IContactDocument> {
|
|
1116
|
+
private readonly events;
|
|
1117
|
+
constructor(model: Model<IContactDocument>, plugins: PluginType[], deps: ContactRepositoryDeps, pagination?: PaginationConfig);
|
|
1118
|
+
/**
|
|
1119
|
+
* Create + emit `crm:contact.created`. Hosts call this instead of
|
|
1120
|
+
* `create()` when they want the event side-effect (e.g. webhook fan-out).
|
|
1121
|
+
*/
|
|
1122
|
+
createContact(input: Partial<IContactDocument>, ctx?: CrmContext): Promise<IContactDocument>;
|
|
1123
|
+
/**
|
|
1124
|
+
* Merge enrichment payload into the contact. The `patch` is applied
|
|
1125
|
+
* verbatim; deep-merge of `contact.*` channels is the caller's job
|
|
1126
|
+
* (they own the provider response shape).
|
|
1127
|
+
*/
|
|
1128
|
+
enrich(id: string, patch: Partial<IContactDocument>, extras?: {
|
|
1129
|
+
provider?: string;
|
|
1130
|
+
}, ctx?: CrmContext): Promise<IContactDocument>;
|
|
1131
|
+
/** Set / re-assign the contact's owner. Atomic; no-op when unchanged. */
|
|
1132
|
+
assign(id: string, ownerId: string, ctx?: CrmContext): Promise<IContactDocument>;
|
|
1133
|
+
/**
|
|
1134
|
+
* Merge two contacts. Secondary's non-conflicting fields are folded
|
|
1135
|
+
* into primary, tags are unioned, then secondary is deleted.
|
|
1136
|
+
*
|
|
1137
|
+
* Hosts wanting transactional safety can pass `ctx.session` —
|
|
1138
|
+
* mongokit threads it through `update` + `delete`.
|
|
1139
|
+
*
|
|
1140
|
+
* Re-pointing related Activities / Notes / Opportunities is the host's
|
|
1141
|
+
* job (they own those relationships) — subscribe to
|
|
1142
|
+
* `crm:contact.merged` and rewrite `subjectId` / `primaryContactId`
|
|
1143
|
+
* from there.
|
|
1144
|
+
*/
|
|
1145
|
+
merge(input: MergeContactInput, ctx?: CrmContext): Promise<IContactDocument>;
|
|
906
1146
|
}
|
|
907
1147
|
//#endregion
|
|
908
|
-
//#region src/
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
* real emails / SMS / etc. via the host's pipeline. This package does
|
|
912
|
-
* NOT call it automatically — hosts subscribe to `crm:activity.*`
|
|
913
|
-
* events and call `outreach.send()` from their own handler so pacing,
|
|
914
|
-
* retry, and bounce handling live where they belong.
|
|
915
|
-
*
|
|
916
|
-
* The port intentionally stays minimal; implementations forward to
|
|
917
|
-
* SendGrid, Postmark, Twilio, Mailgun, or an in-house SMTP stack.
|
|
918
|
-
*/
|
|
919
|
-
interface OutreachSendRequest {
|
|
920
|
-
channel: 'email' | 'sms' | 'social' | string;
|
|
921
|
-
toAddress: string;
|
|
922
|
-
subject?: string;
|
|
923
|
-
body: string;
|
|
924
|
-
activityId?: string;
|
|
925
|
-
/** Host metadata — template id, campaign ref, personalization vars. */
|
|
926
|
-
metadata?: Record<string, unknown>;
|
|
1148
|
+
//#region src/repositories/account.repository.d.ts
|
|
1149
|
+
interface AccountRepositoryDeps {
|
|
1150
|
+
events: EventTransport;
|
|
927
1151
|
}
|
|
928
|
-
interface
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
1152
|
+
interface MergeAccountInput {
|
|
1153
|
+
primaryId: string;
|
|
1154
|
+
secondaryId: string;
|
|
1155
|
+
strategy?: 'preferPrimary' | 'preferSecondary';
|
|
932
1156
|
}
|
|
933
|
-
|
|
934
|
-
|
|
1157
|
+
declare class AccountRepository extends Repository<IAccountDocument> {
|
|
1158
|
+
private readonly events;
|
|
1159
|
+
constructor(model: Model<IAccountDocument>, plugins: PluginType[], deps: AccountRepositoryDeps, pagination?: PaginationConfig);
|
|
1160
|
+
createAccount(input: Partial<IAccountDocument>, ctx?: CrmContext): Promise<IAccountDocument>;
|
|
1161
|
+
enrich(id: string, patch: Partial<IAccountDocument>, extras?: {
|
|
1162
|
+
provider?: string;
|
|
1163
|
+
}, ctx?: CrmContext): Promise<IAccountDocument>;
|
|
1164
|
+
assign(id: string, ownerId: string, ctx?: CrmContext): Promise<IAccountDocument>;
|
|
1165
|
+
merge(input: MergeAccountInput, ctx?: CrmContext): Promise<IAccountDocument>;
|
|
935
1166
|
}
|
|
936
1167
|
//#endregion
|
|
937
|
-
//#region src/
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
findById(id: string): Promise<Account | null>;
|
|
943
|
-
findByDomain(domain: string): Promise<Account | null>;
|
|
944
|
-
list(filter?: AccountFilter): Promise<Account[]>;
|
|
945
|
-
create(input: Omit<Account, 'createdAt' | 'updatedAt'>): Promise<Account>;
|
|
946
|
-
update(id: string, patch: Partial<Account>): Promise<Account>;
|
|
947
|
-
delete(id: string): Promise<void>;
|
|
1168
|
+
//#region src/repositories/campaign.repository.d.ts
|
|
1169
|
+
interface CampaignRepositoryDeps {
|
|
1170
|
+
events: EventTransport;
|
|
1171
|
+
/** Reject `createCampaign` on duplicate names per-tenant (default true). */
|
|
1172
|
+
rejectDuplicates?: boolean;
|
|
948
1173
|
}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1174
|
+
type ExtrasWithRevenue = {
|
|
1175
|
+
by?: string;
|
|
1176
|
+
note?: string;
|
|
1177
|
+
actualRevenueAmount?: number;
|
|
1178
|
+
};
|
|
1179
|
+
declare class CampaignRepository extends Repository<ICampaignDocument> {
|
|
1180
|
+
private readonly events;
|
|
1181
|
+
private readonly rejectDuplicates;
|
|
1182
|
+
constructor(model: Model<ICampaignDocument>, plugins: PluginType[], deps: CampaignRepositoryDeps, pagination?: PaginationConfig);
|
|
1183
|
+
createCampaign(input: Partial<ICampaignDocument>, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
1184
|
+
activate(id: string, by?: string, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
1185
|
+
pause(id: string, reason?: string, by?: string, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
1186
|
+
resume(id: string, by?: string, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
1187
|
+
complete(id: string, extras?: ExtrasWithRevenue, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
1188
|
+
archive(id: string, by?: string, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
1189
|
+
private _transition;
|
|
960
1190
|
}
|
|
961
1191
|
//#endregion
|
|
962
|
-
//#region src/
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
findById(id: string): Promise<Contact | null>;
|
|
968
|
-
findByEmail(email: string): Promise<Contact | null>;
|
|
969
|
-
list(filter?: ContactFilter): Promise<Contact[]>;
|
|
970
|
-
create(input: Omit<Contact, 'createdAt' | 'updatedAt'>): Promise<Contact>;
|
|
971
|
-
update(id: string, patch: Partial<Contact>): Promise<Contact>;
|
|
972
|
-
delete(id: string): Promise<void>;
|
|
1192
|
+
//#region src/repositories/subscription.repository.d.ts
|
|
1193
|
+
interface SubscriptionRepositoryDeps {
|
|
1194
|
+
events: EventTransport;
|
|
1195
|
+
/** Default DOI policy when `subscribe` doesn't pass `requireDoubleOptIn`. */
|
|
1196
|
+
defaultRequireDoubleOptIn?: boolean;
|
|
973
1197
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1198
|
+
interface SubscribeInput {
|
|
1199
|
+
contactId: string;
|
|
1200
|
+
campaignId: string;
|
|
1201
|
+
source?: string;
|
|
1202
|
+
consentIpAddress?: string;
|
|
1203
|
+
consentUserAgent?: string;
|
|
1204
|
+
metadata?: Record<string, unknown>;
|
|
1205
|
+
/** Override the engine-level default. */
|
|
1206
|
+
requireDoubleOptIn?: boolean;
|
|
983
1207
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
update(id: string, patch: Partial<Lead>): Promise<Lead>;
|
|
995
|
-
casStatus(id: string, expected: LeadStatus, next: LeadStatus, patch?: Partial<Lead>): Promise<Lead | null>;
|
|
1208
|
+
declare class SubscriptionRepository extends Repository<ISubscriptionDocument> {
|
|
1209
|
+
private readonly events;
|
|
1210
|
+
private readonly defaultRequireDoubleOptIn;
|
|
1211
|
+
constructor(model: Model<ISubscriptionDocument>, plugins: PluginType[], deps: SubscriptionRepositoryDeps, pagination?: PaginationConfig);
|
|
1212
|
+
subscribe(input: SubscribeInput, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
1213
|
+
confirm(token: string, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
1214
|
+
unsubscribe(token: string, reason?: string, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
1215
|
+
markBounced(id: string, reason?: string, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
1216
|
+
markComplained(id: string, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
1217
|
+
private _transition;
|
|
996
1218
|
}
|
|
997
1219
|
//#endregion
|
|
998
|
-
//#region src/
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
private readonly items;
|
|
1002
|
-
constructor(clock?: Clock);
|
|
1003
|
-
findById(id: string): Promise<LossReason | null>;
|
|
1004
|
-
list(activeOnly?: boolean): Promise<LossReason[]>;
|
|
1005
|
-
create(input: Omit<LossReason, 'createdAt' | 'updatedAt'>): Promise<LossReason>;
|
|
1006
|
-
update(id: string, patch: Partial<LossReason>): Promise<LossReason>;
|
|
1220
|
+
//#region src/repositories/activity.repository.d.ts
|
|
1221
|
+
interface ActivityRepositoryDeps {
|
|
1222
|
+
events: EventTransport;
|
|
1007
1223
|
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1224
|
+
declare class ActivityRepository extends Repository<IActivityDocument> {
|
|
1225
|
+
private readonly events;
|
|
1226
|
+
constructor(model: Model<IActivityDocument>, plugins: PluginType[], deps: ActivityRepositoryDeps, pagination?: PaginationConfig);
|
|
1227
|
+
plan(input: Partial<IActivityDocument>, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
1228
|
+
start(id: string, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
1229
|
+
complete(id: string, completedAt?: Date, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
1230
|
+
cancel(id: string, reason?: string, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
1231
|
+
/**
|
|
1232
|
+
* Push an activity's `dueDate`. Allowed on planned / in_progress only;
|
|
1233
|
+
* rescheduling a completed or cancelled activity makes no sense.
|
|
1234
|
+
* Emits `crm:activity.rescheduled` with the previous date for audit.
|
|
1235
|
+
*/
|
|
1236
|
+
reschedule(id: string, newDueDate: Date, extras?: {
|
|
1237
|
+
reason?: string;
|
|
1238
|
+
by?: string;
|
|
1239
|
+
}, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
1240
|
+
/**
|
|
1241
|
+
* Record the outcome of an activity (call result, email engagement,
|
|
1242
|
+
* meeting confirmation). Stored under `metadata.outcome` so it stays
|
|
1243
|
+
* polymorphic — the shape is the channel's concern, not this package's.
|
|
1244
|
+
*
|
|
1245
|
+
* Does NOT transition status — call `complete()` separately when the
|
|
1246
|
+
* outcome implies completion. This split lets agents log partial
|
|
1247
|
+
* outcomes (e.g. "left voicemail") without forcing terminal state.
|
|
1248
|
+
*/
|
|
1249
|
+
recordOutcome(id: string, outcome: Record<string, unknown>, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
1250
|
+
private _transition;
|
|
1251
|
+
/** Count `planned` activities with `dueDate` before `asOf`. Dashboard KPI. */
|
|
1252
|
+
countOverduePlanned(asOf: Date, ctx?: CrmContext): Promise<number>;
|
|
1253
|
+
/** Latest `limit` activities — lightweight projection for the activity feed. */
|
|
1254
|
+
findRecentForFeed(limit: number, ctx?: CrmContext): Promise<IActivityDocument[]>;
|
|
1019
1255
|
}
|
|
1020
1256
|
//#endregion
|
|
1021
|
-
//#region src/
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
private readonly items;
|
|
1025
|
-
constructor(clock?: Clock);
|
|
1026
|
-
findById(id: string): Promise<Opportunity | null>;
|
|
1027
|
-
list(filter?: OpportunityFilter): Promise<Opportunity[]>;
|
|
1028
|
-
create(input: Omit<Opportunity, 'createdAt' | 'updatedAt'>): Promise<Opportunity>;
|
|
1029
|
-
update(id: string, patch: Partial<Opportunity>): Promise<Opportunity>;
|
|
1030
|
-
delete(id: string): Promise<void>;
|
|
1031
|
-
casStatus(id: string, expected: OpportunityStatus, next: OpportunityStatus, patch?: Partial<Opportunity>): Promise<Opportunity | null>;
|
|
1032
|
-
casStage(id: string, expectedStageId: string, nextStageId: string, patch?: Partial<Opportunity>): Promise<Opportunity | null>;
|
|
1257
|
+
//#region src/repositories/note.repository.d.ts
|
|
1258
|
+
interface NoteRepositoryDeps {
|
|
1259
|
+
events: EventTransport;
|
|
1033
1260
|
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
private readonly items;
|
|
1039
|
-
constructor(clock?: Clock);
|
|
1040
|
-
findById(id: string): Promise<Pipeline | null>;
|
|
1041
|
-
list(includeArchived?: boolean): Promise<Pipeline[]>;
|
|
1042
|
-
create(input: Omit<Pipeline, 'createdAt' | 'updatedAt'>): Promise<Pipeline>;
|
|
1043
|
-
update(id: string, patch: Partial<Pipeline>): Promise<Pipeline>;
|
|
1261
|
+
declare class NoteRepository extends Repository<INoteDocument> {
|
|
1262
|
+
private readonly events;
|
|
1263
|
+
constructor(model: Model<INoteDocument>, plugins: PluginType[], deps: NoteRepositoryDeps, pagination?: PaginationConfig);
|
|
1264
|
+
addNote(input: Partial<INoteDocument>, ctx?: CrmContext): Promise<INoteDocument>;
|
|
1044
1265
|
}
|
|
1045
1266
|
//#endregion
|
|
1046
|
-
//#region src/
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
private counter;
|
|
1056
|
-
constructor(nowMs?: () => number);
|
|
1057
|
-
send(request: OutreachSendRequest): Promise<OutreachSendResult>;
|
|
1267
|
+
//#region src/repositories/loss-reason.repository.d.ts
|
|
1268
|
+
interface LossReasonRepositoryDeps {
|
|
1269
|
+
events: EventTransport;
|
|
1270
|
+
}
|
|
1271
|
+
declare class LossReasonRepository extends Repository<ILossReasonDocument> {
|
|
1272
|
+
private readonly events;
|
|
1273
|
+
constructor(model: Model<ILossReasonDocument>, plugins: PluginType[], deps: LossReasonRepositoryDeps, pagination?: PaginationConfig);
|
|
1274
|
+
/** Hide from pickers without breaking historical FKs. */
|
|
1275
|
+
archive(id: string, ctx?: CrmContext): Promise<ILossReasonDocument>;
|
|
1058
1276
|
}
|
|
1059
1277
|
//#endregion
|
|
1060
|
-
//#region src/
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
//#endregion
|
|
1064
|
-
//#region src/domain/errors.d.ts
|
|
1065
|
-
/**
|
|
1066
|
-
* CRM error vocabulary. Hosts catch `CrmError` at API edges.
|
|
1067
|
-
*/
|
|
1068
|
-
declare class CrmError extends Error {
|
|
1069
|
-
readonly code: string;
|
|
1070
|
-
readonly details?: Record<string, unknown>;
|
|
1071
|
-
constructor(code: string, message: string, details?: Record<string, unknown>);
|
|
1072
|
-
}
|
|
1073
|
-
declare class NotFoundError extends CrmError {
|
|
1074
|
-
constructor(kind: string, id: string);
|
|
1075
|
-
}
|
|
1076
|
-
declare class InvalidLeadTransitionError extends CrmError {
|
|
1077
|
-
constructor(details: {
|
|
1078
|
-
from: string;
|
|
1079
|
-
to: string;
|
|
1080
|
-
leadId: string;
|
|
1081
|
-
});
|
|
1278
|
+
//#region src/repositories/email-event.repository.d.ts
|
|
1279
|
+
interface EmailEventRepositoryDeps {
|
|
1280
|
+
events: EventTransport;
|
|
1082
1281
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1282
|
+
interface RecordEmailEventInput {
|
|
1283
|
+
subjectKind: EmailEventSubjectKind;
|
|
1284
|
+
subjectId: string;
|
|
1285
|
+
campaignId?: string;
|
|
1286
|
+
messageId?: string;
|
|
1287
|
+
url?: string;
|
|
1288
|
+
userAgent?: string;
|
|
1289
|
+
ip?: string;
|
|
1290
|
+
metadata?: Record<string, unknown>;
|
|
1089
1291
|
}
|
|
1090
|
-
declare class
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1292
|
+
declare class EmailEventRepository extends Repository<IEmailEventDocument> {
|
|
1293
|
+
private readonly events;
|
|
1294
|
+
constructor(model: Model<IEmailEventDocument>, plugins: PluginType[], deps: EmailEventRepositoryDeps, pagination?: PaginationConfig);
|
|
1295
|
+
recordOpen(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
1296
|
+
recordClick(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
1297
|
+
recordBounce(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
1298
|
+
recordComplaint(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
1299
|
+
recordUnsubscribe(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
1300
|
+
private _record;
|
|
1096
1301
|
}
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1302
|
+
//#endregion
|
|
1303
|
+
//#region src/repositories/conversation.repository.d.ts
|
|
1304
|
+
interface ConversationRepositoryDeps {
|
|
1305
|
+
events: EventTransport;
|
|
1306
|
+
}
|
|
1307
|
+
interface OpenConversationInput {
|
|
1308
|
+
channel: ConversationChannel;
|
|
1309
|
+
participantKind: ConversationParticipantKind;
|
|
1310
|
+
participantId: string;
|
|
1311
|
+
channelUserId?: string;
|
|
1312
|
+
assigneeId?: string;
|
|
1313
|
+
metadata?: Record<string, unknown>;
|
|
1102
1314
|
}
|
|
1103
|
-
declare class
|
|
1104
|
-
|
|
1315
|
+
declare class ConversationRepository extends Repository<IConversationDocument> {
|
|
1316
|
+
private readonly events;
|
|
1317
|
+
constructor(model: Model<IConversationDocument>, plugins: PluginType[], deps: ConversationRepositoryDeps, pagination?: PaginationConfig);
|
|
1318
|
+
openConversation(input: OpenConversationInput, ctx?: CrmContext): Promise<IConversationDocument>;
|
|
1319
|
+
assign(id: string, assigneeId: string, ctx?: CrmContext): Promise<IConversationDocument>;
|
|
1320
|
+
resolve(id: string, ctx?: CrmContext): Promise<IConversationDocument>;
|
|
1321
|
+
reopen(id: string, ctx?: CrmContext): Promise<IConversationDocument>;
|
|
1322
|
+
/** Reset unread badge. Pure UI affordance, no event. */
|
|
1323
|
+
markRead(id: string, ctx?: CrmContext): Promise<IConversationDocument>;
|
|
1324
|
+
/**
|
|
1325
|
+
* Bump `lastMessageAt` and (for inbound) increment `unreadCount`.
|
|
1326
|
+
* Called by `MessageRepository` when a message is recorded — not part
|
|
1327
|
+
* of the public surface. Returns the conversation for the caller's
|
|
1328
|
+
* follow-up writes.
|
|
1329
|
+
*/
|
|
1330
|
+
touch(id: string, args: {
|
|
1331
|
+
direction: 'inbound' | 'outbound';
|
|
1332
|
+
sentAt: Date;
|
|
1333
|
+
}, ctx?: CrmContext): Promise<IConversationDocument | null>;
|
|
1334
|
+
private _setStatus;
|
|
1105
1335
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1336
|
+
//#endregion
|
|
1337
|
+
//#region src/repositories/message.repository.d.ts
|
|
1338
|
+
interface MessageRepositoryDeps {
|
|
1339
|
+
events: EventTransport;
|
|
1340
|
+
conversations: ConversationRepository;
|
|
1111
1341
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1342
|
+
interface RecordMessageInput {
|
|
1343
|
+
conversationId: string;
|
|
1344
|
+
body: string;
|
|
1345
|
+
attachments?: IMessageAttachment[];
|
|
1346
|
+
externalMessageId?: string;
|
|
1347
|
+
senderRef?: string;
|
|
1348
|
+
recipientRef?: string;
|
|
1349
|
+
sentAt?: Date;
|
|
1350
|
+
metadata?: Record<string, unknown>;
|
|
1351
|
+
}
|
|
1352
|
+
declare class MessageRepository extends Repository<IMessageDocument> {
|
|
1353
|
+
private readonly events;
|
|
1354
|
+
private readonly conversations;
|
|
1355
|
+
constructor(model: Model<IMessageDocument>, plugins: PluginType[], deps: MessageRepositoryDeps, pagination?: PaginationConfig);
|
|
1356
|
+
recordInbound(input: RecordMessageInput, ctx?: CrmContext): Promise<IMessageDocument>;
|
|
1357
|
+
recordOutbound(input: RecordMessageInput, ctx?: CrmContext): Promise<IMessageDocument>;
|
|
1358
|
+
/** Wire delivery callback (e.g. WhatsApp `status` webhook). */
|
|
1359
|
+
updateStatus(id: string, status: MessageDeliveryStatus, ctx?: CrmContext): Promise<IMessageDocument>;
|
|
1360
|
+
private _record;
|
|
1361
|
+
/** Latest `limit` messages — lightweight projection for the activity feed. */
|
|
1362
|
+
findRecentForFeed(limit: number, ctx?: CrmContext): Promise<IMessageDocument[]>;
|
|
1114
1363
|
}
|
|
1115
1364
|
//#endregion
|
|
1116
|
-
//#region src/
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1365
|
+
//#region src/engine/engine-types.d.ts
|
|
1366
|
+
interface CrmLogger {
|
|
1367
|
+
info?(msg: string, meta?: Record<string, unknown>): void;
|
|
1368
|
+
warn?(msg: string, meta?: Record<string, unknown>): void;
|
|
1369
|
+
error?(msg: string, meta?: Record<string, unknown>): void;
|
|
1370
|
+
debug?(msg: string, meta?: Record<string, unknown>): void;
|
|
1371
|
+
}
|
|
1372
|
+
interface CrmConfig {
|
|
1373
|
+
/** Mongoose connection — package creates models on this connection. */
|
|
1374
|
+
connection: Connection;
|
|
1375
|
+
/**
|
|
1376
|
+
* Tenant column shape. `'objectId'` (default) matches Better Auth orgs
|
|
1377
|
+
* and unlocks `$lookup` / `.populate()`; `'string'` matches UUID hosts.
|
|
1378
|
+
* Threaded into both schemas and `multiTenantPlugin` so they stay in
|
|
1379
|
+
* sync (PACKAGE_RULES §9.2).
|
|
1380
|
+
*/
|
|
1381
|
+
tenantFieldType?: TenantFieldType;
|
|
1382
|
+
/**
|
|
1383
|
+
* When `true` (default), wire `multiTenantPlugin` on every repository
|
|
1384
|
+
* with `required: true`. Set `false` only for fixtures / smoke tests
|
|
1385
|
+
* that intentionally drop the scope.
|
|
1386
|
+
*/
|
|
1387
|
+
multiTenant?: boolean;
|
|
1388
|
+
/** Arc-compatible event transport. Default: in-process bus. */
|
|
1389
|
+
eventTransport?: EventTransport;
|
|
1390
|
+
/** Logger surface used by the in-process bus + repositories. */
|
|
1391
|
+
logger?: CrmLogger;
|
|
1392
|
+
/** Pagination defaults for every repository (mongokit). */
|
|
1393
|
+
pagination?: PaginationConfig;
|
|
1394
|
+
/** Extra mongokit plugins applied to every repository (after defaults). */
|
|
1395
|
+
plugins?: PluginType[];
|
|
1396
|
+
/**
|
|
1397
|
+
* On a Mongoose model-name collision (another engine / hot reload owns
|
|
1398
|
+
* the name): `false` (default) throws `CrmModelCollisionError`; `true`
|
|
1399
|
+
* deletes + re-registers. Test fixtures / hot reload only (§21).
|
|
1400
|
+
*/
|
|
1401
|
+
forceRecreate?: boolean;
|
|
1402
|
+
/**
|
|
1403
|
+
* Mongoose auto-index builds. Default `true` (dev). Set `false` in
|
|
1404
|
+
* production and run `engine.syncIndexes()` from a deploy script so
|
|
1405
|
+
* cold-boot index builds don't blow Fastify's plugin timeout (§35).
|
|
1406
|
+
*/
|
|
1407
|
+
autoIndex?: boolean;
|
|
1408
|
+
/**
|
|
1409
|
+
* Skip the boot-time `transactions` capability requirement, downgrading
|
|
1410
|
+
* it to a warning. Set only when the host never calls
|
|
1411
|
+
* `LeadService.convert()` inside a transaction (standalone Mongo).
|
|
1412
|
+
*/
|
|
1413
|
+
allowNonTransactional?: boolean;
|
|
1414
|
+
}
|
|
1415
|
+
interface ResolvedCrmConfig extends SchemaBuildConfig {
|
|
1416
|
+
connection: Connection;
|
|
1417
|
+
tenantFieldType: TenantFieldType;
|
|
1418
|
+
multiTenant: boolean;
|
|
1419
|
+
forceRecreate: boolean;
|
|
1420
|
+
autoIndex: boolean;
|
|
1421
|
+
logger?: CrmLogger;
|
|
1422
|
+
pagination?: PaginationConfig;
|
|
1423
|
+
plugins: PluginType[];
|
|
1424
|
+
}
|
|
1425
|
+
interface CrmRepositories {
|
|
1426
|
+
pipeline: PipelineRepository;
|
|
1427
|
+
lead: LeadRepository;
|
|
1428
|
+
opportunity: OpportunityRepository;
|
|
1429
|
+
contact: ContactRepository;
|
|
1430
|
+
account: AccountRepository;
|
|
1431
|
+
campaign: CampaignRepository;
|
|
1432
|
+
subscription: SubscriptionRepository;
|
|
1433
|
+
activity: ActivityRepository;
|
|
1434
|
+
note: NoteRepository;
|
|
1435
|
+
lossReason: LossReasonRepository;
|
|
1436
|
+
emailEvent: EmailEventRepository;
|
|
1437
|
+
conversation: ConversationRepository;
|
|
1438
|
+
message: MessageRepository;
|
|
1439
|
+
}
|
|
1440
|
+
interface CrmEngine {
|
|
1441
|
+
/** Repositories ARE the API surface (PACKAGE_RULES §1). */
|
|
1442
|
+
readonly repositories: Readonly<CrmRepositories>;
|
|
1443
|
+
/** Arc-compatible event transport. */
|
|
1444
|
+
readonly events: EventTransport;
|
|
1445
|
+
/** Mongoose models — for arc adapter wiring. */
|
|
1446
|
+
readonly models: Readonly<CrmModels>;
|
|
1447
|
+
/** Resolved configuration (frozen). */
|
|
1448
|
+
readonly config: Readonly<ResolvedCrmConfig>;
|
|
1449
|
+
/**
|
|
1450
|
+
* Build/align every model's indexes against its schema. Call once per
|
|
1451
|
+
* deploy when booted with `autoIndex: false` (§35). Idempotent.
|
|
1452
|
+
*/
|
|
1453
|
+
syncIndexes(): Promise<void>;
|
|
1454
|
+
/** Release resources. Safe to call multiple times. */
|
|
1455
|
+
dispose(): Promise<void>;
|
|
1153
1456
|
}
|
|
1154
|
-
interface CrmEventDefinition<TSchema extends z.ZodType = z.ZodType> {
|
|
1155
|
-
readonly name: string;
|
|
1156
|
-
readonly version: number;
|
|
1157
|
-
readonly description?: string;
|
|
1158
|
-
readonly schema: CrmEventSchema;
|
|
1159
|
-
readonly zodSchema: TSchema;
|
|
1160
|
-
create(payload: z.infer<TSchema>, meta?: Partial<DomainEvent['meta']>): DomainEvent<z.infer<TSchema>>;
|
|
1161
|
-
readonly __payload?: z.infer<TSchema>;
|
|
1162
|
-
}
|
|
1163
|
-
type CrmEventPayloadOf<D> = D extends CrmEventDefinition<infer S> ? z.infer<S> : never;
|
|
1164
|
-
declare const leadCreatedSchema: z.ZodObject<{
|
|
1165
|
-
leadId: z.ZodString;
|
|
1166
|
-
email: z.ZodOptional<z.ZodString>;
|
|
1167
|
-
score: z.ZodOptional<z.ZodNumber>;
|
|
1168
|
-
}, z.core.$strip>;
|
|
1169
|
-
declare const leadStatusChangedSchema: z.ZodObject<{
|
|
1170
|
-
leadId: z.ZodString;
|
|
1171
|
-
from: z.ZodString;
|
|
1172
|
-
to: z.ZodString;
|
|
1173
|
-
}, z.core.$strip>;
|
|
1174
|
-
declare const leadScoredSchema: z.ZodObject<{
|
|
1175
|
-
leadId: z.ZodString;
|
|
1176
|
-
score: z.ZodNumber;
|
|
1177
|
-
}, z.core.$strip>;
|
|
1178
|
-
declare const leadConvertedSchema: z.ZodObject<{
|
|
1179
|
-
leadId: z.ZodString;
|
|
1180
|
-
contactId: z.ZodString;
|
|
1181
|
-
accountId: z.ZodOptional<z.ZodString>;
|
|
1182
|
-
opportunityId: z.ZodString;
|
|
1183
|
-
}, z.core.$strip>;
|
|
1184
|
-
declare const leadDisqualifiedSchema: z.ZodObject<{
|
|
1185
|
-
leadId: z.ZodString;
|
|
1186
|
-
reason: z.ZodString;
|
|
1187
|
-
}, z.core.$strip>;
|
|
1188
|
-
declare const accountCreatedSchema: z.ZodObject<{
|
|
1189
|
-
accountId: z.ZodString;
|
|
1190
|
-
}, z.core.$strip>;
|
|
1191
|
-
declare const accountUpdatedSchema: z.ZodObject<{
|
|
1192
|
-
accountId: z.ZodString;
|
|
1193
|
-
}, z.core.$strip>;
|
|
1194
|
-
declare const contactCreatedSchema: z.ZodObject<{
|
|
1195
|
-
contactId: z.ZodString;
|
|
1196
|
-
email: z.ZodOptional<z.ZodString>;
|
|
1197
|
-
}, z.core.$strip>;
|
|
1198
|
-
declare const contactUpdatedSchema: z.ZodObject<{
|
|
1199
|
-
contactId: z.ZodString;
|
|
1200
|
-
}, z.core.$strip>;
|
|
1201
|
-
declare const opportunityCreatedSchema: z.ZodObject<{
|
|
1202
|
-
opportunityId: z.ZodString;
|
|
1203
|
-
pipelineId: z.ZodString;
|
|
1204
|
-
stageId: z.ZodString;
|
|
1205
|
-
}, z.core.$strip>;
|
|
1206
|
-
declare const opportunityStageAdvancedSchema: z.ZodObject<{
|
|
1207
|
-
opportunityId: z.ZodString;
|
|
1208
|
-
from: z.ZodObject<{
|
|
1209
|
-
stageId: z.ZodString;
|
|
1210
|
-
sequence: z.ZodNumber;
|
|
1211
|
-
}, z.core.$strip>;
|
|
1212
|
-
to: z.ZodObject<{
|
|
1213
|
-
stageId: z.ZodString;
|
|
1214
|
-
sequence: z.ZodNumber;
|
|
1215
|
-
}, z.core.$strip>;
|
|
1216
|
-
}, z.core.$strip>;
|
|
1217
|
-
declare const opportunityStageRegressedSchema: z.ZodObject<{
|
|
1218
|
-
opportunityId: z.ZodString;
|
|
1219
|
-
from: z.ZodObject<{
|
|
1220
|
-
stageId: z.ZodString;
|
|
1221
|
-
sequence: z.ZodNumber;
|
|
1222
|
-
}, z.core.$strip>;
|
|
1223
|
-
to: z.ZodObject<{
|
|
1224
|
-
stageId: z.ZodString;
|
|
1225
|
-
sequence: z.ZodNumber;
|
|
1226
|
-
}, z.core.$strip>;
|
|
1227
|
-
}, z.core.$strip>;
|
|
1228
|
-
declare const opportunityWonSchema: z.ZodObject<{
|
|
1229
|
-
opportunityId: z.ZodString;
|
|
1230
|
-
amount: z.ZodOptional<z.ZodObject<{
|
|
1231
|
-
amount: z.ZodNumber;
|
|
1232
|
-
currency: z.ZodString;
|
|
1233
|
-
}, z.core.$strip>>;
|
|
1234
|
-
}, z.core.$strip>;
|
|
1235
|
-
declare const opportunityLostSchema: z.ZodObject<{
|
|
1236
|
-
opportunityId: z.ZodString;
|
|
1237
|
-
lostReasonId: z.ZodOptional<z.ZodString>;
|
|
1238
|
-
}, z.core.$strip>;
|
|
1239
|
-
declare const opportunityAbandonedSchema: z.ZodObject<{
|
|
1240
|
-
opportunityId: z.ZodString;
|
|
1241
|
-
}, z.core.$strip>;
|
|
1242
|
-
declare const pipelineCreatedSchema: z.ZodObject<{
|
|
1243
|
-
pipelineId: z.ZodString;
|
|
1244
|
-
}, z.core.$strip>;
|
|
1245
|
-
declare const pipelineArchivedSchema: z.ZodObject<{
|
|
1246
|
-
pipelineId: z.ZodString;
|
|
1247
|
-
}, z.core.$strip>;
|
|
1248
|
-
declare const activityPlannedSchema: z.ZodObject<{
|
|
1249
|
-
activityId: z.ZodString;
|
|
1250
|
-
type: z.ZodString;
|
|
1251
|
-
subjectKind: z.ZodEnum<{
|
|
1252
|
-
lead: "lead";
|
|
1253
|
-
opportunity: "opportunity";
|
|
1254
|
-
contact: "contact";
|
|
1255
|
-
account: "account";
|
|
1256
|
-
}>;
|
|
1257
|
-
subjectId: z.ZodString;
|
|
1258
|
-
}, z.core.$strip>;
|
|
1259
|
-
declare const activityCompletedSchema: z.ZodObject<{
|
|
1260
|
-
activityId: z.ZodString;
|
|
1261
|
-
completedAt: z.ZodISODateTime;
|
|
1262
|
-
}, z.core.$strip>;
|
|
1263
|
-
declare const activityCancelledSchema: z.ZodObject<{
|
|
1264
|
-
activityId: z.ZodString;
|
|
1265
|
-
reason: z.ZodOptional<z.ZodString>;
|
|
1266
|
-
}, z.core.$strip>;
|
|
1267
|
-
declare const noteAddedSchema: z.ZodObject<{
|
|
1268
|
-
noteId: z.ZodString;
|
|
1269
|
-
subjectKind: z.ZodEnum<{
|
|
1270
|
-
lead: "lead";
|
|
1271
|
-
opportunity: "opportunity";
|
|
1272
|
-
contact: "contact";
|
|
1273
|
-
account: "account";
|
|
1274
|
-
}>;
|
|
1275
|
-
subjectId: z.ZodString;
|
|
1276
|
-
}, z.core.$strip>;
|
|
1277
|
-
type LeadCreatedPayload = z.infer<typeof leadCreatedSchema>;
|
|
1278
|
-
type LeadStatusChangedPayload = z.infer<typeof leadStatusChangedSchema>;
|
|
1279
|
-
type LeadScoredPayload = z.infer<typeof leadScoredSchema>;
|
|
1280
|
-
type LeadConvertedPayload = z.infer<typeof leadConvertedSchema>;
|
|
1281
|
-
type LeadDisqualifiedPayload = z.infer<typeof leadDisqualifiedSchema>;
|
|
1282
|
-
type AccountCreatedPayload = z.infer<typeof accountCreatedSchema>;
|
|
1283
|
-
type AccountUpdatedPayload = z.infer<typeof accountUpdatedSchema>;
|
|
1284
|
-
type ContactCreatedPayload = z.infer<typeof contactCreatedSchema>;
|
|
1285
|
-
type ContactUpdatedPayload = z.infer<typeof contactUpdatedSchema>;
|
|
1286
|
-
type OpportunityCreatedPayload = z.infer<typeof opportunityCreatedSchema>;
|
|
1287
|
-
type OpportunityStageAdvancedPayload = z.infer<typeof opportunityStageAdvancedSchema>;
|
|
1288
|
-
type OpportunityStageRegressedPayload = z.infer<typeof opportunityStageRegressedSchema>;
|
|
1289
|
-
type OpportunityWonPayload = z.infer<typeof opportunityWonSchema>;
|
|
1290
|
-
type OpportunityLostPayload = z.infer<typeof opportunityLostSchema>;
|
|
1291
|
-
type OpportunityAbandonedPayload = z.infer<typeof opportunityAbandonedSchema>;
|
|
1292
|
-
type PipelineCreatedPayload = z.infer<typeof pipelineCreatedSchema>;
|
|
1293
|
-
type PipelineArchivedPayload = z.infer<typeof pipelineArchivedSchema>;
|
|
1294
|
-
type ActivityPlannedPayload = z.infer<typeof activityPlannedSchema>;
|
|
1295
|
-
type ActivityCompletedPayload = z.infer<typeof activityCompletedSchema>;
|
|
1296
|
-
type ActivityCancelledPayload = z.infer<typeof activityCancelledSchema>;
|
|
1297
|
-
type NoteAddedPayload = z.infer<typeof noteAddedSchema>;
|
|
1298
|
-
declare const LeadCreated: CrmEventDefinition<z.ZodObject<{
|
|
1299
|
-
leadId: z.ZodString;
|
|
1300
|
-
email: z.ZodOptional<z.ZodString>;
|
|
1301
|
-
score: z.ZodOptional<z.ZodNumber>;
|
|
1302
|
-
}, z.core.$strip>>;
|
|
1303
|
-
declare const LeadStatusChanged: CrmEventDefinition<z.ZodObject<{
|
|
1304
|
-
leadId: z.ZodString;
|
|
1305
|
-
from: z.ZodString;
|
|
1306
|
-
to: z.ZodString;
|
|
1307
|
-
}, z.core.$strip>>;
|
|
1308
|
-
declare const LeadScored: CrmEventDefinition<z.ZodObject<{
|
|
1309
|
-
leadId: z.ZodString;
|
|
1310
|
-
score: z.ZodNumber;
|
|
1311
|
-
}, z.core.$strip>>;
|
|
1312
|
-
declare const LeadConverted: CrmEventDefinition<z.ZodObject<{
|
|
1313
|
-
leadId: z.ZodString;
|
|
1314
|
-
contactId: z.ZodString;
|
|
1315
|
-
accountId: z.ZodOptional<z.ZodString>;
|
|
1316
|
-
opportunityId: z.ZodString;
|
|
1317
|
-
}, z.core.$strip>>;
|
|
1318
|
-
declare const LeadDisqualified: CrmEventDefinition<z.ZodObject<{
|
|
1319
|
-
leadId: z.ZodString;
|
|
1320
|
-
reason: z.ZodString;
|
|
1321
|
-
}, z.core.$strip>>;
|
|
1322
|
-
declare const AccountCreated: CrmEventDefinition<z.ZodObject<{
|
|
1323
|
-
accountId: z.ZodString;
|
|
1324
|
-
}, z.core.$strip>>;
|
|
1325
|
-
declare const AccountUpdated: CrmEventDefinition<z.ZodObject<{
|
|
1326
|
-
accountId: z.ZodString;
|
|
1327
|
-
}, z.core.$strip>>;
|
|
1328
|
-
declare const ContactCreated: CrmEventDefinition<z.ZodObject<{
|
|
1329
|
-
contactId: z.ZodString;
|
|
1330
|
-
email: z.ZodOptional<z.ZodString>;
|
|
1331
|
-
}, z.core.$strip>>;
|
|
1332
|
-
declare const ContactUpdated: CrmEventDefinition<z.ZodObject<{
|
|
1333
|
-
contactId: z.ZodString;
|
|
1334
|
-
}, z.core.$strip>>;
|
|
1335
|
-
declare const OpportunityCreated: CrmEventDefinition<z.ZodObject<{
|
|
1336
|
-
opportunityId: z.ZodString;
|
|
1337
|
-
pipelineId: z.ZodString;
|
|
1338
|
-
stageId: z.ZodString;
|
|
1339
|
-
}, z.core.$strip>>;
|
|
1340
|
-
declare const OpportunityStageAdvanced: CrmEventDefinition<z.ZodObject<{
|
|
1341
|
-
opportunityId: z.ZodString;
|
|
1342
|
-
from: z.ZodObject<{
|
|
1343
|
-
stageId: z.ZodString;
|
|
1344
|
-
sequence: z.ZodNumber;
|
|
1345
|
-
}, z.core.$strip>;
|
|
1346
|
-
to: z.ZodObject<{
|
|
1347
|
-
stageId: z.ZodString;
|
|
1348
|
-
sequence: z.ZodNumber;
|
|
1349
|
-
}, z.core.$strip>;
|
|
1350
|
-
}, z.core.$strip>>;
|
|
1351
|
-
declare const OpportunityStageRegressed: CrmEventDefinition<z.ZodObject<{
|
|
1352
|
-
opportunityId: z.ZodString;
|
|
1353
|
-
from: z.ZodObject<{
|
|
1354
|
-
stageId: z.ZodString;
|
|
1355
|
-
sequence: z.ZodNumber;
|
|
1356
|
-
}, z.core.$strip>;
|
|
1357
|
-
to: z.ZodObject<{
|
|
1358
|
-
stageId: z.ZodString;
|
|
1359
|
-
sequence: z.ZodNumber;
|
|
1360
|
-
}, z.core.$strip>;
|
|
1361
|
-
}, z.core.$strip>>;
|
|
1362
|
-
declare const OpportunityWon: CrmEventDefinition<z.ZodObject<{
|
|
1363
|
-
opportunityId: z.ZodString;
|
|
1364
|
-
amount: z.ZodOptional<z.ZodObject<{
|
|
1365
|
-
amount: z.ZodNumber;
|
|
1366
|
-
currency: z.ZodString;
|
|
1367
|
-
}, z.core.$strip>>;
|
|
1368
|
-
}, z.core.$strip>>;
|
|
1369
|
-
declare const OpportunityLost: CrmEventDefinition<z.ZodObject<{
|
|
1370
|
-
opportunityId: z.ZodString;
|
|
1371
|
-
lostReasonId: z.ZodOptional<z.ZodString>;
|
|
1372
|
-
}, z.core.$strip>>;
|
|
1373
|
-
declare const OpportunityAbandoned: CrmEventDefinition<z.ZodObject<{
|
|
1374
|
-
opportunityId: z.ZodString;
|
|
1375
|
-
}, z.core.$strip>>;
|
|
1376
|
-
declare const PipelineCreated: CrmEventDefinition<z.ZodObject<{
|
|
1377
|
-
pipelineId: z.ZodString;
|
|
1378
|
-
}, z.core.$strip>>;
|
|
1379
|
-
declare const PipelineArchived: CrmEventDefinition<z.ZodObject<{
|
|
1380
|
-
pipelineId: z.ZodString;
|
|
1381
|
-
}, z.core.$strip>>;
|
|
1382
|
-
declare const ActivityPlanned: CrmEventDefinition<z.ZodObject<{
|
|
1383
|
-
activityId: z.ZodString;
|
|
1384
|
-
type: z.ZodString;
|
|
1385
|
-
subjectKind: z.ZodEnum<{
|
|
1386
|
-
lead: "lead";
|
|
1387
|
-
opportunity: "opportunity";
|
|
1388
|
-
contact: "contact";
|
|
1389
|
-
account: "account";
|
|
1390
|
-
}>;
|
|
1391
|
-
subjectId: z.ZodString;
|
|
1392
|
-
}, z.core.$strip>>;
|
|
1393
|
-
declare const ActivityCompleted: CrmEventDefinition<z.ZodObject<{
|
|
1394
|
-
activityId: z.ZodString;
|
|
1395
|
-
completedAt: z.ZodISODateTime;
|
|
1396
|
-
}, z.core.$strip>>;
|
|
1397
|
-
declare const ActivityCancelled: CrmEventDefinition<z.ZodObject<{
|
|
1398
|
-
activityId: z.ZodString;
|
|
1399
|
-
reason: z.ZodOptional<z.ZodString>;
|
|
1400
|
-
}, z.core.$strip>>;
|
|
1401
|
-
declare const NoteAdded: CrmEventDefinition<z.ZodObject<{
|
|
1402
|
-
noteId: z.ZodString;
|
|
1403
|
-
subjectKind: z.ZodEnum<{
|
|
1404
|
-
lead: "lead";
|
|
1405
|
-
opportunity: "opportunity";
|
|
1406
|
-
contact: "contact";
|
|
1407
|
-
account: "account";
|
|
1408
|
-
}>;
|
|
1409
|
-
subjectId: z.ZodString;
|
|
1410
|
-
}, z.core.$strip>>;
|
|
1411
1457
|
/**
|
|
1412
|
-
*
|
|
1413
|
-
*
|
|
1414
|
-
*
|
|
1415
|
-
* `
|
|
1458
|
+
* Operation context threaded through every domain verb. Extends
|
|
1459
|
+
* primitives' `OperationContext` and narrows `IdLike` to types Mongoose
|
|
1460
|
+
* stores cleanly. Host-specific extras go through the inherited
|
|
1461
|
+
* `metadata?` field — keep the typed surface tight.
|
|
1416
1462
|
*/
|
|
1417
|
-
|
|
1463
|
+
interface CrmContext extends OperationContext {
|
|
1464
|
+
organizationId?: string | mongoose1.Types.ObjectId;
|
|
1465
|
+
actorId?: string | mongoose1.Types.ObjectId;
|
|
1466
|
+
/** Mongo transaction session (passed through to mongokit). */
|
|
1467
|
+
session?: unknown;
|
|
1468
|
+
}
|
|
1469
|
+
type _ModelTypes = Model<unknown>;
|
|
1470
|
+
//#endregion
|
|
1471
|
+
//#region src/events/helpers.d.ts
|
|
1472
|
+
declare function createEvent$1<T>(type: string, payload: T, ctx?: CrmContext, meta?: Partial<EventMeta>): DomainEvent<T>;
|
|
1473
|
+
//#endregion
|
|
1474
|
+
//#region src/events/in-process-bus.d.ts
|
|
1475
|
+
declare class InProcessCrmBus implements EventTransport {
|
|
1476
|
+
readonly name = "in-process-crm";
|
|
1477
|
+
private subs;
|
|
1478
|
+
private logger?;
|
|
1479
|
+
constructor(options?: {
|
|
1480
|
+
logger?: CrmLogger;
|
|
1481
|
+
});
|
|
1482
|
+
publish(event: DomainEvent): Promise<void>;
|
|
1483
|
+
subscribe(pattern: string, handler: EventHandler): Promise<() => void>;
|
|
1484
|
+
close(): Promise<void>;
|
|
1485
|
+
}
|
|
1418
1486
|
//#endregion
|
|
1419
|
-
export {
|
|
1420
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1487
|
+
export { IMessageAttachment as $, ContactUpdated as $n, CAMPAIGN_TRANSITIONS as $t, AccountRepository as A, SchemaBuildConfig as An, PipelineArchived as Ar, buildActivitySchema as At, OpportunityRepositoryDeps as B, ActivityOutcomeRecorded as Bn, ISubscriptionDocument as Bt, ActivityRepository as C, LEAD_TRANSITIONS as Cn, OpportunityAssigned as Cr, ILossReasonDocument as Ct, SubscriptionRepositoryDeps as D, IStageDocument as Dn, OpportunityStageAdvanced as Dr, buildNoteSchema as Dt, SubscriptionRepository as E, IPipelineDocument as En, OpportunityLost as Er, INoteDocument as Et, MergeContactInput as F, AccountEnriched as Fn, SubscriptionCreated as Fr, ActivityStatus as Ft, composeScorers as G, CampaignCompleted as Gn, SUBSCRIPTION_TRANSITIONS as Gt, LeadRepositoryDeps as H, ActivityRescheduled as Hn, buildSubscriptionSchema as Ht, CloseInput as I, AccountMerged as In, SubscriptionUnsubscribed as Ir, ActivityType as It, PipelineRepositoryDeps as J, CampaignResumed as Jn, ICampaignDocument as Jt, defaultLeadScorer as K, CampaignCreated as Kn, SubscriptionStatus as Kt, MoveStageInput as L, AccountUpdated as Ln, crmEventDefinitions as Lr, SUBJECT_KINDS as Lt, MergeAccountInput as M, tenantFieldDef as Mn, SubscriptionBounced as Mr, ACTIVITY_STATUSES as Mt, ContactRepository as N, AccountAssigned as Nn, SubscriptionComplained as Nr, ACTIVITY_TRANSITIONS as Nt, CampaignRepository as O, buildPipelineSchema as On, OpportunityStageRegressed as Or, createNoteModel as Ot, ContactRepositoryDeps as P, AccountCreated as Pn, SubscriptionConfirmed as Pr, ACTIVITY_TYPES as Pt, createCrmModels as Q, ContactMerged as Qn, CAMPAIGN_STATUSES as Qt, OpenOpportunityInput as R, ActivityCancelled as Rn, CRM_EVENTS as Rr, SubjectKind as Rt, NoteRepositoryDeps as S, LEAD_STATUSES as Sn, OpportunityAmountChanged as Sr, EmailEventKind as St, SubscribeInput as T, canTransitionLead as Tn, OpportunityExtended as Tr, createLossReasonModel as Tt, LeadInput as U, CampaignActivated as Un, createSubscriptionModel as Ut, LeadRepository as V, ActivityPlanned as Vn, ISubscriptionStatusEntry as Vt, LeadScorer as W, CampaignArchived as Wn, SUBSCRIPTION_STATUSES as Wt, CreateModelsOptions as X, ContactCreated as Xn, buildCampaignSchema as Xt, CRM_MODEL_NAMES as Y, ContactAssigned as Yn, ICampaignStatusEntry as Yt, CrmModels as Z, ContactEnriched as Zn, createCampaignModel as Zt, EmailEventRepositoryDeps as _, canTransitionOpportunity as _n, LeadStatusChanged as _r, EmailEventSubjectKind as _t, CrmEngine as a, IContactDocument as an, CrmEventSchema as ar, createConversationModel as at, LossReasonRepositoryDeps as b, buildLeadSchema as bn, NoteAdded as br, createEmailEventModel as bt, ResolvedCrmConfig as c, buildContactSchema as cn, EmailEventComplained as cr, CONVERSATION_STATUSES as ct, MessageRepositoryDeps as d, IOpportunityStatusEntry as dn, LeadAssigned as dr, ConversationStatus as dt, CampaignStatus as en, ConversationAssigned as er, IMessageDocument as et, RecordMessageInput as f, buildOpportunitySchema as fn, LeadConverted as fr, MESSAGE_DELIVERY_STATUSES as ft, EmailEventRepository as g, OpportunityStatus as gn, LeadScored as gr, EMAIL_EVENT_SUBJECT_KINDS as gt, OpenConversationInput as h, OPPORTUNITY_TRANSITIONS as hn, LeadEnriched as hr, MessageDirection as ht, CrmContext as i, createAccountModel as in, CrmEventDefinition as ir, buildConversationSchema as it, AccountRepositoryDeps as j, TenantFieldType as jn, PipelineCreated as jr, createActivityModel as jt, CampaignRepositoryDeps as k, createPipelineModel as kn, OpportunityWon as kr, IActivityDocument as kt, _ModelTypes as l, createContactModel as ln, EmailEventOpened as lr, ConversationChannel as lt, ConversationRepositoryDeps as m, OPPORTUNITY_STATUSES as mn, LeadDisqualified as mr, MessageDeliveryStatus as mt, createEvent$1 as n, IAccountDocument as nn, ConversationReopened as nr, createMessageModel as nt, CrmLogger as o, IContactInfoEmbedded as on, EmailEventBounced as or, CONVERSATION_CHANNELS as ot, ConversationRepository as p, createOpportunityModel as pn, LeadCreated as pr, MESSAGE_DIRECTIONS as pt, PipelineRepository as q, CampaignPaused as qn, canTransitionSubscription as qt, CrmConfig as r, buildAccountSchema as rn, ConversationResolved as rr, IConversationDocument as rt, CrmRepositories as s, IContactName as sn, EmailEventClicked as sr, CONVERSATION_PARTICIPANT_KINDS as st, InProcessCrmBus as t, canTransitionCampaign as tn, ConversationCreated as tr, buildMessageSchema as tt, MessageRepository as u, IOpportunityDocument as un, EmailEventUnsubscribed as ur, ConversationParticipantKind as ut, RecordEmailEventInput as v, ILeadDocument as vn, MessageReceived as vr, IEmailEventDocument as vt, ActivityRepositoryDeps as w, LeadStatus as wn, OpportunityCreated as wr, buildLossReasonSchema as wt, NoteRepository as x, createLeadModel as xn, OpportunityAbandoned as xr, EMAIL_EVENT_KINDS as xt, LossReasonRepository as y, ILeadStatusEntry as yn, MessageSent as yr, buildEmailEventSchema as yt, OpportunityRepository as z, ActivityCompleted as zn, CrmEventName as zr, canTransitionActivity as zt };
|