Skip to content

Commission Engine (Differential Model)

The IWM Platform uses a Differential Commission Model with 7 income types. Partners earn commissions based on the difference between their rank rate and their downline's rank rate, with unlimited depth.


Commission Model Overview

PropertyValue
Model TypeDifferential (not Unilevel)
DepthUnlimited
Income Types7 (3 Active + 3 Passive + 1 Pool)
Primary CurrencyUSD
Rate Range3% - 20% based on rank

Core Calculation Formula

IF consultant_rank > source_partner_rank:
    commission = (consultant_rate - source_rate) × amount
ELSE:
    commission = 0  // No commission when rank is equal or lower

The 7 Income Types

Active Income (Types 1-3)

TypeNameTriggerCalculation
1Personal SalesDirect sale to own clientpersonal_rate × amount
2Team SalesDownline partner makes saleDifferential on sale amount
3Repeat SalesExisting client repurchasesSame as Personal Sales

Passive Income (Types 4-6)

TypeNameTriggerCalculation
4Portfolio ReturnsOwn investment generates profitStrategy-specific returns
5Client ProfitsPersonal client earns profitpassive_rate × client_profit
6Network ProfitsDownline's client earns profitDifferential on profit amount

Leadership Income (Type 7)

TypeNameTriggerCalculation
7Leadership PoolWeekly/Monthly distributionEqual share among qualified

Calculation Flow

                    Transaction Completed


                    ┌─────────────────────┐
                    │ Identify Income Type│
                    │ (1-7)               │
                    └──────────┬──────────┘


                    ┌─────────────────────┐
                    │ Get Referral        │
                    │ Attribution         │
                    └──────────┬──────────┘


                    ┌─────────────────────┐
                    │ Get Upline Chain    │
                    │ (Unlimited Depth)   │
                    └──────────┬──────────┘


              ┌────────────────────────────────┐
              │ For Each Partner in Upline:    │
              │  1. Get partner rank & rate    │
              │  2. Compare to source rate     │
              │  3. Calculate differential     │
              │  4. Create transaction record  │
              │  5. Update pending balance     │
              └────────────────────────────────┘


                    ┌─────────────────────┐
                    │ Emit Commission     │
                    │ Calculated Events   │
                    └─────────────────────┘

Differential Commission Processor

typescript
interface DifferentialCommissionPayload {
  idempotencyKey: string;
  incomeType:
    | "PERSONAL_SALES"
    | "TEAM_SALES"
    | "REPEAT_SALES"
    | "CLIENT_PROFITS"
    | "NETWORK_PROFITS"
    | "LEADERSHIP_POOL";
  sourceType:
    | "ORDER"
    | "INVESTMENT"
    | "INVESTMENT_PROFIT"
    | "POOL_DISTRIBUTION";
  sourceId: string;
  amountUsd: number;
  sourcePartnerId: string; // Partner who triggered this event
  sourcePartnerRank: string;
  sourcePartnerRate: number;
}

async function processDifferentialCommission(
  job: DifferentialCommissionPayload,
) {
  const {
    idempotencyKey,
    sourceId,
    sourcePartnerId,
    sourcePartnerRate,
    amountUsd,
  } = job;

  // 1. Check idempotency
  const existing = await db.idempotencyKey.findUnique({
    where: { key: idempotencyKey },
  });
  if (existing) return existing.response;

  // 2. Process with proper locking
  return await db.$transaction(
    async (tx) => {
      // 2a. Get ENTIRE upline chain (unlimited depth)
      const upline = await tx.$queryRaw`
      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 mlm.partner_tree_paths ptp
      JOIN mlm.partners p ON p.id = ptp.ancestor_id
      JOIN mlm.ranks r ON r.id = p.current_rank_id
      WHERE ptp.descendant_id = ${sourcePartnerId}::uuid
        AND ptp.depth >= 1
      ORDER BY ptp.depth ASC
    `;

      if (upline.length === 0) {
        await saveIdempotencyKey(tx, idempotencyKey, { commissions: [] });
        return { commissions: [] };
      }

      // 2b. Lock all partner balances in consistent order
      const partnerIds = upline.map((u) => u.partner_id).sort();
      await tx.$queryRaw`
      SELECT id FROM mlm.partner_balances
      WHERE partner_id = ANY(${partnerIds}::uuid[])
      ORDER BY partner_id
      FOR UPDATE
    `;

      // 2c. Calculate differential commissions
      const commissions = [];
      let currentSourceRate = sourcePartnerRate;

      for (const ancestor of upline) {
        if (ancestor.status !== "ACTIVE") continue;

        // Get the appropriate rate based on income type
        const ancestorRate = getApplicableRate(job.incomeType, ancestor);

        // Differential calculation
        const differentialRate = ancestorRate - currentSourceRate;

        if (differentialRate > 0) {
          const grossAmountUsd = amountUsd * (differentialRate / 100);
          const netAmountUsd = grossAmountUsd;

          // Create commission record
          const commission = await tx.commissionTransaction.create({
            data: {
              partnerId: ancestor.partner_id,
              incomeType: job.incomeType,
              sourceType: job.sourceType,
              sourceId,
              sourcePartnerId,
              ownRate: ancestorRate,
              sourceRate: currentSourceRate,
              differentialRate,
              grossAmountUsd,
              netAmountUsd,
              currency: "USD",
              status: "PENDING",
              idempotencyKey: `${idempotencyKey}:${ancestor.partner_id}`,
            },
          });

          // Update pending balance
          await tx.partnerBalance.update({
            where: { partnerId: ancestor.partner_id },
            data: {
              pendingBalanceUsd: { increment: netAmountUsd },
              version: { increment: 1 },
              lastCalculatedAt: new Date(),
              updatedAt: new Date(),
            },
          });

          commissions.push(commission);

          // Update current source rate for next iteration
          currentSourceRate = ancestorRate;
        }

        // Stop if we've reached the maximum rate (20%)
        if (currentSourceRate >= 20) break;
      }

      await saveIdempotencyKey(tx, idempotencyKey, {
        commissionIds: commissions.map((c) => c.id),
      });

      return { commissions };
    },
    {
      isolationLevel: "Serializable",
      timeout: 30000,
    },
  );
}

