Skip to content

Use one export rule across the to-do, the sidebar and the report page - #102953

Open
dukenv0307 wants to merge 18 commits into
Expensify:mainfrom
dukenv0307:unify-export-rule
Open

dukenv0307 wants to merge 18 commits into
Expensify:mainfrom
dukenv0307:unify-export-rule

Conversation

@dukenv0307

@dukenv0307 dukenv0307 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Explanation of Change

Read the exporter from the connections like the server does, and skip reports that are archived, queued for export, or cash-basis and not yet paid.

Fixed Issues

$ #102868
BE PR: https://github.com/Expensify/Auth/pull/25129, https://github.com/Expensify/Auth/pull/25628

Tests

  1. Sign in as an admin on a Collect/Control workspace with an accounting integration connected (QuickBooks Online, Xero or Sage Intacct).
  2. Go to Workspace → Accounting → Advanced and set:
    • Auto-sync: off
    • Accounting method: Cash
  3. In the integration's export settings, confirm the Preferred exporter is your own account.
  4. Create an expense on that workspace, submit it, and approve it. Do not pay it.
  5. Open Home and look at the To-dos list.
    • Expected: there is no "Export 1 report" row for this report.
  6. Open Reports (Spend) and search type:expense-report action:export exported:never exporter:me.
    • Expected: no results — the same answer as the to-do.
  7. Pay the report.
  8. Reload Home and re-run the same search.
  9. Verify that the report now appears in both — "Export 1 report" on Home, and 1 result in the search.
  • Verify that no errors appear in the JS console

Offline tests

Same as above

QA Steps

Same as above

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari Screenshot 2026-10-03 at 11 17 52 Screenshot 2026-10-03 at 11 19 41 Screenshot 2026-10-03 at 11 18 00

@dukenv0307 dukenv0307 changed the title Use one export rule across the to-do, the sidebar and the report page [Hold BE] Use one export rule across the to-do, the sidebar and the report page Oct 5, 2026
@dukenv0307

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-21T22:37:53.687728Z
We couldn’t complete this review. Comment @codex review to try again.
8de29f4 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.

Files with missing lines Coverage Δ
src/CONST/index.ts 95.90% <ø> (ø)
src/libs/ReportPrimaryActionUtils.ts 95.52% <100.00%> (+0.50%) ⬆️
src/libs/SearchUIUtils.ts 73.60% <100.00%> (-0.02%) ⬇️
src/libs/TodosUtils.ts 97.14% <100.00%> (ø)
src/libs/ReportPreviewActionUtils.ts 91.73% <75.00%> (-0.71%) ⬇️
src/libs/ReportUtils.ts 88.92% <94.44%> (+0.09%) ⬆️
src/libs/PolicyUtils/connections.ts 95.77% <91.66%> (-2.10%) ⬇️
... and 10 files with indirect coverage changes

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c927d9ab2

ℹ️ 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".

Comment thread tests/unit/TodosUtilsTest.ts
Comment thread src/libs/ReportPrimaryActionUtils.ts
Comment thread src/libs/ReportPrimaryActionUtils.ts
Comment thread src/libs/ReportUtils.ts
@dukenv0307

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 920bf86e10

ℹ️ 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".

Comment thread src/libs/ReportPrimaryActionUtils.ts Outdated
Comment thread src/libs/ReportPrimaryActionUtils.ts
@dukenv0307
dukenv0307 marked this pull request as ready for review October 13, 2026 04:05
@dukenv0307
dukenv0307 requested review from a team as code owners October 13, 2026 04:05
@melvin-bot
melvin-bot Bot requested review from joekaufmanexpensify and situchan and removed request for a team October 13, 2026 04:05
@melvin-bot

melvin-bot Bot commented Oct 13, 2026

Copy link
Copy Markdown

@situchan 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]

@melvin-bot
melvin-bot Bot removed the request for review from a team October 13, 2026 04:05
Comment thread src/libs/ReportUtils.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b3aa80d9f

ℹ️ 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".

Comment thread src/libs/ReportUtils.ts Outdated
@dukenv0307 dukenv0307 changed the title [Hold BE] Use one export rule across the to-do, the sidebar and the report page Use one export rule across the to-do, the sidebar and the report page Oct 13, 2026

@joekaufmanexpensify joekaufmanexpensify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good for product

@situchan

Copy link
Copy Markdown
Contributor
bug.mov

I set accountingMethod by manually switching to Accrual and then back to Cash.
It's weird that accountingMethod wasn't set first time (without switching).

@situchan

Copy link
Copy Markdown
Contributor

So the bug is that Cash is selected as default in UI, despite accountingMethod key not exist after connecting integration.
Only set after calling UpdateQuickbooksOnlineAccountingMethod api.
Should we fix this separately?

test
bug.mov

@situchan

Copy link
Copy Markdown
Contributor

Looks good. Just waiting on #102953 (comment)

@situchan

Copy link
Copy Markdown
Contributor

@codex review

@situchan

Copy link
Copy Markdown
Contributor

@MelvinBot review

@MelvinBot

Copy link
Copy Markdown
Contributor

Review

The logic looks right overall, and every CI check passes except the PR Author checklist. I found two things to fix before merge, plus the cash-basis item you already raised.

1. Cash basis: the report preview still offers Export. ReportPrimaryActionUtils.ts:351-353 now hides Export on an approved but unpaid cash-basis report. canExport in ReportPreviewActionUtils.ts:202-230 still returns isApproved || isReimbursed || isClosed for the same report. On main, both places agree. After this PR, the exporter sees no Export in the report header or the to-do, but does see it on the chat preview. The queued-export gap there predates this PR, but this mismatch is new. Apply the same accounting-method check in canExport.

2. The file's doc comment now sits on an import. In connections.ts:12-16, the "Which accounting integration is connected…" block comment moved below the imports. It now reads as JSDoc for import {CONST as COMMON_CONST} from 'expensify-common'. Move it back to the top of the file.

3. Card-only reports on cash basis (your open thread). You're still waiting on the backend fix. When it lands, the cash branch at ReportPrimaryActionUtils.ts:351 needs the same carve-out, for example isReportReimbursed || hasOnlyNonReimbursableTransactions(...). Also decide how mixed reports behave, since cash basis holds back only out-of-pocket spend. Without this, the to-do, Search and the header will drift apart again.

Checked with no issues
  • hasExportError now reads only the latest integration message, and ignores messages older than the last approval reset. This also changes didExportFail in the primary and secondary actions. That looks intended and more accurate.
  • isQueuedForExport falls back to report.lastActionType. A stale queued value is safe, because isExported and hasExportError run first or override it.
  • The reportNameValuePairs passed from getReportPrimaryAction belong to the expense report, not the chat. That matches how the pay check on line 237 uses them, so the archive gate reads the right flag.
  • getIntegrationAccountingMethod leaves out Certinia. That's correct, because FinancialForceConnectionConfig has no accountingMethod.
  • The new tests still have no // Given / // When / // Then comments, which CLAUDE.md requires. You've already declined this on purpose, so I'm only noting it.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d72b9d07ba

ℹ️ 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".

Comment thread src/libs/PolicyUtils/connections.ts
Comment thread src/libs/ReportPrimaryActionUtils.ts Outdated
@MelvinBot

Copy link
Copy Markdown
Contributor

Regression check

I found one likely regression and three smaller risks. I reviewed the code at bb98a14 but did not run the app. Testing these cases needs a connected accounting integration.

1. Likely regression: "queued for export" actions now show in chat and the LHN. ReportActionsUtils.ts:1272-1273 builds the list of visible action types from every value in CONST.REPORT.ACTIONS.TYPE. On main, QUEUEDFOREXPORT was missing from that list, so shouldReportActionBeVisible hid these actions. Adding the constant makes them visible. They then fall through to the generic message renderer and can become the LHN preview text. Whether a row appears depends on the server's message text, which I couldn't check. Fix: hide this type explicitly in shouldReportActionBeVisible. isQueuedForExport reads the raw actions, so hiding them won't affect it.

