MLM Module (Partners, Referrals, Commissions, Ranks)
Overview
The MLM (Multi-Level Marketing) Module is the core business engine of the IWM Platform. It manages the partner network, referral tracking, commission calculations, rank advancement, and payout processing. This module implements a Differential Commission Model with 7 income types where partners earn commissions based on the difference between their rank rate and their downline's rank rate, with unlimited depth.
Key Features
| Feature | Description |
|---|---|
| Commission Model | Differential (not Unilevel) |
| Depth | Unlimited |
| Income Types | 7 (3 Active + 3 Passive + 1 Leadership Pool) |
| Primary Currency | USD |
| Ranks | 21 (Consultant 0-11 with PRO variants) |
| Rank Maintenance | Non-expiring (ranks never decrease) |
Responsibilities
- Partner registration and lifecycle management
- Referral link generation and attribution tracking
- Network tree structure management (closure table)
- Rank qualification and progression
- Commission calculation (differential model)
- 7 income types processing
- Leadership pool distribution
- Balance management (pending, available)
- Payout request processing
Domain Entities
Partner
The central entity representing an MLM network member.
| Field | Type | Description |
|---|---|---|
| id | UUID | Partner identifier |
| user_id | UUID | Reference to core.users |
| sponsor_id | UUID | Direct upline partner |
| referral_code | VARCHAR(20) | Unique referral code |
| status | ENUM | Partner status |
| current_rank_id | UUID | Current rank |
| highest_rank_id | UUID | Highest achieved rank (same as current - non-expiring) |
| direct_referrals_count | INT | Direct downline count |
| total_network_size | INT | Total network size |
| tree_depth | INT | Depth in tree from root |
| total_structure_turnover_usd | DECIMAL | Total structure turnover in USD |
| personal_turnover_usd | DECIMAL | Personal turnover in USD |
| is_activated | BOOLEAN | Has made $1,100 personal purchase |
| joined_at | TIMESTAMP | Registration timestamp |
| activated_at | TIMESTAMP | Rank 1 activation timestamp |
PartnerTreePath
Closure table for efficient tree queries (unlimited depth).
| Field | Type | Description |
|---|---|---|
| ancestor_id | UUID | Ancestor partner |
| descendant_id | UUID | Descendant partner |
| depth | INT | Distance between nodes |
ReferralLink
Trackable referral links for attribution.
| Field | Type | Description |
|---|---|---|
| id | UUID | Link identifier |
| partner_id | UUID | Owning partner |
| code | VARCHAR(20) | Unique link code |
| name | VARCHAR(100) | Link label (Instagram, YouTube) |
| target_url | VARCHAR(500) | Custom landing page |
| utm_source | VARCHAR(100) | UTM source parameter |
| utm_medium | VARCHAR(100) | UTM medium parameter |
| utm_campaign | VARCHAR(100) | UTM campaign parameter |
| clicks_count | INT | Total clicks |
| registrations_count | INT | Registrations from link |
| conversions_count | INT | Conversions (purchases/investments) |
| is_active | BOOLEAN | Link active status |
| expires_at | TIMESTAMP | Optional expiration |
ReferralAttribution
Tracks referral source for users.
| Field | Type | Description |
|---|---|---|
| id | UUID | Attribution identifier |
| user_id | UUID | Referred user |
| partner_id | UUID | Referring partner |
| link_id | UUID | Source link (optional) |
| attribution_type | ENUM | FIRST_TOUCH or LAST_TOUCH |
| first_touch_at | TIMESTAMP | First interaction |
| last_touch_at | TIMESTAMP | Last interaction |
| converted_at | TIMESTAMP | Conversion timestamp |
| cookie_id | VARCHAR(100) | Tracking cookie ID |
Rank
MLM rank definitions (21-tier system).
| Field | Type | Description |
|---|---|---|
| id | UUID | Rank identifier |
| code | VARCHAR(20) | Unique code (0, 1, 2, ..., 11, 4_PRO, ..., 11_PRO) |
| name | VARCHAR(100) | Display name (Consultant 0, Consultant 1, etc.) |
| level | INT | Rank level (0-21) |
| is_pro | BOOLEAN | PRO variant flag |
| turnover_requirement_usd | DECIMAL | Total structure turnover required |
| personal_sales_rate | DECIMAL | Rate for active income (3%-20%) |
| entrance_fee_rate | DECIMAL | Rate for investment entrance fees (10.5%-20%) |
| passive_income_rate | DECIMAL | Rate for passive income (0%-20%) |
| leadership_pool_eligible | BOOLEAN | Eligible for leadership pools |
| description | TEXT | Rank description |
| badge_url | VARCHAR(500) | Rank badge image |
| color_code | VARCHAR(20) | Brand color |
| is_active | BOOLEAN | Rank available |
CommissionTransaction
Individual commission record with income type.
| Field | Type | Description |
|---|---|---|
| id | UUID | Transaction identifier |
| partner_id | UUID | Receiving partner |
| income_type | ENUM | 7 income types |
| source_type | ENUM | ORDER, INVESTMENT, INVESTMENT_PROFIT, POOL_DISTRIBUTION |
| source_id | UUID | Source entity ID |
| source_partner_id | UUID | Partner who triggered this commission |
| own_rate | DECIMAL | Partner's applicable rate |
| source_rate | DECIMAL | Source partner's rate |
| differential_rate | DECIMAL | Difference between rates |
| gross_amount_usd | DECIMAL | Amount before deductions |
| net_amount_usd | DECIMAL | Final amount |
| currency | VARCHAR(3) | Currency (USD) |
| status | ENUM | Transaction status |
| period_id | VARCHAR(20) | Accounting period |
| idempotency_key | VARCHAR(255) | Duplicate prevention |
PartnerBalance
Partner financial state in USD.
| Field | Type | Description |
|---|---|---|
| id | UUID | Balance identifier |
| partner_id | UUID | Partner reference |
| available_balance_usd | DECIMAL | Withdrawable amount |
| pending_balance_usd | DECIMAL | Awaiting holding period |
| total_earned_usd | DECIMAL | Lifetime earnings |
| total_withdrawn_usd | DECIMAL | Lifetime withdrawals |
| income_personal_sales_usd | DECIMAL | Type 1 lifetime earnings |
| income_team_sales_usd | DECIMAL | Type 2 lifetime earnings |
| income_repeat_sales_usd | DECIMAL | Type 3 lifetime earnings |
| income_portfolio_returns_usd | DECIMAL | Type 4 lifetime earnings |
| income_client_profits_usd | DECIMAL | Type 5 lifetime earnings |
| income_network_profits_usd | DECIMAL | Type 6 lifetime earnings |
| income_leadership_pool_usd | DECIMAL | Type 7 lifetime earnings |
| currency | VARCHAR(3) | Balance currency (USD) |
| version | INT | Optimistic lock version |
| last_calculated_at | TIMESTAMP | Last commission calculation |
LeadershipPool
Leadership pool configuration.
| Field | Type | Description |
|---|---|---|
| id | UUID | Pool identifier |
| pool_code | VARCHAR(20) | Unique code (POOL_5, POOL_6, etc.) |
| eligible_ranks | VARCHAR[] | Ranks eligible for this pool |
| percentage_of_turnover | DECIMAL | Percentage of company turnover |
| distribution_frequency | ENUM | WEEKLY or MONTHLY |
| qualification_volumes | JSONB | Required volumes by rank |
| is_active | BOOLEAN | Pool active status |
PoolDistribution
Record of pool distribution event.
| Field | Type | Description |
|---|---|---|
| id | UUID | Distribution identifier |
| pool_id | UUID | Reference to leadership pool |
| period_start | TIMESTAMP | Period start date |
| period_end | TIMESTAMP | Period end date |
| total_turnover_usd | DECIMAL | Total company turnover |
| pool_amount_usd | DECIMAL | Total pool amount |
| qualified_participants | INT | Number of qualified partners |
| per_person_amount_usd | DECIMAL | Amount per participant |
| status | ENUM | PROCESSING, DISTRIBUTED |
| distributed_at | TIMESTAMP | Distribution completion time |
PayoutRequest
Withdrawal request from partner.
| Field | Type | Description |
|---|---|---|
| id | UUID | Request identifier |
| partner_id | UUID | Requesting partner |
| amount_usd | DECIMAL | Requested amount in USD |
| currency | VARCHAR(3) | Currency code |
| payout_method_type | ENUM | BANK_CARD, BANK_TRANSFER, CRYPTO, EWALLET |
| payout_details | JSONB | Encrypted payment info |
| status | ENUM | Request status |
| rejection_reason | TEXT | If rejected |
| processed_by | UUID | Admin who processed |
| external_reference | VARCHAR(255) | Payment provider reference |
Partner Lifecycle
Registration Flow
Partner Status Flow
Rank 0 to Rank 1 Activation
The transition from Rank 0 to Rank 1 unlocks the full marketing plan:
| Requirement | Details |
|---|---|
| Personal Purchase | Minimum $1,100 personal purchase |
| Qualifying Products | Si14 AG shares OR any investment product |
| Unlocks | Full marketing plan with all 7 income types |
Referral System
Link Generation
Partners can create multiple referral links for different channels:
UTM Parameter Tracking
Links support full UTM tracking:
| Parameter | Example | Purpose |
|---|---|---|
| utm_source | Traffic source | |
| utm_medium | social | Marketing medium |
| utm_campaign | summer_2024 | Campaign identifier |
Cookie-Based Attribution
Attribution Rules:
- Cookie lifetime: 30 days
- Attribution type: Last-touch (most recent referrer wins)
- Override: New referral link click updates attribution
- Persistence: Attribution locked at conversion (purchase/investment)
Tree Structure
Closure Table Pattern (Unlimited Depth)
The partner network uses a closure table for efficient hierarchical queries with unlimited depth:
Key Queries
Get Direct Referrals (Level 1):
SELECT descendant_id FROM partner_tree_paths
WHERE ancestor_id = :partner_id AND depth = 1Get Full Downline (Unlimited Depth):
SELECT descendant_id, depth FROM partner_tree_paths
WHERE ancestor_id = :partner_id AND depth > 0
ORDER BY depthGet Upline Chain (For Differential Commission):
SELECT
p.id as partner_id,
p.status,
r.code as rank_code,
r.personal_sales_rate,
r.passive_income_rate,
r.entrance_fee_rate,
ptp.depth
FROM partner_tree_paths ptp
JOIN partners p ON p.id = ptp.ancestor_id
JOIN ranks r ON r.id = p.current_rank_id
WHERE ptp.descendant_id = :partner_id AND ptp.depth >= 1
ORDER BY ptp.depth ASCRank System
21-Tier Rank Hierarchy
Commission Rates by Rank
| Rank | Turnover ($) | Personal Sales | Entrance Fee | Passive Income |
|---|---|---|---|---|
| 0 | 0 | 3% | 10.5% | 0% |
| 1 | 1,100 | 5% | 11% | 5% |
| 2 | 10,000 | 8% | 11.5% | 8% |
| 3 | 50,000 | 10% | 12% | 10% |
| 4 | 100,000 | 12% | 12.5% | 12% |
| 4_PRO | 200,000 | 13% | 13% | 13% |
| 5 | 400,000 | 14% | 13.5% | 14% |
| 5_PRO | 700,000 | 15% | 14% | 15% |
| 6 | 1,000,000 | 16% | 14.5% | 16% |
| 6_PRO | 1,500,000 | 16.5% | 15% | 16.5% |
| 7 | 2,000,000 | 17% | 15.5% | 17% |
| 7_PRO | 3,000,000 | 17.5% | 16% | 17.5% |
| 8 | 5,000,000 | 18% | 16.5% | 18% |
| 8_PRO | 7,000,000 | 18.5% | 17% | 18.5% |
| 9 | 10,000,000 | 19% | 17.5% | 19% |
| 9_PRO | 15,000,000 | 19.25% | 18% | 19.25% |
| 10 | 25,000,000 | 19.5% | 18.5% | 19.5% |
| 10_PRO | 50,000,000 | 19.75% | 19% | 19.75% |
| 11 | 100,000,000 | 20% | 19.5% | 20% |
| 11_PRO | 800,000,000 | 20% | 20% | 20% |
Rank Qualification Rules
| Rule | Description |
|---|---|
| Automatic Advancement | Ranks increase immediately when turnover threshold is met |
| Non-Expiring | Once achieved, ranks never expire or decrease |
| No Maintenance | No monthly maintenance requirements |
| Instant Benefits | Commission rates apply immediately upon rank change |
Rank 0 vs Rank 1+
| Capability | Rank 0 | Rank 1+ |
|---|---|---|
| Referral Link | Yes | Yes |
| Personal Sales Commission | 3% | 5%-20% |
| Team Sales (Differential) | No | Yes |
| Passive Income | No | Yes |
| Leadership Pools | No | Rank 5+ |
The 7 Income Types
Overview
Active Income (Types 1-3)
| Type | Name | Trigger | Calculation |
|---|---|---|---|
| 1 | Personal Sales | Direct sale to own client | personal_rate × amount |
| 2 | Team Sales | Downline partner makes sale | Differential on sale amount |
| 3 | Repeat Sales | Existing client repurchases | Same as Personal Sales |
Passive Income (Types 4-6)
| Type | Name | Trigger | Calculation |
|---|---|---|---|
| 4 | Portfolio Returns | Own investment generates profit | Strategy-specific returns |
| 5 | Client Profits | Personal client earns profit | passive_rate × client_profit |
| 6 | Network Profits | Downline's client earns profit | Differential on profit amount |
Leadership Income (Type 7)
| Type | Name | Trigger | Calculation |
|---|---|---|---|
| 7 | Leadership Pool | Weekly/Monthly distribution | Equal share among qualified |
Commission Calculation
Differential Commission Model
The core formula for Team Sales and Network Profits:
IF consultant_rank > source_partner_rank:
commission = (consultant_rate - source_rate) × amount
ELSE:
commission = 0 // No commission when rank is equal or lowerDifferential Calculation Flow
Commission Example
Scenario: Partner at Rank 2 (8% rate) makes a $10,000 sale
| Upline Partner | Rank | Rate | Differential | Commission |
|---|---|---|---|---|
| Source Partner | 2 | 8% | N/A (Personal Sales) | $800 |
| Direct Sponsor | 4 | 12% | 12% - 8% = 4% | $400 |
| Level 2 | 5 | 14% | 14% - 12% = 2% | $200 |
| Level 3 | 6 | 16% | 16% - 14% = 2% | $200 |
| Level 4 | 6 | 16% | 16% - 16% = 0% | $0 |
| Level 5 | 11 | 20% | 20% - 16% = 4% | $400 |
| Level 6+ | Any | Any | All remaining | $0 (max rate reached) |
Total distributed: $800 + $400 + $200 + $200 + $400 = $2,000 (20% of sale)
Commission Triggers
| Trigger | Source Type | Income Types |
|---|---|---|
| Order Completed | ORDER | Personal Sales, Team Sales, Repeat Sales |
| Investment Activated | INVESTMENT | Personal Sales (entrance fee), Team Sales |
| Investment Profit | INVESTMENT_PROFIT | Client Profits, Network Profits |
| Pool Distribution | POOL_DISTRIBUTION | Leadership Pool |
Commission Status Flow
| Status | Description | Balance Impact |
|---|---|---|
| PENDING | Calculated, awaiting holding period | +pending_balance |
| APPROVED | Holding period complete | pending → available |
| PAID | In partner's available balance | Already in available |
| REVERSED | Order refunded before payout | -pending_balance |
| CLAWBACK | Order refunded after payout | -available_balance |
Leadership Pools
Pool Configuration
| Pool | Eligible Ranks | % of Turnover | Frequency | Qualification |
|---|---|---|---|---|
| POOL_5 | 5, 5_PRO | 1% | Weekly | $5,000 / $10,000 weekly volume |
| POOL_6 | 6, 6_PRO | 0.5% | Weekly | $20,000 / $30,000 weekly volume |
| POOL_7 | 7, 7_PRO | 0.5% | Weekly | $45,000 / $60,000 weekly volume |
| POOL_8 | 8, 8_PRO | 0.5% | Weekly | $90,000 / $120,000 weekly volume |
| POOL_9 | 9, 9_PRO | 1% | Monthly | Rank achievement only |
| POOL_10 | 10, 10_PRO | 1% | Monthly | Rank achievement only |
| POOL_11 | 11, 11_PRO | 1% | Monthly | Rank achievement only |
Note: Pools 9-11 do not require separate volume qualification. Partners who achieve and maintain these ranks automatically participate in monthly distribution. The rank's turnover requirement ($10M-$800M) serves as the qualification threshold.
50% Branch Rule (Pools 5-8 only)
No single branch (direct downline leg) can contribute more than 50% of qualification volume:
Example:
- Required qualification: $10,000
- Branch A volume: $80,000 → counts as max $5,000 (50% cap)
- Branch B volume: $15,000 → counts as $5,000+ (remainder needed)
- Result: Qualified (diverse structure)Distribution Process
Balance Management
Balance Types
Pending Period by Source
| Source Type | Pending Period | Reason |
|---|---|---|
| Product Order | 14 days | Refund/return window |
| Investment | 7 days | Fund verification |
| Passive Income | 7 days | Profit confirmation |
| Leadership Pool | 0 days | Immediate upon distribution |
Income Breakdown
Balance tracks earnings by income type:
| Field | Income Type |
|---|---|
| income_personal_sales_usd | Type 1: Personal Sales |
| income_team_sales_usd | Type 2: Team Sales |
| income_repeat_sales_usd | Type 3: Repeat Sales |
| income_portfolio_returns_usd | Type 4: Portfolio Returns |
| income_client_profits_usd | Type 5: Client Profits |
| income_network_profits_usd | Type 6: Network Profits |
| income_leadership_pool_usd | Type 7: Leadership Pool |
Concurrency Safety
Balance operations use optimistic locking with version numbers:
// Example: Update balance with version check
const result = await tx.partnerBalance.update({
where: {
partnerId: partner.id,
version: expectedVersion,
},
data: {
pendingBalanceUsd: { increment: amount },
version: { increment: 1 },
updatedAt: new Date(),
},
});Payout System
Payout Request Flow
Payout Rules
- Minimum Amount: $100 USD minimum withdrawal
- Single Pending: Only one pending payout per partner
- KYC Required: STANDARD KYC level required
- Balance Deduction: Amount deducted immediately on request
- Failure Refund: Balance restored if payment fails
- Partner Status: Must be ACTIVE to request payout
Payout Methods
| Method | Provider | Processing Time |
|---|---|---|
| Bank Card | Stripe/YooKassa | 1-3 business days |
| Bank Transfer | Manual | 3-5 business days |
| Crypto | Various | Same day |
| E-Wallet | Various | Same day |
Events Published
| Event | Trigger | Payload |
|---|---|---|
| PartnerRegistered | New partner created | partnerId, userId, sponsorId |
| PartnerActivated | $1,100 purchase (Rank 0→1) | partnerId, activationType |
| PartnerStatusChanged | Status transition | partnerId, fromStatus, toStatus |
| ReferralLinkCreated | New link created | linkId, partnerId, code |
| ReferralLinkClicked | Link visited | linkId, partnerId, visitorInfo |
| ReferralAttributed | User attributed to partner | userId, partnerId, linkId |
| CommissionCalculated | Commission created | transactionId, partnerId, incomeType, amount |
| CommissionApproved | Holding period complete | transactionId, partnerId, amount |
| CommissionPaid | Commission moved to available | transactionId, partnerId, amount |
| CommissionReversed | Commission reversed | transactionId, partnerId, reason |
| BalanceUpdated | Balance changed | partnerId, type, amount, newBalance |
| PayoutRequested | Payout submitted | payoutId, partnerId, amount |
| PayoutApproved | Payout approved | payoutId, partnerId |
| PayoutCompleted | Payout processed | payoutId, partnerId, reference |
| PayoutRejected | Payout rejected | payoutId, partnerId, reason |
| RankChanged | Rank promotion | partnerId, fromRank, toRank |
| PoolDistributed | Leadership pool paid | poolId, amount, participants |
Events Consumed
| Event | Source | Handler |
|---|---|---|
| UserRegistered | Core | Create partner if referral code present |
| OrderCompleted | Commerce | Calculate Personal/Team/Repeat Sales |
| OrderRefunded | Commerce | Reverse commissions |
| InvestmentActivated | Investment | Calculate entrance fee commissions |
| InvestmentProfitDistributed | Investment | Calculate Client/Network Profits |
Business Rules and Invariants
Partner Rules
- One partner per user (1:1 relationship)
- Partner cannot sponsor themselves
- Sponsor cannot be changed after registration
- Only ACTIVE partners earn commissions
- TERMINATED partners cannot be reactivated
- All partners start at Rank 0
Commission Rules
- Commissions calculated only for ACTIVE upline partners
- Unlimited depth for differential commissions
- Differential stops when rate reaches 20%
- Idempotency key prevents duplicate commissions
- Reversed/cancelled source reverses all related commissions
- Leadership pool distributions are immediate (no pending period)
Rank Rules
- Ranks are non-expiring (never decrease)
- Rank advancement is automatic upon meeting turnover threshold
- Rank 0→1 requires $1,100 personal purchase
- All subsequent ranks qualify on Total Structure Turnover
- Commission rates apply immediately upon rank change
Balance Rules
- Available balance cannot be negative
- Pending balance cannot be negative
- Version must match for update (optimistic locking)
- Total earned >= total withdrawn + available + pending
Payout Rules
- Only one pending/processing payout per partner
- Minimum withdrawal: $100 USD
- KYC verification required
- Partner must be ACTIVE to request payout
Integration Points
Provides to Other Modules
| Interface | Consumers | Purpose |
|---|---|---|
| IPartnerLookupService | Commerce, Investment | Get partner by referral code |
| ICommissionService | Commerce, Investment | Trigger commission calculation |
| IAttributionService | Commerce, Investment | Get referral attribution for user |
| IPassiveIncomeService | Investment | Trigger client/network profit calculations |
Consumes from Other Modules
| Interface | Provider | Purpose |
|---|---|---|
| IUserLookupService | Core | Get user profile data |
| IKycStatusService | Core | Check KYC level for payouts |
| IInvestmentProfitService | Investment | Get profit data for passive income |