Skip to content

[Bulk Edit Expenses] Implement frontend changes #75617

@marcaaron

Description

@marcaaron

Part of the Bulk Edit expenses in NewDot project

Tracking issue: https://github.com/Expensify/Expensify/issues/541817
Doc section: https://docs.google.com/document/d/1IMn36LsoyA0xG0-_eLNrFvCYeddiumuoLGCefrdm1qU/
Project: Migrate

Summary

  • Extend existing selection and editing to support bulk editing of multiple editable expenses.
  • Reuse SearchContext for multi-select, add a new “Edit multiple expenses” action, and implement a new edit page with optimistic updates and system messages per expense.

Objectives

  • Support multi-selection of editable expenses.
  • Add a multi-transaction permission helper.
  • Add “Edit multiple expenses” menu item and navigation.
  • Build SearchEditMultiplePage (empty initial values, policy-aware).
  • Implement optimistic updates and per-expense system messages using UpdateMoneyRequest.

Implementation Steps

Bulk Edit Permission Check

  • Add canEditMultipleTransactions(selectedTransactions) in ReportUtils.ts.
  • Behavior:
    • Ensure at least 2 expenses are selected.
    • For each selected transaction:
      • Obtain its report action via getIOUActionForTransactionID.
      • Call canEditFieldOfMoneyRequest for key fields (amount, merchant, category, tag, comment, taxCode, created, currency, state).
    • If any transaction exposes at least one editable field, return true to enable “Edit multiple”.
  • Non-editable fields (due to transaction/report state) still render with a right caret; updates for those fields are ignored for those specific expenses when the command runs (parity with Classic).
  • Add unit tests for both canEditMultipleTransactions() and canEditFieldOfMoneyRequest().

Add “Edit Multiple” Option to Bulk Actions Menu

  • The green “Selected” button is rendered by ButtonWithDropdownMenu.
    • Narrow screens: SearchSelectedNarrow.
    • Wide screens: SearchFiltersBar.
  • Extend useSelectedTransactionsActions and SearchPage header buttons:
    • Add a new option when selectedTransactionsKeys.length >= 2.
    • Option details:
      • icon: Expensicons.Pencil
      • text: translate('search.bulkActions.editMultiple')
      • value: CONST.SEARCH.BULK_ACTION_TYPES.EDIT (add this CONST)
      • onSelected: navigate to SearchEditMultiplePage
    • Place this option as the FIRST item.

Build the Edit Multiple Expenses Page

  • Create SearchEditMultiplePage using a layout similar to MoneyRequestView.
  • Fields render EMPTY initially (no prefill), matching Classic.
  • Use MenuItemWithTopDescription for each field.
  • Determine policyID:
    • If selection originates from a single report context: use report.policyID.
    • If selection spans multiple reports or search: use submitter’s default from ONYXKEYS.NVP_ACTIVE_POLICY_ID.
  • Load policy via ONYXKEYS.COLLECTION.POLICY[policyID].
  • On field edit and save (per-field subpage), stage values for submission.

Save and Optimistic Updates

  • Add a bottom “Save” button (success styling) on SearchEditMultiplePage.

  • On press:

    • Loop through selected transactions.
    • For each transaction, call UpdateMoneyRequest with only changed fields in updates.
    • Generate modifiedExpenseReportActionID via NumberUtils.rand().
  • Optimistic Onyx updates per transaction:

    • Update ONYXKEYS.COLLECTION.TRANSACTION[transactionID] with changed fields only.
    • Set pendingFields[field] = CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE for each changed field.
    • Provide successData to clear pendingFields.
    • Provide failureData to revert values and surface errors.
  • UpdateMoneyRequest parameters per request (one transaction per call):

    • authToken: string
    • transactionID: string
    • modifiedExpenseReportActionID: string (optimistic ID)
    • updates object (only include edited fields):
      • merchant: string (≤255 chars)
      • created: string (YYYY-MM-DD)
      • amount: number (cents; negative for expenses)
      • currency: string (3-letter code)
      • state: number (reimbursable/billable enums: 3 or 4)
      • category: string (name)
      • tag: string (name)
      • comment: string (description)
      • taxCode: string (externalID of tax UDF; only rate is editable in Bulk Edit UI)

6) Optimistic System Messages

  • After each successful update, add one system message per updated expense.
  • Prepare optimistic report actions so users see immediate feedback:
    • type: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE
    • actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE
    • originalMessage: OriginalMessageModifiedExpense containing changed fields with old → new values
  • Use buildOptimisticModifiedExpenseReportAction.
  • Add these optimistic actions to the corresponding transaction thread reports via optimisticData.

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

Status
HIGH

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions