Skip to content

Commit

Permalink
Merge pull request #40711 from koko57/feat/36985-create-new-rate-fiel…
Browse files Browse the repository at this point in the history
…d-followups

[CP Staging] Feat/36985 create new rate field followups

(cherry picked from commit 7e5b436)
  • Loading branch information
neil-marcellini authored and OSBotify committed Apr 23, 2024
1 parent f601fa3 commit fa748ea
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 64 deletions.
5 changes: 1 addition & 4 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,6 @@ function MoneyRequestConfirmationList({
style={[styles.moneyRequestMenuItem]}
titleStyle={styles.flex1}
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams()))}
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
disabled={didConfirm}
// todo: handle edit for transaction while moving from track expense
interactive={!isReadOnly && !isMovingTransactionFromTrackExpense}
Expand All @@ -767,9 +766,7 @@ function MoneyRequestConfirmationList({
description={translate('common.distance')}
style={[styles.moneyRequestMenuItem]}
titleStyle={styles.flex1}
onPress={() =>
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams()))
}
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams()))}
disabled={didConfirm}
interactive={!isReadOnly}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ function MoneyRequestPreviewContent({
}

if (isFetchingWaypointsFromServer && !requestAmount) {
return translate('iou.routePending');
return translate('iou.fieldPending');
}

return CurrencyUtils.convertToDisplayString(requestAmount, requestCurrency);
Expand Down
29 changes: 19 additions & 10 deletions src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ type MoneyRequestViewOnyxPropsWithoutTransaction = {
/** The actions from the parent report */
parentReportActions: OnyxEntry<OnyxTypes.ReportActions>;

/** The rates for the policy */
rates: Record<string, MileageRate>;
/** The distance rates from the policy */
distanceRates: Record<string, MileageRate>;
};

type MoneyRequestViewPropsWithoutTransaction = MoneyRequestViewOnyxPropsWithoutTransaction & {
Expand All @@ -95,16 +95,17 @@ function MoneyRequestView({
policy,
transactionViolations,
shouldShowAnimatedBackground,
rates,
distanceRates,
}: MoneyRequestViewProps) {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {isOffline} = useNetwork();
const {isSmallScreenWidth} = useWindowDimensions();
const {translate, toLocaleDigit} = useLocalize();
const {canUseViolations, canUseP2PDistanceRequests} = usePermissions();
const parentReportAction = parentReportActions?.[report.parentReportActionID ?? ''] ?? null;
const isTrackExpense = ReportUtils.isTrackExpenseReport(report);
const {canUseViolations, canUseP2PDistanceRequests} = usePermissions(isTrackExpense ? CONST.IOU.TYPE.TRACK : undefined);
const moneyRequestReport = parentReport;
const {
created: transactionDate,
Expand Down Expand Up @@ -150,14 +151,20 @@ function MoneyRequestView({
const canEditMerchant = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.MERCHANT);
const canEditDate = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DATE);
const canEditReceipt = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT);
const canEditDistance = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE);
// TODO: remove the !isTrackExpense from this condition after this fix: https://github.com/Expensify/Expensify/issues/382786
const canEditDistance = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE) && !isTrackExpense;

// A flag for verifying that the current report is a sub-report of a workspace chat
// if the policy of the report is either Collect or Control, then this report must be tied to workspace chat
const isPolicyExpenseChat = ReportUtils.isGroupPolicy(report);

const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTagList), [policyTagList]);

<<<<<<< HEAD
=======
const iouType = isTrackExpense ? CONST.IOU.TYPE.TRACK : CONST.IOU.TYPE.SUBMIT;

