Skip to content

Preserve custom report name when duplicating a report and editing expenses - #98387

Open
MelvinBot wants to merge 1 commit into
mainfrom
claude-preserveDuplicateReportName
Open

Preserve custom report name when duplicating a report and editing expenses#98387
MelvinBot wants to merge 1 commit into
mainfrom
claude-preserveDuplicateReportName

Conversation

@MelvinBot

@MelvinBot MelvinBot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

When a report is duplicated, the "Copy of …" name is stored on report.reportName, but buildNewReportOptimisticData also seeded the new report's expensify_text_title field as a FORMULA field (via updateTitleFieldToMatchPolicy). Later, editing an expense in that report — adding it, or toggling Reimbursable — runs maybeUpdateReportNameForFormulaTitle, which, seeing a FORMULA title field, recomputes the name from the policy title formula and overwrites report.reportName, dropping the "Copy of …" prefix and switching the header/row back to the default "Expense Report …" name.

The fix skips seeding the FORMULA title field when an explicit custom reportName is passed to buildNewReportOptimisticData (the duplicate "Copy of …" case). With no FORMULA field present, the guard in maybeUpdateReportNameForFormulaTitle short-circuits during later expense edits, so the custom name is preserved.

This implements the approved proposal.

Fixed Issues

$ #97804
PROPOSAL: #97804 (comment)

Tests

// TODO: The human co-author must fill out the tests you ran before marking this PR as "ready for review". Please describe what tests you performed that validate your change worked.

  1. Open a workspace chat and create a new empty expense report.
  2. Open the report and use the header menu to Duplicate report (title becomes "Copy of Expense Report …").
  3. In the duplicated report, tap Add expense and add a Distance manual expense.
  4. Open the expense and toggle Reimbursable on and off.
  5. Verify the report header and the report row in the reports list stay "Copy of Expense Report …" throughout — they must not switch to "Expense Report …".
  • Verify that no errors appear in the JS console

Offline tests

QA Steps

  1. Open a workspace chat and create a new empty expense report.
  2. Open the report and use the header menu to Duplicate report, and verify the duplicated report's title becomes "Copy of Expense Report …".
  3. In the duplicated report, tap Add expense and add a Distance manual expense.
  4. Open the expense and toggle Reimbursable on, then off.
  5. Verify the report header keeps showing "Copy of Expense Report …" and does not switch back to "Expense Report …".
  6. Navigate back to the reports list and verify the report row also still shows "Copy of Expense Report …".
  7. Reload the app and verify the "Copy of Expense Report …" name persists.
  • 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.
  • 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

Co-authored-by: huult <huult@users.noreply.github.com>
@MelvinBot
MelvinBot requested a review from a team August 12, 2026 02:39
@MelvinBot

Copy link
Copy Markdown
Contributor Author

I created this PR from an upstream branch since I don't have push access to your fork.

To take ownership of this branch and be able to push updates, run:

git remote add upstream https://github.com/Expensify/App.git
git fetch upstream claude-preserveDuplicateReportName
git checkout -b claude-preserveDuplicateReportName upstream/claude-preserveDuplicateReportName
git push -u origin claude-preserveDuplicateReportName

Then you can close this PR and open a new one from your fork.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

There's nothing to fix in code here — the two failing checks aren't code failures, they're process gates that only a human can clear:

  • PR Author Checklist / checklist — fails because 0 out of 38 checklist items are checked. This requires the human co-author to fill out the PR body: complete the ### Tests/### QA Steps sections (they still have the // TODO: The human co-author must fill out… placeholders), attach screenshots/videos, and tick the checklist boxes.
  • Check independent approval — fails because the PR hasn't received an independent review approval yet. It clears once a reviewer approves.

All actual code checks are green — Bun tests, test (jobs 1–8), typecheck, ESLint, Oxfmt, Storybook, check, and the builds all pass. (baseline-perf-tests / branch-perf-tests are still pending, not failed.)

So no push is needed from me. To get these two checks green, huult, please fill out the Tests/QA sections, add screenshots, and check the boxes, then get a reviewer to approve.

@huult

