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

Feat: update the report when a payment is refunded #29344

Merged
merged 27 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fd857e7
Feat: update the report when a payment is refunded
getusha Oct 11, 2023
2b33b90
run prettier
getusha Oct 11, 2023
0aac629
prevent crash by checking key existence
getusha Oct 11, 2023
d29b2b9
Merge remote-tracking branch 'expensify/main' into upgrade-react-nati…
getusha Oct 11, 2023
b7986d4
Add es translations
getusha Oct 11, 2023
444b732
use report action value
getusha Oct 11, 2023
89b7bd5
Merge remote-tracking branch 'expensify/main' into feat-payment-expir…
getusha Oct 12, 2023
5d3ef6a
Merge remote-tracking branch 'expensify/main' into feat-payment-expir…
getusha Oct 17, 2023
99d4202
use props.report value for amount and name
getusha Oct 17, 2023
c4f921f
Merge remote-tracking branch 'expensify/main' into feat-payment-expir…
getusha Nov 10, 2023
839326e
update 'reason' to 'cancellationReason'
getusha Nov 10, 2023
f2c59f3
remove usage of report.ownerEmail and add condition for canceled case
getusha Nov 10, 2023
0b1f90b
fix lint
getusha Nov 10, 2023
a4013f1
run prettier
getusha Nov 10, 2023
97d8c5e
lint!
getusha Nov 10, 2023
2f0af0c
fix crash
getusha Nov 13, 2023
ef72ec7
run prettier
getusha Nov 13, 2023
6b78581
add type in OriginalMessage for Dequeued action
getusha Nov 28, 2023
899ee0a
update report preview based on dequeued action
getusha Nov 28, 2023
0e3887f
Merge remote-tracking branch 'expensify/main' into feat-payment-expir…
getusha Nov 28, 2023
40b9818
missed condition
getusha Nov 28, 2023
8cccd75
run prettier
getusha Nov 28, 2023
d5c4dbe
add condition to handle canceled case
getusha Nov 28, 2023
30f43e4
lint!
getusha Nov 28, 2023
2bbd0ef
fix LHN last message text preview
getusha Nov 28, 2023
555ddcb
use isCancelledIOU and remove redundant function
getusha Nov 30, 2023
75ad8c4
run prettier
getusha Nov 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ const CONST = {
MODIFIEDEXPENSE: 'MODIFIEDEXPENSE',
MOVED: 'MOVED',
REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED',
REIMBURSEMENTDEQUEUED: 'REIMBURSEMENTDEQUEUED',
RENAMED: 'RENAMED',
REPORTPREVIEW: 'REPORTPREVIEW',
SUBMITTED: 'SUBMITTED',
Expand Down Expand Up @@ -1155,6 +1156,9 @@ const CONST = {
SVG: 'svg',
},
RECEIPT_ERROR: 'receiptError',
CANCEL_REASON: {
PAYMENT_EXPIRED: 'CANCEL_REASON_PAYMENT_EXPIRED',
},
},

