Skip to content

[$175] Improvement: Reorder "Bank address" and "Bank city" inputs #104561

Open

Description

@m-natarajan

If you haven’t already, check out our contributing guidelines for onboarding. To join our Slack channel, fill out this form.


Version Number: 9.5.15-1
Reproducible in staging?: Y
Reproducible in production?: Y
If this was caught during regression testing, add the test name, ID and link from BrowserStack:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by: @Eskalifer1
Slack conversation (hyperlinked to channel name): #Expensify Bugs

Action Performed:

  1. Create a workspace with EUR as its currency.
  2. Go to Workflows > Payments > Add bank account > Connect manually.
  3. Select any country (e.g., Croatia) and click Confirm.
  4. Observe the order of the inputs in the second step.

Expected Result:

Bank address field first. Reorder the Bank address and Bank city inputs so that Bank address appears first.

Actual Result:

Bank city field first, This creates unnecessary work because, in most cases, users wouldn't need to enter the city separately if they selected the bank address first. Additionally, the automatically populated value may overwrite a city they have already entered, forcing them to review or correct it.

Workaround:

Unknown

Platforms:

Select the officially supported platforms where the issue was reproduced:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari

Screenshots/Videos

2026-10-15.18.37.04.mov
Recording.3723.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit

Activity

  1. added
    ImprovementItem broken or needs improvement.
    BugSomething is broken. Auto assigns a BugZero manager.
    on Oct 21, 2026
  2. MelvinBot commented on Oct 21, 2026

    @MelvinBot
    Contributor

    Proposal

    What is the root cause of that problem?

    BankAccountDetails renders corpayFields.formFields in the order the GetCorpayBankAccountFields API returns them. It never sorts them. For this country/currency, the backend lists bankCity before bankAddressLine1. Picking an address in the Bank address search fills in bankCity automatically, so a city the user already typed gets overwritten.

    The personal wallet version of this page already sorts the fields by CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS, where bankAddressLine1 comes before bankCity. The workspace flow is missing that sort.

    Code references

    What changes do you think we should make in order to solve the problem?

    1. In BankAccountDetails.tsx, reorder the fields that appear in CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS into that list's order. Leave every other field (account number, SWIFT, and so on) in its original slot. Put the sorted bank-info fields back into the slots those fields held before. This puts Bank address before Bank city for every country, whatever order the backend sends.
    2. Don't copy the personal page's comparator as-is. On this page, fields outside the list get indexOf = -1, so that comparator would move them to the top.
    3. Optional: put the logic in a small util under NonUSD/utils/. Reuse it in Confirmation.tsx:34 so the summary uses the same order.
    4. Add a unit test for the util.

    What alternative solutions did you explore? (Optional)

    • Change the field order on the backend. That fixes every client, but the fix is outside the App repo. Your App-side sort fixes the issue on its own.
    • Stop the address search from overwriting a city the user already entered. This fixes the overwrite but leaves the odd order in place.
    Possibly related

    I found the root cause in the code. I didn't reproduce it in the app.


    Next Steps for Contributor+ team:
    To accept: @MelvinBot implement [this](https://github.com/Expensify/App/issues/104561) to create a draft PR.
    To refine: @MelvinBot <your feedback>
    To reject: Explain why you are rejecting Melvin's proposal.


    view run

  3. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Oct 21, 2026
  4. j3ffffff commented on Oct 21, 2026

    @j3ffffff

    VERDICT: POST
    ROOT_CAUSE_ONELINER: The BankAccountDetails component renders corpayFields.formFields in the raw API-returned order, and for countries like Croatia the API places bankCity before bankAddressLine1, despite CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS defining the correct order (address before city).
    PROPOSAL_TYPE: FIRST
    AUTOPOST_SAFE: YES

  5. melvin-bot commented on Oct 21, 2026

    @melvin-bot

    Triggered auto assignment to Contributor-plus team member for initial proposal review - @marufsharifi (External)

  6. changed the title [-]Improvement: Reorder "Bank address" and "Bank city" inputs[/-] [+][$175] Improvement: Reorder "Bank address" and "Bank city" inputs[/+] on Oct 21, 2026
  7. melvin-bot commented on Oct 21, 2026

    @melvin-bot
  8. camesenin commented on Oct 21, 2026

    @camesenin

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    In the workspace "Add bank account" manual setup flow for certain country/currency combinations (e.g., EUR and Croatia), "Bank city" renders above "Bank address". Selecting an address in the address search overwrites an already filled city field. "Bank address" must render before "Bank city".

    What is the root cause of that problem?

    BankAccountDetails renders corpayFields.formFields directly in the array order returned by the GetCorpayBankAccountFields API without applying deterministic UI field sorting.

    What changes do you think we should make in order to solve the problem?

    Sort corpayFields.formFields prior to rendering in src/pages/workspace/expensifyCard/BankAccountDetails.tsx using the pre-defined priority array in CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.

    Create a shallow copy of the form fields array before sorting to prevent mutating props/state directly:

    // src/pages/workspace/expensifyCard/BankAccountDetails.tsx
    import CONST from '@src/CONST';
    
    // Within the component render logic prior to rendering inputs:
    const sortedFormFields = useMemo(() => {
        if (!corpayFields?.formFields) {
            return [];
        }
        return [...corpayFields.formFields].sort((a, b) => {
            const indexA = CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.indexOf(a.name);
            const indexB = CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.indexOf(b.name);
    
            if (indexA !== -1 && indexB !== -1) {
                return indexA - indexB;
            }
            if (indexA !== -1) {
                return -1;
            }
            if (indexB !== -1) {
                return 1;
            }
            return 0;
        });
    }, [corpayFields?.formFields]);

    Replace iteration over corpayFields.formFields with sortedFormFields in the JSX output.

    What alternative solutions did you explore? (Optional)

    None. Sorting on the client side using existing application constants mirrors the established behavior of the personal bank account flow.

    Contributor details
    Your Expensify account email: [email protected]
    Upwork Profile Link: https://www.upwork.com/freelancers/~01b60d704ba377be83

  9. melvin-bot commented on Oct 21, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  10. Stephen3453 commented on Oct 21, 2026

    @Stephen3453

    Proposal

    What is the root cause of that problem?

    In src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx, bankAccountDetailsFields is corpayFields?.formFields?.filter(...) and inputs is a plain .map over it, so the inputs follow the order the Corpay API returns. For Croatia that order lists bankCity before bankAddressLine1. The Bank address input is an AddressSearch with renamedInputKeys={{city: 'bankCity'}}, so picking an address overwrites a city the user already typed. The personal-wallet page (InternationalDepositAccount/subPages/BankInformation.tsx) avoids this by sorting with CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.indexOf(...). The workspace flow has no sort.

    What changes do you think we should make in order to solve the problem?

    1. Add a small helper putAddressBeforeCity(fields) (for example in NonUSD/utils/). It finds the indexes of bankAddressLine1 and bankCity. If bankCity comes first, it returns a copy with those two entries swapped. Otherwise it returns the fields unchanged. Every other field keeps its slot, and it is a no-op for countries that don't return both fields.
    2. In BankAccountDetails.tsx, wrap the filter result: const bankAccountDetailsFields = putAddressBeforeCity(corpayFields?.formFields?.filter(...) ?? []). fieldIds and subStepKeys derive from it, so nothing else changes.
    3. Apply the same helper to formFields in Confirmation.tsx (summaryItems) so the summary matches the form order.
    4. Unit test for the helper: [bankCity, bankAddressLine1, swift] gives [bankAddressLine1, bankCity, swift]. Already-correct order, a missing field and an empty array come back unchanged.

    What alternative solutions did you explore? (Optional)

    • MelvinBot (same root cause): sorts all BANK_INFORMATION_FIELDS members back into their original slots. That is more code than the issue needs, and it needs a careful comparator, because indexOf returns -1 for fields outside the list and a comparator copied from the wallet page would move them to the top. Swapping the two named fields is smaller and cannot reorder anything else.
    • Reuse the wallet page's .sort(...) comparator as is: this would shuffle account number and SWIFT fields to the top, so I rejected it.
    • Stop AddressSearch from overwriting an existing city: this fixes the overwrite but not the order the issue asks for.
    • Change the order on the backend: it is outside the App repo.

    I read the code but did not reproduce it in the app.

  11. khizzcr7 commented on Oct 21, 2026

    @khizzcr7

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    In the workspace "Add bank account" manual setup flow for certain country/currency combinations (e.g. Croatia/EUR), "Bank city" renders above "Bank address". Selecting an address in the address search then overwrites a city the user may have already entered, creating unnecessary rework.

    What is the root cause of that problem?

    In src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx, the form fields are rendered in the raw array order returned by the GetCorpayBankAccountFields API: bankAccountDetailsFields is built by filtering corpayFields.formFields (line 42) and mapped straight into inputs (line 87) with no client-side ordering, so field order is whatever the API happens to return for that country/currency combo. Additionally, fields whose id is in CONST.CORPAY_FIELDS.SPECIAL_LIST_ADDRESS_KEYS render as an AddressSearch input (lines 29-33) with renamedInputKeys mapping city to bankCity (lines 107-111), which auto-populates the city when an address is selected - clobbering any city already entered when the city field sits above.

    What changes do you think we should make in order to solve the problem?

    Deterministically order bankAccountDetailsFields before rendering so the address-search field(s) come before the city field, on a shallow copy of the array so corpayFields is never mutated. Unknown/new field ids keep their API order (stable fallback). The validate loop iterates the fields order-independently, so no change is needed there.

    What alternative solutions did you explore?

    Sorting keyed off a hardcoded constant priority list for the whole form - rejected, because the field set is country-dependent (API-driven) and a priority list would silently break ordering for combos not in the list. Ordering keyed on the existing SPECIAL_LIST_ADDRESS_KEYS grouping (address fields before plain text fields) generalizes to all country/currency combos.

    I will verify with the issue's exact repro (EUR workspace, manual bank connect, Croatia): Bank address renders above Bank city, selecting an address auto-populates street + city without clobbering a manually entered city, required-field validation still fires regardless of field order, and draft persistence across steps is unchanged. I will also spot-check a second country combo to confirm no ordering regression.

  12. sijo0218 commented on Oct 21, 2026

    @sijo0218
    Contributor details

    Your Expensify account email: [email protected]
    Upwork Profile Link: https://www.upwork.com/freelancers/~011091133bbb09cd1c

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    In the workspace manual bank account setup flow for non-USD currencies (e.g., EUR and Croatia), on the "What are your bank details?" step (BankAccountDetails), the "Bank city" field renders above "Bank address". Because "Bank address" uses AddressSearch with renamedInputKeys={{city: 'bankCity'}}, selecting an address automatically populates the city, overwriting whatever city the user may have already entered and forcing unnecessary rework.

    What is the root cause of that problem?

    In src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx (lines 42, 87), bankAccountDetailsFields is constructed by filtering corpayFields?.formFields:

    const bankAccountDetailsFields = corpayFields?.formFields?.filter((field) => !field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX));

    It renders fields directly in the raw order returned by the Corpay GetCorpayBankAccountFields API without any deterministic UI ordering. For certain countries (such as Croatia with EUR), the Corpay API lists bankCity before bankAddressLine1.

    Because bankAddressLine1 is recognized as a special address key (CONST.CORPAY_FIELDS.SPECIAL_LIST_ADDRESS_KEYS.includes(field.id)), it renders an <AddressSearch> component configured with:

    renamedInputKeys={{
        street: 'bankAddressLine1',
        city: 'bankCity',
        country: '',
    }}

    Selecting an address in AddressSearch automatically updates both bankAddressLine1 and bankCity. Having bankCity positioned above bankAddressLine1 creates unnecessary friction and overwrites pre-filled user input.

    In contrast, the personal wallet flow (src/pages/settings/Wallet/InternationalDepositAccount/subPages/BankInformation.tsx:95 and Confirmation.tsx:137) explicitly enforces canonical ordering using CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS:

    ['bankName', 'bankAddressLine1', 'bankAddressLine2', 'bankCity', 'bankRegion', 'bankPostal', 'BeneficiaryBankBranchName']

    The non-USD workspace flow currently lacks this canonical sorting.

    What changes do you think we should make in order to solve the problem?

    1. Create utility helper sortBankInformationFields:
      Create src/pages/ReimbursementAccount/NonUSD/utils/sortBankInformationFields.ts that orders all bank information fields according to the canonical sequence in CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS, while preserving the exact relative positions of non-bank-information fields (e.g., IBAN, accountNumber):
    import CONST from '@src/CONST';
    import type {CorpayFormField} from '@src/types/onyx';
    
    /**
     * Sorts bank information fields according to the canonical order defined in CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS
     * while preserving the positions of non-bank-information fields.
     */
    function sortBankInformationFields(fields: CorpayFormField[]): CorpayFormField[] {
        const bankInfoIndices: number[] = [];
        const bankInfoFields: CorpayFormField[] = [];
    
        fields.forEach((field, index) => {
            if (CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.includes(field.id)) {
                bankInfoIndices.push(index);
                bankInfoFields.push(field);
            }
        });
    
        bankInfoFields.sort((a, b) => CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.indexOf(a.id) - CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.indexOf(b.id));
    
        const result = [...fields];
        bankInfoIndices.forEach((originalIndex, i) => {
            result[originalIndex] = bankInfoFields[i];
        });
    
        return result;
    }
    
    export default sortBankInformationFields;
    1. Sort fields in BankAccountDetails.tsx:
      In src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx:
    + import sortBankInformationFields from '@pages/ReimbursementAccount/NonUSD/utils/sortBankInformationFields';
    ...
    - const bankAccountDetailsFields = corpayFields?.formFields?.filter((field) => !field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX));
    + const bankAccountDetailsFields = useMemo(() => {
    +     const filteredFields = corpayFields?.formFields?.filter((field) => !field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX));
    +     return sortBankInformationFields(filteredFields ?? []);
    + }, [corpayFields?.formFields]);
    1. Sort fields in Confirmation.tsx:
      In src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx:
    + import sortBankInformationFields from '@pages/ReimbursementAccount/NonUSD/utils/sortBankInformationFields';
    ...
    - const formFields = corpayFields?.formFields;
    + const formFields = useMemo(() => sortBankInformationFields(corpayFields?.formFields ?? []), [corpayFields?.formFields]);

    This ensures the Confirmation review summary reflects the exact same field order as the input step.

    1. Add Unit Tests:
      Add comprehensive unit tests in tests/unit/sortBankInformationFieldsTest.ts validating:
    • bankAddressLine1 is ordered before bankCity when Corpay returns them in reverse.
    • Full sequence ordering: bankName -> bankAddressLine1 -> bankAddressLine2 -> bankCity -> bankRegion -> bankPostal.
    • Unrelated fields (such as IBAN) maintain their original relative slots.
    • Returns empty or unchanged arrays when no bank info fields are present.

    What alternative solutions did you explore? (Optional)

    • Hardcoding a two-field swap between bankCity and bankAddressLine1: Brittle and fails if bankAddressLine2, bankRegion, or bankPostal are also returned out of sequence. Utilizing the established CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS constant ensures all address fields adhere to canonical order.
    • Sorting the entire array directly via .sort((a, b) => indexOf(a.id) - indexOf(b.id)): Rejected because indexOf returns -1 for account details (e.g., IBAN), which would unintentionally shift non-address fields to the top. The proposed slot-replacement strategy cleanly sorts bank info fields in-place without altering non-bank fields.
  13. bonnhatnguyen commented on Oct 21, 2026

    @bonnhatnguyen

    Contributor details
    Your Expensify account email: [email protected]
    Upwork Profile Link: https://www.upwork.com/freelancers/~0139ed4098bdc50182

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    In the Add Bank Account manual setup flow for non-USD accounts (e.g. workspace with EUR currency and selecting Croatia), the "Bank city" field appears before the "Bank address" field. When a user enters the city first and then selects their bank address via AddressSearch, the auto-populated city overwrites the previously entered value.

    What is the root cause of that problem?

    In src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx:39:
    bankAccountDetailsFields extracts form fields directly from corpayFields?.formFields:

    const bankAccountDetailsFields = corpayFields?.formFields?.filter((field) => !field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX));

    It renders them in whatever arbitrary order the Corpay API returns. For countries like Croatia, the API lists bankCity before bankAddressLine1.
    In contrast, src/pages/settings/Wallet/InternationalDepositAccount/subPages/BankInformation.tsx:82-84 already standardizes the field order by sorting against CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS:

    Object.values(fieldsMap[CONST.CORPAY_FIELDS.PAGE_NAME.BANK_INFORMATION] ?? {})
        .sort((a, b) => CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.indexOf(a.id) - CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.indexOf(b.id))

    Where CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS defines:
    ['bankName', 'bankAddressLine1', 'bankAddressLine2', 'bankCity', 'bankRegion', 'bankPostal', 'BeneficiaryBankBranchName'].
    BankAccountDetails.tsx does not sort bankAccountDetailsFields, causing the input order to drift based on raw API responses.

    What changes do you think we should make in order to solve the problem?

    In src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx:39:
    Sort bankAccountDetailsFields using CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS:

    const bankAccountDetailsFields = corpayFields?.formFields
        ?.filter((field) => !field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX))
        ?.sort((a, b) => {
            const indexA = CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.indexOf(a.id);
            const indexB = CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS.indexOf(b.id);
            if (indexA === -1 && indexB === -1) {
                return 0;
            }
            if (indexA === -1) {
                return 1;
            }
            if (indexB === -1) {
                return -1;
            }
            return indexA - indexB;
        });

    This guarantees consistent field ordering across all countries: bankAddressLine1 will always precede bankCity.

    What alternative solutions did you explore? (Optional)

    • Hardcoding a swap for bankAddressLine1 and bankCity: Rejected because reusing CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS matches the existing implementation in BankInformation.tsx and ensures all bank information fields follow the identical canonical order.

    Testing

    1. Create a workspace with EUR currency.
    2. Navigate to Workflows > Payments > Add bank account > Connect manually.
    3. Select Croatia and confirm.
    4. On the Bank Information step, verify that "Bank address" is displayed before "Bank city".
    5. Use AddressSearch to select an address and verify that the city autocompletes seamlessly without user disruption.
  14. melvin-bot commented on Oct 21, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  15. Abdallah-1551 commented on Oct 22, 2026

    @Abdallah-1551

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    In the workspace manual bank account flow for non-USD currencies (e.g. a EUR workspace with Croatia), the "What are your bank details?" step shows "Bank city" above "Bank address". "Bank address" is an address-search input, and picking a suggestion also fills in the city. If the user has already typed a city, it gets overwritten. "Bank address" should come before "Bank city".

    What is the root cause of that problem?

    src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx builds bankAccountDetailsFields by filtering corpayFields?.formFields and maps the result straight into inputs. Nothing sorts it, so the UI follows whatever order the GetCorpayBankAccountFields API returns. For Croatia/EUR the backend returns bankCity before bankAddressLine1.

    The bankAddressLine1 input renders as AddressSearch with renamedInputKeys={{street: 'bankAddressLine1', city: 'bankCity', country: ''}}. Selecting a suggestion therefore writes bankCity and clobbers a manually entered city.

    The personal wallet page (InternationalDepositAccount/subPages/BankInformation.tsx) already sorts by CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS, which lists bankAddressLine1 before bankCity. The workspace flow never got this sort.

    What changes do you think we should make in order to solve the problem?

    1. Add a util src/pages/ReimbursementAccount/NonUSD/utils/sortBankInformationFields.ts.
      • It takes a list of Corpay form fields and returns a new array. It never mutates the input, because the input comes from Onyx.
      • It collects the fields whose id is in CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS, along with the indexes they occupy.
      • It sorts those fields by their position in the constant.
      • It writes them back into the same slots. Account number, IBAN, SWIFT and all other fields keep their original positions.
    import CONST from '@src/CONST';
    import type {CorpayFormField} from '@src/types/onyx';
    
    function sortBankInformationFields(fields: CorpayFormField[]): CorpayFormField[] {
        const order = CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS as readonly string[];
        const slots: number[] = [];
        const bankFields: CorpayFormField[] = [];
    
        fields.forEach((field, index) => {
            if (!order.includes(field.id)) {
                return;
            }
            slots.push(index);
            bankFields.push(field);
        });
    
        bankFields.sort((a, b) => order.indexOf(a.id) - order.indexOf(b.id));
    
        const result = [...fields];
        slots.forEach((slot, i) => {
            result[slot] = bankFields[i];
        });
        return result;
    }
    
    export default sortBankInformationFields;
    1. Use it in BankAccountDetails.tsx. Wrap the filtered list:
    const bankAccountDetailsFields = useMemo(() => {
        const filtered = corpayFields?.formFields?.filter((field) => !field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX));
        return sortBankInformationFields(filtered ?? []);
    }, [corpayFields?.formFields]);

    fieldIds, subStepKeys, the validation loop and the inputs map all derive from this list. They need no other change.

    1. Use it in Confirmation.tsx for the formFields that feed summaryItems, so the summary order matches the form.

    2. Do not copy the wallet page's comparator as-is. Fields outside the constant get indexOf = -1, so that comparator would move account number and SWIFT fields to the top. The slot-replacement approach avoids this.

    What alternative solutions did you explore? (Optional)

    • Sort the whole array with indexOf or a "-1 goes last" comparator. This moves account and SWIFT fields relative to the bank-info fields, which changes the layout for other countries. I rejected it.
    • Swap only bankCity and bankAddressLine1. This is smaller, but it is brittle. It does not fix bankAddressLine2, bankRegion or bankPostal if they arrive out of order, and it ignores the existing canonical constant.
    • Sort by SPECIAL_LIST_ADDRESS_KEYS or a new priority list. This adds a second source of truth next to BANK_INFORMATION_FIELDS.
    • Stop AddressSearch from overwriting an existing city. This fixes the overwrite but leaves the order the issue asks to change.
    • Change the order on the backend. This is outside the App repo, and the client-side fix works on its own.

    Testing

    Unit tests (tests/unit/sortBankInformationFieldsTest.ts):

    • [bankCity, bankAddressLine1, swift] returns [bankAddressLine1, bankCity, swift].
    • The full sequence comes out as bankName, bankAddressLine1, bankAddressLine2, bankCity, bankRegion, bankPostal.
    • Non-bank fields (IBAN, accountNumber) keep their original slots when interleaved with bank fields.
    • An already-correct order, an empty array, and an array with no bank-info fields come back unchanged.
    • The input array is not mutated.

    Manual:

    1. Create a workspace with EUR currency.
    2. Go to Workflows > Payments > Add bank account > Connect manually.
    3. Select Croatia and click Confirm.
    4. On the bank details step, verify "Bank address" appears before "Bank city".
    5. Pick an address suggestion. Street and city fill in, and no previously typed city is lost, because the city is now below the address.
    6. Leave the required fields empty and verify validation errors still show.
    7. Continue to the Confirmation step and verify the summary uses the same order. Go back and verify draft values persist.
    8. Repeat with another country, such as Germany or the UK, and confirm there is no ordering regression. Account and IBAN fields must stay in place.
  16. melvin-bot commented on Oct 22, 2026

    @melvin-bot

    📣 @Abdallah-1551! 📣
    Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork.
    Please follow these steps:

    1. Make sure you've read and understood the contributing guidelines.
    2. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
    3. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
    4. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.
      Screen Shot 2022-11-16 at 4 42 54 PM
      Format:
    Contributor details
    Your Expensify account email: <REPLACE EMAIL HERE>
    Upwork Profile Link: <REPLACE LINK HERE>
    
  17. marufsharifi commented on Oct 22, 2026

    @marufsharifi
    Contributor

    @MelvinBot Implement this

  18. MelvinBot commented on Oct 22, 2026

    @MelvinBot
    Contributor

    🤖 Draft PR created: #104679
    Please mark it as "Ready for review" or ask me to do that for you when it is ready for review.

    The PR puts Bank address before Bank city on the bank details step and on the confirmation summary. Other fields, such as IBAN and SWIFT, keep their positions.

    What changed and what was tested
    • New helper sortBankInformationFields.ts sorts the bank information fields by CONST.CORPAY_FIELDS.BANK_INFORMATION_FIELDS. The sorted fields go back into the slots they held.
    • BankAccountDetails.tsx and Confirmation.tsx use the helper.
    • New unit tests pass, along with 8 related suites (58 tests), typecheck, lint, the React Compiler check, and spell check.
    • I couldn't check the UI in a browser. The test browser showed a blank page on both tries, which is an environment problem. Please check the Croatia/EUR flow by hand.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributorImprovementItem broken or needs improvement.

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions