@classytic/revenue 0.0.2 → 0.0.22

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 CHANGED
@@ -6,449 +6,375 @@ Thin, focused, production-ready library with smart defaults. Built for SaaS, mar
6
6
 
7
7
  ## Features
8
8
 
9
- - **Subscriptions**: Create, renew, upgrade, downgrade with smart proration
10
- - **Payment Processing**: Multi-gateway support (Stripe, SSLCommerz, bKash, manual)
11
- - **Transaction Management**: Complete lifecycle with verification and refunds
12
- - **Provider Pattern**: Pluggable payment providers (like AI SDK)
13
- - **Framework Agnostic**: Works with Fastify, Express, Nest, or standalone
14
- - **Model Flexible**: Plain Mongoose OR @classytic/mongokit Repository
9
+ - **Subscriptions**: Create, renew, pause, cancel with lifecycle management
10
+ - **Payment Processing**: Multi-gateway support (Stripe, SSLCommerz, manual, etc.)
11
+ - **Transaction Management**: Income/expense tracking with verification and refunds
12
+ - **Provider Pattern**: Pluggable payment providers (like LangChain/Vercel AI SDK)
13
+ - **Framework Agnostic**: Works with Express, Fastify, Next.js, or standalone
15
14
  - **TypeScript Ready**: Full type definitions included
16
- - **Zero Dependencies**: Only requires `mongoose` as peer dependency
17
15
 
18
16
  ## Installation
19
17
 
20
18
  ```bash
21
19
  npm install @classytic/revenue
20
+ npm install @classytic/revenue-manual # For manual payments
22
21
  ```
23
22
 
24
- ## Transaction Model Setup
25
-
26
- Spread library enums/schemas into your Transaction model:
27
-
28
- ```javascript
29
- import mongoose from 'mongoose';
30
- import {
31
- TRANSACTION_STATUS_VALUES,
32
- LIBRARY_CATEGORIES,
33
- } from '@classytic/revenue/enums';
34
- import {
35
- gatewaySchema,
36
- currentPaymentSchema,
37
- paymentDetailsSchema,
38
- } from '@classytic/revenue/schemas';
39
-
40
- // Merge library categories with your own
41
- const MY_CATEGORIES = {
42
- ...LIBRARY_CATEGORIES, // subscription, purchase
43
- SALARY: 'salary',
44
- RENT: 'rent',
45
- EQUIPMENT: 'equipment',
46
- // Add as many as you need
47
- };
48
-
49
- const transactionSchema = new mongoose.Schema({
50
- // Required by library
51
- organizationId: { type: String, required: true, index: true },
52
- amount: { type: Number, required: true, min: 0 },
53
- status: { type: String, enum: TRANSACTION_STATUS_VALUES, required: true },
54
- category: { type: String, enum: Object.values(MY_CATEGORIES), required: true },
55
-
56
- // Spread library schemas
57
- gateway: gatewaySchema,
58
- currentPayment: currentPaymentSchema,
59
- paymentDetails: paymentDetailsSchema,
60
-
61
- // Add your fields
62
- notes: String,
63
- invoiceNumber: String,
64
- }, { timestamps: true });
65
-
66
- export default mongoose.model('Transaction', transactionSchema);
67
- ```
68
-
69
- **See [`examples/transaction.model.js`](examples/transaction.model.js) for complete example with indexes.**
70
-
71
- ## Quick Start
72
-
73
- ### Minimal Setup (3 lines)
23
+ ## Quick Start (30 seconds)
74
24
 
75
25
  ```javascript
76
26
  import { createRevenue } from '@classytic/revenue';
27
+ import { ManualProvider } from '@classytic/revenue-manual';
77
28
  import Transaction from './models/Transaction.js';
78
29
 
79
- // Works out-of-box with built-in manual provider
30
+ // 1. Configure
80
31
  const revenue = createRevenue({
81
32
  models: { Transaction },
33
+ providers: { manual: new ManualProvider() },
82
34
  });
83
35
 
84
- // Create a subscription
36
+ // 2. Create subscription
85
37
  const { subscription, transaction } = await revenue.subscriptions.create({
86
38
  data: { organizationId, customerId },
87
39
  planKey: 'monthly',
88
- amount: 99.99,
40
+ amount: 1500,
41
+ gateway: 'manual',
42
+ paymentData: { method: 'bkash', walletNumber: '01712345678' },
89
43
  });
44
+
45
+ // 3. Verify payment
46
+ await revenue.payments.verify(transaction.gateway.paymentIntentId);
47
+
48
+ // 4. Refund if needed
49
+ await revenue.payments.refund(transaction._id, 500, { reason: 'Partial refund' });
90
50
  ```