2. The More menu still offers Export when the header hides it. The secondary isExportAction has no cash-basis check and no queued check. On an approved but unpaid cash-basis report, Export disappears from the header, Search, and the to-do, but still appears under More.

3. Card-only reports lose Export when transactions aren't loaded. hasOnlyNonReimbursableTransactions returns false for an empty array, and callers pass [] rather than undefined. On a cash-basis workspace, an approved card-only report then shows no Export until its transactions load. This also applies to a $0 report. On main, Export showed for these reports.

4. A stale lastActionType could hide Export for good. isQueuedForExport returns true if report.lastActionType is QUEUEDFOREXPORT, even when cached actions are newer. Suppose a queued export ends without an export action or a failed integration message. Export would then stay hidden on the report page and in the to-do. Only the server clears that field, so please confirm it always replaces this value.

Checked with no regression found
  • hasExportError now reads only the latest integration message after the last approval reset. Its callers (Pay logic, didExportFail) behave as intended. No status badge reads it, because badges use report.hasExportError.
  • An unset accountingMethod is treated as accrual. The QBO, QBD, NetSuite, Xero, and Intacct settings pages display Cash when it is unset. That mismatch already existed before this PR, and situchan raised it above.
  • getActions in SearchUIUtils now builds the transaction list before the early PAID return. Report rows pass precomputed transactions, so the extra cost is small.

@dukenv0307

Copy link
Copy Markdown
Contributor Author

@MelvinBot

Case 1 is wrong since the backend sends QUEUEDFOREXPORT with an empty message
Case 2 is not a regression since we didn't change it
Case 3+4 are fixed.

Please review again

@MelvinBot

Copy link
Copy Markdown
Contributor

Re-review

All four points are settled, and I found no blocking issues in 8de29f4. Every CI check passes except Check independent approval.

  • Case 1: You're right. An empty message makes isDeletedAction return true, so shouldReportActionBeVisible hides the action. It can't show in chat or become the LHN preview.
  • Case 2: Agreed. The secondary isExportAction is the same as on main.
  • Case 3: Fixed. isCardOnlyReport falls back to the report totals when no transactions are loaded.
  • Case 4: Fixed. isQueuedForExport now reads only the cached actions.

Two optional follow-ups:

  1. Add a unit test for isCardOnlyReport with an empty transaction list. No test covers the totals fallback yet.
  2. Without the lastActionType fallback, the Export to-do depends on cached actions. If someone queues a manual export in another session, the to-do shows Export until that report's actions load. This only applies with auto-sync off, so I think the trade-off is fine.

@dukenv0307
dukenv0307 requested a review from situchan October 20, 2026 02:04
@dukenv0307

Copy link
Copy Markdown
Contributor Author

@situchan All yours!

Comment on lines +12 to +15
/**
* Which accounting integration is connected, whether it is syncing, and who exports.
* Extracted from PolicyUtils/index.ts to keep that file smaller.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This comment was wrongly moved

Comment thread src/libs/ReportPrimaryActionUtils.ts Outdated
/** Needed to skip archived reports, which the backend never returns as exportable */
reportNameValuePairs?: ReportNameValuePairs;

/** Needed for the cash-basis carve-out on card-only reports; Search snapshot rows aren't reliably in Onyx */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Avoid semicolon in inline comment

@melvin-bot
melvin-bot Bot requested a review from mountiny October 21, 2026 20:28
@situchan

Copy link
Copy Markdown
Contributor

Conflicts!

@MelvinBot

Copy link
Copy Markdown
Contributor

Regression check (round 3)

I found no new regressions in 8de29f4. The head hasn't changed since my last re-review, so this time I also checked how the PR interacts with main. Main has moved 1015 commits ahead.

Merging main: none of the 1015 commits touch the export logic. Only two import lists conflict, and both are easy to fix:

  • ReportPreviewActionUtils.ts: keep canAdminPayReport and getIntegrationAccountingMethod. Drop canMemberWrite and getReimbursementChoice, because main removed their only use in canPay. Leaving them in fails lint.
  • ReportPrimaryActionUtils.ts: keep canAdminPayReport and getIntegrationAccountingMethod, and drop canMemberWrite. Keep isGroupPolicy, which main still uses.

