Skip to content

[Payment due @FitseTLT] Fix approval limit CSV import conversion - #101422

Merged
Gonals merged 10 commits into
Expensify:mainfrom
rushatgabhane:682002-approval-limit-csv
Oct 8, 2026
Merged

Gonals merged 10 commits into
Expensify:mainfrom
rushatgabhane:682002-approval-limit-csv

Conversation

@rushatgabhane

@rushatgabhane rushatgabhane commented Sep 17, 2026 •

Copy link
Copy Markdown
Member

Explanation of Change

Updated member CSV imports so approval limits are treated as the desired amount in the workspace currency.
For example, an approval limit of 500 in a USD workspace is sent as 50000 cents and displayed as $500 instead of $5.

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/682002
PROPOSAL:

Tests

  1. Created a CSV with Email, Approval limit, and Over limit forward to fields.
  2. Set Approval limit in the CSV to the desired approval limit amount, e.g. 500.
  3. Created a workspace and enabled approvals.
  4. Imported the CSV and mapped all fields.
  5. Opened Workflows > Approvals.
  6. Verified that the workflow showed the desired approval limit amount, e.g. $500, instead of $5.
  • Verify that no errors appear in the JS console

Offline tests

No offline behavior was changed. Offline testing was not performed.

QA Steps

  1. Create a CSV with Email, Approval limit, and Over limit forward to fields.
  2. Set Approval limit in the CSV to the desired approval limit amount, e.g. 500.
  3. Create a workspace and enable approvals.
  4. Import the CSV, keep the user as a member, and map all fields.
  5. Go to Workflows > Approvals and verify it shows the desired approval limit amount, e.g. $500, not $5.
  6. In the Network tab, verify ImportMembersSpreadsheet sends the approval limit converted to the backend minor-unit value, e.g. approvalLimit: 50000 for a $500 USD workspace.
  • 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.
  • If the PR adds or modifies the UI:
    • I asked an AI agent to review the changes for accessibility issues and addressed its findings.
    • I tested with a screen reader (VoiceOver on macOS) and verified all new/changed elements are reachable with a logical focus order.
    • I verified all new/changed elements have meaningful accessible names and roles.
    • I verified state changes are announced (e.g. checked/unchecked, expanded/collapsed, selected).
  • 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 csv after change
csv.value.test.mp4

@melvin-bot

melvin-bot Bot commented Sep 17, 2026

Copy link
Copy Markdown

Hey, I noticed you changed src/languages/en.ts in a PR from a fork. For security reasons, translations are not generated automatically for PRs from forks.

If you want to automatically generate translations for other locales, an Expensify employee will have to:

  1. Look at the code and make sure there are no malicious changes.
  2. Run the Generate static translations GitHub workflow. If you have write access and the K2 extension, you can simply click: [this button]

Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running:

npx bun ./scripts/generateTranslations.ts --help

Typically, you'd want to translate only what you changed by running npx bun ./scripts/generateTranslations.ts --compare-ref main

@rushatgabhane
rushatgabhane force-pushed the 682002-approval-limit-csv branch from bc2ef2f to bcbfdc7 Compare September 17, 2026 13:28
@codecov

codecov Bot commented Sep 17, 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/libs/importSpreadsheetUtils.ts 61.60% <100.00%> (+0.65%) ⬆️
...rc/pages/workspace/members/ImportedMembersPage.tsx 80.27% <33.33%> (-6.76%) ⬇️
... and 12 files with indirect coverage changes

@rushatgabhane
rushatgabhane force-pushed the 682002-approval-limit-csv branch from bcbfdc7 to 3cde44e Compare September 17, 2026 13:49
@rushatgabhane

Copy link
Copy Markdown
Member Author

@MelvinBot The current CURRENCY_SYMBOLS regex only supports $, €, £, and ¥, but Expensify supports more currencies. What is the best existing repository or external-library approach to parse and clean currency symbols for every supported currency?
Please recommend the exact helper or implementation we should use in ImportedMembersPage.tsx, while preserving currency-specific decimals, blank values, validation, and storing cents as a string.

@MelvinBot

Copy link
Copy Markdown
Contributor

Don't use a symbol whitelist and don't add a library. The authoritative list of every currency Expensify supports is already on the client: Onyx CURRENCY_LIST carries a symbol per currency (159 distinct symbols), exposed as getCurrencySymbol from useCurrencyListActions() — the same hook this file already uses for getCurrencyDecimals. Strip the workspace currency's symbol/code, with \p{Sc} as a catch-all for any other Unicode currency sign.

Separately: src/pages/workspace/members/ImportedMembersPage.tsx:220 multiplies by 10 ** decimals, which is wrong for the 33 zero-decimal currencies. See below.

Recommended implementation

Delete CONST.REGEX.CURRENCY_SYMBOLS and add this to src/libs/importSpreadsheetUtils.ts (the shared home every Imported*Page already imports):

import StringUtils from './StringUtils';
import {stripCommaFromAmount, stripSpacesFromAmount} from './MoneyRequestUtils';

/**
 * Normalize an amount cell from an imported spreadsheet. Removes the workspace currency's symbol or ISO
 * code (prefix/suffix only, where currency markers actually appear) and any Unicode currency sign, plus
 * grouping separators and whitespace. Everything else is left intact so validateAmount can reject it.
 */
function normalizeImportedAmount(value: string, currencySymbol?: string, currencyCode?: string): string {
    const tokens = [currencySymbol, currencyCode].filter(Boolean).map((token) => StringUtils.escapeRegExp(token as string));
    const withoutCurrencyCode = tokens.length > 0 ? value.trim().replace(new RegExp(`^(?:${tokens.join('|')})\\s*|\\s*(?:${tokens.join('|')})$`, 'i'), '') : value;
    return stripCommaFromAmount(stripSpacesFromAmount(withoutCurrencyCode.replaceAll(/\p{Sc}/gu, '')));
}

Then in both call sites, replace stripCommaFromAmount(stripSpacesFromAmount(...).replaceAll(CONST.REGEX.CURRENCY_SYMBOLS, '')) with:

const {getCurrencySymbol, getCurrencyDecimals} = useCurrencyListActions();
const currency = policy?.outputCurrency;
const normalized = normalizeImportedAmount(String(value), getCurrencySymbol(currency ?? ''), currency);

validateAmount(normalized, getCurrencyDecimals(currency)) stays exactly as-is — it already returns true for '', so blank values keep working, and it still enforces the currency's decimal count.

Why this over the alternatives
Approach Verdict
Onyx CURRENCY_LIST symbol + \p{Sc} (recommended) Covers all currencies. The symbol list is backend-owned data the app already loads, so it never goes stale. Anchoring the token replace to prefix/suffix avoids eating letters mid-value for single-letter symbols (D = GMD, G = HTG, B = PAB).
[^\d.-] — the existing repo precedent in src/libs/actions/CompanyCards.ts:89 and src/libs/actions/ImportTransactions.ts:167 Covers every currency but guts your validation — "12abc" silently becomes 12 and passes. Those importers have no validation gate; yours does, so don't copy it.
/\p{Sc}/gu alone (one-char change from the PR) Better than [$€£¥], but misses every alphabetic symbol: CHF, kr, Kč, zł, Ft, Dhs, RM, Bs. Most of the 159 symbols contain letters.
getLocalizedCurrencySymbol (src/libs/CurrencyUtils.ts:90) Returns one locale-specific rendering of one currency (US$ vs $). Built for display, not parsing.
External library (currency-symbol-map etc.) Nothing like it is in package.json, and expensify-common has no symbol list or amount parser — only Num formatting helpers. Adding one would duplicate CURRENCY_LIST with a less authoritative copy.

Also fix: cents conversion is 100× off for zero-decimal currencies

Unrelated to the symbol question, but it's in the same lines. The backend stores 1/100 units for every currency, regardless of the currency's decimal count — see the doc comment on convertToBackendAmount, and note that convertToFrontendAmountAsString always divides by 100 while using decimals only for display precision.

The manual UI path agrees: WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx:171 writes convertToBackendAmount(...) and :66 reads it back with convertToFrontendAmountAsString.

With 10 ** getCurrencyDecimals(currency), a JPY workspace importing 5000 stores 5000, which reads back as (5000 / 100).toFixed(0) = ¥50. That hits all 33 zero-decimal currencies in the list (JPY, KRW, VND, CLP, ISK, HUF-adjacent, XOF, XAF, …).

approvalLimit = String(convertToBackendAmount(Number.parseFloat(normalizedApprovalLimit)));

Keep getCurrencyDecimals where it belongs — in validateAmount, deciding how many decimals the user may type. The value stays a string, so the wire shape at src/libs/actions/Policy/Member.ts:1032 is unchanged.

Test to add

There is currently no test covering the approval-limit CSV column. tests/unit/ImportTransactions.test.ts:387-406 ('should handle amounts with currency symbols and commas') is the precedent to mirror — add cases for a non-Latin symbol (₹500), an alphabetic one (CHF 1,200.50 in a CHF workspace), a zero-decimal currency (¥5000 → 500000), a blank cell, and a rejected value (12abc).


Next Steps: Reply with @MelvinBot <your feedback> to refine this.


view run

