Skip to content

Remove vendor gate intacct - #100455

Merged
Beamanator merged 12 commits into
Expensify:mainfrom
KioCoan:removeVendorGateIntacct
Sep 17, 2026
Merged

Beamanator merged 12 commits into
Expensify:mainfrom
KioCoan:removeVendorGateIntacct

Conversation

@KioCoan

@KioCoan KioCoan commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Vendor matching R2 (Sage Intacct) has shipped, every Sage Intacct-connected workspace has been enrolled in the vendorMatching beta, and the Integration-Server exporter gate is already gone (https://github.com/Expensify/Integration-Server/pull/9282, on production since 2026-09-04). Intacct code paths should therefore stop consulting the beta. Xero (R3), Rillet (R4), and DualEntry are still pre-GA, so CONST.BETAS.VENDOR_MATCHING stays and keeps gating those three. This is the Intacct counterpart of the QBO cleanup in #98516.

Only two gates read the beta on an Intacct path, so only two change:

  • PolicyUtils.hasVendorFeature now short-circuits to true on isIntacctVendorMatchingActive alongside isQBOVendorMatchingActive, before the beta is consulted:

    if (isQBOVendorMatchingActive(policy) || isIntacctVendorMatchingActive(policy)) {
        return true;
    }
    return isVendorMatchingBetaEnabled && (isXeroVendorMatchingActive(policy) || isRilletVendorMatchingActive(policy) || isDualEntryVendorMatchingActive(policy));

    Every cross-integration vendor surface already routes through it and needed no edit: ViolationsUtils, MoneyRequestView, WorkspaceVendorsPage, getWorkspaceMenuItems (workspace menu and search router suggestions), MerchantRulePageBase, AddVendorPage, IOURequestStepVendor, and the product marketing CTA.

  • WorkspaceMoreFeaturesPage decides whether the Vendors row is visible from the active vendor source, and used to exempt only QBO from the beta. It now treats both QBO and Sage Intacct as GA. The active-source lookup itself is unchanged, so a lingering GA connection still cannot unlock the row for a beta-gated integration.

GA does not widen the export mode gate: an Intacct workspace exporting non-reimbursable expenses as Vendor Bill still has no vendor feature, with or without the beta.

Deliberately untouched: no page under src/pages/workspace/accounting/intacct/ reads the beta, so there is no Intacct analogue of the QBO accounting page change. The two Xero-only pages (DynamicXeroExportConfigurationPage, DynamicXeroNonReimbursableDefaultContactSelectPage) keep their beta check.

Known follow-up, out of scope here: ProductMarketingWindowManager still gates its fallback-workspace connections prefetch on the beta, so an off-beta QBO or Intacct fallback workspace routes the marketing CTA to More features instead of Vendors. That is a one-line change plus a test and will go in its own PR.

Deploy order: this PR goes first. The matching Web-Expensify PR (https://github.com/Expensify/Web-Expensify/pull/55939, auto-matcher and card-feed gates) must only be merged after this one is on production. Otherwise Concierge auto-match messages would show up on workspaces whose App still hides the Vendor row.

Fixed Issues

https://github.com/Expensify/Expensify/issues/677006

Tests

  1. Ran the suites that cover every surface behind the gate and verified they all pass:
    npx jest tests/unit/PolicyUtilsTest.ts tests/unit/ViolationUtilsTest.ts tests/unit/AddVendorPageTest.ts tests/unit/VendorMatchingMerchantRulesTest.ts tests/ui/MoneyRequestViewTest.tsx tests/ui/WorkspaceMoreFeaturesPageTest.tsx
    
    What they pin, all with the vendorMatching beta off:
    • hasVendorFeature is true for Intacct on Credit Card Charge, and still false for Intacct on Vendor Bill, for Intacct with no export destination, and for Xero.
    • The inactiveVendor violation is added for an Intacct vendor missing from the synced list, not added for a vendor that is in the list, not added while the vendor list is still hydrating, and removed when the export switches to Vendor Bill.
    • The Vendor row renders on a non-reimbursable Intacct expense and shows the vendor display name.
    • The More features Vendors row shows locked ON for Intacct on Credit Card Charge, locked OFF for Intacct on Vendor Bill, still shows for Intacct with a lingering Xero connection, and stays hidden for a Xero-only workspace.
    • The merchant rule "Set vendor to" row and the Add vendor page are available on Intacct.
  2. Ran npm run typecheck and ESLint on the touched files and verified no errors.
  • Verify that no errors appear in the JS console

Offline tests

No network-dependent behavior changes. The gate is resolved from policy.connections, which is already in Onyx, so the vendor UI shows or hides identically offline.

  1. On a Sage Intacct workspace set up as in the QA steps, open a non-reimbursable expense while online and verify the Vendor row is visible.
  2. Go offline, reopen the same expense, and verify the Vendor row is still visible.

QA Steps

Precondition: two workspaces on the Control plan whose owners are not in the vendorMatching beta. Workspace A is connected to Sage Intacct, workspace B is connected to Xero. Each needs at least one non-reimbursable (company card) expense.

  1. On workspace A, go to Workspace > Accounting > Export > Non-reimbursable expenses and set "Export as" to Credit card charge. Let the sync finish.
  2. Open Workspace > More features and verify the Vendors row is present, switched on, and locked.
  3. Open Workspace > Vendors and verify the page lists the vendors imported from Sage Intacct.
  4. Open a non-reimbursable expense on workspace A and verify a Vendor row is shown on the expense.
  5. Tap the Vendor row, pick a vendor, and verify the selection saves and the row shows that vendor's name.
  6. Open Workspace > Rules > Merchant, add or edit a rule, and verify the Set vendor to row is present and its picker lists the Sage Intacct vendors.
  7. Set a vendor on an expense, make that vendor inactive in Sage Intacct, run Sync now on the connection, and verify the expense shows the inactive vendor violation.
  8. Change workspace A's non-reimbursable export to Vendor bill. Verify the Vendors row in More features is still present but switched off, the Vendors page is no longer in the workspace menu, and the Vendor row no longer shows on non-reimbursable expenses.
  9. Regression check on workspace B (Xero, owner not in the beta): repeat steps 2 to 6 and verify none of the vendor UI appears.
  10. Add workspace B's owner to the vendorMatching beta, reload, and verify the vendor UI (labeled Supplier on Xero) appears.

Cover web plus one native platform. We can tag @heyjennahay to help with this.

  • 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 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 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

@KioCoan
KioCoan marked this pull request as ready for review September 17, 2026 04:06
@KioCoan
KioCoan requested review from a team as code owners September 17, 2026 04:06
@melvin-bot
melvin-bot Bot requested review from garrettmknight and removed request for a team September 17, 2026 04:06
@KioCoan KioCoan added the InternalQA This pull request required internal QA label Sep 17, 2026
@KioCoan
KioCoan requested a review from Beamanator September 17, 2026 04:32
@garrettmknight
garrettmknight removed their request for review September 17, 2026 13:25

@Beamanator Beamanator 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.

LGTM

@Beamanator

Beamanator commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible 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 checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • 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 verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • 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 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.
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this 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.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Android: HybridApp
Android: mWeb Chrome
iOS: HybridApp
iOS: mWeb Safari
MacOS: Chrome / Safari

@Beamanator
Beamanator merged commit 6dc68cf into Expensify:main Sep 17, 2026
37 of 41 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🚧 Beamanator has triggered a test Expensify/App build. You can view the workflow run here.

@Beamanator

Copy link
Copy Markdown
Contributor

thank you sir!!

@OSBotify

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@KioCoan
KioCoan deleted the removeVendorGateIntacct branch September 17, 2026 14:31
@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/Beamanator in version: 9.4.82-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 cancelled 🔪
🍎 iOS 🍎 cancelled 🔪

@MelvinBot

Copy link
Copy Markdown
Contributor

Yes, help site changes are required

Draft PR: Docs updates for E/A#100455 Publish Sage Intacct vendor matching article

The core problem: docs/articles/new-expensify/connections/sage-intacct/Manage-Vendor-Matching-for-Sage-Intacct.md already existed, but it was hidden from the live help site with noindex: true and sitemap: false while the feature was beta-gated. Now that this PR removed the vendorMatching gate from the Intacct paths, the article describes a GA feature that customers still can't find. The QBO article has no such flags after the equivalent cleanup in [No QA] Remove the QBO vendor matching beta gate, and the Xero article stays in docs/articles/Unlisted/ because Xero is still pre-GA — so Sage Intacct was the odd one out.

What the draft PR changes

Change Why
Removed noindex: true and sitemap: false The feature is GA, so the article should publish and be indexed. This is the substantive change.
Added a ## Where to find your imported Sage Intacct vendors section The Vendors row on More features and the Vendors page are exactly what your PR unhides, and the article never told admins where they appear. It also notes that switching to Vendor bills removes them again.
Credit Card ChargesCredit cards The Intacct Export company card expenses as picker renders nonReimbursableExpenses.values.creditCardCharge, which is Credit cards in src/languages/en.ts:5423. "Credit Card Charges" is the Sage Intacct record name, not our label. Fixed in the article, its keywords, and internalScope.
Replaced a broken image with a <!-- SCREENSHOT: --> placeholder The article pointed at assets/images/2_Awesome_Co_Control_Intacct_-_Accounting.png, which doesn't exist in docs/assets/images/. Publishing as-is would have shipped a broken image. A real screenshot still needs capturing.
Cross-linked the article from Configure-Sage-Intacct.md Mirrors the two links the QBO configuration article already carries, so admins reach vendor matching from the export settings they're already reading about. Also corrected that section's labels to Credit cards, Vendor bills, and Default vendor.
Label verification and what I deliberately left alone

Verified against the live UI: Accounting, More features, and the Sage Intacct connection row were read back from live NewDot web. The More features sections render as Integrate, Organize, Manage, Spend, Earn.

Verified from source: the Vendors row sits in the Organize section, not Integrate, per WorkspaceMoreFeaturesPage/index.tsx:505-592, so the article says Organize. The switch is intentionally locked (index.tsx:581), so the article says it can't be turned off there. Export company card expenses as, Credit cards, Vendor bills, Default vendor, Vendors, and Vendor all came from src/languages/en.ts.

I could not create a Sage Intacct-connected Workspace in the test environment, so the Intacct-specific strings were verified from the translation source and the rendering components rather than by driving a connected Workspace. Worth a second pair of eyes on a real Intacct Workspace.

Left alone on purpose:

  • Configure-Sage-Intacct.md has pre-existing heading and capitalization violations of docs/HELP_AUTHORING_GUIDELINES.md (# Step 1: Select Entity, ## Billable Expenses, **Expense Reports** / **Vendor Bills** in the out-of-pocket section). I only corrected the section I touched; restructuring that article belongs in its own PR.
  • No Xero, Rillet, or DualEntry doc changes, matching your note that those stay behind CONST.BETAS.VENDOR_MATCHING.
  • The ProductMarketingWindowManager follow-up you flagged has no user-facing doc impact, so nothing was written for it.

npm run spell-changed passes: 2 files checked, 0 issues.


@KioCoan, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR Ready for review

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/Beamanator in version: 9.4.86-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/Beamanator in version: 9.4.89-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/luacmartins in version: 9.4.89-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 failure ❌

Bundle Size Analysis (Sentry):

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

InternalQA This pull request required internal QA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants