Skip to content

Commit

Permalink
Merge pull request #52197 from paultsimura/fix/49278-pending-refactor
Browse files Browse the repository at this point in the history
fix: 0.00 for Pending... @1.00 / mi
  • Loading branch information
francoisl authored Nov 11, 2024
2 parents 9d8571b + 139154c commit 3967e86
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 770 deletions.
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 @@ -3709,12 +3709,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 @@ -249,7 +249,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 @@ -281,7 +293,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 @@ -290,20 +324,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 @@ -861,49 +913,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 @@ -1216,7 +1225,6 @@ function buildTransactionsMergeParams(reviewDuplicates: OnyxEntry<ReviewDuplicat
export {
buildOptimisticTransaction,
calculateTaxAmount,
calculateAmountForUpdatedWaypointOrRate,
getWorkspaceTaxesSettingsName,
getDefaultTaxCode,
transformedTaxRates,
Expand Down
Loading

0 comments on commit 3967e86

Please sign in to comment.