MLM & Affiliate System 6.1.1

29 July 2026

This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.

MONEY FLOWCOMMISSIONSMLM LEVELSSETTINGSPAYOUTSPROFIT REPORTINGKYCMULTI CURRENCYDESIGN SYSTEM

MLM & Affiliate v6.1.1

Release Date: July 29, 2026 Tags: MONEY FLOW, COMMISSIONS, MLM LEVELS, SETTINGS, PAYOUTS, PROFIT REPORTING, KYC, MULTI CURRENCY, DESIGN SYSTEM

Overview

Version 6.1.1 fixes how much the affiliate program actually pays.

Commissions were being paid twice. There are two reward engines — one that fires the moment a transaction happens and one that reviews activity on a schedule — and they did not know about each other. Separately, the top of every chain was overpaid: a member with no sponsor of their own is recorded as their own referrer, and walking up the chain from there returned that same person forever. And four settings on the affiliate screen — Require Approval, Maximum Commission Rate, Payout Threshold and Default Commission Rate — were configurable and ignored.

Reported profit will fall. Commissions claimed by affiliates were money leaving the platform that nothing recorded, so Admin → Finance → Profit reported fees collected as though they were profit kept. Every claim now debits the platform's own wallet, by exactly what your programme was already paying out.

Four of the steps below look for money and settings a past defect has already left wrong. Run them.

Requires Core v6.5.8.

Update Instructions

pnpm updator

Then, in this order:

1. Restart the backend

pm2 restart all

2. Find commissions that were paid twice

Rewards created by the periodic evaluator for a condition that also has a live trigger are duplicates of a reward the transaction already paid. The evaluator's rewards are recognisable by their sourceId shape — <conditionId>_<referrerId>_<referredId>_<period> — while the event path writes <CONDITION>:<source>:<id>:

SELECT r.id, r.referrerId, r.reward, r.isClaimed, c.name AS condition, r.createdAt
FROM mlm_referral_reward r
JOIN mlm_referral_condition c ON c.id = r.conditionId
WHERE r.sourceId LIKE CONCAT(r.conditionId, '\_%')
  AND c.name IN (
    'WELCOME_BONUS','ECOMMERCE_PURCHASE','ICO_CONTRIBUTION','STAKING','STAKING_LOYALTY',
    'AI_INVESTMENT','INVESTMENT','GENERAL_INVESTMENT','FOREX_INVESTMENT','NFT_PURCHASE',
    'NFT_SALE','P2P_TRADE','P2P_TRADE_COMPLETION','COPY_TRADING','FUTURES_TRADE',
    'BINARY_WIN','BINARY_TRADE_VOLUME','FX_TRADE_COMMISSION','FX_TRADE_VOLUME'
  )
ORDER BY r.createdAt DESC;

Rows still showing isClaimed = 0 can simply be deleted. Rows already claimed were paid into a wallet — decide whether to write them off or recover them; this release does not touch history.

3. Find sponsors overpaid by the self-referral walk

On a BINARY or UNILEVEL structure, a member at the top of a chain received one reward per remaining level from a single transaction. They share a sourceId prefix and differ only in the :L<n> suffix:

SELECT referrerId, SUBSTRING_INDEX(sourceId, ':L', 1) AS source,
       COUNT(*) AS levelsPaid, SUM(reward) AS totalPaid
FROM mlm_referral_reward
WHERE sourceId LIKE '%:L%'
GROUP BY referrerId, source
HAVING levelsPaid > 1;

Any row here paid one member at more than one level for the same transaction. Only the lowest :L<n> is genuine.

4. Repair any condition with a blank type

A condition whose type is empty can never be matched by the periodic evaluator, and cannot be saved from the admin screen. On installs where the server was not running in strict mode, MySQL accepted an empty value into that field:

SELECT id, name, type FROM mlm_referral_condition WHERE type = '' OR type IS NULL;
-- e.g. BINARY_TRADE_VOLUME should be BINARY_WIN, matching the seeder and its siblings
UPDATE mlm_referral_condition SET type = 'BINARY_WIN'
 WHERE name = 'BINARY_TRADE_VOLUME' AND (type = '' OR type IS NULL);

5. Check the three settings that just became real