function getApplicableRate(incomeType: string, partner: any): number {
  switch (incomeType) {
    case "PERSONAL_SALES":
    case "TEAM_SALES":
    case "REPEAT_SALES":
      return partner.personal_sales_rate;
    case "CLIENT_PROFITS":
    case "NETWORK_PROFITS":
      return partner.passive_income_rate;
    default:
      return partner.personal_sales_rate;
  }
}

Passive Income Calculation

Type 5: Client Profits

When a partner's direct client earns profit from an investment:

typescript
async function processClientProfitCommission(
  clientId: string,
  profitAmountUsd: number,
  investmentId: string,
) {
  // Get the partner who referred this client
  const attribution = await db.referralAttribution.findUnique({
    where: { userId: clientId },
  });

  if (!attribution) return;

  const partner = await db.partner.findUnique({
    where: { id: attribution.partnerId },
    include: { rank: true },
  });

  if (!partner || partner.status !== "ACTIVE") return;

  // Calculate passive income
  const passiveRate = partner.rank.passiveIncomeRate;
  const commissionUsd = profitAmountUsd * (passiveRate / 100);

  // Create commission transaction
  await createCommission({
    partnerId: partner.id,
    incomeType: "CLIENT_PROFITS",
    sourceType: "INVESTMENT_PROFIT",
    sourceId: investmentId,
    grossAmountUsd: commissionUsd,
    netAmountUsd: commissionUsd,
  });

  // Trigger network profit calculation for upline
  await triggerNetworkProfitCalculation(partner.id, commissionUsd, passiveRate);
}

Type 6: Network Profits (Differential on Passive Income)

typescript
async function triggerNetworkProfitCalculation(
  sourcePartnerId: string,
  clientProfitAmount: number,
  sourceRate: number,
) {
  // Queue job for differential calculation on network profits
  await boss.send("network-profit-calculation", {
    idempotencyKey: `network-profit:${sourcePartnerId}:${Date.now()}`,
    incomeType: "NETWORK_PROFITS",
    sourceType: "INVESTMENT_PROFIT",
    sourcePartnerId,
    amountUsd: clientProfitAmount,
    sourcePartnerRate: sourceRate,
  });
}

Leadership Pool Distribution

Pool Configuration

PoolRanks% of TurnoverFrequencyQualification
POOL_55, 5_PRO1%Weekly$5,000 / $10,000 weekly volume
POOL_66, 6_PRO0.5%Weekly$20,000 / $30,000 weekly volume
POOL_77, 7_PRO0.5%Weekly$45,000 / $60,000 weekly volume
POOL_88, 8_PRO0.5%Weekly$90,000 / $120,000 weekly volume
POOL_99, 9_PRO1%MonthlyRank achievement only
POOL_1010, 10_PRO1%MonthlyRank achievement only
POOL_1111, 11_PRO1%MonthlyRank achievement only

Note: Pools 9-11 do not require separate volume qualification. Partners who have achieved and maintain these ranks automatically participate in monthly distribution. The rank's turnover requirement ($10M-$800M) serves as the qualification threshold.

Distribution Process

typescript
async function distributeLeadershipPool(
  poolCode: string,
  periodStart: Date,
  periodEnd: Date,
) {
  const pool = await db.leadershipPool.findUnique({
    where: { poolCode },
  });

  // 1. Calculate total company turnover for period
  const totalTurnover = await calculatePeriodTurnover(periodStart, periodEnd);
  const poolAmount = totalTurnover * pool.percentageOfTurnover;

  // 2. Find qualified participants
  const qualifiedPartners = await findQualifiedPartners(
    pool,
    periodStart,
    periodEnd,
  );

  if (qualifiedPartners.length === 0) {
    return { distributed: false, reason: "No qualified participants" };
  }

  // 3. Calculate per-person share
  const perPersonAmount = poolAmount / qualifiedPartners.length;

  // 4. Create distribution record
  const distribution = await db.poolDistribution.create({
    data: {
      poolId: pool.id,
      periodStart,
      periodEnd,
      totalTurnoverUsd: totalTurnover,
      poolAmountUsd: poolAmount,
      qualifiedParticipants: qualifiedPartners.length,
      perPersonAmountUsd: perPersonAmount,
      status: "PROCESSING",
    },
  });

  // 5. Distribute to each qualified partner
  for (const partner of qualifiedPartners) {
    await db.$transaction(async (tx) => {
      // Create participation record
      await tx.poolParticipation.create({
        data: {
          distributionId: distribution.id,
          partnerId: partner.id,
          qualified: true,
          qualificationVolumeUsd: partner.qualificationVolume,
          amountReceivedUsd: perPersonAmount,
          branchVolumes: partner.branchVolumes,
        },
      });

      // Create commission transaction
      await tx.commissionTransaction.create({
        data: {
          partnerId: partner.id,
          incomeType: "LEADERSHIP_POOL",
          sourceType: "POOL_DISTRIBUTION",
          sourceId: distribution.id,
          grossAmountUsd: perPersonAmount,
          netAmountUsd: perPersonAmount,
          currency: "USD",
          status: "APPROVED", // Pool distributions are immediate
        },
      });

      // Add directly to available balance (no pending period for pools)
      await tx.partnerBalance.update({
        where: { partnerId: partner.id },
        data: {
          availableBalanceUsd: { increment: perPersonAmount },
          totalEarnedUsd: { increment: perPersonAmount },
          incomeLeadershipPoolUsd: { increment: perPersonAmount },
          version: { increment: 1 },
          updatedAt: new Date(),
        },
      });
    });
  }

  // 6. Mark distribution as complete
  await db.poolDistribution.update({
    where: { id: distribution.id },
    data: {
      status: "DISTRIBUTED",
      distributedAt: new Date(),
    },
  });

  return {
    distributed: true,
    poolAmount,
    participants: qualifiedPartners.length,
    perPerson: perPersonAmount,
  };
}

50% Branch Rule Validation

typescript
async function findQualifiedPartners(
  pool: LeadershipPool,
  periodStart: Date,
  periodEnd: Date,
) {
  const eligibleRanks = pool.eligibleRanks;
  const qualificationVolumes = pool.qualificationVolumes as Record<
    string,
    number
  >;

  // Get all partners with eligible ranks
  const candidates = await db.partner.findMany({
    where: {
      status: "ACTIVE",
      rank: { code: { in: eligibleRanks } },
    },
    include: { rank: true },
  });

  const qualifiedPartners = [];

  for (const partner of candidates) {
    const requiredVolume = qualificationVolumes[partner.rank.code];

    // Calculate branch volumes
    const branchVolumes = await calculateBranchVolumes(
      partner.id,
      periodStart,
      periodEnd,
    );

    // Apply 50% cap per branch
    const maxPerBranch = requiredVolume * 0.5;
    const cappedTotal = Object.values(branchVolumes).reduce(
      (sum, vol) => sum + Math.min(vol, maxPerBranch),
      0,
    );

    if (cappedTotal >= requiredVolume) {
      qualifiedPartners.push({
        ...partner,
        qualificationVolume: cappedTotal,
        branchVolumes,
      });
    }
  }

  return qualifiedPartners;
}

async function calculateBranchVolumes(
  partnerId: string,
  periodStart: Date,
  periodEnd: Date,
): Promise<Record<string, number>> {
  // Get direct referrals (branch roots)
  const directReferrals = await db.partner.findMany({
    where: { sponsorId: partnerId },
  });

  const branchVolumes: Record<string, number> = {};

  for (const branch of directReferrals) {
    // Get all descendants of this branch
    const branchDescendants = await db.partnerTreePath.findMany({
      where: { ancestorId: branch.id },
    });

    const descendantIds = branchDescendants.map((d) => d.descendantId);
    descendantIds.push(branch.id);

    // Sum turnover for this branch
    const turnover = await db.commissionTransaction.aggregate({
      where: {
        sourcePartnerId: { in: descendantIds },
        createdAt: { gte: periodStart, lte: periodEnd },
        incomeType: { in: ["PERSONAL_SALES", "REPEAT_SALES"] },
      },
      _sum: { grossAmountUsd: true },
    });

    branchVolumes[branch.id] = turnover._sum.grossAmountUsd || 0;
  }

  return branchVolumes;
}

Batch Processing Schedule

JobFrequencyTimeDescription
Commission ApprovalDaily02:00 UTCMove pending to approved
Balance SettlementDaily03:00 UTCMove approved to available
Weekly Pool DistributionSunday23:00 UTCDistribute Pools 5-8
Monthly Pool Distribution1st of month01:00 UTCDistribute Pools 9-11
Rank RecalculationHourly:00Check for rank promotions

Commission Status Flow

PENDING → APPROVED → PAID

 REVERSED/CLAWBACK (if refund/chargeback)
StatusDescriptionBalance Impact
PENDINGCalculated, awaiting holding period+pending_balance
APPROVEDHolding period completepending → available
PAIDIn partner's available balanceAlready in available
REVERSEDOrder refunded before payout-pending_balance
CLAWBACKOrder refunded after payout-available_balance