@rushatgabhane

Copy link
Copy Markdown
Member Author

@MelvinBot can you resolve conflicts

Resolved conflicts in src/libs/importSpreadsheetUtils.ts: main added
findColumnName/getCompanyCardColumnMappings while this branch added
normalizeImportedAmount. Both are additive, so kept both plus their
imports and combined the export list.
@MelvinBot

Copy link
Copy Markdown
Contributor

Done — conflicts resolved and pushed as a merge commit (2c58e14). The PR is MERGEABLE again.

One file conflicted: src/libs/importSpreadsheetUtils.ts

Both sides were purely additive, so I kept both:

The 11 language files auto-merged; ImportedMembersPage.tsx was untouched by main.

How I verified the resolution
  • The merged tree differs from main by exactly the PR's original 13 files and the same 55 insertions, 5 deletions as before the merge — so the merge added nothing and dropped nothing from your change.
  • No duplicate declarations; all 4 imports are used; all 5 exported names resolve for every one of the 11 import sites (including tests/unit/ImportTransactions.test.ts).
  • MoneyRequestUtils and StringUtils don't import importSpreadsheetUtils, so the new import edge doesn't create a cycle.
  • APIs the branch depends on all survived main's edits to CurrencyUtils/MoneyRequestUtils: convertToBackendAmount, validateAmount, stripCommaFromAmount, stripSpacesFromAmount, and useCurrencyListActions().getCurrencyDecimals/getCurrencySymbol.
  • Mobile-Expensify submodule pointer matches main.

Heads-up: I could not run typecheck, lint, or prettier locally — those commands were blocked in my sandbox, so I verified statically instead. Please let CI confirm before merging.

Unrelated to the conflict, two things in this PR still need you:

  1. The PROPOSAL: line in the description is still the <add the approved proposal comment URL here> placeholder.
  2. invalidApprovalLimit is the English string in all 11 locales, including de/fr/ja/zh-hans.

@rushatgabhane

Copy link
Copy Markdown
Member Author

@MelvinBot are the conflicts cause because of me?

@MelvinBot

Copy link
Copy Markdown
Contributor

No — this wasn't something you did. The conflict came from [Payment due @abdulrahuman5196] Improve column auto-mapping when the file structure is different landing on main at 16:11 UTC on Sep 17, about 2 hours after your last commit.

That PR rewrote the top of src/libs/importSpreadsheetUtils.ts (+289 lines, plus a new ColumnRole import) and changed the single export {...} line at the bottom. Those are the exact two anchors your change also touches to add normalizeImportedAmount. Both sides were purely additive, so git had no basis to order them and just flagged the overlap — unavoidable timing, not a mistake.

The PR is MERGEABLE now. The BLOCKED status is from two failing checks, and neither is caused by your change or by the conflict resolution — both files come from main and are not in your diff:

They should clear once those fixes land on main and you merge it in again.


view run

@rushatgabhane

Copy link
Copy Markdown
Member Author

