🤝 Affiliates Processing
📖 Overview
The Affiliates module handles all background processing for the affiliate program, including commission calculations, leaderboard generation, and payout expiration tracking.
Environment Flag: QM_AFFILIATES=true
Source Location: queue-manager/crons/affiliates/
Processing Pattern: Scheduled cron-based execution
🗄️ Collections Used
affiliate-payout
- Operations: Read/Write
- Model:
shared/models/affiliate-payout.js - Usage: Track commission payouts and their status
affiliates-leaderboard
- Operations: Create/Update
- Model:
shared/models/affiliates-leaderboard.js - Usage: Store monthly leaderboard rankings
accounts
- Operations: Read
- Model:
shared/models/account.js - Usage: Query affiliate account relationships and referrals
🔄 Processing Flow
graph TB
CRON[Cron Scheduler] -->|Monthly| COMM[Commissions Service]
CRON -->|Daily| LEAD[Leaderboard Service]
CRON -->|Daily| EXPIRE[Expire Payouts Service]
COMM -->|Query| DB[(MongoDB)]
LEAD -->|Query| DB
EXPIRE -->|Query| DB
COMM -->|Add Jobs| COMM_Q[Commissions Queue]
LEAD -->|Calculate| LEAD_CALC[Rankings]
EXPIRE -->|Update| PAYOUT[Payouts]
COMM_Q -->|Process| STRIPE[Stripe API]
LEAD_CALC -->|Store| DB
PAYOUT -->|Update Status| DB
🔧 Jobs in This Module
Core Jobs
- 📘 Commissions - Monthly commission calculations and payouts
- 📗 Leaderboard - Daily affiliate ranking updates
- 📙 Expire Payouts - Daily payout expiration tracking
⚙️ Configuration
Required Environment Variables:
QM_AFFILIATES=true # Enable affiliate processing module
MONGO_DB_URL=... # MongoDB connection
REDIS_HOST=localhost # Redis for Bull queues
REDIS_PORT=6379
📘 Commissions Processing
Overview
Calculates and processes affiliate commissions on a monthly basis, creating payout records and potentially processing payments through Stripe.
Cron Schedule: 0 12 1 * * (Monthly on the 1st at 12:00 PM)
Source Files:
- Cron:
queue-manager/crons/affiliates/commissions.js - Service:
queue-manager/services/affiliates/commissions.js - Queue:
queue-manager/queues/affiliates/commissions.js
Processing Flow
sequenceDiagram
participant CRON as Cron (Monthly)
participant SERVICE as Commissions Service
participant QUEUE as Commissions Queue
participant DB as MongoDB
participant STRIPE as Stripe API
CRON->>SERVICE: Execute monthly
SERVICE->>DB: Query affiliate accounts
DB-->>SERVICE: Affiliate data
SERVICE->>SERVICE: Calculate commissions
SERVICE->>QUEUE: Add commission jobs
QUEUE->>STRIPE: Process payments
STRIPE-->>QUEUE: Payment results
QUEUE->>DB: Store payout records
Key Features
- Monthly Execution: Runs on the 1st of each month
- Commission Calculation: Calculates based on referral revenue
- Payout Creation: Creates
affiliate-payoutrecords - Payment Processing: Optional Stripe integration for automatic payouts
- In-Progress Protection: Prevents concurrent execution
Code Pattern
Cron Initialization (crons/affiliates/commissions.js):
const processCommissions = require('../../services/affiliates/commissions');
const Queue = require('../../queues/affiliates/commissions');
const cron = require('node-cron');
let inProgress = false;
exports.start = async () => {
let Q = await Queue.start();
cron.schedule('0 12 1 * *', async () => {
if (!inProgress) {
inProgress = true;
await processCommissions(Q);
inProgress = false;
}
});
};
Service Logic (services/affiliates/commissions.js):
- Queries affiliate accounts with active referrals
- Calculates commission amounts based on subscription revenue
- Adds jobs to queue for processing
- Handles commission tiers and special rates
Queue Processing (queues/affiliates/commissions.js):
- Processes commission payout jobs
- Creates Stripe transfers (if configured)
- Updates payout status
- Handles payment failures with retry logic
📗 Leaderboard Generation
Overview
Generates daily affiliate leaderboard rankings based on referral performance metrics.
Cron Schedule: 0 2 * * * (Daily at 2:00 AM)
Source Files:
- Cron:
queue-manager/crons/affiliates/leaderboard.js - Service:
queue-manager/services/affiliates/leaderboard.js
Processing Flow
sequenceDiagram
participant CRON as Cron (Daily)
participant SERVICE as Leaderboard Service
participant DB as MongoDB
CRON->>SERVICE: Execute daily
SERVICE->>DB: Query affiliate metrics
DB-->>SERVICE: Referral data, revenue
SERVICE->>SERVICE: Calculate rankings
SERVICE->>DB: Store leaderboard
DB-->>SERVICE: Updated
Key Features
- Daily Updates: Fresh leaderboard rankings every day
- Multiple Metrics: Ranks by referrals, revenue, conversions
- Historical Tracking: Maintains monthly leaderboard archives
- Performance Optimization: Uses aggregation pipelines
Ranking Criteria
Rankings calculated based on:
- Total Referrals: Number of referred accounts
- Active Referrals: Currently active subscriptions
- Revenue Generated: Total subscription revenue from referrals
- Conversion Rate: Referral signups to paid conversions
Code Pattern
Cron Initialization (crons/affiliates/leaderboard.js):
const updateLeaderboard = require('../../services/affiliates/leaderboard');
const cron = require('node-cron');
let inProgress = false;
exports.start = async () => {
cron.schedule('0 2 * * *', async () => {
if (!inProgress) {
inProgress = true;
await updateLeaderboard();
inProgress = false;
}
});
};
Service Logic (services/affiliates/leaderboard.js):
- Aggregates affiliate performance metrics
- Calculates rankings and scores
- Updates
affiliates-leaderboardcollection - Maintains historical data
📙 Payout Expiration
Overview
Tracks and expires unclaimed affiliate payouts after a specified period.
Cron Schedule: 0 3 * * * (Daily at 3:00 AM)
Source Files:
- Cron:
queue-manager/crons/affiliates/expirePayouts.js - Service:
queue-manager/services/affiliates/expirePayouts.js
Processing Flow
sequenceDiagram
participant CRON as Cron (Daily)
participant SERVICE as Expire Service
participant DB as MongoDB
CRON->>SERVICE: Execute daily
SERVICE->>DB: Query pending payouts
DB-->>SERVICE: Old unclaimed payouts
SERVICE->>SERVICE: Check expiration dates
SERVICE->>DB: Update status to 'expired'
DB-->>SERVICE: Updated
Key Features
- Automatic Expiration: Expires payouts after defined period (e.g., 90 days)
- Status Tracking: Updates payout status to
expired - Notification Integration: Can trigger notifications to affiliates
- Grace Period: Configurable expiration threshold
Expiration Logic
Payouts expire if:
- Status is
pendingorapproved - Created date exceeds expiration threshold (default: 90 days)
- No claim action taken by affiliate
- No active dispute on the payout
Code Pattern
Cron Initialization (crons/affiliates/expirePayouts.js):
const expireOldPayouts = require('../../services/affiliates/expirePayouts');
const cron = require('node-cron');
let inProgress = false;
exports.start = async () => {
cron.schedule('0 3 * * *', async () => {
if (!inProgress) {
inProgress = true;
await expireOldPayouts();
inProgress = false;
}
});
};
Service Logic (services/affiliates/expirePayouts.js):
- Queries payouts older than expiration threshold
- Filters by status (
pending,approved) - Bulk updates statuses to
expired - Logs expiration events
🔗 Related Documentation
- Queue Manager Overview
- Architecture (link removed - file does not exist)
- Configuration (link removed - file does not exist)
Module Status: Active
Execution Pattern: Scheduled (Monthly/Daily)
Last Updated: 2025-10-10