91
51
 
92
- That's it! The package works immediately with sensible defaults.
52
+ **That's it!** Working revenue system in 3 steps.
93
53
 
94
- ## Usage Examples
54
+ ## Transaction Model Setup
95
55
 
96
- ### With Payment Provider
56
+ The library requires a Transaction model with specific fields and provides reusable schemas:
97
57
 
98
58
  ```javascript
99
- import { createRevenue } from '@classytic/revenue';
100
- // Future: import { stripe } from '@classytic/revenue-stripe';
59
+ import mongoose from 'mongoose';
60
+ import {
61
+ TRANSACTION_TYPE_VALUES,
62
+ TRANSACTION_STATUS_VALUES,
63
+ } from '@classytic/revenue/enums';
64
+ import {
65
+ gatewaySchema,
66
+ paymentDetailsSchema,
67
+ } from '@classytic/revenue/schemas';
101
68
 
102
- const revenue = createRevenue({
103
- models: { Transaction },
104
- providers: {
105
- // Built-in manual provider is auto-included
106
- // stripe: stripe({ apiKey: process.env.STRIPE_KEY }),
107
- },
108
- });
69
+ const transactionSchema = new mongoose.Schema({
70
+ // ============ REQUIRED BY LIBRARY ============
71
+ organizationId: { type: String, required: true, index: true },
72
+ amount: { type: Number, required: true, min: 0 },
73
+ type: { type: String, enum: TRANSACTION_TYPE_VALUES, required: true }, // 'income' | 'expense'
74
+ method: { type: String, required: true }, // 'manual' | 'bkash' | 'card' | etc.
75
+ status: { type: String, enum: TRANSACTION_STATUS_VALUES, required: true },
76
+ category: { type: String, required: true }, // Your custom categories
77
+
78
+ // ============ LIBRARY SCHEMAS (nested) ============
79
+ gateway: gatewaySchema, // Payment gateway details
80
+ paymentDetails: paymentDetailsSchema, // Payment info (wallet, bank, etc.)
81
+
82
+ // ============ YOUR CUSTOM FIELDS ============
83
+ customerId: String,
84
+ currency: { type: String, default: 'BDT' },
85
+ verifiedAt: Date,
86
+ verifiedBy: mongoose.Schema.Types.ObjectId,
87
+ refundedAmount: Number,
88
+ idempotencyKey: { type: String, unique: true, sparse: true },
89
+ metadata: mongoose.Schema.Types.Mixed,
90
+ }, { timestamps: true });
109
91
 
110
- // Create subscription with payment gateway
111
- await revenue.subscriptions.create({
112
- data: { organizationId, customerId },
113
- planKey: 'monthly',
114
- amount: 99.99,
115
- gateway: 'stripe', // or 'manual'
116
- });
92
+ export default mongoose.model('Transaction', transactionSchema);
117
93
  ```
118
94
 
119
- ### With Hooks
95
+ ## Available Schemas
120
96
 
121
- ```javascript
122
- const revenue = createRevenue({
123
- models: { Transaction },
124
- hooks: {
125
- 'payment.verified': async ({ transaction }) => {
126
- console.log('Payment verified:', transaction._id);
127
- // Send email, update analytics, etc.
128
- },
129
- 'subscription.created': async ({ subscription, transaction }) => {
130
- console.log('New subscription:', subscription._id);
131
- },
132
- },
133
- });
134
- ```
97
+ | Schema | Purpose | Key Fields |
98
+ |--------|---------|------------|
99
+ | `gatewaySchema` | Payment gateway integration | `type`, `paymentIntentId`, `sessionId` |
100
+ | `paymentDetailsSchema` | Payment method info | `walletNumber`, `trxId`, `bankName` |
101
+ | `commissionSchema` | Commission tracking | `rate`, `grossAmount`, `netAmount` |
102
+ | `currentPaymentSchema` | Latest payment (for Order/Subscription models) | `transactionId`, `status`, `verifiedAt` |
103
+ | `subscriptionInfoSchema` | Subscription details (for Order models) | `planKey`, `startDate`, `endDate` |
135
104
 
136
- ### Custom Logger
105
+ **Usage:** Import and use as nested objects (NOT spread):
137
106
 
138
107
  ```javascript
139
- import winston from 'winston';
108
+ import { gatewaySchema } from '@classytic/revenue/schemas';
140
109
 
141
- const revenue = createRevenue({
142
- models: { Transaction },
143
- logger: winston.createLogger({ /* config */ }),
110
+ const schema = new mongoose.Schema({
111
+ gateway: gatewaySchema, // Correct - nested
112
+ // ...gatewaySchema, // Wrong - don't spread
144
113
  });
145
114
  ```
146
115
 
147
116
  ## Core API
148
117
 
149
- ### Services
150
-
151
- The `revenue` instance provides three focused services:
152
-
153
- #### Subscriptions
118
+ ### Subscriptions
154
119
 
155
120
  ```javascript
156
121
  // Create subscription
157
- const { subscription, transaction, paymentIntent } = await revenue.subscriptions.create({
158
- data: { organizationId, customerId, ... },
159
- planKey: 'monthly',
160
- amount: 99.99,
161
- currency: 'USD',
162
- gateway: 'manual', // optional
163
- metadata: { /* ... */ }, // optional
164
- });
122
+ const { subscription, transaction, paymentIntent } =
123
+ await revenue.subscriptions.create({
124
+ data: { organizationId, customerId },
125
+ planKey: 'monthly',
126
+ amount: 1500,
127
+ currency: 'BDT',
128
+ gateway: 'manual',
129
+ paymentData: { method: 'bkash', walletNumber: '01712345678' },
130
+ });
131
+
132
+ // Verify and activate
133
+ await revenue.payments.verify(transaction.gateway.paymentIntentId);
134
+ await revenue.subscriptions.activate(subscription._id);
165
135
 
166
136
  // Renew subscription
167
- await revenue.subscriptions.renew(subscriptionId, { amount: 99.99 });
168
-
169
- // Activate subscription
170
- await revenue.subscriptions.activate(subscriptionId);
171
-
172
- // Cancel subscription
173
- await revenue.subscriptions.cancel(subscriptionId, { immediate: true });
137
+ await revenue.subscriptions.renew(subscription._id, {
138
+ gateway: 'manual',
139
+ paymentData: { method: 'nagad' },
140
+ });
174
141
 
175
142
  // Pause/Resume
176
- await revenue.subscriptions.pause(subscriptionId);
177
- await revenue.subscriptions.resume(subscriptionId);
143
+ await revenue.subscriptions.pause(subscription._id, { reason: 'Customer request' });
144
+ await revenue.subscriptions.resume(subscription._id, { extendPeriod: true });
178
145
 
179
- // Get/List
180
- await revenue.subscriptions.get(subscriptionId);
181
- await revenue.subscriptions.list(filters, options);
146
+ // Cancel
147
+ await revenue.subscriptions.cancel(subscription._id, { immediate: true });
182
148
  ```
183
149
 
184
- #### Payments
150
+ ### Payments
185
151
 