>>>>>>> 7e5b436 (Merge pull request #40711 from koko57/feat/36985-create-new-rate-field-followups)
// Flags for showing categories and tags
// transactionCategory can be an empty string
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
Expand All @@ -183,10 +190,11 @@ function MoneyRequestView({

const currency = policy ? policy.outputCurrency : PolicyUtils.getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD;

const mileageRate = TransactionUtils.isCustomUnitRateIDForP2P(transaction) ? DistanceRequestUtils.getRateForP2P(currency) : rates[rateID as string] ?? {};
const {unit, rate} = mileageRate;
const mileageRate = TransactionUtils.isCustomUnitRateIDForP2P(transaction) ? DistanceRequestUtils.getRateForP2P(currency) : distanceRates[rateID as string] ?? {};
const {unit} = mileageRate;
const rate = (transaction?.comment?.customUnit?.defaultP2PRate as number) ?? mileageRate.rate;

const distance = DistanceRequestUtils.getDistanceFromMerchant(transactionMerchant, unit);
const distance = DistanceRequestUtils.convertToDistanceInMeters((transaction?.comment?.customUnit?.quantity as number) ?? 0, unit);
const rateToDisplay = DistanceRequestUtils.getRateForDisplay(unit, rate, currency, translate, toLocaleDigit, isOffline);
const distanceToDisplay = DistanceRequestUtils.getDistanceForDisplay(hasRoute, distance, unit, rate, translate);

Expand Down Expand Up @@ -280,7 +288,7 @@ function MoneyRequestView({
<OfflineWithFeedback pendingAction={getPendingFieldAction('waypoints')}>
<MenuItemWithTopDescription
description={translate('common.distance')}
title={distanceToDisplay}
title={getPendingFieldAction('waypoints') ? translate('iou.fieldPending') : distanceToDisplay}
interactive={canEditDistance}
shouldShowRightIcon={canEditDistance}
titleStyle={styles.flex1}
Expand All @@ -289,6 +297,7 @@ function MoneyRequestView({
}
/>
</OfflineWithFeedback>
{/* TODO: correct the pending field action https://github.com/Expensify/App/issues/36987 */}
<OfflineWithFeedback pendingAction={getPendingFieldAction('waypoints')}>
<MenuItemWithTopDescription
description={translate('common.rate')}
Expand Down Expand Up @@ -578,7 +587,7 @@ export default withOnyx<MoneyRequestViewPropsWithoutTransaction, MoneyRequestVie
key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report ? report.parentReportID : '0'}`,
canEvict: false,
},
rates: {
distanceRates: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`,
selector: DistanceRequestUtils.getMileageRates,
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReportActionItem/ReportPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ function ReportPreview({
return translate('iou.receiptScanning');
}
if (hasOnlyTransactionsWithPendingRoutes) {
return translate('iou.routePending');
return translate('iou.fieldPending');
}

// If iouReport is not available, get amount from the action message (Ex: "Domain20821's Workspace owes $33.00" or "paid ₫60" or "paid -₫60 elsewhere")
Expand Down
2 changes: 1 addition & 1 deletion src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ export default {
canceled: 'Canceled',
posted: 'Posted',
deleteReceipt: 'Delete receipt',
routePending: 'Pending...',
fieldPending: 'Pending...',
defaultRate: 'Default rate',
receiptScanning: 'Scan in progress…',
receiptMissingDetails: 'Receipt missing details',
Expand Down
2 changes: 1 addition & 1 deletion src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ export default {
canceled: 'Canceló',
posted: 'Contabilizado',
deleteReceipt: 'Eliminar recibo',
routePending: 'Pendiente...',
fieldPending: 'Pendiente...',
defaultRate: 'Tasa predeterminada',
receiptScanning: 'Escaneo en curso…',
receiptMissingDetails: 'Recibo con campos vacíos',
Expand Down
61 changes: 23 additions & 38 deletions src/libs/DistanceRequestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,6 @@ type MileageRate = {
name?: string;
};

const policies: OnyxCollection<Policy> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.POLICY,
callback: (policy, key) => {
if (!policy || !key || !policy.name) {
return;
}

policies[key] = policy;
},
});

let lastSelectedDistanceRates: OnyxEntry<LastSelectedDistanceRates> = {};
Onyx.connect({
key: ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES,
Expand Down Expand Up @@ -116,7 +104,7 @@ function getRoundedDistanceInUnits(distanceInMeters: number, unit: Unit): string
* @param currency The currency associated with the rate
* @param translate Translate function
* @param toLocaleDigit Function to convert to localized digit
* @returns A string that describes the distance traveled and the rate used for expense calculation
* @returns A string that displays the rate used for expense calculation
*/
function getRateForDisplay(
unit: Unit | undefined,
Expand All @@ -130,15 +118,15 @@ function getRateForDisplay(
return translate('iou.defaultRate');
}
if (!rate || !currency || !unit) {
return translate('iou.routePending');
return translate('iou.fieldPending');
}

const singularDistanceUnit = unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.mile') : translate('common.kilometer');
const ratePerUnit = PolicyUtils.getUnitRateValue(toLocaleDigit, {rate});
const formattedRate = PolicyUtils.getUnitRateValue(toLocaleDigit, {rate});
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const currencySymbol = CurrencyUtils.getCurrencySymbol(currency) || `${currency} `;

return `${currencySymbol}${ratePerUnit} / ${singularDistanceUnit}`;
return `${currencySymbol}${formattedRate} / ${singularDistanceUnit}`;
}

/**
Expand All @@ -150,8 +138,8 @@ function getRateForDisplay(
* @returns A string that describes the distance traveled
*/
function getDistanceForDisplay(hasRoute: boolean, distanceInMeters: number, unit: Unit | undefined, rate: number | undefined, translate: LocaleContextProps['translate']): string {
if (!hasRoute || !rate || !unit) {
return translate('iou.routePending');
if (!hasRoute || !rate || !unit || !distanceInMeters) {
return translate('iou.fieldPending');
}

const distanceInUnits = getRoundedDistanceInUnits(distanceInMeters, unit);
Expand Down Expand Up @@ -182,7 +170,7 @@ function getDistanceMerchant(
toLocaleDigit: LocaleContextProps['toLocaleDigit'],
): string {
if (!hasRoute || !rate) {
return translate('iou.routePending');
return translate('iou.fieldPending');
}

const distanceInUnits = getDistanceForDisplay(hasRoute, distanceInMeters, unit, rate, translate);
Expand All @@ -201,11 +189,7 @@ function getDistanceMerchant(
function getMileageRates(policy: OnyxEntry<Policy>): Record<string, MileageRate> {
const mileageRates: Record<string, MileageRate> = {};

if (!policy) {
return mileageRates;
}

if (!policy?.customUnits) {
if (!policy || !policy?.customUnits) {
return mileageRates;
}

Expand All @@ -227,6 +211,12 @@ function getMileageRates(policy: OnyxEntry<Policy>): Record<string, MileageRate>
return mileageRates;
}

/**
* Retrieves the rate and unit for a P2P distance expense for a given currency.
*
* @param currency
* @returns The rate and unit in RateAndUnit object.
*/
function getRateForP2P(currency: string): RateAndUnit {
return CONST.CURRENCY_TO_DEFAULT_MILEAGE_RATE[currency] ?? CONST.CURRENCY_TO_DEFAULT_MILEAGE_RATE.USD;
}
Expand All @@ -246,22 +236,17 @@ function getDistanceRequestAmount(distance: number, unit: Unit, rate: number): n
}

/**
* Extracts the distance from a merchant string.
* Converts the distance from kilometers or miles to meters.
*
* @param merchant - The merchant string containing the distance.
* @returns The distance extracted from the merchant string.
* @param distance - The distance to be converted.
* @param unit - The unit of measurement for the distance.
* @returns The distance in meters.
*/
function getDistanceFromMerchant(merchant: string | undefined, unit: Unit): number {
if (!merchant) {
return 0;
}

const distance = Number(merchant.split(' ')[0]);
if (!distance) {
return 0;
function convertToDistanceInMeters(distance: number, unit: Unit): number {
if (unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_KILOMETERS) {
return distance / METERS_TO_KM;
}
// we need to convert the distance back to meters (it's saved in kilometers or miles in merchant) to pass it to getDistanceForDisplay
return unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_KILOMETERS ? distance / METERS_TO_KM : distance / METERS_TO_MILES;
return distance / METERS_TO_MILES;
}

/**
Expand Down Expand Up @@ -289,8 +274,8 @@ export default {
getMileageRates,
getDistanceForDisplay,
getRateForP2P,
getDistanceFromMerchant,
getCustomUnitRateID,
convertToDistanceInMeters,
};

export type {MileageRate};
4 changes: 2 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2629,7 +2629,7 @@ function getTransactionReportName(reportAction: OnyxEntry<ReportAction | Optimis
}

if (TransactionUtils.isFetchingWaypointsFromServer(transaction)) {
return Localize.translateLocal('iou.routePending');
return Localize.translateLocal('iou.fieldPending');
}

if (TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction)) {
Expand Down Expand Up @@ -2742,7 +2742,7 @@ function getReportPreviewMessage(
}

if (!isEmptyObject(linkedTransaction) && TransactionUtils.isFetchingWaypointsFromServer(linkedTransaction) && !TransactionUtils.getAmount(linkedTransaction)) {
return Localize.translateLocal('iou.routePending');
return Localize.translateLocal('iou.fieldPending');
}

const originalMessage = iouReportAction?.originalMessage as IOUMessage | undefined;
Expand Down
4 changes: 2 additions & 2 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1857,7 +1857,7 @@ function getUpdateMoneyRequestParams(
...updatedTransaction,
amount: CONST.IOU.DEFAULT_AMOUNT,
modifiedAmount: CONST.IOU.DEFAULT_AMOUNT,
modifiedMerchant: Localize.translateLocal('iou.routePending'),
modifiedMerchant: Localize.translateLocal('iou.fieldPending'),
};

// Delete the draft transaction when editing waypoints when the server responds successfully and there are no errors
Expand Down Expand Up @@ -2135,7 +2135,7 @@ function getUpdateTrackExpenseParams(
...updatedTransaction,
amount: CONST.IOU.DEFAULT_AMOUNT,
modifiedAmount: CONST.IOU.DEFAULT_AMOUNT,
modifiedMerchant: Localize.translateLocal('iou.routePending'),
modifiedMerchant: Localize.translateLocal('iou.fieldPending'),
};

// Delete the draft transaction when editing waypoints when the server responds successfully and there are no errors
Expand Down
6 changes: 3 additions & 3 deletions src/pages/iou/request/step/IOURequestStepDistance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ function IOURequestStepDistance({
amount: 0,
comment: '',
currency: transaction?.currency ?? 'USD',
merchant: translate('iou.routePending'),
merchant: translate('iou.fieldPending'),
created: transaction?.created ?? '',
category: '',
tag: '',
Expand All @@ -242,7 +242,7 @@ function IOURequestStepDistance({
return;
}
IOU.setMoneyRequestPendingFields(transactionID, {waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD});
IOU.setMoneyRequestMerchant(transactionID, translate('iou.routePending'), false);
IOU.setMoneyRequestMerchant(transactionID, translate('iou.fieldPending'), false);
IOU.createDistanceRequest(
report,
participants[0],
Expand All @@ -252,7 +252,7 @@ function IOURequestStepDistance({
'',
0,
transaction?.currency ?? 'USD',
translate('iou.routePending'),
translate('iou.fieldPending'),
false,
TransactionUtils.getValidWaypoints(waypoints, true),
);
Expand Down
2 changes: 1 addition & 1 deletion src/pages/iou/request/step/IOURequestStepDistanceRate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function IOURequestStepDistanceRate({

const unit = (Object.values(rates)[0]?.unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.mile') : translate('common.kilometer')) as Unit;

const initiallyFocusedOption = rates[lastSelectedRateID]?.name ?? CONST.CUSTOM_UNITS.DEFAULT_RATE;
const initiallyFocusedOption = sections.find((item) => item.isSelected)?.keyForList;

function selectDistanceRate(customUnitRateID: string) {
IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? '');
Expand Down

0 comments on commit fa748ea

Please sign in to comment.