Skip to content

Add {report:debitedAmount} and {report:creditedAmount} formula tokens - #100060

Draft
ishpaul777 wants to merge 4 commits into
Expensify:mainfrom
ishpaul777:ishpaul/655941-formula-debited-credited-amount
Draft

Add {report:debitedAmount} and {report:creditedAmount} formula tokens#100060
ishpaul777 wants to merge 4 commits into
Expensify:mainfrom
ishpaul777:ishpaul/655941-formula-debited-credited-amount

Conversation

@ishpaul777

@ishpaul777 ishpaul777 commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Teaches the NewDot formula engine {report:debitedAmount} and {report:creditedAmount} so it resolves the same token set as the Auth and Web-Expensify engines. Both amounts are already on the report in Onyx. A missing amount resolves to empty, which covers same-currency payments and reports that have not been reimbursed yet. A trailing currency that needs conversion is left as the raw token so the backend fills it in, which is how {report:total:EUR} already behaves here.

These tokens are primarily for custom CSV and PDF export templates, which the Web-Expensify engine renders. On the client they matter in two places: a report field formula that also references {field:...} is resolved live in the report view, and an optimistic report title is computed locally, where an unknown token would otherwise be left on screen as raw placeholder text.

HelpDot lists the tokens in the Expensify Classic export article. They are deliberately not listed in the report title articles, because Auth freezes title and field formulas once a report reaches approved and these amounts only exist after the payment converts during reimbursement, so a title using them would always be empty.

Ship with Auth#24161 and Web-Expensify#55803.

Fixed Issues

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

Tests

  1. Open a workspace, go to More features and enable Report fields.
  2. Add a text report field named Payment with the formula {field:Employee ID} paid {report:debitedAmount} / received {report:creditedAmount}, where Employee ID is another report field on the same workspace.
  3. Open an expense report that has not been reimbursed and confirm the Payment field shows no amounts and no raw {report:debitedAmount} or {report:creditedAmount} text.
  4. Open a report that was reimbursed in the same currency and confirm both amounts are still empty.
  5. Open a report that was reimbursed across currencies and confirm the field shows the debited amount in the company bank account currency and the credited amount in the member's bank account currency.
  6. Set the workspace report title formula to Paid {report:debitedAmount}, create a new report, and confirm the title contains no raw token text.
  7. Verify that no errors appear in the JS console.
  • Verify that no errors appear in the JS console

Offline tests

  1. Open a report that was reimbursed across currencies so it is cached in Onyx.
  2. Go offline.
  3. Confirm the report field still shows both formatted amounts from the cached report.

QA Steps

  1. Open a workspace, go to More features and enable Report fields.
  2. Add a text report field named Payment with the formula {field:Employee ID} paid {report:debitedAmount} / received {report:creditedAmount}, where Employee ID is another report field on the same workspace.
  3. Open an expense report that has not been reimbursed and confirm the Payment field shows no amounts and no raw {report:debitedAmount} or {report:creditedAmount} text.
  4. Open a report that was reimbursed in the same currency and confirm both amounts are still empty.
  5. Open a report that was reimbursed across currencies and confirm the field shows the debited amount in the company bank account currency and the credited amount in the member's bank account currency.
  6. Verify that no errors appear in the JS console.
  • 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 the 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

Keep NewDot titles and HelpDot in lockstep with Classic: {report:debitedAmount} and {report:creditedAmount}, empty when the reimbursement has no FX split.
@ishpaul777
ishpaul777 requested review from a team and stephanieelliott as code owners September 1, 2026 15:56
@melvin-bot
melvin-bot Bot requested review from garrettmknight and removed request for a team September 1, 2026 15:57
@melvin-bot

melvin-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

Concierge reviewer checklist:

  • I have verified the accuracy of the article
    • The article is within a hub that makes sense, and the navigation is correct
    • All processes, screenshots, and examples align with current product behavior.
    • All links within the doc have been verified for correct destination and functionality.
  • I have verified the readability of the article
    • The article's language is clear, concise, and free of jargon.
    • The grammar, spelling, and punctuation are correct.
    • The article contains at least one image, or that an image is not necessary
  • I have verified the formatting of the article
    • The article has consistent formatting (headings, bullet points, etc.) with other HelpDot articles and that aligns with the HelpDot formatting standards.
    • The article has proper text spacing and breaks for readability.
  • I have verified the article has the appropriate tone and style
    • The article's tone is professional, friendly, and suitable for the target audience.
    • The article's tone, terminology, and voice are consistent throughout.
  • I have verified the overall quality of the article
    • The article is not missing any information, nor does it contain redundant information.
    • The article fully addresses user needs.
  • I have verified that all requested improvements have been addressed

For more detailed instructions on completing this checklist, see How do I review a HelpDot PR as a Concierge Team member?

cc @RachCHopkins

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T16:08:23.188025Z 0c2f06a PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@melvin-bot

melvin-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

@parasharrajat @RachCHopkins One of you needs to 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 September 1, 2026 15:57
Comment thread src/libs/Formula.ts Outdated
Comment thread src/libs/Formula.ts Outdated
Fix CONSISTENCY-16 semicolon-joined comment and extract the shared
debited/credited amount formatting into one helper (CONSISTENCY-3).
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

HelpDot Documentation Review

Overall Assessment
This PR adds backend support for two new report formula variables ({report:debitedAmount} and {report:creditedAmount}) for cross-border reimbursements, along with matching documentation. The doc changes are narrow: two new table rows added to each of three existing formula reference articles. This review scores only the proposed documentation changes (the added table rows), not the surrounding legacy content. Documentation files changed: Set-Custom-Report-Names.md (expensify-classic/reports), Export-Expenses-And-Reports.md (expensify-classic/spending-insights), and Customize-and-Enforce-Report-Titles.md (new-expensify/reports-and-expenses).

Scores Summary

  • Readability: 9/10 - The new rows are clear, concise, and consistent with the established table format in each article. Descriptions explain both what the value represents and the key edge case (empty when not a cross-border reimbursement).
  • AI Readiness: 8/10 - Descriptions use full, unambiguous phrasing (cross-border reimbursement, company bank account, employee bank account) that maps well to real search intent. The additions stay within the existing reference tables and do not introduce new headings, so no heading/metadata concerns arise from the diff itself.
  • Style Compliance: 9/10 - The additions match the exact column structure, code formatting (backticks in the two New Expensify / Set-Custom articles), and example conventions already used in each table. Terminology is consistent. No UI button/tab/navigation phrasing is introduced, so the naming conventions have limited applicability here.

Key Findings

  • Consistency is strong: the New Expensify (Customize-and-Enforce-Report-Titles.md) and classic Set-Custom-Report-Names.md rows are identical and correctly formatted with backticks and an Example column. The Export-Expenses-And-Reports.md rows correctly follow that article two-column, plain-text convention with paired label/formula rows.
  • The descriptions clearly document the empty-value behavior for non-cross-border reports, which matches the backend logic in src/libs/Formula.ts (returns empty when debitedAmount/creditedAmount is missing). Documentation and implementation are aligned.
  • Example values are coherent across files (82.50 debited, C110.00 credited), reinforcing the cross-currency nature of the feature.
  • Minor nit: the currency-conversion edge case (the token is preserved verbatim when a currency modifier forces a conversion, e.g. {report:debitedAmount:EUR}, per the unit test in tests/unit/FormulaTest.ts) is not mentioned in the docs. This is an advanced edge case and likely fine to omit, but a one-line note could preempt confusion for power users applying currency modifiers.

Recommendations

  • No blocking documentation issues. The additions are accurate, consistent, and well-scoped.
  • Optional: consider a brief note that a currency-code modifier (e.g. :EUR) on these tokens will not convert the amount, since these values are already expressed in their originating bank-account currency.

Files Reviewed

  • Set-Custom-Report-Names.md - Two new formula rows added; formatting and content consistent. Approved.
  • Export-Expenses-And-Reports.md - Four new rows (label + formula pairs) matching this article convention. Approved.
  • Customize-and-Enforce-Report-Titles.md - Two new formula rows added; identical to the classic Set-Custom article. Approved.

Note: The remaining changed files (src/libs/Formula.ts, tests/unit/FormulaTest.ts, cspell.json) are implementation/config and outside the scope of this documentation review.

| `{report:type}` | Expense Report | Report type (Expense Report, Invoice, Bill) |
| `{report:reimbursable}` | $143.43 | Reimbursable amount |
| `{report:debitedAmount}` | $82.50 | Amount taken from the company bank account for a cross-border reimbursement |
| `{report:creditedAmount}` | C$110.00 | Amount deposited to the employee bank account for a cross-border reimbursement |

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.

Terminology: In New Expensify articles, prefer "member" over "employee" per the naming conventions. Consider "Amount deposited to the member's bank account for a cross-border reimbursement" to align with Expensify NewDot terminology.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0c2f06a846

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/libs/Formula.ts Outdated
Comment on lines 310 to 312
// Empty is a real value for submit and reimbursement-amount tokens; keep it.
if (value === '' && !isSubmissionInfoPart(part) && !isReimbursementAmountPart(part)) {
value = part.definition;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve reimbursement tokens when formatting fails

When an amount and source currency exist but formatting returns an empty string—for example, {report:debitedAmount:UNKNOWN} uses an invalid display currency—this blanket exemption treats the empty value as resolved. Consequently, hasUnresolvedTokens remains false and computeOptimisticReportName() accepts a title with the amount silently removed instead of retaining the server-rendered title. Distinguish an intentionally missing reimbursement amount from formatting failures so the latter preserve the raw token.

Useful? React with 👍 / 👎.

Title and field formulas are frozen once a report reaches approved, and the
amounts only exist after the payment converts during reimbursement, so a
title using these tokens is always empty. They stay in the export reference.
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.

1 participant