186
152
  ```javascript
187
- // Verify payment
188
- const { transaction, paymentResult, status } = await revenue.payments.verify(
189
- paymentIntentId,
190
- { verifiedBy: userId }
191
- );
153
+ // Verify payment (admin approval for manual)
154
+ const { transaction } = await revenue.payments.verify(paymentIntentId, {
155
+ verifiedBy: adminUserId,
156
+ });
192
157
 
193
158
  // Get payment status
194
- const { transaction, status, provider } = await revenue.payments.getStatus(paymentIntentId);
159
+ const { status } = await revenue.payments.getStatus(paymentIntentId);
195
160
 
196
- // Refund payment
197
- const { transaction, refundResult } = await revenue.payments.refund(
198
- paymentId,
199
- amount, // optional, defaults to full refund
200
- { reason: 'Customer request' }
161
+ // Refund (creates separate EXPENSE transaction)
162
+ const { transaction, refundTransaction } = await revenue.payments.refund(
163
+ transactionId,
164
+ 500, // Amount or null for full refund
165
+ { reason: 'Customer requested' }
201
166
  );
202
167
 
203
- // Handle webhook
204
- const { event, transaction, status } = await revenue.payments.handleWebhook(
168
+ // Handle webhook (for automated providers like Stripe)
169
+ const { event, transaction } = await revenue.payments.handleWebhook(
205
170
  'stripe',
206
- payload,
171
+ webhookPayload,
207
172
  headers
208
173
  );
209
174
  ```
210
175
 
211
- #### Transactions
176
+ ### Transactions
212
177
 
213
178
  ```javascript
214
- // Get transaction
179
+ // Get transaction by ID
215
180
  const transaction = await revenue.transactions.get(transactionId);
216
181
 
217
- // List transactions
218
- const { transactions, total, page, limit, pages } = await revenue.transactions.list(
219
- { organizationId, status: 'verified' },
220
- { limit: 50, skip: 0, sort: { createdAt: -1 } }
182
+ // List with filters
183
+ const { transactions, total } = await revenue.transactions.list(
184
+ { type: 'income', status: 'verified' },
185
+ { limit: 50, sort: { createdAt: -1 } }
221
186
  );
222
187
 
223
- // Update transaction
224
- await revenue.transactions.update(transactionId, { notes: 'Updated' });
188
+ // Calculate net revenue
189
+ const income = await revenue.transactions.list({ type: 'income' });
190
+ const expense = await revenue.transactions.list({ type: 'expense' });
191
+ const netRevenue = income.total - expense.total;
225
192
  ```
226
193
 
227
- **Note**: For analytics, exports, or complex queries, use Mongoose aggregations directly on your Transaction model. This keeps the service thin and focused.
194
+ ## Transaction Types (Income vs Expense)
228
195
 
229
- ### Providers
196
+ The library uses **double-entry accounting**:
230
197
 
231
- ```javascript
232
- // Get specific provider
233
- const stripeProvider = revenue.getProvider('stripe');
234
-
235
- // Check capabilities
236
- const capabilities = stripeProvider.getCapabilities();
237
- // {
238
- // supportsWebhooks: true,
239
- // supportsRefunds: true,
240
- // supportsPartialRefunds: true,
241
- // requiresManualVerification: false
242
- // }
243
- ```
244
-
245
- ## Error Handling
246
-
247
- All errors are typed with codes for easy handling:
198
+ - **INCOME** (`'income'`): Money coming in - payments, subscriptions
199
+ - **EXPENSE** (`'expense'`): Money going out - refunds, payouts
248
200
 
249
201
  ```javascript
250
- import {
251
- TransactionNotFoundError,
252
- ProviderNotFoundError,
253
- RefundNotSupportedError
254
- } from '@classytic/revenue';
202
+ const revenue = createRevenue({
203
+ models: { Transaction },
204
+ config: {
205
+ transactionTypeMapping: {
206
+ subscription: 'income',
207
+ purchase: 'income',
208
+ refund: 'expense', // Refunds create separate expense transactions
209
+ },
210
+ },
211
+ });
212
+ ```
255
213
 
256
- try {
257
- await revenue.payments.verify(intentId);
258
- } catch (error) {
259
- if (error instanceof TransactionNotFoundError) {
260
- console.log('Transaction not found:', error.metadata.transactionId);
261
- }
214
+ **Refund Pattern:**
215
+ - Refund creates NEW transaction with `type: 'expense'`
216
+ - Original transaction status becomes `'refunded'` or `'partially_refunded'`
217
+ - Both linked via metadata for audit trail
218
+ - Calculate net: `SUM(income) - SUM(expense)`
262
219
 
263
- if (error.code === 'TRANSACTION_NOT_FOUND') {
264
- // Handle specific error
265
- }
220
+ ## Custom Categories
266
221
 
267
- if (error.retryable) {
268
- // Retry the operation
269
- }
270
- }
271
- ```
272
-
273
- ### Error Classes
274
-
275
- - `RevenueError` - Base error class
276
- - `ConfigurationError` - Configuration issues
277
- - `ModelNotRegisteredError` - Model not provided
278
- - `ProviderError` - Provider-related errors
279
- - `ProviderNotFoundError` - Provider doesn't exist
280
- - `PaymentIntentCreationError` - Failed to create payment intent
281
- - `PaymentVerificationError` - Verification failed
282
- - `NotFoundError` - Resource not found
283
- - `TransactionNotFoundError` - Transaction not found
284
- - `SubscriptionNotFoundError` - Subscription not found
285
- - `ValidationError` - Validation failed
286
- - `InvalidAmountError` - Invalid amount
287
- - `MissingRequiredFieldError` - Required field missing
288
- - `StateError` - Invalid state
289
- - `AlreadyVerifiedError` - Already verified
290
- - `InvalidStateTransitionError` - Invalid state change
291
- - `RefundNotSupportedError` - Provider doesn't support refunds
292
- - `RefundError` - Refund failed
293
-
294
- ## Enums & Schemas
222
+ Map logical entities to transaction categories:
295
223
 
296
224
  ```javascript
297
- import {
298
- TRANSACTION_STATUS,
299
- PAYMENT_GATEWAY_TYPE,
300
- SUBSCRIPTION_STATUS,
301
- PLAN_KEYS,
302
- currentPaymentSchema,
303
- subscriptionInfoSchema,
304
- } from '@classytic/revenue';
225
+ const revenue = createRevenue({
226
+ models: { Transaction },
227
+ config: {
228
+ categoryMappings: {
229
+ Order: 'order_subscription',
230
+ PlatformSubscription: 'platform_subscription',
231
+ Membership: 'gym_membership',
232
+ Enrollment: 'course_enrollment',
233
+ },
234
+ },
235
+ });
305
236
 
