Repository navigation
fix: Report - Formula report field initial value {report:i} is not persisted & resets to {report:id} - #84207
Conversation
|
Hey, I noticed you changed If you want to automatically generate translations for other locales, an Expensify employee will have to:
Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running: npx ts-node ./scripts/generateTranslations.ts --helpTypically, you'd want to translate only what you changed by running |
|
@linhvovan29546 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] |
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-03-26.at.10.18.46.movAndroid: mWeb ChromeScreen.Recording.2026-03-26.at.10.19.18.moviOS: HybridAppScreen.Recording.2026-03-26.at.10.09.44.moviOS: mWeb SafariScreen.Recording.2026-03-26.at.10.16.31.movMacOS: Chrome / SafariScreen.Recording.2026-03-26.at.10.08.31.mov |
|
@annaweber830 Do you have access to the open-source Slack channel? |
|
Could you please address this comment? |
linhvovan29546
left a comment
There was a problem hiding this comment.
@annaweber830 Could you please merge main and resolve conflict?
| reportFieldNameRequiredError: 'Please enter a report field name', | ||
| reportFieldTypeRequiredError: 'Please choose a report field type', | ||
| circularReferenceError: "This field can't refer to itself. Please update.", | ||
| unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Unsupported formula token(s): ${value}. Use supported tokens such as {report:id}.`, |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d0979fb0b3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const submitField = rest.at(1)?.trim().toLowerCase(); | ||
| if (!submitField || !supportedSubmitPersonFields.has(submitField)) { |
There was a problem hiding this comment.
Permit
{report:submit:from}/{report:submit:to} tokens
This validation now treats report:submit:from and report:submit:to as invalid unless a third segment is present, so formulas using those 2-segment tokens will be blocked with unsupportedFormulaValueError. That conflicts with our documented/embedded formula vocabulary where both tokens are valid (see docs/articles/new-expensify/reports-and-expenses/Customize-and-Enforce-Report-Titles.md lines 62-63 and src/languages/en.ts line 5404), so this introduces a regression by rejecting formulas users are told to use.
Useful? React with 👍 / 👎.
| FORMULA_PART_TYPES: {REPORT: string}; | ||
| }; | ||
|
|
||
| const supportedReportFields = new Set([ |
There was a problem hiding this comment.
Looks like we're missing some accepted formulas. Can you check here and test adding them?
There was a problem hiding this comment.
I mean we're only validating the formula here
|
@annaweber830 Could you please checking this comment #84207 (comment) |
| switch (field.toLowerCase()) { | ||
| case 'id': | ||
| return getBase62ReportID(Number(report.reportID)); | ||
| case 'oldid': |
There was a problem hiding this comment.
Hmm, I think you misunderstood what I meant. Why do we need to add these cases?
|
|
||
| switch (direction.toLowerCase()) { | ||
| case 'from': | ||
| if (subPath.length === 0) { |
There was a problem hiding this comment.
| } | ||
| return computePersonalDetailsField(subPath, context.submitterPersonalDetails, context.policy); | ||
| case 'to': | ||
| if (subPath.length === 0) { |
There was a problem hiding this comment.
| FORMULA_PART_TYPES: {REPORT: string}; | ||
| }; | ||
|
|
||
| const supportedReportFields = new Set([ |
There was a problem hiding this comment.
I mean we're only validating the formula here
|
I was busy last week, I’ll test this tomorrow. |
linhvovan29546
left a comment
There was a problem hiding this comment.
@annaweber830 Could you please confirm spanish translation on slack open source channel?
| return getHumanReadableStatus(statusNum); | ||
| } | ||
|
|
||
| /** |
There was a problem hiding this comment.
This comment is not attached to any function. So can we remove this?
| return Object.values(fieldList ?? {}).some((reportField) => reportField.name.toLowerCase() === fieldName.toLowerCase()); | ||
| } | ||
|
|
||
| type FormulaParsePart = { |
There was a problem hiding this comment.
Can we use FormulaPart type instead of create new type?
|
@annaweber830 The change LGTM! Could please fix the Spell check as well? |
|
@annaweber830 Could you please check these comment? |
|
@marcochavezf Could you please help run the translation script? Thanks! #84207 (comment) |
Ran the workflow here https://github.com/Expensify/App/actions/runs/24041843834 |
🦜 Polyglot Parrot! 🦜Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues: View the translation diffdiff --git a/src/languages/de.ts b/src/languages/de.ts
index 887a2465..45f7831e 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -5577,7 +5577,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
reportFieldNameRequiredError: 'Bitte gib einen Berichtsfeldnamen ein',
reportFieldTypeRequiredError: 'Bitte wähle einen Berichtsfeldtyp aus',
circularReferenceError: 'Dieses Feld kann nicht auf sich selbst verweisen. Bitte aktualisieren.',
- unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Formelfeld ${value} wurde nicht erkannt`,
+ unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Formelfeld ${value} nicht erkannt`,
reportFieldInitialValueRequiredError: 'Bitte wähle einen Anfangswert für ein Berichtsfeld aus',
genericFailureMessage: 'Beim Aktualisieren des Berichtfelds ist ein Fehler aufgetreten. Bitte versuche es erneut.',
},
@@ -7447,7 +7447,14 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
searchIn: 'Suchen in',
searchPlaceholder: 'Nach etwas suchen',
suggestions: 'Vorschläge',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Vorschläge verfügbar${query ? ` für ${query}` : ''}. ${count} Ergebnis.`,
other: (resultCount: number) => `Vorschläge verfügbar${query ? ` für ${query}` : ''}. ${resultCount} Ergebnisse.`,
}),
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index b5427d86..d7c545d9 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -5599,7 +5599,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
reportFieldNameRequiredError: 'Veuillez saisir un nom de champ de note de frais',
reportFieldTypeRequiredError: 'Veuillez choisir un type de champ de note de frais',
circularReferenceError: 'Ce champ ne peut pas faire référence à lui-même. Veuillez le mettre à jour.',
- unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Le champ de formule ${value} n’est pas reconnu`,
+ unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Champ de formule ${value} non reconnu`,
reportFieldInitialValueRequiredError: 'Veuillez choisir une valeur initiale pour le champ de note de frais',
genericFailureMessage: 'Une erreur s’est produite lors de la mise à jour du champ de note de frais. Veuillez réessayer.',
},
@@ -7471,7 +7471,14 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
searchIn: 'Rechercher dans',
searchPlaceholder: 'Rechercher quelque chose',
suggestions: 'Suggestions',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Suggestions disponibles${query ? ` pour ${query}` : ''}. ${count} résultat.`,
other: (resultCount: number) => `Suggestions disponibles${query ? ` pour ${query}` : ''}. ${resultCount} résultats.`,
}),
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 152f6d90..833ea7a6 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -5568,7 +5568,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
reportFieldNameRequiredError: 'Inserisci un nome per il campo del report',
reportFieldTypeRequiredError: 'Scegli un tipo di campo del report',
circularReferenceError: 'Questo campo non può fare riferimento a se stesso. Aggiorna per favore.',
- unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Il campo formula ${value} non è riconosciuto`,
+ unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Campo formula ${value} non riconosciuto`,
reportFieldInitialValueRequiredError: 'Scegli un valore iniziale per il campo del resoconto',
genericFailureMessage: 'Si è verificato un errore durante l’aggiornamento del campo del report. Riprova.',
},
@@ -7435,7 +7435,14 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
searchIn: 'Cerca in',
searchPlaceholder: 'Cerca qualcosa',
suggestions: 'Suggerimenti',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Suggerimenti disponibili${query ? ` per ${query}` : ''}. ${count} risultato.`,
other: (resultCount: number) => `Suggerimenti disponibili${query ? ` per ${query}` : ''}. ${resultCount} risultati.`,
}),
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index aedfc7ac..7d3b28cc 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -5503,7 +5503,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
reportFieldNameRequiredError: 'レポート項目名を入力してください',
reportFieldTypeRequiredError: 'レポートフィールドの種類を選択してください',
circularReferenceError: 'このフィールドを自分自身に参照することはできません。更新してください。',
- unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `数式フィールド ${value} は認識されません`,
+ unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `数式フィールド ${value} が認識されません`,
reportFieldInitialValueRequiredError: 'レポート項目の初期値を選択してください',
genericFailureMessage: 'レポートフィールドの更新中にエラーが発生しました。もう一度お試しください。',
},
@@ -7343,7 +7343,14 @@ ${reportName}
searchIn: '検索対象',
searchPlaceholder: '何かを検索',
suggestions: '提案',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `候補があります${query ? `: ${query}` : ''}。${count}件の結果。`,
other: (resultCount: number) => `候補があります${query ? `: ${query}` : ''}。${resultCount}件の結果。`,
}),
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 80dda741..020b91d5 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -5548,7 +5548,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
reportFieldNameRequiredError: 'Voer een naam voor een rapportveld in',
reportFieldTypeRequiredError: 'Kies een veldtype voor het rapport',
circularReferenceError: 'Dit veld kan niet naar zichzelf verwijzen. Werk het alsjeblieft bij.',
- unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Formuleveld ${value} wordt niet herkend`,
+ unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Formuleveld ${value} niet herkend`,
reportFieldInitialValueRequiredError: 'Kies een beginwaarde voor een rapportveld',
genericFailureMessage: 'Er is een fout opgetreden bij het bijwerken van het rapportveld. Probeer het opnieuw.',
},
@@ -7401,7 +7401,14 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
searchIn: 'Zoeken in',
searchPlaceholder: 'Zoek iets',
suggestions: 'Suggesties',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Suggesties beschikbaar${query ? ` voor ${query}` : ''}. ${count} resultaat.`,
other: (resultCount: number) => `Suggesties beschikbaar${query ? ` voor ${query}` : ''}. ${resultCount} resultaten.`,
}),
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 46a194ac..c9149a47 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -5544,7 +5544,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
reportFieldNameRequiredError: 'Wprowadź nazwę pola raportu',
reportFieldTypeRequiredError: 'Wybierz typ pola raportu',
circularReferenceError: 'To pole nie może odnosić się do siebie. Zaktualizuj je.',
- unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Pole formuły ${value} nie jest rozpoznawane`,
+ unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Pole formuły ${value} nie zostało rozpoznane`,
reportFieldInitialValueRequiredError: 'Wybierz początkową wartość pola raportu',
genericFailureMessage: 'Wystąpił błąd podczas aktualizowania pola raportu. Spróbuj ponownie.',
},
@@ -7402,7 +7402,14 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
searchIn: 'Szukaj w',
searchPlaceholder: 'Wyszukaj coś',
suggestions: 'Sugestie',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Dostępne sugestie${query ? ` dla ${query}` : ''}. ${count} wynik.`,
other: (resultCount: number) => `Dostępne sugestie${query ? ` dla ${query}` : ''}. ${resultCount} wyniki.`,
}),
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index e8ea5c17..0396496c 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -5548,7 +5548,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
reportFieldNameRequiredError: 'Insira um nome de campo de relatório',
reportFieldTypeRequiredError: 'Escolha um tipo de campo de relatório',
circularReferenceError: 'Este campo não pode fazer referência a si mesmo. Atualize, por favor.',
- unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `O campo de fórmula ${value} não é reconhecido`,
+ unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Campo de fórmula ${value} não reconhecido`,
reportFieldInitialValueRequiredError: 'Escolha um valor inicial para o campo de relatório',
genericFailureMessage: 'Ocorreu um erro ao atualizar o campo do relatório. Tente novamente.',
},
@@ -7389,7 +7389,14 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
searchIn: 'Pesquisar em',
searchPlaceholder: 'Pesquisar algo',
suggestions: 'Sugestões',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Sugestões disponíveis${query ? ` para ${query}` : ''}. ${count} resultado.`,
other: (resultCount: number) => `Sugestões disponíveis${query ? ` para ${query}` : ''}. ${resultCount} resultados.`,
}),
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 5d4d7be6..292b714e 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -5411,7 +5411,7 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
reportFieldNameRequiredError: '请输入报表字段名称',
reportFieldTypeRequiredError: '请选择报表字段类型',
circularReferenceError: '此字段不能引用自身。请更新。',
- unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `无法识别公式字段${value}`,
+ unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `无法识别公式字段 ${value}`,
reportFieldInitialValueRequiredError: '请选择报表字段的初始值',
genericFailureMessage: '更新报表字段时出错。请重试。',
},
@@ -7219,7 +7219,14 @@ ${reportName}
searchIn: '搜索范围',
searchPlaceholder: '搜索内容',
suggestions: '建议',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `有可用建议${query ? `:${query}` : ''}。共${count}条结果。`,
other: (resultCount: number) => `有可用建议${query ? `:${query}` : ''}。共${resultCount}条结果。`,
}),
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
|
@annaweber830 Please apply the translation diff #84207 (comment) |
|
@annaweber830 Eslint failed |
|
🚧 @marcochavezf has triggered a test Expensify/App build. You can view the workflow run here. |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/marcochavezf in version: 9.3.59-0 🚀
Bundle Size Analysis (Sentry): |
|
No help site changes are required for this PR. This PR adds input validation for formula-type report field initial values (rejecting unsupported tokens like
These are internal validation improvements that surface as inline error messages in the UI. Help site articles don't document individual validation/error messages, so no docs update is needed. Note: The existing Enable Report Fields article lists only Text, Date, and List as field types — it does not mention Formula. This is a pre-existing documentation gap unrelated to this PR. If you'd like me to open a separate issue or PR to add Formula to that doc, let me know. |
|
🚀 Deployed to production by https://github.com/AndrewGable in version: 9.3.59-4 🚀
|

Explanation of Change
fix: Report - Formula report field initial value {report:i} is not persisted & resets to {report:id}
Fixed Issues
$ #79855
PROPOSAL: #79855 (comment)
Tests
Pre-condition: report field is enabled
Offline tests
Same as test
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
Pre-condition: report field is enabled
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Screen.Recording.2026-03-04.at.2.50.25.PM.mov