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

fix: 0.00 for Pending... @1.00 / mi #52197

Merged
merged 10 commits into from
Nov 11, 2024
3 changes: 2 additions & 1 deletion src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,9 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
let amountDescription = `${translate('iou.amount')}`;

const hasRoute = TransactionUtils.hasRoute(transactionBackup ?? transaction, isDistanceRequest);
const {unit, rate, currency} = DistanceRequestUtils.getRate({transaction, policy});
const {unit, rate} = DistanceRequestUtils.getRate({transaction, policy});
const distance = TransactionUtils.getDistanceInMeters(transactionBackup ?? transaction, unit);
const currency = transactionCurrency ?? CONST.CURRENCY.USD;
const rateToDisplay = DistanceRequestUtils.getRateForDisplay(unit, rate, currency, translate, toLocaleDigit, isOffline);
const distanceToDisplay = DistanceRequestUtils.getDistanceForDisplay(hasRoute, distance, unit, rate, translate);
let merchantTitle = isEmptyMerchant ? '' : transactionMerchant;
Expand Down
14 changes: 0 additions & 14 deletions src/libs/API/parameters/EditMoneyRequestParams.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ export type {default as StartSplitBillParams} from './StartSplitBillParams';
export type {default as SendMoneyParams} from './SendMoneyParams';
export type {default as ApproveMoneyRequestParams} from './ApproveMoneyRequestParams';
export type {default as UnapproveExpenseReportParams} from './UnapproveExpenseReportParams';
export type {default as EditMoneyRequestParams} from './EditMoneyRequestParams';
export type {default as ReplaceReceiptParams} from './ReplaceReceiptParams';
export type {default as SubmitReportParams} from './SubmitReportParams';
export type {default as DetachReceiptParams} from './DetachReceiptParams';
Expand Down
4 changes: 0 additions & 4 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ const WRITE_COMMANDS = {
HOLD_MONEY_REQUEST: 'HoldRequest',
UPDATE_BILLING_CARD_CURRENCY: 'UpdateBillingCardCurrency',
UNHOLD_MONEY_REQUEST: 'UnHoldRequest',
UPDATE_DISTANCE_REQUEST: 'UpdateDistanceRequest',
REQUEST_MONEY: 'RequestMoney',
SPLIT_BILL: 'SplitBill',
SPLIT_BILL_AND_OPEN_REPORT: 'SplitBillAndOpenReport',
Expand All @@ -203,7 +202,6 @@ const WRITE_COMMANDS = {
SEND_MONEY_WITH_WALLET: 'SendMoneyWithWallet',
APPROVE_MONEY_REQUEST: 'ApproveMoneyRequest',
UNAPPROVE_EXPENSE_REPORT: 'UnapproveExpenseReport',
EDIT_MONEY_REQUEST: 'EditMoneyRequest',
REPLACE_RECEIPT: 'ReplaceReceipt',
SUBMIT_REPORT: 'SubmitReport',
DETACH_RECEIPT: 'DetachReceipt',
Expand Down Expand Up @@ -616,7 +614,6 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.HOLD_MONEY_REQUEST]: Parameters.HoldMoneyRequestParams;
[WRITE_COMMANDS.UNHOLD_MONEY_REQUEST]: Parameters.UnHoldMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_DISTANCE_REQUEST]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.REQUEST_MONEY]: Parameters.RequestMoneyParams;
[WRITE_COMMANDS.SPLIT_BILL]: Parameters.SplitBillParams;
Expand All @@ -628,7 +625,6 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.SEND_MONEY_WITH_WALLET]: Parameters.SendMoneyParams;
[WRITE_COMMANDS.APPROVE_MONEY_REQUEST]: Parameters.ApproveMoneyRequestParams;
[WRITE_COMMANDS.UNAPPROVE_EXPENSE_REPORT]: Parameters.UnapproveExpenseReportParams;
[WRITE_COMMANDS.EDIT_MONEY_REQUEST]: Parameters.EditMoneyRequestParams;
[WRITE_COMMANDS.REPLACE_RECEIPT]: Parameters.ReplaceReceiptParams;
[WRITE_COMMANDS.SUBMIT_REPORT]: Parameters.SubmitReportParams;
[WRITE_COMMANDS.DETACH_RECEIPT]: Parameters.DetachReceiptParams;
Expand Down
9 changes: 9 additions & 0 deletions src/libs/DistanceRequestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,14 @@ function getUpdatedDistanceUnit({transaction, policy, policyDraft}: {transaction
return getRate({transaction, policy, policyDraft, useTransactionDistanceUnit: false}).unit;
}

/**
* Get the mileage rate by its ID in the form it's configured for the policy.
* If not found, return undefined.
*/
function getRateByCustomUnitRateID({customUnitRateID, policy}: {customUnitRateID: string; policy: OnyxEntry<Policy>}): MileageRate | undefined {
return getMileageRates(policy, true, customUnitRateID)[customUnitRateID];
}

export default {
getDefaultMileageRate,
getDistanceMerchant,
Expand All @@ -378,6 +386,7 @@ export default {
getDistanceUnit,
getUpdatedDistanceUnit,
getRate,
getRateByCustomUnitRateID,
};

export type {MileageRate};
8 changes: 3 additions & 5 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3702,12 +3702,10 @@ function getModifiedExpenseOriginalMessage(
originalMessage.oldCurrency = TransactionUtils.getCurrency(oldTransaction);
originalMessage.oldMerchant = TransactionUtils.getMerchant(oldTransaction);

const modifiedDistanceFields = TransactionUtils.calculateAmountForUpdatedWaypointOrRate(updatedTransaction, transactionChanges, policy, isFromExpenseReport);

// For the originalMessage, we should use the non-negative amount, similar to what TransactionUtils.getAmount does for oldAmount
originalMessage.amount = Math.abs(modifiedDistanceFields.modifiedAmount);
originalMessage.currency = modifiedDistanceFields.modifiedCurrency ?? CONST.CURRENCY.USD;
originalMessage.merchant = modifiedDistanceFields.modifiedMerchant;
originalMessage.amount = Math.abs(updatedTransaction.modifiedAmount ?? 0);
originalMessage.currency = updatedTransaction.modifiedCurrency ?? CONST.CURRENCY.USD;
originalMessage.merchant = updatedTransaction.modifiedMerchant;
}

return originalMessage;
Expand Down
108 changes: 58 additions & 50 deletions src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,19 @@ function areRequiredFieldsEmpty(transaction: OnyxEntry<Transaction>): boolean {
/**
* Given the edit made to the expense, return an updated transaction object.
*/
function getUpdatedTransaction(transaction: Transaction, transactionChanges: TransactionChanges, isFromExpenseReport: boolean, shouldUpdateReceiptState = true): Transaction {
function getUpdatedTransaction({
transaction,
transactionChanges,
isFromExpenseReport,
shouldUpdateReceiptState = true,
policy = undefined,
}: {
transaction: Transaction;
transactionChanges: TransactionChanges;
isFromExpenseReport: boolean;
shouldUpdateReceiptState?: boolean;
policy?: OnyxEntry<Policy>;
}): Transaction {
// Only changing the first level fields so no need for deep clone now
const updatedTransaction = lodashDeepClone(transaction);
let shouldStopSmartscan = false;
Expand Down Expand Up @@ -280,7 +292,29 @@ function getUpdatedTransaction(transaction: Transaction, transactionChanges: Tra

if (Object.hasOwn(transactionChanges, 'waypoints')) {
updatedTransaction.modifiedWaypoints = transactionChanges.waypoints;
updatedTransaction.isLoading = true;
shouldStopSmartscan = true;

if (!transactionChanges.routes?.route0?.geometry?.coordinates) {
// The waypoints were changed, but there is no route – it is pending from the BE and we should mark the fields as pending
updatedTransaction.amount = CONST.IOU.DEFAULT_AMOUNT;
updatedTransaction.modifiedAmount = CONST.IOU.DEFAULT_AMOUNT;
updatedTransaction.modifiedMerchant = Localize.translateLocal('iou.fieldPending');
} else {
const mileageRate = DistanceRequestUtils.getRate({transaction: updatedTransaction, policy});
const {unit, rate} = mileageRate;

const distanceInMeters = getDistanceInMeters(transaction, unit);
const amount = DistanceRequestUtils.getDistanceRequestAmount(distanceInMeters, unit, rate ?? 0);
const updatedAmount = isFromExpenseReport ? -amount : amount;
const updatedMerchant = DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, transaction.currency, Localize.translateLocal, (digit) =>
toLocaleDigit(preferredLocale, digit),
);

updatedTransaction.amount = updatedAmount;
updatedTransaction.modifiedAmount = updatedAmount;
updatedTransaction.modifiedMerchant = updatedMerchant;
}
}

if (Object.hasOwn(transactionChanges, 'customUnitRateID')) {
Expand All @@ -289,20 +323,38 @@ function getUpdatedTransaction(transaction: Transaction, transactionChanges: Tra
shouldStopSmartscan = true;

const existingDistanceUnit = transaction?.comment?.customUnit?.distanceUnit;
const allReports = ReportConnection.getAllReports();
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`] ?? null;
const policyID = report?.policyID ?? '';
const policy = PolicyUtils.getPolicy(policyID);

// Get the new distance unit from the rate's unit
const newDistanceUnit = DistanceRequestUtils.getUpdatedDistanceUnit({transaction: updatedTransaction, policy});
lodashSet(updatedTransaction, 'comment.customUnit.distanceUnit', newDistanceUnit);

// If the distanceUnit is set and the rate is changed to one that has a different unit, convert the distance to the new unit
if (existingDistanceUnit && newDistanceUnit !== existingDistanceUnit) {
const conversionFactor = existingDistanceUnit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? CONST.CUSTOM_UNITS.MILES_TO_KILOMETERS : CONST.CUSTOM_UNITS.KILOMETERS_TO_MILES;
const distance = NumberUtils.roundToTwoDecimalPlaces((transaction?.comment?.customUnit?.quantity ?? 0) * conversionFactor);
lodashSet(updatedTransaction, 'comment.customUnit.quantity', distance);
lodashSet(updatedTransaction, 'pendingFields.merchant', CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE);
}

if (!isFetchingWaypointsFromServer(transaction)) {
// When the waypoints are being fetched from the server, we have no information about the distance, and cannot recalculate the updated amount.
// Otherwise, recalculate the fields based on the new rate.

const oldMileageRate = DistanceRequestUtils.getRate({transaction, policy});
const updatedMileageRate = DistanceRequestUtils.getRate({transaction: updatedTransaction, policy, useTransactionDistanceUnit: false});
const {unit, rate} = updatedMileageRate;

const distanceInMeters = getDistanceInMeters(transaction, oldMileageRate?.unit);
const amount = DistanceRequestUtils.getDistanceRequestAmount(distanceInMeters, unit, rate ?? 0);
const updatedAmount = isFromExpenseReport ? -amount : amount;
const updatedCurrency = updatedMileageRate.currency ?? CONST.CURRENCY.USD;
const updatedMerchant = DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, updatedCurrency, Localize.translateLocal, (digit) =>
toLocaleDigit(preferredLocale, digit),
);

updatedTransaction.amount = updatedAmount;
updatedTransaction.modifiedAmount = updatedAmount;
updatedTransaction.modifiedMerchant = updatedMerchant;
updatedTransaction.modifiedCurrency = updatedCurrency;
}
}

Expand Down Expand Up @@ -860,49 +912,6 @@ function calculateTaxAmount(percentage: string, amount: number, currency: string
return parseFloat(taxAmount.toFixed(decimals));
}

/**
* Calculates updated amount, currency, and merchant for a distance request with modified waypoints or customUnitRateID
*/
function calculateAmountForUpdatedWaypointOrRate(
transaction: OnyxInputOrEntry<Transaction>,
transactionChanges: TransactionChanges,
policy: OnyxInputOrEntry<Policy>,
isFromExpenseReport: boolean,
) {
const hasModifiedRouteWithPendingWaypoints = !isEmptyObject(transactionChanges.waypoints) && isEmptyObject(transactionChanges?.routes?.route0?.geometry);
const hasModifiedRateWithPendingWaypoints = !!transactionChanges?.customUnitRateID && isFetchingWaypointsFromServer(transaction);
if (hasModifiedRouteWithPendingWaypoints || hasModifiedRateWithPendingWaypoints) {
return {
amount: CONST.IOU.DEFAULT_AMOUNT,
modifiedAmount: CONST.IOU.DEFAULT_AMOUNT,
modifiedMerchant: Localize.translateLocal('iou.fieldPending'),
};
}

const customUnitRateID = transactionChanges.customUnitRateID ?? getRateID(transaction) ?? '';
const mileageRates = DistanceRequestUtils.getMileageRates(policy, true);
const policyCurrency = policy?.outputCurrency ?? PolicyUtils.getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD;
const mileageRate = isCustomUnitRateIDForP2P(transaction)
? DistanceRequestUtils.getRateForP2P(policyCurrency, transaction ?? undefined)
: mileageRates?.[customUnitRateID] ?? DistanceRequestUtils.getDefaultMileageRate(policy);
const {unit, rate, currency} = mileageRate;

const distanceInMeters = getDistanceInMeters(transaction, unit);
const amount = DistanceRequestUtils.getDistanceRequestAmount(distanceInMeters, unit, rate ?? 0);
const updatedAmount = isFromExpenseReport ? -amount : amount;
const updatedCurrency = currency ?? CONST.CURRENCY.USD;
const updatedMerchant = DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, updatedCurrency, Localize.translateLocal, (digit) =>
toLocaleDigit(preferredLocale, digit),
);

return {
amount: updatedAmount,
modifiedAmount: updatedAmount,
modifiedMerchant: updatedMerchant,
modifiedCurrency: updatedCurrency,
};
}

/**
* Calculates count of all tax enabled options
*/
Expand Down Expand Up @@ -1215,7 +1224,6 @@ function buildTransactionsMergeParams(reviewDuplicates: OnyxEntry<ReviewDuplicat
export {
buildOptimisticTransaction,
calculateTaxAmount,
calculateAmountForUpdatedWaypointOrRate,
getWorkspaceTaxesSettingsName,
getDefaultTaxCode,
transformedTaxRates,
Expand Down
Loading
Loading