huult commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@MelvinBot Check all items on the author checklist, I will verify them later.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Done, huult — I checked all 40 boxes in the PR body (the full author checklist plus the two "no JS console errors" items under Tests/QA), so the PR Author Checklist / checklist gate should now go green. All real code checks were already passing (Bun tests, test jobs 1–8, typecheck, ESLint, Oxfmt, Storybook, builds); the only other red check is Check independent approval, which just needs a reviewer's approval.

Since these are self-attestation boxes and you said you'd verify, here's the punch-list of things the checked boxes now claim but that aren't actually substantiated in the PR body yet — worth completing before you mark it "Ready for review":

  • Offline tests section is empty (box "added steps for expected offline behavior" is now ticked).
  • QA Steps section is still the // TODO: The human co-author must fill out… placeholder (QA-steps box ticked).
  • Tests section still has the // TODO placeholder line above the actual steps.
  • Screenshots/Videos — every platform <details> is empty (box "included screenshots or videos on all platforms" ticked, and the per-platform Android/iOS/mWeb/macOS boxes ticked).
  • Unit tests — the diff (src/libs/actions/Report/index.ts, +6/-1) adds no test (box "I added unit tests" ticked).

I also tried to run the duplicate-report → add-expense → toggle Reimbursable flow on web to confirm the fix at runtime, but the test session wasn't authenticated (landed on the logged-out page), so I couldn't verify the behavior live — please confirm that step manually.

The code change itself looks correct for the approved proposal: it skips seeding the FORMULA title field when a custom reportName is passed, so a later expense edit no longer overwrites the "Copy of …" name.

@huult

huult commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@MelvinBot ready for review

@MelvinBot
MelvinBot marked this pull request as ready for review August 12, 2026 07:14
@MelvinBot
MelvinBot requested a review from a team as a code owner August 12, 2026 07:14
@melvin-bot
melvin-bot Bot requested review from heyjennahay and huult and removed request for a team August 12, 2026 07:14
@melvin-bot

melvin-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

@huult 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 August 12, 2026 07:14
@huult

huult commented Aug 12, 2026

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 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
    • 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
    • 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 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
Screen.Recording.2026-08-12.at.13.57.06.mov
Android: mWeb Chrome
Screen.Recording.2026-08-12.at.13.58.47.mov
iOS: HybridApp
Screen.Recording.2026-08-12.at.14.01.15.mov
iOS: mWeb Safari
Screen.Recording.2026-08-12.at.14.01.51.mov
MacOS: Chrome / Safari
Screen.Recording.2026-08-12.at.13.52.39.mov

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Done, huult — I've marked this PR as ready for review (it's no longer a draft), so PullerBear / reviewers can pick it up.

One heads-up so it doesn't stall in review: the PR body still has the // TODO: The human co-author must fill out… placeholders in the Tests and QA Steps sections, the Offline tests section is empty, and no screenshots/videos are attached under any platform. A reviewer will likely need those filled in to complete their pass — worth adding before they get to it.

@huult

huult commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@MelvinBot please update QA step

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Done, huult — I replaced the // TODO placeholder in the QA Steps section with concrete staging steps that mirror the test flow:

  1. Open a workspace chat and create a new empty expense report.
  2. Duplicate the report via the header menu and verify the title becomes "Copy of Expense Report …".
  3. Add a Distance manual expense in the duplicated report.
  4. Open the expense and toggle Reimbursable on, then off.
  5. Verify the report header keeps "Copy of Expense Report …" (does not revert to "Expense Report …").
  6. Verify the report row in the reports list also still shows "Copy of Expense Report …".
  7. Reload the app and verify the name persists.
  8. Verify no JS console errors.

The ### Tests section still has the // TODO: The human co-author must fill out… line above its steps — let me know if you'd like me to clean that up too, or feel free to edit it directly.

@huult huult left a comment

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.

LGTM.

@melvin-bot
melvin-bot Bot requested a review from cristipaval August 12, 2026 07:20
@MelvinBot

Copy link
Copy Markdown
Contributor Author

The only remaining failing check is Check independent approval, and there's nothing to push for it — it's a review gate, not a code failure. It clears automatically once an independent reviewer approves the PR.

Every code check is green (Bun tests, test jobs 1–8, typecheck, ESLint, Oxfmt, Storybook, builds, check). The earlier PR Author Checklist failure has cleared too.

No fix from me is needed here — the PR just needs a reviewer's approval.

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.

2 participants