@classytic/revenue 1.1.2 → 1.1.4

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 (89) hide show
  1. package/README.md +8 -7
  2. package/dist/application/services/index.d.mts +4 -0
  3. package/dist/application/services/index.mjs +3 -0
  4. package/dist/base-CsTlVQJe.d.mts +136 -0
  5. package/dist/base-DCoyIUj6.mjs +152 -0
  6. package/dist/category-resolver-DV83N8ok.mjs +284 -0
  7. package/dist/commission-split-BzB8cd39.mjs +485 -0
  8. package/dist/core/events.d.mts +294 -0
  9. package/dist/core/events.mjs +100 -0
  10. package/dist/core/index.d.mts +9 -0
  11. package/dist/core/index.mjs +8 -0
  12. package/dist/enums/index.d.mts +157 -0
  13. package/dist/enums/index.mjs +56 -0
  14. package/dist/errors-rRdOqnWx.d.mts +787 -0
  15. package/dist/escrow.enums-CZGrrdg7.mjs +101 -0
  16. package/dist/{escrow.enums-CE0VQsfe.d.ts → escrow.enums-DwdLuuve.d.mts} +30 -28
  17. package/dist/idempotency-DaYcUGY1.mjs +172 -0
  18. package/dist/index-Dsp7H5Wb.d.mts +471 -0
  19. package/dist/index.d.mts +9 -0
  20. package/dist/index.mjs +38 -0
  21. package/dist/infrastructure/plugins/{index.d.ts → index.d.mts} +81 -109
  22. package/dist/infrastructure/plugins/index.mjs +345 -0
  23. package/dist/money-CvrDOijQ.mjs +271 -0
  24. package/dist/money-DPG8AtJ8.d.mts +112 -0
  25. package/dist/{payment.enums-C1BiGlRa.d.ts → payment.enums-HAuAS9Pp.d.mts} +14 -13
  26. package/dist/payment.enums-tEFVa-Xp.mjs +69 -0
  27. package/dist/plugin-BbK0OVHy.d.mts +327 -0
  28. package/dist/plugin-Cd_V04Em.mjs +210 -0
  29. package/dist/providers/index.d.mts +3 -0
  30. package/dist/providers/index.mjs +3 -0
  31. package/dist/reconciliation/{index.d.ts → index.d.mts} +90 -112
  32. package/dist/reconciliation/index.mjs +192 -0
  33. package/dist/retry-HHCOXYdn.d.mts +186 -0
  34. package/dist/revenue-BhdS7nXh.mjs +553 -0
  35. package/dist/schemas/index.d.mts +2665 -0
  36. package/dist/schemas/index.mjs +717 -0
  37. package/dist/schemas/validation.d.mts +375 -0
  38. package/dist/schemas/validation.mjs +325 -0
  39. package/dist/{settlement.enums-ByC1x0ye.d.ts → settlement.enums-DFhkqZEY.d.mts} +31 -29
  40. package/dist/settlement.schema-DnNSFpGd.d.mts +344 -0
  41. package/dist/settlement.service-DjzAjezU.d.mts +594 -0
  42. package/dist/settlement.service-DmdKv0Zu.mjs +2511 -0
  43. package/dist/split.enums-BrjabxIX.mjs +86 -0
  44. package/dist/split.enums-DmskfLOM.d.mts +43 -0
  45. package/dist/tax-BoCt5cEd.d.mts +61 -0
  46. package/dist/tax-EQ15DO81.mjs +162 -0
  47. package/dist/transaction.enums-pCyMFT4Z.mjs +96 -0
  48. package/dist/utils/{index.d.ts → index.d.mts} +91 -161
  49. package/dist/utils/index.mjs +346 -0
  50. package/package.json +39 -37
  51. package/dist/application/services/index.d.ts +0 -6
  52. package/dist/application/services/index.js +0 -3288
  53. package/dist/application/services/index.js.map +0 -1
  54. package/dist/core/events.d.ts +0 -455
  55. package/dist/core/events.js +0 -122
  56. package/dist/core/events.js.map +0 -1
  57. package/dist/core/index.d.ts +0 -13
  58. package/dist/core/index.js +0 -4591
  59. package/dist/core/index.js.map +0 -1
  60. package/dist/enums/index.d.ts +0 -159
  61. package/dist/enums/index.js +0 -296
  62. package/dist/enums/index.js.map +0 -1
  63. package/dist/index-DxIK0UmZ.d.ts +0 -633
  64. package/dist/index-EnfKzDbs.d.ts +0 -806
  65. package/dist/index-cLJBLUvx.d.ts +0 -478
  66. package/dist/index.d.ts +0 -43
  67. package/dist/index.js +0 -4864
  68. package/dist/index.js.map +0 -1
  69. package/dist/infrastructure/plugins/index.js +0 -292
  70. package/dist/infrastructure/plugins/index.js.map +0 -1
  71. package/dist/money-widWVD7r.d.ts +0 -111
  72. package/dist/plugin-Bb9HOE10.d.ts +0 -336
  73. package/dist/providers/index.d.ts +0 -145
  74. package/dist/providers/index.js +0 -141
  75. package/dist/providers/index.js.map +0 -1
  76. package/dist/reconciliation/index.js +0 -140
  77. package/dist/reconciliation/index.js.map +0 -1
  78. package/dist/retry-D4hFUwVk.d.ts +0 -194
  79. package/dist/schemas/index.d.ts +0 -2655
  80. package/dist/schemas/index.js +0 -841
  81. package/dist/schemas/index.js.map +0 -1
  82. package/dist/schemas/validation.d.ts +0 -384
  83. package/dist/schemas/validation.js +0 -303
  84. package/dist/schemas/validation.js.map +0 -1
  85. package/dist/settlement.schema-CpamV7ZY.d.ts +0 -343
  86. package/dist/split.enums-DG3TxQf9.d.ts +0 -42
  87. package/dist/tax-CV8A0sxl.d.ts +0 -60
  88. package/dist/utils/index.js +0 -1202
  89. package/dist/utils/index.js.map +0 -1
@@ -1,18 +1,9 @@
1
- import { C as CommissionInfo, c as SplitRule, a as SplitInfo, d as MonetizationTypeValue, T as TransactionDocument, e as TransactionTypeOptions, F as FieldUpdateValidationResult, L as Logger, f as PeriodRangeParams, g as PeriodRangeResult, h as ProratedAmountParams, D as DurationResult, S as SubscriptionDocument, i as SubscriptionEntity } from '../index-cLJBLUvx.js';
2
- import { T as TaxConfig, a as TaxCalculation, b as TaxType } from '../tax-CV8A0sxl.js';
3
- export { M as Money, a as MoneyValue, f as fromSmallestUnit, t as toSmallestUnit } from '../money-widWVD7r.js';
4
- import { R as Result } from '../retry-D4hFUwVk.js';
5
- export { C as CircuitBreaker, l as CircuitBreakerConfig, n as CircuitState, k as RetryConfig, j as createCircuitBreaker, r as retry } from '../retry-D4hFUwVk.js';
6
- import 'mongoose';
7
- import '@classytic/shared-types';
8
-
9
- /**
10
- * Commission Calculation Utility
11
- * @classytic/revenue
12
- *
13
- * Handles platform commission calculation with gateway fee deduction
14
- */
1
+ import { B as TransactionDocument, E as ProratedAmountParams, F as SplitInfo, L as SplitRule, R as SubscriptionDocument, T as PeriodRangeResult, U as TransactionTypeOptions, c as FieldUpdateValidationResult, d as Logger, i as CommissionInfo, m as MonetizationTypeValue, o as DurationResult, w as PeriodRangeParams, z as SubscriptionEntity } from "../index-Dsp7H5Wb.mjs";
2
+ import { a as createCircuitBreaker, i as RetryConfig, l as Result, n as CircuitBreakerConfig, o as retry, r as CircuitState, t as CircuitBreaker } from "../retry-HHCOXYdn.mjs";
3
+ import { i as toSmallestUnit, n as MoneyValue, r as fromSmallestUnit, t as Money } from "../money-DPG8AtJ8.mjs";
4
+ import { n as TaxConfig, r as TaxType, t as TaxCalculation } from "../tax-BoCt5cEd.mjs";
15
5
 
6
+ //#region src/shared/utils/calculators/commission.d.ts
16
7
  /**
17
8
  * Build commission object for transaction
18
9
  *
@@ -31,15 +22,8 @@ declare function calculateCommission(amount: number, commissionRate: number, gat
31
22
  * @returns Reversed commission or null
32
23
  */
33
24
  declare function reverseCommission(originalCommission: CommissionInfo | null | undefined, originalAmount: number, refundAmount: number): CommissionInfo | null;
34
-
35
- /**
36
- * Tax Utilities
37
- * @classytic/revenue
38
- *
39
- * Tax calculation utilities
40
- * Philosophy: Apps provide rates, library does math (like Stripe)
41
- */
42
-
25
+ //#endregion
26
+ //#region src/shared/utils/calculators/tax.d.ts
43
27
  /**
44
28
  * Calculate tax for a transaction
45
29
  *
@@ -140,18 +124,12 @@ declare function getTaxType(transactionFlow: 'inflow' | 'outflow', category: str
140
124
  * ```
141
125
  */
