Skip to content

OUT-3609: bank account selector dropdown for invoice settings - #232

Merged
SandipBajracharya merged 2 commits into
feature/stripe-fees-and-depositfrom
OUT-3609
Apr 21, 2026
Merged

OUT-3609: bank account selector dropdown for invoice settings#232
SandipBajracharya merged 2 commits into
feature/stripe-fees-and-depositfrom
OUT-3609

Conversation

@SandipBajracharya

@SandipBajracharya SandipBajracharya commented Apr 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add bank account dropdown in Invoice Detail settings (below bankDepositFeeFlag checkbox)
  • Fetch QBO bank accounts via SWR (GET /api/quickbooks/setting/bank-account)
  • Include bankAccountRef in settingState for single-request save
  • Click-outside-to-close, loading state, empty state, and amber warning when unselected
  • Pass new props through SettingAccordionInvoiceDetail

Files changed

  • src/hook/useSettings.tsuseInvoiceDetailSettings hook: bank account state, SWR fetch, single API call submit
  • src/components/dashboard/settings/sections/invoice/InvoiceDetail.tsx — custom dropdown UI
  • src/components/dashboard/settings/SettingAccordion.tsx — prop passthrough

Test plan

  • Enable absorbedFeeFlagbankDepositFeeFlag checkbox appears
  • Enable bankDepositFeeFlag → bank account dropdown appears, loads QBO accounts
  • Select a bank account → Confirm button shows
  • Click Confirm → settings + bankAccountRef saved in single request
  • Reload page → selected bank account persists
  • Cancel → resets to saved state
  • Disable absorbedFeeFlag → dropdown and deposit checkbox disappear
  • Warning shown when flag is on but no account selected

🤖 Generated with Claude Code

SandipBajracharya and others added 2 commits April 21, 2026 18:05
…s UI

- Add bank account dropdown in InvoiceDetail below bankDepositFeeFlag checkbox
- Fetch QBO bank accounts via SWR (GET /api/quickbooks/setting/bank-account)
- Include bankAccountRef in settingState for single-request save
- Add click-outside-to-close, loading state, and amber warning when unselected
- Pass bankAccounts, isBankAccountsLoading, selectBankAccount props via SettingAccordion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t bank account

Block the Confirm/Update button when bankDepositFeeFlag is on but no
bank account is selected. Without a bank account, the webhook deposit
flow throws on every payment.succeeded event.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Apr 21, 2026

Copy link
Copy Markdown

@vercel

vercel Bot commented Apr 21, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
quickbooks-sync Ready Ready Preview, Comment Apr 21, 2026 0:35am

Request Review

@greptile-apps

greptile-apps Bot commented Apr 21, 2026

Copy link
Copy Markdown

Greptile Summary

This PR introduces Stripe absorbed-fees and bank-deposit settings to the Invoice Details section: two new checkboxes (absorbedFeeFlag, bankDepositFeeFlag) and a conditionally-rendered bank-account dropdown backed by a new SWR-powered endpoint. The showButton guard correctly blocks submission when bankDepositFeeFlag is on but no account is selected.

Two minor quality issues were noted: bankAccountRef is not reset to null when absorbedFeeFlag is disabled (stale value gets persisted to the backend), and the changeSettings prop type in InvoiceDetail is narrower (boolean) than the hook's implementation (boolean | string | null), which could cause confusing TypeScript errors for future callers.

Confidence Score: 5/5

Safe to merge; the two findings are P2 quality issues that do not block core functionality.

All findings are P2 — a stale bankAccountRef in an edge-case submit path and a type-width mismatch. Neither causes a runtime error or user-visible breakage in the happy path.

src/components/dashboard/settings/sections/invoice/InvoiceDetail.tsx — stale bankAccountRef on toggle-off

Important Files Changed

Filename Overview
src/hook/useSettings.ts Adds useInvoiceDetailSettings with new absorbedFeeFlag, bankDepositFeeFlag, and bankAccountRef state; conditionally fetches bank accounts via SWR; changeSettings accepts `boolean
src/components/dashboard/settings/sections/invoice/InvoiceDetail.tsx New UI for absorbed-fees and bank-deposit checkboxes plus a bank-account dropdown; bankAccountRef is not reset to null when absorbedFeeFlag is disabled, causing a stale value to be submitted to the backend.
src/components/dashboard/settings/SettingAccordion.tsx Wires the new bankAccounts, isBankAccountsLoading, and selectBankAccount props through to InvoiceDetail; no issues found.

Sequence Diagram

sequenceDiagram
    participant U as User
    participant ID as InvoiceDetail (UI)
    participant H as useInvoiceDetailSettings
    participant SWR as SWR Cache
    participant API as /api/quickbooks/setting

    U->>ID: Toggle absorbedFeeFlag ON
    ID->>H: changeSettings('absorbedFeeFlag', true)
    H->>H: setSettingState(...)

    U->>ID: Toggle bankDepositFeeFlag ON
    ID->>H: changeSettings('bankDepositFeeFlag', true)
    H->>SWR: fetch /api/quickbooks/setting/bank-account
    SWR-->>H: bankAccounts[]
    H-->>ID: render bank account dropdown

    U->>ID: Select bank account
    ID->>H: selectBankAccount(id)
    H->>H: setSettingState({ bankAccountRef: id })

    U->>ID: Click Update Setting
    ID->>H: submitInvoiceSettings()
    H->>API: POST { absorbedFeeFlag, bankDepositFeeFlag, bankAccountRef, ... }
    API-->>H: success
    H->>SWR: mutate(invoice settings key)

    Note over ID,H: If absorbedFeeFlag toggled OFF,
    Note over ID,H: bankDepositFeeFlag is reset but
    Note over ID,H: bankAccountRef retains stale value
Loading

Comments Outside Diff (1)

  1. src/components/dashboard/settings/sections/invoice/InvoiceDetail.tsx, line 58-65 (link)

    P2 bankAccountRef not cleared when disabling absorbedFeeFlag

    When absorbedFeeFlag is toggled off, bankDepositFeeFlag is correctly reset to false, but bankAccountRef retains its previous value. The entire settingState (including the stale bankAccountRef) is submitted to the backend via submitInvoiceSettings, meaning the bank account reference is persisted even though neither deposit flag is active. If the backend ever reads bankAccountRef without checking the parent flags, this can cause unintended behaviour.

    Alternatively, expose a dedicated clearBankAccount helper from the hook that calls setSettingState(prev => ({ ...prev, bankAccountRef: null })) and call it here.

Reviews (1): Last reviewed commit: "fix(OUT-3609): prevent settings save whe..." | Re-trigger Greptile

Comment thread src/hook/useSettings.ts
Comment on lines +548 to 556
const changeSettings = (
flag: keyof InvoiceSettingType,
state: boolean,
state: boolean | string | null,
) => {
setSettingState((prev) => ({
...prev,
[flag]: state,
}))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 changeSettings prop type is narrower than the hook's implementation

InvoiceDetailProps.changeSettings is declared as (flag: keyof InvoiceSettingType, state: boolean) => void, but the hook's implementation accepts boolean | string | null. Because bankAccountRef is string | null in InvoiceSettingType, any future attempt to call changeSettings('bankAccountRef', ...) directly from InvoiceDetail will be rejected by TypeScript with the current prop type. Aligning the types avoids this footgun — update both the hook signature and the InvoiceDetailProps declaration to boolean | string | null.

@SandipBajracharya SandipBajracharya changed the title OUT-3609 OUT-3609: bank account selector dropdown for invoice settings Apr 21, 2026
@SandipBajracharya
SandipBajracharya merged commit 0748e3d into feature/stripe-fees-and-deposit Apr 21, 2026
4 checks passed
@SandipBajracharya

Copy link
Copy Markdown
Collaborator Author

Same changes as in PR which has been approved.

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.

1 participant