Open Admin → Affiliate → Settings before traffic hits it:

  • Require Approval now decides what it says it decides. If the switch is OFF but your referrals have been landing as PENDING, they will now go straight to ACTIVE and start earning.
  • Maximum Commission Rate now caps what a condition may award. If any existing condition awards a higher percentage than the limit, it keeps working — the cap applies when a condition is next saved — but you will not be able to save it until the limit is raised.
  • Payout Threshold now holds claims back until an affiliate's unclaimed balance reaches it. It defaults to 50 on most installs. Set it to 0 if you do not want a minimum, or affiliates below the threshold will be unable to withdraw.

Upgrade Notes

None in setup. Nine behaviour changes worth knowing:

  • Commission totals will drop. The duplicate scheduled payout is gone, and the top of each chain is paid once instead of once per level. What remains is what your configuration actually specifies.
  • Reported profit will fall. Commissions claimed from this release onward are recorded as a cost and taken out of the platform wallet. Nothing claimed before the upgrade is backfilled.
  • Volume and period-total conditions count only activity in their own reward currency. Qualifying totals change, and members who qualified purely on foreign-currency activity stop qualifying.
  • The Require Approval switch now takes effect, in whichever direction it is currently set.
  • Claims below the payout threshold are refused. Set the threshold to 0 to restore the previous behaviour.
  • A condition awarding more than the maximum commission rate can no longer be saved. Existing conditions keep working until they are next edited.
  • Pending and rejected referrals are no longer in the tree. Existing entries are left alone; the change applies to referrals decided from now on.
  • "Default Commission Rate" is gone from the settings screen. It controlled nothing; the stored value is simply ignored.
  • Where per-feature verification is enforced, the affiliate dashboard and the claim button are gated. Installs that do not enforce it are unaffected.

Changed

The affiliate dashboard is now behind the affiliate verification gate

Where Enforce KYC Feature Access is switched on, a member whose verification level does not carry the Affiliate Program feature can no longer open the affiliate dashboard: the referral link, QR code, share buttons, earnings charts and referral list are replaced by a verification prompt. Previously the dashboard was viewable by anyone and verification was only checked when a member tried to act on it.

  • Applies to installs running per-feature KYC enforcement. It is off by default; where it is off, the dashboard behaves exactly as before.

Claiming a commission now requires verification

Where Enforce KYC Feature Access is switched on, an affiliate whose verification level does not carry the Affiliate Payouts feature can still see everything they have earned but can no longer claim it. The claim dialog shows a verification notice in place of the amount and the button, and a claim attempted anyway is refused rather than paid.

  • Applies to installs running per-feature KYC enforcement. It is off by default; where it is off, claiming behaves exactly as before.

Claimed commissions are now recorded as a cost against platform profit

Until now, Admin → Finance → Profit counted only what the platform collected. Fees earned were recorded; the commissions paid out of them were not. A programme paying out more than it earned still read as healthy, because the number on the screen was gross revenue presented as net.

Claiming a referral reward now writes an offsetting negative entry against profit and debits the platform's own (Super Admin) wallet at the same moment the affiliate is credited.

  • Reported profit will drop, by the value of every commission claimed from this release onward — money that was already leaving the platform and simply was not being counted. History is not rewritten; nothing claimed before the upgrade is backfilled.
  • The platform wallet balance moves. Referral payouts now come out of it in the reward's own currency and wallet type, so the balance reflects what the programme has actually cost.
  • A thin balance never blocks a claim. Only what the platform wallet actually holds is debited; any shortfall is logged for the operator and the full commission is still recorded against profit. The affiliate is paid in full either way.

The public affiliate page was rebuilt, and its promises rewritten

The affiliate landing page has a new layout and new artwork. The animated orb and particle background and the scroll indicator are gone, and the two-card call to action at the foot is now a single closing block.

The copy changed materially, and deliberately. The old page advertised "No approval required", "Instant Payouts", "No minimums" and "Withdraw anytime, no minimum threshold" — claims this same release makes untrue, now that Require Approval and Payout Threshold actually do what they say. The page now reads "Recurring commission · weekly payouts · full attribution".

  • Worth checking: read the new page against how your programme is actually configured, particularly your payout threshold and whether referrals need approving.

The affiliate area was rebuilt on the platform's design system

