Repository navigation
Description
Summary
When a user's Verified Bank Account (VBA) is locked — either a workspace VBA (policy.achAccount.state === 'LOCKED') or a personal bank account (accountData.state === 'LOCKED') — there is currently no indication on the HomePage and no guided flow to resolve it in NewDot.
In OldDot, users see a "Fix" button on their locked bank account in settings, which opens the UnlockWithdrawalBankAccount modal. That modal calls the BankAccount_UnlockSend / InitiateBankAccountUnlock API to create a Concierge conversation escalated to Operations for manual resolution.
We should add a widget to the Time Sensitive section on the HomePage that alerts users when they have a locked bank account and provides a CTA to initiate the unlock flow (matching OldDot behavior).
Current Behavior
- The
SETTLEMENT_ACCOUNT_LOCKEDreport action posts a chat message with a link to workspace settings, but the workspace settings page treats a locked VBA as "no VBA" (hasVBAonly returnstrueforOPENstate), leading to a dead end. BankAccount.isLocked()helper exists insrc/libs/models/BankAccount.tsbut is unused.CONST.BANK_ACCOUNT.STATE.LOCKEDconstant is defined but not checked anywhere in the Time Sensitive section.- There is no equivalent of OldDot's
BankAccount_UnlockSendAPI integration in NewDot.
Expected Behavior
A new widget appears in the Time Sensitive section when any of the user's bank accounts are in the LOCKED state:
- Workspace VBAs: Show for workspace admins when
policy.achAccount.state === 'LOCKED' - Personal bank accounts: Show when
bankAccountList[].accountData.state === 'LOCKED'
The widget should display:
- A lock icon with a danger-colored background
- Title: "Your business bank account has been locked" (workspace) / "Your bank account has been locked" (personal)
- Subtitle: workspace name (for workspace VBAs) or "Wallet" (for personal)
- CTA button: "Fix" (reuse existing
ctaFixtranslation,danger: truestyle) - On press: Call
InitiateBankAccountUnlockAPI with thebankAccountID, then navigate to Concierge chat (matching OldDot behavior)
Data Availability
No new backend data is needed to detect locked VBAs:
policy.achAccount.statealready comes down viaONYXKEYS.COLLECTION.POLICYand includes theLOCKEDvalueONYXKEYS.BANK_ACCOUNT_LISTentries haveaccountData.statewhich can beLOCKED- Both are populated by existing
OpenApp/ReconnectAppAPI responses
For the unlock CTA:
- The
InitiateBankAccountUnlockwrite command already exists on the backend (apiCommandTypes.php) — it needs to be integrated into the NewDot API layer - It accepts a
bankAccountIDparameter and creates a Concierge conversation escalated to Operations
Implementation Details
Architecture
Backend (OpenApp) → Onyx (COLLECTION.POLICY, BANK_ACCOUNT_LIST)
↓
TimeSensitiveSection detects locked state
↓
UnlockBankAccount widget renders
↓
CTA → InitiateBankAccountUnlock API → Concierge chat
Files to Change
-
src/pages/home/TimeSensitiveSection/items/UnlockBankAccount.tsx(new)- Widget component using
BaseWidgetItem(same pattern asFixCompanyCardConnection.tsx) - Props:
bankAccountID,policyName?,maskedAccountNumber?
- Widget component using
-
src/pages/home/TimeSensitiveSection/index.tsx- Add detection logic: iterate
adminPoliciescheckingpolicy.achAccount?.state === CONST.BANK_ACCOUNT.STATE.LOCKED - Add
useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST)for personal locked accounts - Add condition to
hasAnyTimeSensitiveContentguard - Render widget at appropriate priority (suggest between broken card connections and discount offers)
- Add detection logic: iterate
-
src/libs/actions/BankAccounts.ts- Add
initiateBankAccountUnlock(bankAccountID: number)function calling theInitiateBankAccountUnlockwrite command
- Add
-
src/libs/API/types.ts- Add
InitiateBankAccountUnlockto write commands and parameter types
- Add
-
src/languages/en.ts,src/languages/pt-BR.ts,src/languages/zh-hans.ts- Add translation strings under
homePage.timeSensitiveSection.unlockBankAccount
- Add translation strings under
OldDot Reference
Key OldDot files for reference:
Web-Expensify/site/app/modals/settings/unlockWithdrawalBankAccount.jsx— unlock modal UIWeb-Expensify/site/app/settings/reimbursement/bankAccountView.jsx— locked state detection + "Fix" buttonWeb-Expensify/lib/BankAccountAPI.php—sendEmailToUnlock()backend logicWeb-Expensify/api.php—InitiateBankAccountUnlockcommand routing
Open Questions
- Should the masked account number be displayed in the widget? The
ACHAccounttype hasaccountNumber(may be masked from backend) and personalBankAccounthasdescription("Account ending in XXXX"). Need to verify actual API response format. - Priority order within Time Sensitive section: suggested after card fraud but before broken card connections, since a locked VBA blocks reimbursements.
EXFY-18795
Issue Owner
Current Issue Owner: @ZhenjaHorbachMetadata
Metadata
Type
Projects
- StatusShow more project fieldsDone
Activity
JmillsExpensify commentedon Mar 3, 2026
I'll get this one turned around today.
JmillsExpensify commentedon Mar 3, 2026
This is blocked on this PR, so putting it on Hold for now.
[-]Add Locked VBA (Verified Bank Account) widget to Time Sensitive section on HomePage[/-][+][HOLD] Add Locked VBA (Verified Bank Account) widget to Time Sensitive[/+]melvin-bot commentedon Mar 4, 2026
Triggered auto assignment to @dubielzyk-expensify (
Design), see these Stack Overflow questions for more details.grgia commentedon Mar 4, 2026
@dubielzyk-expensify we will need to confirm the mock here, though we can reuse the existing patterns
for context, we are holding on #69159
The action to unlock from the above PR is:
dubielzyk-expensify commentedon Mar 5, 2026
I re-read that like 4 times and have no idea what it means haha 😅 The time sensitive locked bank account card sounds good to me. Could you rephrase the question or let me know what mock is needed?
JmillsExpensify commentedon Mar 5, 2026
I think the CTA in Time Sensitive should be something like: "Unlock your bank account to resume payments."
grgia commentedon Mar 5, 2026
Haha that is from the QA steps from the PR
grgia commentedon Mar 5, 2026
I like that CTA @JmillsExpensify
25 remaining items
[-]Add Locked VBA (Verified Bank Account) widget to Time Sensitive[/-][+][Due for payment 2026-05-12] Add Locked VBA (Verified Bank Account) widget to Time Sensitive[/+]melvin-bot commentedon May 5, 2026
Reviewinglabel has been removed, please complete the "BugZero Checklist".melvin-bot commentedon May 5, 2026
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.66-7 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:
If no regressions arise, payment will be issued on 2026-05-12. 🎊
For reference, here are some details about the assignees on this issue:
ZhenjaHorbach commentedon May 6, 2026
I suppose we can close this issue
mountiny commentedon May 6, 2026
@JmillsExpensify i think first we should add regression test before closing
JmillsExpensify commentedon May 6, 2026
Agreed. I'll add one now.
JmillsExpensify commentedon May 6, 2026
All set.