Skip to content

Commit

Permalink
Merge pull request #37160 from paultsimura/fix/36267-report-name-formula
Browse files Browse the repository at this point in the history
feat: Use formula for the optimistic expense report
  • Loading branch information
thienlnam authored Feb 28, 2024
2 parents 130eeed + f898f07 commit 85c7119
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ const CONST = {
DATE: {
SQL_DATE_TIME: 'YYYY-MM-DD HH:mm:ss',
FNS_FORMAT_STRING: 'yyyy-MM-dd',
FNS_DATE_TIME_FORMAT_STRING: 'yyyy-MM-dd HH:mm:ss',
LOCAL_TIME_FORMAT: 'h:mm a',
YEAR_MONTH_FORMAT: 'yyyyMM',
MONTH_FORMAT: 'MMMM',
Expand Down
47 changes: 45 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {format} from 'date-fns';
import ExpensiMark from 'expensify-common/lib/ExpensiMark';
import Str from 'expensify-common/lib/str';
import {isEmpty} from 'lodash';
Expand Down Expand Up @@ -1981,6 +1982,13 @@ function getFormulaTypeReportField(reportFields: PolicyReportFields) {
return Object.values(reportFields).find((field) => field.type === 'formula');
}

/**
* Given a set of report fields, return the field that refers to title
*/
function getTitleReportField(reportFields: PolicyReportFields) {
return Object.values(reportFields).find((field) => isReportFieldOfTypeTitle(field));
}

/**
* Get the report fields attached to the policy given policyID
*/
Expand Down Expand Up @@ -2854,6 +2862,38 @@ function buildOptimisticIOUReport(payeeAccountID: number, payerAccountID: number
};
}

function getHumanReadableStatus(statusNum: number): string {
const status = Object.keys(CONST.REPORT.STATUS_NUM).find((key) => CONST.REPORT.STATUS_NUM[key as keyof typeof CONST.REPORT.STATUS_NUM] === statusNum);
return status ? `${status.charAt(0)}${status.slice(1).toLowerCase()}` : '';
}

/**
* Populates the report field formula with the values from the report and policy.
* Currently, this only supports optimistic expense reports.
* Each formula field is either replaced with a value, or removed.
* If after all replacements the formula is empty, the original formula is returned.
* See {@link https://help.expensify.com/articles/expensify-classic/insights-and-custom-reporting/Custom-Templates}
*/
function populateOptimisticReportFormula(formula: string, report: OptimisticExpenseReport, policy: Policy | EmptyObject): string {
const createdDate = report.lastVisibleActionCreated ? new Date(report.lastVisibleActionCreated) : undefined;
const result = formula
.replaceAll('{report:id}', report.reportID)
// We don't translate because the server response is always in English
.replaceAll('{report:type}', 'Expense Report')
.replaceAll('{report:startdate}', createdDate ? format(createdDate, CONST.DATE.FNS_FORMAT_STRING) : '')
.replaceAll('{report:total}', report.total?.toString() ?? '')
.replaceAll('{report:currency}', report.currency ?? '')
.replaceAll('{report:policyname}', policy.name ?? '')
.replaceAll('{report:created}', createdDate ? format(createdDate, CONST.DATE.FNS_DATE_TIME_FORMAT_STRING) : '')
.replaceAll('{report:created:yyyy-MM-dd}', createdDate ? format(createdDate, CONST.DATE.FNS_FORMAT_STRING) : '')
.replaceAll('{report:status}', report.statusNum !== undefined ? getHumanReadableStatus(report.statusNum) : '')
.replaceAll('{user:email}', currentUserEmail ?? '')
.replaceAll('{user:email|frontPart}', currentUserEmail ? currentUserEmail.split('@')[0] : '')
.replaceAll(/\{report:(.+)}/g, '');

return result.trim().length ? result : formula;
}

/**
* Builds an optimistic Expense report with a randomly generated reportID
*
Expand All @@ -2863,7 +2903,6 @@ function buildOptimisticIOUReport(payeeAccountID: number, payerAccountID: number
* @param total - Amount in cents
* @param currency
*/

function buildOptimisticExpenseReport(chatReportID: string, policyID: string, payeeAccountID: number, total: number, currency: string): OptimisticExpenseReport {
// The amount for Expense reports are stored as negative value in the database
const storedTotal = total * -1;
Expand All @@ -2884,7 +2923,6 @@ function buildOptimisticExpenseReport(chatReportID: string, policyID: string, pa
type: CONST.REPORT.TYPE.EXPENSE,
ownerAccountID: payeeAccountID,
currency,

// We don't translate reportName because the server response is always in English
reportName: `${policyName} owes ${formattedTotal}`,
stateNum,
Expand All @@ -2900,6 +2938,11 @@ function buildOptimisticExpenseReport(chatReportID: string, policyID: string, pa
expenseReport.managerID = policy.submitsTo;
}

const titleReportField = getTitleReportField(getReportFieldsByPolicyID(policyID) ?? {});
if (!!titleReportField && reportFieldsEnabled(expenseReport)) {
expenseReport.reportName = populateOptimisticReportFormula(titleReportField.defaultValue, expenseReport, policy);
}

return expenseReport;
}

Expand Down

0 comments on commit 85c7119

Please sign in to comment.