GROWL: {
Expand Down
5 changes: 4 additions & 1 deletion src/components/ReportActionItem/MoneyRequestPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ function MoneyRequestPreview(props) {
const isDistanceRequest = TransactionUtils.isDistanceRequest(props.transaction);
const isExpensifyCardTransaction = TransactionUtils.isExpensifyCardTransaction(props.transaction);
const isSettled = ReportUtils.isSettled(props.iouReport.reportID);
const isCancelled = ReportActionsUtils.isReimbursementDeQueued(props.iouReport.reportID);
const isDeleted = lodashGet(props.action, 'pendingAction', null) === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;

// Show the merchant for IOUs and expenses only if they are custom or not related to scanning smartscan
Expand Down Expand Up @@ -220,6 +221,8 @@ function MoneyRequestPreview(props) {
message += ` • ${props.translate('iou.approved')}`;
} else if (props.iouReport.isWaitingOnBankAccount) {
message += ` • ${props.translate('iou.pending')}`;
} else if (isCancelled) {
message += ` • ${props.translate('iou.canceled')}`;
}
return message;
};
Expand Down Expand Up @@ -280,7 +283,7 @@ function MoneyRequestPreview(props) {
<View style={styles.moneyRequestPreviewBoxText}>
<View style={[styles.flexRow]}>
<Text style={[styles.textLabelSupporting, styles.flex1, styles.lh20, styles.mb1]}>
{getPreviewHeaderText() + (isSettled ? ` • ${getSettledMessage()}` : '')}
{getPreviewHeaderText() + (isSettled && !isCancelled ? ` • ${getSettledMessage()}` : '')}
</Text>
{hasFieldErrors && (
<Icon
Expand Down
8 changes: 7 additions & 1 deletion src/components/ReportActionItem/MoneyRequestView.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ function MoneyRequestView({report, parentReport, policyCategories, shouldShowHor

// Flags for allowing or disallowing editing a money request
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);
const isCancelled = ReportActionsUtils.isReimbursementDeQueued(moneyRequestReport.reportID);
const canEdit = ReportUtils.canEditMoneyRequest(parentReportAction);
const canEditAmount = canEdit && !isSettled && !isCardTransaction;

Expand All @@ -133,11 +134,16 @@ function MoneyRequestView({report, parentReport, policyCategories, shouldShowHor
if (TransactionUtils.isPending(transaction)) {
amountDescription += ` • ${translate('iou.pending')}`;
}
if (isCancelled) {
amountDescription += ` • ${translate('iou.canceled')}`;
}
} else {
if (!isDistanceRequest) {
amountDescription += ` • ${translate('iou.cash')}`;
}
if (isSettled) {
if (isCancelled) {
amountDescription += ` • ${translate('iou.canceled')}`;
} else if (isSettled) {
amountDescription += ` • ${translate('iou.settledExpensify')}`;
} else if (report.isWaitingOnBankAccount) {
amountDescription += ` • ${translate('iou.pending')}`;
Expand Down
4 changes: 4 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
BeginningOfChatHistoryAnnounceRoomPartOneParams,
BeginningOfChatHistoryAnnounceRoomPartTwo,
BeginningOfChatHistoryDomainRoomPartOneParams,
CanceledRequestParams,
CharacterLimitParams,
ConfirmThatParams,
DateShouldBeAfterParams,
Expand Down Expand Up @@ -542,6 +543,7 @@ export default {
pay: 'Pay',
viewDetails: 'View details',
pending: 'Pending',
canceled: 'Canceled',
posted: 'Posted',
deleteReceipt: 'Delete receipt',
receiptScanning: 'Receipt scan in progress…',
Expand Down Expand Up @@ -572,6 +574,8 @@ export default {
managerApproved: ({manager}: ManagerApprovedParams) => `${manager} approved:`,
payerSettled: ({amount}: PayerSettledParams) => `paid ${amount}`,
waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `started settling up, payment is held until ${submitterDisplayName} adds a bank account`,
canceledRequest: ({amount, submitterDisplayName}: CanceledRequestParams) =>
`Canceled the ${amount} payment, because ${submitterDisplayName} did not enable their Expensify Wallet within 30 days`,
settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) =>
`${submitterDisplayName} added a bank account. The ${amount} payment has been made.`,
paidElsewhereWithAmount: ({payer, amount}: PaidElsewhereWithAmountParams) => `${payer} paid ${amount} elsewhere`,
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
BeginningOfChatHistoryAnnounceRoomPartOneParams,
BeginningOfChatHistoryAnnounceRoomPartTwo,
BeginningOfChatHistoryDomainRoomPartOneParams,
CanceledRequestParams,
CharacterLimitParams,
ConfirmThatParams,
DateShouldBeAfterParams,
Expand Down Expand Up @@ -534,6 +535,7 @@ export default {
pay: 'Pagar',
viewDetails: 'Ver detalles',
pending: 'Pendiente',
canceled: 'Canceló',
posted: 'Contabilizado',
deleteReceipt: 'Eliminar recibo',
receiptScanning: 'Escaneo de recibo en curso…',
Expand Down Expand Up @@ -564,6 +566,8 @@ export default {
managerApproved: ({manager}: ManagerApprovedParams) => `${manager} aprobó:`,
payerSettled: ({amount}: PayerSettledParams) => `pagó ${amount}`,
waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} añada una cuenta bancaria`,
canceledRequest: ({amount, submitterDisplayName}: CanceledRequestParams) =>
`Canceló el pago ${amount}, porque ${submitterDisplayName} no habilitó su billetera Expensify en un plazo de 30 días.`,
settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) =>
`${submitterDisplayName} añadió una cuenta bancaria. El pago de ${amount} se ha realizado.`,
paidElsewhereWithAmount: ({payer, amount}: PaidElsewhereWithAmountParams) => `${payer} pagó ${amount} de otra forma`,
Expand Down
3 changes: 3 additions & 0 deletions src/languages/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ type PayerSettledParams = {amount: number | string};

type WaitingOnBankAccountParams = {submitterDisplayName: string};

type CanceledRequestParams = {amount: string; submitterDisplayName: string};

type SettledAfterAddedBankAccountParams = {submitterDisplayName: string; amount: string};
Comment on lines +128 to 130
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two types are the same, can we merged them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertKozik

type RequestAmountParams = {amount: number};

type AmountEachParams = {amount: number};

type SplitAmountParams = {amount: number};

there are a lot of duplicate types, don't you think its better to keep it for its clear naming? if we want to add another param it'll be easier since we have types for each function, if not what should we name the type after combining it as one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, makes sense, lets keep it as it is


type PaidElsewhereWithAmountParams = {payer: string; amount: string};
Expand Down Expand Up @@ -282,6 +284,7 @@ export type {
ManagerApprovedParams,
PayerSettledParams,
WaitingOnBankAccountParams,
CanceledRequestParams,
SettledAfterAddedBankAccountParams,
PaidElsewhereWithAmountParams,
PaidWithExpensifyWithAmountParams,
Expand Down
2 changes: 2 additions & 0 deletions src/libs/OptionsListUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ function getLastMessageTextForReport(report) {
lastMessageTextFromReport = ReportUtils.getReportPreviewMessage(iouReport, lastIOUMoneyReport, true, ReportUtils.isChatReport(report));
} else if (ReportActionUtils.isReimbursementQueuedAction(lastReportAction)) {
lastMessageTextFromReport = ReportUtils.getReimbursementQueuedActionMessage(lastReportAction, report);
} else if (ReportActionUtils.isReimbursementDeQueuedAction(lastReportAction)) {
lastMessageTextFromReport = ReportUtils.getReimbursementDeQueuedActionMessage(report);
} else if (ReportActionUtils.isDeletedParentAction(lastReportAction) && ReportUtils.isChatReport(report)) {
lastMessageTextFromReport = ReportUtils.getDeletedParentActionMessageForChatReport(lastReportAction);
} else if (ReportUtils.isReportMessageAttachment({text: report.lastMessageText, html: report.lastMessageHtml, translationKey: report.lastMessageTranslationKey})) {
Expand Down
18 changes: 18 additions & 0 deletions src/libs/ReportActionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,22 @@ function isChannelLogMemberAction(reportAction: OnyxEntry<ReportAction>) {
);
}

/**
* Returns whether the report is dequeued only using reportID
*/
function isReimbursementDeQueued(reportID: string): boolean {
if (!allReportActions) {
return false;
}

const reportAction = Object.values(allReportActions[`${reportID}`] ?? {});
getusha marked this conversation as resolved.
Show resolved Hide resolved
return reportAction.some((action) => action?.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTDEQUEUED);
}

function isReimbursementDeQueuedAction(reportAction: OnyxEntry<ReportAction>): boolean {
return reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTDEQUEUED;
}

/**
* Returns whether the comment is a thread parent message/the first message in a thread
*/
Expand Down Expand Up @@ -698,6 +714,8 @@ export {
hasRequestFromCurrentAccount,
getFirstVisibleReportActionID,
isChannelLogMemberAction,
isReimbursementDeQueued,
isReimbursementDeQueuedAction,
};

export type {LastVisibleMessage};
15 changes: 15 additions & 0 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,16 @@ function getReimbursementQueuedActionMessage(reportAction: OnyxEntry<ReportActio
return Localize.translateLocal(messageKey, {submitterDisplayName});
}

/**
* Returns the preview message for `REIMBURSEMENTDEQUEUED` action
*/
function getReimbursementDeQueuedActionMessage(report: OnyxEntry<Report>): string {
const submitterDisplayName = getDisplayNameForParticipant(report?.ownerAccountID, true) ?? '';
const amount = CurrencyUtils.convertToDisplayString(report?.total ?? 0, report?.currency);

return Localize.translateLocal('iou.canceledRequest', {submitterDisplayName, amount});
}

/**
* Returns the last visible message for a given report after considering the given optimistic actions
*
Expand Down Expand Up @@ -1684,6 +1694,10 @@ function getMoneyRequestReportName(report: OnyxEntry<Report>, policy: OnyxEntry<
return `${payerPaidAmountMessage} • ${Localize.translateLocal('iou.pending')}`;
}

if (report?.reportID && ReportActionsUtils.isReimbursementDeQueued(report.reportID)) {
return `${payerPaidAmountMessage} • ${Localize.translateLocal('iou.canceled')}`;
}

if (hasNonReimbursableTransactions(report?.reportID)) {
return Localize.translateLocal('iou.payerSpentAmount', {payer: payerName, amount: formattedAmount});
}
Expand Down Expand Up @@ -4376,6 +4390,7 @@ export {
shouldUseFullTitleToDisplay,
parseReportRouteParams,
getReimbursementQueuedActionMessage,
getReimbursementDeQueuedActionMessage,
getPersonalDetailsForAccountID,
getChannelLogMemberMessage,
getRoom,
Expand Down
6 changes: 6 additions & 0 deletions src/pages/home/report/ReportActionItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withW
import usePrevious from '@hooks/usePrevious';
import compose from '@libs/compose';
import ControlSelection from '@libs/ControlSelection';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import focusTextInputAfterAnimation from '@libs/focusTextInputAfterAnimation';
import Navigation from '@libs/Navigation/Navigation';
Expand Down Expand Up @@ -413,6 +414,11 @@ function ReportActionItem(props) {
</>
</ReportActionItemBasicMessage>
);
} else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTDEQUEUED) {
const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails, [props.report.ownerAccountID, 'displayName']);
const amount = CurrencyUtils.convertToDisplayString(props.report.total, props.report.currency);

children = <ReportActionItemBasicMessage message={props.translate('iou.canceledRequest', {submitterDisplayName, amount})} />;
} else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE) {
children = <ReportActionItemBasicMessage message={ReportUtils.getModifiedExpenseMessage(props.action)} />;
} else {
Expand Down
6 changes: 6 additions & 0 deletions src/types/onyx/OriginalMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ type OriginalMessageReimbursementQueued = {
originalMessage: unknown;
};

type OriginalMessageReimbursementDequeued = {
actionName: typeof CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTDEQUEUED;
originalMessage: unknown;
};

type OriginalMessageMoved = {
actionName: typeof CONST.REPORT.ACTIONS.TYPE.MOVED;
originalMessage: {
Expand All @@ -220,6 +225,7 @@ type OriginalMessage =
| OriginalMessagePolicyTask
| OriginalMessageModifiedExpense
| OriginalMessageReimbursementQueued
| OriginalMessageReimbursementDequeued
| OriginalMessageMoved;

export default OriginalMessage;
Expand Down
Loading