@classytic/revenue 0.0.1
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/LICENSE +21 -0
- package/README.md +454 -0
- package/core/builder.js +170 -0
- package/core/container.js +119 -0
- package/core/errors.js +262 -0
- package/enums/index.js +70 -0
- package/enums/monetization.enums.js +15 -0
- package/enums/payment.enums.js +43 -0
- package/enums/subscription.enums.js +33 -0
- package/enums/transaction.enums.js +53 -0
- package/index.js +58 -0
- package/package.json +62 -0
- package/providers/base.js +162 -0
- package/providers/manual.js +171 -0
- package/revenue.d.ts +290 -0
- package/schemas/index.js +21 -0
- package/schemas/subscription/index.js +17 -0
- package/schemas/subscription/info.schema.js +115 -0
- package/schemas/subscription/plan.schema.js +48 -0
- package/schemas/transaction/common.schema.js +22 -0
- package/schemas/transaction/gateway.schema.js +69 -0
- package/schemas/transaction/index.js +20 -0
- package/schemas/transaction/payment.schema.js +110 -0
- package/services/payment.service.js +400 -0
- package/services/subscription.service.js +537 -0
- package/services/transaction.service.js +142 -0
- package/utils/hooks.js +44 -0
- package/utils/index.js +8 -0
- package/utils/logger.js +36 -0
- package/utils/transaction-type.js +254 -0
package/utils/index.js
ADDED
package/utils/logger.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
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 '@fitverse/monetization';
|
|
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;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transaction Type Detection & Classification
|
|
3
|
+
*
|
|
4
|
+
* Distinguishes between:
|
|
5
|
+
* - Monetization-managed transactions (library-controlled, strict rules)
|
|
6
|
+
* - Manual admin transactions (flexible, admin-controlled)
|
|
7
|
+
*
|
|
8
|
+
* @module @classytic/revenue/utils/transaction-type
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Transaction types with different protection rules
|
|
13
|
+
*/
|
|
14
|
+
export const TRANSACTION_TYPE = {
|
|
15
|
+
MONETIZATION: 'monetization', // Library-managed (subscriptions, purchases)
|
|
16
|
+
MANUAL: 'manual', // Admin-managed (expenses, income, adjustments)
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Default monetization categories
|
|
21
|
+
* Users can extend this via config.categoryMappings
|
|
22
|
+
*/
|
|
23
|
+
const DEFAULT_MONETIZATION_CATEGORIES = [
|
|
24
|
+
'subscription',
|
|
25
|
+
'purchase',
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Check if category is monetization-related
|
|
30
|
+
* @param {string} category - Transaction category
|
|
31
|
+
* @param {Array<string>} additionalCategories - Additional categories from user config
|
|
32
|
+
* @returns {boolean}
|
|
33
|
+
*/
|
|
34
|
+
function isMonetizationCategory(category, additionalCategories = []) {
|
|
35
|
+
const allCategories = [...DEFAULT_MONETIZATION_CATEGORIES, ...additionalCategories];
|
|
36
|
+
return allCategories.includes(category);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if transaction is monetization-managed
|
|
41
|
+
*
|
|
42
|
+
* Monetization-managed means:
|
|
43
|
+
* - Created through subscription/purchase flows via the library
|
|
44
|
+
* - Status controlled by payment webhooks/verification
|
|
45
|
+
* - Amount/commission calculated by library
|
|
46
|
+
* - Protected fields: status, amount, commission, gateway, verifiedAt, verifiedBy
|
|
47
|
+
*
|
|
48
|
+
* @param {Object} transaction - Transaction document or data
|
|
49
|
+
* @param {Object} options - Options
|
|
50
|
+
* @param {Array<string>} options.targetModels - Target models from config (default: ['Subscription', 'Membership'])
|
|
51
|
+
* @param {Array<string>} options.additionalCategories - Additional categories from user config
|
|
52
|
+
* @returns {boolean}
|
|
53
|
+
*/
|
|
54
|
+
export function isMonetizationTransaction(transaction, options = {}) {
|
|
55
|
+
const {
|
|
56
|
+
targetModels = ['Subscription', 'Membership'],
|
|
57
|
+
additionalCategories = [],
|
|
58
|
+
} = options;
|
|
59
|
+
|
|
60
|
+
// Check 1: Has referenceModel from registered models
|
|
61
|
+
if (transaction.referenceModel && targetModels.includes(transaction.referenceModel)) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check 2: Category is monetization-related
|
|
66
|
+
if (transaction.category) {
|
|
67
|
+
return isMonetizationCategory(transaction.category, additionalCategories);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Check if transaction is manual admin transaction
|
|
75
|
+
*
|
|
76
|
+
* Manual transactions:
|
|
77
|
+
* - Created directly by admins for operational expenses/income
|
|
78
|
+
* - Can be self-verified by admins
|
|
79
|
+
* - More flexible updates allowed
|
|
80
|
+
* - No commission/gateway complexity
|
|
81
|
+
*
|
|
82
|
+
* @param {Object} transaction - Transaction document or data
|
|
83
|
+
* @param {Object} options - Options (same as isMonetizationTransaction)
|
|
84
|
+
* @returns {boolean}
|
|
85
|
+
*/
|
|
86
|
+
export function isManualTransaction(transaction, options = {}) {
|
|
87
|
+
return !isMonetizationTransaction(transaction, options);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get transaction type
|
|
92
|
+
*
|
|
93
|
+
* @param {Object} transaction - Transaction document or data
|
|
94
|
+
* @param {Object} options - Options (same as isMonetizationTransaction)
|
|
95
|
+
* @returns {string} TRANSACTION_TYPE.MONETIZATION or TRANSACTION_TYPE.MANUAL
|
|
96
|
+
*/
|
|
97
|
+
export function getTransactionType(transaction, options = {}) {
|
|
98
|
+
return isMonetizationTransaction(transaction, options)
|
|
99
|
+
? TRANSACTION_TYPE.MONETIZATION
|
|
100
|
+
: TRANSACTION_TYPE.MANUAL;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Protected fields for monetization transactions
|
|
105
|
+
* These fields cannot be updated directly by admins
|
|
106
|
+
*/
|
|
107
|
+
export const PROTECTED_MONETIZATION_FIELDS = [
|
|
108
|
+
'status',
|
|
109
|
+
'amount',
|
|
110
|
+
'platformCommission',
|
|
111
|
+
'netAmount',
|
|
112
|
+
'verifiedAt',
|
|
113
|
+
'verifiedBy',
|
|
114
|
+
'gateway',
|
|
115
|
+
'webhook',
|
|
116
|
+
'metadata.commission',
|
|
117
|
+
'metadata.gateway',
|
|
118
|
+
'type',
|
|
119
|
+
'category',
|
|
120
|
+
'referenceModel',
|
|
121
|
+
'referenceId',
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Editable fields for monetization transactions (before verification)
|
|
126
|
+
* These fields can be updated by frontend/customer before payment is verified
|
|
127
|
+
*/
|
|
128
|
+
export const EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION = [
|
|
129
|
+
'reference',
|
|
130
|
+
'paymentDetails',
|
|
131
|
+
'notes',
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Allowed fields for manual transaction creation
|
|
136
|
+
*/
|
|
137
|
+
export const MANUAL_TRANSACTION_CREATE_FIELDS = [
|
|
138
|
+
'organizationId',
|
|
139
|
+
'type',
|
|
140
|
+
'category',
|
|
141
|
+
'amount',
|
|
142
|
+
'method',
|
|
143
|
+
'reference',
|
|
144
|
+
'paymentDetails',
|
|
145
|
+
'notes',
|
|
146
|
+
'date', // Transaction date (can be backdated)
|
|
147
|
+
'description',
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Allowed fields for manual transaction updates
|
|
152
|
+
*/
|
|
153
|
+
export const MANUAL_TRANSACTION_UPDATE_FIELDS = [
|
|
154
|
+
'amount',
|
|
155
|
+
'method',
|
|
156
|
+
'reference',
|
|
157
|
+
'paymentDetails',
|
|
158
|
+
'notes',
|
|
159
|
+
'date',
|
|
160
|
+
'description',
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get allowed update fields based on transaction type and status
|
|
165
|
+
*
|
|
166
|
+
* @param {Object} transaction - Transaction document
|
|
167
|
+
* @param {Object} options - Options for transaction type detection
|
|
168
|
+
* @returns {Array<string>} Allowed field names
|
|
169
|
+
*/
|
|
170
|
+
export function getAllowedUpdateFields(transaction, options = {}) {
|
|
171
|
+
const type = getTransactionType(transaction, options);
|
|
172
|
+
|
|
173
|
+
if (type === TRANSACTION_TYPE.MONETIZATION) {
|
|
174
|
+
// Monetization transactions: only allow pre-verification edits
|
|
175
|
+
if (transaction.status === 'pending') {
|
|
176
|
+
return EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION;
|
|
177
|
+
}
|
|
178
|
+
// After verification, no direct updates allowed
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Manual transactions: more flexible
|
|
183
|
+
if (transaction.status === 'verified' || transaction.status === 'completed') {
|
|
184
|
+
// Once verified/completed, only notes can be updated
|
|
185
|
+
return ['notes'];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Pending manual transactions can be fully edited
|
|
189
|
+
return MANUAL_TRANSACTION_UPDATE_FIELDS;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Validate if field update is allowed
|
|
194
|
+
*
|
|
195
|
+
* @param {Object} transaction - Transaction document
|
|
196
|
+
* @param {string} fieldName - Field being updated
|
|
197
|
+
* @param {Object} options - Options for transaction type detection
|
|
198
|
+
* @returns {Object} { allowed: boolean, reason?: string }
|
|
199
|
+
*/
|
|
200
|
+
export function validateFieldUpdate(transaction, fieldName, options = {}) {
|
|
201
|
+
const allowedFields = getAllowedUpdateFields(transaction, options);
|
|
202
|
+
|
|
203
|
+
if (allowedFields.includes(fieldName)) {
|
|
204
|
+
return { allowed: true };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const type = getTransactionType(transaction, options);
|
|
208
|
+
|
|
209
|
+
if (type === TRANSACTION_TYPE.MONETIZATION) {
|
|
210
|
+
if (PROTECTED_MONETIZATION_FIELDS.includes(fieldName)) {
|
|
211
|
+
return {
|
|
212
|
+
allowed: false,
|
|
213
|
+
reason: `Field "${fieldName}" is protected for monetization transactions. Updates must go through payment flow.`,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
allowed: false,
|
|
220
|
+
reason: `Field "${fieldName}" cannot be updated for ${transaction.status} transactions.`,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Check if transaction can be self-verified by admin
|
|
226
|
+
*
|
|
227
|
+
* @param {Object} transaction - Transaction document
|
|
228
|
+
* @param {Object} options - Options for transaction type detection
|
|
229
|
+
* @returns {boolean}
|
|
230
|
+
*/
|
|
231
|
+
export function canSelfVerify(transaction, options = {}) {
|
|
232
|
+
const type = getTransactionType(transaction, options);
|
|
233
|
+
|
|
234
|
+
// Only manual transactions can be self-verified
|
|
235
|
+
if (type === TRANSACTION_TYPE.MANUAL) {
|
|
236
|
+
return transaction.status === 'pending';
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export default {
|
|
243
|
+
TRANSACTION_TYPE,
|
|
244
|
+
isMonetizationTransaction,
|
|
245
|
+
isManualTransaction,
|
|
246
|
+
getTransactionType,
|
|
247
|
+
PROTECTED_MONETIZATION_FIELDS,
|
|
248
|
+
EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION,
|
|
249
|
+
MANUAL_TRANSACTION_CREATE_FIELDS,
|
|
250
|
+
MANUAL_TRANSACTION_UPDATE_FIELDS,
|
|
251
|
+
getAllowedUpdateFields,
|
|
252
|
+
validateFieldUpdate,
|
|
253
|
+
canSelfVerify,
|
|
254
|
+
};
|