Skip to content

Commit d166392

Browse files
authored
Merge pull request Expensify#86174 from nabi-ebrahimi/feature/allow-received-reimbursement-option
Allow submitters to select "Received reimbursement" option
2 parents 33deff8 + 9f29e75 commit d166392

20 files changed

Lines changed: 465 additions & 9 deletions

src/CONST/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,7 @@ const CONST = {
13791379
SECONDARY_ACTIONS: {
13801380
SUBMIT: 'submit',
13811381
APPROVE: 'approve',
1382+
RECEIVED_PAYMENT: 'receivedPayment',
13821383
REMOVE_HOLD: 'removeHold',
13831384
UNAPPROVE: 'unapprove',
13841385
CANCEL_PAYMENT: 'cancelPayment',
@@ -9123,6 +9124,7 @@ const CONST = {
91239124
CLOSE_PDF_MODAL: 'MoreMenu-ClosePDFModal',
91249125
SUBMIT: 'MoreMenu-Submit',
91259126
APPROVE: 'MoreMenu-Approve',
9127+
RECEIVED_PAYMENT: 'MoreMenu-ReceivedPayment',
91269128
UNAPPROVE: 'MoreMenu-Unapprove',
91279129
CANCEL_PAYMENT: 'MoreMenu-CancelPayment',
91289130
HOLD: 'MoreMenu-Hold',

src/components/MoneyReportHeaderActions/MoneyReportHeaderSecondaryActions.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,10 @@ function MoneyReportHeaderSecondaryActionsInner({reportID, primaryAction, isRepo
273273
const lifecycleActions = useLifecycleActions({
274274
reportID,
275275
startApprovedAnimation,
276+
startAnimation,
276277
startSubmittingAnimation,
277-
onHoldMenuOpen: (requestType, onConfirm) => {
278-
openHoldMenu({requestType, onConfirm: onConfirm ?? (() => startApprovedAnimation())});
278+
onHoldMenuOpen: (requestType, onConfirm, paymentType) => {
279+
openHoldMenu({requestType, onConfirm: onConfirm ?? (() => startApprovedAnimation()), paymentType});
279280
},
280281
});
281282

src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,17 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
157157
const {confirmApproval, handleSubmitReport, shouldBlockSubmit, isBlockSubmitDueToPreventSelfApproval} = useLifecycleActions({
158158
reportID,
159159
startApprovedAnimation,
160+
startAnimation,
160161
startSubmittingAnimation,
161-
onHoldMenuOpen: (requestType) => openHoldMenu({requestType, onConfirm: () => clearSelectedTransactions(true)}),
162+
onHoldMenuOpen: (requestType, onConfirm, paymentType) =>
163+
openHoldMenu({
164+
requestType,
165+
onConfirm: () => {
166+
onConfirm?.();
167+
clearSelectedTransactions(true);
168+
},
169+
paymentType,
170+
}),
162171
});
163172

164173
const {

src/hooks/useLifecycleActions.tsx

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ import {
2020
shouldBlockSubmitDueToStrictPolicyRules,
2121
} from '@libs/ReportUtils';
2222
import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils} from '@libs/TransactionUtils';
23-
import {cancelPayment} from '@userActions/IOU/PayMoneyRequest';
23+
import {cancelPayment, markReportPaymentReceived} from '@userActions/IOU/PayMoneyRequest';
2424
import {approveMoneyRequest, reopenReport, retractReport, submitReport, unapproveExpenseReport} from '@userActions/IOU/ReportWorkflow';
2525
import {markPendingRTERTransactionsAsCash} from '@userActions/Transaction';
2626
import CONST from '@src/CONST';
2727
import ONYXKEYS from '@src/ONYXKEYS';
28+
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
2829
import useConfirmModal from './useConfirmModal';
2930
import useConfirmPendingRTERAndProceed from './useConfirmPendingRTERAndProceed';
3031
import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
@@ -42,8 +43,9 @@ import useTransactionsAndViolationsForReport from './useTransactionsAndViolation
4243
type UseLifecycleActionsParams = {
4344
reportID: string | undefined;
4445
startApprovedAnimation: () => void;
46+
startAnimation: () => void;
4547
startSubmittingAnimation: () => void;
46-
onHoldMenuOpen: (requestType: ActionHandledType, onConfirm?: () => void) => void;
48+
onHoldMenuOpen: (requestType: ActionHandledType, onConfirm?: () => void, paymentType?: PaymentMethodType) => void;
4749
};
4850

4951
type UseLifecycleActionsResult = {
@@ -58,7 +60,7 @@ type UseLifecycleActionsResult = {
5860
* Provides report lifecycle transition actions (submit, approve, unapprove, cancel payment, retract, reopen)
5961
* and their associated guards (delegate access, hold, pending RTER, strict policy rules).
6062
*/
61-
function useLifecycleActions({reportID, startApprovedAnimation, startSubmittingAnimation, onHoldMenuOpen}: UseLifecycleActionsParams): UseLifecycleActionsResult {
63+
function useLifecycleActions({reportID, startApprovedAnimation, startAnimation, startSubmittingAnimation, onHoldMenuOpen}: UseLifecycleActionsParams): UseLifecycleActionsResult {
6264
const [moneyRequestReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
6365
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(moneyRequestReport?.policyID)}`);
6466
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(moneyRequestReport?.chatReportID)}`);
@@ -95,7 +97,7 @@ function useLifecycleActions({reportID, startApprovedAnimation, startSubmittingA
9597
const {clearSelectedTransactions} = useSearchActionsContext();
9698
const shouldCalculateTotals = useSearchShouldCalculateTotals(currentSearchKey, currentSearchQueryJSON?.hash, true);
9799

98-
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Send', 'ThumbsUp', 'CircularArrowBackwards', 'Clear']);
100+
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Send', 'ThumbsUp', 'CircularArrowBackwards', 'Clear', 'MoneyBag']);
99101

100102
const nextApproverAccountID = getNextApproverAccountID(moneyRequestReport);
101103
const isSubmitterSameAsNextApprover =
@@ -251,6 +253,44 @@ function useLifecycleActions({reportID, startApprovedAnimation, startSubmittingA
251253
sentryLabel: CONST.SENTRY_LABEL.MORE_MENU.APPROVE,
252254
onSelected: confirmApproval,
253255
},
256+
[CONST.REPORT.SECONDARY_ACTIONS.RECEIVED_PAYMENT]: {
257+
value: CONST.REPORT.SECONDARY_ACTIONS.RECEIVED_PAYMENT,
258+
text: translate('iou.receivedPayment'),
259+
icon: expensifyIcons.MoneyBag,
260+
sentryLabel: CONST.SENTRY_LABEL.MORE_MENU.RECEIVED_PAYMENT,
261+
onSelected: async () => {
262+
if (isDelegateAccessRestricted) {
263+
showDelegateNoAccessModal();
264+
return;
265+
}
266+
267+
const result = await showConfirmModal({
268+
title: translate('iou.confirmPaymentReceivedModalTitle'),
269+
prompt: translate('iou.receivedPaymentConfirmation'),
270+
confirmText: translate('iou.confirmReceivedPayment'),
271+
cancelText: translate('common.cancel'),
272+
});
273+
274+
if (result.action !== ModalActions.CONFIRM) {
275+
return;
276+
}
277+
278+
if (isAnyTransactionOnHold) {
279+
onHoldMenuOpen(
280+
CONST.IOU.REPORT_ACTION_TYPE.PAY,
281+
() => {
282+
startAnimation();
283+
markReportPaymentReceived(chatReport, moneyRequestReport, nextStep);
284+
},
285+
CONST.IOU.PAYMENT_TYPE.ELSEWHERE,
286+
);
287+
return;
288+
}
289+
290+
startAnimation();
291+
markReportPaymentReceived(chatReport, moneyRequestReport, nextStep);
292+
},
293+
},
254294
[CONST.REPORT.SECONDARY_ACTIONS.UNAPPROVE]: {
255295
value: CONST.REPORT.SECONDARY_ACTIONS.UNAPPROVE,
256296
text: translate('iou.unapprove'),

src/languages/de.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,10 @@ const translations: TranslationDeepObject<typeof en> = {
13121312
settlePayment: (formattedAmount: string) => `${formattedAmount} bezahlen`,
13131313
settleBusiness: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} als Unternehmen bezahlen` : `Mit Geschäftskonto bezahlen`),
13141314
payElsewhere: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} als bezahlt markieren` : `Als bezahlt markieren`),
1315+
confirmPaymentReceivedModalTitle: 'Zahlungseingang bestätigen',
1316+
receivedPayment: 'Zahlung erhalten',
1317+
receivedPaymentConfirmation: 'Bitte fahren Sie nur fort, wenn Sie die Zahlung bereits außerhalb von Expensify erhalten haben.',
1318+
confirmReceivedPayment: 'Ja, ich habe die Zahlung erhalten.',
13151319
settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `${amount} mit persönlichem Konto ${last4Digits} bezahlt` : `Mit Privatkonto bezahlt`),
13161320
settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `${amount} mit Geschäftskonto ${last4Digits} bezahlt` : `Mit Geschäftskonto bezahlt`),
13171321
payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Bezahle ${formattedAmount} über ${policyName}` : `Bezahlen über ${policyName}`),

src/languages/en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,10 @@ const translations = {
13641364
settlePayment: (formattedAmount: string) => `Pay ${formattedAmount}`,
13651365
settleBusiness: (formattedAmount?: string) => (formattedAmount ? `Pay ${formattedAmount} as a business` : `Pay with business account`),
13661366
payElsewhere: (formattedAmount?: string) => (formattedAmount ? `Mark ${formattedAmount} as paid` : `Mark as paid`),
1367+
confirmPaymentReceivedModalTitle: 'Confirm payment received',
1368+
receivedPayment: 'Received payment',
1369+
receivedPaymentConfirmation: "Please proceed only if you've already received payment outside of Expensify.",
1370+
confirmReceivedPayment: "Yes, I've received payment",
13671371
settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `paid ${amount} with personal account ${last4Digits}` : `Paid with personal account`),
13681372
settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `paid ${amount} with business account ${last4Digits}` : `Paid with business account`),
13691373
payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Pay ${formattedAmount} via ${policyName}` : `Pay via ${policyName}`),

src/languages/es.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,10 @@ const translations: TranslationDeepObject<typeof en> = {
12641264
settlePayment: (formattedAmount) => `Pagar ${formattedAmount}`,
12651265
settleBusiness: (formattedAmount) => (formattedAmount ? `Pagar ${formattedAmount} como negocio` : `Pago con cuenta empresarial`),
12661266
payElsewhere: (formattedAmount) => (formattedAmount ? `Marcar ${formattedAmount} como pagado` : `Marcar como pagado`),
1267+
confirmPaymentReceivedModalTitle: 'Confirmar el pago recibido',
1268+
receivedPayment: 'Pago recibido',
1269+
receivedPaymentConfirmation: 'Por favor, continúa solo si ya has recibido el pago fuera de Expensify.',
1270+
confirmReceivedPayment: 'Sí, he recibido el pago.',
12671271
settleInvoicePersonal: (amount, last4Digits) => (amount ? `pagado ${amount} con cuenta personal ${last4Digits}` : `Pagado con cuenta personal`),
12681272
settleInvoiceBusiness: (amount, last4Digits) => (amount ? `pagado ${amount} con cuenta de empresa ${last4Digits}` : `Pagado con cuenta de empresa`),
12691273
payWithPolicy: (policyName, formattedAmount) => (formattedAmount ? `Pay ${formattedAmount} via ${policyName}` : `Pay via ${policyName}`),

src/languages/fr.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,10 @@ const translations: TranslationDeepObject<typeof en> = {
13161316
settlePayment: (formattedAmount: string) => `Payer ${formattedAmount}`,
13171317
settleBusiness: (formattedAmount?: string) => (formattedAmount ? `Payer ${formattedAmount} en tant qu’entreprise` : `Payer avec le compte professionnel`),
13181318
payElsewhere: (formattedAmount?: string) => (formattedAmount ? `Marquer ${formattedAmount} comme payé` : `Marquer comme payé`),
1319+
confirmPaymentReceivedModalTitle: 'Confirmer la réception du paiement',
1320+
receivedPayment: 'Paiement reçu',
1321+
receivedPaymentConfirmation: 'Veuillez continuer uniquement si vous avez déjà reçu le paiement en dehors d’Expensify.',
1322+
confirmReceivedPayment: 'Oui, j’ai reçu le paiement.',
13191323
settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `a payé ${amount} avec le compte personnel ${last4Digits}` : `Payé avec un compte personnel`),
13201324
settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `a payé ${amount} avec le compte professionnel ${last4Digits}` : `Payé avec le compte professionnel`),
13211325
payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Payer ${formattedAmount} via ${policyName}` : `Payer via ${policyName}`),

src/languages/it.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,10 @@ const translations: TranslationDeepObject<typeof en> = {
13121312
settlePayment: (formattedAmount: string) => `Paga ${formattedAmount}`,
13131313
settleBusiness: (formattedAmount?: string) => (formattedAmount ? `Paga ${formattedAmount} come azienda` : `Paga con conto aziendale`),
13141314
payElsewhere: (formattedAmount?: string) => (formattedAmount ? `Segna ${formattedAmount} come pagato` : `Segna come pagata`),
1315+
confirmPaymentReceivedModalTitle: 'Conferma la ricezione del pagamento',
1316+
receivedPayment: 'Pagamento ricevuto',
1317+
receivedPaymentConfirmation: 'Procedi solo se hai già ricevuto il pagamento al di fuori di Expensify.',
1318+
confirmReceivedPayment: 'Sì, ho ricevuto il pagamento.',
13151319
settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `pagato ${amount} con conto personale ${last4Digits}` : `Pagato con conto personale`),
13161320
settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `ha pagato ${amount} con il conto aziendale ${last4Digits}` : `Pagato con conto aziendale`),
13171321
payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Paga ${formattedAmount} tramite ${policyName}` : `Paga tramite ${policyName}`),

src/languages/ja.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,10 @@ const translations: TranslationDeepObject<typeof en> = {
12951295
settlePayment: (formattedAmount: string) => `${formattedAmount} を支払う`,
12961296
settleBusiness: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} をビジネスとして支払う` : `ビジネスアカウントで支払う`),
12971297
payElsewhere: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} を支払済みにする` : `支払い済みにする`),
1298+
confirmPaymentReceivedModalTitle: '支払いを受領したことを確認',
1299+
receivedPayment: '支払い受領済み',
1300+
receivedPaymentConfirmation: 'Expensify以外で支払いを受け取っている場合のみ続行してください。',
1301+
confirmReceivedPayment: 'はい、支払いを受け取りました。',
12981302
settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `個人アカウント(下4桁 ${last4Digits})で ${amount} を支払いました` : `個人アカウントで支払い済み`),
12991303
settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `ビジネス口座(末尾${last4Digits})で${amount}を支払いました` : `ビジネスアカウントで支払済み`),
13001304
payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `${policyName}で${formattedAmount}を支払う` : `${policyName}で支払う`),

0 commit comments

Comments
 (0)