Fix Account and Wallet RBR still showing for personal cards past the 90-day grace period#96364
Fix Account and Wallet RBR still showing for personal cards past the 90-day grace period#96364wildan-m wants to merge 3 commits into
Conversation
…race period The 90-day grace correctly removed the home task, but the Account indicator and the Wallet row red dot stayed lit for personal cards. Both are driven by the card's own error, which the issue requires us to keep so the card stays fixable: - getShouldShowRBR short-circuits on hasFeedErrors before the grace check, so a past-grace card's error still forced the RBR. - hasPaymentMethodError counts any personal card with errors, and it feeds both the Account indicator (useAccountIndicatorChecks) and the Wallet row (InitialSettingsPage). Gate both on isBrokenConnectionPastDismissThreshold, leaving card.errors untouched so the Wallet-page card row keeps its error and Fix card action. Adds regression tests for a past-grace card that still carries the error (the case the original fixtures missed), plus guards that within-grace and unrelated errors still show.
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
…al-card-rbr-followup
|
@jayeshmangwani Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ac02fdb2c8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // The broken connection is reported as an error on the card itself, so past the grace period it must not | ||
| // count towards the RBR either — otherwise keeping the error (so the card stays fixable) would keep the | ||
| // Account/Wallet red dot lit forever. | ||
| const hasCardErrors = (!isEmptyObject(card.errors) || !isEmptyObject(card.errorFields)) && !isPastDismissThreshold; |
There was a problem hiding this comment.
Don't suppress unrelated personal-card field errors
When a personal card is past the broken-connection dismiss threshold, this drops every card.errors/card.errorFields entry, not just the stale connection prompt. For example, a failed personal-card reimbursable or start-date update writes card.errorFields in src/libs/actions/Card.ts, and if the card also still has the old broken lastScrapeResult/lastScrape, personalCard.shouldShowRBR remains false, so Settings > Wallet no longer gets a red dot for that new actionable field error.
Useful? React with 👍 / 👎.
| // Once a personal card's broken connection has been unresolved past the grace period we stop leading the user | ||
| // to it, so it must not light the Account/Wallet RBR. The error itself is kept on the card so it can still be | ||
| // fixed from the Wallet page. | ||
| return !CardUtils.isBrokenConnectionPastDismissThreshold(card); |
There was a problem hiding this comment.
Don't hide fresh card errors on stale broken cards
This returns false for any personal card with errors once its broken connection is past the dismiss threshold, even if those errors came from a different action. A failed remove/unassign restores the card with a generic card.errors while preserving the stale broken-connection fields, so the Account/Wallet indicators stop lighting for that new failure; the grace-period check should only suppress the broken-connection error itself.
Useful? React with 👍 / 👎.
|
@jayeshmangwani @joekaufmanexpensify The follow up PR is ready |
Addresses Codex review. The previous change dropped ALL of a stale-broken personal card's errors/errorFields, so an unrelated actionable error also lost its RBR — a failed reimbursable/start-date update (another errorFields entry) or a failed remove (card.errors). Now only errorFields.lastScrape (the broken-connection error the card detail page reads) is excluded from the RBR once past the grace period; every other error is kept. Reverts the over-broad hasPaymentMethodError gate, since card.errors on a personal card is an actionable error, not the connection error. Adds regression tests for a past-grace card that also carries an unrelated field error and one that carries a card-level error.
|
Good catch — fixed in |
Explanation of Change
Follow-up to #93523. That PR added the 90-day grace period and correctly removed the Home task, but for personal cards the
Accountindicator and theWalletrow red dot stayed on — which the issue asks us to remove:Reported on production by @joekaufmanexpensify: #91451 (comment)
Why it happens. Those two dots never ask "is this past 90 days?" — they only ask "does this card have an error?", via
getShouldShowRBR()(which returns early onhasFeedErrors) andhasPaymentMethodError()(true for any personal card with errors). Since the issue tells us to keep that error so the card stays fixable, the dots never turn off. The Home task disappearing is the giveaway: the 90-day check works, these two paths just skip it.The fix. Make both paths respect the same 90-day check.
card.errorsis untouched, so theWalletpage still shows the error with a working Fix card button — only theAccount/Walletdots stop. Cards inside the grace period, and cards with unrelated errors, are unaffected (both covered by new tests).Fixed Issues
$ #91451
PROPOSAL: #91451 (comment)
Tests
This is shared logic (no platform-specific code), so it behaves the same on web, mWeb, iOS and Android.
Important — what actually reproduces this. It only shows up on a personal card (one added on
Account > Wallet, i.e.fundIDis absent or'0') whose broken connection also carries an error on the card itself. That error is what lights theAccount/Walletred dots, and we deliberately keep it so the card stays fixable. A company card from a workspace will not reproduce it — it goes through the feed path, which the existing grace check already covers.Rather than waiting 90 days for real data, paste this in the browser console on a dev build to put your existing personal card into exactly that state:
Account > Wallet > Add personal card). Run the script withDAYS_AGO = 1.DAYS_AGO = 100.Walletpage: still listed with its own red dot, and opening it still shows "Your card connection is broken." with a working Fix card button (the error is kept so it stays fixable).RESET = trueto put the card back to healthy.You can also read the underlying state directly instead of eyeballing the dots:
shouldShowRBRis what drives theAccount/Walletred dots;isFeedConnectionBrokendrives the Home task. Onmainthe task is correctly gone butshouldShowRBRstaystrue— which is exactly what was reported.Offline tests
Same as the Tests above. This is a derived value computed from data already in Onyx plus the device date, so it behaves identically offline — the task and indicators stay hidden for a past-grace connection, and the card keeps its error and Fix card action.
QA Steps
Please treat this as a regression check around the card feature. Behaviour is the same on all platforms, so any one platform is fine.
Walletpage with its error and a working Fix card button.If a 90-days-broken connection isn't available as test data, the removal is also covered by automated unit tests; the essential manual checks are step 1 (recently-broken still prompts) and step 3 (no regressions).
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Kapture.2026-07-18.at.10.46.14.mp4