142
126
  declare function reverseTax(originalTax: TaxCalculation & {
143
- type?: TaxType;
127
+ type?: TaxType;
144
128
  }, originalAmount: number, refundAmount: number): TaxCalculation & {
145
- type?: TaxType;
129
+ type?: TaxType;
146
130
  };
147
-
148
- /**
149
- * Commission Split Utilities
150
- * @classytic/revenue
151
- *
152
- * Multi-party commission split calculation for affiliate/referral systems
153
- */
154
-
131
+ //#endregion
132
+ //#region src/shared/utils/calculators/commission-split.d.ts
155
133
  /**
156
134
  * Calculate multi-party commission splits
157
135
  *
@@ -190,104 +168,91 @@ declare function calculateOrganizationPayout(amount: number, splits?: SplitInfo[
190
168
  * @returns Reversed splits
191
169
  */
192
170
  declare function reverseSplits(originalSplits: SplitInfo[] | undefined | null, originalAmount: number, refundAmount: number): SplitInfo[];
193
-
194
- /**
195
- * Idempotency Utilities
196
- * @classytic/revenue
197
- *
198
- * Prevent duplicate operations with idempotency keys
199
- * Inspired by: Stripe, Amazon SQS deduplication
200
- */
201
-
171
+ //#endregion
172
+ //#region src/shared/utils/resilience/idempotency.d.ts
202
173
  interface IdempotencyRecord<T = unknown> {
203
- /** Idempotency key */
204
- key: string;
205
- /** Operation result (if completed) */
206
- result?: T;
207
- /** Operation status */
208
- status: 'pending' | 'completed' | 'failed';
209
- /** Creation timestamp */
210
- createdAt: Date;
211
- /** Completion timestamp */
212
- completedAt?: Date;
213
- /** Request hash for validation */
214
- requestHash: string;
215
- /** TTL - when record expires */
216
- expiresAt: Date;
174
+ /** Idempotency key */
175
+ key: string;
176
+ /** Operation result (if completed) */
177
+ result?: T;
178
+ /** Operation status */
179
+ status: 'pending' | 'completed' | 'failed';
180
+ /** Creation timestamp */
181
+ createdAt: Date;
182
+ /** Completion timestamp */
183
+ completedAt?: Date;
184
+ /** Request hash for validation */
185
+ requestHash: string;
186
+ /** TTL - when record expires */
187
+ expiresAt: Date;
217
188
  }
218
189
  interface IdempotencyStore {
219
- /** Get record by key */
220
- get<T>(key: string): Promise<IdempotencyRecord<T> | null>;
221
- /** Set or update record */
222
- set<T>(key: string, record: IdempotencyRecord<T>): Promise<void>;
223
- /** Delete record */
224
- delete(key: string): Promise<void>;
225
- /** Check if key exists */
226
- exists(key: string): Promise<boolean>;
190
+ /** Get record by key */
191
+ get<T>(key: string): Promise<IdempotencyRecord<T> | null>;
192
+ /** Set or update record */
193
+ set<T>(key: string, record: IdempotencyRecord<T>): Promise<void>;
194
+ /** Delete record */
195
+ delete(key: string): Promise<void>;
196
+ /** Check if key exists */
197
+ exists(key: string): Promise<boolean>;
227
198
  }
228
199
  interface IdempotencyConfig {
229
- /** TTL in milliseconds (default: 24 hours) */
230
- ttl?: number;
231
- /** Custom store implementation */
232
- store?: IdempotencyStore;
233
- /** Key prefix */
234
- prefix?: string;
200
+ /** TTL in milliseconds (default: 24 hours) */
201
+ ttl?: number;
202
+ /** Custom store implementation */
203
+ store?: IdempotencyStore;
204
+ /** Key prefix */
205
+ prefix?: string;
235
206
  }
236
207
  declare class IdempotencyError extends Error {
237
- readonly code: 'DUPLICATE_REQUEST' | 'REQUEST_IN_PROGRESS' | 'REQUEST_MISMATCH';
238
- constructor(message: string, code: 'DUPLICATE_REQUEST' | 'REQUEST_IN_PROGRESS' | 'REQUEST_MISMATCH');
208
+ readonly code: 'DUPLICATE_REQUEST' | 'REQUEST_IN_PROGRESS' | 'REQUEST_MISMATCH';
209
+ constructor(message: string, code: 'DUPLICATE_REQUEST' | 'REQUEST_IN_PROGRESS' | 'REQUEST_MISMATCH');
239
210
  }
240
211
  /**
241
212
  * Idempotency manager
242
213
  */
