Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Nov 2, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Fixed currency display in admin program info so amounts now render correctly in standard units.
  • Improvements

    • Updated payout balance checks to detect pending balances and automatically schedule a follow-up re-check before creating payouts, with clearer status messaging.

@vercel
Copy link
Contributor

vercel bot commented Nov 2, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Nov 2, 2025 3:23am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 2, 2025

Walkthrough

Currency display in the admin user-info component now converts stored cents to main units before formatting. The payouts balance-available cron route was reworked to schedule a qstash re-check when available balance is zero but pending balance exists, altering pre-payout balance handling and messages.

Changes

Cohort / File(s) Summary
Currency formatting
apps/web/app/(ee)/admin.dub.co/(dashboard)/components/user-info.tsx
When rendering program currency fields, values are divided by 100 before passing to the formatter (convert cents → base units). Non-currency fields unchanged.
Payout balance logic & scheduling
apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts
Added imports (qstash, APP_DOMAIN_WITH_NGROK, currencyFormatter, formatDate, log); changed balance-check flow to: if available balance is 0 and pending balance > 0, schedule a qstash re-check in 1 hour and return a pending response; otherwise continue payout creation with existing rounding behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Cron as Cron Job
    participant Route as balance-available route
    participant Stripe as Stripe API
    participant Qstash as Qstash Scheduler

    Cron->>Route: Invoke balance-available endpoint
    Route->>Stripe: Fetch balances (available, pending)
    alt available > 0
        Route->>Stripe: Create payout
        Note right of Route: Apply currency rounding for HUF/TWD if needed
        Route-->>Cron: Return payout-created response
    else available = 0 and pending > 0
        Route->>Qstash: Schedule re-check (delay: 1 hour) with APP_DOMAIN_WITH_NGROK
        Note right of Route: Log scheduling & return pending message
        Route-->>Cron: Return pending-state response
    else available = 0 and pending = 0
        Route-->>Cron: Return zero-available-balance message
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas needing attention:
    • qstash scheduling parameters and URL construction (APP_DOMAIN_WITH_NGROK) in balance-available/route.ts
    • Correct interpretation of balance.pending indexing and amount extraction
    • Rounding rules and currency conversion consistency (HUF/TWD and cents→units) across payout and UI code

Possibly related PRs

Suggested reviewers

  • devkiran

Poem

🐇 I hop through cents to find the sum,

I fix a nickel, dime, and drum.
When balances sleep and need an hour,
Qstash will wake them, nudge their power.
A tiny rabbit, code made sweet.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "Retry balance-available cron if there's a pending balance" directly corresponds to the primary changes in the changeset. The main file modification (balance-available/route.ts) implements new logic to schedule a re-check via qstash when a pending balance is detected, which is precisely what the title describes. The title is specific, clear, and avoids vague terminology. While the changeset includes a minor currency formatting adjustment in user-info.tsx, the title appropriately focuses on the more substantial change. A developer reviewing the commit history would clearly understand that this PR introduces retry/rescheduling functionality for the balance-available cron based on the presence of pending balances.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch retry-balance-available

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@steven-tey
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 2, 2025

✅ Actions performed

Full review triggered.

@steven-tey
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 2, 2025

✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d164e4c and d0a702b.

📒 Files selected for processing (1)
  • apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: steven-tey
Repo: dubinc/dub PR: 0
File: :0-0
Timestamp: 2025-06-25T21:20:59.837Z
Learning: In the Dub codebase, payout limit validation uses a two-stage pattern: server actions perform quick sanity checks (payoutsUsage > payoutsLimit) for immediate user feedback, while the cron job (/cron/payouts) performs authoritative validation (payoutsUsage + payoutAmount > payoutsLimit) with actual calculated amounts before processing. This design provides fast user feedback while ensuring accurate limit enforcement at transaction time.
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/ui/partners/bounties/bounty-logic.tsx:88-96
Timestamp: 2025-08-26T15:03:05.381Z
Learning: In bounty forms, currency values are stored in cents in the backend but converted to dollars when loaded into forms, and converted back to cents when saved. The form logic works entirely with dollar amounts. Functions like generateBountyName that run during save logic receive cent values and need to divide by 100, but display logic within the form should format dollar values directly.
📚 Learning: 2025-08-25T21:41:06.073Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2758
File: apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts:43-45
Timestamp: 2025-08-25T21:41:06.073Z
Learning: For Stripe API calls on connected accounts, the stripeAccount parameter should be passed in the first parameter object (e.g., stripe.balance.retrieve({ stripeAccount })), not as request options in the second parameter.