306
- // Use in your models
307
- const organizationSchema = new Schema({
308
- currentPayment: currentPaymentSchema,
309
- subscription: subscriptionInfoSchema,
237
+ // Usage
238
+ await revenue.subscriptions.create({
239
+ entity: 'Order', // Maps to 'order_subscription' category
240
+ monetizationType: 'subscription',
241
+ // ...
310
242
  });
311
243
  ```
312
244
 
313
- ## TypeScript
245
+ **Note:** `entity` is a logical identifier (not a database model name) for organizing your business logic.
314
246
 
315
- Full TypeScript support included:
316
-
317
- ```typescript
318
- import { createRevenue, Revenue, RevenueOptions } from '@classytic/revenue';
247
+ ## Hooks
319
248
 
320
- const options: RevenueOptions = {
321
- models: { Transaction: TransactionModel },
322
- };
323
-
324
- const revenue: Revenue = createRevenue(options);
249
+ ```javascript
250
+ const revenue = createRevenue({
251
+ models: { Transaction },
252
+ hooks: {
253
+ 'subscription.created': async ({ subscription, transaction }) => {
254
+ console.log('New subscription:', subscription._id);
255
+ },
256
+ 'payment.verified': async ({ transaction }) => {
257
+ // Send confirmation email
258
+ },
259
+ 'payment.refunded': async ({ refundTransaction }) => {
260
+ // Process refund notification
261
+ },
262
+ },
263
+ });
325
264
  ```
326
265
 
327
- ## Advanced Usage
266
+ **Available hooks:**
267
+ - `subscription.created`, `subscription.activated`, `subscription.renewed`
268
+ - `subscription.paused`, `subscription.resumed`, `subscription.cancelled`
269
+ - `payment.verified`, `payment.refunded`
270
+ - `payment.webhook.{type}` (for webhook events)
271
+
272
+ ## Building Payment Providers
328
273
 
329
- ### Custom Providers
274
+ Create custom providers for Stripe, PayPal, etc.:
330
275
 
331
276
  ```javascript
332
- import { PaymentProvider } from '@classytic/revenue';
277
+ import { PaymentProvider, PaymentIntent, PaymentResult } from '@classytic/revenue';
333
278
 
334
- class MyCustomProvider extends PaymentProvider {
335
- name = 'my-gateway';
279
+ export class StripeProvider extends PaymentProvider {
280
+ constructor(config) {
281
+ super(config);
282
+ this.name = 'stripe';
283
+ this.stripe = new Stripe(config.apiKey);
284
+ }
336
285
 
337
286
  async createIntent(params) {
338
- // Implementation
287
+ const intent = await this.stripe.paymentIntents.create({
288
+ amount: params.amount,
289
+ currency: params.currency,
290
+ });
291
+
292
+ return new PaymentIntent({
293
+ id: intent.id,
294
+ provider: 'stripe',
295
+ status: intent.status,
296
+ amount: intent.amount,
297
+ currency: intent.currency,
298
+ clientSecret: intent.client_secret,
299
+ raw: intent,
300
+ });
339
301
  }
340
302
 
341
303
  async verifyPayment(intentId) {
342
- // Implementation
304
+ const intent = await this.stripe.paymentIntents.retrieve(intentId);
305
+ return new PaymentResult({
306
+ id: intent.id,
307
+ provider: 'stripe',
308
+ status: intent.status === 'succeeded' ? 'succeeded' : 'failed',
309
+ paidAt: new Date(),
310
+ raw: intent,
311
+ });
343
312
  }
344
313
 
345
- getCapabilities() {
346
- return {
347
- supportsWebhooks: true,
348
- supportsRefunds: true,
349
- supportsPartialRefunds: false,
350
- requiresManualVerification: false,
351
- };
352
- }
314
+ // Implement: getStatus(), refund(), handleWebhook()
353
315
  }
354
-
355
- const revenue = createRevenue({
356
- models: { Transaction },
357
- providers: {
358
- 'my-gateway': new MyCustomProvider(),
359
- },
360
- });
361
- ```
362
-
363
- ### DI Container Access
364
-
365
- ```javascript
366
- const revenue = createRevenue({ models: { Transaction } });
367
-
368
- // Access container
369
- const models = revenue.container.get('models');
370
- const providers = revenue.container.get('providers');
371
316
  ```
372
317
 
373
- ## Hook Events
318
+ **See:** [`docs/guides/PROVIDER_GUIDE.md`](../docs/guides/PROVIDER_GUIDE.md) for complete guide.
374
319
 
375
- Available hook events:
320
+ ## TypeScript
376
321
 
377
- - `payment.verified` - Payment verified
378
- - `payment.failed` - Payment failed
379
- - `subscription.created` - Subscription created
380
- - `subscription.renewed` - Subscription renewed
381
- - `subscription.activated` - Subscription activated
382
- - `subscription.cancelled` - Subscription cancelled
383
- - `subscription.paused` - Subscription paused
384
- - `subscription.resumed` - Subscription resumed
385
- - `transaction.created` - Transaction created
386
- - `transaction.updated` - Transaction updated
322
+ Full TypeScript support included:
387
323
 
388
- Hooks are fire-and-forget - they never break the main flow. Errors are logged but don't throw.
324
+ ```typescript
325
+ import { createRevenue, Revenue, PaymentService } from '@classytic/revenue';
326
+ import { TRANSACTION_TYPE, TRANSACTION_STATUS } from '@classytic/revenue/enums';
389
327
 
390
- ## Architecture
328
+ const revenue: Revenue = createRevenue({
329
+ models: { Transaction },
330
+ });
391
331
 
332
+ // All services are fully typed
333
+ const payment = await revenue.payments.verify(id);
334
+ const subscription = await revenue.subscriptions.create({ ... });
392
335
  ```
393
- @classytic/revenue (core package)
394
- ├── Builder (createRevenue)
395
- ├── DI Container
396
- ├── Services (focused on lifecycle)
397
- │ ├── SubscriptionService
398
- │ ├── PaymentService
399
- │ └── TransactionService
400
- ├── Providers
401
- │ ├── base.js (interface)
402
- │ └── manual.js (built-in)
403
- ├── Error classes
404
- └── Schemas & Enums
405
-
406
- @classytic/revenue-stripe (future)
407
- @classytic/revenue-sslcommerz (future)
408
- @classytic/revenue-fastify (framework adapter, future)
409
- ```
410
-
411
- ## Design Principles
412
336
 
413
- - **KISS**: Keep It Simple, Stupid
414
- - **DRY**: Don't Repeat Yourself
415
- - **SOLID**: Single responsibility, focused services
416
- - **Immutable**: Revenue instance is deeply frozen
417
- - **Thin Core**: Core operations only, users extend as needed
418
- - **Smart Defaults**: Works out-of-box with minimal config
337
+ ## Examples
419
338
 
420
- ## Migration from Legacy API
339
+ - [`examples/basic-usage.js`](examples/basic-usage.js) - Quick start guide
340
+ - [`examples/transaction.model.js`](examples/transaction.model.js) - Complete model setup
341
+ - [`examples/transaction-type-mapping.js`](examples/transaction-type-mapping.js) - Income/expense configuration
342
+ - [`examples/complete-flow.js`](examples/complete-flow.js) - Full lifecycle with state management
343
+ - [`examples/multivendor-platform.js`](examples/multivendor-platform.js) - Multi-tenant setup
421
344
 
422
- If you're using the old `initializeRevenue()` API:
345
+ ## Error Handling
423
346
 
424
347
  ```javascript
425
- // Old (legacy API - removed)
426
- import { initializeRevenue, monetization, payment } from '@classytic/revenue';
427
- initializeRevenue({ TransactionModel, transactionService });
428
- await monetization.createSubscription(params);
348
+ import {
349
+ TransactionNotFoundError,
350
+ ProviderNotFoundError,
351
+ AlreadyVerifiedError,
352
+ RefundError,
353
+ } from '@classytic/revenue';
429
354
 
430
- // ✅ New (DI-based API)
431
- import { createRevenue } from '@classytic/revenue';
432
- const revenue = createRevenue({ models: { Transaction } });
433
- await revenue.subscriptions.create(params);
355
+ try {
356
+ await revenue.payments.verify(id);
357
+ } catch (error) {
358
+ if (error instanceof AlreadyVerifiedError) {
359
+ console.log('Already verified');
360
+ } else if (error instanceof TransactionNotFoundError) {
361
+ console.log('Transaction not found');
362
+ }
363
+ }
434
364
  ```
435
365
 
436
366
  ## Documentation
437
367
 
438
- - **[Building Payment Providers](../docs/guides/PROVIDER_GUIDE.md)** - Create custom payment integrations
439
- - **[Examples](../docs/examples/)** - Complete usage examples
440
- - **[Full Documentation](../docs/README.md)** - Comprehensive guides
368
+ - **[Provider Guide](../docs/guides/PROVIDER_GUIDE.md)** - Build custom payment providers
369
+ - **[Architecture](../docs/README.md#architecture)** - System design and patterns
370
+ - **[API Reference](../docs/README.md)** - Complete API documentation
441
371
 
442
372
  ## Support
443
373
 
444
- - **GitHub**: https://github.com/classytic/revenue
445
- - **Issues**: https://github.com/classytic/revenue/issues
446
- - **npm**: https://npmjs.com/package/@classytic/revenue
374
+ - **GitHub**: [classytic/revenue](https://github.com/classytic/revenue)
375
+ - **Issues**: [Report bugs](https://github.com/classytic/revenue/issues)
376
+ - **NPM**: [@classytic/revenue](https://www.npmjs.com/package/@classytic/revenue)
447
377
 
448
378
  ## License
449
379
 
450
- MIT © Classytic (Classytic)
451
-
452
- ---
453
-
454
- **Built with ❤️ following SOLID principles and industry best practices**
380
+ MIT © [Classytic](https://github.com/classytic)