243
214
  declare class IdempotencyManager {
244
- private store;
245
- private ttl;
246
- private prefix;
247
- constructor(config?: IdempotencyConfig);
248
- /**
249
- * Generate a unique idempotency key
250
- */
251
- generateKey(): string;
252
- /**
253
- * Hash request parameters for validation
254
- * Uses deterministic JSON serialization and simple hash function
255
- */
256
- private hashRequest;
257
- /**
258
- * Execute operation with idempotency protection
259
- */
260
- execute<T>(key: string, params: unknown, operation: () => Promise<T>): Promise<Result<T, IdempotencyError>>;
261
- /**
262
- * Check if operation with key was already completed
263
- */
264
- wasCompleted(key: string): Promise<boolean>;
265
- /**
266
- * Get cached result for key
267
- */
268
- getCached<T>(key: string): Promise<T | null>;
269
- /**
270
- * Invalidate a key (force re-execution on next call)
271
- */
272
- invalidate(key: string): Promise<void>;
273
- /**
274
- * Destroy the idempotency manager and cleanup resources
275
- * Call this when shutting down to prevent memory leaks
276
- */
277
- destroy(): void;
215
+ private store;
216
+ private ttl;
217
+ private prefix;
218
+ constructor(config?: IdempotencyConfig);
219
+ /**
220
+ * Generate a unique idempotency key
221
+ */
222
+ generateKey(): string;
223
+ /**
224
+ * Hash request parameters for validation
225
+ * Uses deterministic JSON serialization and simple hash function
226
+ */
227
+ private hashRequest;
228
+ /**
229
+ * Execute operation with idempotency protection
230
+ */
231
+ execute<T>(key: string, params: unknown, operation: () => Promise<T>): Promise<Result<T, IdempotencyError>>;
232
+ /**
233
+ * Check if operation with key was already completed
234
+ */
235
+ wasCompleted(key: string): Promise<boolean>;
236
+ /**
237
+ * Get cached result for key
238
+ */
239
+ getCached<T>(key: string): Promise<T | null>;
240
+ /**
241
+ * Invalidate a key (force re-execution on next call)
242
+ */
243
+ invalidate(key: string): Promise<void>;
244
+ /**
245
+ * Destroy the idempotency manager and cleanup resources
246
+ * Call this when shutting down to prevent memory leaks
247
+ */
248
+ destroy(): void;
278
249
  }
279
250
  /**
280
251
  * Create idempotency manager
281
252
  */
282
253
  declare function createIdempotencyManager(config?: IdempotencyConfig): IdempotencyManager;
283
-
284
- /**
285
- * Category Resolver Utility
286
- * @classytic/revenue
287
- *
288
- * Resolves transaction category based on categoryMappings
289
- */
290
-
254
+ //#endregion
255
+ //#region src/shared/utils/validators/category-resolver.d.ts
291
256
  /**
292
257
  * Resolve category for a transaction based on entity and monetizationType
293
258
  *
@@ -324,23 +289,14 @@ declare function createIdempotencyManager(config?: IdempotencyConfig): Idempoten
324
289
  * // Returns: 'platform_subscription'
325
290
  */
326
291
  declare function resolveCategory(entity: string | null | undefined, monetizationType: MonetizationTypeValue, categoryMappings?: Record<string, string>): string;
327
-
328
- /**
329
- * Transaction Type Detection & Classification
330
- *
331
- * Distinguishes between:
332
- * - Monetization-managed transactions (library-controlled, strict rules)
333
- * - Manual admin transactions (flexible, admin-controlled)
334
- *
335
- * @module @classytic/revenue/utils/transaction-type
336
- */
337
-
292
+ //#endregion
293
+ //#region src/utils/transaction-type.d.ts
338
294
  /**
339
295
  * Transaction types with different protection rules
340
296
  */
341
297
  declare const TRANSACTION_MANAGEMENT_TYPE: {
342
- readonly MONETIZATION: "monetization";
343
- readonly MANUAL: "manual";
298
+ readonly MONETIZATION: "monetization";
299
+ readonly MANUAL: "manual";
344
300
  };
345
301
  type TransactionManagementType = typeof TRANSACTION_MANAGEMENT_TYPE[keyof typeof TRANSACTION_MANAGEMENT_TYPE];
346
302
  /**
@@ -416,22 +372,8 @@ declare function validateFieldUpdate(transaction: Partial<TransactionDocument>,
416
372
  * @param options - Options for transaction type detection
417
373
  */
418
374
  declare function canSelfVerify(transaction: Partial<TransactionDocument>, options?: TransactionTypeOptions): boolean;
