Skip to content

OUT-4262: Disable QBO bank reconciliation beta and remove setting from UI - #291

Open
aschwartz91 wants to merge 2 commits into
masterfrom
cursor/disable-bank-reconciliation-beta-33b7
Open

aschwartz91 wants to merge 2 commits into
masterfrom
cursor/disable-bank-reconciliation-beta-33b7

Conversation

@aschwartz91

@aschwartz91 aschwartz91 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Context for @priosshrsth

Marlon approved shutting down the QBO automatic bank reconciliation beta. It still has bugs reported from customers, and further work is backlogged. As of today, all 8 beta workspaces have been emailed that it's turning off this week, with success@assembly.com cc'd.

This PR is the code side of OUT-4262 removes the setting from the UI and hard-disables deposit creation for every portal. Regular invoice and payment sync isn't affected.

After merging: clear the beta workspaces from AB_FEATURE_TESTING_PORTALS (rZSajb5cp, s2L9uTbcp, us-west-2_RGylW5Iu6, O2LKFe_9p, t4gOgqxzp, ASNx0Cznp, mWBjPk09p, us-east-1_FwKKN1cgl). The hard-off flag already blocks the feature, but this keeps the env tidy. I'm out after Friday, so please reach out to Marlon with any questions.


Context for @priosshrsth

Marlon approved shutting down the QBO automatic bank reconciliation beta. It still has bugs reported from customers, and further work is backlogged. As of today, all 8 beta workspaces have been emailed that it's turning off this week, with success@assembly.com cc'd.

This PR is the code side of OUT-4262 removes the setting from the UI and hard-disables deposit creation for every portal. Regular invoice and payment sync isn't affected.

After merging: clear the beta workspaces from AB_FEATURE_TESTING_PORTALS (rZSajb5cp, s2L9uTbcp, us-west-2_RGylW5Iu6, O2LKFe_9p, t4gOgqxzp, ASNx0Cznp, mWBjPk09p, us-east-1_FwKKN1cgl). The hard-off flag already blocks the feature, but this keeps the env tidy. I'm out after Friday, so please reach out to Marlon with any questions.


Changes

  • Add hard-off flag (BANK_DEPOSIT_FEATURE_ENABLED = false) in isPortalInBankDepositABTest() to block new invoices from being marked as batched
  • Remove AB gate from PayoutService#reconcile() so existing invoices with isBatchedDeposit=true can still have their deposits created and Stripe fees booked
  • Remove "Create bank deposits for automatic bank reconciliation" toggle from Invoice Details settings UI
  • Remove deposit bank account picker from Invoice Details settings UI
  • Remove bank deposit warning modal and related state from useInvoiceDetailSettings hook
  • Remove unused props from InvoiceDetail component and SettingAccordion
  • Update unit tests to reflect the new behavior

Resolves OUT-4262

Requesting review from @priosshrsth

How Existing Batched Invoices Are Handled

The hard-off works at two different points:

