@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,248 @@
1
+ import { SmrtClassOptions } from '@happyvertical/smrt-core';
2
+ import { AttributionExceptionCollection } from '../collections/AttributionExceptionCollection.js';
3
+ import { AttributionPolicyCollection } from '../collections/AttributionPolicyCollection.js';
4
+ import { ReferralCollection } from '../collections/ReferralCollection.js';
5
+ import { ReferralProgramCollection } from '../collections/ReferralProgramCollection.js';
6
+ import { ReferralTouchCollection } from '../collections/ReferralTouchCollection.js';
7
+ import { ReferrerCollection } from '../collections/ReferrerCollection.js';
8
+ import { AttributionException } from '../models/AttributionException.js';
9
+ import { Referral } from '../models/Referral.js';
10
+ import { ReferralTouch } from '../models/ReferralTouch.js';
11
+ /**
12
+ * Thrown by {@link AttributionService.override} when the target already has
13
+ * a QUALIFIED referral: qualified credit is governed by its term snapshot
14
+ * and commission adjustments downstream — re-attribution would silently
15
+ * orphan agreed terms.
16
+ */
17
+ export declare class QualifiedReferralOverrideError extends Error {
18
+ constructor(referralIds: string[]);
19
+ }
20
+ /** Collaborators for {@link AttributionService}. */
21
+ export interface AttributionServiceDeps {
22
+ touches: ReferralTouchCollection;
23
+ referrals: ReferralCollection;
24
+ exceptions: AttributionExceptionCollection;
25
+ policies: AttributionPolicyCollection;
26
+ programs: ReferralProgramCollection;
27
+ referrers: ReferrerCollection;
28
+ }
29
+ /** Why {@link AttributionService.resolve} refused to attribute. */
30
+ export type AttributionRefusalReason = 'existing_client_ineligible' | 'no_active_policy' | 'no_eligible_touches';
31
+ /** Input for {@link AttributionService.resolve}. */
32
+ export interface ResolveAttributionInput {
33
+ /** Generic qualifying target the referrals will point at. */
34
+ targetKind: string;
35
+ /** Identifier within the `targetKind` namespace. */
36
+ targetId: string;
37
+ /** The program to attribute under. */
38
+ programId: string;
39
+ /** Prospect identity to gather touches by (in addition to the target). */
40
+ subjectKind?: string;
41
+ /** Identifier within the `subjectKind` namespace. */
42
+ subjectId?: string;
43
+ /**
44
+ * The prospect's own profile id, when known — enables the self-referral
45
+ * eligibility check against each candidate referrer's `profileId`.
46
+ */
47
+ subjectProfileId?: string;
48
+ /**
49
+ * Caller's statement that the prospect is already a client. Policies with
50
+ * `allowExistingClients: false` refuse the whole resolution.
51
+ */
52
+ isExistingClient?: boolean;
53
+ /** Overrides the program's `defaultAttributionPolicyKey`. */
54
+ policyKey?: string;
55
+ /** Clock override for deterministic tests. */
56
+ now?: Date;
57
+ }
58
+ /** Result of {@link AttributionService.resolve}. */
59
+ export interface AttributionResolution {
60
+ /**
61
+ * The attributed referral(s): one for sole credit, several siblings for
62
+ * `split` mode. Empty when an exception was raised, the resolution was
63
+ * refused, or nothing was eligible.
64
+ */
65
+ referrals: Referral[];
66
+ /** The conflict parked for review, when the policy could not conclude. */
67
+ exception: AttributionException | null;
68
+ /** Why nothing was attributed, when refused outright. */
69
+ refused?: AttributionRefusalReason;
70
+ }
71
+ /** Input for {@link AttributionService.recordManualAssignment}. */
72
+ export interface RecordManualAssignmentInput {
73
+ referrerId: string;
74
+ programId: string;
75
+ targetKind: string;
76
+ targetId: string;
77
+ /** Prospect identity; defaults to the target pair when omitted. */
78
+ subjectKind?: string;
79
+ subjectId?: string;
80
+ /** Who recorded the assignment (audit). Required. */
81
+ actorProfileId: string;
82
+ /** Free-form rationale recorded in the touch evidence. */
83
+ reason?: string;
84
+ /** When the assignment applies from; defaults to now. */
85
+ occurredAt?: Date;
86
+ }
87
+ /** One credit award inside a resolution/override. */
88
+ export interface AttributionAward {
89
+ referrerId: string;
90
+ /** Credit share (0–1]; awards must sum to 1.0 (±0.0001). */
91
+ creditFraction: number;
92
+ }
93
+ /** Input for {@link AttributionService.resolveException}. */
94
+ export interface ResolveExceptionInput {
95
+ exceptionId: string;
96
+ awards: AttributionAward[];
97
+ /** Non-empty rationale. Required — resolutions are audited. */
98
+ resolutionReason: string;
99
+ /** Who resolved the exception (audit). Required. */
100
+ actorProfileId: string;
101
+ /** Clock override for deterministic tests. */
102
+ now?: Date;
103
+ }
104
+ /** Input for {@link AttributionService.override}. */
105
+ export interface OverrideAttributionInput {
106
+ targetKind: string;
107
+ targetId: string;
108
+ programId: string;
109
+ awards: AttributionAward[];
110
+ /** Non-empty rationale. Required — overrides are audited. */
111
+ resolutionReason: string;
112
+ /** Who performed the override (audit). Required. */
113
+ actorProfileId: string;
114
+ /** Clock override for deterministic tests. */
115
+ now?: Date;
116
+ }
117
+ /** Result of {@link AttributionService.resolveException} / {@link AttributionService.override}. */
118
+ export interface AttributionAwardResult {
119
+ /** The attributed referral(s) the awards created. */
120
+ referrals: Referral[];
121
+ /** The resolved exception row auditing the decision. */
122
+ exception: AttributionException;
123
+ }
124
+ export declare class AttributionService {
125
+ private readonly deps;
126
+ constructor(deps: AttributionServiceDeps);
127
+ static create(classOptions?: SmrtClassOptions): Promise<AttributionService>;
128
+ /**
129
+ * Resolve attribution for one target under one program.
130
+ *
131
+ * IDEMPOTENT: existing non-disqualified `attributed`/`qualified`
132
+ * referrals for the target+program are returned as-is (no new rows), and
133
+ * an already-OPEN exception for the target+program is returned instead of
134
+ * a duplicate.
135
+ *
136
+ * Flow:
137
+ * 1. **Policy** — the program's `defaultAttributionPolicyKey` (or the
138
+ * `policyKey` override) is resolved via `latestActiveByKey`; no active
139
+ * version → `refused: 'no_active_policy'`.
140
+ * 2. **Existing-client gate** — `isExistingClient` with a policy that
141
+ * disallows it → `refused: 'existing_client_ineligible'`.
142
+ * 3. **Candidates** — touches gathered by the subject pair (when given)
143
+ * and by the target pair, deduplicated, restricted to the program and
144
+ * to `occurredAt` within `[now - windowDays, now]`.
145
+ * 4. **Eligibility** — self-referrals (candidate referrer's `profileId`
146
+ * equals `subjectProfileId`) are dropped unless the policy allows
147
+ * them. Nothing left → `refused: 'no_eligible_touches'`.
148
+ * 5. **Conflicts** — `conflictBehavior: 'review'` with more than one
149
+ * distinct eligible referrer, exact-timestamp ties between distinct
150
+ * referrers in `first_touch`/`last_touch`, or competing manual
151
+ * assignments in `assigned` mode → an OPEN AttributionException
152
+ * carrying the candidates; NO referral rows.
153
+ * 6. **Credit** — otherwise the mode elects the winner(s):
154
+ * `first_touch`/`last_touch` (earliest/latest), `assigned` (most
155
+ * recent manual assignment; assignments beat clicks by definition),
156
+ * or `split` (every distinct eligible referrer, equal fractions
157
+ * rounded to 4 dp with the remainder on the last, one shared
158
+ * `splitGroupId`). Referrals are created `pending → attributed` with
159
+ * the policy pin, winning touch, `attributedAt = now`, and
160
+ * `expiresAt = now + windowDays`.
161
+ */
162
+ resolve(input: ResolveAttributionInput): Promise<AttributionResolution>;
163
+ /**
164
+ * Record an operator's manual assignment as an immutable
165
+ * `manual_assignment` ReferralTouch (evidence carries the actor, reason,
166
+ * and target) and return it. The caller then runs {@link resolve} — under
167
+ * an `assigned`-mode policy the assignment wins over click evidence.
168
+ */
169
+ recordManualAssignment(input: RecordManualAssignmentInput): Promise<ReferralTouch>;
170
+ /**
171
+ * Resolve an OPEN exception by awarding credit explicitly.
172
+ *
173
+ * Requires a non-empty `resolutionReason` (throws otherwise) and awards
174
+ * whose `creditFraction`s sum to 1.0 (±0.0001) across distinct referrers.
175
+ * Creates the attributed referral(s) from the exception's target/program
176
+ * (split semantics — shared `splitGroupId` — when several awards), then
177
+ * marks the exception resolved (`resolutionMode: 'override'`, the award
178
+ * audit fields, `resolvedReferralIds`).
179
+ */
180
+ resolveException(input: ResolveExceptionInput): Promise<AttributionAwardResult>;
181
+ /**
182
+ * Re-attribute an already-attributed target.
183
+ *
184
+ * Requires a non-empty `resolutionReason` and awards summing to 1.0.
185
+ * REFUSES (throws {@link QualifiedReferralOverrideError}) when the target
186
+ * has a QUALIFIED referral — those are governed by term snapshots and
187
+ * commission adjustments downstream. Otherwise: disqualifies the existing
188
+ * `attributed` referrals for the target+program (stamping the audit
189
+ * exception's id into their metadata), creates the newly awarded
190
+ * attributed referral(s), and writes a RESOLVED AttributionException as
191
+ * the audit record (candidates = the displaced + awarded referrers).
192
+ *
193
+ * The new referrals inherit the POLICY PIN the displaced credit carried
194
+ * (an override re-decides WHO earned the introduction, not which policy
195
+ * version governed it); the program's current default active policy is
196
+ * the fallback when nothing was displaced.
197
+ */
198
+ override(input: OverrideAttributionInput): Promise<AttributionAwardResult>;
199
+ private requireProgram;
200
+ /**
201
+ * The active policy governing a resolution: the explicit `policyKey`
202
+ * override when given, else the program's default key; resolved to its
203
+ * latest ACTIVE version. `null` when no key or no active version.
204
+ */
205
+ private resolvePolicy;
206
+ /**
207
+ * Candidate touches for a resolution: gathered by the subject pair (when
208
+ * given) and by the target pair, deduplicated, restricted to the program,
209
+ * to `occurredAt` within `[now - windowDays, now]`, and to referrers that
210
+ * pass the self-referral gate. Sorted by `occurredAt` ascending.
211
+ */
212
+ private gatherEligibleTouches;
213
+ /** Create an OPEN exception carrying the competing candidates. */
214
+ private createOpenException;
215
+ /**
216
+ * The policy pin an exception was raised under (stamped into its
217
+ * metadata at creation); falls back to the program's current default
218
+ * active policy for exceptions created without one.
219
+ */
220
+ private resolvePolicyPin;
221
+ /**
222
+ * The policy pin an override re-attributes under: the pin the displaced
223
+ * credit carried (looking the exact version's `windowDays` back up for
224
+ * the new expiry), falling back to the program's current default active
225
+ * policy when nothing pinned was displaced.
226
+ */
227
+ private resolveOverridePolicyPin;
228
+ /**
229
+ * Create one referral as `pending`, transition it `pending → attributed`
230
+ * (stamping `attributedAt`), set the policy pin and expiry, and save.
231
+ */
232
+ private createAttributedReferral;
233
+ /**
234
+ * Equal split fractions for `n` referrers, each rounded to 4 decimal
235
+ * places, with the LAST adjusted so the set sums to exactly 1.0.
236
+ */
237
+ private static equalFractions;
238
+ private static assertResolutionReason;
239
+ /**
240
+ * Attribution decisions are audited — a blank actor would permanently
241
+ * resolve/override credit with an empty `resolvedByProfileId`, defeating
242
+ * the audit trail.
243
+ */
244
+ private static assertActor;
245
+ private static assertAwards;
246
+ }
247
+ export default AttributionService;
248
+ //# sourceMappingURL=AttributionService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttributionService.d.ts","sourceRoot":"","sources":["../../../src/referrals/services/AttributionService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import { SmrtClassOptions } from '@happyvertical/smrt-core';
2
+ import { Commission, CommissionCalculationService, CommissionCollection, CommissionComponentSkip, EarningEvent } from '../../commissions/index.js';
3
+ import { ReferralCollection } from '../collections/ReferralCollection.js';
4
+ import { ReferralTermSnapshotCollection } from '../collections/ReferralTermSnapshotCollection.js';
5
+ import { ReferrerCollection } from '../collections/ReferrerCollection.js';
6
+ /**
7
+ * The `termsSnapshotKind` every referral-bridged Commission carries —
8
+ * points `termsSnapshotId` at a ReferralTermSnapshot row.
9
+ */
10
+ export declare const REFERRAL_TERMS_SNAPSHOT_KIND = "referral_term_snapshot";
11
+ /** Collaborators for {@link ReferralCommissionService}. */
12
+ export interface ReferralCommissionServiceDeps {
13
+ referrals: ReferralCollection;
14
+ snapshots: ReferralTermSnapshotCollection;
15
+ referrers: ReferrerCollection;
16
+ /** The commissions module's calculation service (same package). */
17
+ calculation: CommissionCalculationService;
18
+ /** The commissions module's commission collection (occurrence counting). */
19
+ commissions: CommissionCollection;
20
+ }
21
+ /** Input for {@link ReferralCommissionService.processEarningEvent}. */
22
+ export interface ProcessEarningEventInput {
23
+ /** The (persisted) earning event to pay referrals from. */
24
+ event: EarningEvent;
25
+ /** Resolve qualified referrals by target … */
26
+ targetKind?: string;
27
+ targetId?: string;
28
+ /** … or name them explicitly (takes precedence over the target pair). */
29
+ referralIds?: string[];
30
+ /** Reserved clock override for symmetry with the sibling services. */
31
+ now?: Date;
32
+ }
33
+ /** Why a referral produced no calculation. */
34
+ export type ReferralProcessingSkipReason = 'referral_not_found' | 'not_qualified' | 'missing_snapshot' | 'referrer_missing_earner' | 'tenant_mismatch';
35
+ /** One referral the bridge skipped, and why. */
36
+ export interface ReferralProcessingSkip {
37
+ referralId: string;
38
+ reason: ReferralProcessingSkipReason;
39
+ }
40
+ /** Per-referral calculation outcome. */
41
+ export interface ReferralCommissionOutcome {
42
+ referralId: string;
43
+ /** Commissions newly created for this referral by THIS call. */
44
+ created: Commission[];
45
+ /** Idempotent replays — commissions that already existed. */
46
+ existing: Commission[];
47
+ /** Components the calculation declined, with reasons. */
48
+ skipped: CommissionComponentSkip[];
49
+ }
50
+ /** Result of {@link ReferralCommissionService.processEarningEvent}. */
51
+ export interface ProcessEarningEventResult {
52
+ /** One entry per qualified referral that reached calculation. */
53
+ results: ReferralCommissionOutcome[];
54
+ /** Referrals that never reached calculation, with reasons. */
55
+ skippedReferrals: ReferralProcessingSkip[];
56
+ }
57
+ export declare class ReferralCommissionService {
58
+ private readonly deps;
59
+ constructor(deps: ReferralCommissionServiceDeps);
60
+ static create(classOptions?: SmrtClassOptions): Promise<ReferralCommissionService>;
61
+ /**
62
+ * Turn one earning event into Commissions for every qualified referral it
63
+ * concerns.
64
+ *
65
+ * Referral resolution: explicit `referralIds` when given (rows that are
66
+ * missing / not qualified are reported in `skippedReferrals`), else
67
+ * `findQualifiedByTarget(targetKind, targetId)`. One of the two forms is
68
+ * required.
69
+ *
70
+ * Per referral:
71
+ * 1. Load its ReferralTermSnapshot (`'missing_snapshot'` skip when the
72
+ * pointer is empty/dangling).
73
+ * 2. Resolve the referrer's `earnerId`
74
+ * (`'referrer_missing_earner'` skip when absent — roles without a
75
+ * payout account cannot earn).
76
+ * 3. Delegate to `CommissionCalculationService.calculateForEvent` with
77
+ * the snapshot's plan pin, FROZEN components, currency (mismatches
78
+ * surface as the calc service's `currency_mismatch` skips),
79
+ * clearingDays, the referral's `creditFraction` as the share, its
80
+ * `splitGroupId`, the
81
+ * `('referral_term_snapshot', snapshot.id)` terms reference, and an
82
+ * occurrence resolver counting existing Commissions for
83
+ * `(termsSnapshotId, componentKey)` from PRIOR events.
84
+ *
85
+ * Fully idempotent on replay: the calculation service's dedupe keys
86
+ * return prior rows in each outcome's `existing`.
87
+ */
88
+ processEarningEvent(input: ProcessEarningEventInput): Promise<ProcessEarningEventResult>;
89
+ }
90
+ export default ReferralCommissionService;
91
+ //# sourceMappingURL=ReferralCommissionService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReferralCommissionService.d.ts","sourceRoot":"","sources":["../../../src/referrals/services/ReferralCommissionService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EACL,KAAK,UAAU,EACf,4BAA4B,EAC5B,oBAAoB,EACpB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,8BAA8B,EAAE,MAAM,kDAAkD,CAAC;AAClG,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG1E;;;GAGG;AACH,eAAO,MAAM,4BAA4B,2BAA2B,CAAC;AAErE,2DAA2D;AAC3D,MAAM,WAAW,6BAA6B;IAC5C,SAAS,EAAE,kBAAkB,CAAC;IAC9B,SAAS,EAAE,8BAA8B,CAAC;IAC1C,SAAS,EAAE,kBAAkB,CAAC;IAC9B,mEAAmE;IACnE,WAAW,EAAE,4BAA4B,CAAC;IAC1C,4EAA4E;IAC5E,WAAW,EAAE,oBAAoB,CAAC;CACnC;AAED,uEAAuE;AACvE,MAAM,WAAW,wBAAwB;IACvC,2DAA2D;IAC3D,KAAK,EAAE,YAAY,CAAC;IACpB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,sEAAsE;IACtE,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,8CAA8C;AAC9C,MAAM,MAAM,4BAA4B,GACpC,oBAAoB,GACpB,eAAe,GACf,kBAAkB,GAClB,yBAAyB,GACzB,iBAAiB,CAAC;AAEtB,gDAAgD;AAChD,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,4BAA4B,CAAC;CACtC;AAED,wCAAwC;AACxC,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,6DAA6D;IAC7D,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,yDAAyD;IACzD,OAAO,EAAE,uBAAuB,EAAE,CAAC;CACpC;AAED,uEAAuE;AACvE,MAAM,WAAW,yBAAyB;IACxC,iEAAiE;IACjE,OAAO,EAAE,yBAAyB,EAAE,CAAC;IACrC,8DAA8D;IAC9D,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;CAC5C;AAED,qBAAa,yBAAyB;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,6BAA6B;WAEnD,MAAM,CACjB,YAAY,GAAE,gBAAqB,GAClC,OAAO,CAAC,yBAAyB,CAAC;IAUrC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACG,mBAAmB,CACvB,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,yBAAyB,CAAC;CA4HtC;AAED,eAAe,yBAAyB,CAAC"}
@@ -0,0 +1,135 @@
1
+ import { SmrtClassOptions } from '@happyvertical/smrt-core';
2
+ import { CommissionPlanCollection } from '../../commissions/index.js';
3
+ import { AttributionPolicyCollection } from '../collections/AttributionPolicyCollection.js';
4
+ import { ReferralAgreementCollection } from '../collections/ReferralAgreementCollection.js';
5
+ import { ReferralCollection } from '../collections/ReferralCollection.js';
6
+ import { ReferralTermSnapshotCollection } from '../collections/ReferralTermSnapshotCollection.js';
7
+ import { ReferrerCollection } from '../collections/ReferrerCollection.js';
8
+ import { Referral } from '../models/Referral.js';
9
+ import { ReferralTermSnapshot } from '../models/ReferralTermSnapshot.js';
10
+ /** Collaborators for {@link ReferralQualificationService}. */
11
+ export interface ReferralQualificationServiceDeps {
12
+ referrals: ReferralCollection;
13
+ agreements: ReferralAgreementCollection;
14
+ /** The commissions module's plan collection (same package). */
15
+ plans: CommissionPlanCollection;
16
+ policies: AttributionPolicyCollection;
17
+ snapshots: ReferralTermSnapshotCollection;
18
+ referrers: ReferrerCollection;
19
+ }
20
+ /** Why {@link ReferralQualificationService.qualify} refused. */
21
+ export type QualificationRefusalReason = 'not_attributed' | 'existing_client_ineligible' | 'self_referral_ineligible' | 'no_active_agreement' | 'no_active_plan';
22
+ /** Input for {@link ReferralQualificationService.qualify}. */
23
+ export interface QualifyReferralInput {
24
+ referralId: string;
25
+ /** Clock override for deterministic tests. */
26
+ now?: Date;
27
+ /** Re-check flag: the prospect is already a client. */
28
+ isExistingClient?: boolean;
29
+ /** Re-check flag: the prospect's own profile id (self-referral gate). */
30
+ subjectProfileId?: string;
31
+ }
32
+ /** Result of {@link ReferralQualificationService.qualify}. */
33
+ export interface QualifyReferralResult {
34
+ /** Whether the referral is (now or already) qualified. */
35
+ qualified: boolean;
36
+ /** `true` only when THIS call minted the snapshot. */
37
+ created: boolean;
38
+ /** The governing snapshot (`null` on refusal). */
39
+ snapshot: ReferralTermSnapshot | null;
40
+ /** The (re)loaded referral (`null` only when the id is unknown). */
41
+ referral: Referral | null;
42
+ /** Why qualification was refused, when it was. */
43
+ reason?: QualificationRefusalReason;
44
+ }
45
+ /** Input for {@link ReferralQualificationService.requalify}. */
46
+ export interface RequalifyReferralInput {
47
+ referralId: string;
48
+ /** Non-empty rationale recorded in the referral metadata. Required. */
49
+ reason: string;
50
+ /** Clock override for deterministic tests. */
51
+ now?: Date;
52
+ }
53
+ /** Result of {@link ReferralQualificationService.requalify}. */
54
+ export interface RequalifyReferralResult {
55
+ /** Whether a new snapshot now governs the referral. */
56
+ requalified: boolean;
57
+ /** The NEW governing snapshot (`null` on refusal). */
58
+ snapshot: ReferralTermSnapshot | null;
59
+ /** The previously governing snapshot's id (kept as history). */
60
+ previousSnapshotId: string;
61
+ /** Why requalification was refused, when it was. */
62
+ reason?: 'no_active_agreement' | 'no_active_plan';
63
+ }
64
+ export declare class ReferralQualificationService {
65
+ private readonly deps;
66
+ constructor(deps: ReferralQualificationServiceDeps);
67
+ static create(classOptions?: SmrtClassOptions): Promise<ReferralQualificationService>;
68
+ /**
69
+ * Qualify an attributed referral.
70
+ *
71
+ * Flow:
72
+ * 1. **Status** — the referral must be `attributed`
73
+ * (`reason: 'not_attributed'` otherwise). Already `qualified` →
74
+ * IDEMPOTENT: the existing snapshot returns with `created: false`.
75
+ * 2. **Eligibility re-check** — the attribution-time policy version's
76
+ * flags are re-applied against the caller's current knowledge:
77
+ * `isExistingClient` (`existing_client_ineligible`) and
78
+ * `subjectProfileId` vs the referrer's profile
79
+ * (`self_referral_ineligible`). Refusals do NOT change the referral's
80
+ * status — disqualification stays an explicit caller decision.
81
+ * 3. **Agreement** — the ACTIVE ReferralAgreement for
82
+ * (referrerId, programId) effective at `now`
83
+ * (`reason: 'no_active_agreement'` when none).
84
+ * 4. **Plan** — the agreement's pinned `commissionPlanVersion`, or the
85
+ * latest active version when the pin is `0`; the resolved version must
86
+ * be ACTIVE (`reason: 'no_active_plan'` otherwise).
87
+ * 5. **Snapshot** — mint the immutable ReferralTermSnapshot (frozen
88
+ * component copy, currency, clearingDays, approvalMode, agreement +
89
+ * plan + policy version refs), point `referral.snapshotId` at it, and
90
+ * transition `attributed → qualified` (stamping `qualifiedAt`).
91
+ */
92
+ qualify(input: QualifyReferralInput): Promise<QualifyReferralResult>;
93
+ /**
94
+ * Explicitly re-snapshot a QUALIFIED referral under the CURRENT terms —
95
+ * the "amendment explicitly applied" path: after a plan/agreement
96
+ * amendment, earnings keep flowing through the OLD snapshot until an
97
+ * operator invokes this.
98
+ *
99
+ * Creates a NEW snapshot from the currently active agreement/plan,
100
+ * repoints `referral.snapshotId`, leaves the old snapshot row untouched
101
+ * (history — commissions it produced still reference it), and appends
102
+ * `{ at, reason, fromSnapshotId, toSnapshotId }` to the referral
103
+ * metadata's `requalifications` array.
104
+ *
105
+ * Throws on misuse (unknown referral, non-qualified status, empty
106
+ * reason); refuses with a typed reason when no active agreement/plan
107
+ * currently governs.
108
+ */
109
+ requalify(input: RequalifyReferralInput): Promise<RequalifyReferralResult>;
110
+ private requireReferral;
111
+ /**
112
+ * The exact policy version pinned on the referral, when it exists —
113
+ * resolved in the REFERRAL's tenant lane (global fallback): background
114
+ * qualification runs without ambient tenant context, and another
115
+ * tenant's same-keyed policy must never supply the eligibility flags.
116
+ */
117
+ private findPolicyVersion;
118
+ /**
119
+ * The CommissionPlan an agreement binds: the pinned version when
120
+ * `commissionPlanVersion > 0`, else the latest active version. Either
121
+ * way the resolved row must be ACTIVE — superseded/retired terms cannot
122
+ * govern a NEW qualification (an amendment should be activated, or the
123
+ * agreement re-pinned, first).
124
+ */
125
+ private resolvePlan;
126
+ /**
127
+ * Mint the immutable snapshot: agreement/plan/policy refs plus the FROZEN
128
+ * component copy and the calculation inputs. `planVersion` records the
129
+ * RESOLVED version — this is where an unpinned (`0`) agreement version
130
+ * gets pinned.
131
+ */
132
+ private mintSnapshot;
133
+ }
134
+ export default ReferralQualificationService;
135
+ //# sourceMappingURL=ReferralQualificationService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReferralQualificationService.d.ts","sourceRoot":"","sources":["../../../src/referrals/services/ReferralQualificationService.ts"],"names":[],"mappings":"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"}