-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
feat: add payment-based referral commission system #2755
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. WalkthroughAdds a referral commission feature: new configuration options, UI settings, option handling, a CreditReferralCommission function, and calls to credit inviters after successful top-ups across multiple recharge flows. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant WebUI
participant Controller
participant TopUpModel
participant UserModel
participant DB
User->>WebUI: submit top-up
WebUI->>Controller: POST /topup (or callback)
Controller->>TopUpModel: process top-up, update topUp record
TopUpModel->>DB: persist top-up and quota changes
TopUpModel->>UserModel: CreditReferralCommission(userId, amount)
UserModel->>DB: read recharging user, read inviter, update inviter quotas & history
UserModel->>DB: persist inviter changes
UserModel-->>Controller: return (err ignored by caller)
Controller-->>WebUI: respond success
WebUI-->>User: show success
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
When a referred user recharges, the inviter receives a configurable percentage as commission credited to their AffQuota. New settings: - ReferralCommissionEnabled: Toggle commission feature - ReferralCommissionPercent: Commission percentage (0-100) - ReferralCommissionMaxRecharges: Limit commission to first N recharges Commission is calculated in all payment handlers: - Stripe (Recharge) - Creem (RechargeCreem) - Manual completion (ManualCompleteTopUp) Closes QuantumNous#128, QuantumNous#187, QuantumNous#1852
982619b to
dd7ddf5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🤖 Fix all issues with AI agents
In `@model/topup.go`:
- Around line 103-105: The call to CreditReferralCommission(topUp.UserId,
topUp.Money) currently discards errors; change it to capture the returned error,
and if non-nil log and/or emit a metric but do not fail the top-up flow—e.g.,
err := CreditReferralCommission(topUp.UserId, topUp.Money); if err != nil { use
the project logger (e.g., processLogger or log) to log a warning with
topUp.UserId and topUp.Money and increment a referral-credit failure metric } so
inviters/issues are visible while keeping the top-up success unaffected.
In `@web/src/i18n/locales/en.json`:
- Around line 2405-2414: Remove the duplicate translation key "次" from the
en.json fragment in this diff: locate the second occurrence of the key "次" in
the block that contains "邀请充值返佣设置"/"Referral Commission Settings" and delete
that duplicate entry so only the original definition (the one defined earlier at
the key "次") remains, ensuring no other keys or surrounding JSON punctuation are
altered.
In `@web/src/i18n/locales/fr.json`:
- Around line 2407-2415: The fr.json file contains a duplicate translation key
"次" (newly added near the commission settings block) which overrides the earlier
definition ("Fois"); remove the newly added duplicate entry and instead
reference or update the existing "次" key so translations remain consistent, or
if this string needs a different wording/context create a new unique key (e.g.,
"commission_times") and use that key in the commission-related UI code; ensure
only one "次" entry remains and that the commission labels point to the correct
key.
In `@web/src/i18n/locales/ja.json`:
- Around line 2390-2398: Remove the duplicate JSON key "次" introduced in the
block containing "邀请充值返佣设置"/"招待コミッション設定" and its Japanese value; instead rely on
the existing "次" key already defined earlier in the file (the one at the other
occurrence) so there is only a single "次" key in the ja.json locale. Locate the
duplicate within the object that includes "启用充值返佣"/"チャージコミッションを有効化" and delete
that "次" entry, leaving the other translated entries intact.
In `@web/src/i18n/locales/ru.json`:
- Around line 2420-2428: Remove the duplicate translation key "次" in ru.json:
locate the second occurrence of the key (the one inside the "邀请充值返佣设置" block)
and delete that entry so only the original "次" translation remains; ensure the
surrounding JSON stays valid (commas adjusted) after removal.
In `@web/src/i18n/locales/vi.json`:
- Around line 2917-2925: Remove the duplicate translation entry for the key "次"
in vi.json by deleting the later occurrence in the "邀请充值返佣设置" block (the
trailing `"次": "lần",` entry) so only the original definition earlier in the
file remains; ensure you leave the earlier key-value intact and run the i18n
linter/validator to confirm no duplicates remain.
In `@web/src/i18n/locales/zh.json`:
- Around line 2390-2398: Remove the duplicate JSON key "次" from the zh locale
file by deleting the redundant entry (the later occurrence in the block
containing "邀请充值返佣设置" ...), leaving only the original "次" definition (the
earlier entry around line 1471) to avoid duplicate keys in
web/src/i18n/locales/zh.json and ensure the locale JSON contains a single "次"
key.
♻️ Duplicate comments (2)
model/topup.go (2)
309-312: Same issue as above: handle referral commission errors.Same pattern as Line 104 — please add error logging/telemetry here too.
383-385: Same issue as above: handle referral commission errors.Same pattern as Line 104 — please add error logging/telemetry here too.
🧹 Nitpick comments (2)
model/user.go (2)
362-369: Consider adding error handling for the count query.The
DB.Model().Count()call on line 365 does not check for errors. If the database query fails,rechargeCountwill remain 0, and the commission will be paid regardless of actual recharge history. This could lead to paying commissions even when the limit should have been reached.♻️ Proposed fix
// Check max recharges limit (if configured) if common.ReferralCommissionMaxRecharges > 0 { // Count successful recharges for this user var rechargeCount int64 - DB.Model(&TopUp{}).Where("user_id = ? AND status = ?", userId, common.TopUpStatusSuccess).Count(&rechargeCount) + if err := DB.Model(&TopUp{}).Where("user_id = ? AND status = ?", userId, common.TopUpStatusSuccess).Count(&rechargeCount).Error; err != nil { + return err // Fail safely if we can't verify recharge count + } if int(rechargeCount) > common.ReferralCommissionMaxRecharges { return nil // Max recharges reached, no more commission } }
383-394: Consider using a transaction for atomicity.The inviter's quota update is not protected by a transaction. If
DB.Save(inviter)fails afterGetUserByIdsucceeds, the system state could be inconsistent between retries. While the caller ignores errors from this function (making it "best effort"), using a transaction would ensure the quota fields are updated atomically.Additionally, concurrent recharges by the same referred user could cause a race condition where both read the same
AffQuotavalue before either writes, potentially resulting in lost updates.♻️ Proposed fix using atomic update
// Get inviter and credit commission to their AffQuota - inviter, err := GetUserById(user.InviterId, true) - if err != nil { - return err - } - - inviter.AffQuota += commission - inviter.AffHistoryQuota += commission - err = DB.Save(inviter).Error + err = DB.Model(&User{}).Where("id = ?", user.InviterId).Updates(map[string]interface{}{ + "aff_quota": gorm.Expr("aff_quota + ?", commission), + "aff_history": gorm.Expr("aff_history + ?", commission), + }).Error if err != nil { return err }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@model/user.go`:
- Around line 383-394: The current read-modify-write using GetUserById and
DB.Save can lose concurrent updates; instead perform atomic DB-side increments
for the inviter quotas. Replace the read/modify/save (GetUserById,
inviter.AffQuota += commission, inviter.AffHistoryQuota += commission,
DB.Save(inviter)) with a single transactional atomic update such as using GORM's
UpdateColumn/UpdateColumns with gorm.Expr to increment aff_quota and
aff_history_quota (e.g. DB.Transaction(...) and DB.Model(&User{}).Where("id =
?", user.InviterId).UpdateColumns(map[string]interface{}{"aff_quota":
gorm.Expr("aff_quota + ?", commission), "aff_history_quota":
gorm.Expr("aff_history_quota + ?", commission)})), and handle the case where no
rows are affected as an error.
♻️ Duplicate comments (3)
web/src/i18n/locales/ru.json (1)
2420-2428: Remove the duplicate"次"key to fix linting.Line 2428 redefines a key already present at Line 1504; this trips
noDuplicateObjectKeysand silently overrides the earlier value.🧹 Proposed fix
"保存返佣设置": "Сохранить настройки комиссии", - "次": "раз",web/src/i18n/locales/fr.json (1)
2407-2415: Duplicate translation key overrides existing value.
"次"is already defined earlier in this file. Keeping a second"次"here silently overwrites the previous translation and can change unrelated UI labels. Remove the duplicate or use a unique key for the commission section.🧹 Proposed fix
- "次": "fois",web/src/i18n/locales/zh.json (1)
2390-2398: Remove the duplicate"次"key to avoid JSON override.
This duplicate has already been flagged in a previous review; please delete the later occurrence.✂️ Proposed fix
@@ - "次": "次",
🧹 Nitpick comments (1)
controller/topup.go (1)
288-291: Log referral commission failures for visibility.The call ignores errors entirely, so misconfig or DB issues will be invisible. Consider logging when commission crediting fails.
🔧 Suggested tweak
- // Credit referral commission to inviter (if enabled) - _ = model.CreditReferralCommission(topUp.UserId, topUp.Money) + // Credit referral commission to inviter (if enabled) + if err := model.CreditReferralCommission(topUp.UserId, topUp.Money); err != nil { + log.Printf("credit referral commission failed for user %d: %v", topUp.UserId, err) + }
- Log referral commission errors instead of silently ignoring them - Use atomic DB update for inviter quota to prevent race conditions - Remove duplicate "次" translation keys from all locale files
51f348f to
8f9265a
Compare
Summary
Closes #128, #187, #1852
Changes
ReferralCommissionEnabled,ReferralCommissionPercent,ReferralCommissionMaxRechargessettingsCreditReferralCommission()helper function inmodel/user.gomodel/topup.go→Recharge())model/topup.go→RechargeCreem())model/topup.go→ManualCompleteTopUp())controller/topup.go→ callback handler)Summary by CodeRabbit
New Features
Localization
✏️ Tip: You can customize this high-level summary in your review settings.