Create referral commissions in workflows#3969
Conversation
…ommission after approval
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughRefactors partner-referral creation to use a discriminated args/structured-result API, adds voidReferralCommissions to bulk-void downstream referral commissions transactionally, wires these into cron endpoints, workflows, webhooks, and commission updates, and adds a DB index on sourceCommissionId. ChangesReferral Commission Void and Return Propagation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 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. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
apps/web/lib/partner-referrals/create-referral-commission.ts (1)
376-490: 💤 Low valueAdd explicit return or exhaustiveness check at end of
resolveReferralContext.The function implicitly returns
undefinedwhen control flow falls through after the twoifblocks. While the discriminated union ensures only"commission"or"partner"are valid at compile time, adding an explicit exhaustiveness check improves maintainability if new source types are added later.♻️ Suggested exhaustiveness pattern
return { sourceCommission: null, programId, partnerId, referredByPartnerId, }; } + + // Exhaustiveness check - should never be reached + const _exhaustiveCheck: never = args; + return _exhaustiveCheck; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/lib/partner-referrals/create-referral-commission.ts` around lines 376 - 490, resolveReferralContext can implicitly return undefined if args.source is neither "commission" nor "partner"; add an explicit exhaustiveness check at the end of the function to return a stable value (e.g., null) or throw an error. Locate the resolveReferralContext function and after the existing if (args.source === "partner") block add a final branch that handles unexpected args.source (use a never-exhaustive check or a default case referencing args.source) and return null or throw with a clear message so callers never receive undefined.apps/web/app/(ee)/api/cron/commissions/referrals/queue/route.ts (1)
35-51: 💤 Low valueRemove unused Prisma selections in referral queue
In
apps/web/app/(ee)/api/cron/commissions/referrals/queue/route.ts,payout.programEnrollmentandpayout.commissionsare selected but never used in the route logic, andcreateNetworkReferralCommission(apps/web/lib/partner-referrals/create-network-referral-commission.ts) only relies onpayout.id/amount/programId(it re-fetches networkprogramEnrollmentitself). Remove these fields from the Prismaselectto avoid unnecessary DB work.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/app/`(ee)/api/cron/commissions/referrals/queue/route.ts around lines 35 - 51, The Prisma query in route.ts is selecting payout.programEnrollment and payout.commissions even though the route logic and createNetworkReferralCommission only need payout.id, payout.amount, and payout.programId; remove the nested selects for programEnrollment and commissions from the payout selection in apps/web/app/(ee)/api/cron/commissions/referrals/queue/route.ts so the query only selects the necessary payout fields (id, amount, programId), leaving createNetworkReferralCommission (apps/web/lib/partner-referrals/create-network-referral-commission.ts) to refetch programEnrollment itself.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/lib/api/commissions/update-partner-commission.ts`:
- Around line 320-328: The call to voidReferralCommissions should only happen
for terminal void statuses; wrap the invocation of voidReferralCommissions (the
call passing sourceCommissionStatus: finalStatus!) in a conditional that checks
finalStatus is one of ["refunded","duplicate","fraud","canceled"] and skip it
when finalStatus is undefined or "pending" (or any non-terminal status). Update
the code around the voidReferralCommissions call so you only pass
sourceCommissionStatus when inside that conditional to avoid nulling payoutIds
or forwarding invalid statuses.
In `@apps/web/lib/api/commissions/void-referral-commissions.ts`:
- Around line 35-62: The current flow reads mutable commissions via
prisma.commission.findMany but then updates by id without re-checking
eligibility, which can overwrite immutable rows; wrap the read+write in a single
transaction and perform the update with the same eligibility predicates (the
original where block: sourceCommissionId in sourceCommissionIds AND (status =
"pending" OR (status = "processed" AND payout.status in
MUTABLE_PAYOUT_STATUSES))) using prisma.commission.updateMany (or include the
same predicates in the update call) so only eligible rows are modified, then
reconcile/log based on the update result (rowsAffected/returned rows) to act
only on actually changed commissions (refer to the existing
prisma.commission.findMany selection and the update logic near the
updateById/updateMany calls).
---
Nitpick comments:
In `@apps/web/app/`(ee)/api/cron/commissions/referrals/queue/route.ts:
- Around line 35-51: The Prisma query in route.ts is selecting
payout.programEnrollment and payout.commissions even though the route logic and
createNetworkReferralCommission only need payout.id, payout.amount, and
payout.programId; remove the nested selects for programEnrollment and
commissions from the payout selection in
apps/web/app/(ee)/api/cron/commissions/referrals/queue/route.ts so the query
only selects the necessary payout fields (id, amount, programId), leaving
createNetworkReferralCommission
(apps/web/lib/partner-referrals/create-network-referral-commission.ts) to
refetch programEnrollment itself.
In `@apps/web/lib/partner-referrals/create-referral-commission.ts`:
- Around line 376-490: resolveReferralContext can implicitly return undefined if
args.source is neither "commission" nor "partner"; add an explicit
exhaustiveness check at the end of the function to return a stable value (e.g.,
null) or throw an error. Locate the resolveReferralContext function and after
the existing if (args.source === "partner") block add a final branch that
handles unexpected args.source (use a never-exhaustive check or a default case
referencing args.source) and return null or throw with a clear message so
callers never receive undefined.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9570db4f-08a2-40e2-8f13-2f9f291cc474
📒 Files selected for processing (11)
apps/web/app/(ee)/api/cron/commissions/referrals/create/route.tsapps/web/app/(ee)/api/cron/commissions/referrals/queue/route.tsapps/web/app/(ee)/api/stripe/integration/webhook/charge-refunded.tsapps/web/app/(ee)/api/workflows/create-partner-commission/route.tsapps/web/app/(ee)/api/workflows/partner-approved/route.tsapps/web/lib/api/commissions/bulk-update-partner-commissions.tsapps/web/lib/api/commissions/update-partner-commission.tsapps/web/lib/api/commissions/void-referral-commissions.tsapps/web/lib/partner-referrals/create-referral-commission.tsapps/web/scripts/dev/test-partner-referrals.tspackages/prisma/schema/commission.prisma
💤 Files with no reviewable changes (1)
- apps/web/scripts/dev/test-partner-referrals.ts
Gate referral creation on sale commission type, return createReferralCommission from partner-approved workflow, and count paid sales toward referral earnings limits.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai full review please |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/lib/partner-referrals/create-referral-commission.ts (1)
181-200:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftThreshold referrals stop firing when the threshold is actually crossed.
This branch is now reached from
apps/web/app/(ee)/api/workflows/create-partner-commission/route.tsright after the sale commission is created, but the aggregate still only counts source commissions withstatus: "paid". That means the sale that crosses the threshold is usually invisible here, and once it later transitions topaidthis slice no longer shows any non-network path that re-runscreateReferralCommission. The referral bonus will be delayed until some later sale, or never created if no later sale arrives.Either re-trigger
commissionThresholdwhen source commissions becomepaid, or change the threshold calculation to include the current source commission at creation time if that is the intended business rule.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/lib/partner-referrals/create-referral-commission.ts` around lines 181 - 200, The threshold branch in create-referral-commission.ts checks prisma.commission.aggregate with status: "paid", which ignores the just-created source commission and delays/refuses the referral bonus; fix by including the current source commission when computing total (or alternatively ensure this function is retriggered when a source commission transitions to "paid"). Concretely, update the commissionThreshold branch that uses prisma.commission.aggregate to add the current commission's earnings into the total before comparing to commissionsThresholdInCents (e.g., add a currentCommissionEarnings variable from the incoming/created commission and sum it with totalCommissionsEarned) or change the caller/workflow to invoke createReferralCommission when a commission status flips to "paid" so the aggregate with status: "paid" includes the new sale. Ensure references to partnerId, programId, prisma.commission.aggregate, commissionsThresholdInCents and referredByPartnerId are used to locate the code to modify.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/lib/api/commissions/bulk-update-partner-commissions.ts`:
- Around line 171-176: The call to voidReferralCommissions is missing the acting
user so downstream referral status changes lose actor attribution; update the
invocation in bulk-update-partner-commissions (where you currently pass
workspaceId, programId, sourceCommissionIds: commissionIds,
sourceCommissionStatus: status) to also pass the userId (or actingUserId) from
this bulk path so voidReferralCommissions receives the actor and records it on
the referral commission updates.
In `@apps/web/lib/api/commissions/update-partner-commission.ts`:
- Around line 322-329: The call to voidReferralCommissions is omitting the actor
so the side-effect activity log loses the user attribution; update the call site
to pass the parent mutation's userId into voidReferralCommissions (add userId:
userId) and ensure the voidReferralCommissions function signature accepts and
forwards that userId to the activity/logging logic so referral commission
updates are attributed correctly.
In `@apps/web/lib/api/commissions/void-referral-commissions.ts`:
- Around line 91-97: The current tx.commission.findMany call queries by
sourceCommissionId and status (using sourceCommissionIds and
sourceCommissionStatus), which can return rows that were already in that status;
instead, capture the exact referral commission IDs changed by the mutation (from
the update result) and re-query tx.commission.findMany using where: { id: { in:
updatedReferralCommissionIds } } so you only fetch commissions actually modified
(reference the tx.commission.findMany call and the variable that holds the
update result/IDs).
---
Outside diff comments:
In `@apps/web/lib/partner-referrals/create-referral-commission.ts`:
- Around line 181-200: The threshold branch in create-referral-commission.ts
checks prisma.commission.aggregate with status: "paid", which ignores the
just-created source commission and delays/refuses the referral bonus; fix by
including the current source commission when computing total (or alternatively
ensure this function is retriggered when a source commission transitions to
"paid"). Concretely, update the commissionThreshold branch that uses
prisma.commission.aggregate to add the current commission's earnings into the
total before comparing to commissionsThresholdInCents (e.g., add a
currentCommissionEarnings variable from the incoming/created commission and sum
it with totalCommissionsEarned) or change the caller/workflow to invoke
createReferralCommission when a commission status flips to "paid" so the
aggregate with status: "paid" includes the new sale. Ensure references to
partnerId, programId, prisma.commission.aggregate, commissionsThresholdInCents
and referredByPartnerId are used to locate the code to modify.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: aed61b89-fe36-46ff-9451-44c3ca3ff925
📒 Files selected for processing (20)
apps/web/app/(ee)/api/admin/payouts/get-payouts-timeseries.tsapps/web/app/(ee)/api/cron/commissions/referrals/create/route.tsapps/web/app/(ee)/api/cron/commissions/referrals/network/route.tsapps/web/app/(ee)/api/cron/commissions/referrals/queue/route.tsapps/web/app/(ee)/api/cron/payouts/charge-succeeded/send-paypal-payouts.tsapps/web/app/(ee)/api/stripe/integration/webhook/charge-refunded.tsapps/web/app/(ee)/api/workflows/create-partner-commission/route.tsapps/web/app/(ee)/api/workflows/partner-approved/route.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/webhooks/[webhookId]/page-client.tsxapps/web/app/providers.tsxapps/web/lib/api/commissions/bulk-update-partner-commissions.tsapps/web/lib/api/commissions/update-partner-commission.tsapps/web/lib/api/commissions/void-referral-commissions.tsapps/web/lib/partner-referrals/create-referral-commission.tsapps/web/lib/partners/create-stablecoin-payout.tsapps/web/lib/partners/create-stripe-transfer.tsapps/web/playwright/workspaces/billing-trial.spec.tsapps/web/scripts/dev/test-partner-referrals.tsapps/web/ui/partners/partner-link-selector.tsxpackages/prisma/schema/commission.prisma
💤 Files with no reviewable changes (2)
- apps/web/scripts/dev/test-partner-referrals.ts
- apps/web/app/(ee)/api/cron/commissions/referrals/queue/route.ts
Summary by CodeRabbit
New Features
Refactor
Performance