@MelvinBot is the - TypeScript Checks / typecheck (pull_request)](https://github.com/Expensify/App/actions/runs/35272704781/job/105375696220?pr=101422)
and
ESLint check / ESLint check (pull_request)
failing because of me?

@MelvinBot

Copy link
Copy Markdown
Contributor

No, neither failure is yours. Both are in test files your PR doesn't touch, and both are already fixed on main — your branch is just stale (head is from Sep 17). Merge main into the branch and both should go green.

Your diff only touches src/languages/*.ts, src/libs/importSpreadsheetUtils.ts and src/pages/workspace/members/ImportedMembersPage.tsx.

Evidence

TypeScript Checks — 2 errors, both in tests/unit/ModifiedExpenseMessageTest.ts:460 and :491:

error TS2741: Property 'movedFromReportName' is missing in type '{ ... }'

getForReportAction gained a required movedFromReportName param in src/libs/ModifiedExpenseMessage.ts on main. The test on main was updated to pass it — ModifiedExpenseMessageTest.ts:473 now includes movedFromReportName: undefined plus formatPhoneNumber. Your branch predates that update, so it still has the old call sites.

ESLint — 1 error in tests/unit/pages/workspace/accounting/netsuite/NetSuiteTokenInputPageTest.tsx:100:

Unsafe type assertion: type 'UsePermissions' is more narrow than the original type.
  @typescript-eslint/no-unsafe-type-assertion

That comes from as ReturnType<typeof usePermissions> on the mockedUsePermissions.mockReturnValue(...) call. Grepping main for that assertion returns nothing — it's already been removed.


view run

@rushatgabhane
rushatgabhane marked this pull request as ready for review September 25, 2026 16:40
@rushatgabhane
rushatgabhane requested review from a team as code owners September 25, 2026 16:40
@melvin-bot
melvin-bot Bot requested review from FitseTLT and trjExpensify and removed request for a team September 25, 2026 16:40
@melvin-bot

melvin-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown

@FitseTLT 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 removed request for a team September 25, 2026 16:40
Comment thread src/pages/workspace/members/ImportedMembersPage.tsx Outdated
Comment thread src/pages/workspace/members/ImportedMembersPage.tsx Outdated
@FitseTLT

This comment was marked as outdated.

Comment thread src/languages/de.ts Outdated
fieldNotMapped: (fieldName: string) => `Ups! Ein erforderliches Feld („${fieldName}“) wurde nicht zugeordnet. Bitte überprüfe es und versuche es erneut.`,
singleFieldMultipleColumns: (fieldName: string) => `Ups! Du hast ein einzelnes Feld („${fieldName}“) mehreren Spalten zugeordnet. Bitte überprüfe dies und versuche es erneut.`,
emptyMappedField: (fieldName: string) => `Ups! Das Feld („${fieldName}“) enthält einen oder mehrere leere Werte. Bitte überprüfe es und versuche es erneut.`,
invalidApprovalLimit: 'Approval limits must be valid amounts for the workspace currency.',

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.

The copies are not translated

Comment on lines +101 to +103
} else {
errors = {};
}

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 is unnecessary

/**
* Normalizes an amount cell from an imported spreadsheet by removing its currency marker, grouping separators, and whitespace.
*/
function normalizeImportedAmount(value: string, currencySymbol?: string, currencyCode?: string): string {

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.

It would be ideal to add a unit test.

const customField2 = membersCustomField2Column !== -1 ? (membersCustomField2?.[containsHeader ? index + 1 : index] ?? '') : undefined;
const approvalLimit = membersApprovalLimitColumn !== -1 ? (membersApprovalLimit?.[containsHeader ? index + 1 : index] ?? '') : undefined;
const approvalLimitValue = membersApprovalLimit?.[containsHeader ? index + 1 : index] ?? '';
const normalizedApprovalLimit = normalizeImportedAmount(approvalLimitValue, currencySymbol, currency);

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.

We can take this in the if condition

@FitseTLT

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 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 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 and each prop has a /** comment above it */
    • The file is named correctly
    • 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
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • 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 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 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
2026-09-30.16-52-30.mp4
Android: mWeb Chrome
2026-09-30.16-21-45.mp4
iOS: HybridApp
iOS: mWeb Safari
2026-09-30.16-19-09.mp4
MacOS: Chrome / Safari
2026-09-30.16-16-16.mp4

@melvin-bot melvin-bot Bot changed the title Fix approval limit CSV import conversion [Payment due @FitseTLT] Fix approval limit CSV import conversion Sep 30, 2026
@melvin-bot

melvin-bot Bot commented Sep 30, 2026

Copy link
Copy Markdown

🎯 @FitseTLT, thanks for reviewing and testing this PR! 🎉

A payment issue will be created for your review once this PR is deployed to production.
E/E issue linked to the PR - https://www.github.com/Expensify/Expensify/issues/682002.

If payment is not needed (e.g., regression PR review fix etc), react with 👎 to this comment to prevent the payment issue from being created.

@FitseTLT

FitseTLT commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

🎀 👀 🎀 C+ reviewed

@brianlee-expensify

Copy link
Copy Markdown
Contributor

@rushatgabhane any updates here? 👋

@rushatgabhane

rushatgabhane commented Oct 6, 2026 •

Copy link
Copy Markdown
Member Author

@brianlee-expensify im waiting for an internal engineer to approve
i've asked in c+ channel but no reply yet.

@Gonals assigned you for final review 🙇

@rushatgabhane
rushatgabhane requested a review from Gonals October 6, 2026 11:02
@Gonals
Gonals merged commit d3f8911 into Expensify:main Oct 8, 2026
35 of 36 checks passed
@OSBotify

OSBotify commented Oct 8, 2026

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.

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

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

@OSBotify

OSBotify commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/Gonals in version: 9.5.6-0 🚀

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

@MelvinBot

Copy link
Copy Markdown
Contributor

No help site update is needed: this bug fix makes CSV-imported approval limits use the amount users already expect (for example, 500 becomes $500), and no article says otherwise.


view run

@OSBotify

OSBotify commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/puneetlath in version: 9.5.6-6 🚀

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

Bundle Size Analysis (Sentry):

@melvin-bot

melvin-bot Bot commented Oct 9, 2026

Copy link
Copy Markdown

🤖 Payment issue created: #103657

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.

7 participants