Two behaviors are worth confirming against the backend. Neither is a confirmed bug:

  1. A closed cash-basis report that is never paid loses Export. The cash gate at ReportPrimaryActionUtils.ts:355-357 and ReportPreviewActionUtils.ts:233-235 lets a closed report export only if it is card-only. Take a workspace with reimbursements off and a closed report with out-of-pocket expenses. That report never gets paid, so Export disappears from the header, the preview, Search, and the to-do. On main, Export shows. If the backend treats closed reports the same way, this is fine.
  2. Export stays hidden if a queued export never gets a follow-up action. isQueuedForExport checks only the newest action. Suppose an export job ends without posting an export or integration message. Export then stays hidden until another action lands. This is low risk if the backend always posts a result.
Checked with no regression found
  • hasExportError callers: the only callers that pass actions are isPrimaryPayAction, isExportAction, and getSecondaryReportActions, and each now behaves as intended. The preview passes no actions, so its behavior is unchanged. Every INTEGRATIONSMESSAGE is an export result, so a non-export message can't hide an earlier failure.
  • Exporter source: the to-do and the export suggestion now read the connection exporter instead of policy.exporter. This matches the PR's goal, and the two now agree.
  • Export suggestion: getValidConnectedIntegration covers every accounting connection. Unverified NetSuite and Certinia connections are excluded from both the to-do and the suggestion.
  • Certinia in getConnectionExporters: Certinia exporters now get the same exporter warnings and permissions as other integrations.
  • isCardOnlyReport: it compares totals only with === 0 and !== 0, so negative totals on expense reports don't matter. IOU and invoice reports are excluded earlier.
  • getActions reordering: this changes no behavior, and it adds very little cost.
  • Archived NVPs: every caller passes the expense report's own NVPs.

I didn't run the app. These cases need a connected accounting integration, which the test account doesn't have.


view run

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Failed to sample tokens
ℹ️ 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".

@mountiny

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Failed to sample tokens
ℹ️ 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".

@dukenv0307

Copy link
Copy Markdown
Contributor Author

@MelvinBot Why is the test failing?

@MelvinBot

Copy link
Copy Markdown
Contributor

The typecheck failure isn't caused by this PR. It comes from code already on main, and every open PR that ran typecheck after about 22:40 UTC on Oct 21 fails the same way.

All the errors are in two files this PR doesn't touch:

  • src/libs/getTransactionFromTransactionListItem.ts(66): 'attendees' does not exist in type 'Record<…>'
  • tests/ui/DynamicWorkspaceSettlementAccountPageTest.tsx(219, 228, 241): the connection-name union isn't assignable to keyof Connections

Your branch has no conflicts with main, so CI typechecks the merge with the latest main and picks up these errors. You don't need to change anything. Once main is fixed, merge main again or re-run the check.

Evidence
  • Failing run: typecheck job at e8b8af6.
  • An unrelated PR branch, claude-avatarTooltipCenteredLHN, fails typecheck with the same six errors.
  • Every typecheck run on a PR branch since 22:43 UTC on Oct 21 has failed. Before then, most runs passed.
  • The other failing check, Check independent approval, is a review gate, not a test.

view run

