@happyvertical/smrt-sales 0.40.7 → 0.40.9
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/AGENTS.md +3 -2
- package/dist/agreements.js +1 -1
- package/dist/chunks/__smrt-register__-D08SaNJE.js +6 -0
- package/dist/chunks/{__smrt-register__-D9Gim8vC.js.map → __smrt-register__-D08SaNJE.js.map} +1 -1
- package/dist/chunks/{commissions-pI_MmBxN.js → commissions-CelWwvjZ.js} +354 -74
- package/dist/chunks/commissions-CelWwvjZ.js.map +1 -0
- package/dist/chunks/{referrals-cYYg4YZw.js → referrals-BXqD65KR.js} +2 -2
- package/dist/chunks/{referrals-cYYg4YZw.js.map → referrals-BXqD65KR.js.map} +1 -1
- package/dist/commissions/collections/CommissionAdjustmentOperationCollection.d.ts +24 -0
- package/dist/commissions/collections/CommissionAdjustmentOperationCollection.d.ts.map +1 -0
- package/dist/commissions/models/CommissionAdjustment.d.ts.map +1 -1
- package/dist/commissions/models/CommissionAdjustmentOperation.d.ts +23 -0
- package/dist/commissions/models/CommissionAdjustmentOperation.d.ts.map +1 -0
- package/dist/commissions/services/CommissionAdjustmentService.d.ts +68 -0
- package/dist/commissions/services/CommissionAdjustmentService.d.ts.map +1 -0
- package/dist/commissions/services/index.d.ts +1 -0
- package/dist/commissions/services/index.d.ts.map +1 -1
- package/dist/commissions.js +3 -3
- package/dist/crm.js +1 -1
- package/dist/index.js +4 -4
- package/dist/manifest.json +221 -2
- package/dist/referrals.js +2 -2
- package/dist/smrt-knowledge.json +57 -7
- package/package.json +6 -6
- package/dist/chunks/__smrt-register__-D9Gim8vC.js +0 -6
- package/dist/chunks/commissions-pI_MmBxN.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"__smrt-register__-
|
|
1
|
+
{"version":3,"file":"__smrt-register__-D08SaNJE.js","names":[],"sources":["../../src/__smrt-register__.ts"],"sourcesContent":["import { ObjectRegistry } from '@happyvertical/smrt-core';\n\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n"],"mappings":""}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { SmrtCollection, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
|
|
2
|
-
import { TenantScoped, assertTenantReadAllowed, getCurrentTenant, tenantId } from "@happyvertical/smrt-tenancy";
|
|
2
|
+
import { TenantContextError, TenantScoped, assertTenantReadAllowed, getCurrentTenant, requireTenantId, tenantId } from "@happyvertical/smrt-tenancy";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
3
4
|
//#region src/commissions/models/CommissionAdjustment.ts
|
|
4
|
-
var __defProp$
|
|
5
|
-
var __getOwnPropDesc$
|
|
6
|
-
var __decorateClass$
|
|
7
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
5
|
+
var __defProp$7 = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __decorateClass$7 = (decorators, target, key, kind) => {
|
|
8
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
|
|
8
9
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
9
|
-
if (kind && result) __defProp$
|
|
10
|
+
if (kind && result) __defProp$7(target, key, result);
|
|
10
11
|
return result;
|
|
11
12
|
};
|
|
12
13
|
var frozenAdjustmentSnapshot = /* @__PURE__ */ new WeakMap();
|
|
@@ -30,6 +31,7 @@ var CommissionAdjustment = class extends SmrtObject {
|
|
|
30
31
|
metadata = "{}";
|
|
31
32
|
constructor(options = {}) {
|
|
32
33
|
super(options);
|
|
34
|
+
if ("operationId" in options) throw new Error("CommissionAdjustment has no public operationId field; use CommissionAdjustmentService.createAdjustment()");
|
|
33
35
|
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
34
36
|
if (options.commissionId !== void 0) this.commissionId = options.commissionId;
|
|
35
37
|
if (options.earnerId !== void 0) this.earnerId = options.earnerId;
|
|
@@ -102,13 +104,13 @@ var CommissionAdjustment = class extends SmrtObject {
|
|
|
102
104
|
});
|
|
103
105
|
}
|
|
104
106
|
};
|
|
105
|
-
__decorateClass$
|
|
106
|
-
__decorateClass$
|
|
107
|
-
__decorateClass$
|
|
108
|
-
__decorateClass$
|
|
109
|
-
__decorateClass$
|
|
110
|
-
__decorateClass$
|
|
111
|
-
CommissionAdjustment = __decorateClass$
|
|
107
|
+
__decorateClass$7([tenantId({ nullable: true })], CommissionAdjustment.prototype, "tenantId", 2);
|
|
108
|
+
__decorateClass$7([foreignKey("Commission", { required: true })], CommissionAdjustment.prototype, "commissionId", 2);
|
|
109
|
+
__decorateClass$7([foreignKey("Earner", { required: true })], CommissionAdjustment.prototype, "earnerId", 2);
|
|
110
|
+
__decorateClass$7([field({ required: true })], CommissionAdjustment.prototype, "reason", 2);
|
|
111
|
+
__decorateClass$7([crossPackageRef("@happyvertical/smrt-profiles:Profile")], CommissionAdjustment.prototype, "createdByProfileId", 2);
|
|
112
|
+
__decorateClass$7([foreignKey("CommissionPayout")], CommissionAdjustment.prototype, "payoutId", 2);
|
|
113
|
+
CommissionAdjustment = __decorateClass$7([TenantScoped({ mode: "optional" }), smrt({
|
|
112
114
|
api: { include: [
|
|
113
115
|
"create",
|
|
114
116
|
"list",
|
|
@@ -193,12 +195,12 @@ var CommissionAdjustmentCollection = class extends SmrtCollection {
|
|
|
193
195
|
};
|
|
194
196
|
//#endregion
|
|
195
197
|
//#region src/commissions/models/Commission.ts
|
|
196
|
-
var __defProp$
|
|
197
|
-
var __getOwnPropDesc$
|
|
198
|
-
var __decorateClass$
|
|
199
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
198
|
+
var __defProp$6 = Object.defineProperty;
|
|
199
|
+
var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
|
|
200
|
+
var __decorateClass$6 = (decorators, target, key, kind) => {
|
|
201
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
|
|
200
202
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
201
|
-
if (kind && result) __defProp$
|
|
203
|
+
if (kind && result) __defProp$6(target, key, result);
|
|
202
204
|
return result;
|
|
203
205
|
};
|
|
204
206
|
var COMMISSION_STATUS_TRANSITIONS = {
|
|
@@ -466,12 +468,12 @@ var Commission = class extends SmrtObject {
|
|
|
466
468
|
return null;
|
|
467
469
|
}
|
|
468
470
|
};
|
|
469
|
-
__decorateClass$
|
|
470
|
-
__decorateClass$
|
|
471
|
-
__decorateClass$
|
|
472
|
-
__decorateClass$
|
|
473
|
-
__decorateClass$
|
|
474
|
-
Commission = __decorateClass$
|
|
471
|
+
__decorateClass$6([tenantId({ nullable: true })], Commission.prototype, "tenantId", 2);
|
|
472
|
+
__decorateClass$6([foreignKey("Earner", { required: true })], Commission.prototype, "earnerId", 2);
|
|
473
|
+
__decorateClass$6([foreignKey("EarningEvent")], Commission.prototype, "earningEventId", 2);
|
|
474
|
+
__decorateClass$6([foreignKey("CommissionPayout")], Commission.prototype, "payoutId", 2);
|
|
475
|
+
__decorateClass$6([field({ required: true })], Commission.prototype, "dedupeKey", 2);
|
|
476
|
+
Commission = __decorateClass$6([TenantScoped({ mode: "optional" }), smrt({
|
|
475
477
|
conflictColumns: ["dedupe_key"],
|
|
476
478
|
api: { include: [
|
|
477
479
|
"list",
|
|
@@ -606,12 +608,12 @@ var CommissionCollection = class extends SmrtCollection {
|
|
|
606
608
|
};
|
|
607
609
|
//#endregion
|
|
608
610
|
//#region src/commissions/models/CommissionPayout.ts
|
|
609
|
-
var __defProp$
|
|
610
|
-
var __getOwnPropDesc$
|
|
611
|
-
var __decorateClass$
|
|
612
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
611
|
+
var __defProp$5 = Object.defineProperty;
|
|
612
|
+
var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
|
|
613
|
+
var __decorateClass$5 = (decorators, target, key, kind) => {
|
|
614
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
|
|
613
615
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
614
|
-
if (kind && result) __defProp$
|
|
616
|
+
if (kind && result) __defProp$5(target, key, result);
|
|
615
617
|
return result;
|
|
616
618
|
};
|
|
617
619
|
var PAYOUT_STATUS_TRANSITIONS = {
|
|
@@ -872,12 +874,12 @@ ${memo}` : memo;
|
|
|
872
874
|
return null;
|
|
873
875
|
}
|
|
874
876
|
};
|
|
875
|
-
__decorateClass$
|
|
876
|
-
__decorateClass$
|
|
877
|
-
__decorateClass$
|
|
878
|
-
__decorateClass$
|
|
879
|
-
__decorateClass$
|
|
880
|
-
CommissionPayout = __decorateClass$
|
|
877
|
+
__decorateClass$5([tenantId({ nullable: true })], CommissionPayout.prototype, "tenantId", 2);
|
|
878
|
+
__decorateClass$5([foreignKey("Earner", { required: true })], CommissionPayout.prototype, "earnerId", 2);
|
|
879
|
+
__decorateClass$5([crossPackageRef("@happyvertical/smrt-commerce:Invoice")], CommissionPayout.prototype, "invoiceId", 2);
|
|
880
|
+
__decorateClass$5([field({ required: true })], CommissionPayout.prototype, "idempotencyKey", 2);
|
|
881
|
+
__decorateClass$5([field({ indexed: true })], CommissionPayout.prototype, "sourceId", 2);
|
|
882
|
+
CommissionPayout = __decorateClass$5([TenantScoped({ mode: "optional" }), smrt({
|
|
881
883
|
conflictColumns: ["idempotency_key"],
|
|
882
884
|
api: { include: ["list", "get"] },
|
|
883
885
|
mcp: { include: ["list", "get"] },
|
|
@@ -1008,12 +1010,12 @@ var ADJUSTMENT_SETTLEABLE_COMMISSION_STATUSES = [
|
|
|
1008
1010
|
];
|
|
1009
1011
|
//#endregion
|
|
1010
1012
|
//#region src/commissions/models/CommissionPlan.ts
|
|
1011
|
-
var __defProp$
|
|
1012
|
-
var __getOwnPropDesc$
|
|
1013
|
-
var __decorateClass$
|
|
1014
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
1013
|
+
var __defProp$4 = Object.defineProperty;
|
|
1014
|
+
var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
|
|
1015
|
+
var __decorateClass$4 = (decorators, target, key, kind) => {
|
|
1016
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
|
|
1015
1017
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
1016
|
-
if (kind && result) __defProp$
|
|
1018
|
+
if (kind && result) __defProp$4(target, key, result);
|
|
1017
1019
|
return result;
|
|
1018
1020
|
};
|
|
1019
1021
|
var PLAN_STATUS_TRANSITIONS = {
|
|
@@ -1244,9 +1246,9 @@ var CommissionPlan = class extends SmrtObject {
|
|
|
1244
1246
|
return null;
|
|
1245
1247
|
}
|
|
1246
1248
|
};
|
|
1247
|
-
__decorateClass$
|
|
1248
|
-
__decorateClass$
|
|
1249
|
-
CommissionPlan = __decorateClass$
|
|
1249
|
+
__decorateClass$4([tenantId({ nullable: true })], CommissionPlan.prototype, "tenantId", 2);
|
|
1250
|
+
__decorateClass$4([field({ required: true })], CommissionPlan.prototype, "planKey", 2);
|
|
1251
|
+
CommissionPlan = __decorateClass$4([TenantScoped({ mode: "optional" }), smrt({
|
|
1250
1252
|
conflictColumns: [
|
|
1251
1253
|
"tenant_id",
|
|
1252
1254
|
"plan_key",
|
|
@@ -1351,12 +1353,12 @@ var CommissionPlanCollection = class extends SmrtCollection {
|
|
|
1351
1353
|
};
|
|
1352
1354
|
//#endregion
|
|
1353
1355
|
//#region src/commissions/models/Earner.ts
|
|
1354
|
-
var __defProp$
|
|
1355
|
-
var __getOwnPropDesc$
|
|
1356
|
-
var __decorateClass$
|
|
1357
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
1356
|
+
var __defProp$3 = Object.defineProperty;
|
|
1357
|
+
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
|
|
1358
|
+
var __decorateClass$3 = (decorators, target, key, kind) => {
|
|
1359
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
|
|
1358
1360
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
1359
|
-
if (kind && result) __defProp$
|
|
1361
|
+
if (kind && result) __defProp$3(target, key, result);
|
|
1360
1362
|
return result;
|
|
1361
1363
|
};
|
|
1362
1364
|
var Earner = class extends SmrtObject {
|
|
@@ -1422,9 +1424,9 @@ var Earner = class extends SmrtObject {
|
|
|
1422
1424
|
this.metadata = JSON.stringify(data ?? {});
|
|
1423
1425
|
}
|
|
1424
1426
|
};
|
|
1425
|
-
__decorateClass$
|
|
1426
|
-
__decorateClass$
|
|
1427
|
-
Earner = __decorateClass$
|
|
1427
|
+
__decorateClass$3([tenantId({ nullable: true })], Earner.prototype, "tenantId", 2);
|
|
1428
|
+
__decorateClass$3([crossPackageRef("@happyvertical/smrt-profiles:Profile")], Earner.prototype, "profileId", 2);
|
|
1429
|
+
Earner = __decorateClass$3([TenantScoped({ mode: "optional" }), smrt({
|
|
1428
1430
|
api: { include: [
|
|
1429
1431
|
"list",
|
|
1430
1432
|
"get",
|
|
@@ -1463,12 +1465,12 @@ var EarnerCollection = class extends SmrtCollection {
|
|
|
1463
1465
|
};
|
|
1464
1466
|
//#endregion
|
|
1465
1467
|
//#region src/commissions/models/EarnerSourceAttribution.ts
|
|
1466
|
-
var __defProp$
|
|
1467
|
-
var __getOwnPropDesc$
|
|
1468
|
-
var __decorateClass$
|
|
1469
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
1468
|
+
var __defProp$2 = Object.defineProperty;
|
|
1469
|
+
var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
|
|
1470
|
+
var __decorateClass$2 = (decorators, target, key, kind) => {
|
|
1471
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
|
|
1470
1472
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
1471
|
-
if (kind && result) __defProp$
|
|
1473
|
+
if (kind && result) __defProp$2(target, key, result);
|
|
1472
1474
|
return result;
|
|
1473
1475
|
};
|
|
1474
1476
|
var EarnerSourceAttribution = class extends SmrtObject {
|
|
@@ -1542,14 +1544,14 @@ var EarnerSourceAttribution = class extends SmrtObject {
|
|
|
1542
1544
|
if (earnerTenant !== mappingTenant) throw new Error(`EarnerSourceAttribution ${this.id ?? "<new>"}: mapping tenant '${mappingTenant ?? "global"}' does not match earner tenant '${earnerTenant ?? "global"}' \u2014 a mapping must live in its earner's tenant.`);
|
|
1543
1545
|
}
|
|
1544
1546
|
};
|
|
1545
|
-
__decorateClass$
|
|
1546
|
-
__decorateClass$
|
|
1547
|
-
__decorateClass$
|
|
1548
|
-
__decorateClass$
|
|
1547
|
+
__decorateClass$2([tenantId({ nullable: true })], EarnerSourceAttribution.prototype, "tenantId", 2);
|
|
1548
|
+
__decorateClass$2([foreignKey("Earner", { required: true })], EarnerSourceAttribution.prototype, "earnerId", 2);
|
|
1549
|
+
__decorateClass$2([field({ required: true })], EarnerSourceAttribution.prototype, "sourceKind", 2);
|
|
1550
|
+
__decorateClass$2([field({
|
|
1549
1551
|
required: true,
|
|
1550
1552
|
indexed: true
|
|
1551
1553
|
})], EarnerSourceAttribution.prototype, "sourceId", 2);
|
|
1552
|
-
EarnerSourceAttribution = __decorateClass$
|
|
1554
|
+
EarnerSourceAttribution = __decorateClass$2([TenantScoped({ mode: "optional" }), smrt({
|
|
1553
1555
|
conflictColumns: [
|
|
1554
1556
|
"tenant_id",
|
|
1555
1557
|
"source_kind",
|
|
@@ -1615,12 +1617,12 @@ var EarnerSourceAttributionCollection = class extends SmrtCollection {
|
|
|
1615
1617
|
};
|
|
1616
1618
|
//#endregion
|
|
1617
1619
|
//#region src/commissions/models/EarningEvent.ts
|
|
1618
|
-
var __defProp = Object.defineProperty;
|
|
1619
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
1620
|
-
var __decorateClass = (decorators, target, key, kind) => {
|
|
1621
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
1620
|
+
var __defProp$1 = Object.defineProperty;
|
|
1621
|
+
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
1622
|
+
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
1623
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
|
1622
1624
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
1623
|
-
if (kind && result) __defProp(target, key, result);
|
|
1625
|
+
if (kind && result) __defProp$1(target, key, result);
|
|
1624
1626
|
return result;
|
|
1625
1627
|
};
|
|
1626
1628
|
var persistedEventState = /* @__PURE__ */ new WeakMap();
|
|
@@ -1768,18 +1770,18 @@ var EarningEvent = class extends SmrtObject {
|
|
|
1768
1770
|
return null;
|
|
1769
1771
|
}
|
|
1770
1772
|
};
|
|
1771
|
-
__decorateClass([tenantId({ nullable: true })], EarningEvent.prototype, "tenantId", 2);
|
|
1772
|
-
__decorateClass([field({ required: true })], EarningEvent.prototype, "eventKind", 2);
|
|
1773
|
-
__decorateClass([field({
|
|
1773
|
+
__decorateClass$1([tenantId({ nullable: true })], EarningEvent.prototype, "tenantId", 2);
|
|
1774
|
+
__decorateClass$1([field({ required: true })], EarningEvent.prototype, "eventKind", 2);
|
|
1775
|
+
__decorateClass$1([field({
|
|
1774
1776
|
type: "integer",
|
|
1775
1777
|
nullable: true
|
|
1776
1778
|
})], EarningEvent.prototype, "netAmountCents", 2);
|
|
1777
|
-
__decorateClass([field({
|
|
1779
|
+
__decorateClass$1([field({
|
|
1778
1780
|
type: "integer",
|
|
1779
1781
|
nullable: true
|
|
1780
1782
|
})], EarningEvent.prototype, "marginCents", 2);
|
|
1781
|
-
__decorateClass([field({ required: true })], EarningEvent.prototype, "dedupeKey", 2);
|
|
1782
|
-
EarningEvent = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
1783
|
+
__decorateClass$1([field({ required: true })], EarningEvent.prototype, "dedupeKey", 2);
|
|
1784
|
+
EarningEvent = __decorateClass$1([TenantScoped({ mode: "optional" }), smrt({
|
|
1783
1785
|
conflictColumns: ["dedupe_key"],
|
|
1784
1786
|
api: { include: [
|
|
1785
1787
|
"create",
|
|
@@ -1861,6 +1863,284 @@ function calculateCommissionAmountCents(baseCents, rate, shareFraction) {
|
|
|
1861
1863
|
return roundCents(baseCents * rate * (shareFraction ?? 1));
|
|
1862
1864
|
}
|
|
1863
1865
|
//#endregion
|
|
1866
|
+
//#region src/commissions/models/CommissionAdjustmentOperation.ts
|
|
1867
|
+
var __defProp = Object.defineProperty;
|
|
1868
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
1869
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
1870
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
1871
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
1872
|
+
if (kind && result) __defProp(target, key, result);
|
|
1873
|
+
return result;
|
|
1874
|
+
};
|
|
1875
|
+
var CommissionAdjustmentOperation = class extends SmrtObject {
|
|
1876
|
+
tenantId = "";
|
|
1877
|
+
adjustmentId;
|
|
1878
|
+
constructor(options = {}) {
|
|
1879
|
+
super(options);
|
|
1880
|
+
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
1881
|
+
if (options.adjustmentId !== void 0) this.adjustmentId = options.adjustmentId;
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
__decorateClass([tenantId()], CommissionAdjustmentOperation.prototype, "tenantId", 2);
|
|
1885
|
+
__decorateClass([field({
|
|
1886
|
+
sqlType: "UUID",
|
|
1887
|
+
required: true,
|
|
1888
|
+
readonly: true,
|
|
1889
|
+
indexed: true
|
|
1890
|
+
})], CommissionAdjustmentOperation.prototype, "adjustmentId", 2);
|
|
1891
|
+
CommissionAdjustmentOperation = __decorateClass([TenantScoped({ mode: "required" }), smrt({
|
|
1892
|
+
api: false,
|
|
1893
|
+
mcp: false,
|
|
1894
|
+
cli: false
|
|
1895
|
+
})], CommissionAdjustmentOperation);
|
|
1896
|
+
//#endregion
|
|
1897
|
+
//#region src/commissions/collections/CommissionAdjustmentOperationCollection.ts
|
|
1898
|
+
var CommissionAdjustmentOperationCollection = class extends SmrtCollection {
|
|
1899
|
+
static _itemClass = CommissionAdjustmentOperation;
|
|
1900
|
+
/** Tenant-scoped lookup; foreign-tenant operation payloads stay invisible. */
|
|
1901
|
+
async findByOperationId(operationId) {
|
|
1902
|
+
const tenantId = requireTenantId();
|
|
1903
|
+
const [operation] = await this.query(`SELECT
|
|
1904
|
+
id, slug, context, created_at, updated_at, tenant_id,
|
|
1905
|
+
CAST(adjustment_id AS TEXT) AS adjustment_id
|
|
1906
|
+
FROM ${this.tableName}
|
|
1907
|
+
WHERE id = ? AND tenant_id = ?
|
|
1908
|
+
LIMIT 1`, [operationId, tenantId], { allowRawOnTenantScoped: true });
|
|
1909
|
+
return operation ?? null;
|
|
1910
|
+
}
|
|
1911
|
+
/**
|
|
1912
|
+
* Claim the globally unique operation UUID without changing an existing
|
|
1913
|
+
* winner. This must run inside the same transaction that creates the
|
|
1914
|
+
* corresponding adjustment.
|
|
1915
|
+
*/
|
|
1916
|
+
async claim(input) {
|
|
1917
|
+
if (requireTenantId().toLowerCase() !== input.tenantId.toLowerCase()) throw new Error("CommissionAdjustment operation tenant mismatch");
|
|
1918
|
+
const inserted = await this.query(`INSERT INTO ${this.tableName} (
|
|
1919
|
+
id, slug, context, tenant_id, adjustment_id
|
|
1920
|
+
) VALUES (?, ?, ?, ?, ?)
|
|
1921
|
+
ON CONFLICT (id) DO NOTHING
|
|
1922
|
+
RETURNING id`, [
|
|
1923
|
+
input.operationId,
|
|
1924
|
+
input.operationId,
|
|
1925
|
+
"",
|
|
1926
|
+
input.tenantId,
|
|
1927
|
+
input.adjustmentId
|
|
1928
|
+
], { allowRawOnTenantScoped: true });
|
|
1929
|
+
return {
|
|
1930
|
+
operation: await this.findByOperationId(input.operationId),
|
|
1931
|
+
claimed: inserted.length === 1
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
};
|
|
1935
|
+
//#endregion
|
|
1936
|
+
//#region src/commissions/services/CommissionAdjustmentService.ts
|
|
1937
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
1938
|
+
var CommissionAdjustmentReplayConflictError = class extends Error {
|
|
1939
|
+
constructor(operationId, mismatches) {
|
|
1940
|
+
super(`Commission adjustment operation '${operationId}' was already used with different immutable ${mismatches.length === 1 ? "field" : "fields"}: ` + mismatches.join(", "));
|
|
1941
|
+
this.operationId = operationId;
|
|
1942
|
+
this.mismatches = mismatches;
|
|
1943
|
+
this.name = "CommissionAdjustmentReplayConflictError";
|
|
1944
|
+
}
|
|
1945
|
+
operationId;
|
|
1946
|
+
mismatches;
|
|
1947
|
+
code = "COMMISSION_ADJUSTMENT_REPLAY_CONFLICT";
|
|
1948
|
+
};
|
|
1949
|
+
var CommissionAdjustmentValidationError = class extends Error {
|
|
1950
|
+
constructor(reason, message) {
|
|
1951
|
+
super(message);
|
|
1952
|
+
this.reason = reason;
|
|
1953
|
+
this.name = "CommissionAdjustmentValidationError";
|
|
1954
|
+
}
|
|
1955
|
+
reason;
|
|
1956
|
+
code = "COMMISSION_ADJUSTMENT_VALIDATION_ERROR";
|
|
1957
|
+
};
|
|
1958
|
+
var CommissionAdjustmentService = class CommissionAdjustmentService {
|
|
1959
|
+
constructor(deps) {
|
|
1960
|
+
this.deps = deps;
|
|
1961
|
+
}
|
|
1962
|
+
deps;
|
|
1963
|
+
static async create(options = {}) {
|
|
1964
|
+
return new CommissionAdjustmentService({
|
|
1965
|
+
commissions: await CommissionCollection.create(options),
|
|
1966
|
+
adjustments: await CommissionAdjustmentCollection.create(options),
|
|
1967
|
+
operations: await CommissionAdjustmentOperationCollection.create(options),
|
|
1968
|
+
earners: await EarnerCollection.create(options)
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
1971
|
+
/**
|
|
1972
|
+
* Create exactly one immutable adjustment for `operationId`.
|
|
1973
|
+
*
|
|
1974
|
+
* The operation fence table's primary UUID is the serialization point. The
|
|
1975
|
+
* fence and adjustment are committed in one transaction. An exact replay
|
|
1976
|
+
* returns the persisted row; any changed immutable input raises
|
|
1977
|
+
* {@link CommissionAdjustmentReplayConflictError}. The claim primitive uses
|
|
1978
|
+
* `ON CONFLICT DO NOTHING`, so a losing PostgreSQL transaction remains
|
|
1979
|
+
* usable and can read/verify the committed winner rather than entering an
|
|
1980
|
+
* aborted transaction state.
|
|
1981
|
+
*/
|
|
1982
|
+
async createAdjustment(input) {
|
|
1983
|
+
const intent = this.canonicalize(input);
|
|
1984
|
+
this.assertTenant(intent.tenantId);
|
|
1985
|
+
return await this.runTransaction(async (deps) => {
|
|
1986
|
+
const existingOperation = await deps.operations.findByOperationId(intent.operationId);
|
|
1987
|
+
if (existingOperation) return await this.replayFromOperation(deps, existingOperation, intent);
|
|
1988
|
+
await this.assertParentAndEarner(deps, intent);
|
|
1989
|
+
const adjustmentId = randomUUID();
|
|
1990
|
+
const claimed = await deps.operations.claim({
|
|
1991
|
+
operationId: intent.operationId,
|
|
1992
|
+
tenantId: intent.tenantId,
|
|
1993
|
+
adjustmentId
|
|
1994
|
+
});
|
|
1995
|
+
if (!claimed.operation) throw new CommissionAdjustmentReplayConflictError(intent.operationId, ["tenantId"]);
|
|
1996
|
+
if (!claimed.claimed) return await this.replayFromOperation(deps, claimed.operation, intent);
|
|
1997
|
+
const { operationId: _operationId, ...adjustmentIntent } = intent;
|
|
1998
|
+
const adjustment = await deps.adjustments.create({
|
|
1999
|
+
id: adjustmentId,
|
|
2000
|
+
...adjustmentIntent
|
|
2001
|
+
});
|
|
2002
|
+
this.assertExactReplay(adjustment, intent);
|
|
2003
|
+
return {
|
|
2004
|
+
adjustment,
|
|
2005
|
+
created: true
|
|
2006
|
+
};
|
|
2007
|
+
});
|
|
2008
|
+
}
|
|
2009
|
+
canonicalize(input) {
|
|
2010
|
+
this.assertUuid(input.operationId, "invalid_operation_id", "operationId");
|
|
2011
|
+
this.assertUuid(input.tenantId, "invalid_tenant_id", "tenantId");
|
|
2012
|
+
if (input.tenantId !== input.tenantId.toLowerCase()) throw new CommissionAdjustmentValidationError("invalid_tenant_id", "Commission adjustment tenantId must use canonical lowercase UUID casing");
|
|
2013
|
+
this.assertUuid(input.commissionId, "invalid_commission_id", "commissionId");
|
|
2014
|
+
this.assertUuid(input.earnerId, "invalid_earner_id", "earnerId");
|
|
2015
|
+
this.assertUuid(input.createdByProfileId, "invalid_operator_profile_id", "createdByProfileId");
|
|
2016
|
+
if (!COMMISSION_ADJUSTMENT_KINDS.includes(input.adjustmentKind)) throw new CommissionAdjustmentValidationError("invalid_adjustment_kind", `Unknown commission adjustment kind '${String(input.adjustmentKind)}'`);
|
|
2017
|
+
if (!Number.isSafeInteger(input.amountCents) || input.amountCents === 0) throw new CommissionAdjustmentValidationError("invalid_amount", "Commission adjustment amountCents must be a non-zero safe integer");
|
|
2018
|
+
const currency = input.currency.trim().toUpperCase();
|
|
2019
|
+
if (!/^[A-Z]{3}$/.test(currency)) throw new CommissionAdjustmentValidationError("invalid_currency", "Commission adjustment currency must be a three-letter ISO code");
|
|
2020
|
+
const reason = input.reason.trim();
|
|
2021
|
+
if (!reason) throw new CommissionAdjustmentValidationError("reason_required", "Commission adjustment reason is required");
|
|
2022
|
+
return {
|
|
2023
|
+
operationId: input.operationId.toLowerCase(),
|
|
2024
|
+
tenantId: input.tenantId.toLowerCase(),
|
|
2025
|
+
commissionId: input.commissionId.toLowerCase(),
|
|
2026
|
+
earnerId: input.earnerId.toLowerCase(),
|
|
2027
|
+
adjustmentKind: input.adjustmentKind,
|
|
2028
|
+
amountCents: input.amountCents,
|
|
2029
|
+
currency,
|
|
2030
|
+
reason,
|
|
2031
|
+
createdByProfileId: input.createdByProfileId.toLowerCase(),
|
|
2032
|
+
metadata: this.canonicalMetadata(input.metadata === void 0 ? {} : input.metadata)
|
|
2033
|
+
};
|
|
2034
|
+
}
|
|
2035
|
+
assertTenant(tenantId) {
|
|
2036
|
+
let activeTenantId;
|
|
2037
|
+
try {
|
|
2038
|
+
activeTenantId = requireTenantId();
|
|
2039
|
+
} catch (error) {
|
|
2040
|
+
if (!(error instanceof TenantContextError)) throw error;
|
|
2041
|
+
throw new CommissionAdjustmentValidationError("tenant_context_mismatch", "Commission adjustment creation requires an active tenant context");
|
|
2042
|
+
}
|
|
2043
|
+
if (activeTenantId !== activeTenantId.toLowerCase() || activeTenantId !== tenantId) throw new CommissionAdjustmentValidationError("tenant_context_mismatch", "Commission adjustment tenant must exactly match the canonical lowercase active tenant");
|
|
2044
|
+
}
|
|
2045
|
+
async assertParentAndEarner(deps, intent) {
|
|
2046
|
+
const commission = await deps.commissions.get({ id: intent.commissionId });
|
|
2047
|
+
if (!commission) throw new CommissionAdjustmentValidationError("commission_not_found", `Commission '${intent.commissionId}' was not found in the active tenant`);
|
|
2048
|
+
if (commission.tenantId?.toLowerCase() !== intent.tenantId) throw new CommissionAdjustmentValidationError("commission_tenant_mismatch", "Commission does not belong to the adjustment tenant");
|
|
2049
|
+
if (commission.earnerId.toLowerCase() !== intent.earnerId) throw new CommissionAdjustmentValidationError("earner_mismatch", `Adjustment earner '${intent.earnerId}' does not match Commission earner '${commission.earnerId}'`);
|
|
2050
|
+
if (commission.currency.toUpperCase() !== intent.currency) throw new CommissionAdjustmentValidationError("currency_mismatch", `Adjustment currency '${intent.currency}' does not match Commission currency '${commission.currency}'`);
|
|
2051
|
+
const earner = await deps.earners.get({ id: intent.earnerId });
|
|
2052
|
+
if (!earner) throw new CommissionAdjustmentValidationError("earner_not_found", `Earner '${intent.earnerId}' was not found in the active tenant`);
|
|
2053
|
+
if (earner.tenantId?.toLowerCase() !== intent.tenantId) throw new CommissionAdjustmentValidationError("earner_tenant_mismatch", "Earner does not belong to the adjustment tenant");
|
|
2054
|
+
}
|
|
2055
|
+
assertExactReplay(existing, intent) {
|
|
2056
|
+
const mismatches = [];
|
|
2057
|
+
if (existing.tenantId?.toLowerCase() !== intent.tenantId) mismatches.push("tenantId");
|
|
2058
|
+
if (existing.commissionId.toLowerCase() !== intent.commissionId) mismatches.push("commissionId");
|
|
2059
|
+
if (existing.earnerId.toLowerCase() !== intent.earnerId) mismatches.push("earnerId");
|
|
2060
|
+
if (existing.adjustmentKind !== intent.adjustmentKind) mismatches.push("adjustmentKind");
|
|
2061
|
+
if (existing.amountCents !== intent.amountCents) mismatches.push("amountCents");
|
|
2062
|
+
if (existing.currency.toUpperCase() !== intent.currency) mismatches.push("currency");
|
|
2063
|
+
if (existing.reason !== intent.reason) mismatches.push("reason");
|
|
2064
|
+
if (existing.createdByProfileId.toLowerCase() !== intent.createdByProfileId) mismatches.push("createdByProfileId");
|
|
2065
|
+
if (canonicalizePersistedJson(existing.metadata) !== intent.metadata) mismatches.push("metadata");
|
|
2066
|
+
if (mismatches.length > 0) throw new CommissionAdjustmentReplayConflictError(intent.operationId, mismatches);
|
|
2067
|
+
}
|
|
2068
|
+
assertUuid(value, reason, field) {
|
|
2069
|
+
if (typeof value !== "string" || !UUID_RE.test(value)) throw new CommissionAdjustmentValidationError(reason, `Commission adjustment ${field} must be a UUID`);
|
|
2070
|
+
}
|
|
2071
|
+
canonicalMetadata(metadata) {
|
|
2072
|
+
try {
|
|
2073
|
+
if (!isPlainJsonObject(metadata)) throw new TypeError("metadata must be a plain JSON object");
|
|
2074
|
+
return stableJson(metadata);
|
|
2075
|
+
} catch (error) {
|
|
2076
|
+
throw new CommissionAdjustmentValidationError("invalid_metadata", `Commission adjustment metadata must be JSON-serializable: ${error instanceof Error ? error.message : String(error)}`);
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
async replayFromOperation(deps, operation, intent) {
|
|
2080
|
+
const adjustment = await deps.adjustments.get({ id: operation.adjustmentId });
|
|
2081
|
+
if (!adjustment) throw new CommissionAdjustmentValidationError("operation_adjustment_missing", `Commission adjustment operation '${intent.operationId}' has no visible adjustment`);
|
|
2082
|
+
this.assertExactReplay(adjustment, intent);
|
|
2083
|
+
return {
|
|
2084
|
+
adjustment,
|
|
2085
|
+
created: false
|
|
2086
|
+
};
|
|
2087
|
+
}
|
|
2088
|
+
async runTransaction(fn) {
|
|
2089
|
+
const db = this.deps.adjustments.db;
|
|
2090
|
+
if (typeof db.transaction !== "function") throw new CommissionAdjustmentValidationError("transaction_unavailable", "Commission adjustment creation requires a transaction-capable database adapter");
|
|
2091
|
+
return await db.transaction(async (tx) => fn({
|
|
2092
|
+
commissions: await CommissionCollection.create({ db: tx }),
|
|
2093
|
+
adjustments: await CommissionAdjustmentCollection.create({ db: tx }),
|
|
2094
|
+
operations: await CommissionAdjustmentOperationCollection.create({ db: tx }),
|
|
2095
|
+
earners: await EarnerCollection.create({ db: tx })
|
|
2096
|
+
}));
|
|
2097
|
+
}
|
|
2098
|
+
};
|
|
2099
|
+
function canonicalizePersistedJson(value) {
|
|
2100
|
+
try {
|
|
2101
|
+
return stableJson(JSON.parse(value));
|
|
2102
|
+
} catch {
|
|
2103
|
+
return value;
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
function stableJson(value) {
|
|
2107
|
+
return JSON.stringify(sortJsonValue(value, /* @__PURE__ */ new Set()));
|
|
2108
|
+
}
|
|
2109
|
+
function isPlainJsonObject(value) {
|
|
2110
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2111
|
+
const prototype = Object.getPrototypeOf(value);
|
|
2112
|
+
return prototype === Object.prototype || prototype === null;
|
|
2113
|
+
}
|
|
2114
|
+
function sortJsonValue(value, ancestors) {
|
|
2115
|
+
if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) return value;
|
|
2116
|
+
if (Array.isArray(value)) {
|
|
2117
|
+
if (ancestors.has(value)) throw new TypeError("metadata must be acyclic");
|
|
2118
|
+
ancestors.add(value);
|
|
2119
|
+
try {
|
|
2120
|
+
return value.map((item) => sortJsonValue(item, ancestors));
|
|
2121
|
+
} finally {
|
|
2122
|
+
ancestors.delete(value);
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
if (value && typeof value === "object") {
|
|
2126
|
+
const prototype = Object.getPrototypeOf(value);
|
|
2127
|
+
if (prototype !== Object.prototype && prototype !== null) throw new TypeError("metadata objects must be plain JSON objects");
|
|
2128
|
+
if (ancestors.has(value)) throw new TypeError("metadata must be acyclic");
|
|
2129
|
+
ancestors.add(value);
|
|
2130
|
+
try {
|
|
2131
|
+
const sorted = /* @__PURE__ */ Object.create(null);
|
|
2132
|
+
for (const key of Object.keys(value).sort()) {
|
|
2133
|
+
const item = value[key];
|
|
2134
|
+
if (item !== void 0) sorted[key] = sortJsonValue(item, ancestors);
|
|
2135
|
+
}
|
|
2136
|
+
return sorted;
|
|
2137
|
+
} finally {
|
|
2138
|
+
ancestors.delete(value);
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
throw new TypeError("metadata must contain only JSON values");
|
|
2142
|
+
}
|
|
2143
|
+
//#endregion
|
|
1864
2144
|
//#region src/commissions/services/CommissionBalanceService.ts
|
|
1865
2145
|
var CommissionBalanceService = class CommissionBalanceService {
|
|
1866
2146
|
constructor(commissions, adjustments) {
|
|
@@ -3270,6 +3550,6 @@ var EarnerAttributionService = class EarnerAttributionService {
|
|
|
3270
3550
|
}
|
|
3271
3551
|
};
|
|
3272
3552
|
//#endregion
|
|
3273
|
-
export {
|
|
3553
|
+
export { EARNING_EVENT_KINDS as A, COMMISSION_ADJUSTMENT_KINDS as C, COMMISSION_STATUSES as D, COMMISSION_PLAN_STATUSES as E, Commission as F, CommissionAdjustmentCollection as I, CommissionAdjustment as L, CommissionPayoutCollection as M, CommissionPayout as N, EARNER_SOURCE_ATTRIBUTION_STATUSES as O, CommissionCollection as P, ADJUSTMENT_SETTLEABLE_COMMISSION_STATUSES as S, COMMISSION_PAYOUT_STATUSES as T, EarnerCollection as _, CommissionBalanceService as a, CommissionPlan as b, CommissionAdjustmentValidationError as c, centsToAmount as d, roundCents as f, EarnerSourceAttribution as g, EarnerSourceAttributionCollection as h, CommissionCalculationService as i, PAYOUT_METHODS as j, EARNER_STATUSES as k, amountToCents as l, EarningEvent as m, CommissionSettlementService as n, CommissionAdjustmentReplayConflictError as o, EarningEventCollection as p, CommissionPayoutService as r, CommissionAdjustmentService as s, EarnerAttributionService as t, calculateCommissionAmountCents as u, Earner as v, COMMISSION_BASES as w, validateCommissionPlanComponents as x, CommissionPlanCollection as y };
|
|
3274
3554
|
|
|
3275
|
-
//# sourceMappingURL=commissions-
|
|
3555
|
+
//# sourceMappingURL=commissions-CelWwvjZ.js.map
|