Skip to content

Commit 9a6b28d

Browse files
authored
Merge pull request Expensify#79294 from marufsharifi/fix/offline-reimbursable-report-title-not-updating
Fix report title not updating when reimbursable expense is changed offline
2 parents b6b66f6 + e7e5aaf commit 9a6b28d

2 files changed

Lines changed: 35 additions & 0 deletions

File tree

src/libs/ReportUtils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6701,13 +6701,19 @@ function populateOptimisticReportFormula(formula: string, report: OptimisticExpe
67016701

67026702
const createdDate = report.lastVisibleActionCreated ? new Date(report.lastVisibleActionCreated) : undefined;
67036703

6704+
const totalAmount = report.total !== undefined && !Number.isNaN(report.total) ? Math.abs(report.total) : 0;
6705+
const nonReimbursableTotal =
6706+
'nonReimbursableTotal' in report && report.nonReimbursableTotal !== undefined && !Number.isNaN(report.nonReimbursableTotal) ? Math.abs(report.nonReimbursableTotal) : 0;
6707+
const reimbursableAmount = totalAmount - nonReimbursableTotal;
6708+
67046709
const result = formula
67056710
// We don't translate because the server response is always in English
67066711
.replaceAll(/\{report:type\}/gi, 'Expense Report')
67076712
.replaceAll(/\{report:startdate\}/gi, createdDate ? format(createdDate, CONST.DATE.FNS_FORMAT_STRING) : '')
67086713
.replaceAll(/\{report:enddate\}/gi, createdDate ? format(createdDate, CONST.DATE.FNS_FORMAT_STRING) : '')
67096714
.replaceAll(/\{report:id\}/gi, getBase62ReportID(Number(report.reportID)))
67106715
.replaceAll(/\{report:total\}/gi, report.total !== undefined && !Number.isNaN(report.total) ? convertToDisplayString(Math.abs(report.total), report.currency).toString() : '')
6716+
.replaceAll(/\{report:reimbursable\}/gi, report.total !== undefined && !Number.isNaN(report.total) ? convertToDisplayString(reimbursableAmount, report.currency).toString() : '')
67116717
.replaceAll(/\{report:currency\}/gi, report.currency ?? '')
67126718
.replaceAll(/\{report:policyname\}/gi, policy?.name ?? '')
67136719
.replaceAll(/\{report:workspacename\}/gi, policy?.name ?? '')

src/libs/actions/IOU/index.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ import {
186186
isSettled,
187187
isTestTransactionReport,
188188
isTrackExpenseReport,
189+
populateOptimisticReportFormula,
189190
prepareOnboardingOnyxData,
190191
shouldCreateNewMoneyRequestReport as shouldCreateNewMoneyRequestReportReportUtils,
191192
shouldEnableNegative,
@@ -3006,6 +3007,22 @@ function getDeleteTrackExpenseInformation(
30063007
return {parameters, optimisticData, successData, failureData, shouldDeleteTransactionThread, chatReport};
30073008
}
30083009

3010+
/**
3011+
* Recalculates the report name using the policy's custom title formula.
3012+
* This is needed when report totals change (e.g., adding expenses or changing reimbursable status)
3013+
* to ensure the report title reflects the updated values like {report:reimbursable}.
3014+
*/
3015+
function recalculateOptimisticReportName(iouReport: OnyxTypes.Report, policy: OnyxEntry<OnyxTypes.Policy>): string | undefined {
3016+
if (!policy?.fieldList?.[CONST.POLICY.FIELDS.FIELD_LIST_TITLE]) {
3017+
return undefined;
3018+
}
3019+
const titleFormula = policy.fieldList[CONST.POLICY.FIELDS.FIELD_LIST_TITLE]?.defaultValue ?? '';
3020+
if (!titleFormula) {
3021+
return undefined;
3022+
}
3023+
return populateOptimisticReportFormula(titleFormula, iouReport as Parameters<typeof populateOptimisticReportFormula>[1], policy);
3024+
}
3025+
30093026
/**
30103027
* Gathers all the data needed to submit an expense. It attempts to find existing reports, iouReports, and receipts. If it doesn't find them, then
30113028
* it creates optimistic versions of them and uses those instead
@@ -3148,6 +3165,12 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma
31483165
iouReport.nonReimbursableTotal = (iouReport.nonReimbursableTotal ?? 0) - amount;
31493166
}
31503167
}
3168+
3169+
// Recalculate reportName to reflect updated totals
3170+
const updatedReportName = recalculateOptimisticReportName(iouReport, policy);
3171+
if (updatedReportName) {
3172+
iouReport.reportName = updatedReportName;
3173+
}
31513174
}
31523175
if (typeof iouReport.unheldTotal === 'number') {
31533176
// Use newReportTotal in scenarios where the total is based on more than just the current transaction amount, and we need to override it manually
@@ -4260,6 +4283,12 @@ function getUpdateMoneyRequestParams(params: GetUpdateMoneyRequestParamsType): U
42604283
updatedMoneyRequestReport.unheldNonReimbursableTotal += updatedTransaction.reimbursable ? -updatedTransaction.amount : updatedTransaction.amount;
42614284
}
42624285
}
4286+
4287+
// Recalculate reportName after all totals are updated
4288+
const updatedReportName = recalculateOptimisticReportName(updatedMoneyRequestReport, policy);
4289+
if (updatedReportName) {
4290+
updatedMoneyRequestReport.reportName = updatedReportName;
4291+
}
42634292
} else {
42644293
updatedMoneyRequestReport = updateIOUOwnerAndTotal(
42654294
iouReport,

0 commit comments

Comments
 (0)