419
-
420
- /**
421
- * Logger Abstraction for Monetization Library
422
- *
423
- * Defaults to console for standalone usage
424
- * Can be overridden with custom logger (pino, winston, etc)
425
- *
426
- * Usage:
427
- * ```typescript
428
- * import { setLogger } from '@classytic/revenue';
429
- *
430
- * // Optional: Use your own logger
431
- * setLogger(myPinoLogger);
432
- * ```
433
- */
434
-
375
+ //#endregion
376
+ //#region src/utils/logger.d.ts
435
377
  /**
436
378
  * Set custom logger implementation
437
379
  * @param customLogger - Logger instance with info, warn, error, debug methods
@@ -441,14 +383,8 @@ declare function setLogger(customLogger: Logger): void;
441
383
  * Logger proxy - delegates to current logger implementation
442
384
  */
443
385
  declare const logger: Logger;
444
-
445
- /**
446
- * Subscription Period Utilities
447
- * @classytic/revenue/utils/subscription
448
- *
449
- * Universal period calculation, proration, and date utilities
450
- */
451
-
386
+ //#endregion
387
+ //#region src/utils/subscription/period.d.ts
452
388
  type DurationUnit = 'days' | 'day' | 'weeks' | 'week' | 'months' | 'month' | 'years' | 'year';
453
389
  /**
454
390
  * Add duration to date
@@ -466,14 +402,8 @@ declare function calculateProratedAmount(params: ProratedAmountParams): number;
466
402
  * Convert interval + count to duration/unit
467
403
  */
468
404
  declare function resolveIntervalToDuration(interval?: string, intervalCount?: number): DurationResult;
469
-
470
- /**
471
- * Subscription Action Utilities
472
- * @classytic/revenue/utils/subscription
473
- *
474
- * Eligibility checks for subscription actions
475
- */
476
-
405
+ //#endregion
406
+ //#region src/utils/subscription/actions.d.ts
477
407
  /**
478
408
  * Check if subscription is active
479
409
  */
