@happyvertical/smrt-sales 0.39.2

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.
Files changed (201) hide show
  1. package/AGENTS.md +87 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/__smrt-register__.d.ts +2 -0
  6. package/dist/__smrt-register__.d.ts.map +1 -0
  7. package/dist/chunks/__smrt-register__-kWdT7LOt.js +6 -0
  8. package/dist/chunks/__smrt-register__-kWdT7LOt.js.map +1 -0
  9. package/dist/chunks/commissions-BCxqOKVM.js +2181 -0
  10. package/dist/chunks/commissions-BCxqOKVM.js.map +1 -0
  11. package/dist/chunks/crm-DwEz7E2r.js +1428 -0
  12. package/dist/chunks/crm-DwEz7E2r.js.map +1 -0
  13. package/dist/chunks/referrals-BY47p70T.js +2880 -0
  14. package/dist/chunks/referrals-BY47p70T.js.map +1 -0
  15. package/dist/commissions/collections/CommissionAdjustmentCollection.d.ts +26 -0
  16. package/dist/commissions/collections/CommissionAdjustmentCollection.d.ts.map +1 -0
  17. package/dist/commissions/collections/CommissionCollection.d.ts +43 -0
  18. package/dist/commissions/collections/CommissionCollection.d.ts.map +1 -0
  19. package/dist/commissions/collections/CommissionPayoutCollection.d.ts +19 -0
  20. package/dist/commissions/collections/CommissionPayoutCollection.d.ts.map +1 -0
  21. package/dist/commissions/collections/CommissionPlanCollection.d.ts +46 -0
  22. package/dist/commissions/collections/CommissionPlanCollection.d.ts.map +1 -0
  23. package/dist/commissions/collections/EarnerCollection.d.ts +14 -0
  24. package/dist/commissions/collections/EarnerCollection.d.ts.map +1 -0
  25. package/dist/commissions/collections/EarningEventCollection.d.ts +27 -0
  26. package/dist/commissions/collections/EarningEventCollection.d.ts.map +1 -0
  27. package/dist/commissions/collections/index.d.ts +11 -0
  28. package/dist/commissions/collections/index.d.ts.map +1 -0
  29. package/dist/commissions/index.d.ts +20 -0
  30. package/dist/commissions/index.d.ts.map +1 -0
  31. package/dist/commissions/models/Commission.d.ts +150 -0
  32. package/dist/commissions/models/Commission.d.ts.map +1 -0
  33. package/dist/commissions/models/CommissionAdjustment.d.ts +62 -0
  34. package/dist/commissions/models/CommissionAdjustment.d.ts.map +1 -0
  35. package/dist/commissions/models/CommissionPayout.d.ts +119 -0
  36. package/dist/commissions/models/CommissionPayout.d.ts.map +1 -0
  37. package/dist/commissions/models/CommissionPlan.d.ts +117 -0
  38. package/dist/commissions/models/CommissionPlan.d.ts.map +1 -0
  39. package/dist/commissions/models/Earner.d.ts +49 -0
  40. package/dist/commissions/models/Earner.d.ts.map +1 -0
  41. package/dist/commissions/models/EarningEvent.d.ts +89 -0
  42. package/dist/commissions/models/EarningEvent.d.ts.map +1 -0
  43. package/dist/commissions/models/index.d.ts +11 -0
  44. package/dist/commissions/models/index.d.ts.map +1 -0
  45. package/dist/commissions/money.d.ts +42 -0
  46. package/dist/commissions/money.d.ts.map +1 -0
  47. package/dist/commissions/services/CommissionBalanceService.d.ts +14 -0
  48. package/dist/commissions/services/CommissionBalanceService.d.ts.map +1 -0
  49. package/dist/commissions/services/CommissionCalculationService.d.ts +142 -0
  50. package/dist/commissions/services/CommissionCalculationService.d.ts.map +1 -0
  51. package/dist/commissions/services/CommissionPayoutService.d.ts +134 -0
  52. package/dist/commissions/services/CommissionPayoutService.d.ts.map +1 -0
  53. package/dist/commissions/services/CommissionSettlementService.d.ts +42 -0
  54. package/dist/commissions/services/CommissionSettlementService.d.ts.map +1 -0
  55. package/dist/commissions/services/index.d.ts +9 -0
  56. package/dist/commissions/services/index.d.ts.map +1 -0
  57. package/dist/commissions/types.d.ts +243 -0
  58. package/dist/commissions/types.d.ts.map +1 -0
  59. package/dist/commissions.d.ts +2 -0
  60. package/dist/commissions.d.ts.map +1 -0
  61. package/dist/commissions.js +3 -0
  62. package/dist/crm/collections/LeadCollection.d.ts +79 -0
  63. package/dist/crm/collections/LeadCollection.d.ts.map +1 -0
  64. package/dist/crm/collections/OpportunityCollection.d.ts +42 -0
  65. package/dist/crm/collections/OpportunityCollection.d.ts.map +1 -0
  66. package/dist/crm/collections/OpportunityConversionCollection.d.ts +26 -0
  67. package/dist/crm/collections/OpportunityConversionCollection.d.ts.map +1 -0
  68. package/dist/crm/collections/PipelineDefinitionCollection.d.ts +46 -0
  69. package/dist/crm/collections/PipelineDefinitionCollection.d.ts.map +1 -0
  70. package/dist/crm/collections/PipelineStageCollection.d.ts +22 -0
  71. package/dist/crm/collections/PipelineStageCollection.d.ts.map +1 -0
  72. package/dist/crm/collections/SalesActivityCollection.d.ts +24 -0
  73. package/dist/crm/collections/SalesActivityCollection.d.ts.map +1 -0
  74. package/dist/crm/collections/SalesRepresentativeCollection.d.ts +19 -0
  75. package/dist/crm/collections/SalesRepresentativeCollection.d.ts.map +1 -0
  76. package/dist/crm/index.d.ts +27 -0
  77. package/dist/crm/index.d.ts.map +1 -0
  78. package/dist/crm/models/Lead.d.ts +135 -0
  79. package/dist/crm/models/Lead.d.ts.map +1 -0
  80. package/dist/crm/models/Opportunity.d.ts +111 -0
  81. package/dist/crm/models/Opportunity.d.ts.map +1 -0
  82. package/dist/crm/models/OpportunityConversion.d.ts +66 -0
  83. package/dist/crm/models/OpportunityConversion.d.ts.map +1 -0
  84. package/dist/crm/models/PipelineDefinition.d.ts +58 -0
  85. package/dist/crm/models/PipelineDefinition.d.ts.map +1 -0
  86. package/dist/crm/models/PipelineStage.d.ts +66 -0
  87. package/dist/crm/models/PipelineStage.d.ts.map +1 -0
  88. package/dist/crm/models/SalesActivity.d.ts +76 -0
  89. package/dist/crm/models/SalesActivity.d.ts.map +1 -0
  90. package/dist/crm/models/SalesRepresentative.d.ts +60 -0
  91. package/dist/crm/models/SalesRepresentative.d.ts.map +1 -0
  92. package/dist/crm/types.d.ts +228 -0
  93. package/dist/crm/types.d.ts.map +1 -0
  94. package/dist/crm.d.ts +2 -0
  95. package/dist/crm.d.ts.map +1 -0
  96. package/dist/crm.js +3 -0
  97. package/dist/index.d.ts +4 -0
  98. package/dist/index.d.ts.map +1 -0
  99. package/dist/index.js +5 -0
  100. package/dist/manifest.json +9340 -0
  101. package/dist/referrals/collections/AttributionExceptionCollection.d.ts +17 -0
  102. package/dist/referrals/collections/AttributionExceptionCollection.d.ts.map +1 -0
  103. package/dist/referrals/collections/AttributionPolicyCollection.d.ts +50 -0
  104. package/dist/referrals/collections/AttributionPolicyCollection.d.ts.map +1 -0
  105. package/dist/referrals/collections/ReferralAgreementCollection.d.ts +48 -0
  106. package/dist/referrals/collections/ReferralAgreementCollection.d.ts.map +1 -0
  107. package/dist/referrals/collections/ReferralCollection.d.ts +25 -0
  108. package/dist/referrals/collections/ReferralCollection.d.ts.map +1 -0
  109. package/dist/referrals/collections/ReferralLinkCollection.d.ts +96 -0
  110. package/dist/referrals/collections/ReferralLinkCollection.d.ts.map +1 -0
  111. package/dist/referrals/collections/ReferralProgramCollection.d.ts +18 -0
  112. package/dist/referrals/collections/ReferralProgramCollection.d.ts.map +1 -0
  113. package/dist/referrals/collections/ReferralTermSnapshotCollection.d.ts +13 -0
  114. package/dist/referrals/collections/ReferralTermSnapshotCollection.d.ts.map +1 -0
  115. package/dist/referrals/collections/ReferralTouchCollection.d.ts +30 -0
  116. package/dist/referrals/collections/ReferralTouchCollection.d.ts.map +1 -0
  117. package/dist/referrals/collections/ReferrerCollection.d.ts +17 -0
  118. package/dist/referrals/collections/ReferrerCollection.d.ts.map +1 -0
  119. package/dist/referrals/index.d.ts +38 -0
  120. package/dist/referrals/index.d.ts.map +1 -0
  121. package/dist/referrals/models/AttributionException.d.ts +85 -0
  122. package/dist/referrals/models/AttributionException.d.ts.map +1 -0
  123. package/dist/referrals/models/AttributionPolicy.d.ts +128 -0
  124. package/dist/referrals/models/AttributionPolicy.d.ts.map +1 -0
  125. package/dist/referrals/models/Referral.d.ts +112 -0
  126. package/dist/referrals/models/Referral.d.ts.map +1 -0
  127. package/dist/referrals/models/ReferralAgreement.d.ts +125 -0
  128. package/dist/referrals/models/ReferralAgreement.d.ts.map +1 -0
  129. package/dist/referrals/models/ReferralLink.d.ts +71 -0
  130. package/dist/referrals/models/ReferralLink.d.ts.map +1 -0
  131. package/dist/referrals/models/ReferralProgram.d.ts +57 -0
  132. package/dist/referrals/models/ReferralProgram.d.ts.map +1 -0
  133. package/dist/referrals/models/ReferralTermSnapshot.d.ts +61 -0
  134. package/dist/referrals/models/ReferralTermSnapshot.d.ts.map +1 -0
  135. package/dist/referrals/models/ReferralTouch.d.ts +55 -0
  136. package/dist/referrals/models/ReferralTouch.d.ts.map +1 -0
  137. package/dist/referrals/models/Referrer.d.ts +69 -0
  138. package/dist/referrals/models/Referrer.d.ts.map +1 -0
  139. package/dist/referrals/services/AttributionService.d.ts +248 -0
  140. package/dist/referrals/services/AttributionService.d.ts.map +1 -0
  141. package/dist/referrals/services/ReferralCommissionService.d.ts +91 -0
  142. package/dist/referrals/services/ReferralCommissionService.d.ts.map +1 -0
  143. package/dist/referrals/services/ReferralQualificationService.d.ts +135 -0
  144. package/dist/referrals/services/ReferralQualificationService.d.ts.map +1 -0
  145. package/dist/referrals/types.d.ts +226 -0
  146. package/dist/referrals/types.d.ts.map +1 -0
  147. package/dist/referrals.d.ts +2 -0
  148. package/dist/referrals.d.ts.map +1 -0
  149. package/dist/referrals.js +3 -0
  150. package/dist/smrt-knowledge.json +5501 -0
  151. package/dist/svelte/__tests__/format.test.js +68 -0
  152. package/dist/svelte/__tests__/types.test.js +349 -0
  153. package/dist/svelte/components/AttributionConflictQueue.svelte +361 -0
  154. package/dist/svelte/components/AttributionConflictQueue.svelte.d.ts +15 -0
  155. package/dist/svelte/components/AttributionConflictQueue.svelte.d.ts.map +1 -0
  156. package/dist/svelte/components/CommissionBreakdown.svelte +251 -0
  157. package/dist/svelte/components/CommissionBreakdown.svelte.d.ts +11 -0
  158. package/dist/svelte/components/CommissionBreakdown.svelte.d.ts.map +1 -0
  159. package/dist/svelte/components/CommissionExpenseSummary.svelte +186 -0
  160. package/dist/svelte/components/CommissionExpenseSummary.svelte.d.ts +13 -0
  161. package/dist/svelte/components/CommissionExpenseSummary.svelte.d.ts.map +1 -0
  162. package/dist/svelte/components/ExecutedAgreementsList.svelte +136 -0
  163. package/dist/svelte/components/ExecutedAgreementsList.svelte.d.ts +11 -0
  164. package/dist/svelte/components/ExecutedAgreementsList.svelte.d.ts.map +1 -0
  165. package/dist/svelte/components/LeadList.svelte +224 -0
  166. package/dist/svelte/components/LeadList.svelte.d.ts +19 -0
  167. package/dist/svelte/components/LeadList.svelte.d.ts.map +1 -0
  168. package/dist/svelte/components/OpportunityBoard.svelte +230 -0
  169. package/dist/svelte/components/OpportunityBoard.svelte.d.ts +17 -0
  170. package/dist/svelte/components/OpportunityBoard.svelte.d.ts.map +1 -0
  171. package/dist/svelte/components/OpportunityDetail.svelte +472 -0
  172. package/dist/svelte/components/OpportunityDetail.svelte.d.ts +27 -0
  173. package/dist/svelte/components/OpportunityDetail.svelte.d.ts.map +1 -0
  174. package/dist/svelte/components/PayoutBatchReview.svelte +285 -0
  175. package/dist/svelte/components/PayoutBatchReview.svelte.d.ts +21 -0
  176. package/dist/svelte/components/PayoutBatchReview.svelte.d.ts.map +1 -0
  177. package/dist/svelte/components/PayoutHistoryList.svelte +245 -0
  178. package/dist/svelte/components/PayoutHistoryList.svelte.d.ts +11 -0
  179. package/dist/svelte/components/PayoutHistoryList.svelte.d.ts.map +1 -0
  180. package/dist/svelte/components/ReferralLinkManager.svelte +216 -0
  181. package/dist/svelte/components/ReferralLinkManager.svelte.d.ts +17 -0
  182. package/dist/svelte/components/ReferralLinkManager.svelte.d.ts.map +1 -0
  183. package/dist/svelte/components/ReferralStatusList.svelte +118 -0
  184. package/dist/svelte/components/ReferralStatusList.svelte.d.ts +11 -0
  185. package/dist/svelte/components/ReferralStatusList.svelte.d.ts.map +1 -0
  186. package/dist/svelte/components/ReferrerEarningsSummary.svelte +106 -0
  187. package/dist/svelte/components/ReferrerEarningsSummary.svelte.d.ts +11 -0
  188. package/dist/svelte/components/ReferrerEarningsSummary.svelte.d.ts.map +1 -0
  189. package/dist/svelte/components/SalesDashboard.svelte +192 -0
  190. package/dist/svelte/components/SalesDashboard.svelte.d.ts +29 -0
  191. package/dist/svelte/components/SalesDashboard.svelte.d.ts.map +1 -0
  192. package/dist/svelte/format.d.ts +46 -0
  193. package/dist/svelte/format.d.ts.map +1 -0
  194. package/dist/svelte/format.js +75 -0
  195. package/dist/svelte/index.d.ts +50 -0
  196. package/dist/svelte/index.d.ts.map +1 -0
  197. package/dist/svelte/index.js +37 -0
  198. package/dist/svelte/types.d.ts +422 -0
  199. package/dist/svelte/types.d.ts.map +1 -0
  200. package/dist/svelte/types.js +376 -0
  201. package/package.json +89 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * CRM module of `@happyvertical/smrt-sales`.
