Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated total amount when change the different currency #35880

Merged
merged 16 commits into from
Feb 16, 2024
Merged
13 changes: 11 additions & 2 deletions src/libs/IOUUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,18 @@ function calculateAmount(numberOfParticipants: number, total: number, currency:
* If user1 requests $17 from user2, then we have: {ownerAccountID: user1, managerID: user2, total: $7 (still a positive amount, but now owed to user1)}
*
* @param isDeleting - whether the user is deleting the request
* @param isUpdating - whether the user is updating the request
*/
function updateIOUOwnerAndTotal<TReport extends OnyxEntry<Report>>(iouReport: TReport, actorAccountID: number, amount: number, currency: string, isDeleting = false): TReport {
if (currency !== iouReport?.currency) {
function updateIOUOwnerAndTotal<TReport extends OnyxEntry<Report>>(
iouReport: TReport,
actorAccountID: number,
amount: number,
currency: string,
isDeleting = false,
isUpdating = false,
): TReport {
// For the update case, we have calculated the diff amount in the calculateDiffAmount function so there is no need to compare currencies here
if ((currency !== iouReport?.currency && !isUpdating) || !iouReport) {
return iouReport;
}

Expand Down
59 changes: 41 additions & 18 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,36 @@ function createDistanceRequest(
Report.notifyNewAction(chatReport.reportID, userAccountID);
}

/**
* Compute the diff amount when we update the transaction
*/
function calculateDiffAmount(iouReport: OnyxEntry<OnyxTypes.Report>, updatedTransaction: OnyxEntry<OnyxTypes.Transaction>, transaction: OnyxEntry<OnyxTypes.Transaction>): number {
if (!iouReport) {
return 0;
}
const isExpenseReport = ReportUtils.isExpenseReport(iouReport);
const updatedCurrency = TransactionUtils.getCurrency(updatedTransaction);
const currentCurrency = TransactionUtils.getCurrency(transaction);

const currentAmount = TransactionUtils.getAmount(transaction, isExpenseReport);
const updatedAmount = TransactionUtils.getAmount(updatedTransaction, isExpenseReport);

if (updatedCurrency === iouReport?.currency && currentCurrency !== iouReport?.currency) {
// Add the diff to the total if we change the currency from a different currency to the currency of the IOU report
return updatedAmount;
}
if (updatedCurrency !== iouReport?.currency && currentCurrency === iouReport?.currency) {
// Subtract the diff from the total if we change the currency from the currency of IOU report to a different currency
return -updatedAmount;
}
if (updatedCurrency === iouReport?.currency && updatedTransaction?.modifiedAmount) {
// Calculate the diff between the updated amount and the current amount if we change the amount and the currency of the transaction is the currency of the report
return updatedAmount - currentAmount;
}

return 0;
}

/**
* @param transactionID
* @param transactionThreadReportID
Expand Down Expand Up @@ -1098,23 +1128,21 @@ function getUpdateMoneyRequestParams(
},
},
});
}

// Step 4: Compute the IOU total and update the report preview message (and report header) so LHN amount owed is correct.
// Should only update if the transaction matches the currency of the report, else we wait for the update
// from the server with the currency conversion
let updatedMoneyRequestReport = {...iouReport};
if ((hasPendingWaypoints || updatedTransaction?.modifiedAmount) && updatedTransaction?.currency === iouReport?.currency) {
const diff = TransactionUtils.getAmount(transaction, true) - TransactionUtils.getAmount(updatedTransaction, true);
// Step 4: Compute the IOU total and update the report preview message (and report header) so LHN amount owed is correct.
let updatedMoneyRequestReport = {...iouReport};
const diff = calculateDiffAmount(iouReport, updatedTransaction, transaction);

if (ReportUtils.isExpenseReport(iouReport) && typeof updatedMoneyRequestReport.total === 'number') {
updatedMoneyRequestReport.total += diff;
// For expense report, the amount is negative so we should subtract total from diff
updatedMoneyRequestReport.total -= diff;
} else {
updatedMoneyRequestReport = iouReport
? IOUUtils.updateIOUOwnerAndTotal(iouReport, updatedReportAction.actorAccountID ?? -1, diff, TransactionUtils.getCurrency(transaction), false)
? IOUUtils.updateIOUOwnerAndTotal(iouReport, updatedReportAction.actorAccountID ?? -1, diff, TransactionUtils.getCurrency(transaction), false, true)
: {};
}
updatedMoneyRequestReport.cachedTotal = CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedTransaction?.modifiedCurrency);

updatedMoneyRequestReport.cachedTotal = CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedTransaction?.currency);
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
Expand Down Expand Up @@ -2782,23 +2810,18 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor

// STEP 4: Update the iouReport and reportPreview with new totals and messages if it wasn't deleted
let updatedIOUReport: OnyxTypes.Report | null;
const currency = TransactionUtils.getCurrency(transaction);
const updatedReportPreviewAction: OnyxTypes.ReportAction | EmptyObject = {...reportPreviewAction};
updatedReportPreviewAction.pendingAction = shouldDeleteIOUReport ? CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE : CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE;
if (iouReport && ReportUtils.isExpenseReport(iouReport)) {
updatedIOUReport = {...iouReport};

if (typeof updatedIOUReport.total === 'number') {
if (typeof updatedIOUReport.total === 'number' && currency === iouReport?.currency) {
// Because of the Expense reports are stored as negative values, we add the total from the amount
updatedIOUReport.total += TransactionUtils.getAmount(transaction, true);
}
} else {
updatedIOUReport = IOUUtils.updateIOUOwnerAndTotal(
iouReport,
reportAction.actorAccountID ?? -1,
TransactionUtils.getAmount(transaction, false),
TransactionUtils.getCurrency(transaction),
true,
);
updatedIOUReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, reportAction.actorAccountID ?? -1, TransactionUtils.getAmount(transaction, false), currency, true);
}

if (updatedIOUReport) {
Expand Down
Loading