@@ -494,5 +424,5 @@ declare function canPauseSubscription(entity: SubscriptionEntity | null | undefi
494
424
  * Check if can resume
495
425
  */
496
426
  declare function canResumeSubscription(entity: SubscriptionEntity | null | undefined): boolean;
497
-
498
- export { type DurationUnit, EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION, IdempotencyManager, MANUAL_TRANSACTION_CREATE_FIELDS, MANUAL_TRANSACTION_UPDATE_FIELDS, PROTECTED_MONETIZATION_FIELDS, TRANSACTION_MANAGEMENT_TYPE, type TransactionManagementType, addDuration, calculateCommission, calculateOrganizationPayout, calculatePeriodRange, calculateProratedAmount, calculateSplits, calculateTax, canCancelSubscription, canPauseSubscription, canRenewSubscription, canResumeSubscription, canSelfVerify, createIdempotencyManager, getAllowedUpdateFields, getTaxType, getTransactionType, isManualTransaction, isMonetizationTransaction, isSubscriptionActive, logger, logger as loggerDefault, resolveCategory, resolveIntervalToDuration, reverseCommission, reverseSplits, reverseTax, setLogger, validateFieldUpdate };
427
+ //#endregion
428
+ export { CircuitBreaker, CircuitBreakerConfig, CircuitState, type DurationUnit, EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION, IdempotencyManager, MANUAL_TRANSACTION_CREATE_FIELDS, MANUAL_TRANSACTION_UPDATE_FIELDS, Money, MoneyValue, PROTECTED_MONETIZATION_FIELDS, RetryConfig, TRANSACTION_MANAGEMENT_TYPE, TransactionManagementType, addDuration, calculateCommission, calculateOrganizationPayout, calculatePeriodRange, calculateProratedAmount, calculateSplits, calculateTax, canCancelSubscription, canPauseSubscription, canRenewSubscription, canResumeSubscription, canSelfVerify, createCircuitBreaker, createIdempotencyManager, fromSmallestUnit, getAllowedUpdateFields, getTaxType, getTransactionType, isManualTransaction, isMonetizationTransaction, isSubscriptionActive, logger, logger as loggerDefault, resolveCategory, resolveIntervalToDuration, retry, reverseCommission, reverseSplits, reverseTax, setLogger, toSmallestUnit, validateFieldUpdate };
@@ -0,0 +1,346 @@
1
+ import { a as reverseCommission, c as retry, i as calculateCommission, n as calculateSplits, o as CircuitBreaker, r as reverseSplits, s as createCircuitBreaker, t as calculateOrganizationPayout } from "../commission-split-BzB8cd39.mjs";
2
+ import { n as createIdempotencyManager, t as IdempotencyManager } from "../idempotency-DaYcUGY1.mjs";
3
+ import { t as resolveCategory } from "../category-resolver-DV83N8ok.mjs";
4
+ import { f as SUBSCRIPTION_STATUS } from "../split.enums-BrjabxIX.mjs";
5
+ import { n as fromSmallestUnit, r as toSmallestUnit, t as Money } from "../money-CvrDOijQ.mjs";
6
+ import { n as getTaxType, r as reverseTax, t as calculateTax } from "../tax-EQ15DO81.mjs";
7
+
8
+ //#region src/utils/transaction-type.ts
9
+ /**
10
+ * Transaction types with different protection rules
11
+ */
12
+ const TRANSACTION_MANAGEMENT_TYPE = {
13
+ MONETIZATION: "monetization",
14
+ MANUAL: "manual"
15
+ };
16
+ /**
17
+ * Default monetization categories
18
+ * Users can extend this via config.categoryMappings
19
+ */
20
+ const DEFAULT_MONETIZATION_CATEGORIES = ["subscription", "purchase"];
21
+ /**
22
+ * Check if category is monetization-related
23
+ * @param category - Transaction category
24
+ * @param additionalCategories - Additional categories from user config
25
+ */
26
+ function isMonetizationCategory(category, additionalCategories = []) {
27
+ return [...DEFAULT_MONETIZATION_CATEGORIES, ...additionalCategories].includes(category);
28
+ }
29
+ /**
30
+ * Check if transaction is monetization-managed
31
+ *
32
+ * Monetization-managed means:
33
+ * - Created through subscription/purchase flows via the library
34
+ * - Status controlled by payment webhooks/verification
35
+ * - Amount/commission calculated by library
36
+ * - Protected fields: status, amount, commission, gateway, verifiedAt, verifiedBy
37
+ *
38
+ * @param transaction - Transaction document or data
39
+ * @param options - Options
40
+ */
41
+ function isMonetizationTransaction(transaction, options = {}) {
42
+ const { targetModels = ["Subscription", "Membership"], additionalCategories = [] } = options;
43
+ if (transaction.sourceModel && targetModels.includes(transaction.sourceModel)) return true;
44
+ if (transaction.category) return isMonetizationCategory(transaction.category, additionalCategories);
45
+ return false;
46
+ }
47
+ /**
48
+ * Check if transaction is manual admin transaction
49
+ *
50
+ * Manual transactions:
51
+ * - Created directly by admins for operational expenses/income
52
+ * - Can be self-verified by admins
53
+ * - More flexible updates allowed
54
+ * - No commission/gateway complexity
55
+ *
56
+ * @param transaction - Transaction document or data
57
+ * @param options - Options (same as isMonetizationTransaction)
58
+ */
59
+ function isManualTransaction(transaction, options = {}) {
60
+ return !isMonetizationTransaction(transaction, options);
61
+ }
62
+ /**
63
+ * Get transaction type
64
+ *
65
+ * @param transaction - Transaction document or data
66
+ * @param options - Options (same as isMonetizationTransaction)
67
+ */
68
+ function getTransactionType(transaction, options = {}) {
69
+ return isMonetizationTransaction(transaction, options) ? TRANSACTION_MANAGEMENT_TYPE.MONETIZATION : TRANSACTION_MANAGEMENT_TYPE.MANUAL;
70
+ }
71
+ /**
72
+ * Protected fields for monetization transactions
73
+ * These fields cannot be updated directly by admins
74
+ */
75
+ const PROTECTED_MONETIZATION_FIELDS = [
76
+ "status",
77
+ "amount",
78
+ "platformCommission",
79
+ "netAmount",
80
+ "verifiedAt",
81
+ "verifiedBy",
82
+ "gateway",
83
+ "webhook",
84
+ "metadata.commission",
85
+ "metadata.gateway",
86
+ "type",
87
+ "category",
88
+ "sourceModel",
89
+ "sourceId"
90
+ ];
91
+ /**
92
+ * Editable fields for monetization transactions (before verification)
93
+ * These fields can be updated by frontend/customer before payment is verified
94
+ */
95
+ const EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION = [
96
+ "reference",
97
+ "paymentDetails",
98
+ "notes"
99
+ ];
100
+ /**
101
+ * Allowed fields for manual transaction creation
102
+ */
103
+ const MANUAL_TRANSACTION_CREATE_FIELDS = [
104
+ "organizationId",
105
+ "type",
106
+ "category",
107
+ "amount",
108
+ "method",
109
+ "reference",
110
+ "paymentDetails",
111
+ "notes",
112
+ "date",
113
+ "description"
114
+ ];
115
+ /**
116
+ * Allowed fields for manual transaction updates
117
+ */
118
+ const MANUAL_TRANSACTION_UPDATE_FIELDS = [
119
+ "amount",
120
+ "method",
121
+ "reference",
122
+ "paymentDetails",
123
+ "notes",
124
+ "date",
125
+ "description"
126
+ ];
127
+ /**
128
+ * Get allowed update fields based on transaction type and status
129
+ *
130
+ * @param transaction - Transaction document
131
+ * @param options - Options for transaction type detection
132
+ */
133
+ function getAllowedUpdateFields(transaction, options = {}) {
134
+ if (getTransactionType(transaction, options) === TRANSACTION_MANAGEMENT_TYPE.MONETIZATION) {
135
+ if (transaction.status === "pending") return EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION;
136
+ return [];
137
+ }
138
+ if (transaction.status === "verified" || transaction.status === "completed") return ["notes"];
139
+ return MANUAL_TRANSACTION_UPDATE_FIELDS;
140
+ }
141
+ /**
142
+ * Validate if field update is allowed
143
+ *
144
+ * @param transaction - Transaction document
145
+ * @param fieldName - Field being updated
146
+ * @param options - Options for transaction type detection
147
+ */
148
+ function validateFieldUpdate(transaction, fieldName, options = {}) {
149
+ if (getAllowedUpdateFields(transaction, options).includes(fieldName)) return { allowed: true };
150
+ if (getTransactionType(transaction, options) === TRANSACTION_MANAGEMENT_TYPE.MONETIZATION) {
151
+ if (PROTECTED_MONETIZATION_FIELDS.includes(fieldName)) return {
152
+ allowed: false,
153
+ reason: `Field "${fieldName}" is protected for monetization transactions. Updates must go through payment flow.`
154
+ };
155
+ }
156
+ return {
157
+ allowed: false,
158
+ reason: `Field "${fieldName}" cannot be updated for ${transaction.status} transactions.`
159
+ };
160
+ }
161
+ /**
162
+ * Check if transaction can be self-verified by admin
163
+ *
164
+ * @param transaction - Transaction document
165
+ * @param options - Options for transaction type detection
166
+ */
167
+ function canSelfVerify(transaction, options = {}) {
168
+ if (getTransactionType(transaction, options) === TRANSACTION_MANAGEMENT_TYPE.MANUAL) return transaction.status === "pending";
169
+ return false;
170
+ }
171
+
172
+ //#endregion
173
+ //#region src/utils/logger.ts
174
+ let _logger = console;
175
+ /**
176
+ * Set custom logger implementation
177
+ * @param customLogger - Logger instance with info, warn, error, debug methods
178
+ */
179
+ function setLogger(customLogger) {
180
+ _logger = customLogger;
181
+ }
182
+ /**
183
+ * Logger proxy - delegates to current logger implementation
184
+ */
185
+ const logger = {
186
+ info: (...args) => {
187
+ (_logger.info ?? _logger.log)?.call(_logger, ...args);
188
+ },
189
+ warn: (...args) => {
190
+ (_logger.warn ?? _logger.log)?.call(_logger, "WARN:", ...args);
191
+ },
192
+ error: (...args) => {
193
+ (_logger.error ?? _logger.log)?.call(_logger, "ERROR:", ...args);
194
+ },
195
+ debug: (...args) => {
196
+ (_logger.debug ?? _logger.log)?.call(_logger, "DEBUG:", ...args);
197
+ }
198
+ };
199
+
200
+ //#endregion
201
+ //#region src/utils/subscription/period.ts
202
+ /**
203
+ * Add duration to date
204
+ */
205
+ function addDuration(startDate, duration, unit = "days") {
206
+ const date = new Date(startDate);
207
+ switch (unit) {
208
+ case "months":
209
+ case "month":
210
+ date.setMonth(date.getMonth() + duration);
211
+ return date;
212
+ case "years":
213
+ case "year":
214
+ date.setFullYear(date.getFullYear() + duration);
215
+ return date;
216
+ case "weeks":
217
+ case "week":
218
+ date.setDate(date.getDate() + duration * 7);
219
+ return date;
220
+ default:
221
+ date.setDate(date.getDate() + duration);
222
+ return date;
223
+ }
224
+ }
225
+ /**
226
+ * Calculate subscription period start/end dates
227
+ */
228
+ function calculatePeriodRange(params) {
229
+ const { currentEndDate = null, startDate = null, duration, unit = "days", now = /* @__PURE__ */ new Date() } = params;
230
+ let periodStart;
231
+ if (startDate) periodStart = new Date(startDate);
232
+ else if (currentEndDate) {
233
+ const end = new Date(currentEndDate);
234
+ periodStart = end > now ? end : now;
235
+ } else periodStart = now;
236
+ const periodEnd = addDuration(periodStart, duration, unit);
237
+ return {
238
+ startDate: periodStart,
239
+ endDate: periodEnd
240
+ };
241
+ }
242
+ /**
243
+ * Calculate prorated refund amount for unused period
244
+ */
245
+ function calculateProratedAmount(params) {
246
+ const { amountPaid, startDate, endDate, asOfDate = /* @__PURE__ */ new Date(), precision = 2 } = params;
247
+ if (!amountPaid || amountPaid <= 0) return 0;
248
+ const start = new Date(startDate);
249
+ const end = new Date(endDate);
250
+ const asOf = new Date(asOfDate);
251
+ const totalMs = end.getTime() - start.getTime();
252
+ if (totalMs <= 0) return 0;
253
+ const remainingMs = Math.max(0, end.getTime() - asOf.getTime());
254
+ if (remainingMs <= 0) return 0;
255
+ const amount = amountPaid * (remainingMs / totalMs);
256
+ const factor = 10 ** precision;
257
+ return Math.round(amount * factor) / factor;
258
+ }
259
+ /**
260
+ * Convert interval + count to duration/unit
261
+ */
262
+ function resolveIntervalToDuration(interval = "month", intervalCount = 1) {
263
+ const normalized = (interval || "month").toLowerCase();
264
+ const count = Number(intervalCount) > 0 ? Number(intervalCount) : 1;
265
+ switch (normalized) {
266
+ case "year":
267
+ case "years": return {
268
+ duration: count,
269
+ unit: "years"
270
+ };
271
+ case "week":
272
+ case "weeks": return {
273
+ duration: count,
274
+ unit: "weeks"
275
+ };
276
+ case "quarter":
277
+ case "quarters": return {
278
+ duration: count * 3,
279
+ unit: "months"
280
+ };
281
+ case "day":
282
+ case "days": return {
283
+ duration: count,
284
+ unit: "days"
285
+ };
286
+ default: return {
287
+ duration: count,
288
+ unit: "months"
289
+ };
290
+ }
291
+ }
292
+
293
+ //#endregion
294
+ //#region src/utils/subscription/actions.ts
295
+ /**
296
+ * Subscription Action Utilities
297
+ * @classytic/revenue/utils/subscription
298
+ *
299
+ * Eligibility checks for subscription actions
300
+ */
301
+ /**
302
+ * Check if subscription is active
303
+ */
304
+ function isSubscriptionActive(subscription) {
305
+ if (!subscription) return false;
306
+ if (!subscription.isActive) return false;
307
+ if (subscription.endDate) {
308
+ const now = /* @__PURE__ */ new Date();
309
+ if (new Date(subscription.endDate) < now) return false;
310
+ }
311
+ return true;
312
+ }
313
+ /**
314
+ * Check if can renew
315
+ */
316
+ function canRenewSubscription(entity) {
317
+ if (!entity?.subscription) return false;
318
+ return isSubscriptionActive(entity.subscription);
319
+ }
320
+ /**
321
+ * Check if can cancel
322
+ */
323
+ function canCancelSubscription(entity) {
324
+ if (!entity?.subscription) return false;
325
+ if (!isSubscriptionActive(entity.subscription)) return false;
326
+ return !entity.subscription.canceledAt;
327
+ }
328
+ /**
329
+ * Check if can pause
330
+ */
331
+ function canPauseSubscription(entity) {
332
+ if (!entity?.subscription) return false;
333
+ if (entity.status === SUBSCRIPTION_STATUS.PAUSED) return false;
334
+ if (entity.status === SUBSCRIPTION_STATUS.CANCELLED) return false;
335
+ return isSubscriptionActive(entity.subscription);
336
+ }
337
+ /**
338
+ * Check if can resume
339
+ */
340
+ function canResumeSubscription(entity) {
341
+ if (!entity?.subscription) return false;
342
+ return entity.status === SUBSCRIPTION_STATUS.PAUSED;
343
+ }
344
+
345
+ //#endregion
346
+ export { CircuitBreaker, EDITABLE_MONETIZATION_FIELDS_PRE_VERIFICATION, IdempotencyManager, MANUAL_TRANSACTION_CREATE_FIELDS, MANUAL_TRANSACTION_UPDATE_FIELDS, Money, PROTECTED_MONETIZATION_FIELDS, TRANSACTION_MANAGEMENT_TYPE, addDuration, calculateCommission, calculateOrganizationPayout, calculatePeriodRange, calculateProratedAmount, calculateSplits, calculateTax, canCancelSubscription, canPauseSubscription, canRenewSubscription, canResumeSubscription, canSelfVerify, createCircuitBreaker, createIdempotencyManager, fromSmallestUnit, getAllowedUpdateFields, getTaxType, getTransactionType, isManualTransaction, isMonetizationTransaction, isSubscriptionActive, logger, logger as loggerDefault, resolveCategory, resolveIntervalToDuration, retry, reverseCommission, reverseSplits, reverseTax, setLogger, toSmallestUnit, validateFieldUpdate };