Applied to files:

  • apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (3)
apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts (3)

2-2: LGTM!

The new imports are necessary for the qstash retry scheduling feature and enhanced logging/formatting.

Also applies to: 8-13


53-63: LGTM!

Enhanced error logging with partner email and stripe account improves debugging, and the availableBalance variable name is more descriptive.


92-166: LGTM!

The existing payout creation, database updates, and email notification logic remain unchanged and correctly handle the payout flow after the new pending balance checks.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

♻️ Duplicate comments (2)
apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts (2)

67-67: Unsafe array access - add bounds check.

Accessing balance.pending[0] without verifying the array has elements will cause a runtime error if balance.pending is empty.

Apply this diff to add a safety check:

-    const pendingBalance = balance.pending[0].amount;
+    const pendingBalance = balance.pending?.[0]?.amount ?? 0;

82-85: Use the actual currency instead of hardcoded "USD".

The currency formatter is using a hardcoded "USD" value instead of the currency variable extracted from the balance on line 63.

Apply this diff to use the correct currency:

-          `Pending balance found for partner ${partner.email} (${stripeAccount}): ${currencyFormatter(pendingBalance / 100, { currency: "USD" })}. Scheduling another check in 1 hour...`,
+          `Pending balance found for partner ${partner.email} (${stripeAccount}): ${currencyFormatter(pendingBalance / 100, { currency })}. Scheduling another check in 1 hour...`,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9543107 and d0a702b.

📒 Files selected for processing (2)
  • apps/web/app/(ee)/admin.dub.co/(dashboard)/components/user-info.tsx (1 hunks)
  • apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: steven-tey
Repo: dubinc/dub PR: 0
File: :0-0
Timestamp: 2025-06-25T21:20:59.837Z
Learning: In the Dub codebase, payout limit validation uses a two-stage pattern: server actions perform quick sanity checks (payoutsUsage > payoutsLimit) for immediate user feedback, while the cron job (/cron/payouts) performs authoritative validation (payoutsUsage + payoutAmount > payoutsLimit) with actual calculated amounts before processing. This design provides fast user feedback while ensuring accurate limit enforcement at transaction time.
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/ui/partners/bounties/bounty-logic.tsx:88-96
Timestamp: 2025-08-26T15:03:05.381Z
Learning: In bounty forms, currency values are stored in cents in the backend but converted to dollars when loaded into forms, and converted back to cents when saved. The form logic works entirely with dollar amounts. Functions like generateBountyName that run during save logic receive cent values and need to divide by 100, but display logic within the form should format dollar values directly.
📚 Learning: 2025-09-12T17:31:10.548Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2833
File: apps/web/lib/actions/partners/approve-bounty-submission.ts:53-61
Timestamp: 2025-09-12T17:31:10.548Z
Learning: In approve-bounty-submission.ts, the logic `bounty.rewardAmount ?? rewardAmount` is intentional. Bounties with preset reward amounts should use those fixed amounts, and the rewardAmount override parameter is only used when bounty.rewardAmount is null/undefined (for custom reward bounties). This follows the design pattern where bounties are either "flat rate" (fixed amount) or "custom" (variable amount set during approval).

Applied to files:

  • apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts
📚 Learning: 2025-08-25T21:41:06.073Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2758
File: apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts:43-45
Timestamp: 2025-08-25T21:41:06.073Z
Learning: For Stripe API calls on connected accounts, the stripeAccount parameter should be passed in the first parameter object (e.g., stripe.balance.retrieve({ stripeAccount })), not as request options in the second parameter.

Applied to files:

  • apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts
🔇 Additional comments (3)
apps/web/app/(ee)/api/cron/payouts/balance-available/route.ts (3)

2-2: LGTM! Imports are appropriate for the new scheduling functionality.

All imported utilities are used correctly in the code.

Also applies to: 8-13


53-61: LGTM! Proper early exit with appropriate error logging.

The check for empty available balance array prevents potential undefined access issues downstream.


71-81: LGTM! Qstash scheduling implementation is correct.

The retry mechanism properly schedules a re-check in 1 hour when pending balance exists, using the correct delay (3600 seconds) and payload structure.

@steven-tey steven-tey merged commit 069c11f into main Nov 2, 2025
8 of 10 checks passed
@steven-tey steven-tey deleted the retry-balance-available branch November 2, 2025 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants