@classytic/crm 0.1.1 → 0.3.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 +61 -0
- package/dist/chunk.js +13 -0
- package/dist/index.d.ts +1312 -1157
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2654 -1625
- package/dist/index.js.map +1 -1
- package/package.json +15 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,145 +1,305 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as __exportAll } from "./chunk.js";
|
|
2
|
+
import * as mongoose0 from "mongoose";
|
|
3
|
+
import { Connection, Model, Schema, SchemaDefinitionProperty } from "mongoose";
|
|
4
|
+
import { PaginationConfig, PluginType, Repository } from "@classytic/mongokit";
|
|
5
|
+
import { DomainEvent, EventHandler, EventMeta, EventTransport } from "@classytic/primitives/events";
|
|
6
|
+
import * as _classytic_primitives_state_machine0 from "@classytic/primitives/state-machine";
|
|
2
7
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Money } from "@classytic/primitives/money";
|
|
8
|
+
import { StatusChangeEntry, StatusHistory, appendStatus, lastTransitionTo, latestEntry, timeInStatus } from "@classytic/primitives/status-history";
|
|
9
|
+
import { OperationContext } from "@classytic/primitives/context";
|
|
6
10
|
|
|
7
|
-
//#region src/
|
|
11
|
+
//#region src/models/tenant-field.d.ts
|
|
12
|
+
type TenantFieldType = 'objectId' | 'string';
|
|
13
|
+
interface SchemaBuildConfig {
|
|
14
|
+
/** Schema type for the tenant column. Engine plumbs this everywhere. */
|
|
15
|
+
tenantFieldType: TenantFieldType;
|
|
16
|
+
}
|
|
8
17
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
18
|
+
* Tenant-column schema definition. Use this anywhere a model has
|
|
19
|
+
* `organizationId` — never write the raw type in a schema file.
|
|
11
20
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
21
|
+
declare function tenantFieldDef(config: SchemaBuildConfig): SchemaDefinitionProperty;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/models/pipeline.schema.d.ts
|
|
24
|
+
/** Mongoose document shape for a single embedded stage. */
|
|
25
|
+
interface IStageDocument {
|
|
26
|
+
_id: mongoose0.Types.ObjectId;
|
|
14
27
|
name: string;
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
/** Ascending order in the pipeline. Treated as identifier on `moveToStage`. */
|
|
29
|
+
sequence: number;
|
|
30
|
+
/** Default win-probability assigned to opportunities entering this stage. */
|
|
31
|
+
defaultProbability: number;
|
|
32
|
+
color?: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
}
|
|
35
|
+
/** Mongoose document shape for a Pipeline. */
|
|
36
|
+
interface IPipelineDocument {
|
|
37
|
+
_id: mongoose0.Types.ObjectId;
|
|
38
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
39
|
+
name: string;
|
|
40
|
+
/** Deprecates the pipeline — existing opps still move, no new ones created. */
|
|
41
|
+
isArchived: boolean;
|
|
42
|
+
/** Embedded stages, kept ordered by `sequence`. */
|
|
43
|
+
stages: IStageDocument[];
|
|
44
|
+
/** Free-form label for the sales team / motion that owns this pipeline. */
|
|
45
|
+
teamRef?: string;
|
|
26
46
|
metadata?: Record<string, unknown>;
|
|
27
47
|
createdAt: Date;
|
|
28
48
|
updatedAt: Date;
|
|
29
49
|
}
|
|
50
|
+
declare function buildPipelineSchema(config: SchemaBuildConfig): Schema<IPipelineDocument>;
|
|
51
|
+
declare function createPipelineModel(connection: Connection, config: SchemaBuildConfig): Model<IPipelineDocument>;
|
|
30
52
|
//#endregion
|
|
31
|
-
//#region src/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
//#region src/enums/lead-status.d.ts
|
|
54
|
+
/**
|
|
55
|
+
* Lead lifecycle — from initial inquiry through conversion.
|
|
56
|
+
*
|
|
57
|
+
* new — just captured (web form, import, referral)
|
|
58
|
+
* contacted — SDR has reached out
|
|
59
|
+
* qualified — meets ICP / BANT
|
|
60
|
+
* converted — turned into Contact + Account + Opportunity
|
|
61
|
+
* disqualified — rejected (bad fit, spam, duplicate)
|
|
62
|
+
* nurturing — not ready now; parked for later outreach
|
|
63
|
+
*/
|
|
64
|
+
declare const LEAD_STATUSES: readonly ["new", "contacted", "qualified", "converted", "disqualified", "nurturing"];
|
|
65
|
+
type LeadStatus = (typeof LEAD_STATUSES)[number];
|
|
66
|
+
declare const LEAD_TRANSITIONS: Record<LeadStatus, readonly LeadStatus[]>;
|
|
67
|
+
declare function canTransitionLead(from: LeadStatus, to: LeadStatus): boolean;
|
|
46
68
|
//#endregion
|
|
47
|
-
//#region src/
|
|
48
|
-
interface
|
|
49
|
-
|
|
69
|
+
//#region src/models/lead.schema.d.ts
|
|
70
|
+
interface ILeadStatusEntry {
|
|
71
|
+
status: LeadStatus;
|
|
72
|
+
occurredAt: Date;
|
|
73
|
+
by?: string;
|
|
74
|
+
note?: string;
|
|
50
75
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
76
|
+
interface ILeadDocument {
|
|
77
|
+
_id: mongoose0.Types.ObjectId;
|
|
78
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
79
|
+
fullName: string;
|
|
80
|
+
firstName?: string;
|
|
81
|
+
lastName?: string;
|
|
82
|
+
email?: string;
|
|
83
|
+
phone?: string;
|
|
84
|
+
companyName?: string;
|
|
85
|
+
jobTitle?: string;
|
|
86
|
+
source?: string;
|
|
87
|
+
campaignRef?: string;
|
|
88
|
+
score: number;
|
|
89
|
+
status: LeadStatus;
|
|
90
|
+
statusHistory: ILeadStatusEntry[];
|
|
91
|
+
ownerId?: string;
|
|
92
|
+
tags: string[];
|
|
93
|
+
convertedContactId?: mongoose0.Types.ObjectId | string;
|
|
94
|
+
convertedAccountId?: mongoose0.Types.ObjectId | string;
|
|
95
|
+
convertedOpportunityId?: mongoose0.Types.ObjectId | string;
|
|
96
|
+
convertedAt?: Date;
|
|
97
|
+
disqualifyReason?: string;
|
|
98
|
+
metadata?: Record<string, unknown>;
|
|
99
|
+
createdAt: Date;
|
|
100
|
+
updatedAt: Date;
|
|
56
101
|
}
|
|
102
|
+
declare function buildLeadSchema(config: SchemaBuildConfig): Schema<ILeadDocument>;
|
|
103
|
+
declare function createLeadModel(connection: Connection, config: SchemaBuildConfig): Model<ILeadDocument>;
|
|
57
104
|
//#endregion
|
|
58
|
-
//#region src/
|
|
105
|
+
//#region src/enums/opportunity-status.d.ts
|
|
59
106
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
107
|
+
* Top-level opportunity status. Movement through pipeline STAGES
|
|
108
|
+
* happens while status is `open`; `won` / `lost` are terminal
|
|
109
|
+
* outcomes. Re-opening a lost deal is a host-level decision —
|
|
110
|
+
* convention is to clone the opportunity rather than revive the
|
|
111
|
+
* terminal record.
|
|
62
112
|
*/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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;
|
|
113
|
+
declare const OPPORTUNITY_STATUSES: readonly ["open", "won", "lost", "abandoned"];
|
|
114
|
+
type OpportunityStatus = (typeof OPPORTUNITY_STATUSES)[number];
|
|
115
|
+
declare const OPPORTUNITY_TRANSITIONS: Record<OpportunityStatus, readonly OpportunityStatus[]>;
|
|
116
|
+
declare function canTransitionOpportunity(from: OpportunityStatus, to: OpportunityStatus): boolean;
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/models/opportunity.schema.d.ts
|
|
119
|
+
interface IOpportunityStatusEntry {
|
|
120
|
+
status: OpportunityStatus;
|
|
121
|
+
stageId?: string;
|
|
122
|
+
occurredAt: Date;
|
|
123
|
+
by?: string;
|
|
124
|
+
note?: string;
|
|
96
125
|
}
|
|
126
|
+
interface IOpportunityDocument {
|
|
127
|
+
_id: mongoose0.Types.ObjectId;
|
|
128
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
129
|
+
name: string;
|
|
130
|
+
accountId?: mongoose0.Types.ObjectId | string;
|
|
131
|
+
primaryContactId?: mongoose0.Types.ObjectId | string;
|
|
132
|
+
pipelineId: mongoose0.Types.ObjectId | string;
|
|
133
|
+
stageId: string;
|
|
134
|
+
status: OpportunityStatus;
|
|
135
|
+
statusHistory: IOpportunityStatusEntry[];
|
|
136
|
+
amount?: number;
|
|
137
|
+
currency: string;
|
|
138
|
+
probability: number;
|
|
139
|
+
expectedCloseAt?: Date;
|
|
140
|
+
closedAt?: Date;
|
|
141
|
+
lostReasonId?: mongoose0.Types.ObjectId | string;
|
|
142
|
+
ownerId?: string;
|
|
143
|
+
sourceLeadId?: mongoose0.Types.ObjectId | string;
|
|
144
|
+
tags: string[];
|
|
145
|
+
metadata?: Record<string, unknown>;
|
|
146
|
+
createdAt: Date;
|
|
147
|
+
updatedAt: Date;
|
|
148
|
+
}
|
|
149
|
+
declare function buildOpportunitySchema(config: SchemaBuildConfig): Schema<IOpportunityDocument>;
|
|
150
|
+
declare function createOpportunityModel(connection: Connection, config: SchemaBuildConfig): Model<IOpportunityDocument>;
|
|
97
151
|
//#endregion
|
|
98
|
-
//#region src/
|
|
99
|
-
interface
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
152
|
+
//#region src/models/contact.schema.d.ts
|
|
153
|
+
interface IContactName {
|
|
154
|
+
given: string;
|
|
155
|
+
family: string;
|
|
156
|
+
middle?: string;
|
|
157
|
+
prefix?: string;
|
|
158
|
+
suffix?: string;
|
|
159
|
+
preferred?: string;
|
|
160
|
+
}
|
|
161
|
+
interface IContactInfoEmbedded {
|
|
162
|
+
email?: string;
|
|
163
|
+
personalEmail?: string;
|
|
164
|
+
phone?: string;
|
|
165
|
+
alternatePhone?: string;
|
|
166
|
+
}
|
|
167
|
+
interface IContactDocument {
|
|
168
|
+
_id: mongoose0.Types.ObjectId;
|
|
169
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
170
|
+
name: IContactName;
|
|
171
|
+
contact: IContactInfoEmbedded;
|
|
172
|
+
jobTitle?: string;
|
|
173
|
+
accountId?: mongoose0.Types.ObjectId | string;
|
|
174
|
+
ownerId?: string;
|
|
175
|
+
tags: string[];
|
|
176
|
+
metadata?: Record<string, unknown>;
|
|
177
|
+
createdAt: Date;
|
|
178
|
+
updatedAt: Date;
|
|
111
179
|
}
|
|
112
|
-
|
|
180
|
+
declare function buildContactSchema(config: SchemaBuildConfig): Schema<IContactDocument>;
|
|
181
|
+
declare function createContactModel(connection: Connection, config: SchemaBuildConfig): Model<IContactDocument>;
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/models/account.schema.d.ts
|
|
184
|
+
interface IAccountDocument {
|
|
185
|
+
_id: mongoose0.Types.ObjectId;
|
|
186
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
113
187
|
name: string;
|
|
114
188
|
domain?: string;
|
|
115
189
|
industry?: string;
|
|
116
190
|
sizeBucket?: string;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
currency: string;
|
|
120
|
-
};
|
|
191
|
+
annualRevenueAmount?: number;
|
|
192
|
+
annualRevenueCurrency: string;
|
|
121
193
|
ownerId?: string;
|
|
122
|
-
tags
|
|
194
|
+
tags: string[];
|
|
123
195
|
metadata?: Record<string, unknown>;
|
|
196
|
+
createdAt: Date;
|
|
197
|
+
updatedAt: Date;
|
|
124
198
|
}
|
|
125
|
-
declare
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
199
|
+
declare function buildAccountSchema(config: SchemaBuildConfig): Schema<IAccountDocument>;
|
|
200
|
+
declare function createAccountModel(connection: Connection, config: SchemaBuildConfig): Model<IAccountDocument>;
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/enums/campaign-status.d.ts
|
|
203
|
+
/**
|
|
204
|
+
* Campaign lifecycle.
|
|
205
|
+
*
|
|
206
|
+
* draft — being built; not running, no sends, no UTM attribution counted
|
|
207
|
+
* active — running; participating in attribution + automation
|
|
208
|
+
* paused — temporarily halted; can be resumed; no sends fire
|
|
209
|
+
* completed — finished its run; preserved for historical attribution
|
|
210
|
+
* archived — soft-hidden from the default UI; still queryable
|
|
211
|
+
*/
|
|
212
|
+
declare const CAMPAIGN_STATUSES: readonly ["draft", "active", "paused", "completed", "archived"];
|
|
213
|
+
type CampaignStatus = (typeof CAMPAIGN_STATUSES)[number];
|
|
214
|
+
declare const CAMPAIGN_TRANSITIONS: Record<CampaignStatus, readonly CampaignStatus[]>;
|
|
215
|
+
declare function canTransitionCampaign(from: CampaignStatus, to: CampaignStatus): boolean;
|
|
216
|
+
//#endregion
|
|
217
|
+
//#region src/models/campaign.schema.d.ts
|
|
218
|
+
interface ICampaignStatusEntry {
|
|
219
|
+
status: CampaignStatus;
|
|
220
|
+
occurredAt: Date;
|
|
221
|
+
by?: string;
|
|
222
|
+
note?: string;
|
|
140
223
|
}
|
|
224
|
+
interface ICampaignDocument {
|
|
225
|
+
_id: mongoose0.Types.ObjectId;
|
|
226
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
227
|
+
name: string;
|
|
228
|
+
description?: string;
|
|
229
|
+
status: CampaignStatus;
|
|
230
|
+
statusHistory: ICampaignStatusEntry[];
|
|
231
|
+
utmSource?: string;
|
|
232
|
+
utmMedium?: string;
|
|
233
|
+
utmCampaign?: string;
|
|
234
|
+
startDate?: Date;
|
|
235
|
+
endDate?: Date;
|
|
236
|
+
budgetAmount?: number;
|
|
237
|
+
expectedRevenueAmount?: number;
|
|
238
|
+
actualRevenueAmount?: number;
|
|
239
|
+
currency: string;
|
|
240
|
+
ownerId?: string;
|
|
241
|
+
tags: string[];
|
|
242
|
+
metadata?: Record<string, unknown>;
|
|
243
|
+
createdAt: Date;
|
|
244
|
+
updatedAt: Date;
|
|
245
|
+
}
|
|
246
|
+
declare function buildCampaignSchema(config: SchemaBuildConfig): Schema<ICampaignDocument>;
|
|
247
|
+
declare function createCampaignModel(connection: Connection, config: SchemaBuildConfig): Model<ICampaignDocument>;
|
|
141
248
|
//#endregion
|
|
142
|
-
//#region src/
|
|
249
|
+
//#region src/enums/subscription-status.d.ts
|
|
250
|
+
/**
|
|
251
|
+
* Subscription lifecycle.
|
|
252
|
+
*
|
|
253
|
+
* pending — double-opt-in pending confirmation
|
|
254
|
+
* confirmed — actively subscribed; eligible to receive sends
|
|
255
|
+
* unsubscribed — user opted out via unsubscribe link (or operator action)
|
|
256
|
+
* bounced — provider reported hard bounce; permanent suppression
|
|
257
|
+
* complained — recipient hit "spam" / "report" in their email client;
|
|
258
|
+
* permanent suppression (CAN-SPAM + provider trust)
|
|
259
|
+
*
|
|
260
|
+
* All terminal states are non-reopenable. Re-subscribing creates a new
|
|
261
|
+
* Subscription row — the audit trail of unsubscribes/bounces is preserved.
|
|
262
|
+
*/
|
|
263
|
+
declare const SUBSCRIPTION_STATUSES: readonly ["pending", "confirmed", "unsubscribed", "bounced", "complained"];
|
|
264
|
+
type SubscriptionStatus = (typeof SUBSCRIPTION_STATUSES)[number];
|
|
265
|
+
declare const SUBSCRIPTION_TRANSITIONS: Record<SubscriptionStatus, readonly SubscriptionStatus[]>;
|
|
266
|
+
declare function canTransitionSubscription(from: SubscriptionStatus, to: SubscriptionStatus): boolean;
|
|
267
|
+
//#endregion
|
|
268
|
+
//#region src/models/subscription.schema.d.ts
|
|
269
|
+
interface ISubscriptionStatusEntry {
|
|
270
|
+
status: SubscriptionStatus;
|
|
271
|
+
occurredAt: Date;
|
|
272
|
+
by?: string;
|
|
273
|
+
note?: string;
|
|
274
|
+
}
|
|
275
|
+
interface ISubscriptionDocument {
|
|
276
|
+
_id: mongoose0.Types.ObjectId;
|
|
277
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
278
|
+
contactId: mongoose0.Types.ObjectId | string;
|
|
279
|
+
campaignId: mongoose0.Types.ObjectId | string;
|
|
280
|
+
status: SubscriptionStatus;
|
|
281
|
+
statusHistory: ISubscriptionStatusEntry[];
|
|
282
|
+
source?: string;
|
|
283
|
+
consentTimestamp: Date;
|
|
284
|
+
consentIpAddress?: string;
|
|
285
|
+
consentUserAgent?: string;
|
|
286
|
+
confirmationToken?: string;
|
|
287
|
+
unsubscribeToken: string;
|
|
288
|
+
/** Audit timestamps for compliance — set on the matching transition. */
|
|
289
|
+
confirmedAt?: Date;
|
|
290
|
+
unsubscribedAt?: Date;
|
|
291
|
+
unsubscribeReason?: string;
|
|
292
|
+
bouncedAt?: Date;
|
|
293
|
+
bounceReason?: string;
|
|
294
|
+
complainedAt?: Date;
|
|
295
|
+
metadata?: Record<string, unknown>;
|
|
296
|
+
createdAt: Date;
|
|
297
|
+
updatedAt: Date;
|
|
298
|
+
}
|
|
299
|
+
declare function buildSubscriptionSchema(config: SchemaBuildConfig): Schema<ISubscriptionDocument>;
|
|
300
|
+
declare function createSubscriptionModel(connection: Connection, config: SchemaBuildConfig): Model<ISubscriptionDocument>;
|
|
301
|
+
//#endregion
|
|
302
|
+
//#region src/enums/activity.d.ts
|
|
143
303
|
/**
|
|
144
304
|
* Activity type vocabulary. The package stores `type` as free-form
|
|
145
305
|
* string so hosts can extend; these constants cover the common
|
|
@@ -159,414 +319,218 @@ declare function canTransitionActivity(from: ActivityStatus, to: ActivityStatus)
|
|
|
159
319
|
declare const SUBJECT_KINDS: readonly ["lead", "opportunity", "contact", "account"];
|
|
160
320
|
type SubjectKind = (typeof SUBJECT_KINDS)[number];
|
|
161
321
|
//#endregion
|
|
162
|
-
//#region src/
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
* to `crm:activity.*` events, filter by `subjectKind`, react).
|
|
168
|
-
*/
|
|
169
|
-
interface Activity {
|
|
170
|
-
id: string;
|
|
171
|
-
type: ActivityType | string;
|
|
322
|
+
//#region src/models/activity.schema.d.ts
|
|
323
|
+
interface IActivityDocument {
|
|
324
|
+
_id: mongoose0.Types.ObjectId;
|
|
325
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
326
|
+
type: ActivityType;
|
|
172
327
|
status: ActivityStatus;
|
|
173
328
|
subjectKind: SubjectKind;
|
|
174
|
-
subjectId: string;
|
|
175
|
-
|
|
176
|
-
|
|
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). */
|
|
329
|
+
subjectId: mongoose0.Types.ObjectId | string;
|
|
330
|
+
title: string;
|
|
331
|
+
description?: string;
|
|
182
332
|
ownerId?: string;
|
|
183
|
-
participantIds
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
* call-recording url. Host-owned semantics.
|
|
187
|
-
*/
|
|
333
|
+
participantIds: string[];
|
|
334
|
+
dueDate?: Date;
|
|
335
|
+
completedAt?: Date;
|
|
188
336
|
externalRef?: string;
|
|
189
337
|
metadata?: Record<string, unknown>;
|
|
190
338
|
createdAt: Date;
|
|
191
339
|
updatedAt: Date;
|
|
192
340
|
}
|
|
341
|
+
declare function buildActivitySchema(config: SchemaBuildConfig): Schema<IActivityDocument>;
|
|
342
|
+
declare function createActivityModel(connection: Connection, config: SchemaBuildConfig): Model<IActivityDocument>;
|
|
193
343
|
//#endregion
|
|
194
|
-
//#region src/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
* also the cheapest "activity log" entry to create.
|
|
199
|
-
*/
|
|
200
|
-
interface Note {
|
|
201
|
-
id: string;
|
|
344
|
+
//#region src/models/note.schema.d.ts
|
|
345
|
+
interface INoteDocument {
|
|
346
|
+
_id: mongoose0.Types.ObjectId;
|
|
347
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
202
348
|
subjectKind: SubjectKind;
|
|
203
|
-
subjectId: string;
|
|
349
|
+
subjectId: mongoose0.Types.ObjectId | string;
|
|
204
350
|
body: string;
|
|
205
351
|
authorId?: string;
|
|
206
|
-
|
|
207
|
-
format?: 'plain' | 'markdown';
|
|
352
|
+
pinned: boolean;
|
|
208
353
|
metadata?: Record<string, unknown>;
|
|
209
354
|
createdAt: Date;
|
|
210
355
|
updatedAt: Date;
|
|
211
356
|
}
|
|
357
|
+
declare function buildNoteSchema(config: SchemaBuildConfig): Schema<INoteDocument>;
|
|
358
|
+
declare function createNoteModel(connection: Connection, config: SchemaBuildConfig): Model<INoteDocument>;
|
|
212
359
|
//#endregion
|
|
213
|
-
//#region src/
|
|
214
|
-
interface
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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';
|
|
360
|
+
//#region src/models/loss-reason.schema.d.ts
|
|
361
|
+
interface ILossReasonDocument {
|
|
362
|
+
_id: mongoose0.Types.ObjectId;
|
|
363
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
364
|
+
name: string;
|
|
365
|
+
description?: string;
|
|
366
|
+
isActive: boolean;
|
|
367
|
+
/** Display ordering in admin UIs. */
|
|
368
|
+
sequence: number;
|
|
269
369
|
metadata?: Record<string, unknown>;
|
|
370
|
+
createdAt: Date;
|
|
371
|
+
updatedAt: Date;
|
|
270
372
|
}
|
|
271
|
-
|
|
272
|
-
|
|
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;
|
|
294
|
-
}
|
|
373
|
+
declare function buildLossReasonSchema(config: SchemaBuildConfig): Schema<ILossReasonDocument>;
|
|
374
|
+
declare function createLossReasonModel(connection: Connection, config: SchemaBuildConfig): Model<ILossReasonDocument>;
|
|
295
375
|
//#endregion
|
|
296
|
-
//#region src/
|
|
376
|
+
//#region src/enums/email-event-kind.d.ts
|
|
297
377
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
378
|
+
* Email engagement event kinds, recorded against a Contact / Campaign /
|
|
379
|
+
* Subscription tuple as the recipient interacts with a sent message.
|
|
380
|
+
*
|
|
381
|
+
* open — recipient's mail client loaded the tracking pixel.
|
|
382
|
+
* Imperfect signal: image-block clients suppress it, some
|
|
383
|
+
* clients pre-fetch and inflate counts. Useful in aggregate.
|
|
384
|
+
*
|
|
385
|
+
* click — recipient followed a tracked link. High-signal: actual
|
|
386
|
+
* user action, not background fetch.
|
|
300
387
|
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
388
|
+
* bounce — provider reported delivery failed. Pair with the
|
|
389
|
+
* `bounce` status on Subscription for permanent suppression.
|
|
390
|
+
*
|
|
391
|
+
* complaint — recipient hit "spam" / "report" in their inbox. Pair
|
|
392
|
+
* with `complained` Subscription status.
|
|
393
|
+
*
|
|
394
|
+
* unsubscribe — recipient hit the unsubscribe link in the email. May
|
|
395
|
+
* fire BEFORE the Subscription itself is marked unsubscribed
|
|
396
|
+
* (the host can choose to confirm before flipping status).
|
|
397
|
+
*
|
|
398
|
+
* Open and click are "engagement signal"; bounce/complaint/unsubscribe are
|
|
399
|
+
* "suppression signal". The service exposes aggregates over both
|
|
400
|
+
* categories so consumers can compute open rate, click rate, bounce rate
|
|
401
|
+
* without filtering kind themselves.
|
|
304
402
|
*/
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
403
|
+
declare const EMAIL_EVENT_KINDS: readonly ["open", "click", "bounce", "complaint", "unsubscribe"];
|
|
404
|
+
type EmailEventKind = (typeof EMAIL_EVENT_KINDS)[number];
|
|
405
|
+
/** Engagement (positive signal). */
|
|
406
|
+
//#endregion
|
|
407
|
+
//#region src/models/email-event.schema.d.ts
|
|
408
|
+
declare const EMAIL_EVENT_SUBJECT_KINDS: readonly ["contact", "subscription"];
|
|
409
|
+
type EmailEventSubjectKind = (typeof EMAIL_EVENT_SUBJECT_KINDS)[number];
|
|
410
|
+
interface IEmailEventDocument {
|
|
411
|
+
_id: mongoose0.Types.ObjectId;
|
|
412
|
+
organizationId: mongoose0.Types.ObjectId | string;
|
|
413
|
+
kind: EmailEventKind;
|
|
414
|
+
subjectKind: EmailEventSubjectKind;
|
|
415
|
+
subjectId: mongoose0.Types.ObjectId | string;
|
|
416
|
+
campaignId?: mongoose0.Types.ObjectId | string;
|
|
417
|
+
messageId?: string;
|
|
418
|
+
url?: string;
|
|
419
|
+
userAgent?: string;
|
|
420
|
+
ip?: string;
|
|
315
421
|
metadata?: Record<string, unknown>;
|
|
316
422
|
createdAt: Date;
|
|
317
|
-
updatedAt: Date;
|
|
318
423
|
}
|
|
424
|
+
declare function buildEmailEventSchema(config: SchemaBuildConfig): Schema<IEmailEventDocument>;
|
|
425
|
+
declare function createEmailEventModel(connection: Connection, config: SchemaBuildConfig): Model<IEmailEventDocument>;
|
|
319
426
|
//#endregion
|
|
320
|
-
//#region src/
|
|
321
|
-
interface
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
427
|
+
//#region src/models/create-models.d.ts
|
|
428
|
+
interface CrmModels {
|
|
429
|
+
Pipeline: Model<IPipelineDocument>;
|
|
430
|
+
Lead: Model<ILeadDocument>;
|
|
431
|
+
Opportunity: Model<IOpportunityDocument>;
|
|
432
|
+
Contact: Model<IContactDocument>;
|
|
433
|
+
Account: Model<IAccountDocument>;
|
|
434
|
+
Campaign: Model<ICampaignDocument>;
|
|
435
|
+
Subscription: Model<ISubscriptionDocument>;
|
|
436
|
+
Activity: Model<IActivityDocument>;
|
|
437
|
+
Note: Model<INoteDocument>;
|
|
438
|
+
LossReason: Model<ILossReasonDocument>;
|
|
439
|
+
EmailEvent: Model<IEmailEventDocument>;
|
|
440
|
+
}
|
|
441
|
+
declare function createCrmModels(connection: Connection, config: SchemaBuildConfig): CrmModels;
|
|
335
442
|
//#endregion
|
|
336
|
-
//#region src/
|
|
337
|
-
interface
|
|
338
|
-
|
|
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>;
|
|
443
|
+
//#region src/repositories/pipeline.repository.d.ts
|
|
444
|
+
interface PipelineRepositoryDeps {
|
|
445
|
+
events: EventTransport;
|
|
353
446
|
}
|
|
354
|
-
declare class
|
|
355
|
-
private readonly repo;
|
|
447
|
+
declare class PipelineRepository extends Repository<IPipelineDocument> {
|
|
356
448
|
private readonly events;
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
449
|
+
constructor(model: Model<IPipelineDocument>, plugins: PluginType[], deps: PipelineRepositoryDeps, pagination?: PaginationConfig);
|
|
450
|
+
/**
|
|
451
|
+
* Read a single embedded stage. Used by Opportunity create / move to
|
|
452
|
+
* validate stage membership + pick up `defaultProbability`.
|
|
453
|
+
*/
|
|
454
|
+
getStage(pipelineId: string, stageId: string, ctx?: CrmContext): Promise<IStageDocument>;
|
|
455
|
+
/** First stage by `sequence` ascending. */
|
|
456
|
+
getFirstStage(pipelineId: string, ctx?: CrmContext): Promise<IStageDocument>;
|
|
457
|
+
/** Stage immediately after the given one. `null` at terminal stage. */
|
|
458
|
+
getNextStage(pipelineId: string, stageId: string, ctx?: CrmContext): Promise<IStageDocument | null>;
|
|
459
|
+
/** Soft-deprecate — existing opps still move; no new ones can be created. */
|
|
460
|
+
archive(id: string, ctx?: CrmContext): Promise<IPipelineDocument>;
|
|
369
461
|
}
|
|
370
462
|
//#endregion
|
|
371
|
-
//#region src/
|
|
463
|
+
//#region src/shared/calculators/scoring.d.ts
|
|
464
|
+
/** Minimal Lead shape the scorer reads. */
|
|
465
|
+
type LeadInput = Pick<ILeadDocument, 'email' | 'phone' | 'companyName' | 'tags' | 'jobTitle'>;
|
|
466
|
+
type LeadScorer = (lead: LeadInput) => number;
|
|
372
467
|
/**
|
|
373
|
-
*
|
|
468
|
+
* Reference implementation. Intentionally simple — hosts read it and
|
|
469
|
+
* replace it.
|
|
374
470
|
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
* nurturing — not ready now; parked for later outreach
|
|
471
|
+
* +20 if email is present
|
|
472
|
+
* +20 if phone is present
|
|
473
|
+
* +20 if companyName is present
|
|
474
|
+
* +10 per populated tag up to 40
|
|
475
|
+
* +10 if jobTitle hints senior (director / manager / head / chief / vp / founder)
|
|
381
476
|
*/
|
|
382
|
-
declare
|
|
383
|
-
|
|
384
|
-
declare
|
|
385
|
-
declare function canTransitionLead(from: LeadStatus, to: LeadStatus): boolean;
|
|
477
|
+
declare function defaultLeadScorer(lead: LeadInput): number;
|
|
478
|
+
/** Compose multiple small rules into one scorer. */
|
|
479
|
+
declare function composeScorers(...rules: readonly LeadScorer[]): LeadScorer;
|
|
386
480
|
//#endregion
|
|
387
|
-
//#region src/
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
interface Lead {
|
|
395
|
-
id: string;
|
|
396
|
-
/** Name / email / phone / company captured at inquiry time. */
|
|
397
|
-
firstName?: string;
|
|
398
|
-
lastName?: string;
|
|
399
|
-
fullName: string;
|
|
400
|
-
email?: string;
|
|
401
|
-
phone?: string;
|
|
402
|
-
companyName?: string;
|
|
403
|
-
jobTitle?: string;
|
|
404
|
-
/** How the lead arrived (`web-form`, `referral`, `event`, `ads`, …). */
|
|
405
|
-
source?: string;
|
|
406
|
-
/** Free-form campaign identifier — the host's campaign system owns its semantics. */
|
|
407
|
-
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;
|
|
414
|
-
status: LeadStatus;
|
|
415
|
-
statusHistory: readonly LeadStatusEntry[];
|
|
416
|
-
ownerId?: string;
|
|
417
|
-
tags?: readonly string[];
|
|
418
|
-
/** On successful `convert`, links to the resulting records. */
|
|
419
|
-
convertedContactId?: string;
|
|
420
|
-
convertedAccountId?: string;
|
|
421
|
-
convertedOpportunityId?: string;
|
|
422
|
-
convertedAt?: Date;
|
|
423
|
-
/** Disqualification detail. */
|
|
424
|
-
disqualifyReason?: string;
|
|
425
|
-
metadata?: Record<string, unknown>;
|
|
426
|
-
createdAt: Date;
|
|
427
|
-
updatedAt: Date;
|
|
481
|
+
//#region src/repositories/lead.repository.d.ts
|
|
482
|
+
interface LeadRepositoryDeps {
|
|
483
|
+
events: EventTransport;
|
|
484
|
+
/** Override the default lead scorer. */
|
|
485
|
+
scorer?: LeadScorer;
|
|
486
|
+
/** Reject `create()` when an email already exists in-tenant (default true). */
|
|
487
|
+
rejectDuplicates?: boolean;
|
|
428
488
|
}
|
|
429
|
-
|
|
430
|
-
status: LeadStatus;
|
|
431
|
-
occurredAt: Date;
|
|
489
|
+
type TransitionExtras = {
|
|
432
490
|
by?: string;
|
|
433
491
|
note?: string;
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
* convention is to clone the opportunity rather than revive the
|
|
442
|
-
* terminal record.
|
|
443
|
-
*/
|
|
444
|
-
declare const OPPORTUNITY_STATUSES: readonly ["open", "won", "lost", "abandoned"];
|
|
445
|
-
type OpportunityStatus = (typeof OPPORTUNITY_STATUSES)[number];
|
|
446
|
-
declare const OPPORTUNITY_TRANSITIONS: Record<OpportunityStatus, readonly OpportunityStatus[]>;
|
|
447
|
-
declare function canTransitionOpportunity(from: OpportunityStatus, to: OpportunityStatus): boolean;
|
|
448
|
-
//#endregion
|
|
449
|
-
//#region src/domain/entities/opportunity.d.ts
|
|
450
|
-
/**
|
|
451
|
-
* A qualified sales opportunity. Opportunities live inside a Pipeline
|
|
452
|
-
* and progress through Stages. Status captures the outcome
|
|
453
|
-
* (`open` / `won` / `lost` / `abandoned`); stage captures the current
|
|
454
|
-
* step.
|
|
455
|
-
*/
|
|
456
|
-
interface Opportunity {
|
|
457
|
-
id: string;
|
|
458
|
-
name: string;
|
|
459
|
-
accountId?: string;
|
|
460
|
-
primaryContactId?: string;
|
|
461
|
-
/** Which pipeline this opportunity belongs to (sales, partnerships, renewals). */
|
|
462
|
-
pipelineId: string;
|
|
463
|
-
/** Current stage — index INTO the pipeline's `stages` array. */
|
|
464
|
-
stageId: string;
|
|
465
|
-
status: OpportunityStatus;
|
|
466
|
-
statusHistory: readonly OpportunityStatusEntry[];
|
|
467
|
-
/** Host-expected deal value. */
|
|
468
|
-
amount?: Money;
|
|
492
|
+
patch?: Partial<ILeadDocument>;
|
|
493
|
+
};
|
|
494
|
+
declare class LeadRepository extends Repository<ILeadDocument> {
|
|
495
|
+
private readonly events;
|
|
496
|
+
private readonly scorer;
|
|
497
|
+
private readonly rejectDuplicates;
|
|
498
|
+
constructor(model: Model<ILeadDocument>, plugins: PluginType[], deps: LeadRepositoryDeps, pagination?: PaginationConfig);
|
|
469
499
|
/**
|
|
470
|
-
*
|
|
471
|
-
*
|
|
500
|
+
* Create a Lead. Auto-scores on insert so hosts can route immediately.
|
|
501
|
+
* Rejects duplicate emails inside the same tenant unless
|
|
502
|
+
* `rejectDuplicates: false` was set at engine boot.
|
|
472
503
|
*/
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
updatedAt: Date;
|
|
485
|
-
}
|
|
486
|
-
interface OpportunityStatusEntry {
|
|
487
|
-
status: OpportunityStatus;
|
|
488
|
-
stageId?: string;
|
|
489
|
-
occurredAt: Date;
|
|
490
|
-
by?: string;
|
|
491
|
-
note?: string;
|
|
492
|
-
}
|
|
493
|
-
//#endregion
|
|
494
|
-
//#region src/domain/ports/lead-repository.port.d.ts
|
|
495
|
-
interface LeadFilter {
|
|
496
|
-
status?: LeadStatus | readonly LeadStatus[];
|
|
497
|
-
ownerId?: string;
|
|
498
|
-
source?: string;
|
|
499
|
-
minScore?: number;
|
|
500
|
-
}
|
|
501
|
-
interface LeadRepository {
|
|
502
|
-
findById(id: string): Promise<Lead | null>;
|
|
503
|
-
findByEmail(email: string): Promise<Lead | null>;
|
|
504
|
-
list(filter?: LeadFilter): Promise<Lead[]>;
|
|
505
|
-
create(l: Omit<Lead, 'createdAt' | 'updatedAt'>): Promise<Lead>;
|
|
506
|
-
update(id: string, patch: Partial<Lead>): Promise<Lead>;
|
|
507
|
-
casStatus(id: string, expected: LeadStatus, next: LeadStatus, patch?: Partial<Lead>): Promise<Lead | null>;
|
|
508
|
-
}
|
|
509
|
-
//#endregion
|
|
510
|
-
//#region src/domain/ports/opportunity-repository.port.d.ts
|
|
511
|
-
interface OpportunityFilter {
|
|
512
|
-
status?: OpportunityStatus | readonly OpportunityStatus[];
|
|
513
|
-
pipelineId?: string;
|
|
514
|
-
stageId?: string;
|
|
515
|
-
ownerId?: string;
|
|
516
|
-
accountId?: string;
|
|
517
|
-
closingBetween?: {
|
|
518
|
-
from: Date;
|
|
519
|
-
to: Date;
|
|
520
|
-
};
|
|
521
|
-
}
|
|
522
|
-
interface OpportunityRepository {
|
|
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>;
|
|
504
|
+
createLead(input: Partial<ILeadDocument>, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
505
|
+
markContacted(id: string, extras?: TransitionExtras, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
506
|
+
qualify(id: string, extras?: TransitionExtras, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
507
|
+
disqualify(id: string, reason: string, extras?: Omit<TransitionExtras, 'patch'>, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
508
|
+
nurture(id: string, extras?: TransitionExtras, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
509
|
+
/**
|
|
510
|
+
* Recompute + persist the lead's score. Called from `createLead`
|
|
511
|
+
* automatically; hosts also call this after enrichment writes.
|
|
512
|
+
*/
|
|
513
|
+
recomputeScore(id: string, ctx?: CrmContext): Promise<ILeadDocument>;
|
|
514
|
+
private _transition;
|
|
530
515
|
}
|
|
531
516
|
//#endregion
|
|
532
|
-
//#region src/
|
|
533
|
-
interface
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
id: string;
|
|
538
|
-
}[];
|
|
539
|
-
} | null>;
|
|
540
|
-
getStage(pipelineId: string, stageId: string): Promise<{
|
|
541
|
-
id: string;
|
|
542
|
-
sequence: number;
|
|
543
|
-
defaultProbability: number;
|
|
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;
|
|
517
|
+
//#region src/repositories/opportunity.repository.d.ts
|
|
518
|
+
interface OpportunityRepositoryDeps {
|
|
519
|
+
events: EventTransport;
|
|
520
|
+
/** Cross-repo reference: read embedded stages from Pipeline. */
|
|
521
|
+
pipelines: PipelineRepository;
|
|
559
522
|
}
|
|
560
|
-
interface
|
|
523
|
+
interface OpenOpportunityInput {
|
|
561
524
|
name: string;
|
|
562
525
|
pipelineId: string;
|
|
563
|
-
/**
|
|
526
|
+
/** When omitted, opp enters the pipeline's first stage. */
|
|
564
527
|
stageId?: string;
|
|
565
528
|
accountId?: string;
|
|
566
529
|
primaryContactId?: string;
|
|
567
530
|
sourceLeadId?: string;
|
|
568
|
-
amount?:
|
|
569
|
-
|
|
531
|
+
amount?: number;
|
|
532
|
+
currency?: string;
|
|
533
|
+
/** Override the stage's `defaultProbability`. */
|
|
570
534
|
probability?: number;
|
|
571
535
|
expectedCloseAt?: Date;
|
|
572
536
|
ownerId?: string;
|
|
@@ -575,493 +539,408 @@ interface CreateOpportunityInput {
|
|
|
575
539
|
}
|
|
576
540
|
interface MoveStageInput {
|
|
577
541
|
stageId: string;
|
|
578
|
-
/** Override probability. Defaults to the target stage's `defaultProbability`. */
|
|
579
|
-
probability?: number;
|
|
580
542
|
by?: string;
|
|
581
543
|
note?: string;
|
|
544
|
+
/** Override the target stage's `defaultProbability`. */
|
|
545
|
+
probability?: number;
|
|
582
546
|
}
|
|
583
547
|
interface CloseInput {
|
|
584
|
-
amount?: Money;
|
|
585
|
-
closedAt?: Date;
|
|
586
548
|
by?: string;
|
|
587
549
|
note?: string;
|
|
588
|
-
|
|
589
|
-
|
|
550
|
+
closedAt?: Date;
|
|
551
|
+
amount?: number;
|
|
590
552
|
lostReasonId?: string;
|
|
591
553
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
* changes call the pipeline service to validate membership + default
|
|
595
|
-
* probability; status transitions (`won` / `lost` / `abandoned`) are
|
|
596
|
-
* terminal.
|
|
597
|
-
*/
|
|
598
|
-
declare class OpportunityService {
|
|
599
|
-
private readonly repo;
|
|
554
|
+
declare class OpportunityRepository extends Repository<IOpportunityDocument> {
|
|
555
|
+
private readonly events;
|
|
600
556
|
private readonly pipelines;
|
|
557
|
+
constructor(model: Model<IOpportunityDocument>, plugins: PluginType[], deps: OpportunityRepositoryDeps, pagination?: PaginationConfig);
|
|
558
|
+
openOpportunity(input: OpenOpportunityInput, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
559
|
+
/**
|
|
560
|
+
* Atomic stage move. CAS on `(status='open', stageId=current)` so two
|
|
561
|
+
* concurrent moves can't both win. Emits `stage_advanced` or
|
|
562
|
+
* `stage_regressed` based on `sequence` ordering of the embedded stages.
|
|
563
|
+
*/
|
|
564
|
+
moveToStage(id: string, input: MoveStageInput, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
565
|
+
win(id: string, input?: CloseInput, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
566
|
+
lose(id: string, input?: CloseInput, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
567
|
+
abandon(id: string, by?: string, note?: string, ctx?: CrmContext): Promise<IOpportunityDocument>;
|
|
568
|
+
private _closeStatus;
|
|
569
|
+
}
|
|
570
|
+
//#endregion
|
|
571
|
+
//#region src/repositories/contact.repository.d.ts
|
|
572
|
+
interface ContactRepositoryDeps {
|
|
573
|
+
events: EventTransport;
|
|
574
|
+
}
|
|
575
|
+
declare class ContactRepository extends Repository<IContactDocument> {
|
|
601
576
|
private readonly events;
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
win(id: string, input?: CloseInput, options?: MutationOptions): Promise<Opportunity>;
|
|
609
|
-
lose(id: string, input?: LoseInput, options?: MutationOptions): Promise<Opportunity>;
|
|
610
|
-
abandon(id: string, by?: string, note?: string, options?: MutationOptions): Promise<Opportunity>;
|
|
611
|
-
delete(id: string): Promise<void>;
|
|
612
|
-
findById(id: string): Promise<Opportunity | null>;
|
|
613
|
-
list(filter?: Parameters<OpportunityRepository['list']>[0]): Promise<Opportunity[]>;
|
|
614
|
-
private _require;
|
|
615
|
-
private _transitionStatus;
|
|
616
|
-
private _emit;
|
|
577
|
+
constructor(model: Model<IContactDocument>, plugins: PluginType[], deps: ContactRepositoryDeps, pagination?: PaginationConfig);
|
|
578
|
+
/**
|
|
579
|
+
* Create + emit `crm:contact.created`. Hosts call this instead of
|
|
580
|
+
* `create()` when they want the event side-effect (e.g. webhook fan-out).
|
|
581
|
+
*/
|
|
582
|
+
createContact(input: Partial<IContactDocument>, ctx?: CrmContext): Promise<IContactDocument>;
|
|
617
583
|
}
|
|
618
584
|
//#endregion
|
|
619
|
-
//#region src/
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
type LeadScorer = (lead: Lead) => number;
|
|
629
|
-
/**
|
|
630
|
-
* Reference implementation. Intentionally simple so hosts read it and
|
|
631
|
-
* understand the shape, then replace it.
|
|
632
|
-
*
|
|
633
|
-
* +20 if email is present
|
|
634
|
-
* +20 if phone is present
|
|
635
|
-
* +20 if companyName is present
|
|
636
|
-
* +10 per populated tag up to 40
|
|
637
|
-
* +10 if jobTitle looks director/manager/head (case-insensitive)
|
|
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
|
-
* ```
|
|
653
|
-
*/
|
|
654
|
-
declare function composeScorers(...rules: readonly LeadScorer[]): LeadScorer;
|
|
585
|
+
//#region src/repositories/account.repository.d.ts
|
|
586
|
+
interface AccountRepositoryDeps {
|
|
587
|
+
events: EventTransport;
|
|
588
|
+
}
|
|
589
|
+
declare class AccountRepository extends Repository<IAccountDocument> {
|
|
590
|
+
private readonly events;
|
|
591
|
+
constructor(model: Model<IAccountDocument>, plugins: PluginType[], deps: AccountRepositoryDeps, pagination?: PaginationConfig);
|
|
592
|
+
createAccount(input: Partial<IAccountDocument>, ctx?: CrmContext): Promise<IAccountDocument>;
|
|
593
|
+
}
|
|
655
594
|
//#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`). */
|
|
680
|
-
scorer?: LeadScorer;
|
|
681
|
-
/** When true (default), `create()` rejects dup emails. */
|
|
595
|
+
//#region src/repositories/campaign.repository.d.ts
|
|
596
|
+
interface CampaignRepositoryDeps {
|
|
597
|
+
events: EventTransport;
|
|
598
|
+
/** Reject `createCampaign` on duplicate names per-tenant (default true). */
|
|
682
599
|
rejectDuplicates?: boolean;
|
|
683
600
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
601
|
+
type ExtrasWithRevenue = {
|
|
602
|
+
by?: string;
|
|
603
|
+
note?: string;
|
|
604
|
+
actualRevenueAmount?: number;
|
|
605
|
+
};
|
|
606
|
+
declare class CampaignRepository extends Repository<ICampaignDocument> {
|
|
607
|
+
private readonly events;
|
|
608
|
+
private readonly rejectDuplicates;
|
|
609
|
+
constructor(model: Model<ICampaignDocument>, plugins: PluginType[], deps: CampaignRepositoryDeps, pagination?: PaginationConfig);
|
|
610
|
+
createCampaign(input: Partial<ICampaignDocument>, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
611
|
+
activate(id: string, by?: string, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
612
|
+
pause(id: string, reason?: string, by?: string, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
613
|
+
resume(id: string, by?: string, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
614
|
+
complete(id: string, extras?: ExtrasWithRevenue, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
615
|
+
archive(id: string, by?: string, ctx?: CrmContext): Promise<ICampaignDocument>;
|
|
616
|
+
private _transition;
|
|
617
|
+
}
|
|
618
|
+
//#endregion
|
|
619
|
+
//#region src/repositories/subscription.repository.d.ts
|
|
620
|
+
interface SubscriptionRepositoryDeps {
|
|
621
|
+
events: EventTransport;
|
|
622
|
+
/** Default DOI policy when `subscribe` doesn't pass `requireDoubleOptIn`. */
|
|
623
|
+
defaultRequireDoubleOptIn?: boolean;
|
|
624
|
+
}
|
|
625
|
+
interface SubscribeInput {
|
|
626
|
+
contactId: string;
|
|
627
|
+
campaignId: string;
|
|
692
628
|
source?: string;
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
tags?: readonly string[];
|
|
629
|
+
consentIpAddress?: string;
|
|
630
|
+
consentUserAgent?: string;
|
|
696
631
|
metadata?: Record<string, unknown>;
|
|
632
|
+
/** Override the engine-level default. */
|
|
633
|
+
requireDoubleOptIn?: boolean;
|
|
697
634
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
635
|
+
declare class SubscriptionRepository extends Repository<ISubscriptionDocument> {
|
|
636
|
+
private readonly events;
|
|
637
|
+
private readonly defaultRequireDoubleOptIn;
|
|
638
|
+
constructor(model: Model<ISubscriptionDocument>, plugins: PluginType[], deps: SubscriptionRepositoryDeps, pagination?: PaginationConfig);
|
|
639
|
+
subscribe(input: SubscribeInput, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
640
|
+
confirm(token: string, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
641
|
+
unsubscribe(token: string, reason?: string, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
642
|
+
markBounced(id: string, reason?: string, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
643
|
+
markComplained(id: string, ctx?: CrmContext): Promise<ISubscriptionDocument>;
|
|
644
|
+
private _transition;
|
|
707
645
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
opportunityId: string;
|
|
646
|
+
//#endregion
|
|
647
|
+
//#region src/repositories/activity.repository.d.ts
|
|
648
|
+
interface ActivityRepositoryDeps {
|
|
649
|
+
events: EventTransport;
|
|
713
650
|
}
|
|
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;
|
|
651
|
+
declare class ActivityRepository extends Repository<IActivityDocument> {
|
|
724
652
|
private readonly events;
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
constructor(config: LeadServiceConfig);
|
|
731
|
-
create(input: CreateLeadInput, options?: MutationOptions): Promise<Lead>;
|
|
732
|
-
markContacted(id: string, by?: string, note?: string, options?: MutationOptions): Promise<Lead>;
|
|
733
|
-
qualify(id: string, by?: string, note?: string, options?: MutationOptions): Promise<Lead>;
|
|
734
|
-
disqualify(id: string, reason: string, by?: string, options?: MutationOptions): Promise<Lead>;
|
|
735
|
-
nurture(id: string, by?: string, options?: MutationOptions): Promise<Lead>;
|
|
736
|
-
convert(id: string, input: ConvertLeadInput, options?: MutationOptions): Promise<ConvertResult>;
|
|
737
|
-
/** Recompute score and persist. Hosts can call on update or on demand. */
|
|
738
|
-
recomputeScore(id: string, options?: MutationOptions): Promise<Lead>;
|
|
739
|
-
findById(id: string): Promise<Lead | null>;
|
|
740
|
-
list(filter?: Parameters<LeadRepository['list']>[0]): Promise<Lead[]>;
|
|
741
|
-
private _updateScore;
|
|
742
|
-
private _require;
|
|
653
|
+
constructor(model: Model<IActivityDocument>, plugins: PluginType[], deps: ActivityRepositoryDeps, pagination?: PaginationConfig);
|
|
654
|
+
plan(input: Partial<IActivityDocument>, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
655
|
+
start(id: string, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
656
|
+
complete(id: string, completedAt?: Date, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
657
|
+
cancel(id: string, reason?: string, ctx?: CrmContext): Promise<IActivityDocument>;
|
|
743
658
|
private _transition;
|
|
744
|
-
private _emit;
|
|
745
659
|
}
|
|
746
660
|
//#endregion
|
|
747
|
-
//#region src/
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
color?: string;
|
|
761
|
-
/** Describes what "reaching this stage" means. */
|
|
762
|
-
description?: string;
|
|
661
|
+
//#region src/repositories/note.repository.d.ts
|
|
662
|
+
interface NoteRepositoryDeps {
|
|
663
|
+
events: EventTransport;
|
|
664
|
+
}
|
|
665
|
+
declare class NoteRepository extends Repository<INoteDocument> {
|
|
666
|
+
private readonly events;
|
|
667
|
+
constructor(model: Model<INoteDocument>, plugins: PluginType[], deps: NoteRepositoryDeps, pagination?: PaginationConfig);
|
|
668
|
+
addNote(input: Partial<INoteDocument>, ctx?: CrmContext): Promise<INoteDocument>;
|
|
669
|
+
}
|
|
670
|
+
//#endregion
|
|
671
|
+
//#region src/repositories/loss-reason.repository.d.ts
|
|
672
|
+
interface LossReasonRepositoryDeps {
|
|
673
|
+
events: EventTransport;
|
|
763
674
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
*/
|
|
770
|
-
interface Pipeline {
|
|
771
|
-
id: string;
|
|
772
|
-
name: string;
|
|
773
|
-
/** Deprecates this pipeline — opportunities can still move within it but no new ones are created. */
|
|
774
|
-
isArchived: boolean;
|
|
775
|
-
stages: readonly Stage[];
|
|
776
|
-
/** Free-form label for the sales team / motion that owns this pipeline. */
|
|
777
|
-
teamRef?: string;
|
|
778
|
-
metadata?: Record<string, unknown>;
|
|
779
|
-
createdAt: Date;
|
|
780
|
-
updatedAt: Date;
|
|
675
|
+
declare class LossReasonRepository extends Repository<ILossReasonDocument> {
|
|
676
|
+
private readonly events;
|
|
677
|
+
constructor(model: Model<ILossReasonDocument>, plugins: PluginType[], deps: LossReasonRepositoryDeps, pagination?: PaginationConfig);
|
|
678
|
+
/** Hide from pickers without breaking historical FKs. */
|
|
679
|
+
archive(id: string, ctx?: CrmContext): Promise<ILossReasonDocument>;
|
|
781
680
|
}
|
|
782
681
|
//#endregion
|
|
783
|
-
//#region src/
|
|
784
|
-
interface
|
|
785
|
-
|
|
786
|
-
list(includeArchived?: boolean): Promise<Pipeline[]>;
|
|
787
|
-
create(p: Omit<Pipeline, 'createdAt' | 'updatedAt'>): Promise<Pipeline>;
|
|
788
|
-
update(id: string, patch: Partial<Pipeline>): Promise<Pipeline>;
|
|
682
|
+
//#region src/repositories/email-event.repository.d.ts
|
|
683
|
+
interface EmailEventRepositoryDeps {
|
|
684
|
+
events: EventTransport;
|
|
789
685
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
ids?: IdGenerator;
|
|
799
|
-
}
|
|
800
|
-
interface CreatePipelineInput {
|
|
801
|
-
name: string;
|
|
802
|
-
stages: readonly Omit<Stage, 'id'>[];
|
|
803
|
-
teamRef?: string;
|
|
686
|
+
interface RecordEmailEventInput {
|
|
687
|
+
subjectKind: EmailEventSubjectKind;
|
|
688
|
+
subjectId: string;
|
|
689
|
+
campaignId?: string;
|
|
690
|
+
messageId?: string;
|
|
691
|
+
url?: string;
|
|
692
|
+
userAgent?: string;
|
|
693
|
+
ip?: string;
|
|
804
694
|
metadata?: Record<string, unknown>;
|
|
805
695
|
}
|
|
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;
|
|
696
|
+
declare class EmailEventRepository extends Repository<IEmailEventDocument> {
|
|
814
697
|
private readonly events;
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
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;
|
|
698
|
+
constructor(model: Model<IEmailEventDocument>, plugins: PluginType[], deps: EmailEventRepositoryDeps, pagination?: PaginationConfig);
|
|
699
|
+
recordOpen(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
700
|
+
recordClick(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
701
|
+
recordBounce(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
702
|
+
recordComplaint(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
703
|
+
recordUnsubscribe(input: RecordEmailEventInput, ctx?: CrmContext): Promise<IEmailEventDocument>;
|
|
704
|
+
private _record;
|
|
830
705
|
}
|
|
831
706
|
//#endregion
|
|
832
|
-
//#region src/
|
|
833
|
-
interface
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
/**
|
|
841
|
-
|
|
842
|
-
currency: string;
|
|
843
|
-
}
|
|
844
|
-
interface ForecastOptions {
|
|
707
|
+
//#region src/engine/engine-types.d.ts
|
|
708
|
+
interface CrmLogger {
|
|
709
|
+
info?(msg: string, meta?: Record<string, unknown>): void;
|
|
710
|
+
warn?(msg: string, meta?: Record<string, unknown>): void;
|
|
711
|
+
error?(msg: string, meta?: Record<string, unknown>): void;
|
|
712
|
+
debug?(msg: string, meta?: Record<string, unknown>): void;
|
|
713
|
+
}
|
|
714
|
+
interface CrmConfig {
|
|
715
|
+
/** Mongoose connection — package creates models on this connection. */
|
|
716
|
+
connection: Connection;
|
|
845
717
|
/**
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
*
|
|
718
|
+
* Tenant column shape. `'objectId'` (default) matches Better Auth orgs
|
|
719
|
+
* and unlocks `$lookup` / `.populate()`; `'string'` matches UUID hosts.
|
|
720
|
+
* Threaded into both schemas and `multiTenantPlugin` so they stay in
|
|
721
|
+
* sync (PACKAGE_RULES §9.2).
|
|
849
722
|
*/
|
|
850
|
-
|
|
723
|
+
tenantFieldType?: TenantFieldType;
|
|
851
724
|
/**
|
|
852
|
-
*
|
|
853
|
-
* `
|
|
725
|
+
* When `true` (default), wire `multiTenantPlugin` on every repository
|
|
726
|
+
* with `required: true`. Set `false` only for fixtures / smoke tests
|
|
727
|
+
* that intentionally drop the scope.
|
|
854
728
|
*/
|
|
855
|
-
|
|
729
|
+
multiTenant?: boolean;
|
|
730
|
+
/** Arc-compatible event transport. Default: in-process bus. */
|
|
731
|
+
eventTransport?: EventTransport;
|
|
732
|
+
/** Logger surface used by the in-process bus + repositories. */
|
|
733
|
+
logger?: CrmLogger;
|
|
734
|
+
/** Pagination defaults for every repository (mongokit). */
|
|
735
|
+
pagination?: PaginationConfig;
|
|
736
|
+
/** Extra mongokit plugins applied to every repository (after defaults). */
|
|
737
|
+
plugins?: PluginType[];
|
|
738
|
+
}
|
|
739
|
+
interface ResolvedCrmConfig extends SchemaBuildConfig {
|
|
740
|
+
connection: Connection;
|
|
741
|
+
tenantFieldType: TenantFieldType;
|
|
742
|
+
multiTenant: boolean;
|
|
743
|
+
logger?: CrmLogger;
|
|
744
|
+
pagination?: PaginationConfig;
|
|
745
|
+
plugins: PluginType[];
|
|
746
|
+
}
|
|
747
|
+
interface CrmRepositories {
|
|
748
|
+
pipeline: PipelineRepository;
|
|
749
|
+
lead: LeadRepository;
|
|
750
|
+
opportunity: OpportunityRepository;
|
|
751
|
+
contact: ContactRepository;
|
|
752
|
+
account: AccountRepository;
|
|
753
|
+
campaign: CampaignRepository;
|
|
754
|
+
subscription: SubscriptionRepository;
|
|
755
|
+
activity: ActivityRepository;
|
|
756
|
+
note: NoteRepository;
|
|
757
|
+
lossReason: LossReasonRepository;
|
|
758
|
+
emailEvent: EmailEventRepository;
|
|
759
|
+
}
|
|
760
|
+
interface CrmEngine {
|
|
761
|
+
/** Repositories ARE the API surface (PACKAGE_RULES §1). */
|
|
762
|
+
readonly repositories: Readonly<CrmRepositories>;
|
|
763
|
+
/** Arc-compatible event transport. */
|
|
764
|
+
readonly events: EventTransport;
|
|
765
|
+
/** Mongoose models — for arc adapter wiring. */
|
|
766
|
+
readonly models: Readonly<CrmModels>;
|
|
767
|
+
/** Resolved configuration (frozen). */
|
|
768
|
+
readonly config: Readonly<ResolvedCrmConfig>;
|
|
769
|
+
/** Release resources. Safe to call multiple times. */
|
|
770
|
+
dispose(): Promise<void>;
|
|
856
771
|
}
|
|
857
772
|
/**
|
|
858
|
-
*
|
|
859
|
-
*
|
|
860
|
-
*
|
|
861
|
-
*
|
|
862
|
-
* Integer-safe: sums are computed on minor-unit amounts (consistent
|
|
863
|
-
* with `@classytic/primitives/money`'s integer convention). Currency
|
|
864
|
-
* mismatch across a bucket throws — hosts dealing in multi-currency
|
|
865
|
-
* run this once per currency after partitioning.
|
|
866
|
-
*/
|
|
867
|
-
declare function forecast(opportunities: readonly Opportunity[], options?: ForecastOptions): ForecastRow[];
|
|
868
|
-
/**
|
|
869
|
-
* Pipeline conversion summary — how opportunities partitioned across
|
|
870
|
-
* stages and final outcome. Useful for "where do deals die?" analysis.
|
|
773
|
+
* Operation context threaded through every domain verb. Extends
|
|
774
|
+
* primitives' `OperationContext` and narrows `IdLike` to types Mongoose
|
|
775
|
+
* stores cleanly. Host-specific extras go through the inherited
|
|
776
|
+
* `metadata?` field — keep the typed surface tight.
|
|
871
777
|
*/
|
|
872
|
-
interface
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
conversionRate: number;
|
|
778
|
+
interface CrmContext extends OperationContext {
|
|
779
|
+
organizationId?: string | mongoose0.Types.ObjectId;
|
|
780
|
+
actorId?: string | mongoose0.Types.ObjectId;
|
|
781
|
+
/** Mongo transaction session (passed through to mongokit). */
|
|
782
|
+
session?: unknown;
|
|
878
783
|
}
|
|
879
|
-
|
|
784
|
+
type _ModelTypes = Model<unknown>;
|
|
880
785
|
//#endregion
|
|
881
|
-
//#region src/
|
|
882
|
-
|
|
883
|
-
* Standardized reason for closing an opportunity as `lost`. Seeded
|
|
884
|
-
* once by the host; referenced by id on the opportunity. Keeping
|
|
885
|
-
* these as records (vs free-form strings) is what makes lost-reason
|
|
886
|
-
* analytics possible.
|
|
887
|
-
*/
|
|
888
|
-
interface LossReason {
|
|
889
|
-
id: string;
|
|
890
|
-
name: string;
|
|
891
|
-
/** Broad category — `price`, `feature-gap`, `timing`, `competitor`, `no-decision`. */
|
|
892
|
-
category?: string;
|
|
893
|
-
description?: string;
|
|
894
|
-
active: boolean;
|
|
895
|
-
metadata?: Record<string, unknown>;
|
|
896
|
-
createdAt: Date;
|
|
897
|
-
updatedAt: Date;
|
|
898
|
-
}
|
|
786
|
+
//#region src/engine/create-crm.d.ts
|
|
787
|
+
declare function createCrm(config: CrmConfig): Promise<CrmEngine>;
|
|
899
788
|
//#endregion
|
|
900
|
-
//#region src/
|
|
901
|
-
interface
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
create(r: Omit<LossReason, 'createdAt' | 'updatedAt'>): Promise<LossReason>;
|
|
905
|
-
update(id: string, patch: Partial<LossReason>): Promise<LossReason>;
|
|
789
|
+
//#region src/repositories/create-repositories.d.ts
|
|
790
|
+
interface CreateCrmRepositoriesDeps {
|
|
791
|
+
events: EventTransport;
|
|
792
|
+
config: ResolvedCrmConfig;
|
|
906
793
|
}
|
|
794
|
+
declare function createCrmRepositories(models: CrmModels, deps: CreateCrmRepositoriesDeps): CrmRepositories;
|
|
907
795
|
//#endregion
|
|
908
|
-
//#region src/
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
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>;
|
|
796
|
+
//#region src/services/lead.service.d.ts
|
|
797
|
+
interface ConvertLeadInput {
|
|
798
|
+
pipelineId: string;
|
|
799
|
+
/** Defaults to `<companyName> — <source>` / `<fullName> — New`. */
|
|
800
|
+
opportunityName?: string;
|
|
801
|
+
/** Stored flat on the opportunity (`amount` + `currency`). */
|
|
802
|
+
amount?: number;
|
|
803
|
+
currency?: string;
|
|
804
|
+
expectedCloseAt?: Date;
|
|
805
|
+
by?: string;
|
|
927
806
|
}
|
|
928
|
-
interface
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
807
|
+
interface ConvertResult {
|
|
808
|
+
lead: ILeadDocument;
|
|
809
|
+
contact: IContactDocument;
|
|
810
|
+
account?: IAccountDocument;
|
|
811
|
+
opportunity: IOpportunityDocument;
|
|
812
|
+
/** @deprecated use contact._id */
|
|
813
|
+
contactId: string;
|
|
814
|
+
/** @deprecated use account._id */
|
|
815
|
+
accountId?: string;
|
|
816
|
+
/** @deprecated use opportunity._id */
|
|
817
|
+
opportunityId: string;
|
|
932
818
|
}
|
|
933
|
-
interface
|
|
934
|
-
|
|
819
|
+
interface LeadServiceDeps {
|
|
820
|
+
lead: LeadRepository;
|
|
821
|
+
contact: ContactRepository;
|
|
822
|
+
account: AccountRepository;
|
|
823
|
+
opportunity: OpportunityRepository;
|
|
824
|
+
events: EventTransport;
|
|
935
825
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
private readonly
|
|
940
|
-
private readonly
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
826
|
+
declare class LeadService {
|
|
827
|
+
private readonly leads;
|
|
828
|
+
private readonly contacts;
|
|
829
|
+
private readonly accounts;
|
|
830
|
+
private readonly opportunities;
|
|
831
|
+
private readonly events;
|
|
832
|
+
constructor(deps: LeadServiceDeps);
|
|
833
|
+
/**
|
|
834
|
+
* Construct from an already-built CrmEngine — the host's preferred path.
|
|
835
|
+
* Avoids manually wiring four repositories.
|
|
836
|
+
*/
|
|
837
|
+
static fromEngine(engine: CrmEngine): LeadService;
|
|
838
|
+
/**
|
|
839
|
+
* Convert a Lead into Account + Contact + Opportunity, then transition
|
|
840
|
+
* the lead. Wrap the call in `connection.transaction()` and pass the
|
|
841
|
+
* session via `ctx.session` for atomicity — all four writes commit or
|
|
842
|
+
* roll back together.
|
|
843
|
+
*
|
|
844
|
+
* Best-effort compensation: if a downstream write fails, already-
|
|
845
|
+
* created docs are deleted in reverse order. The reverse delete may
|
|
846
|
+
* itself fail (e.g. transient DB issues) — when transactions are
|
|
847
|
+
* active, prefer that path; compensation is the no-transaction
|
|
848
|
+
* fallback.
|
|
849
|
+
*/
|
|
850
|
+
convert(leadId: string, input: ConvertLeadInput, ctx?: CrmContext): Promise<ConvertResult>;
|
|
851
|
+
/**
|
|
852
|
+
* The state-machine hop from whichever status the lead is in to
|
|
853
|
+
* `converted`. We do this directly (instead of calling
|
|
854
|
+
* `LeadRepository.qualify` first then a hypothetical `complete`)
|
|
855
|
+
* because the conversion is "this lead is done" regardless of where
|
|
856
|
+
* it started — bypassing the `qualified` waypoint is intentional when
|
|
857
|
+
* a Lead is converted directly from `new` (importers, webhooks).
|
|
858
|
+
*/
|
|
859
|
+
private _markConverted;
|
|
948
860
|
}
|
|
949
861
|
//#endregion
|
|
950
|
-
//#region src/
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
862
|
+
//#region src/events/event-constants.d.ts
|
|
863
|
+
/** PACKAGE_RULES rule 12: `package:resource.verb`. */
|
|
864
|
+
declare const CRM_EVENTS: {
|
|
865
|
+
readonly LEAD_CREATED: "crm:lead.created";
|
|
866
|
+
readonly LEAD_STATUS_CHANGED: "crm:lead.status_changed";
|
|
867
|
+
readonly LEAD_SCORED: "crm:lead.scored";
|
|
868
|
+
readonly LEAD_CONVERTED: "crm:lead.converted";
|
|
869
|
+
readonly LEAD_DISQUALIFIED: "crm:lead.disqualified";
|
|
870
|
+
readonly ACCOUNT_CREATED: "crm:account.created";
|
|
871
|
+
readonly ACCOUNT_UPDATED: "crm:account.updated";
|
|
872
|
+
readonly CONTACT_CREATED: "crm:contact.created";
|
|
873
|
+
readonly CONTACT_UPDATED: "crm:contact.updated";
|
|
874
|
+
readonly OPPORTUNITY_CREATED: "crm:opportunity.created";
|
|
875
|
+
readonly OPPORTUNITY_STAGE_ADVANCED: "crm:opportunity.stage_advanced";
|
|
876
|
+
readonly OPPORTUNITY_STAGE_REGRESSED: "crm:opportunity.stage_regressed";
|
|
877
|
+
readonly OPPORTUNITY_WON: "crm:opportunity.won";
|
|
878
|
+
readonly OPPORTUNITY_LOST: "crm:opportunity.lost";
|
|
879
|
+
readonly OPPORTUNITY_ABANDONED: "crm:opportunity.abandoned";
|
|
880
|
+
readonly PIPELINE_CREATED: "crm:pipeline.created";
|
|
881
|
+
readonly PIPELINE_ARCHIVED: "crm:pipeline.archived";
|
|
882
|
+
readonly ACTIVITY_PLANNED: "crm:activity.planned";
|
|
883
|
+
readonly ACTIVITY_COMPLETED: "crm:activity.completed";
|
|
884
|
+
readonly ACTIVITY_CANCELLED: "crm:activity.cancelled";
|
|
885
|
+
readonly NOTE_ADDED: "crm:note.added";
|
|
886
|
+
readonly CAMPAIGN_CREATED: "crm:campaign.created";
|
|
887
|
+
readonly CAMPAIGN_ACTIVATED: "crm:campaign.activated";
|
|
888
|
+
readonly CAMPAIGN_PAUSED: "crm:campaign.paused";
|
|
889
|
+
readonly CAMPAIGN_RESUMED: "crm:campaign.resumed";
|
|
890
|
+
readonly CAMPAIGN_COMPLETED: "crm:campaign.completed";
|
|
891
|
+
readonly CAMPAIGN_ARCHIVED: "crm:campaign.archived";
|
|
892
|
+
readonly SUBSCRIPTION_CREATED: "crm:subscription.created";
|
|
893
|
+
readonly SUBSCRIPTION_CONFIRMED: "crm:subscription.confirmed";
|
|
894
|
+
readonly SUBSCRIPTION_UNSUBSCRIBED: "crm:subscription.unsubscribed";
|
|
895
|
+
readonly SUBSCRIPTION_BOUNCED: "crm:subscription.bounced";
|
|
896
|
+
readonly SUBSCRIPTION_COMPLAINED: "crm:subscription.complained";
|
|
897
|
+
readonly EMAIL_EVENT_OPENED: "crm:email_event.opened";
|
|
898
|
+
readonly EMAIL_EVENT_CLICKED: "crm:email_event.clicked";
|
|
899
|
+
readonly EMAIL_EVENT_BOUNCED: "crm:email_event.bounced";
|
|
900
|
+
readonly EMAIL_EVENT_COMPLAINED: "crm:email_event.complained";
|
|
901
|
+
readonly EMAIL_EVENT_UNSUBSCRIBED: "crm:email_event.unsubscribed";
|
|
902
|
+
};
|
|
903
|
+
type CrmEventName = (typeof CRM_EVENTS)[keyof typeof CRM_EVENTS];
|
|
961
904
|
//#endregion
|
|
962
|
-
//#region src/
|
|
963
|
-
declare
|
|
964
|
-
private readonly clock;
|
|
965
|
-
private readonly items;
|
|
966
|
-
constructor(clock?: Clock);
|
|
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>;
|
|
973
|
-
}
|
|
905
|
+
//#region src/events/helpers.d.ts
|
|
906
|
+
declare function createEvent<T>(type: string, payload: T, ctx?: CrmContext, meta?: Partial<EventMeta>): DomainEvent<T>;
|
|
974
907
|
//#endregion
|
|
975
|
-
//#region src/
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
908
|
+
//#region src/events/in-process-bus.d.ts
|
|
909
|
+
declare class InProcessCrmBus implements EventTransport {
|
|
910
|
+
readonly name = "in-process-crm";
|
|
911
|
+
private subs;
|
|
912
|
+
private logger?;
|
|
913
|
+
constructor(options?: {
|
|
914
|
+
logger?: CrmLogger;
|
|
915
|
+
});
|
|
981
916
|
publish(event: DomainEvent): Promise<void>;
|
|
982
917
|
subscribe(pattern: string, handler: EventHandler): Promise<() => void>;
|
|
918
|
+
close(): Promise<void>;
|
|
983
919
|
}
|
|
984
920
|
//#endregion
|
|
985
|
-
//#region src/
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
update(id: string, patch: Partial<LossReason>): Promise<LossReason>;
|
|
1007
|
-
}
|
|
1008
|
-
//#endregion
|
|
1009
|
-
//#region src/adapters/in-memory/note-repository.d.ts
|
|
1010
|
-
declare class InMemoryNoteRepository implements NoteRepository {
|
|
1011
|
-
private readonly clock;
|
|
1012
|
-
private readonly items;
|
|
1013
|
-
constructor(clock?: Clock);
|
|
1014
|
-
findById(id: string): Promise<Note | null>;
|
|
1015
|
-
listBySubject(subjectKind: SubjectKind, subjectId: string): Promise<Note[]>;
|
|
1016
|
-
create(input: Omit<Note, 'createdAt' | 'updatedAt'>): Promise<Note>;
|
|
1017
|
-
update(id: string, patch: Partial<Note>): Promise<Note>;
|
|
1018
|
-
delete(id: string): Promise<void>;
|
|
1019
|
-
}
|
|
1020
|
-
//#endregion
|
|
1021
|
-
//#region src/adapters/in-memory/opportunity-repository.d.ts
|
|
1022
|
-
declare class InMemoryOpportunityRepository implements OpportunityRepository {
|
|
1023
|
-
private readonly clock;
|
|
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>;
|
|
1033
|
-
}
|
|
1034
|
-
//#endregion
|
|
1035
|
-
//#region src/adapters/in-memory/pipeline-repository.d.ts
|
|
1036
|
-
declare class InMemoryPipelineRepository implements PipelineRepository {
|
|
1037
|
-
private readonly clock;
|
|
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>;
|
|
1044
|
-
}
|
|
1045
|
-
//#endregion
|
|
1046
|
-
//#region src/adapters/in-memory/outreach-port.d.ts
|
|
1047
|
-
declare class NullOutreachPort implements OutreachPort {
|
|
1048
|
-
private counter;
|
|
1049
|
-
send(_request: OutreachSendRequest): Promise<OutreachSendResult>;
|
|
1050
|
-
}
|
|
1051
|
-
interface RecordedOutreach extends OutreachSendRequest, OutreachSendResult {}
|
|
1052
|
-
declare class InMemoryOutreachPort implements OutreachPort {
|
|
1053
|
-
private readonly nowMs;
|
|
1054
|
-
readonly sent: RecordedOutreach[];
|
|
1055
|
-
private counter;
|
|
1056
|
-
constructor(nowMs?: () => number);
|
|
1057
|
-
send(request: OutreachSendRequest): Promise<OutreachSendResult>;
|
|
1058
|
-
}
|
|
1059
|
-
//#endregion
|
|
1060
|
-
//#region src/adapters/in-memory/id-generator.d.ts
|
|
1061
|
-
declare const cryptoIdGenerator: IdGenerator;
|
|
1062
|
-
declare function createSequentialIdGenerator(prefix?: string): IdGenerator;
|
|
921
|
+
//#region src/core/state-machines.d.ts
|
|
922
|
+
/**
|
|
923
|
+
* Declarative state machines for every CRM aggregate that has lifecycle
|
|
924
|
+
* transitions. Single source of truth for what `from -> to` moves are
|
|
925
|
+
* legal — the repositories' domain verbs (`qualify`, `convert`, `win`,
|
|
926
|
+
* `lose`, `confirm`, `unsubscribe`, ...) call `assertTransition` before
|
|
927
|
+
* they touch Mongo.
|
|
928
|
+
*
|
|
929
|
+
* Per PACKAGE_RULES §30: "State machines map to Arc Actions". The host
|
|
930
|
+
* exposes each domain verb as an arc Action (`POST /:id/action` with
|
|
931
|
+
* `{ action: 'qualify' }`); the verb's implementation lives on the
|
|
932
|
+
* Repository class and uses these machines internally.
|
|
933
|
+
*
|
|
934
|
+
* Built on `@classytic/primitives/state-machine` so the same shape lights
|
|
935
|
+
* up across kits (mongokit's `claim()` pairing, sqlitekit follow-ups).
|
|
936
|
+
*/
|
|
937
|
+
declare const LEAD_MACHINE: _classytic_primitives_state_machine0.StateMachine<"new" | "contacted" | "qualified" | "converted" | "disqualified" | "nurturing">;
|
|
938
|
+
declare const OPPORTUNITY_MACHINE: _classytic_primitives_state_machine0.StateMachine<"open" | "won" | "lost" | "abandoned">;
|
|
939
|
+
declare const CAMPAIGN_MACHINE: _classytic_primitives_state_machine0.StateMachine<"draft" | "active" | "paused" | "completed" | "archived">;
|
|
940
|
+
declare const SUBSCRIPTION_MACHINE: _classytic_primitives_state_machine0.StateMachine<"pending" | "confirmed" | "unsubscribed" | "bounced" | "complained">;
|
|
941
|
+
declare const ACTIVITY_MACHINE: _classytic_primitives_state_machine0.StateMachine<"completed" | "planned" | "in_progress" | "cancelled">;
|
|
1063
942
|
//#endregion
|
|
1064
|
-
//#region src/
|
|
943
|
+
//#region src/core/errors.d.ts
|
|
1065
944
|
/**
|
|
1066
945
|
* CRM error vocabulary. Hosts catch `CrmError` at API edges.
|
|
1067
946
|
*/
|
|
@@ -1112,309 +991,585 @@ declare class DuplicateLeadError extends CrmError {
|
|
|
1112
991
|
declare class EmptyPipelineError extends CrmError {
|
|
1113
992
|
constructor(pipelineId: string);
|
|
1114
993
|
}
|
|
994
|
+
declare class InvalidCampaignTransitionError extends CrmError {
|
|
995
|
+
constructor(details: {
|
|
996
|
+
from: string;
|
|
997
|
+
to: string;
|
|
998
|
+
campaignId: string;
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
declare class DuplicateCampaignError extends CrmError {
|
|
1002
|
+
constructor(name: string);
|
|
1003
|
+
}
|
|
1004
|
+
declare class InvalidSubscriptionTransitionError extends CrmError {
|
|
1005
|
+
constructor(details: {
|
|
1006
|
+
from: string;
|
|
1007
|
+
to: string;
|
|
1008
|
+
subscriptionId: string;
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
declare class DuplicateSubscriptionError extends CrmError {
|
|
1012
|
+
constructor(details: {
|
|
1013
|
+
contactId: string;
|
|
1014
|
+
campaignId: string;
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
declare class InvalidConfirmationTokenError extends CrmError {
|
|
1018
|
+
constructor();
|
|
1019
|
+
}
|
|
1020
|
+
declare class InvalidUnsubscribeTokenError extends CrmError {
|
|
1021
|
+
constructor();
|
|
1022
|
+
}
|
|
1115
1023
|
//#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
|
-
|
|
1024
|
+
//#region src/shared/calculators/forecast.d.ts
|
|
1025
|
+
type OpportunityForecast = Pick<IOpportunityDocument, 'amount' | 'currency' | 'probability' | 'status' | 'expectedCloseAt' | 'stageId' | 'statusHistory'>;
|
|
1026
|
+
interface ForecastRow {
|
|
1027
|
+
/** Bucket key — ISO month `YYYY-MM` by default. */
|
|
1028
|
+
bucket: string;
|
|
1029
|
+
/** Σ amount. */
|
|
1030
|
+
committed: number;
|
|
1031
|
+
/** Σ amount × probability. */
|
|
1032
|
+
weighted: number;
|
|
1033
|
+
/** Number of opportunities in the bucket. */
|
|
1034
|
+
count: number;
|
|
1035
|
+
currency: string;
|
|
1036
|
+
}
|
|
1037
|
+
interface ForecastOptions {
|
|
1038
|
+
/** Bucket function. Default: ISO month from `expectedCloseAt`. */
|
|
1039
|
+
bucket?: (o: OpportunityForecast) => string;
|
|
1040
|
+
/** Filter before bucketing. Default: open + has amount + has expectedCloseAt. */
|
|
1041
|
+
include?: (o: OpportunityForecast) => boolean;
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Aggregate opportunities into a forecast table — one row per bucket.
|
|
1045
|
+
* Currency mismatch within a bucket throws — partition by currency
|
|
1046
|
+
* upstream when multi-currency.
|
|
1047
|
+
*/
|
|
1048
|
+
declare function forecast(opportunities: readonly OpportunityForecast[], options?: ForecastOptions): ForecastRow[];
|
|
1049
|
+
interface ConversionRow {
|
|
1050
|
+
stageId: string;
|
|
1051
|
+
currentCount: number;
|
|
1052
|
+
wonFromHere: number;
|
|
1053
|
+
lostFromHere: number;
|
|
1054
|
+
conversionRate: number;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* "Where do deals die?" summary — opportunities partitioned across
|
|
1058
|
+
* stages with current count + won/lost-from-here.
|
|
1059
|
+
*/
|
|
1060
|
+
declare function pipelineConversion(opportunities: readonly OpportunityForecast[], stageIds: readonly string[]): ConversionRow[];
|
|
1142
1061
|
//#endregion
|
|
1143
|
-
//#region src/
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
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>;
|
|
1062
|
+
//#region src/validators/common.d.ts
|
|
1063
|
+
declare const objectIdLike: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
|
|
1064
|
+
declare const metadataSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1065
|
+
declare const tagsSchema: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1066
|
+
declare const moneyAmountSchema: z.ZodNumber;
|
|
1067
|
+
declare const currencyCodeSchema: z.ZodString;
|
|
1068
|
+
//#endregion
|
|
1069
|
+
//#region src/validators/pipeline.schema.d.ts
|
|
1070
|
+
declare const stageInputSchema: z.ZodObject<{
|
|
1071
|
+
name: z.ZodString;
|
|
1072
|
+
sequence: z.ZodNumber;
|
|
1073
|
+
defaultProbability: z.ZodNumber;
|
|
1074
|
+
color: z.ZodOptional<z.ZodString>;
|
|
1075
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1168
1076
|
}, z.core.$strip>;
|
|
1169
|
-
declare const
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1077
|
+
declare const createPipelineSchema: z.ZodObject<{
|
|
1078
|
+
name: z.ZodString;
|
|
1079
|
+
stages: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1080
|
+
name: z.ZodString;
|
|
1081
|
+
sequence: z.ZodNumber;
|
|
1082
|
+
defaultProbability: z.ZodNumber;
|
|
1083
|
+
color: z.ZodOptional<z.ZodString>;
|
|
1084
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1085
|
+
}, z.core.$strip>>>;
|
|
1086
|
+
teamRef: z.ZodOptional<z.ZodString>;
|
|
1087
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1173
1088
|
}, z.core.$strip>;
|
|
1174
|
-
declare const
|
|
1175
|
-
|
|
1176
|
-
|
|
1089
|
+
declare const updatePipelineSchema: z.ZodObject<{
|
|
1090
|
+
name: z.ZodOptional<z.ZodString>;
|
|
1091
|
+
stages: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1092
|
+
name: z.ZodString;
|
|
1093
|
+
sequence: z.ZodNumber;
|
|
1094
|
+
defaultProbability: z.ZodNumber;
|
|
1095
|
+
color: z.ZodOptional<z.ZodString>;
|
|
1096
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1097
|
+
}, z.core.$strip>>>>;
|
|
1098
|
+
teamRef: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1099
|
+
metadata: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1177
1100
|
}, z.core.$strip>;
|
|
1178
|
-
declare const
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1101
|
+
declare const stageInputSchemaExport: z.ZodObject<{
|
|
1102
|
+
name: z.ZodString;
|
|
1103
|
+
sequence: z.ZodNumber;
|
|
1104
|
+
defaultProbability: z.ZodNumber;
|
|
1105
|
+
color: z.ZodOptional<z.ZodString>;
|
|
1106
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1183
1107
|
}, z.core.$strip>;
|
|
1184
|
-
declare const
|
|
1185
|
-
|
|
1186
|
-
|
|
1108
|
+
declare const pipelineFilterSchema: z.ZodObject<{
|
|
1109
|
+
isArchived: z.ZodOptional<z.ZodCoercedBoolean<unknown>>;
|
|
1110
|
+
teamRef: z.ZodOptional<z.ZodString>;
|
|
1187
1111
|
}, z.core.$strip>;
|
|
1188
|
-
|
|
1189
|
-
|
|
1112
|
+
type CreatePipelineDto = z.infer<typeof createPipelineSchema>;
|
|
1113
|
+
type UpdatePipelineDto = z.infer<typeof updatePipelineSchema>;
|
|
1114
|
+
type StageInputDto = z.infer<typeof stageInputSchema>;
|
|
1115
|
+
//#endregion
|
|
1116
|
+
//#region src/validators/lead.schema.d.ts
|
|
1117
|
+
declare const createLeadSchema: z.ZodObject<{
|
|
1118
|
+
fullName: z.ZodOptional<z.ZodString>;
|
|
1119
|
+
firstName: z.ZodOptional<z.ZodString>;
|
|
1120
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
1121
|
+
email: z.ZodOptional<z.ZodString>;
|
|
1122
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
1123
|
+
companyName: z.ZodOptional<z.ZodString>;
|
|
1124
|
+
jobTitle: z.ZodOptional<z.ZodString>;
|
|
1125
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1126
|
+
campaignRef: z.ZodOptional<z.ZodString>;
|
|
1127
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1128
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1129
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1190
1130
|
}, z.core.$strip>;
|
|
1191
|
-
declare const
|
|
1192
|
-
|
|
1131
|
+
declare const updateLeadSchema: z.ZodObject<{
|
|
1132
|
+
fullName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1133
|
+
firstName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1134
|
+
lastName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1135
|
+
email: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1136
|
+
phone: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1137
|
+
companyName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1138
|
+
jobTitle: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1139
|
+
source: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1140
|
+
campaignRef: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1141
|
+
ownerId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1142
|
+
tags: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
1143
|
+
metadata: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1193
1144
|
}, z.core.$strip>;
|
|
1194
|
-
declare const
|
|
1195
|
-
|
|
1145
|
+
declare const leadFilterSchema: z.ZodObject<{
|
|
1146
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
1147
|
+
new: "new";
|
|
1148
|
+
contacted: "contacted";
|
|
1149
|
+
qualified: "qualified";
|
|
1150
|
+
converted: "converted";
|
|
1151
|
+
disqualified: "disqualified";
|
|
1152
|
+
nurturing: "nurturing";
|
|
1153
|
+
}>>;
|
|
1154
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1196
1155
|
email: z.ZodOptional<z.ZodString>;
|
|
1156
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1157
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1158
|
+
campaignRef: z.ZodOptional<z.ZodString>;
|
|
1159
|
+
scoreMin: z.ZodOptional<z.ZodNumber>;
|
|
1160
|
+
scoreMax: z.ZodOptional<z.ZodNumber>;
|
|
1197
1161
|
}, z.core.$strip>;
|
|
1198
|
-
declare const
|
|
1199
|
-
|
|
1162
|
+
declare const convertLeadSchema: z.ZodObject<{
|
|
1163
|
+
pipelineId: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
|
|
1164
|
+
opportunityName: z.ZodOptional<z.ZodString>;
|
|
1165
|
+
amount: z.ZodOptional<z.ZodNumber>;
|
|
1166
|
+
currency: z.ZodOptional<z.ZodString>;
|
|
1167
|
+
expectedCloseAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1168
|
+
by: z.ZodOptional<z.ZodString>;
|
|
1200
1169
|
}, z.core.$strip>;
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1170
|
+
type CreateLeadDto = z.infer<typeof createLeadSchema>;
|
|
1171
|
+
type UpdateLeadDto = z.infer<typeof updateLeadSchema>;
|
|
1172
|
+
type ConvertLeadDto = z.infer<typeof convertLeadSchema>;
|
|
1173
|
+
type LeadFilterDto = z.infer<typeof leadFilterSchema>;
|
|
1174
|
+
//#endregion
|
|
1175
|
+
//#region src/validators/opportunity.schema.d.ts
|
|
1176
|
+
declare const openOpportunitySchema: z.ZodObject<{
|
|
1177
|
+
name: z.ZodString;
|
|
1178
|
+
pipelineId: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
|
|
1179
|
+
stageId: z.ZodOptional<z.ZodString>;
|
|
1180
|
+
accountId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1181
|
+
primaryContactId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1182
|
+
sourceLeadId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1183
|
+
amount: z.ZodOptional<z.ZodNumber>;
|
|
1184
|
+
currency: z.ZodOptional<z.ZodString>;
|
|
1185
|
+
probability: z.ZodOptional<z.ZodNumber>;
|
|
1186
|
+
expectedCloseAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1187
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1188
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1189
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1190
|
+
}, z.core.$strip>;
|
|
1191
|
+
declare const moveStageSchema: z.ZodObject<{
|
|
1204
1192
|
stageId: z.ZodString;
|
|
1193
|
+
by: z.ZodOptional<z.ZodString>;
|
|
1194
|
+
note: z.ZodOptional<z.ZodString>;
|
|
1195
|
+
probability: z.ZodOptional<z.ZodNumber>;
|
|
1205
1196
|
}, z.core.$strip>;
|
|
1206
|
-
declare const
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
}, z.core.$strip>;
|
|
1212
|
-
to: z.ZodObject<{
|
|
1213
|
-
stageId: z.ZodString;
|
|
1214
|
-
sequence: z.ZodNumber;
|
|
1215
|
-
}, z.core.$strip>;
|
|
1197
|
+
declare const closeWinSchema: z.ZodObject<{
|
|
1198
|
+
by: z.ZodOptional<z.ZodString>;
|
|
1199
|
+
note: z.ZodOptional<z.ZodString>;
|
|
1200
|
+
closedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1201
|
+
amount: z.ZodOptional<z.ZodNumber>;
|
|
1216
1202
|
}, z.core.$strip>;
|
|
1217
|
-
declare const
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1203
|
+
declare const closeLossSchema: z.ZodObject<{
|
|
1204
|
+
by: z.ZodOptional<z.ZodString>;
|
|
1205
|
+
note: z.ZodOptional<z.ZodString>;
|
|
1206
|
+
closedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1207
|
+
lostReasonId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1208
|
+
}, z.core.$strip>;
|
|
1209
|
+
declare const opportunityFilterSchema: z.ZodObject<{
|
|
1210
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
1211
|
+
open: "open";
|
|
1212
|
+
won: "won";
|
|
1213
|
+
lost: "lost";
|
|
1214
|
+
abandoned: "abandoned";
|
|
1215
|
+
}>>;
|
|
1216
|
+
pipelineId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1217
|
+
stageId: z.ZodOptional<z.ZodString>;
|
|
1218
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1219
|
+
accountId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1220
|
+
expectedCloseFrom: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1221
|
+
expectedCloseTo: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1222
|
+
}, z.core.$strip>;
|
|
1223
|
+
type OpenOpportunityDto = z.infer<typeof openOpportunitySchema>;
|
|
1224
|
+
type MoveStageDto = z.infer<typeof moveStageSchema>;
|
|
1225
|
+
type CloseWinDto = z.infer<typeof closeWinSchema>;
|
|
1226
|
+
type CloseLossDto = z.infer<typeof closeLossSchema>;
|
|
1227
|
+
type OpportunityFilterDto = z.infer<typeof opportunityFilterSchema>;
|
|
1228
|
+
//#endregion
|
|
1229
|
+
//#region src/validators/contact.schema.d.ts
|
|
1230
|
+
declare const createContactSchema: z.ZodObject<{
|
|
1231
|
+
name: z.ZodObject<{
|
|
1232
|
+
given: z.ZodString;
|
|
1233
|
+
family: z.ZodDefault<z.ZodString>;
|
|
1234
|
+
middle: z.ZodOptional<z.ZodString>;
|
|
1235
|
+
prefix: z.ZodOptional<z.ZodString>;
|
|
1236
|
+
suffix: z.ZodOptional<z.ZodString>;
|
|
1237
|
+
preferred: z.ZodOptional<z.ZodString>;
|
|
1226
1238
|
}, z.core.$strip>;
|
|
1239
|
+
contact: z.ZodDefault<z.ZodObject<{
|
|
1240
|
+
email: z.ZodOptional<z.ZodString>;
|
|
1241
|
+
personalEmail: z.ZodOptional<z.ZodString>;
|
|
1242
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
1243
|
+
alternatePhone: z.ZodOptional<z.ZodString>;
|
|
1244
|
+
}, z.core.$strip>>;
|
|
1245
|
+
jobTitle: z.ZodOptional<z.ZodString>;
|
|
1246
|
+
accountId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1247
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1248
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1249
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1227
1250
|
}, z.core.$strip>;
|
|
1228
|
-
declare const
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1251
|
+
declare const updateContactSchema: z.ZodObject<{
|
|
1252
|
+
name: z.ZodOptional<z.ZodObject<{
|
|
1253
|
+
given: z.ZodString;
|
|
1254
|
+
family: z.ZodDefault<z.ZodString>;
|
|
1255
|
+
middle: z.ZodOptional<z.ZodString>;
|
|
1256
|
+
prefix: z.ZodOptional<z.ZodString>;
|
|
1257
|
+
suffix: z.ZodOptional<z.ZodString>;
|
|
1258
|
+
preferred: z.ZodOptional<z.ZodString>;
|
|
1233
1259
|
}, z.core.$strip>>;
|
|
1260
|
+
contact: z.ZodOptional<z.ZodDefault<z.ZodObject<{
|
|
1261
|
+
email: z.ZodOptional<z.ZodString>;
|
|
1262
|
+
personalEmail: z.ZodOptional<z.ZodString>;
|
|
1263
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
1264
|
+
alternatePhone: z.ZodOptional<z.ZodString>;
|
|
1265
|
+
}, z.core.$strip>>>;
|
|
1266
|
+
jobTitle: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1267
|
+
accountId: z.ZodOptional<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>>;
|
|
1268
|
+
ownerId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1269
|
+
tags: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
1270
|
+
metadata: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1271
|
+
}, z.core.$strip>;
|
|
1272
|
+
declare const contactFilterSchema: z.ZodObject<{
|
|
1273
|
+
accountId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1274
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1275
|
+
email: z.ZodOptional<z.ZodString>;
|
|
1276
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1277
|
+
}, z.core.$strip>;
|
|
1278
|
+
type CreateContactDto = z.infer<typeof createContactSchema>;
|
|
1279
|
+
type UpdateContactDto = z.infer<typeof updateContactSchema>;
|
|
1280
|
+
//#endregion
|
|
1281
|
+
//#region src/validators/account.schema.d.ts
|
|
1282
|
+
declare const createAccountSchema: z.ZodObject<{
|
|
1283
|
+
name: z.ZodString;
|
|
1284
|
+
domain: z.ZodOptional<z.ZodString>;
|
|
1285
|
+
industry: z.ZodOptional<z.ZodString>;
|
|
1286
|
+
sizeBucket: z.ZodOptional<z.ZodString>;
|
|
1287
|
+
annualRevenueAmount: z.ZodOptional<z.ZodNumber>;
|
|
1288
|
+
annualRevenueCurrency: z.ZodOptional<z.ZodString>;
|
|
1289
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1290
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1291
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1292
|
+
}, z.core.$strip>;
|
|
1293
|
+
declare const updateAccountSchema: z.ZodObject<{
|
|
1294
|
+
name: z.ZodOptional<z.ZodString>;
|
|
1295
|
+
domain: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1296
|
+
industry: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1297
|
+
sizeBucket: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1298
|
+
annualRevenueAmount: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
|
|
1299
|
+
annualRevenueCurrency: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1300
|
+
ownerId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1301
|
+
tags: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
1302
|
+
metadata: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1303
|
+
}, z.core.$strip>;
|
|
1304
|
+
declare const accountFilterSchema: z.ZodObject<{
|
|
1305
|
+
domain: z.ZodOptional<z.ZodString>;
|
|
1306
|
+
industry: z.ZodOptional<z.ZodString>;
|
|
1307
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1308
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1309
|
+
}, z.core.$strip>;
|
|
1310
|
+
type CreateAccountDto = z.infer<typeof createAccountSchema>;
|
|
1311
|
+
type UpdateAccountDto = z.infer<typeof updateAccountSchema>;
|
|
1312
|
+
//#endregion
|
|
1313
|
+
//#region src/validators/campaign.schema.d.ts
|
|
1314
|
+
declare const createCampaignSchema: z.ZodObject<{
|
|
1315
|
+
name: z.ZodString;
|
|
1316
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1317
|
+
utmSource: z.ZodOptional<z.ZodString>;
|
|
1318
|
+
utmMedium: z.ZodOptional<z.ZodString>;
|
|
1319
|
+
utmCampaign: z.ZodOptional<z.ZodString>;
|
|
1320
|
+
startDate: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1321
|
+
endDate: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1322
|
+
budgetAmount: z.ZodOptional<z.ZodNumber>;
|
|
1323
|
+
expectedRevenueAmount: z.ZodOptional<z.ZodNumber>;
|
|
1324
|
+
currency: z.ZodOptional<z.ZodString>;
|
|
1325
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1326
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1327
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1328
|
+
}, z.core.$strip>;
|
|
1329
|
+
declare const updateCampaignSchema: z.ZodObject<{
|
|
1330
|
+
name: z.ZodOptional<z.ZodString>;
|
|
1331
|
+
description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1332
|
+
utmSource: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1333
|
+
utmMedium: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1334
|
+
utmCampaign: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1335
|
+
startDate: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
1336
|
+
endDate: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
1337
|
+
budgetAmount: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
|
|
1338
|
+
expectedRevenueAmount: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
|
|
1339
|
+
currency: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1340
|
+
ownerId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1341
|
+
tags: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
1342
|
+
metadata: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1343
|
+
}, z.core.$strip>;
|
|
1344
|
+
declare const completeCampaignSchema: z.ZodObject<{
|
|
1345
|
+
by: z.ZodOptional<z.ZodString>;
|
|
1346
|
+
note: z.ZodOptional<z.ZodString>;
|
|
1347
|
+
actualRevenueAmount: z.ZodOptional<z.ZodNumber>;
|
|
1348
|
+
}, z.core.$strip>;
|
|
1349
|
+
declare const campaignFilterSchema: z.ZodObject<{
|
|
1350
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
1351
|
+
draft: "draft";
|
|
1352
|
+
active: "active";
|
|
1353
|
+
paused: "paused";
|
|
1354
|
+
completed: "completed";
|
|
1355
|
+
archived: "archived";
|
|
1356
|
+
}>>;
|
|
1357
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1358
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1359
|
+
startDateFrom: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1360
|
+
startDateTo: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1234
1361
|
}, z.core.$strip>;
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1362
|
+
type CreateCampaignDto = z.infer<typeof createCampaignSchema>;
|
|
1363
|
+
type UpdateCampaignDto = z.infer<typeof updateCampaignSchema>;
|
|
1364
|
+
type CompleteCampaignDto = z.infer<typeof completeCampaignSchema>;
|
|
1365
|
+
//#endregion
|
|
1366
|
+
//#region src/validators/subscription.schema.d.ts
|
|
1367
|
+
declare const subscribeSchema: z.ZodObject<{
|
|
1368
|
+
contactId: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
|
|
1369
|
+
campaignId: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
|
|
1370
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1371
|
+
consentIpAddress: z.ZodOptional<z.ZodString>;
|
|
1372
|
+
consentUserAgent: z.ZodOptional<z.ZodString>;
|
|
1373
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1374
|
+
requireDoubleOptIn: z.ZodOptional<z.ZodBoolean>;
|
|
1238
1375
|
}, z.core.$strip>;
|
|
1239
|
-
declare const
|
|
1240
|
-
|
|
1376
|
+
declare const confirmSubscriptionSchema: z.ZodObject<{
|
|
1377
|
+
token: z.ZodString;
|
|
1241
1378
|
}, z.core.$strip>;
|
|
1242
|
-
declare const
|
|
1243
|
-
|
|
1379
|
+
declare const unsubscribeSchema: z.ZodObject<{
|
|
1380
|
+
token: z.ZodString;
|
|
1381
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
1244
1382
|
}, z.core.$strip>;
|
|
1245
|
-
declare const
|
|
1246
|
-
|
|
1383
|
+
declare const subscriptionFilterSchema: z.ZodObject<{
|
|
1384
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
1385
|
+
pending: "pending";
|
|
1386
|
+
confirmed: "confirmed";
|
|
1387
|
+
unsubscribed: "unsubscribed";
|
|
1388
|
+
bounced: "bounced";
|
|
1389
|
+
complained: "complained";
|
|
1390
|
+
}>>;
|
|
1391
|
+
contactId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1392
|
+
campaignId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1247
1393
|
}, z.core.$strip>;
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1394
|
+
type SubscribeDto = z.infer<typeof subscribeSchema>;
|
|
1395
|
+
type ConfirmSubscriptionDto = z.infer<typeof confirmSubscriptionSchema>;
|
|
1396
|
+
type UnsubscribeDto = z.infer<typeof unsubscribeSchema>;
|
|
1397
|
+
//#endregion
|
|
1398
|
+
//#region src/validators/activity.schema.d.ts
|
|
1399
|
+
declare const planActivitySchema: z.ZodObject<{
|
|
1400
|
+
type: z.ZodEnum<{
|
|
1401
|
+
call: "call";
|
|
1402
|
+
email: "email";
|
|
1403
|
+
meeting: "meeting";
|
|
1404
|
+
task: "task";
|
|
1405
|
+
note: "note";
|
|
1406
|
+
sms: "sms";
|
|
1407
|
+
social: "social";
|
|
1408
|
+
demo: "demo";
|
|
1409
|
+
other: "other";
|
|
1410
|
+
}>;
|
|
1251
1411
|
subjectKind: z.ZodEnum<{
|
|
1252
1412
|
lead: "lead";
|
|
1253
1413
|
opportunity: "opportunity";
|
|
1254
1414
|
contact: "contact";
|
|
1255
1415
|
account: "account";
|
|
1256
1416
|
}>;
|
|
1257
|
-
subjectId: z.ZodString
|
|
1417
|
+
subjectId: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
|
|
1418
|
+
title: z.ZodString;
|
|
1419
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1420
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1421
|
+
participantIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1422
|
+
dueDate: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1423
|
+
externalRef: z.ZodOptional<z.ZodString>;
|
|
1424
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1258
1425
|
}, z.core.$strip>;
|
|
1259
|
-
declare const
|
|
1260
|
-
|
|
1261
|
-
|
|
1426
|
+
declare const updateActivitySchema: z.ZodObject<{
|
|
1427
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
1428
|
+
call: "call";
|
|
1429
|
+
email: "email";
|
|
1430
|
+
meeting: "meeting";
|
|
1431
|
+
task: "task";
|
|
1432
|
+
note: "note";
|
|
1433
|
+
sms: "sms";
|
|
1434
|
+
social: "social";
|
|
1435
|
+
demo: "demo";
|
|
1436
|
+
other: "other";
|
|
1437
|
+
}>>;
|
|
1438
|
+
subjectKind: z.ZodOptional<z.ZodEnum<{
|
|
1439
|
+
lead: "lead";
|
|
1440
|
+
opportunity: "opportunity";
|
|
1441
|
+
contact: "contact";
|
|
1442
|
+
account: "account";
|
|
1443
|
+
}>>;
|
|
1444
|
+
subjectId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1445
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1446
|
+
description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1447
|
+
ownerId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1448
|
+
participantIds: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
1449
|
+
dueDate: z.ZodOptional<z.ZodOptional<z.ZodCoercedDate<unknown>>>;
|
|
1450
|
+
externalRef: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1451
|
+
metadata: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1262
1452
|
}, z.core.$strip>;
|
|
1263
|
-
declare const
|
|
1264
|
-
activityId: z.ZodString;
|
|
1453
|
+
declare const cancelActivitySchema: z.ZodObject<{
|
|
1265
1454
|
reason: z.ZodOptional<z.ZodString>;
|
|
1266
1455
|
}, z.core.$strip>;
|
|
1267
|
-
declare const
|
|
1268
|
-
|
|
1269
|
-
|
|
1456
|
+
declare const activityFilterSchema: z.ZodObject<{
|
|
1457
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
1458
|
+
call: "call";
|
|
1459
|
+
email: "email";
|
|
1460
|
+
meeting: "meeting";
|
|
1461
|
+
task: "task";
|
|
1462
|
+
note: "note";
|
|
1463
|
+
sms: "sms";
|
|
1464
|
+
social: "social";
|
|
1465
|
+
demo: "demo";
|
|
1466
|
+
other: "other";
|
|
1467
|
+
}>>;
|
|
1468
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
1469
|
+
completed: "completed";
|
|
1470
|
+
planned: "planned";
|
|
1471
|
+
in_progress: "in_progress";
|
|
1472
|
+
cancelled: "cancelled";
|
|
1473
|
+
}>>;
|
|
1474
|
+
subjectKind: z.ZodOptional<z.ZodEnum<{
|
|
1270
1475
|
lead: "lead";
|
|
1271
1476
|
opportunity: "opportunity";
|
|
1272
1477
|
contact: "contact";
|
|
1273
1478
|
account: "account";
|
|
1274
|
-
}
|
|
1275
|
-
subjectId: z.ZodString
|
|
1479
|
+
}>>;
|
|
1480
|
+
subjectId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1481
|
+
ownerId: z.ZodOptional<z.ZodString>;
|
|
1482
|
+
dueDateFrom: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1483
|
+
dueDateTo: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
1276
1484
|
}, z.core.$strip>;
|
|
1277
|
-
type
|
|
1278
|
-
type
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
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;
|
|
1485
|
+
type PlanActivityDto = z.infer<typeof planActivitySchema>;
|
|
1486
|
+
type CancelActivityDto = z.infer<typeof cancelActivitySchema>;
|
|
1487
|
+
//#endregion
|
|
1488
|
+
//#region src/validators/note.schema.d.ts
|
|
1489
|
+
declare const addNoteSchema: z.ZodObject<{
|
|
1385
1490
|
subjectKind: z.ZodEnum<{
|
|
1386
1491
|
lead: "lead";
|
|
1387
1492
|
opportunity: "opportunity";
|
|
1388
1493
|
contact: "contact";
|
|
1389
1494
|
account: "account";
|
|
1390
1495
|
}>;
|
|
1391
|
-
subjectId: z.ZodString
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
}, z.core.$strip
|
|
1397
|
-
declare const
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
subjectKind: z.ZodEnum<{
|
|
1496
|
+
subjectId: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
|
|
1497
|
+
body: z.ZodString;
|
|
1498
|
+
authorId: z.ZodOptional<z.ZodString>;
|
|
1499
|
+
pinned: z.ZodOptional<z.ZodBoolean>;
|
|
1500
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1501
|
+
}, z.core.$strip>;
|
|
1502
|
+
declare const updateNoteSchema: z.ZodObject<{
|
|
1503
|
+
body: z.ZodOptional<z.ZodString>;
|
|
1504
|
+
pinned: z.ZodOptional<z.ZodBoolean>;
|
|
1505
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1506
|
+
}, z.core.$strip>;
|
|
1507
|
+
declare const noteFilterSchema: z.ZodObject<{
|
|
1508
|
+
subjectKind: z.ZodOptional<z.ZodEnum<{
|
|
1404
1509
|
lead: "lead";
|
|
1405
1510
|
opportunity: "opportunity";
|
|
1406
1511
|
contact: "contact";
|
|
1407
1512
|
account: "account";
|
|
1513
|
+
}>>;
|
|
1514
|
+
subjectId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1515
|
+
authorId: z.ZodOptional<z.ZodString>;
|
|
1516
|
+
pinned: z.ZodOptional<z.ZodCoercedBoolean<unknown>>;
|
|
1517
|
+
}, z.core.$strip>;
|
|
1518
|
+
type AddNoteDto = z.infer<typeof addNoteSchema>;
|
|
1519
|
+
type UpdateNoteDto = z.infer<typeof updateNoteSchema>;
|
|
1520
|
+
//#endregion
|
|
1521
|
+
//#region src/validators/loss-reason.schema.d.ts
|
|
1522
|
+
declare const createLossReasonSchema: z.ZodObject<{
|
|
1523
|
+
name: z.ZodString;
|
|
1524
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1525
|
+
isActive: z.ZodOptional<z.ZodBoolean>;
|
|
1526
|
+
sequence: z.ZodOptional<z.ZodNumber>;
|
|
1527
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1528
|
+
}, z.core.$strip>;
|
|
1529
|
+
declare const updateLossReasonSchema: z.ZodObject<{
|
|
1530
|
+
name: z.ZodOptional<z.ZodString>;
|
|
1531
|
+
description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
1532
|
+
isActive: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
|
|
1533
|
+
sequence: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
|
|
1534
|
+
metadata: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1535
|
+
}, z.core.$strip>;
|
|
1536
|
+
declare const lossReasonFilterSchema: z.ZodObject<{
|
|
1537
|
+
isActive: z.ZodOptional<z.ZodCoercedBoolean<unknown>>;
|
|
1538
|
+
}, z.core.$strip>;
|
|
1539
|
+
type CreateLossReasonDto = z.infer<typeof createLossReasonSchema>;
|
|
1540
|
+
type UpdateLossReasonDto = z.infer<typeof updateLossReasonSchema>;
|
|
1541
|
+
//#endregion
|
|
1542
|
+
//#region src/validators/email-event.schema.d.ts
|
|
1543
|
+
declare const recordEmailEventSchema: z.ZodObject<{
|
|
1544
|
+
subjectKind: z.ZodEnum<{
|
|
1545
|
+
contact: "contact";
|
|
1546
|
+
subscription: "subscription";
|
|
1408
1547
|
}>;
|
|
1409
|
-
subjectId: z.ZodString
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
declare const
|
|
1548
|
+
subjectId: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
|
|
1549
|
+
campaignId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1550
|
+
messageId: z.ZodOptional<z.ZodString>;
|
|
1551
|
+
url: z.ZodOptional<z.ZodString>;
|
|
1552
|
+
userAgent: z.ZodOptional<z.ZodString>;
|
|
1553
|
+
ip: z.ZodOptional<z.ZodString>;
|
|
1554
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1555
|
+
}, z.core.$strip>;
|
|
1556
|
+
declare const emailEventFilterSchema: z.ZodObject<{
|
|
1557
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
1558
|
+
open: "open";
|
|
1559
|
+
click: "click";
|
|
1560
|
+
bounce: "bounce";
|
|
1561
|
+
complaint: "complaint";
|
|
1562
|
+
unsubscribe: "unsubscribe";
|
|
1563
|
+
}>>;
|
|
1564
|
+
subjectKind: z.ZodOptional<z.ZodEnum<{
|
|
1565
|
+
contact: "contact";
|
|
1566
|
+
subscription: "subscription";
|
|
1567
|
+
}>>;
|
|
1568
|
+
subjectId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1569
|
+
campaignId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
|
|
1570
|
+
messageId: z.ZodOptional<z.ZodString>;
|
|
1571
|
+
}, z.core.$strip>;
|
|
1572
|
+
type RecordEmailEventDto = z.infer<typeof recordEmailEventSchema>;
|
|
1418
1573
|
//#endregion
|
|
1419
|
-
export { ACTIVITY_STATUSES, ACTIVITY_TRANSITIONS, ACTIVITY_TYPES,
|
|
1574
|
+
export { ACTIVITY_MACHINE, ACTIVITY_STATUSES, ACTIVITY_TRANSITIONS, ACTIVITY_TYPES, AccountRepository, AccountRepositoryDeps, ActivityRepository, ActivityRepositoryDeps, type ActivityStatus, type ActivityType, CAMPAIGN_MACHINE, CAMPAIGN_STATUSES, CAMPAIGN_TRANSITIONS, CRM_EVENTS, CampaignRepository, CampaignRepositoryDeps, type CampaignStatus, CloseInput, ContactRepository, ContactRepositoryDeps, ConversionRow, ConvertLeadInput, ConvertResult, CreateCrmRepositoriesDeps, CrmConfig, CrmContext, CrmEngine, CrmError, CrmEventName, CrmLogger, CrmModels, CrmRepositories, DuplicateCampaignError, DuplicateLeadError, DuplicateSubscriptionError, EMAIL_EVENT_KINDS, EMAIL_EVENT_SUBJECT_KINDS, type EmailEventKind, EmailEventRepository, EmailEventRepositoryDeps, EmailEventSubjectKind, EmptyPipelineError, ForecastOptions, ForecastRow, type IAccountDocument, type IActivityDocument, type ICampaignDocument, ICampaignStatusEntry, type IContactDocument, IContactInfoEmbedded, IContactName, type IEmailEventDocument, type ILeadDocument, ILeadStatusEntry, type ILossReasonDocument, type INoteDocument, type IOpportunityDocument, IOpportunityStatusEntry, type IPipelineDocument, IStageDocument, type ISubscriptionDocument, ISubscriptionStatusEntry, InProcessCrmBus, InvalidActivityTransitionError, InvalidCampaignTransitionError, InvalidConfirmationTokenError, InvalidLeadTransitionError, InvalidOpportunityTransitionError, InvalidSubscriptionTransitionError, InvalidUnsubscribeTokenError, LEAD_MACHINE, LEAD_STATUSES, LEAD_TRANSITIONS, LeadAlreadyConvertedError, LeadInput, LeadRepository, LeadRepositoryDeps, LeadScorer, LeadService, LeadServiceDeps, type LeadStatus, LossReasonRepository, LossReasonRepositoryDeps, MoveStageInput, NotFoundError, NoteRepository, NoteRepositoryDeps, OPPORTUNITY_MACHINE, OPPORTUNITY_STATUSES, OPPORTUNITY_TRANSITIONS, OpenOpportunityInput, OpportunityForecast, OpportunityRepository, OpportunityRepositoryDeps, type OpportunityStatus, PipelineRepository, PipelineRepositoryDeps, RecordEmailEventInput, ResolvedCrmConfig, SUBJECT_KINDS, SUBSCRIPTION_MACHINE, SUBSCRIPTION_STATUSES, SUBSCRIPTION_TRANSITIONS, SchemaBuildConfig, StageNotInPipelineError, type StatusChangeEntry, type StatusHistory, type SubjectKind, SubscribeInput, SubscriptionRepository, SubscriptionRepositoryDeps, type SubscriptionStatus, TenantFieldType, _ModelTypes, appendStatus, buildAccountSchema, buildActivitySchema, buildCampaignSchema, buildContactSchema, buildEmailEventSchema, buildLeadSchema, buildLossReasonSchema, buildNoteSchema, buildOpportunitySchema, buildPipelineSchema, buildSubscriptionSchema, canTransitionActivity, canTransitionCampaign, canTransitionLead, canTransitionOpportunity, canTransitionSubscription, composeScorers, createAccountModel, createActivityModel, createCampaignModel, createContactModel, createCrm, createCrmModels, createCrmRepositories, createEmailEventModel, createEvent, createLeadModel, createLossReasonModel, createNoteModel, createOpportunityModel, createPipelineModel, createSubscriptionModel, defaultLeadScorer, forecast, lastTransitionTo, latestEntry, pipelineConversion, tenantFieldDef, timeInStatus, index_d_exports as validators };
|
|
1420
1575
|
//# sourceMappingURL=index.d.ts.map
|