-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Add fast settlement option to payout processing #2917
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
Conversation
Warning Rate limit exceeded@steven-tey has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 17 minutes and 52 seconds before requesting another review. ⌛ 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. 📒 Files selected for processing (20)
WalkthroughAdds Fast ACH payout support across DB, backend, UI, and emails: new PaymentMethod enum and invoice.paymentMethod, workspace fastDirectDebitPayouts flag, FAST_ACH_FEE_CENTS and normalization/utilities, UI/UX for selecting Fast ACH, backend validation, fee handling and invoice updates, migration to backfill payment methods, and email/template updates. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User as Partner Manager
participant UI as Payout Invoice Sheet
participant Action as confirmPayoutsAction
participant DB as Prisma
participant Stripe as Stripe API
User->>UI: Choose payment method and optional Fast ACH
UI->>Action: confirmPayouts({ paymentMethodId, fastSettlement, ... })
Action->>DB: Read workspace.fastDirectDebitPayouts
alt fastSettlement == true
Action->>Action: Validate workspace and method type (must be us_bank_account)
Action->>DB: Create invoice with paymentMethod = ach_fast
else
Action->>Action: Normalize method via STRIPE_PAYMENT_METHOD_NORMALIZATION
Action->>DB: Create invoice with normalized paymentMethod
end
Action-->>UI: Return success (invoice created)
sequenceDiagram
autonumber
participant Cron as Payouts Cron
participant DB as Prisma (Invoice)
participant Stripe as Stripe (PaymentIntent)
participant Email as Email Service
Cron->>DB: Load invoice by id (includes paymentMethod)
Cron->>Cron: Compute fees (platform fee + fastAchFee if paymentMethod == ach_fast)
alt paymentMethod in [ach, ach_fast] (us_bank_account)
Cron->>Stripe: Create PaymentIntent (include preferred_settlement_speed if ach_fast)
else paymentMethod in {sepa, acss}
Cron->>Stripe: Create PaymentIntent (FX/currency handling)
end
Cron->>DB: Update invoice with finalized amount/fee/total
Cron->>Email: Send payout emails including paymentMethod
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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 |
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…malize payment methods. Update related schemas and types for consistency.
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: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/ui/partners/payout-invoice-sheet.tsx (1)
299-308
: Add rel="noopener noreferrer" to external settings link.Security best‑practice for target="_blank".
- <a + <a href={`/${slug}/settings/billing`} className={cn( buttonVariants({ variant: "secondary" }), "flex items-center rounded-md border border-neutral-200 p-1.5 text-sm", )} - target="_blank" + target="_blank" + rel="noopener noreferrer" >
🧹 Nitpick comments (5)
apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/route.tsx (1)
64-64
: Consider simplifying the Response construction.The
Uint8Array
wrapper appears unnecessary since theResponse
constructor acceptsBuffer
directly in Node.js/Next.js. The current code works but adds an extra conversion step.If simplification is desired, apply this diff:
- return new Response(new Uint8Array(pdf), { + return new Response(pdf, { headers: { "Content-Type": "application/pdf", "Content-Disposition": `inline; filename="Invoice-${invoice.number}.pdf"`, }, });packages/email/src/types.ts (1)
10-10
: Consider importing from Prisma to avoid type duplication.The
PaymentMethod
type duplicates thePaymentMethod
enum defined inpackages/prisma/schema/invoice.prisma
. Maintaining separate definitions risks divergence if one is updated without the other.Apply this diff to import from Prisma instead:
-export type PaymentMethod = "card" | "ach" | "ach_fast" | "sepa" | "acss"; +export type { PaymentMethod } from "@dub/prisma/client";This ensures type consistency across the codebase. If the email package intentionally avoids Prisma dependencies for architectural reasons, consider documenting that decision.
apps/web/lib/actions/partners/confirm-payouts.ts (1)
120-123
: Align stored invoice.paymentMethod with UI keys or add a UI mapping.You persist “ach/ach_fast/acss/sepa/card”. The UI PAYMENT_METHODS is keyed by “us_bank_account/acss_debit/sepa_debit/ach_fast/card”. Ensure UI maps these (ach→us_bank_account, acss→acss_debit, sepa→sepa_debit) or store UI‑friendly keys here.
Would you prefer to keep normalized values here and map in UI (safer), or change this to UI keys for direct lookup?
apps/web/ui/partners/payout-invoice-sheet.tsx (2)
363-369
: Format percentage to avoid float artifacts (e.g., 2.999999%).Use toFixed then Number to strip trailing zeros.
- <SimpleTooltipContent - title={`${selectedPaymentMethod.fee * 100}% processing fee. ${!DIRECT_DEBIT_PAYMENT_METHOD_TYPES.includes(selectedPaymentMethod.type as Stripe.PaymentMethod.Type) ? " Switch to Direct Debit for a reduced fee." : ""}`} + <SimpleTooltipContent + title={`${Number((selectedPaymentMethod.fee * 100).toFixed(2))}% processing fee.${!DIRECT_DEBIT_PAYMENT_METHOD_TYPES.includes(selectedPaymentMethod.type as Stripe.PaymentMethod.Type) ? " Switch to Direct Debit for a reduced fee." : ""}`} cta="Learn more" href="https://d.to/payouts" />
286-294
: Render selected icon safely for Icon or ReactNode.icon can be a component or a node. Avoid assuming it’s always a component.
- <> - <selectedPaymentMethodOption.icon className="size-4" /> - {selectedPaymentMethodOption.label} - </> + <> + {typeof selectedPaymentMethodOption.icon === "function" ? ( + <selectedPaymentMethodOption.icon className="size-4" /> + ) : ( + selectedPaymentMethodOption.icon + )} + {selectedPaymentMethodOption.label} + </>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts
(5 hunks)apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx
(2 hunks)apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/route.tsx
(2 hunks)apps/web/app/api/workspaces/[idOrSlug]/billing/invoices/route.ts
(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx
(4 hunks)apps/web/lib/actions/partners/confirm-payouts.ts
(6 hunks)apps/web/lib/cron/verify-vercel.ts
(1 hunks)apps/web/lib/partners/constants.ts
(2 hunks)apps/web/lib/payment-methods.ts
(2 hunks)apps/web/lib/zod/schemas/invoices.ts
(1 hunks)apps/web/lib/zod/schemas/workspaces.ts
(1 hunks)apps/web/scripts/migrations/backfill-invoice-payment-method.ts
(1 hunks)apps/web/ui/partners/payout-invoice-sheet.tsx
(12 hunks)packages/email/src/templates/partner-payout-confirmed.tsx
(4 hunks)packages/email/src/types.ts
(1 hunks)packages/prisma/schema/invoice.prisma
(1 hunks)packages/prisma/schema/workspace.prisma
(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
apps/web/lib/zod/schemas/invoices.ts (1)
packages/email/src/types.ts (1)
PaymentMethod
(10-10)
apps/web/scripts/migrations/backfill-invoice-payment-method.ts (1)
apps/web/lib/partners/constants.ts (1)
STRIPE_PAYMENT_METHOD_NORMALIZATION
(103-109)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts (1)
apps/web/lib/partners/constants.ts (1)
FAST_ACH_FEE_CENTS
(12-12)
apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx (2)
packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter
(5-16)apps/web/lib/partners/constants.ts (1)
FAST_ACH_FEE_CENTS
(12-12)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx (3)
apps/web/lib/types.ts (1)
InvoiceProps
(510-510)apps/web/lib/payment-methods.ts (1)
PAYMENT_METHODS
(27-64)packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter
(5-16)
apps/web/ui/partners/payout-invoice-sheet.tsx (4)
apps/web/lib/payment-methods.ts (2)
PAYMENT_METHODS
(27-64)calculatePayoutFeeForMethod
(5-25)packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter
(5-16)apps/web/lib/partners/constants.ts (1)
FAST_ACH_FEE_CENTS
(12-12)packages/ui/src/combobox/index.tsx (2)
Combobox
(85-367)ComboboxOption
(29-37)
apps/web/lib/actions/partners/confirm-payouts.ts (1)
apps/web/lib/partners/constants.ts (1)
STRIPE_PAYMENT_METHOD_NORMALIZATION
(103-109)
packages/email/src/templates/partner-payout-confirmed.tsx (1)
packages/email/src/types.ts (1)
PaymentMethod
(10-10)
⏰ 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 (10)
packages/prisma/schema/workspace.prisma (1)
50-50
: LGTM!The
fasterAchPayouts
field is well-defined with an appropriate default value. The naming clearly conveys its purpose for enabling faster ACH settlement options.packages/prisma/schema/invoice.prisma (3)
12-18
: LGTM!The
PaymentMethod
enum covers all supported payment method types, including the newach_fast
for fast settlement. The enum values are clear and align well with the payment processing domain.
27-27
: LGTM!Making
paymentMethod
optional (PaymentMethod?
) is the right choice for backward compatibility with existing invoices that don't have this field populated.
40-41
: LGTM!The relations to
Program
andProject
are properly configured with explicit field mappings, enabling proper foreign key constraints and data integrity.apps/web/lib/zod/schemas/invoices.ts (1)
2-2
: LGTM!The schema correctly imports and uses the
PaymentMethod
enum from Prisma. The field definition with.nullable().optional()
properly aligns with the Prisma schema'sPaymentMethod?
type.Also applies to: 8-8
apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/route.tsx (1)
39-39
: LGTM!Good attention to consistency by adding the period to match error message formatting standards.
apps/web/lib/partners/constants.ts (2)
12-12
: LGTM!The
FAST_ACH_FEE_CENTS
constant is clearly defined with a helpful inline dollar conversion comment ($25). This makes the business logic transparent.
103-109
: LGTM!The
STRIPE_PAYMENT_METHOD_NORMALIZATION
mapping is well-structured and correctly maps Stripe payment method types to the correspondingPaymentMethod
enum values. Note thatach_fast
is intentionally not included since it's a custom designation handled separately in the payout flow, not a Stripe payment method type.apps/web/app/api/workspaces/[idOrSlug]/billing/invoices/route.ts (1)
73-73
: LGTM!Adding
paymentMethod
to the select clause properly exposes the new field in the API response, making it available to consumers alongside other invoice details.apps/web/lib/zod/schemas/workspaces.ts (1)
175-175
: LGTM!The
fasterAchPayouts
field is correctly added toWorkspaceSchemaExtended
with the appropriate type and default value, aligning perfectly with the Prisma schema definition.
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx
Outdated
Show resolved
Hide resolved
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx
Show resolved
Hide resolved
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx
Show resolved
Hide resolved
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts (1)
173-182
: Consider transaction safety for Stripe API failures.The invoice is updated with finalized amounts before the Stripe payment intent is created (lines 184-203). If the Stripe API call fails, the invoice will contain incorrect amounts, potentially leaving the database in an inconsistent state.
Consider wrapping the invoice update and Stripe API call in a transaction, or implementing rollback logic to handle Stripe API failures gracefully.
🧹 Nitpick comments (1)
apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx (1)
138-139
: Use a shared constant for "ach_fast"
The payment‐method literal"ach_fast"
appears in actions, cron jobs, invoice pages, email templates, and types; definePAYMENT_METHOD_ACH_FAST
in a central constants module and replace these occurrences.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts
(5 hunks)apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx
(2 hunks)apps/web/ui/partners/payout-invoice-sheet.tsx
(11 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/ui/partners/payout-invoice-sheet.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts (1)
apps/web/lib/partners/constants.ts (1)
FAST_ACH_FEE_CENTS
(12-12)
apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx (2)
apps/web/lib/partners/constants.ts (1)
FAST_ACH_FEE_CENTS
(12-12)packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter
(5-16)
⏰ 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 (7)
apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx (2)
1-1
: LGTM!The import is appropriate for handling Fast ACH fees in the invoice.
150-157
: LGTM!The conditional rendering of the Fast ACH fees line item is implemented correctly. It only displays when applicable and uses consistent formatting.
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts (5)
5-5
: LGTM!The import of
FAST_ACH_FEE_CENTS
is correct and will be used to apply the flat fee for fast ACH payouts.
143-144
: LGTM!The fee calculation logic is correct:
- Percentage-based fee is calculated first
- Fast ACH flat fee is added separately
- Total correctly includes both fees
The order ensures the fast ACH fee is not subject to the percentage calculation, which is the intended behavior.
189-196
: No verification needed:ach_fast
is only set whenpaymentMethod.type === "us_bank_account"
via existing guard inconfirm-payouts.ts
.
269-269
: Verify PartnerPayoutConfirmed email content for Fast ACHDirect Debit emails are only sent when
paymentMethod.type
is in DIRECT_DEBIT_PAYMENT_METHOD_TYPES (["us_bank_account","acss_debit","sepa_debit"]
), which covers Fast ACH (Stripe type"us_bank_account"
). Fast ACH payouts will therefore receive the same 4-business-day notice template. Confirm the PartnerPayoutConfirmed email template and update or split it so Fast ACH partners see the correct settlement timeline.
134-141
: PaymentMethod and ACH fee logic validated. Field exists and enum includesach_fast
; null defaults to 0. No concurrent modifications alterpaymentMethod
in this flow.
apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx
Show resolved
Hide resolved
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
♻️ Duplicate comments (1)
apps/web/ui/partners/payout-invoice-sheet.tsx (1)
231-236
: Round the calculated fee to cents before use.
amount
is stored in cents whileselectedPaymentMethod.fee
is a percentage (e.g. 0.015). Multiplying them produces fractional cents, sofee
andtotal
can become non-integers; we also forward those raw values in the confirm payload. That leads to inconsistent invoice math and downstream rounding bugs. Compute the processing portion in cents and round it before adding the optional Fast ACH fee.- const fastAchFee = selectedPaymentMethod.fastSettlement - ? FAST_ACH_FEE_CENTS - : 0; - - const fee = amount * selectedPaymentMethod.fee + fastAchFee; - const total = amount + fee; + const processingFeeCents = Math.round( + amount * selectedPaymentMethod.fee, + ); + const fastAchFee = selectedPaymentMethod.fastSettlement + ? FAST_ACH_FEE_CENTS + : 0; + + const fee = processingFeeCents + fastAchFee; + const total = amount + fee;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/web/lib/actions/partners/confirm-payouts.ts
(6 hunks)apps/web/lib/zod/schemas/workspaces.ts
(1 hunks)apps/web/ui/partners/payout-invoice-sheet.tsx
(11 hunks)packages/prisma/schema/network.prisma
(2 hunks)packages/prisma/schema/partner.prisma
(1 hunks)packages/prisma/schema/program.prisma
(1 hunks)packages/prisma/schema/workspace.prisma
(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- packages/prisma/schema/partner.prisma
- packages/prisma/schema/program.prisma
- packages/prisma/schema/network.prisma
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/lib/actions/partners/confirm-payouts.ts
🧰 Additional context used
🧬 Code graph analysis (1)
apps/web/ui/partners/payout-invoice-sheet.tsx (4)
apps/web/lib/payment-methods.ts (2)
PAYMENT_METHODS
(27-64)calculatePayoutFeeForMethod
(5-25)packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter
(5-16)apps/web/lib/partners/constants.ts (2)
FAST_ACH_FEE_CENTS
(12-12)DIRECT_DEBIT_PAYMENT_METHOD_TYPES
(58-62)packages/ui/src/combobox/index.tsx (2)
Combobox
(85-367)ComboboxOption
(29-37)
⏰ 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 (1)
packages/prisma/schema/workspace.prisma (1)
48-48
: LGTM! Prisma schema definition is correct.The non-nullable
Boolean @default(false)
definition is appropriate for a feature flag. The field is logically placed with other boolean flags and the default value ensures safe migration for existing rows.Note: The corresponding Zod schema in
apps/web/lib/zod/schemas/workspaces.ts:175
should be updated to match this non-nullable definition.
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: 2
♻️ Duplicate comments (2)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx (2)
131-140
: Add rel="noopener noreferrer" to external invoice link.The anchor opening the invoice PDF uses
target="_blank"
but lacks security attributes to prevent reverse-tabnabbing and referrer leakage.Apply this diff:
<a href={invoice.pdfUrl} target="_blank" + rel="noopener noreferrer" className={cn( buttonVariants({ variant: "secondary" }), "flex h-9 items-center justify-center rounded-md border px-3 text-sm", )} > <span>View invoice</span> </a>
262-271
: Add rel="noopener noreferrer" to external invoice link (desktop view).Same security fix needed for the desktop layout.
Apply this diff:
<a href={invoice.pdfUrl} target="_blank" + rel="noopener noreferrer" className={cn( buttonVariants({ variant: "secondary" }), "flex h-9 items-center justify-center rounded-md border px-3 text-sm", )} > <span>View invoice</span> </a>
🧹 Nitpick comments (1)
apps/web/lib/stripe/payment-methods.ts (1)
16-18
: Extract magic number to a named constant.The
0.03
fee surcharge for link/card methods is hard-coded. Consider extracting it to a named constant alongsideFAST_ACH_FEE_CENTS
for better maintainability and clarity.Apply this diff:
+export const LINK_CARD_FEE_SURCHARGE = 0.03; + export const calculatePayoutFeeForMethod = ({ paymentMethod, payoutFee, }: { paymentMethod: Stripe.PaymentMethod.Type; payoutFee: number | undefined; }) => { if (!paymentMethod || payoutFee === undefined || payoutFee === null) { return null; } if (["link", "card"].includes(paymentMethod)) { - return payoutFee + 0.03; + return payoutFee + LINK_CARD_FEE_SURCHARGE; } if (DIRECT_DEBIT_PAYMENT_METHOD_TYPES.includes(paymentMethod)) { return payoutFee; } throw new Error(`Unsupported payment method ${paymentMethod}.`); };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts
(5 hunks)apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx
(2 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx
(4 hunks)apps/web/lib/cron/verify-vercel.ts
(1 hunks)apps/web/lib/partners/constants.ts
(3 hunks)apps/web/lib/stripe/payment-methods.ts
(1 hunks)apps/web/lib/zod/schemas/workspaces.ts
(1 hunks)apps/web/ui/partners/payout-invoice-sheet.tsx
(11 hunks)packages/email/src/templates/partner-payout-confirmed.tsx
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- apps/web/lib/partners/constants.ts
- apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx
- packages/email/src/templates/partner-payout-confirmed.tsx
- apps/web/lib/cron/verify-vercel.ts
- apps/web/lib/zod/schemas/workspaces.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-18T20:23:38.835Z
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/traffic-sources-block.tsx:50-82
Timestamp: 2025-06-18T20:23:38.835Z
Learning: Internal links within the same application that use target="_blank" may not require rel="noopener noreferrer" according to the team's security standards, even though it's generally considered a best practice for any target="_blank" link.
Applied to files:
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx
🧬 Code graph analysis (4)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx (3)
apps/web/lib/types.ts (1)
InvoiceProps
(510-510)apps/web/lib/partners/constants.ts (1)
INVOICE_PAYMENT_METHODS
(70-91)packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter
(5-16)
apps/web/lib/stripe/payment-methods.ts (1)
apps/web/lib/partners/constants.ts (1)
DIRECT_DEBIT_PAYMENT_METHOD_TYPES
(58-62)
apps/web/ui/partners/payout-invoice-sheet.tsx (4)
apps/web/lib/stripe/payment-methods.ts (2)
STRIPE_PAYMENT_METHODS
(27-58)calculatePayoutFeeForMethod
(5-25)packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter
(5-16)apps/web/lib/partners/constants.ts (2)
FAST_ACH_FEE_CENTS
(12-12)DIRECT_DEBIT_PAYMENT_METHOD_TYPES
(58-62)packages/ui/src/combobox/index.tsx (2)
Combobox
(85-367)ComboboxOption
(29-37)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts (1)
apps/web/lib/partners/constants.ts (1)
FAST_ACH_FEE_CENTS
(12-12)
🪛 Biome (2.1.2)
apps/web/ui/partners/payout-invoice-sheet.tsx
[error] 642-642: Avoid using target="_blank" without rel="noopener" or rel="noreferrer".
Opening external links in new tabs without rel="noopener" is a security risk. See the explanation for more details.
Safe fix: Add the rel="noopener" attribute.
(lint/security/noBlankTarget)
⏰ 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 (9)
apps/web/lib/stripe/payment-methods.ts (1)
27-58
: LGTM!The
STRIPE_PAYMENT_METHODS
constant is well-structured with appropriate metadata for each payment method. The use ofObject.freeze
ensures immutability.apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts (3)
134-141
: LGTM!The early invoice loading and Fast ACH fee calculation are correctly implemented. The condition checks for
invoice.paymentMethod === "ach_fast"
which aligns with the normalized payment method values used throughout the codebase.
189-196
: LGTM!The conditional Stripe payment intent configuration correctly sets
preferred_settlement_speed
based on the invoice payment method, enabling Fast ACH settlements when appropriate.
269-269
: LGTM!The email payload correctly includes the payment method with a sensible fallback to "ach" for backward compatibility.
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx (1)
104-110
: LGTM!The updated component signature with
displayPaymentMethod
parameter provides flexible payment method display control. The default value ensures backward compatibility.apps/web/ui/partners/payout-invoice-sheet.tsx (4)
112-170
: LGTM!The payment method options generation correctly creates separate entries for standard and Fast ACH when enabled. The ID suffix approach (
-fast
) is properly handled throughout the flow.
217-244
: LGTM!The fee calculation correctly uses
Math.round()
to handle fractional cents that result from multiplying the payout amount by the fee rate. The Fast ACH fee is properly added as a fixed cost in cents.
250-336
: LGTM!The Combobox integration provides a better UX with rich option rendering, including icons and Fast ACH fee metadata. The implementation properly handles selection state and callbacks.
558-559
: LGTM!The payout confirmation correctly strips the
-fast
suffix and passes thefastSettlement
flag separately, cleanly separating UI representation from the API payload.
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx
Outdated
Show resolved
Hide resolved
@coderabbitai full review |
✅ Actions performedFull review triggered. |
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: 0
🧹 Nitpick comments (1)
apps/web/lib/partners/constants.ts (1)
78-99
: Consider adding type definitions for better type safety.The
INVOICE_PAYMENT_METHODS
constant is well-structured withObject.freeze
for immutability. However, consider defining an explicit type for the payment method keys and structure to improve type safety across the codebase.Example type definitions:
type InvoicePaymentMethodKey = "card" | "ach" | "ach_fast" | "sepa" | "acss"; type InvoicePaymentMethodInfo = { label: string; duration: string; }; export const INVOICE_PAYMENT_METHODS: Readonly<Record<InvoicePaymentMethodKey, InvoicePaymentMethodInfo>> = Object.freeze({ // ... existing implementation });This would provide better autocomplete and catch mismatched keys at compile time.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/lib/partners/constants.ts
(2 hunks)
⏰ 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/lib/partners/constants.ts (3)
12-12
: LGTM! Fast ACH fee constant is well-defined.The
FAST_ACH_FEE_CENTS
constant follows the established pattern of other fee constants in this file and clearly represents the $25 fee for fast ACH transfers.
101-105
: LGTM! Payout statuses are clearly defined.The
INVOICE_AVAILABLE_PAYOUT_STATUSES
array appropriately defines the statuses for available payouts.
70-76
: ACH normalization and fast‐ACH override verified.
STRIPE_PAYMENT_METHOD_NORMALIZATION
is used for standard ACH, and inconfirm-payouts
thefastSettlement
flag correctly switches to"ach_fast"
. Downstream consumers—including migrations, API handlers, and the UI—support both"ach"
and"ach_fast"
.
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: 2
♻️ Duplicate comments (2)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx (2)
131-140
: Add rel="noopener noreferrer" to external invoice link (mobile).The anchor opens an external PDF without security attributes, creating a reverse-tabnabbing risk.
Apply this diff:
<a href={invoice.pdfUrl} target="_blank" + rel="noopener noreferrer" className={cn( buttonVariants({ variant: "secondary" }), "flex h-9 items-center justify-center rounded-md border px-3 text-sm", )} >
262-271
: Add rel="noopener noreferrer" to external invoice link (desktop).Same security issue as mobile view.
Apply this diff:
<a href={invoice.pdfUrl} target="_blank" + rel="noopener noreferrer" className={cn( buttonVariants({ variant: "secondary" }), "flex h-9 items-center justify-center rounded-md border px-3 text-sm", )} >
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx
(4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-18T20:23:38.835Z
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/traffic-sources-block.tsx:50-82
Timestamp: 2025-06-18T20:23:38.835Z
Learning: Internal links within the same application that use target="_blank" may not require rel="noopener noreferrer" according to the team's security standards, even though it's generally considered a best practice for any target="_blank" link.
Applied to files:
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx
🧬 Code graph analysis (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/invoices/page-client.tsx (3)
apps/web/lib/types.ts (1)
InvoiceProps
(510-510)apps/web/lib/partners/constants.ts (1)
INVOICE_PAYMENT_METHODS
(78-99)packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter
(5-16)
⏰ 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
Summary by CodeRabbit
New Features
Bug Fixes
Chores