Point Behavior Why
Invoice freeze point (InvoiceService#readBankDepositFeeFlag) Returns false → new invoices freeze as non-batched Hard-off prevents new batched invoices
Payout reconciliation (PayoutService#reconcile) No AB gate → processes all payouts normally Existing isBatchedDeposit=true invoices get their deposits created and fees booked

This ensures payments already in Undeposited Funds are properly deposited and Stripe fees are booked, while preventing new invoices from being batched.

Env Var Semantics Change

Important: This changes the semantics of AB_FEATURE_TESTING_PORTALS:

Before After
Empty/unset = feature enabled for all portals Empty/unset = feature disabled for everyone (hard-off takes precedence)
Set with portal IDs = enabled only for listed portals Same, but hard-off must be turned off first

To re-enable the feature in the future, set BANK_DEPOSIT_FEATURE_ENABLED = true in src/utils/abTesting.ts.

Testing Criteria

  • All 294 unit tests pass (npx vitest run --project unit)
  • ESLint passes with no new warnings
  • TypeScript type check passes
  • Integration tests are not affected (they mock isPortalInBankDepositABTest directly)

Note: Integration tests could not be run in the CI environment due to Docker unavailability, but they mock the AB gate function directly and will continue to work.

Notes

  • The feature code is preserved (not deleted) so it can be revived later by changing one constant
  • No database migrations or schema changes are needed
  • Existing qb_settings.bank_deposit_fee_flag values in the DB are ignored at runtime since the hard-off gate returns false before checking them
  • Related: OUT-3617 (original AB gate implementation in PR OUT-3617-new: AB feature-testing gate for the bank deposit flow #278)

Impact & Surface Area of Change

  • Settings UI: Invoice Details section no longer shows bank deposit toggle or bank account picker
  • Invoice freeze point: InvoiceService#readBankDepositFeeFlag returns false for all portals, so new invoices freeze with isBatchedDeposit = false
  • Payout reconciliation: PayoutService#reconcile continues to process all payouts normally, so existing batched invoices get their deposits created
  • Existing syncs: Regular invoice/payment sync is unaffected
Open in Web Open in Cursor 

- Add hard-off flag in isPortalInBankDepositABTest to disable the feature
  for all portals regardless of AB_FEATURE_TESTING_PORTALS env var
- Remove bank deposit toggle and bank account picker from Invoice Details UI
- Remove bank deposit warning modal and related state from useInvoiceDetailSettings
- Remove unused props from InvoiceDetail component and SettingAccordion
- Update unit tests to reflect the hard-off behavior

The feature code is preserved and can be re-enabled by setting
BANK_DEPOSIT_FEATURE_ENABLED to true in src/utils/abTesting.ts.

This changes the semantics of AB_FEATURE_TESTING_PORTALS: previously
empty/unset meant enabled for all portals; now the hard-off flag takes
precedence, so empty/unset means disabled for everyone.

Co-authored-by: Adam Schwartz <aschwartz91@users.noreply.github.com>
@vercel

vercel Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
quickbooks-sync Ready Ready Preview Oct 15, 2026 11:37am UTC

Request Review

@linear-code

linear-code Bot commented Oct 14, 2026

Copy link
Copy Markdown

OUT-4262

@greptile-apps

greptile-apps Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] Disables bank reconciliation feature across the product.

Finish or explicitly clean up existing batched invoices before merging the hard-off.

Findings

  1. P1 Existing invoices lose their deposits ▶
  2. P2 Test describes the opposite behavior ▶

Summary

This PR disables the bank deposit beta for every portal and removes its controls from Invoice Details.

  • The bank-deposit beta stays off for every portal.
  • Invoice Details no longer offers bank-deposit settings.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A["Existing invoice: isBatchedDeposit = true"] --> B["Payment goes to Undeposited Funds"]
  A --> C["Individual Stripe fee is deferred"]
  B --> D["Payout arrives"]
  C --> D
  D --> E["Hard-off gate returns no deposit"]
  E --> F["Webhook records SUCCESS"]
  F --> G["Payment remains in Undeposited Funds; fee is missing"]
Loading

Reviews (1) · Last reviewed commit: "feat: disable QBO bank reconciliation be..." · Reviewed by Greptile

Comment thread src/utils/abTesting.ts
* listed portals get it.
*/
export function isPortalInBankDepositABTest(_portalId: string): boolean {
if (!BANK_DEPOSIT_FEATURE_ENABLED) return false

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Existing invoices lose their deposits

Existing invoices with isBatchedDeposit = true still send payments to Undeposited Funds and defer their Stripe fees until the payout. This hard-off makes PayoutService.reconcile skip their deposit, but the webhook still records SUCCESS. Their payments remain in Undeposited Funds and their fees are never booked.

Disable batching for new invoices, but finish existing batched invoices or provide an explicit cleanup path before disabling payout work.

})

it('saves the flag and the bank account ref for an AB-test portal', async () => {
it('drops the flag even when gate mock returns true (defensive test for future re-enablement)', async () => {

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 Test describes the opposite behavior

The new name says the flag is dropped when the gate returns true, but the assertions require bankDepositFeeFlag to be saved as true and the bank account to be written. This gives maintainers the wrong description of what the test protects. Rename it to describe saving the flag and account when the gate allows the portal.

Suggested change
it('drops the flag even when gate mock returns true (defensive test for future re-enablement)', async () => {
it('saves the flag and bank account when the gate returns true', async () => {

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

…262)

- Remove AB gate from PayoutService#reconcile() so existing invoices with
  isBatchedDeposit=true can still have their deposits created and fees booked
- Keep the hard-off at the invoice freeze point (InvoiceService#readBankDepositFeeFlag)
  so new invoices freeze as non-batched
- Update payout service unit tests to reflect the removal of AB gate
- Rename misnamed test to 'saves the flag and bank account when the gate returns true'

This ensures payments already in Undeposited Funds get properly deposited
and Stripe fees are booked, while preventing new invoices from being batched.

Co-authored-by: Adam Schwartz <aschwartz91@users.noreply.github.com>

This branch was successfully deployed

1 active deployment
Preview — 8a1a1808 Deployed Oct 15, 2026 by vercel[bot]
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