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

Projects

Status

HIGH

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions