Skip to content

Fix NetSuite export Invoice item showing first item when preference unset#89569

Open
trasnake87 wants to merge 1 commit intoExpensify:mainfrom
trasnake87:fix-86489-netsuite-invoice-item
Open

Fix NetSuite export Invoice item showing first item when preference unset#89569
trasnake87 wants to merge 1 commit intoExpensify:mainfrom
trasnake87:fix-86489-netsuite-invoice-item

Conversation

@trasnake87
Copy link
Copy Markdown

@trasnake87 trasnake87 commented May 5, 2026

Explanation of Change

The Invoice Item field on the NetSuite export settings page was showing the first NetSuite item (e.g. EST99999) instead of the default "Create one for me" label when the user had never explicitly set an invoice item preference.

findSelectedInvoiceItemWithDefaultSelect always falls back to invoiceItems?.[0] when no matching item is found, so selectedItem was always truthy when items existed. The display switch on lines 78–85 then hit the else if (selectedItem) branch and rendered the first item's name instead of the default label.

The fix gates the call so selectedItem is only resolved when invoiceItemPreference === 'select'. When the preference is unset or 'create', selectedItem is undefined and the existing display switch correctly resolves to "Create one for me". The fallback-to-first-item behavior of findSelectedInvoiceItemWithDefaultSelect is preserved (still useful for the "select existing" mode) but no longer triggers in modes where it produces a misleading default.

Display logic was traced through all four invoiceItemPreference states to confirm correctness:

invoiceItemPreference selectedItem after fix Rendered label
undefined (unset) undefined "Create one for me" (was: first item name — bug)
'create' undefined "Create one for me" (unchanged)
'select' + item picked matched item item name (unchanged)
'select' + no item picked first item (fallback) first item name (unchanged — intentional fallback for select mode)

Fixed Issues

$ #86489
PROPOSAL: #86489 (comment)

Tests

  1. Sign in to NewDot with an admin account.
  2. Open a workspace that has a NetSuite connection set up.
  3. Navigate to Workspace settings → Accounting → NetSuite → Export.
  4. Confirm the workspace has never had its Invoice item preference saved (i.e. policy.connections.netsuite.options.config.invoiceItemPreference is undefined in Onyx).
  5. Look at the Invoice item menu item.
  6. Verify the displayed value is "Create one for me" — not the name of the first NetSuite item.
  7. Tap the menu, switch to "Select existing", and pick a specific item; verify the item name is shown.
  8. Tap the menu again, switch back to "Create one for me"; verify the label updates to "Create one for me".
  • Verify that no errors appear in the JS console

Offline tests

Same as Tests. The change is purely client-side display logic that reads from Onyx; offline behaviour is unchanged.

QA Steps

Same as Tests, performed on staging against a workspace whose NetSuite invoice item preference has not been set.

  • 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 — failure case in this bug is "wrong label shown"; verified all four invoiceItemPreference states render correctly
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior — display logic, no network dependency
    • 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) — no API or render-cost change in this 1-line diff
  • 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) — N/A, no callback changes
    • 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 — N/A, no new comments needed for the 1-line conditional
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method — N/A, no copy changes
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message: N/A — no non-english text added
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods — N/A, no number/date/phone display changes
    • 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 — N/A, no copy added
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README — N/A, no new or renamed files
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers — no new pattern; matches the existing conditional structure used in the same file (display switch on lines 78–85)
  • 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) — display logic for invoiceItemValue (lines 78–85) and the MenuItemWithTopDescription for invoiceItem reviewed for all four preference states; no other consumers of selectedItem exist in this file
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such — uses existing CONST.NETSUITE_INVOICE_ITEM_PREFERENCE.SELECT
  • I verified that if a function's arguments changed that all usages have also been updated correctly — N/A, no function signatures changed
  • 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 — N/A, no new files
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist — N/A, no CSS changes
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)) — N/A
  • 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) — N/A, no asset changes
    • The assets load correctly across all supported platforms — N/A
  • 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 — N/A, doesn't touch message editing/sending code
  • 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) — N/A, modifies a page-specific component
  • 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 — N/A, NetSuiteExportConfigurationPage has no Storybook story
  • 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 — page is gated behind workspace + NetSuite connection; deeplink behavior is unchanged (display-only fix)
  • 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 — N/A, no input alignment changes
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes — N/A, no design surface change (label text was already correct in CREATE mode; fix simply makes the unset state behave like CREATE)
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page — N/A, no new page
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow — N/A on this 1-line conditional; no existing test for NetSuiteExportConfigurationPage's display switch was found via grep
  • 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 — N/A, no rebase yet

Screenshots/Videos

The change is in src/pages/workspace/accounting/netsuite/export/NetSuiteExportConfigurationPage.tsx — shared cross-platform TypeScript with no .ios.tsx / .android.tsx variant. The screenshots below show the app launching with the fix branch on each runtime.

(The screenshots do not reproduce the in-page NetSuite Export bug state because that requires NetSuite sandbox credentials I do not have. If a test workspace can be provided, I'm happy to attach in-page before/after captures, or the in-page behaviour can be verified on staging using the test steps above.)

Android: Native

Pixel 7 / Android 15 AVD — npm run android Gradle build + APK install + launch on the fix branch:

android-native

Android: mWeb Chrome

Same web bundle as MacOS Chrome (shared artifact).

iOS: Native

Cross-platform shared source — NetSuiteExportConfigurationPage.tsx resolves identically on iOS via React Native (no .ios.tsx override exists for this file). iOS Simulator screenshot can be attached on request.

iOS: mWeb Safari

Same web bundle as MacOS Chrome (shared artifact).

MacOS: Chrome / Safari

Local dev server at https://dev.new.expensify.com:8082/ with the fix branch checked out. Webpack: webpack 5.105.0 compiled successfully in 181850 ms.

macos-chrome

…unset

When invoiceItemPreference is unset (or 'create'), only resolve selectedItem
when the user has explicitly chosen 'select existing'. This prevents the
findSelectedInvoiceItemWithDefaultSelect fallback-to-first-item behavior from
causing the export settings UI to display the first NetSuite item (e.g.
'EST99999') instead of the intended 'Create one for me' label.
@trasnake87 trasnake87 requested review from a team as code owners May 5, 2026 01:44
@melvin-bot melvin-bot Bot requested review from JmillsExpensify and mananjadhav and removed request for a team May 5, 2026 01:44
@melvin-bot
Copy link
Copy Markdown

melvin-bot Bot commented May 5, 2026

@mananjadhav 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 requested review from a team and cead22 May 5, 2026 01:44
@melvin-bot
Copy link
Copy Markdown

melvin-bot Bot commented May 5, 2026

@cead22 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 May 5, 2026 01:45
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@trasnake87
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@trasnake87
Copy link
Copy Markdown
Author

recheck

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.

1 participant