@classytic/revenue 0.2.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +498 -501
- package/dist/actions-CwG-b7fR.d.ts +519 -0
- package/dist/core/index.d.ts +884 -0
- package/dist/core/index.js +2941 -0
- package/dist/core/index.js.map +1 -0
- package/dist/enums/index.d.ts +130 -0
- package/dist/enums/index.js +167 -0
- package/dist/enums/index.js.map +1 -0
- package/dist/index-BnJWVXuw.d.ts +378 -0
- package/dist/index-ChVD3P9k.d.ts +504 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +4353 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/index.d.ts +132 -0
- package/dist/providers/index.js +122 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/retry-80lBCmSe.d.ts +234 -0
- package/dist/schemas/index.d.ts +894 -0
- package/dist/schemas/index.js +524 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/validation.d.ts +309 -0
- package/dist/schemas/validation.js +249 -0
- package/dist/schemas/validation.js.map +1 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +1632 -0
- package/dist/services/index.js.map +1 -0
- package/dist/split.enums-DHdM1YAV.d.ts +255 -0
- package/dist/split.schema-BPdFZMbU.d.ts +958 -0
- package/dist/utils/index.d.ts +24 -0
- package/dist/utils/index.js +1067 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +48 -32
- package/core/builder.js +0 -219
- package/core/container.js +0 -119
- package/core/errors.js +0 -262
- package/dist/types/core/builder.d.ts +0 -97
- package/dist/types/core/container.d.ts +0 -57
- package/dist/types/core/errors.d.ts +0 -122
- package/dist/types/enums/escrow.enums.d.ts +0 -24
- package/dist/types/enums/index.d.ts +0 -69
- package/dist/types/enums/monetization.enums.d.ts +0 -6
- package/dist/types/enums/payment.enums.d.ts +0 -16
- package/dist/types/enums/split.enums.d.ts +0 -25
- package/dist/types/enums/subscription.enums.d.ts +0 -15
- package/dist/types/enums/transaction.enums.d.ts +0 -24
- package/dist/types/index.d.ts +0 -22
- package/dist/types/providers/base.d.ts +0 -128
- package/dist/types/schemas/escrow/hold.schema.d.ts +0 -54
- package/dist/types/schemas/escrow/index.d.ts +0 -6
- package/dist/types/schemas/index.d.ts +0 -506
- package/dist/types/schemas/split/index.d.ts +0 -8
- package/dist/types/schemas/split/split.schema.d.ts +0 -142
- package/dist/types/schemas/subscription/index.d.ts +0 -152
- package/dist/types/schemas/subscription/info.schema.d.ts +0 -128
- package/dist/types/schemas/subscription/plan.schema.d.ts +0 -39
- package/dist/types/schemas/transaction/common.schema.d.ts +0 -12
- package/dist/types/schemas/transaction/gateway.schema.d.ts +0 -86
- package/dist/types/schemas/transaction/index.d.ts +0 -202
- package/dist/types/schemas/transaction/payment.schema.d.ts +0 -145
- package/dist/types/services/escrow.service.d.ts +0 -51
- package/dist/types/services/monetization.service.d.ts +0 -193
- package/dist/types/services/payment.service.d.ts +0 -117
- package/dist/types/services/transaction.service.d.ts +0 -40
- package/dist/types/utils/category-resolver.d.ts +0 -46
- package/dist/types/utils/commission-split.d.ts +0 -56
- package/dist/types/utils/commission.d.ts +0 -29
- package/dist/types/utils/hooks.d.ts +0 -17
- package/dist/types/utils/index.d.ts +0 -6
- package/dist/types/utils/logger.d.ts +0 -12
- package/dist/types/utils/subscription/actions.d.ts +0 -28
- package/dist/types/utils/subscription/index.d.ts +0 -2
- package/dist/types/utils/subscription/period.d.ts +0 -47
- package/dist/types/utils/transaction-type.d.ts +0 -102
- package/enums/escrow.enums.js +0 -36
- package/enums/index.d.ts +0 -116
- package/enums/index.js +0 -110
- package/enums/monetization.enums.js +0 -15
- package/enums/payment.enums.js +0 -64
- package/enums/split.enums.js +0 -37
- package/enums/subscription.enums.js +0 -33
- package/enums/transaction.enums.js +0 -69
- package/index.js +0 -76
- package/providers/base.js +0 -162
- package/schemas/escrow/hold.schema.js +0 -62
- package/schemas/escrow/index.js +0 -15
- package/schemas/index.d.ts +0 -33
- package/schemas/index.js +0 -27
- package/schemas/split/index.js +0 -16
- package/schemas/split/split.schema.js +0 -86
- package/schemas/subscription/index.js +0 -17
- package/schemas/subscription/info.schema.js +0 -115
- package/schemas/subscription/plan.schema.js +0 -48
- package/schemas/transaction/common.schema.js +0 -22
- package/schemas/transaction/gateway.schema.js +0 -69
- package/schemas/transaction/index.js +0 -20
- package/schemas/transaction/payment.schema.js +0 -110
- package/services/escrow.service.js +0 -353
- package/services/monetization.service.js +0 -675
- package/services/payment.service.js +0 -535
- package/services/transaction.service.js +0 -142
- package/utils/category-resolver.js +0 -74
- package/utils/commission-split.js +0 -180
- package/utils/commission.js +0 -83
- package/utils/hooks.js +0 -44
- package/utils/index.d.ts +0 -164
- package/utils/index.js +0 -16
- package/utils/logger.js +0 -36
- package/utils/subscription/actions.js +0 -68
- package/utils/subscription/index.js +0 -20
- package/utils/subscription/period.js +0 -123
- package/utils/transaction-type.js +0 -254
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Category Resolver Utility
|
|
3
|
-
* @classytic/revenue
|
|
4
|
-
*
|
|
5
|
-
* Resolves transaction category based on referenceModel and categoryMappings
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { LIBRARY_CATEGORIES } from '../enums/transaction.enums.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Resolve category for a transaction based on entity and monetizationType
|
|
12
|
-
*
|
|
13
|
-
* Resolution Logic:
|
|
14
|
-
* 1. If categoryMappings[entity] exists → use it
|
|
15
|
-
* 2. Otherwise → fall back to default library category
|
|
16
|
-
*
|
|
17
|
-
* @param {String} entity - The logical entity/identifier (e.g., 'Order', 'PlatformSubscription', 'Membership')
|
|
18
|
-
* NOTE: This is NOT a database model name - it's just a logical identifier
|
|
19
|
-
* @param {String} monetizationType - The monetization type ('subscription', 'purchase', 'free')
|
|
20
|
-
* @param {Object} categoryMappings - User-defined category mappings from config
|
|
21
|
-
* @returns {String} Category name for the transaction
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* // With mapping defined
|
|
25
|
-
* resolveCategory('Order', 'subscription', { Order: 'order_subscription' })
|
|
26
|
-
* // Returns: 'order_subscription'
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* // Without mapping, falls back to library default
|
|
30
|
-
* resolveCategory('Order', 'subscription', {})
|
|
31
|
-
* // Returns: 'subscription'
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* // Different entities with different mappings
|
|
35
|
-
* const mappings = {
|
|
36
|
-
* Order: 'order_subscription',
|
|
37
|
-
* PlatformSubscription: 'platform_subscription',
|
|
38
|
-
* TenantUpgrade: 'tenant_upgrade',
|
|
39
|
-
* Membership: 'gym_membership',
|
|
40
|
-
* Enrollment: 'course_enrollment',
|
|
41
|
-
* };
|
|
42
|
-
* resolveCategory('PlatformSubscription', 'subscription', mappings)
|
|
43
|
-
* // Returns: 'platform_subscription'
|
|
44
|
-
*/
|
|
45
|
-
export function resolveCategory(entity, monetizationType, categoryMappings = {}) {
|
|
46
|
-
// If user has defined a custom mapping for this entity, use it
|
|
47
|
-
if (entity && categoryMappings[entity]) {
|
|
48
|
-
return categoryMappings[entity];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Otherwise, fall back to library default based on monetization type
|
|
52
|
-
switch (monetizationType) {
|
|
53
|
-
case 'subscription':
|
|
54
|
-
return LIBRARY_CATEGORIES.SUBSCRIPTION; // 'subscription'
|
|
55
|
-
case 'purchase':
|
|
56
|
-
return LIBRARY_CATEGORIES.PURCHASE; // 'purchase'
|
|
57
|
-
default:
|
|
58
|
-
return LIBRARY_CATEGORIES.SUBSCRIPTION; // Default to subscription
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Validate that a category is defined in user's Transaction model enum
|
|
64
|
-
* This is informational - actual validation happens at Mongoose schema level
|
|
65
|
-
*
|
|
66
|
-
* @param {String} category - Category to validate
|
|
67
|
-
* @param {Array<String>} allowedCategories - List of allowed categories
|
|
68
|
-
* @returns {Boolean} Whether category is valid
|
|
69
|
-
*/
|
|
70
|
-
export function isCategoryValid(category, allowedCategories = []) {
|
|
71
|
-
return allowedCategories.includes(category);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export default resolveCategory;
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Commission Split Utilities
|
|
3
|
-
* @classytic/revenue
|
|
4
|
-
*
|
|
5
|
-
* Multi-party commission split calculation for affiliate/referral systems
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { SPLIT_TYPE, SPLIT_STATUS } from '../enums/split.enums.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Calculate multi-party commission splits
|
|
12
|
-
*
|
|
13
|
-
* @param {Number} amount - Transaction amount
|
|
14
|
-
* @param {Array} splitRules - Split configuration
|
|
15
|
-
* @param {Number} gatewayFeeRate - Gateway fee rate (optional)
|
|
16
|
-
* @returns {Array} Split objects
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* calculateSplits(1000, [
|
|
20
|
-
* { type: 'platform_commission', recipientId: 'platform', recipientType: 'platform', rate: 0.10 },
|
|
21
|
-
* { type: 'affiliate_commission', recipientId: 'affiliate-123', recipientType: 'user', rate: 0.02 },
|
|
22
|
-
* ], 0.018);
|
|
23
|
-
*
|
|
24
|
-
* Returns:
|
|
25
|
-
* [
|
|
26
|
-
* { type: 'platform_commission', recipientId: 'platform', grossAmount: 100, gatewayFeeAmount: 18, netAmount: 82, ... },
|
|
27
|
-
* { type: 'affiliate_commission', recipientId: 'affiliate-123', grossAmount: 20, gatewayFeeAmount: 0, netAmount: 20, ... },
|
|
28
|
-
* ]
|
|
29
|
-
*/
|
|
30
|
-
export function calculateSplits(amount, splitRules = [], gatewayFeeRate = 0) {
|
|
31
|
-
if (!splitRules || splitRules.length === 0) {
|
|
32
|
-
return [];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (amount < 0) {
|
|
36
|
-
throw new Error('Transaction amount cannot be negative');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (gatewayFeeRate < 0 || gatewayFeeRate > 1) {
|
|
40
|
-
throw new Error('Gateway fee rate must be between 0 and 1');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const totalRate = splitRules.reduce((sum, rule) => sum + rule.rate, 0);
|
|
44
|
-
if (totalRate > 1) {
|
|
45
|
-
throw new Error(`Total split rate (${totalRate}) cannot exceed 1.0`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return splitRules.map((rule, index) => {
|
|
49
|
-
if (rule.rate < 0 || rule.rate > 1) {
|
|
50
|
-
throw new Error(`Split rate must be between 0 and 1 for split ${index}`);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const grossAmount = Math.round(amount * rule.rate * 100) / 100;
|
|
54
|
-
|
|
55
|
-
const gatewayFeeAmount = index === 0 && gatewayFeeRate > 0
|
|
56
|
-
? Math.round(amount * gatewayFeeRate * 100) / 100
|
|
57
|
-
: 0;
|
|
58
|
-
|
|
59
|
-
const netAmount = Math.max(0, Math.round((grossAmount - gatewayFeeAmount) * 100) / 100);
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
type: rule.type || SPLIT_TYPE.CUSTOM,
|
|
63
|
-
recipientId: rule.recipientId,
|
|
64
|
-
recipientType: rule.recipientType,
|
|
65
|
-
rate: rule.rate,
|
|
66
|
-
grossAmount,
|
|
67
|
-
gatewayFeeRate: gatewayFeeAmount > 0 ? gatewayFeeRate : 0,
|
|
68
|
-
gatewayFeeAmount,
|
|
69
|
-
netAmount,
|
|
70
|
-
status: SPLIT_STATUS.PENDING,
|
|
71
|
-
dueDate: rule.dueDate || null,
|
|
72
|
-
metadata: rule.metadata || {},
|
|
73
|
-
};
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Calculate organization payout after splits
|
|
79
|
-
*
|
|
80
|
-
* @param {Number} amount - Total transaction amount
|
|
81
|
-
* @param {Array} splits - Calculated splits
|
|
82
|
-
* @returns {Number} Amount organization receives
|
|
83
|
-
*/
|
|
84
|
-
export function calculateOrganizationPayout(amount, splits = []) {
|
|
85
|
-
const totalSplitAmount = splits.reduce((sum, split) => sum + split.grossAmount, 0);
|
|
86
|
-
return Math.max(0, Math.round((amount - totalSplitAmount) * 100) / 100);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Reverse splits proportionally on refund
|
|
91
|
-
*
|
|
92
|
-
* @param {Array} originalSplits - Original split objects
|
|
93
|
-
* @param {Number} originalAmount - Original transaction amount
|
|
94
|
-
* @param {Number} refundAmount - Amount being refunded
|
|
95
|
-
* @returns {Array} Reversed splits
|
|
96
|
-
*/
|
|
97
|
-
export function reverseSplits(originalSplits, originalAmount, refundAmount) {
|
|
98
|
-
if (!originalSplits || originalSplits.length === 0) {
|
|
99
|
-
return [];
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const refundRatio = refundAmount / originalAmount;
|
|
103
|
-
|
|
104
|
-
return originalSplits.map(split => ({
|
|
105
|
-
...split,
|
|
106
|
-
grossAmount: Math.round(split.grossAmount * refundRatio * 100) / 100,
|
|
107
|
-
gatewayFeeAmount: Math.round(split.gatewayFeeAmount * refundRatio * 100) / 100,
|
|
108
|
-
netAmount: Math.round(split.netAmount * refundRatio * 100) / 100,
|
|
109
|
-
status: SPLIT_STATUS.WAIVED,
|
|
110
|
-
}));
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Build commission object with splits support
|
|
115
|
-
* Backward compatible with existing calculateCommission
|
|
116
|
-
*
|
|
117
|
-
* @param {Number} amount - Transaction amount
|
|
118
|
-
* @param {Number} commissionRate - Platform commission rate
|
|
119
|
-
* @param {Number} gatewayFeeRate - Gateway fee rate
|
|
120
|
-
* @param {Object} options - Additional options
|
|
121
|
-
* @returns {Object} Commission with optional splits
|
|
122
|
-
*/
|
|
123
|
-
export function calculateCommissionWithSplits(amount, commissionRate, gatewayFeeRate = 0, options = {}) {
|
|
124
|
-
const { affiliateRate = 0, affiliateId = null, affiliateType = 'user' } = options;
|
|
125
|
-
|
|
126
|
-
if (commissionRate <= 0 && affiliateRate <= 0) {
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const splitRules = [];
|
|
131
|
-
|
|
132
|
-
if (commissionRate > 0) {
|
|
133
|
-
splitRules.push({
|
|
134
|
-
type: SPLIT_TYPE.PLATFORM_COMMISSION,
|
|
135
|
-
recipientId: 'platform',
|
|
136
|
-
recipientType: 'platform',
|
|
137
|
-
rate: commissionRate,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (affiliateRate > 0 && affiliateId) {
|
|
142
|
-
splitRules.push({
|
|
143
|
-
type: SPLIT_TYPE.AFFILIATE_COMMISSION,
|
|
144
|
-
recipientId: affiliateId,
|
|
145
|
-
recipientType: affiliateType,
|
|
146
|
-
rate: affiliateRate,
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const splits = calculateSplits(amount, splitRules, gatewayFeeRate);
|
|
151
|
-
|
|
152
|
-
const platformSplit = splits.find(s => s.type === SPLIT_TYPE.PLATFORM_COMMISSION);
|
|
153
|
-
const affiliateSplit = splits.find(s => s.type === SPLIT_TYPE.AFFILIATE_COMMISSION);
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
rate: commissionRate,
|
|
157
|
-
grossAmount: platformSplit?.grossAmount || 0,
|
|
158
|
-
gatewayFeeRate: platformSplit?.gatewayFeeRate || 0,
|
|
159
|
-
gatewayFeeAmount: platformSplit?.gatewayFeeAmount || 0,
|
|
160
|
-
netAmount: platformSplit?.netAmount || 0,
|
|
161
|
-
status: SPLIT_STATUS.PENDING,
|
|
162
|
-
...(splits.length > 0 && { splits }),
|
|
163
|
-
...(affiliateSplit && {
|
|
164
|
-
affiliate: {
|
|
165
|
-
recipientId: affiliateSplit.recipientId,
|
|
166
|
-
recipientType: affiliateSplit.recipientType,
|
|
167
|
-
rate: affiliateSplit.rate,
|
|
168
|
-
grossAmount: affiliateSplit.grossAmount,
|
|
169
|
-
netAmount: affiliateSplit.netAmount,
|
|
170
|
-
},
|
|
171
|
-
}),
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
export default {
|
|
176
|
-
calculateSplits,
|
|
177
|
-
calculateOrganizationPayout,
|
|
178
|
-
reverseSplits,
|
|
179
|
-
calculateCommissionWithSplits,
|
|
180
|
-
};
|
package/utils/commission.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Commission Calculation Utility
|
|
3
|
-
* @classytic/revenue
|
|
4
|
-
*
|
|
5
|
-
* Handles platform commission calculation with gateway fee deduction
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Build commission object for transaction
|
|
10
|
-
*
|
|
11
|
-
* @param {Number} amount - Transaction amount
|
|
12
|
-
* @param {Number} commissionRate - Commission rate (0 to 1, e.g., 0.10 for 10%)
|
|
13
|
-
* @param {Number} gatewayFeeRate - Gateway fee rate (0 to 1, e.g., 0.018 for 1.8%)
|
|
14
|
-
* @returns {Object} Commission object or null
|
|
15
|
-
*/
|
|
16
|
-
export function calculateCommission(amount, commissionRate, gatewayFeeRate = 0) {
|
|
17
|
-
// No commission if rate is 0 or negative
|
|
18
|
-
if (!commissionRate || commissionRate <= 0) {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Validate inputs
|
|
23
|
-
if (amount < 0) {
|
|
24
|
-
throw new Error('Transaction amount cannot be negative');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (commissionRate < 0 || commissionRate > 1) {
|
|
28
|
-
throw new Error('Commission rate must be between 0 and 1');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (gatewayFeeRate < 0 || gatewayFeeRate > 1) {
|
|
32
|
-
throw new Error('Gateway fee rate must be between 0 and 1');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Calculate commission
|
|
36
|
-
const grossAmount = Math.round(amount * commissionRate * 100) / 100; // Round to 2 decimals
|
|
37
|
-
const gatewayFeeAmount = Math.round(amount * gatewayFeeRate * 100) / 100;
|
|
38
|
-
const netAmount = Math.max(0, Math.round((grossAmount - gatewayFeeAmount) * 100) / 100);
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
rate: commissionRate,
|
|
42
|
-
grossAmount,
|
|
43
|
-
gatewayFeeRate,
|
|
44
|
-
gatewayFeeAmount,
|
|
45
|
-
netAmount,
|
|
46
|
-
status: 'pending',
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Reverse commission on refund (proportional)
|
|
52
|
-
*
|
|
53
|
-
* @param {Object} originalCommission - Original commission object
|
|
54
|
-
* @param {Number} originalAmount - Original transaction amount
|
|
55
|
-
* @param {Number} refundAmount - Amount being refunded
|
|
56
|
-
* @returns {Object} Reversed commission or null
|
|
57
|
-
*/
|
|
58
|
-
export function reverseCommission(originalCommission, originalAmount, refundAmount) {
|
|
59
|
-
if (!originalCommission || !originalCommission.netAmount) {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Calculate proportional refund
|
|
64
|
-
const refundRatio = refundAmount / originalAmount;
|
|
65
|
-
const reversedNetAmount = Math.round(originalCommission.netAmount * refundRatio * 100) / 100;
|
|
66
|
-
const reversedGrossAmount = Math.round(originalCommission.grossAmount * refundRatio * 100) / 100;
|
|
67
|
-
const reversedGatewayFee = Math.round(originalCommission.gatewayFeeAmount * refundRatio * 100) / 100;
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
rate: originalCommission.rate,
|
|
71
|
-
grossAmount: reversedGrossAmount,
|
|
72
|
-
gatewayFeeRate: originalCommission.gatewayFeeRate,
|
|
73
|
-
gatewayFeeAmount: reversedGatewayFee,
|
|
74
|
-
netAmount: reversedNetAmount,
|
|
75
|
-
status: 'waived', // Commission waived due to refund
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export default {
|
|
80
|
-
calculateCommission,
|
|
81
|
-
reverseCommission,
|
|
82
|
-
};
|
|
83
|
-
|
package/utils/hooks.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hook Utilities
|
|
3
|
-
* @classytic/revenue
|
|
4
|
-
*
|
|
5
|
-
* Fire-and-forget hook execution - never blocks main flow
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Trigger hooks asynchronously without waiting
|
|
10
|
-
* Errors are logged but never thrown
|
|
11
|
-
*
|
|
12
|
-
* @param {Object} hooks - Hooks object
|
|
13
|
-
* @param {string} event - Event name
|
|
14
|
-
* @param {Object} data - Event data
|
|
15
|
-
* @param {Object} logger - Logger instance
|
|
16
|
-
*/
|
|
17
|
-
export function triggerHook(hooks, event, data, logger) {
|
|
18
|
-
const handlers = hooks[event] || [];
|
|
19
|
-
|
|
20
|
-
if (handlers.length === 0) {
|
|
21
|
-
return; // No handlers, return immediately
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Fire-and-forget: Don't await, don't block
|
|
25
|
-
Promise.all(
|
|
26
|
-
handlers.map(handler =>
|
|
27
|
-
Promise.resolve(handler(data)).catch(error => {
|
|
28
|
-
logger.error(`Hook "${event}" failed:`, {
|
|
29
|
-
error: error.message,
|
|
30
|
-
stack: error.stack,
|
|
31
|
-
event,
|
|
32
|
-
// Don't log full data (could be huge)
|
|
33
|
-
dataKeys: Object.keys(data),
|
|
34
|
-
});
|
|
35
|
-
})
|
|
36
|
-
)
|
|
37
|
-
).catch(() => {
|
|
38
|
-
// Swallow any Promise.all errors (already logged individually)
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// Return immediately - hooks run in background
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export default triggerHook;
|
package/utils/index.d.ts
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TypeScript definitions for @classytic/revenue/utils
|
|
3
|
-
* Core utilities
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// ============ TRANSACTION TYPE UTILITIES ============
|
|
7
|
-
|
|
8
|
-
export const TRANSACTION_TYPE: {
|
|
9
|
-
readonly MONETIZATION: 'monetization';
|
|
10
|
-
readonly MANUAL: 'manual';
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const PROTECTED_MONETIZATION_FIELDS: readonly string[];
|
|
14
|
-
export const EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION: readonly string[];
|
|
15
|
-
export const MANUAL_TRANSACTION_CREATE_FIELDS: readonly string[];
|
|
16
|
-
export const MANUAL_TRANSACTION_UPDATE_FIELDS: readonly string[];
|
|
17
|
-
|
|
18
|
-
export interface TransactionTypeOptions {
|
|
19
|
-
targetModels?: string[];
|
|
20
|
-
additionalCategories?: string[];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function isMonetizationTransaction(
|
|
24
|
-
transaction: any,
|
|
25
|
-
options?: TransactionTypeOptions
|
|
26
|
-
): boolean;
|
|
27
|
-
|
|
28
|
-
export function isManualTransaction(
|
|
29
|
-
transaction: any,
|
|
30
|
-
options?: TransactionTypeOptions
|
|
31
|
-
): boolean;
|
|
32
|
-
|
|
33
|
-
export function getTransactionType(
|
|
34
|
-
transaction: any,
|
|
35
|
-
options?: TransactionTypeOptions
|
|
36
|
-
): 'monetization' | 'manual';
|
|
37
|
-
|
|
38
|
-
export function getAllowedUpdateFields(
|
|
39
|
-
transaction: any,
|
|
40
|
-
options?: TransactionTypeOptions
|
|
41
|
-
): string[];
|
|
42
|
-
|
|
43
|
-
export interface FieldValidationResult {
|
|
44
|
-
allowed: boolean;
|
|
45
|
-
reason?: string;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function validateFieldUpdate(
|
|
49
|
-
transaction: any,
|
|
50
|
-
fieldName: string,
|
|
51
|
-
options?: TransactionTypeOptions
|
|
52
|
-
): FieldValidationResult;
|
|
53
|
-
|
|
54
|
-
export function canSelfVerify(
|
|
55
|
-
transaction: any,
|
|
56
|
-
options?: TransactionTypeOptions
|
|
57
|
-
): boolean;
|
|
58
|
-
|
|
59
|
-
// ============ LOGGER UTILITIES ============
|
|
60
|
-
|
|
61
|
-
export interface Logger {
|
|
62
|
-
info(...args: any[]): void;
|
|
63
|
-
warn(...args: any[]): void;
|
|
64
|
-
error(...args: any[]): void;
|
|
65
|
-
debug(...args: any[]): void;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const logger: Logger;
|
|
69
|
-
export function setLogger(logger: Logger | Console): void;
|
|
70
|
-
|
|
71
|
-
// ============ HOOK UTILITIES ============
|
|
72
|
-
|
|
73
|
-
export function triggerHook(
|
|
74
|
-
hooks: Record<string, Function[]>,
|
|
75
|
-
event: string,
|
|
76
|
-
data: any,
|
|
77
|
-
logger: Logger
|
|
78
|
-
): void;
|
|
79
|
-
|
|
80
|
-
// ============ COMMISSION UTILITIES ============
|
|
81
|
-
|
|
82
|
-
export interface CommissionObject {
|
|
83
|
-
rate: number;
|
|
84
|
-
grossAmount: number;
|
|
85
|
-
gatewayFeeRate: number;
|
|
86
|
-
gatewayFeeAmount: number;
|
|
87
|
-
netAmount: number;
|
|
88
|
-
status: 'pending' | 'due' | 'paid' | 'waived';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function calculateCommission(
|
|
92
|
-
amount: number,
|
|
93
|
-
commissionRate: number,
|
|
94
|
-
gatewayFeeRate?: number
|
|
95
|
-
): CommissionObject | null;
|
|
96
|
-
|
|
97
|
-
export function reverseCommission(
|
|
98
|
-
originalCommission: CommissionObject,
|
|
99
|
-
originalAmount: number,
|
|
100
|
-
refundAmount: number
|
|
101
|
-
): CommissionObject | null;
|
|
102
|
-
|
|
103
|
-
// ============ SUBSCRIPTION UTILITIES ============
|
|
104
|
-
|
|
105
|
-
export function addDuration(startDate: Date, duration: number, unit?: string): Date;
|
|
106
|
-
|
|
107
|
-
export function calculatePeriodRange(params: {
|
|
108
|
-
currentEndDate?: Date | null;
|
|
109
|
-
startDate?: Date | null;
|
|
110
|
-
duration: number;
|
|
111
|
-
unit?: string;
|
|
112
|
-
now?: Date;
|
|
113
|
-
}): { startDate: Date; endDate: Date };
|
|
114
|
-
|
|
115
|
-
export function calculateProratedAmount(params: {
|
|
116
|
-
amountPaid: number;
|
|
117
|
-
startDate: Date;
|
|
118
|
-
endDate: Date;
|
|
119
|
-
asOfDate?: Date;
|
|
120
|
-
precision?: number;
|
|
121
|
-
}): number;
|
|
122
|
-
|
|
123
|
-
export function resolveIntervalToDuration(
|
|
124
|
-
interval?: string,
|
|
125
|
-
intervalCount?: number
|
|
126
|
-
): { duration: number; unit: string };
|
|
127
|
-
|
|
128
|
-
export function isSubscriptionActive(subscription: any): boolean;
|
|
129
|
-
export function canRenewSubscription(entity: any): boolean;
|
|
130
|
-
export function canCancelSubscription(entity: any): boolean;
|
|
131
|
-
export function canPauseSubscription(entity: any): boolean;
|
|
132
|
-
export function canResumeSubscription(entity: any): boolean;
|
|
133
|
-
|
|
134
|
-
// ============ DEFAULT EXPORT ============
|
|
135
|
-
|
|
136
|
-
declare const _default: {
|
|
137
|
-
TRANSACTION_TYPE: typeof TRANSACTION_TYPE;
|
|
138
|
-
isMonetizationTransaction: typeof isMonetizationTransaction;
|
|
139
|
-
isManualTransaction: typeof isManualTransaction;
|
|
140
|
-
getTransactionType: typeof getTransactionType;
|
|
141
|
-
PROTECTED_MONETIZATION_FIELDS: typeof PROTECTED_MONETIZATION_FIELDS;
|
|
142
|
-
EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION: typeof EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION;
|
|
143
|
-
MANUAL_TRANSACTION_CREATE_FIELDS: typeof MANUAL_TRANSACTION_CREATE_FIELDS;
|
|
144
|
-
MANUAL_TRANSACTION_UPDATE_FIELDS: typeof MANUAL_TRANSACTION_UPDATE_FIELDS;
|
|
145
|
-
getAllowedUpdateFields: typeof getAllowedUpdateFields;
|
|
146
|
-
validateFieldUpdate: typeof validateFieldUpdate;
|
|
147
|
-
canSelfVerify: typeof canSelfVerify;
|
|
148
|
-
logger: typeof logger;
|
|
149
|
-
setLogger: typeof setLogger;
|
|
150
|
-
triggerHook: typeof triggerHook;
|
|
151
|
-
calculateCommission: typeof calculateCommission;
|
|
152
|
-
reverseCommission: typeof reverseCommission;
|
|
153
|
-
addDuration: typeof addDuration;
|
|
154
|
-
calculatePeriodRange: typeof calculatePeriodRange;
|
|
155
|
-
calculateProratedAmount: typeof calculateProratedAmount;
|
|
156
|
-
resolveIntervalToDuration: typeof resolveIntervalToDuration;
|
|
157
|
-
isSubscriptionActive: typeof isSubscriptionActive;
|
|
158
|
-
canRenewSubscription: typeof canRenewSubscription;
|
|
159
|
-
canCancelSubscription: typeof canCancelSubscription;
|
|
160
|
-
canPauseSubscription: typeof canPauseSubscription;
|
|
161
|
-
canResumeSubscription: typeof canResumeSubscription;
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
export default _default;
|
package/utils/index.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core Utilities
|
|
3
|
-
* @classytic/revenue
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export * from './transaction-type.js';
|
|
7
|
-
export { default as logger, setLogger } from './logger.js';
|
|
8
|
-
export { triggerHook } from './hooks.js';
|
|
9
|
-
export { calculateCommission, reverseCommission } from './commission.js';
|
|
10
|
-
export {
|
|
11
|
-
calculateSplits,
|
|
12
|
-
calculateOrganizationPayout,
|
|
13
|
-
reverseSplits,
|
|
14
|
-
calculateCommissionWithSplits,
|
|
15
|
-
} from './commission-split.js';
|
|
16
|
-
export * from './subscription/index.js';
|
package/utils/logger.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Logger Abstraction for Monetization Library
|
|
3
|
-
*
|
|
4
|
-
* Defaults to console for standalone usage
|
|
5
|
-
* Can be overridden with custom logger (pino, winston, etc)
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* ```javascript
|
|
9
|
-
* import { setLogger } from '@classytic/revenue';
|
|
10
|
-
*
|
|
11
|
-
* // Optional: Use your own logger
|
|
12
|
-
* setLogger(myPinoLogger);
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
let _logger = console;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Set custom logger implementation
|
|
20
|
-
* @param {Object} customLogger - Logger instance with info, warn, error, debug methods
|
|
21
|
-
*/
|
|
22
|
-
export function setLogger(customLogger) {
|
|
23
|
-
_logger = customLogger;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Logger proxy - delegates to current logger implementation
|
|
28
|
-
*/
|
|
29
|
-
export const logger = {
|
|
30
|
-
info: (...args) => _logger.info?.(...args) || _logger.log?.('INFO:', ...args),
|
|
31
|
-
warn: (...args) => _logger.warn?.(...args) || _logger.log?.('WARN:', ...args),
|
|
32
|
-
error: (...args) => _logger.error?.(...args) || _logger.log?.('ERROR:', ...args),
|
|
33
|
-
debug: (...args) => _logger.debug?.(...args) || _logger.log?.('DEBUG:', ...args),
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export default logger;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subscription Action Utilities
|
|
3
|
-
* @classytic/revenue/utils/subscription
|
|
4
|
-
*
|
|
5
|
-
* Eligibility checks for subscription actions
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { SUBSCRIPTION_STATUS } from '../../enums/subscription.enums.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Check if subscription is active
|
|
12
|
-
*/
|
|
13
|
-
export function isSubscriptionActive(subscription) {
|
|
14
|
-
if (!subscription) return false;
|
|
15
|
-
if (!subscription.isActive) return false;
|
|
16
|
-
|
|
17
|
-
if (subscription.endDate) {
|
|
18
|
-
const now = new Date();
|
|
19
|
-
const endDate = new Date(subscription.endDate);
|
|
20
|
-
if (endDate < now) return false;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Check if can renew
|
|
28
|
-
*/
|
|
29
|
-
export function canRenewSubscription(entity) {
|
|
30
|
-
if (!entity || !entity.subscription) return false;
|
|
31
|
-
return isSubscriptionActive(entity.subscription);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Check if can cancel
|
|
36
|
-
*/
|
|
37
|
-
export function canCancelSubscription(entity) {
|
|
38
|
-
if (!entity || !entity.subscription) return false;
|
|
39
|
-
if (!isSubscriptionActive(entity.subscription)) return false;
|
|
40
|
-
return !entity.subscription.canceledAt;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Check if can pause
|
|
45
|
-
*/
|
|
46
|
-
export function canPauseSubscription(entity) {
|
|
47
|
-
if (!entity || !entity.subscription) return false;
|
|
48
|
-
if (entity.status === SUBSCRIPTION_STATUS.PAUSED) return false;
|
|
49
|
-
if (entity.status === SUBSCRIPTION_STATUS.CANCELLED) return false;
|
|
50
|
-
return isSubscriptionActive(entity.subscription);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Check if can resume
|
|
55
|
-
*/
|
|
56
|
-
export function canResumeSubscription(entity) {
|
|
57
|
-
if (!entity || !entity.subscription) return false;
|
|
58
|
-
return entity.status === SUBSCRIPTION_STATUS.PAUSED;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export default {
|
|
62
|
-
isSubscriptionActive,
|
|
63
|
-
canRenewSubscription,
|
|
64
|
-
canCancelSubscription,
|
|
65
|
-
canPauseSubscription,
|
|
66
|
-
canResumeSubscription,
|
|
67
|
-
};
|
|
68
|
-
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subscription Utilities Index
|
|
3
|
-
* @classytic/revenue/utils/subscription
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export {
|
|
7
|
-
addDuration,
|
|
8
|
-
calculatePeriodRange,
|
|
9
|
-
calculateProratedAmount,
|
|
10
|
-
resolveIntervalToDuration,
|
|
11
|
-
} from './period.js';
|
|
12
|
-
|
|
13
|
-
export {
|
|
14
|
-
isSubscriptionActive,
|
|
15
|
-
canRenewSubscription,
|
|
16
|
-
canCancelSubscription,
|
|
17
|
-
canPauseSubscription,
|
|
18
|
-
canResumeSubscription,
|
|
19
|
-
} from './actions.js';
|
|
20
|
-
|