From 55ad1f9037aa14888b344f0298f81ecbdbca880a Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 09:13:22 -0300 Subject: [PATCH 01/11] Update PolicyUtils comments regarding beta --- src/libs/PolicyUtils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 53df7ab78939..a0bce463f4db 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -2478,19 +2478,19 @@ function isXeroActiveMatchingSource(policy: OnyxEntry): boolean { * the field. * * The `vendorMatching` beta only gates the integrations that haven't reached GA yet, so - * `isVendorMatchingBetaEnabled` is consulted on the Intacct and Xero branches but not on QBO: + * `isVendorMatchingBetaEnabled` is consulted on the Xero branch but not on QBO or Sage Intacct: * - QBO (R1) with non-reimbursable export = Credit Card or Debit Card. GA, so no beta required - * - Sage Intacct (R2) with non-reimbursable export = Credit Card Charge. Beta required + * - Sage Intacct (R2) with non-reimbursable export = Credit Card Charge. GA, so no beta required * - Xero (R3) has no export destination enum, so a present connection is enough. Beta required */ function hasVendorFeature(policy: OnyxEntry, isVendorMatchingBetaEnabled: boolean): boolean { if (!policy) { return false; } - if (isQBOVendorMatchingActive(policy)) { + if (isQBOVendorMatchingActive(policy) || isIntacctVendorMatchingActive(policy)) { return true; } - return isVendorMatchingBetaEnabled && (isIntacctVendorMatchingActive(policy) || isXeroVendorMatchingActive(policy)); + return isVendorMatchingBetaEnabled && isXeroVendorMatchingActive(policy); } /** From fea425e6b23b321b8a35c05a7da1046137898e4d Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 09:15:39 -0300 Subject: [PATCH 02/11] Update Violations doc comments --- src/libs/Violations/ViolationsUtils.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/Violations/ViolationsUtils.ts b/src/libs/Violations/ViolationsUtils.ts index 08a392df8f45..cd131b128032 100644 --- a/src/libs/Violations/ViolationsUtils.ts +++ b/src/libs/Violations/ViolationsUtils.ts @@ -573,8 +573,9 @@ const ViolationsUtils = { : getTagViolationsForMultiLevelTags(updatedTransaction, newTransactionViolations, policyTagList, hasDependentTags); } - // Inactive vendor violation, gated behind the `vendorMatching` beta. The transaction's - // vendor is never cleared here — admins need to see what was set so they can re-pick. + // Inactive vendor violation, gated on `hasVendorFeature`, which only consults the + // `vendorMatching` beta for integrations that haven't reached GA. The transaction's + // vendor is never cleared here because admins need to see what was set so they can re-pick. if (allBetas !== undefined) { const isVendorMatchingBetaEnabled = Permissions.isBetaEnabled(CONST.BETAS.VENDOR_MATCHING, allBetas); const hasInactiveVendorViolation = newTransactionViolations.some((violation) => violation.name === CONST.VIOLATIONS.INACTIVE_VENDOR); From b538091e1c322441ddb2f1034d0f2508986cca0d Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 09:28:10 -0300 Subject: [PATCH 03/11] Validate beta gate in index --- .../workspace/WorkspaceMoreFeaturesPage/index.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx index f6cdb604ab86..eadaba31bb8b 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx @@ -167,11 +167,13 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro // `hasVendorFeature` stays as the narrower `isActive` predicate (is the export config scoping // vendors right now), so it can't double as the visibility gate. // - // Beta gating mirrors `hasVendorFeature`: QBO (R1) is GA, so a connected QBO workspace always - // sees the row regardless of the `vendorMatching` beta. Sage Intacct (R2) and Xero (R3) haven't - // reached GA, so they only show the row while the beta is enabled. - const vendorMatchingConnection = getConnectedIntegration(policy, [CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]); - const shouldShowVendorsFeature = vendorMatchingConnection === CONST.POLICY.CONNECTIONS.NAME.QBO || (isVendorMatchingEnabled && !!vendorMatchingConnection); + // Beta gating mirrors `hasVendorFeature`: QBO (R1) and Sage Intacct (R2) are GA, so a workspace + // connected to either always sees the row regardless of the `vendorMatching` beta. Xero (R3) + // hasn't reached GA, so it only shows the row while the beta is enabled. The two groups are + // checked separately so a GA connection wins even when a beta-gated one is also connected. + const hasGenerallyAvailableVendorConnection = !!getConnectedIntegration(policy, [CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]); + const hasBetaGatedVendorConnection = !!getConnectedIntegration(policy, [CONST.POLICY.CONNECTIONS.NAME.XERO]); + const shouldShowVendorsFeature = hasGenerallyAvailableVendorConnection || (isVendorMatchingEnabled && hasBetaGatedVendorConnection); const warnAccountingManagesOrganizeFeature = async () => { if (!hasAccountingConnection || !policyID) { From 8730d39a2b8e27a56e772fdb0414a84a988e900d Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 09:42:19 -0300 Subject: [PATCH 04/11] Add money request test case --- tests/ui/MoneyRequestViewTest.tsx | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/ui/MoneyRequestViewTest.tsx b/tests/ui/MoneyRequestViewTest.tsx index 68c75c9ec0b0..7544093be29c 100644 --- a/tests/ui/MoneyRequestViewTest.tsx +++ b/tests/ui/MoneyRequestViewTest.tsx @@ -626,6 +626,38 @@ describe('MoneyRequestView edit fields', () => { }); }); + it('shows the vendor row on Sage Intacct without the vendorMatching beta because Intacct (R2) is generally available', async () => { + const threadReport = { + ...LHNTestUtils.getFakeReport(), + parentReportID: expenseReportID, + parentReportActionID, + }; + + await setupTestData(); + await act(async () => { + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, { + reimbursable: false, + comment: {vendor: {externalID: 'iv-1', wasManuallySet: false}}, + }); + }); + await waitForBatchedUpdatesWithAct(); + + renderMoneyRequestView(threadReport, { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: { + config: {export: {nonReimbursable: CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE}}, + data: {vendors: [{id: 'iv-1', name: 'V001', value: 'Acme Intacct'}]}, + }, + }, + }); + await waitForBatchedUpdatesWithAct(); + + // Intacct keeps the "Vendor" label and shows the vendor's display name, which Intacct stores in `value`. + await waitFor(() => { + expect(screen.getByTestId('menu-item-title-common.vendor')).toHaveTextContent('Acme Intacct'); + }); + }); + it('hides the vendor row on Xero without the vendorMatching beta because Xero (R3) is still pre-GA', async () => { const threadReport = { ...LHNTestUtils.getFakeReport(), From 59a11441692f8991bad51327fa56af0dcc814aa4 Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 09:51:34 -0300 Subject: [PATCH 05/11] Mock Sage for add vendor test --- tests/unit/AddVendorPageTest.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/unit/AddVendorPageTest.ts b/tests/unit/AddVendorPageTest.ts index 8628a8ae1940..9c30112ed0a4 100644 --- a/tests/unit/AddVendorPageTest.ts +++ b/tests/unit/AddVendorPageTest.ts @@ -24,6 +24,18 @@ const buildQBOPolicy = (vendors: Array<{id: string; name: string; currency: stri }), }); +/** Sage Intacct policy whose Credit Card Charge export scopes vendor matching to Intacct. */ +const buildIntacctPolicy = (vendors: Array<{id: string; name: string; value: string}>): Policy => + createMock({ + ...createRandomPolicy(0), + connections: createMock({ + [CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: { + config: {export: {nonReimbursable: CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE}}, + data: {vendors}, + }, + }), + }); + /** Xero policy whose supplier list scopes vendor matching to Xero (label flips vendor -> supplier). */ const buildXeroPolicy = (contacts: Record): Policy => createMock({ @@ -124,12 +136,17 @@ describe('AddVendorPage', () => { */ describe('vendor rule row derivation (MerchantRulePageBase)', () => { const qboPolicy = buildQBOPolicy([{id: 'v-1', name: 'Acme Co', currency: 'USD'}]); + const intacctPolicy = buildIntacctPolicy([{id: 'iv-1', name: 'V001', value: 'Acme Intacct'}]); const xeroPolicy = buildXeroPolicy({xc1: {id: 'xc1', name: 'Acme Xero', email: 'acme@example.com'}}); it('shows the row on QBO with the beta off because QBO vendor matching is generally available', () => { expect(hasVendorFeature(qboPolicy, false)).toBe(true); }); + it('shows the row on Sage Intacct with the beta off because Intacct vendor matching is generally available', () => { + expect(hasVendorFeature(intacctPolicy, false)).toBe(true); + }); + it('hides the row on Xero when the beta is off because Xero vendor matching is not generally available yet', () => { expect(hasVendorFeature(xeroPolicy, false)).toBe(false); }); From c0b67ee89daae5a8442df6938e9289973ae8facd Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 10:16:03 -0300 Subject: [PATCH 06/11] Update workspace more features test --- tests/ui/WorkspaceMoreFeaturesPageTest.tsx | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/ui/WorkspaceMoreFeaturesPageTest.tsx b/tests/ui/WorkspaceMoreFeaturesPageTest.tsx index fab7084036f2..cda32367c796 100644 --- a/tests/ui/WorkspaceMoreFeaturesPageTest.tsx +++ b/tests/ui/WorkspaceMoreFeaturesPageTest.tsx @@ -467,7 +467,36 @@ describe('WorkspaceMoreFeaturesPage', () => { await expect(findLockedSwitch('workspace.moreFeatures.vendors.subtitle')).resolves.toBeOnTheScreen(); }); - // Sage Intacct (R2) and Xero (R3) are still beta-gated, so they stay hidden when the beta is off. + // Sage Intacct R2 is GA, so a connected Intacct workspace shows the row regardless of the vendorMatching beta. + it('shows the Vendors row locked ON for Sage Intacct scoping vendors even with the beta disabled (Intacct is GA)', async () => { + await renderWithVendorMatching( + {[CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: {config: {export: {nonReimbursable: CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE}}}}, + false, + ); + await expect(findLockedSwitch('workspace.moreFeatures.vendors.subtitle')).resolves.toBeOnTheScreen(); + }); + + it('shows the Vendors row locked OFF for Sage Intacct not scoping vendors even with the beta disabled (discovery state, Intacct is GA)', async () => { + await renderWithVendorMatching( + {[CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: {config: {export: {nonReimbursable: CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL}}}}, + false, + ); + await expect(findLockedSwitch('workspace.moreFeatures.vendors.subtitle')).resolves.toBeOnTheScreen(); + }); + + // A GA connection wins the visibility decision even when a beta-gated one is also connected. + it('shows the Vendors row for a Sage Intacct workspace with a lingering Xero connection when the beta is disabled', async () => { + await renderWithVendorMatching( + { + [CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: {config: {export: {nonReimbursable: CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE}}}, + [CONST.POLICY.CONNECTIONS.NAME.XERO]: {config: {isConfigured: true}}, + }, + false, + ); + await expect(findLockedSwitch('workspace.moreFeatures.vendors.subtitle')).resolves.toBeOnTheScreen(); + }); + + // Xero (R3) is still beta-gated, so it stays hidden when the beta is off. it('hides the Vendors row for a beta-gated integration (Xero) when the beta is disabled', async () => { await renderWithVendorMatching({[CONST.POLICY.CONNECTIONS.NAME.XERO]: {config: {}}}, false); expect(vendorsSwitchQuery()).toBeNull(); From 0429ccf0882648ee2eb697714e8aad09c350789f Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 10:33:08 -0300 Subject: [PATCH 07/11] Update Violation utils test --- tests/unit/ViolationUtilsTest.ts | 88 ++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/tests/unit/ViolationUtilsTest.ts b/tests/unit/ViolationUtilsTest.ts index 59e3f7111ea3..1a13f22f2e8a 100644 --- a/tests/unit/ViolationUtilsTest.ts +++ b/tests/unit/ViolationUtilsTest.ts @@ -3005,6 +3005,94 @@ describe('getViolationsOnyxData', () => { expect(result.value).toContainEqual(inactiveVendorViolation); }); + describe('Sage Intacct (R2)', () => { + // Pass a `vendors` array to control the synced list, or `null` to simulate the list still + // hydrating. Intacct vendors carry the display name in `value`. + const policyWithIntacctVendorFeature = ( + nonReimbursable: string = CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE, + vendors: Array<{id: string; name: string; value: string}> | null = [{id: 'iv-active', name: 'V001', value: 'Acme Intacct'}], + ) => + createMock({ + requiresTag: false, + requiresCategory: false, + connections: { + [CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: { + config: {export: {nonReimbursable}}, + data: vendors ? {vendors} : {}, + }, + }, + }); + + it('adds the violation when the vendorMatching beta is disabled but Intacct is configured, because Intacct (R2) is generally available', () => { + isBetaEnabledSpy.mockImplementation(() => false); + policy = policyWithIntacctVendorFeature(); + transaction.comment = {...transaction.comment, vendor: {externalID: 'iv-missing', wasManuallySet: true}}; + const result = ViolationsUtils.getViolationsOnyxData({ + ownerLogin: undefined, + updatedTransaction: transaction, + transactionViolations, + policy, + policyTagList: policyTags, + policyCategories, + hasDependentTags: false, + isInvoiceTransaction: false, + }); + // Intacct is not a supplier source, so the plain vendor violation (no isSupplierViolation flag) is expected. + expect(result.value).toEqual(expect.arrayContaining([inactiveVendorViolation])); + }); + + it('does not add the violation when the Intacct vendor is in the synced list', () => { + isBetaEnabledSpy.mockImplementation(() => false); + policy = policyWithIntacctVendorFeature(); + transaction.comment = {...transaction.comment, vendor: {externalID: 'iv-active', wasManuallySet: true}}; + const result = ViolationsUtils.getViolationsOnyxData({ + ownerLogin: undefined, + updatedTransaction: transaction, + transactionViolations, + policy, + policyTagList: policyTags, + policyCategories, + hasDependentTags: false, + isInvoiceTransaction: false, + }); + expect(result.value).not.toContainEqual(inactiveVendorViolation); + }); + + it('does not add the violation while the Intacct vendor list is still hydrating (vendors undefined)', () => { + isBetaEnabledSpy.mockImplementation(() => false); + policy = policyWithIntacctVendorFeature(CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE, null); + transaction.comment = {...transaction.comment, vendor: {externalID: 'iv-anything', wasManuallySet: true}}; + const result = ViolationsUtils.getViolationsOnyxData({ + ownerLogin: undefined, + updatedTransaction: transaction, + transactionViolations, + policy, + policyTagList: policyTags, + policyCategories, + hasDependentTags: false, + isInvoiceTransaction: false, + }); + expect(result.value).not.toContainEqual(inactiveVendorViolation); + }); + + it('removes an existing violation when the Intacct export switches to Vendor Bill with the beta disabled', () => { + isBetaEnabledSpy.mockImplementation(() => false); + policy = policyWithIntacctVendorFeature(CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL); + transaction.comment = {...transaction.comment, vendor: {externalID: 'iv-missing', wasManuallySet: true}}; + const result = ViolationsUtils.getViolationsOnyxData({ + ownerLogin: undefined, + updatedTransaction: transaction, + transactionViolations: [inactiveVendorViolation], + policy, + policyTagList: policyTags, + policyCategories, + hasDependentTags: false, + isInvoiceTransaction: false, + }); + expect(result.value).not.toContainEqual(inactiveVendorViolation); + }); + }); + describe('Xero (R4)', () => { // Placeholder for "Xero connected, contacts not yet synced". Explicit symbol avoids the // default-parameter trap where `undefined` would fall back to the populated default. From 0ccfbca2c43cd0f5a22d863169539f0e9096f9b6 Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 10:41:14 -0300 Subject: [PATCH 08/11] Include assertions to PolicyUtilsTest --- tests/unit/PolicyUtilsTest.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/unit/PolicyUtilsTest.ts b/tests/unit/PolicyUtilsTest.ts index 57baa12d9ed7..8121af85d0bd 100644 --- a/tests/unit/PolicyUtilsTest.ts +++ b/tests/unit/PolicyUtilsTest.ts @@ -3799,8 +3799,16 @@ describe('PolicyUtils', () => { expect(hasVendorFeature(buildQBOPolicy(CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.VENDOR_BILL), false)).toBe(false); }); - it('returns false when beta is disabled and Intacct CC Charge export is configured because Intacct (R2) is still pre-GA', () => { - expect(hasVendorFeature(buildIntacctPolicy(CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE), false)).toBe(false); + it('returns true when beta is disabled and Intacct non-reimbursable export is Credit Card Charge because Intacct (R2) is generally available', () => { + expect(hasVendorFeature(buildIntacctPolicy(CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE), false)).toBe(true); + }); + + it('returns false when beta is disabled and Intacct non-reimbursable export is Vendor Bill because GA did not widen the export mode gate', () => { + expect(hasVendorFeature(buildIntacctPolicy(CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL), false)).toBe(false); + }); + + it('returns false when beta is disabled and the Intacct non-reimbursable export destination is not set', () => { + expect(hasVendorFeature(buildIntacctPolicy(undefined), false)).toBe(false); }); it('returns false when beta is disabled and Xero is connected because Xero (R3) is still pre-GA', () => { From 4c0d3eb87f05a8147ea26ba1392ef83c958b7593 Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 10:56:39 -0300 Subject: [PATCH 09/11] Add tests for vendor matching --- tests/unit/VendorMatchingMerchantRulesTest.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/unit/VendorMatchingMerchantRulesTest.ts b/tests/unit/VendorMatchingMerchantRulesTest.ts index 1feaff205adf..e8746ebf9157 100644 --- a/tests/unit/VendorMatchingMerchantRulesTest.ts +++ b/tests/unit/VendorMatchingMerchantRulesTest.ts @@ -64,6 +64,18 @@ const buildQBOWithVendorBillExportPolicy = (vendors: Array<{id: string; name: st }); /** Xero policy whose supplier list scopes vendor matching to Xero (label flips vendor -> supplier). */ +/** Sage Intacct policy whose Credit Card Charge export scopes vendor matching to Intacct. */ +const buildIntacctPolicy = (vendors: Array<{id: string; name: string; value: string}>): Policy => + createMock({ + ...createRandomPolicy(0), + connections: createMock({ + [CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: { + config: {export: {nonReimbursable: CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE}}, + data: {vendors}, + }, + }), + }); + const buildXeroPolicy = (contacts: Record | undefined): Policy => createMock({ ...createRandomPolicy(0), @@ -261,6 +273,10 @@ describe('Vendor matching on merchant rules', () => { expect(hasVendorFeature(buildQBOPolicy([{id: 'v-1', name: 'Acme Co', currency: 'USD'}]), false)).toBe(true); }); + it('is visible on Sage Intacct when the beta is off because Intacct (R2) is generally available', () => { + expect(hasVendorFeature(buildIntacctPolicy([{id: 'iv-1', name: 'V001', value: 'Acme Intacct'}]), false)).toBe(true); + }); + it('is hidden on Xero when the beta is off because Xero (R3) is still pre-GA', () => { expect(hasVendorFeature(buildXeroPolicy({xc1: {id: 'xc1', name: 'Acme Xero', email: 'acme@example.com'}}), false)).toBe(false); }); From e668a8014b4c498d2e64c3885811b7533a52b8f2 Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 11:03:37 -0300 Subject: [PATCH 10/11] Keep the Xero builder doc comment on buildXeroPolicy --- tests/unit/VendorMatchingMerchantRulesTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/VendorMatchingMerchantRulesTest.ts b/tests/unit/VendorMatchingMerchantRulesTest.ts index e8746ebf9157..1a90e021078b 100644 --- a/tests/unit/VendorMatchingMerchantRulesTest.ts +++ b/tests/unit/VendorMatchingMerchantRulesTest.ts @@ -63,7 +63,6 @@ const buildQBOWithVendorBillExportPolicy = (vendors: Array<{id: string; name: st }), }); -/** Xero policy whose supplier list scopes vendor matching to Xero (label flips vendor -> supplier). */ /** Sage Intacct policy whose Credit Card Charge export scopes vendor matching to Intacct. */ const buildIntacctPolicy = (vendors: Array<{id: string; name: string; value: string}>): Policy => createMock({ @@ -76,6 +75,7 @@ const buildIntacctPolicy = (vendors: Array<{id: string; name: string; value: str }), }); +/** Xero policy whose supplier list scopes vendor matching to Xero (label flips vendor -> supplier). */ const buildXeroPolicy = (contacts: Record | undefined): Policy => createMock({ ...createRandomPolicy(0), From c291272885396d979a1d57fb046d8efe75b27890 Mon Sep 17 00:00:00 2001 From: Caio Coan Date: Sun, 6 Sep 2026 16:09:31 -0300 Subject: [PATCH 11/11] Type the Intacct export builder parameter in ViolationUtilsTest --- tests/unit/ViolationUtilsTest.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit/ViolationUtilsTest.ts b/tests/unit/ViolationUtilsTest.ts index 1a13f22f2e8a..5feb1a6f156d 100644 --- a/tests/unit/ViolationUtilsTest.ts +++ b/tests/unit/ViolationUtilsTest.ts @@ -8,6 +8,7 @@ import CONST from '@src/CONST'; import IntlStore from '@src/languages/IntlStore'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, PolicyCategories, PolicyTagLists, Report, Transaction, TransactionViolation} from '@src/types/onyx'; +import type {SageIntacctExportConfig} from '@src/types/onyx/Policy'; import type {TransactionCollectionDataSet} from '@src/types/onyx/Transaction'; import Onyx from 'react-native-onyx'; @@ -3009,7 +3010,7 @@ describe('getViolationsOnyxData', () => { // Pass a `vendors` array to control the synced list, or `null` to simulate the list still // hydrating. Intacct vendors carry the display name in `value`. const policyWithIntacctVendorFeature = ( - nonReimbursable: string = CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE, + nonReimbursable: SageIntacctExportConfig['nonReimbursable'] = CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE, vendors: Array<{id: string; name: string; value: string}> | null = [{id: 'iv-active', name: 'V001', value: 'Acme Intacct'}], ) => createMock({