Every affiliate screen now draws on the platform's shared colours instead of its own blue-to-amber gradient identity: a single accent plus the shared success and warning tones. Cards are flatter — gradients, glow blobs and heavy shadows are gone — hero spacing is tighter, statistics blocks use the shared stat card, and figures are set in a tabular monospaced face so columns of numbers line up.

  • Every chart was replaced. Charts on the admin affiliate dashboard and on the member dashboard now use the platform's shared chart cards: different card framing, tooltips and colours, with legends moved into the card footer. Charts with nothing to plot now say so instead of drawing an empty axis.
  • Two charts stopped lying. The member "Reward sources" ring drew a full grey circle labelled "No Rewards Yet" when there was nothing to show — a placeholder that read as data — and now shows a plain empty state. The admin account-status ring used its own colours for active, pending and suspended; it now follows the platform's shared status colours, and is shorter.
  • The condition details popup is now a real dialog: escape closes it, focus stays inside it, and the page behind it stops scrolling. It was previously a hand-built overlay with none of that.
  • The admin condition list collapses fifteen per-type hues onto one accent, so the list reads as a list rather than a colour chart.
  • The leaderboard drops gold, silver and bronze: first place is accented, second and third share a neutral.

Smaller corrections

  • A pending referral now looks like something that needs attention. A referral awaiting approval shows in a warning tone instead of the same inert grey used for anything unrecognised — and since no commission is paid on a pending referral, that distinction matters. The same shared scale now drives the status dot on the network tree and the status and claimed chips on the admin referral detail page, so any status added later gets a sensible colour rather than falling through to grey.
  • Admin affiliate navigation reorganised. Referrals moves to the top level, directly under Dashboard, instead of sitting below the configuration that defines it. Settings is lifted out of the Program group into its own entry at the end, where every other extension's admin area puts it, leaving Program with Conditions and Rewards. Every address is unchanged, so existing bookmarks still work.
  • Admin affiliate pages now use the full content width. They previously sized themselves to their widest element and centred, the only admin area in the platform behaving that way.
  • The conditions placeholder fades instead of vanishing. In Admin → Affiliate → Conditions, selecting a condition made the placeholder panel disappear instantly while the editor faded in over the gap; the two panels now cross-fade.

Fixed

Commissions were paid twice, by two engines that could not see each other

One engine pays a commission the moment a qualifying transaction happens. A second engine independently reviews the same activity on a schedule and pays again. Nothing connected the two, so nothing flagged it. A 200 purchase on a 5% condition paid the sponsor 10 at checkout, then a further 16 shortly after — 26 for a commission configured at 10.

  • Fixed the scheduled engine now skips every condition the live one already handles. It continues to handle the conditions nothing triggers on its own — volume and period totals, and any custom condition you add.

The top of every chain was paid at every remaining level

A member with no sponsor of their own is recorded as their own referrer. The commission walk read that as "this member was referred by themselves" and kept going, so the same person was paid at level 2, level 3, level 4 — up to the configured depth. On a 10/5/4 structure the top sponsor received both the level-2 and the level-3 share of one purchase, and the chain paid out 27% more than the configured split.

  • Fixed the top of a tree is recognised as the top and the walk ends there. A safety check also stops any loop an imported or hand-edited referral list might contain.

Qualifying volume was added up across currencies and paid out as one

The scheduled engine — the one that still handles volume and period-total conditions after this release — summed every referred member's activity regardless of what currency it was denominated in, then paid the total out in the condition's own reward currency. A 0.4 BTC deposit counted as 0.4 and 500,000 JPY counted as 500,000, added into a single number. Minimum amounts were met or missed, and percentage commissions were calculated, for reasons that had nothing to do with value.

  • Fixed only activity denominated in the condition's own reward currency counts toward it. Qualifying totals and the commissions calculated from them change, sometimes dramatically, and members who qualified purely on foreign-currency activity stop qualifying.
  • Fixed: a condition whose reward currency none of its referred members holds now says so in the scheduled run's log — "condition cannot pay as configured" — instead of quietly producing a meaningless total. A condition left with no reward currency at all is skipped with a warning rather than evaluated.

The "Require Approval" switch did nothing

The settings screen and the commission engine were reading two different switches. Turning approval off left every new referral pending — and no commission is ever paid on a pending referral — while the screen showed the feature as disabled. Affiliates recruited under that setting earned nothing and nobody could see why.

  • Fixed the switch on the settings screen is the one that decides.

"Maximum Commission Rate" capped nothing

The setting was configurable, described as "the maximum commission percentage allowed", and used by nothing. You could cap commissions at 30% and then save a condition paying 80%.

  • Fixed saving a percentage-based condition above your configured ceiling is now refused, with a message naming both figures. Fixed-amount rewards are an absolute value rather than a percentage, so the ceiling does not apply to them.

"Payout Threshold" held nothing back

The setting described itself as "minimum balance required before affiliates can request a payout" and was never used, so any reward could be withdrawn however small.

  • Fixed a claim is refused while the affiliate's total unclaimed balance is below the threshold, and the refusal says what the balance is and what it needs to be. The threshold applies to the total balance, not to a single reward, so somebody who has reached it across several rewards can still claim them one at a time.

An upgraded install silently stopped paying

Older versions stored the level percentages in one place and the current settings screen stores them in another. On an upgraded install the old values were dropped and the new ones never written — leaving the program running with no level configuration at all. The engine pays nothing when levels are missing, so every commission stopped, with no error on any screen.

  • Fixed the older configuration is read when the newer one is absent. Saving the settings screen once moves the install fully onto the new format.

The over-100% guard could not fire on the installs that needed it

The engine refuses to pay anything when the level percentages add up to more than 100% of the commission pool — a sensible guard, since the levels are shares of one pot. On installs carrying the older configuration format, every level counted as zero, so the guard happily passed a 250% split.

  • Fixed the total is now calculated correctly. The settings screen also shows the running total under the level inputs and says plainly that going over 100% stops commissions entirely — previously the engine refused silently and the screen gave no clue why payouts had stopped.

Three condition types could never match a transaction

Three condition types were looking for activity that is recorded under a different name — binary wins, futures orders and one credit type. Conditions of those types matched nothing and paid nobody, reporting a clean run every time.

  • Fixed all three now match. Investment and staking conditions also match their return/reward entries, and any condition type that cannot match anything is now reported as a warning instead of quietly matching nothing.

The store-order commission paid on almost every payment the platform recorded

The seeded Ecommerce Order Commission condition matched a catch-all payment category rather than store orders. Gateway payments, platform and ecosystem fees, trading-bot purchases and admin balance adjustments all counted toward it, and the sponsor was paid a percentage of the lot.

  • Fixed store purchases are now recorded in their own right and the condition matches only those. Where this condition is in use, ecommerce commissions on the scheduled engine will be noticeably lower and will correspond to actual orders.

Conditions for addons you do not run were still advertised

A condition is supposed to be hidden when its addon is not installed, but only six of the thirty-five seeded conditions were covered. Everything else — NFT, futures, copy trading, ecosystem tokens, the forex-trading rebates — was listed regardless, so the affiliate page advertised commissions nobody on that install could earn.

  • Fixed every addon-backed condition is now hidden when its addon is absent. Conditions backed by core features (deposits, spot and binary trading, investments) are still always shown, because they are always available.

Approving a referral reported success before it had happened

A failed approval still appeared as a success in the activity log.

  • Fixed the result is now reported honestly.

Pending and rejected referrals still occupied a position in the tree

A referral took its place in the tree the moment it was recorded, before anyone had approved it. A referral awaiting approval — or later rejected — therefore held a position it could never earn from, and in a binary structure it consumed one of only two child slots, pushing genuine members into spillover under someone else. Rejecting a referral never removed it.

  • Fixed a referral takes its position when it becomes active (immediately when approval is off, on approval when it is on), and rejecting one removes it, moving anything beneath it up so a rejection cannot orphan a live sub-tree. Approving twice cannot duplicate a position.

"Default Commission Rate" is gone rather than decorative

The setting was configurable and used by nothing. Unlike the other two commission settings there was nothing for it to apply to — commissions come from each condition's own reward, and there is no per-affiliate rate for a default to modify.

  • Fixed the control is removed from the settings screen instead of being left as something that silently does nothing. Set the rate on each condition in Affiliate → Conditions.

A second genuine reward inside a minute was thrown away

Two qualifying events a minute apart earned one commission; the second was discarded silently.

  • Fixed a repeated request is still recognised and ignored, but two genuinely different earnings are both paid.

The Affiliate Referrals table on a CRM user page could not load

Opening a member in Admin → CRM and scrolling to Affiliate Referrals produced a failed, empty table every time. The table asked for referrals belonging to one member, but a referral is a pair — a referrer and a referred member — with no single owner to filter on, so the request was rejected outright.

  • Fixed the table loads, and shows both directions — the people that member brought in, and the person who brought them in.

Overlapping conditions were invisible

More than one active condition can share the same trigger, and every one of them pays on the same activity. The installer seeds several such pairs. Nothing on the conditions screen said so, so an operator who had configured "5% on store orders" was actually paying 8% and had no way to see it.

  • Fixed each condition now shows which other active conditions share its trigger, so the real cost of a programme is visible where it is configured.