@mountiny mountiny left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(Vit's agent) I compared this PR with the backend rules in https://github.com/Expensify/Auth/pull/25129 and https://github.com/Expensify/Auth/pull/25628, one clause at a time. These all match Auth: the export failure check (only the latest integration message counts, and not one from before the last approval reset), the queued check, the archive check, and the cash basis rule for card only reports, including closed and empty reports. I found no blockers in the code.

Please fix these before merge:

  1. The QA steps fail on a new connection. A newly connected QBO, Xero or Intacct has no accountingMethod key. The settings page shows Cash for that state (DynamicQuickbooksOnlineAccountingMethodPage.tsx:37). getIntegrationAccountingMethod and Auth both read it as Accrual. A tester who sees Cash already selected does not change it, so step 5 shows the to-do. @situchan hit this. Please change step 2 to: select Accrual, then select Cash again, so the key is saved.
  2. The card only rule has no tests. See the inline comment on isCardOnlyReport.
  3. The file docblock in connections.ts still sits on the expensify-common import (from @situchan's thread). Move it back to line 1.
  4. The exporter list does not match Auth for Zoho Books and Business Central. See the inline comment on getConnectionExporters.

Follow-up, not for this PR: an unset accountingMethod has three defaults across the stack.

  • The App settings pages show Cash.
  • Integration-Server uses Cash when ACH reimbursement is on, and Accrual otherwise (QuickbooksOnlineReportExporterHelper.java:4427; the NetSuite, QBD, Xero and Intacct exporters do the same).
  • Auth search and this PR use Accrual.

This PR keeps the to-do and the search in step with each other, so it is not a regression. But the settings page, the exporter and the to-do can still disagree about which method a workspace uses. I think that answers @situchan's question about fixing it separately: yes, in its own issue.

Comment thread src/libs/ReportUtils.ts
* Whether a report is card-only (has non-reimbursable spend and nothing reimbursable). Prefers the per-transaction answer when
* expenses are loaded, and falls back to the stored report totals otherwise, matching the backend's "no reimbursable transaction" check.
*/
function isCardOnlyReport(report: OnyxEntry<Report>, transactionsParam?: Transaction[]): boolean {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(Vit's agent) The last two commits added this function and the card only branch in both isExportAction and canExport. That fixed the bug @situchan found, but no test covers it. Please add these cases:

  1. Cash basis, approved, every expense non reimbursable: Export shows.
  2. Cash basis, approved, one reimbursable and one non reimbursable expense: Export waits for payment.
  3. Cash basis, approved, no transactions passed, total equal to a non zero nonReimbursableTotal: the fallback to report totals returns true.
  4. Case 1 again through getReportPreviewAction, which reaches canExport.

Auth tests cases 1 and 2 in SearchFiltersTest2::testExportActionAutoSyncAndReportState, so these tests keep both sides in step.

policy?.connections?.rillet?.config?.export?.exporter,
policy?.connections?.dualEntry?.config?.export?.exporter,
policy?.connections?.campfire?.config?.export?.exporter,
policy?.connections?.financialforce?.config?.export?.exporter,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(Vit's agent) Adding financialforce matches Auth. Two connections still differ from Auth's FilterUtils::getConnectionExporterFields:

  • Zoho Books: Auth reads zohoBooks.config.export.exporter, and App types that field, but this list has no Zoho Books entry. Before this PR, the to-do and the sidebar suggestion checked policy.exporter. Now they check isPreferredExporter, so a Zoho Books exporter gets no Export to-do, while action:export exporter:me still returns their reports. One line here fixes it.
  • Business Central: this is the reverse. App counts the Business Central exporter, but Auth leaves businessCentral out of its exporter fields, getConnectionConfigQuery and INTEGRATIONS_SUPPORTING_AUTO_EXPORT. A Business Central exporter sees "Export N reports" on Home, and the search returns nothing. This needs an Auth change or a follow-up issue.

Both integrations are behind betas, so few users see this.

Comment thread src/CONST/index.ts
UNREPORTED_TRANSACTION: 'UNREPORTEDTRANSACTION',
UNDELETED_TRANSACTION: 'UNDELETEDTRANSACTION',
OUTDATED_BANK_ACCOUNT: 'OUTDATEDBANKACCOUNT', // OldDot Action
QUEUED_FOR_EXPORT: 'QUEUEDFOREXPORT',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(Vit's agent) Non blocking. This new type puts QUEUEDFOREXPORT into supportedActionTypes, so the type check in shouldReportActionBeVisible (ReportActionsUtils.ts:1340) lets it through. It stays out of chat only because its message is empty, which makes isDeletedAction return true. Auth lists this action in Report::HIDDEN_ACTIONS. If the backend ever gives it message text, it shows up in chat. An explicit hide in shouldReportActionBeVisible would make that safe.

This branch has not been deployed

No deployments
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.

5 participants