fix: keep multi-expense drafts submittable when a subset of receipts …#94456
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 424f73b1ed
ℹ️ 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".
|
I can reproduce this on both staging and dev with this PR:
Screen.Recording.2026-06-25.at.12.13.48.movAccording to the PR description, this shouldn't happen, right? Can you confirm if that is intentional? Thanks. @deetergp @yusufdeveloper2903 |
|
@brunovjk that's expected here — Submit is hidden because that expense is scan-failed with missing required fields, so it's not in a submittable state and its If we want, I can extend the fix so Submit still shows in this case too (as long as there's at least one valid expense) — just let me know if that's the desired behavior. cc @deetergp |
|
Great, thanks for clarifying. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridApp94456_android_web.movAndroid: mWeb Chrome94456_android_web.moviOS: HybridApp94456_ios_native.moviOS: mWeb Safari94456_ios_web.movMacOS: Chrome / Safari94456_web_chrome.mov |
|
Congrats, that's your 5th PR merged! 🎉 Do you know about the ContributorPlus role? It's an opportunity to earn more in the Expensify Open Source community. Keep up the great work - thanks! |
|
🚧 deetergp has triggered a test Expensify/App build. You can view the workflow run here. |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/deetergp in version: 9.4.22-1 🚀
|
|
Deploy Blocker #94884 was identified to be related to this PR. |
|
This PR failing because of the issue #94884 |
|
🚀 Deployed to staging by https://github.com/deetergp in version: 9.4.24-0 🚀
|
|
🤖 No help site changes required — I did not create a docs PR. This PR is a bug fix that makes a multi-expense draft stay submittable when only a subset of its receipts fail SmartScan with missing fields. It restores the Submit affordance, the To Do "to submit" tray entry, and the Spend → Drafts listing for those partially-blocked drafts. It adds no new feature, setting, tab, or UI label. The behavior this PR restores is already documented correctly in the help site, so nothing needs editing:
— Create-and-Submit-Reports.md (live article). The pre-fix code contradicted that line (one scan-failed receipt among several valid ones hid the button); the fix brings the app back in line with the existing docs. I checked the related articles too — Understanding-Report-Statuses-and-Actions.md and Expense-and-Report-Actions.md — and none of them describe the old (buggy) gating, so there is nothing inaccurate to update. @yusufdeveloper2903, since no docs PR was needed, there is no linked help site PR to review. If you believe a doc should be added or clarified (e.g. explicitly calling out the partial scan-failure case in the Submit FAQ), let me know and I'll draft one. |
|
🚀 Deployed to production by https://github.com/cristipaval in version: 9.4.24-0 🚀
Bundle Size Analysis (Sentry): |
|
🚀 Deployed to staging by https://github.com/deetergp in version: 9.4.24-0 🚀
|
Explanation of Change
A draft expense report stopped surfacing its Submit affordance whenever it contained even a single receipt that failed SmartScan and was still missing required fields. The report disappeared from the To Do "to submit" tray, from Spend → Drafts, and lost its in-report Submit button, yet it remained findable via the manual
status:draftsfilter — exactly the reported symptom.The root cause is that both submit predicates gate on
hasSmartScanFailedWithMissingFields, which is a whole-report.some(...): one scan-failed/missing-fields receipt among many makes ittruefor the entire report.isSubmitAction(src/libs/ReportPrimaryActionUtils.ts) returnsfalseon that gate → no To Do tray entry, no Submit button.canSubmitReport(src/libs/actions/IOU/ReportWorkflow.ts) returnsfalseon the same gate → the report's computed action is no longerSUBMIT, so it drops out of the cannedaction:submitDrafts search.This change makes both submit gates block only when there is genuinely nothing to submit — i.e. when every transaction is blocked — mirroring the "all" semantics the codebase already uses for the scanning check (
transactions.every((t) => isScanningTransaction(t))):isSubmitAction, the scanning gate and the scan-failed gate now block only when every transaction is scanning / scan-failed-with-missing-fields, so a partially-blocked draft stays submittable.canSubmitReport, thehasSmartScanFailedWithMissingFieldsterm is now evaluated per-transaction with.every, kept aligned with the already-everyscanning term directly above it.Single-expense reports are unchanged (one failed receipt is the only expense → genuinely nothing to submit).
todos.tsand the report header need no changes — both derive fromisSubmitAction.Fixed Issues
$ #93949
PROPOSAL: #93949 (comment)
Tests
Offline tests
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)Avatar, 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
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Before fix:
Before-fix-mac-chrome.mp4
After fix:
After-fix-mac-chrome.mp4