3
+ *
4
+ * Leads, Opportunities, configurable Pipelines, the SalesRepresentative
5
+ * role, the SalesActivity audit/next-action trail, and idempotent
6
+ * OpportunityConversion links. No referral or commission semantics live
7
+ * here — the only commissions touchpoint is the string `earnerId` FK on
8
+ * SalesRepresentative (see `packages/sales/AGENTS.md`).
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ export { LeadCollection } from './collections/LeadCollection.js';
13
+ export { OpportunityCollection } from './collections/OpportunityCollection.js';
14
+ export { OpportunityConversionCollection } from './collections/OpportunityConversionCollection.js';
15
+ export { PipelineDefinitionCollection } from './collections/PipelineDefinitionCollection.js';
16
+ export { PipelineStageCollection } from './collections/PipelineStageCollection.js';
17
+ export { SalesActivityCollection } from './collections/SalesActivityCollection.js';
18
+ export { SalesRepresentativeCollection } from './collections/SalesRepresentativeCollection.js';
19
+ export { Lead } from './models/Lead.js';
20
+ export { Opportunity } from './models/Opportunity.js';
21
+ export { OpportunityConversion } from './models/OpportunityConversion.js';
22
+ export { PipelineDefinition } from './models/PipelineDefinition.js';
23
+ export { PipelineStage } from './models/PipelineStage.js';
24
+ export { SalesActivity } from './models/SalesActivity.js';
25
+ export { SalesRepresentative } from './models/SalesRepresentative.js';
26
+ export * from './types.js';
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,+BAA+B,EAAE,MAAM,kDAAkD,CAAC;AACnG,OAAO,EAAE,4BAA4B,EAAE,MAAM,+CAA+C,CAAC;AAC7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,6BAA6B,EAAE,MAAM,gDAAgD,CAAC;AAE/F,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,cAAc,YAAY,CAAC"}
@@ -0,0 +1,135 @@
1
+ import { SmrtObject } from '@happyvertical/smrt-core';
2
+ import { LeadOptions, LeadStatus } from '../types.js';
3
+ /**
4
+ * Lead is an identified prospect: a person/organization that showed intent
5
+ * but has not yet been qualified into an Opportunity.
6
+ *
7
+ * Acquisition provenance is generic — `sourceKind`/`sourceId` name where the
8
+ * lead came from (a campaign, an import, a referral, a form, …) without this
9
+ * module knowing referral semantics; `acquisitionContext` preserves the raw
10
+ * acquisition payload as JSON, and audited merges append the loser's context
11
+ * under a `mergedSources` array so no acquisition history is ever lost.
12
+ *
13
+ * Leads are never deleted (audit trail): duplicates are merged via
14
+ * `LeadCollection.mergeLeads()` — the loser becomes terminal `merged` with
15
+ * `mergedIntoId` pointing at the winner, and its activities stay attached.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const leads = await LeadCollection.create({ db });
20
+ * const lead = await leads.create({
21
+ * name: 'Acme rooftop retrofit',
22
+ * email: 'facilities@acme.test',
23
+ * sourceKind: 'campaign',
24
+ * sourceId: 'spring-2026',
25
+ * });
26
+ * const opportunity = await leads.qualify({ leadId: lead.id ?? '' });
27
+ * ```
28
+ */
29
+ export declare class Lead extends SmrtObject {
30
+ /**
31
+ * Tenant ID for multi-tenant isolation.
32
+ * Nullable to support both tenant-scoped and global leads.
33
+ */
34
+ tenantId: string | null;
35
+ /** Short descriptive name of the prospect/deal-to-be. Required. */
36
+ name: string;
37
+ /** Primary human contact name. */
38
+ contactName: string;
39
+ /** Primary contact email. */
40
+ email: string;
41
+ /** Primary contact phone. */
42
+ phone: string;
43
+ /** Prospect organization/company name. */
44
+ organizationName: string;
45
+ /**
46
+ * Optional identity link once the prospect is a known Profile —
47
+ * cross-package string reference to smrt-profiles.
48
+ */
49
+ profileId: string;
50
+ /** Owning sales rep (assignment). Empty while unassigned. */
51
+ ownerRepId: string;
52
+ /** Lifecycle status; transitions are save-guarded (see module map). */
53
+ status: LeadStatus;
54
+ /**
55
+ * Generic acquisition-source kind (open string): `'campaign'`,
56
+ * `'referral'`, `'import'`, `'web_form'`, … CRM stores the pointer without
57
+ * interpreting it — referral attribution lives in the referrals module.
58
+ */
59
+ sourceKind: string;
60
+ /** Identifier within the `sourceKind` namespace. */
61
+ sourceId: string;
62
+ /**
63
+ * Preserved acquisition history as a JSON object string. Use
64
+ * {@link getAcquisitionContext}/{@link setAcquisitionContext}. Merges append
65
+ * the losing lead's context under a `mergedSources` array — both sides'
66
+ * histories survive.
67
+ */
68
+ acquisitionContext: string;
69
+ /**
70
+ * Generic external intake-draft reference (open string) — e.g. the id of a
71
+ * form submission, imported CSV row, or referral intake draft that this
72
+ * lead was materialized from.
73
+ */
74
+ intakeRef: string;
75
+ /**
76
+ * Winner lead this row was merged into. Set (with status `merged`) by
77
+ * `LeadCollection.mergeLeads()`; empty for live leads. Self-referencing FK.
78
+ */
79
+ mergedIntoId: string;
80
+ /** When the lead was qualified into an opportunity. */
81
+ qualifiedAt: Date | null;
82
+ /**
83
+ * Free-form JSON object stored as a string. Use
84
+ * {@link getMetadata}/{@link setMetadata} instead of parsing manually.
85
+ */
86
+ metadata: string;
87
+ constructor(options?: LeadOptions);
88
+ /** Whether the lead has been folded into another lead (terminal). */
89
+ isMerged(): boolean;
90
+ /** Whether the lead has been qualified into an opportunity. */
91
+ isQualified(): boolean;
92
+ /** Parse the acquisition-context JSON string; `{}` on malformed content. */
93
+ getAcquisitionContext(): Record<string, unknown>;
94
+ /** Serialize and store the acquisition-context object. */
95
+ setAcquisitionContext(context: Record<string, unknown>): void;
96
+ /** Parse the metadata JSON string; returns `{}` on malformed content. */
97
+ getMetadata(): Record<string, unknown>;
98
+ /** Serialize and store the metadata object. */
99
+ setMetadata(metadata: Record<string, unknown>): void;
100
+ /**
101
+ * Capture the status the row was loaded with so the save-time transition
102
+ * guard can reject illegal status flips made via raw field assignment
103
+ * (mass-assignment on the generated update route, a stale caller, etc.).
104
+ * Only persisted rows carry a prior status.
105
+ */
106
+ initialize(): Promise<this>;
107
+ /**
108
+ * Validate the status transition before persisting, then save. A forged
109
+ * `status` (e.g. un-merging a merged lead) is rejected here regardless of
110
+ * how the instance was constructed.
111
+ */
112
+ save(): Promise<this>;
113
+ /**
114
+ * Reject an illegal status flip done via raw assignment. No-op transitions
115
+ * and brand-new rows are always allowed.
116
+ */
117
+ protected assertLeadStatusTransition(prior: LeadStatus | undefined): void;
118
+ /**
119
+ * Resolve the AUTHORITATIVE prior status (commerce Contract pattern). The
120
+ * WeakMap is only populated when {@link initialize} loaded the row from the
121
+ * DB; it is empty for an instance built via
122
+ * `collection.create({ id: <existing>, _skipLoad: true })` — the upsert
123
+ * path that writes onto an existing row without hydrating it. Trusting an
124
+ * empty WeakMap there would treat the write as a brand-new row and skip the
125
+ * guard entirely (a poisonable prior-state).
126
+ *
127
+ * So when this instance carries an `id`, read the persisted row straight
128
+ * from the database and treat its `status` as the prior. Only when no row
129
+ * exists (truly new) do we fall back to the WeakMap. The raw row's `status`
130
+ * column is single-word (no snake_case transform).
131
+ */
132
+ protected resolvePriorStatus(): Promise<LeadStatus | undefined>;
133
+ }
134
+ export default Lead;
135
+ //# sourceMappingURL=Lead.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Lead.d.ts","sourceRoot":"","sources":["../../../src/crm/models/Lead.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAIL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA6B3D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAMa,IAAK,SAAQ,UAAU;IAClC;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,mEAAmE;IAEnE,IAAI,EAAE,MAAM,CAAM;IAElB,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAM;IAEzB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAM;IAEnB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAM;IAEnB,0CAA0C;IAC1C,gBAAgB,EAAE,MAAM,CAAM;IAE9B;;;OAGG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB,6DAA6D;IAE7D,UAAU,EAAE,MAAM,CAAM;IAExB,uEAAuE;IACvE,MAAM,EAAE,UAAU,CAAS;IAE3B;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAM;IAExB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAM;IAEtB;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,CAAQ;IAElC;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAM;IAEvB;;;OAGG;IAEH,YAAY,EAAE,MAAM,CAAM;IAE1B,uDAAuD;IACvD,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEhC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAQ;gBAEZ,OAAO,GAAE,WAAgB;IAyBrC,qEAAqE;IACrE,QAAQ,IAAI,OAAO;IAInB,+DAA+D;IAC/D,WAAW,IAAI,OAAO;IAItB,4EAA4E;IAC5E,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYhD,0DAA0D;IAC1D,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI7D,yEAAyE;IACzE,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYtC,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIpD;;;;;OAKG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ1C;;;;OAIG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQpC;;;OAGG;IACH,SAAS,CAAC,0BAA0B,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI;IAYzE;;;;;;;;;;;;;OAaG;cACa,kBAAkB,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;CAatE;AAED,eAAe,IAAI,CAAC"}
@@ -0,0 +1,111 @@
1
+ import { SmrtObject } from '@happyvertical/smrt-core';
2
+ import { OpportunityOptions, OpportunityStatus } from '../types.js';
3
+ /**
4
+ * Opportunity is a qualified engagement: a deal with an expected value moving
5
+ * through the stages of a PipelineDefinition.
6
+ *
7
+ * Money is integer cents (`expectedValueCents`, INTEGER) with an ISO 4217
8
+ * `currency`; `probability` is a decimal in `0`–`1` (DECIMAL). Stage
9
+ * movement goes through `OpportunityCollection.moveToStage()`, which
10
+ * validates the stage belongs to the opportunity's pipeline, adopts the
11
+ * stage's probability, closes the deal on terminal stages, and writes a
12
+ * `stage_change` SalesActivity. `sourceKind`/`sourceId` are copied from the
13
+ * originating Lead at qualification time so reporting can attribute won
14
+ * revenue without joining back through leads.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const opportunities = await OpportunityCollection.create({ db });
19
+ * const moved = await opportunities.moveToStage({
20
+ * opportunityId: opportunity.id ?? '',
21
+ * stageId: proposalStage.id ?? '',
22
+ * });
23
+ * ```
24
+ */
25
+ export declare class Opportunity extends SmrtObject {
26
+ /**
27
+ * Tenant ID for multi-tenant isolation.
28
+ * Nullable to support both tenant-scoped and global opportunities.
29
+ */
30
+ tenantId: string | null;
31
+ /** Deal name shown on boards and lists. Required. */
32
+ name: string;
33
+ /** Originating lead (empty for opportunities created directly). */
34
+ leadId: string;
35
+ /** Owning sales rep. */
36
+ ownerRepId: string;
37
+ /** Pipeline the deal moves through. */
38
+ pipelineId: string;
39
+ /** Current stage within the pipeline. */
40
+ stageId: string;
41
+ /** Expected deal value in integer cents (INTEGER column). */
42
+ expectedValueCents: number;
43
+ /** ISO 4217 currency code for `expectedValueCents`. */
44
+ currency: string;
45
+ /**
46
+ * Win probability (`0`–`1`, DECIMAL). Adopted from the current stage's
47
+ * default on stage moves unless explicitly overridden.
48
+ */
49
+ probability: number;
50
+ /** Forecasted close date. */
51
+ expectedCloseAt: Date | null;
52
+ /** Lifecycle status; `open → won|lost` is save-guarded, terminal after. */
53
+ status: OpportunityStatus;
54
+ /**
55
+ * Human-readable outcome note — conventionally the loss reason
56
+ * (`'budget cut'`) or a win annotation.
57
+ */
58
+ outcomeReason: string;
59
+ /** When the deal closed as won. */
60
+ wonAt: Date | null;
61
+ /** When the deal closed as lost. */
62
+ lostAt: Date | null;
63
+ /**
64
+ * Acquisition source copied from the originating lead at qualification
65
+ * time (open string), kept denormalized for reporting.
66
+ */
67
+ sourceKind: string;
68
+ /** Identifier within the `sourceKind` namespace (copied from the lead). */
69
+ sourceId: string;
70
+ /**
71
+ * Free-form JSON object stored as a string. Use
72
+ * {@link getMetadata}/{@link setMetadata} instead of parsing manually.
73
+ */
74
+ metadata: string;
75
+ constructor(options?: OpportunityOptions);
76
+ /** Whether the deal is still in play. */
77
+ isOpen(): boolean;
78
+ /** Whether the deal closed (won or lost). */
79
+ isClosed(): boolean;
80
+ /** Parse the metadata JSON string; returns `{}` on malformed content. */
81
+ getMetadata(): Record<string, unknown>;
82
+ /** Serialize and store the metadata object. */
83
+ setMetadata(metadata: Record<string, unknown>): void;
84
+ /**
85
+ * Capture the status the row was loaded with so the save-time transition
86
+ * guard can reject illegal status flips made via raw field assignment.
87
+ * Only persisted rows carry a prior status.
88
+ */
89
+ initialize(): Promise<this>;
90
+ /**
91
+ * Validate the status transition before persisting, then save. A forged
92
+ * `status` (e.g. re-opening a lost deal) is rejected here regardless of
93
+ * how the instance was constructed.
94
+ */
95
+ save(): Promise<this>;
96
+ /**
97
+ * Reject an illegal status flip done via raw assignment. No-op transitions
98
+ * and brand-new rows are always allowed.
99
+ */
100
+ protected assertOpportunityStatusTransition(prior: OpportunityStatus | undefined): void;
101
+ /**
102
+ * Resolve the AUTHORITATIVE prior status (commerce Contract pattern): when
103
+ * this instance carries an `id`, re-read the persisted row and use its
104
+ * `status` as the prior — a create-onto-existing is an update, and an
105
+ * un-hydrated instance must not bypass the guard. Falls back to the
106
+ * load-time WeakMap (empty for truly new rows → `undefined` = new).
107
+ */
108
+ protected resolvePriorStatus(): Promise<OpportunityStatus | undefined>;
109
+ }
110
+ export default Opportunity;
111
+ //# sourceMappingURL=Opportunity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Opportunity.d.ts","sourceRoot":"","sources":["../../../src/crm/models/Opportunity.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAqB,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAE/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA0BzE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAMa,WAAY,SAAQ,UAAU;IACzC;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,qDAAqD;IAErD,IAAI,EAAE,MAAM,CAAM;IAElB,mEAAmE;IAEnE,MAAM,EAAE,MAAM,CAAM;IAEpB,wBAAwB;IAExB,UAAU,EAAE,MAAM,CAAM;IAExB,uCAAuC;IAEvC,UAAU,EAAE,MAAM,CAAM;IAExB,yCAAyC;IAEzC,OAAO,EAAE,MAAM,CAAM;IAErB,6DAA6D;IAC7D,kBAAkB,EAAE,MAAM,CAAK;IAE/B,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAS;IAEzB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAO;IAE1B,6BAA6B;IAC7B,eAAe,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEpC,2EAA2E;IAC3E,MAAM,EAAE,iBAAiB,CAAU;IAEnC;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAM;IAE3B,mCAAmC;IACnC,KAAK,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE1B,oCAAoC;IACpC,MAAM,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE3B;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAM;IAExB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAM;IAEtB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAQ;gBAEZ,OAAO,GAAE,kBAAuB;IAyB5C,yCAAyC;IACzC,MAAM,IAAI,OAAO;IAIjB,6CAA6C;IAC7C,QAAQ,IAAI,OAAO;IAInB,yEAAyE;IACzE,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYtC,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIpD;;;;OAIG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ1C;;;;OAIG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQpC;;;OAGG;IACH,SAAS,CAAC,iCAAiC,CACzC,KAAK,EAAE,iBAAiB,GAAG,SAAS,GACnC,IAAI;IAYP;;;;;;OAMG;cACa,kBAAkB,IAAI,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;CAa7E;AAED,eAAe,WAAW,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { SmrtObject } from '@happyvertical/smrt-core';
2
+ import { OpportunityConversionOptions } from '../types.js';
3
+ /**
4
+ * OpportunityConversion records that a WON opportunity materialized into a
5
+ * downstream record — a client, project, contract, subscription, or any
6
+ * caller-defined kind. The target is a generic `(targetKind, targetId)`
7
+ * string pair: CRM never creates (or mutates) the downstream records
8
+ * themselves and never touches referral or commission state.
9
+ *
10
+ * The natural key `(opportunity_id, target_kind, target_id)`
11
+ * (`conflictColumns`) makes recording idempotent — use
12
+ * `OpportunityConversionCollection.recordConversion()`, which enforces the
13
+ * won-status precondition and reports whether the link already existed.
14
+ * Links are append-only: the generated surfaces expose `list`/`get`/`create`
15
+ * only (no update/delete).
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const conversions = await OpportunityConversionCollection.create({ db });
20
+ * const { conversion, created } = await conversions.recordConversion({
21
+ * opportunityId: opportunity.id ?? '',
22
+ * targetKind: 'contract',
23
+ * targetId: contractId,
24
+ * });
25
+ * ```
26
+ */
27
+ export declare class OpportunityConversion extends SmrtObject {
28
+ /**
29
+ * Tenant ID for multi-tenant isolation.
30
+ * Nullable to support both tenant-scoped and global conversions.
31
+ */
32
+ tenantId: string | null;
33
+ /** The won opportunity that converted. Required. */
34
+ opportunityId: string;
35
+ /**
36
+ * Downstream record kind — OPEN string: `'client'`, `'project'`,
37
+ * `'contract'`, `'subscription'`, … Required.
38
+ */
39
+ targetKind: string;
40
+ /** Identifier of the downstream record within `targetKind`. Required. */
41
+ targetId: string;
42
+ /** Optional human-readable note about the conversion. */
43
+ note: string;
44
+ /**
45
+ * Free-form JSON object stored as a string. Use
46
+ * {@link getMetadata}/{@link setMetadata} instead of parsing manually.
47
+ */
48
+ metadata: string;
49
+ constructor(options?: OpportunityConversionOptions);
50
+ /** Parse the metadata JSON string; returns `{}` on malformed content. */
51
+ getMetadata(): Record<string, unknown>;
52
+ /** Serialize and store the metadata object. */
53
+ setMetadata(metadata: Record<string, unknown>): void;
54
+ /**
55
+ * Save with the append-only guard: a fresh instance whose
56
+ * `(opportunityId, targetKind, targetId)` natural key already belongs to
57
+ * a DIFFERENT row is refused — the conflict-column upsert would replace
58
+ * the existing conversion link (note and id) without the won-opportunity
59
+ * validation. Idempotent linking goes through
60
+ * `OpportunityConversionCollection.recordConversion()`, which finds
61
+ * first and reports `{ created: false }`.
62
+ */
63
+ save(): Promise<this>;
64
+ }
65
+ export default OpportunityConversion;
66
+ //# sourceMappingURL=OpportunityConversion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpportunityConversion.d.ts","sourceRoot":"","sources":["../../../src/crm/models/OpportunityConversion.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAqB,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAE/E,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAOa,qBAAsB,SAAQ,UAAU;IACnD;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,oDAAoD;IAEpD,aAAa,EAAE,MAAM,CAAM;IAE3B;;;OAGG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB,yEAAyE;IAEzE,QAAQ,EAAE,MAAM,CAAM;IAEtB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAM;IAElB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAQ;gBAEZ,OAAO,GAAE,4BAAiC;IAWtD,yEAAyE;IACzE,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYtC,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIpD;;;;;;;;OAQG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CA+BrC;AAED,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { SmrtObject } from '@happyvertical/smrt-core';
2
+ import { PipelineDefinitionOptions, PipelineStatus } from '../types.js';
3
+ /**
4
+ * PipelineDefinition names an ordered set of {@link PipelineStage | stages}
5
+ * that opportunities move through. Pipelines are configuration rows, not
6
+ * code: tenants can run several (e.g. `default`, `enterprise`, `renewals`)
7
+ * and reshape stages freely without any Lead/Opportunity model change.
8
+ *
9
+ * The natural key is `(tenant_id, key)` (`conflictColumns`), so re-seeding a
10
+ * pipeline with the same key upserts instead of duplicating. The seeded
11
+ * default pipeline (key `'default'`, 7 stages) comes from
12
+ * `PipelineDefinitionCollection.ensureDefaultPipeline()`.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const pipelines = await PipelineDefinitionCollection.create({ db });
17
+ * const { pipeline, stages } = await pipelines.ensureDefaultPipeline();
18
+ * const enterprise = await pipelines.create({
19
+ * key: 'enterprise',
20
+ * name: 'Enterprise motion',
21
+ * });
22
+ * ```
23
+ */
24
+ export declare class PipelineDefinition extends SmrtObject {
25
+ /**
26
+ * Tenant ID for multi-tenant isolation.
27
+ * Nullable to support both tenant-scoped and global pipelines.
28
+ */
29
+ tenantId: string | null;
30
+ /**
31
+ * Stable machine key, unique per tenant (natural key with `tenantId`).
32
+ * Required — e.g. `'default'`, `'enterprise'`.
33
+ */
34
+ key: string;
35
+ /** Human-readable pipeline name shown on CRM surfaces. */
36
+ name: string;
37
+ /**
38
+ * Marks the tenant's default pipeline. Informational for pickers/UI; the
39
+ * seeded default pipeline sets it `true`.
40
+ */
41
+ isDefault: boolean;
42
+ /** `active` pipelines accept new opportunities; `archived` are read-only history. */
43
+ status: PipelineStatus;
44
+ /**
45
+ * Free-form JSON object stored as a string. Use
46
+ * {@link getMetadata}/{@link setMetadata} instead of parsing manually.
47
+ */
48
+ metadata: string;
49
+ constructor(options?: PipelineDefinitionOptions);
50
+ /** Whether the pipeline accepts new opportunities. */
51
+ isActive(): boolean;
52
+ /** Parse the metadata JSON string; returns `{}` on malformed content. */
53
+ getMetadata(): Record<string, unknown>;
54
+ /** Serialize and store the metadata object. */
55
+ setMetadata(metadata: Record<string, unknown>): void;
56
+ }
57
+ export default PipelineDefinition;
58
+ //# sourceMappingURL=PipelineDefinition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineDefinition.d.ts","sourceRoot":"","sources":["../../../src/crm/models/PipelineDefinition.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAS,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAEnE,OAAO,KAAK,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAOa,kBAAmB,SAAQ,UAAU;IAChD;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;;OAGG;IAEH,GAAG,EAAE,MAAM,CAAM;IAEjB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAM;IAElB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAS;IAE3B,qFAAqF;IACrF,MAAM,EAAE,cAAc,CAAY;IAElC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAQ;gBAEZ,OAAO,GAAE,yBAA8B;IAUnD,sDAAsD;IACtD,QAAQ,IAAI,OAAO;IAInB,yEAAyE;IACzE,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYtC,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGrD;AAED,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { SmrtObject } from '@happyvertical/smrt-core';
2
+ import { PipelineStageOptions } from '../types.js';
3
+ /**
4
+ * PipelineStage is a configurable step within a pipeline. Stages carry the
5
+ * default win `probability` an opportunity adopts on entry and the terminal
6
+ * flags (`isWon`/`isLost`) that close an opportunity when it moves in
7
+ * (see `OpportunityCollection.moveToStage()`).
8
+ *
9
+ * Natural key `(pipeline_id, key)` (`conflictColumns`) — re-seeding a stage
10
+ * key within a pipeline upserts. Stages are plain rows: rename, re-weight,
11
+ * insert, or reorder (via `sortOrder`) with normal collection operations —
12
+ * no Lead/Opportunity model change is ever needed.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const stages = await PipelineStageCollection.create({ db });
17
+ * await stages.create({
18
+ * pipelineId: pipeline.id,
19
+ * key: 'legal_review',
20
+ * name: 'Legal Review',
21
+ * sortOrder: 45, // between seeded proposal (40) and negotiation (50)
22
+ * probability: 0.7,
23
+ * });
24
+ * ```
25
+ */
26
+ export declare class PipelineStage extends SmrtObject {
27
+ /**
28
+ * Tenant ID for multi-tenant isolation.
29
+ * Nullable to support both tenant-scoped and global stages.
30
+ */
31
+ tenantId: string | null;
32
+ /** Owning pipeline. Required. */
33
+ pipelineId: string;
34
+ /**
35
+ * Stable machine key, unique within the pipeline (natural key with
36
+ * `pipelineId`). Required — e.g. `'proposal'`, `'closed_won'`.
37
+ */
38
+ key: string;
39
+ /** Human-readable stage name shown on board columns. */
40
+ name: string;
41
+ /** Ordering within the pipeline (ascending). Seeded in steps of 10. */
42
+ sortOrder: number;
43
+ /**
44
+ * Default win probability (`0`–`1`, DECIMAL) adopted by an opportunity
45
+ * entering this stage unless the move overrides it.
46
+ */
47
+ probability: number;
48
+ /** Terminal flag: moving an opportunity here closes it as `won`. */
49
+ isWon: boolean;
50
+ /** Terminal flag: moving an opportunity here closes it as `lost`. */
51
+ isLost: boolean;
52
+ /**
53
+ * Free-form JSON object stored as a string. Use
54
+ * {@link getMetadata}/{@link setMetadata} instead of parsing manually.
55
+ */
56
+ metadata: string;
57
+ constructor(options?: PipelineStageOptions);
58
+ /** Whether entering this stage closes the opportunity (won or lost). */
59
+ isTerminal(): boolean;
60
+ /** Parse the metadata JSON string; returns `{}` on malformed content. */
61
+ getMetadata(): Record<string, unknown>;
62
+ /** Serialize and store the metadata object. */
63
+ setMetadata(metadata: Record<string, unknown>): void;
64
+ }
65
+ export default PipelineStage;
66
+ //# sourceMappingURL=PipelineStage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineStage.d.ts","sourceRoot":"","sources":["../../../src/crm/models/PipelineStage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAqB,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAE/E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAOa,aAAc,SAAQ,UAAU;IAC3C;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,iCAAiC;IAEjC,UAAU,EAAE,MAAM,CAAM;IAExB;;;OAGG;IAEH,GAAG,EAAE,MAAM,CAAM;IAEjB,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAM;IAElB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAK;IAEtB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAO;IAE1B,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAS;IAEvB,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAS;IAExB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAQ;gBAEZ,OAAO,GAAE,oBAAyB;IAc9C,wEAAwE;IACxE,UAAU,IAAI,OAAO;IAIrB,yEAAyE;IACzE,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYtC,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGrD;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { SmrtObject } from '@happyvertical/smrt-core';
2
+ import { SalesActivityOptions, SalesActivitySubjectKind } from '../types.js';
3
+ /**
4
+ * SalesActivity is the shared trail for Leads and Opportunities: human
5
+ * touchpoints (`note`, `call`, `email`, `meeting`), next actions (`task`
6
+ * with `dueAt`/`completedAt`), and framework-written audit rows
7
+ * (`assignment`, `qualification`, `stage_change`, `merge`, `status_change`).
8
+ *
9
+ * The subject is polymorphic by string pair — `subjectKind`
10
+ * (`'lead' | 'opportunity'`) plus `subjectId` — deliberately NOT a typed FK
11
+ * so one table serves both subjects. `activityKind` is an OPEN string;
12
+ * `SALES_ACTIVITY_KINDS` exports the recommended vocabulary.
13
+ *
14
+ * Activities are an immutable trail: the generated surfaces expose only
15
+ * `create`/`list`/`get` (no update/delete). Merges intentionally leave the
16
+ * losing lead's activities attached to the loser —
17
+ * `LeadCollection.activitiesIncludingMerged()` re-assembles the full history
18
+ * across merge chains.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const activities = await SalesActivityCollection.create({ db });
23
+ * await activities.create({
24
+ * subjectKind: 'lead',
25
+ * subjectId: lead.id,
26
+ * activityKind: 'task',
27
+ * summary: 'Send follow-up deck',
28
+ * dueAt: new Date('2026-08-01'),
29
+ * });
30
+ * const open = await activities.findOpenTasks('lead', lead.id ?? '');
31
+ * ```
32
+ */
33
+ export declare class SalesActivity extends SmrtObject {
34
+ /**
35
+ * Tenant ID for multi-tenant isolation.
36
+ * Nullable to support both tenant-scoped and global activities.
37
+ */
38
+ tenantId: string | null;
39
+ /** Which model the activity attaches to: `'lead'` or `'opportunity'`. */
40
+ subjectKind: SalesActivitySubjectKind;
41
+ /** Id of the subject row. Required. */
42
+ subjectId: string;
43
+ /**
44
+ * Kind of activity — OPEN string so consumers can extend the vocabulary
45
+ * without schema changes. See `SALES_ACTIVITY_KINDS` for the recommended
46
+ * kinds (framework-written rows use `qualification`, `stage_change`,
47
+ * `merge`).
48
+ */
49
+ activityKind: string;
50
+ /** One-line human-readable description. */
51
+ summary: string;
52
+ /** Next-action due date — set for `task`-like activities. */
53
+ dueAt: Date | null;
54
+ /** When the next action was completed; `null` while open. */
55
+ completedAt: Date | null;
56
+ /**
57
+ * Profile of the human/agent who performed or recorded the activity —
58
+ * cross-package string reference to smrt-profiles.
59
+ */
60
+ actorProfileId: string;
61
+ /**
62
+ * Free-form JSON object stored as a string (framework audit rows carry
63
+ * structured detail here, e.g. `stage_change` from/to ids or the full
64
+ * loser snapshot on `merge`). Use {@link getMetadata}/{@link setMetadata}.
65
+ */
66
+ metadata: string;
67
+ constructor(options?: SalesActivityOptions);
68
+ /** Whether this is an open next action (due date set, not completed). */
69
+ isOpenTask(): boolean;
70
+ /** Parse the metadata JSON string; returns `{}` on malformed content. */
71
+ getMetadata(): Record<string, unknown>;
72
+ /** Serialize and store the metadata object. */
73
+ setMetadata(metadata: Record<string, unknown>): void;
74
+ }
75
+ export default SalesActivity;
76
+ //# sourceMappingURL=SalesActivity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SalesActivity.d.ts","sourceRoot":"","sources":["../../../src/crm/models/SalesActivity.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,oBAAoB,EACpB,wBAAwB,EACzB,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAMa,aAAc,SAAQ,UAAU;IAC3C;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,yEAAyE;IACzE,WAAW,EAAE,wBAAwB,CAAU;IAE/C,uCAAuC;IAEvC,SAAS,EAAE,MAAM,CAAM;IAEvB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAU;IAE9B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAM;IAErB,6DAA6D;IAC7D,KAAK,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE1B,6DAA6D;IAC7D,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEhC;;;OAGG;IAEH,cAAc,EAAE,MAAM,CAAM;IAE5B;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAQ;gBAEZ,OAAO,GAAE,oBAAyB;IAiB9C,yEAAyE;IACzE,UAAU,IAAI,OAAO;IAIrB,yEAAyE;IACzE,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYtC,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGrD;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { SmrtObject } from '@happyvertical/smrt-core';
2
+ import { SalesRepresentativeOptions, SalesRepresentativeStatus } from '../types.js';
3
+ /**
4
+ * SalesRepresentative is a ROLE model: it links an identity (smrt-profiles
5
+ * Profile) to sales ownership (Leads/Opportunities reference `ownerRepId`).
6
+ *
7
+ * Roles and money stay separate (see `packages/sales/AGENTS.md` "Roles vs.
8
+ * money"): a rep connects to payouts only through the optional `earnerId`
9
+ * pointing at the commissions module's neutral `Earner`. No referral or
10
+ * commission semantics live on this model.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const reps = await SalesRepresentativeCollection.create({ db });
15
+ * const rep = await reps.create({
16
+ * profileId: 'profile-uuid',
17
+ * title: 'Account Executive',
18
+ * });
19
+ * const active = await reps.findActive();
20
+ * ```
21
+ */
22
+ export declare class SalesRepresentative extends SmrtObject {
23
+ /**
24
+ * Tenant ID for multi-tenant isolation.
25
+ * Nullable to support both tenant-scoped and global (operator-level) reps.
26
+ */
27
+ tenantId: string | null;
28
+ /**
29
+ * Identity of the person acting as a rep — cross-package string reference
30
+ * to a smrt-profiles Profile.
31
+ */
32
+ profileId: string;
33
+ /**
34
+ * Optional link to the commissions module's `Earner` (the neutral payout
35
+ * identity). String-form same-package FK: the Earner class lives in
36
+ * `src/commissions` and is intentionally NOT imported here — the string
37
+ * form registers the relationship without a module dependency, keeping the
38
+ * `crm → commissions` boundary reference-only. Empty when the rep is not
39
+ * commission-compensated.
40
+ */
41
+ earnerId: string;
42
+ /** Role status — only `active` reps should receive new assignments. */
43
+ status: SalesRepresentativeStatus;
44
+ /** Job title shown on CRM surfaces (e.g. `'Account Executive'`). */
45
+ title: string;
46
+ /**
47
+ * Free-form JSON object stored as a string. Use
48
+ * {@link getMetadata}/{@link setMetadata} instead of parsing manually.
49
+ */
50
+ metadata: string;
51
+ constructor(options?: SalesRepresentativeOptions);
52
+ /** Whether the rep may receive new lead/opportunity assignments. */
53
+ isActive(): boolean;
54
+ /** Parse the metadata JSON string; returns `{}` on malformed content. */
55
+ getMetadata(): Record<string, unknown>;
56
+ /** Serialize and store the metadata object. */
57
+ setMetadata(metadata: Record<string, unknown>): void;
58
+ }
59
+ export default SalesRepresentative;
60
+ //# sourceMappingURL=SalesRepresentative.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SalesRepresentative.d.ts","sourceRoot":"","sources":["../../../src/crm/models/SalesRepresentative.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAMa,mBAAoB,SAAQ,UAAU;IACjD;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;;OAGG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB;;;;;;;OAOG;IAEH,QAAQ,EAAE,MAAM,CAAM;IAEtB,uEAAuE;IACvE,MAAM,EAAE,yBAAyB,CAAY;IAE7C,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAM;IAEnB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAQ;gBAEZ,OAAO,GAAE,0BAA+B;IAUpD,oEAAoE;IACpE,QAAQ,IAAI,OAAO;IAInB,yEAAyE;IACzE,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYtC,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGrD;AAED,eAAe,mBAAmB,CAAC"}