Skip to content

Commit 65db650

Browse files
authored
Merge pull request Expensify#42034 from Krishna2323/krishna2323/issue/41440
feat: [Held requests] option does not show in the preview overflow menu.
2 parents 071c0f2 + 41276b8 commit 65db650

File tree

2 files changed

+109
-8
lines changed

2 files changed

+109
-8
lines changed

src/libs/ReportUtils.ts

+75-8
Original file line numberDiff line numberDiff line change
@@ -2404,6 +2404,14 @@ function isReportFieldOfTypeTitle(reportField: OnyxEntry<PolicyReportField>): bo
24042404
return reportField?.type === 'formula' && reportField?.fieldID === CONST.REPORT_FIELD_TITLE_FIELD_ID;
24052405
}
24062406

2407+
/**
2408+
* Check if Report has any held expenses
2409+
*/
2410+
function isHoldCreator(transaction: OnyxEntry<Transaction>, reportID: string): boolean {
2411+
const holdReportAction = ReportActionsUtils.getReportAction(reportID, `${transaction?.comment?.hold ?? ''}`);
2412+
return isActionCreator(holdReportAction);
2413+
}
2414+
24072415
/**
24082416
* Check if report fields are available to use in a report
24092417
*/
@@ -2721,6 +2729,71 @@ function canEditReportAction(reportAction: OnyxEntry<ReportAction>): boolean {
27212729
);
27222730
}
27232731

2732+
function canHoldUnholdReportAction(reportAction: OnyxEntry<ReportAction>): {canHoldRequest: boolean; canUnholdRequest: boolean} {
2733+
if (reportAction?.actionName !== CONST.REPORT.ACTIONS.TYPE.IOU) {
2734+
return {canHoldRequest: false, canUnholdRequest: false};
2735+
}
2736+
2737+
const moneyRequestReportID = reportAction?.originalMessage?.IOUReportID ?? 0;
2738+
const moneyRequestReport = getReport(String(moneyRequestReportID));
2739+
2740+
if (!moneyRequestReportID || !moneyRequestReport) {
2741+
return {canHoldRequest: false, canUnholdRequest: false};
2742+
}
2743+
2744+
const isRequestSettled = isSettled(moneyRequestReport?.reportID);
2745+
const isApproved = isReportApproved(moneyRequestReport);
2746+
const transactionID = moneyRequestReport ? reportAction?.originalMessage?.IOUTransactionID : 0;
2747+
const transaction = allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] ?? ({} as Transaction);
2748+
2749+
const parentReport = getReport(String(moneyRequestReport.parentReportID));
2750+
const parentReportAction = ReportActionsUtils.getParentReportAction(moneyRequestReport);
2751+
2752+
const isRequestIOU = parentReport?.type === 'iou';
2753+
const isRequestHoldCreator = isHoldCreator(transaction, moneyRequestReport?.reportID) && isRequestIOU;
2754+
const isTrackExpenseMoneyReport = isTrackExpenseReport(moneyRequestReport);
2755+
const isActionOwner =
2756+
typeof parentReportAction?.actorAccountID === 'number' &&
2757+
typeof currentUserPersonalDetails?.accountID === 'number' &&
2758+
parentReportAction.actorAccountID === currentUserPersonalDetails?.accountID;
2759+
const isApprover = isMoneyRequestReport(moneyRequestReport) && moneyRequestReport?.managerID !== null && currentUserPersonalDetails?.accountID === moneyRequestReport?.managerID;
2760+
const isOnHold = TransactionUtils.isOnHold(transaction);
2761+
const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction);
2762+
2763+
const canModifyStatus = !isTrackExpenseMoneyReport && (isPolicyAdmin || isActionOwner || isApprover);
2764+
const isDeletedParentAction = isEmptyObject(parentReportAction) || ReportActionsUtils.isDeletedAction(parentReportAction);
2765+
2766+
const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction;
2767+
const canHoldRequest = canHoldOrUnholdRequest && !isOnHold && (isRequestHoldCreator || (!isRequestIOU && canModifyStatus)) && !isScanning;
2768+
const canUnholdRequest = !!(canHoldOrUnholdRequest && isOnHold && (isRequestHoldCreator || (!isRequestIOU && canModifyStatus)));
2769+
2770+
return {canHoldRequest, canUnholdRequest};
2771+
}
2772+
2773+
const changeMoneyRequestHoldStatus = (reportAction: OnyxEntry<ReportAction>): void => {
2774+
if (reportAction?.actionName !== CONST.REPORT.ACTIONS.TYPE.IOU) {
2775+
return;
2776+
}
2777+
const moneyRequestReportID = reportAction?.originalMessage?.IOUReportID ?? 0;
2778+
2779+
const moneyRequestReport = getReport(String(moneyRequestReportID));
2780+
if (!moneyRequestReportID || !moneyRequestReport) {
2781+
return;
2782+
}
2783+
2784+
const transactionID = reportAction?.originalMessage?.IOUTransactionID ?? '';
2785+
const transaction = allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] ?? ({} as Transaction);
2786+
const isOnHold = TransactionUtils.isOnHold(transaction);
2787+
const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${moneyRequestReport.policyID}`] ?? null;
2788+
2789+
if (isOnHold) {
2790+
IOU.unholdRequest(transactionID, reportAction.childReportID ?? '');
2791+
} else {
2792+
const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams());
2793+
Navigation.navigate(ROUTES.MONEY_REQUEST_HOLD_REASON.getRoute(policy?.type ?? CONST.POLICY.TYPE.PERSONAL, transactionID, reportAction.childReportID ?? '', activeRoute));
2794+
}
2795+
};
2796+
27242797
/**
27252798
* Gets all transactions on an IOU report with a receipt
27262799
*/
@@ -6386,14 +6459,6 @@ function navigateToPrivateNotes(report: OnyxEntry<Report>, session: OnyxEntry<Se
63866459
Navigation.navigate(ROUTES.PRIVATE_NOTES_LIST.getRoute(report.reportID));
63876460
}
63886461

6389-
/**
6390-
* Check if Report has any held expenses
6391-
*/
6392-
function isHoldCreator(transaction: OnyxEntry<Transaction>, reportID: string): boolean {
6393-
const holdReportAction = ReportActionsUtils.getReportAction(reportID, `${transaction?.comment?.hold ?? ''}`);
6394-
return isActionCreator(holdReportAction);
6395-
}
6396-
63976462
/**
63986463
* Get all held transactions of a iouReport
63996464
*/
@@ -6905,6 +6970,7 @@ export {
69056970
canCreateTaskInReport,
69066971
canCurrentUserOpenReport,
69076972
canDeleteReportAction,
6973+
canHoldUnholdReportAction,
69086974
canEditFieldOfMoneyRequest,
69096975
canEditMoneyRequest,
69106976
canEditPolicyDescription,
@@ -7132,6 +7198,7 @@ export {
71327198
shouldShowMerchantColumn,
71337199
isCurrentUserInvoiceReceiver,
71347200
isDraftReport,
7201+
changeMoneyRequestHoldStatus,
71357202
createDraftWorkspaceAndNavigateToConfirmationScreen,
71367203
};
71377204

src/pages/home/report/ContextMenu/ContextMenuActions.tsx

+34
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,40 @@ const ContextMenuActions: ContextMenuAction[] = [
256256
},
257257
getDescription: () => {},
258258
},
259+
{
260+
isAnonymousAction: false,
261+
textTranslateKey: 'iou.unholdExpense',
262+
icon: Expensicons.Stopwatch,
263+
shouldShow: (type, reportAction) =>
264+
type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canEditReportAction(reportAction) && ReportUtils.canHoldUnholdReportAction(reportAction).canUnholdRequest,
265+
onPress: (closePopover, {reportAction}) => {
266+
if (closePopover) {
267+
hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction));
268+
return;
269+
}
270+
271+
// No popover to hide, call changeMoneyRequestHoldStatus immediately
272+
ReportUtils.changeMoneyRequestHoldStatus(reportAction);
273+
},
274+
getDescription: () => {},
275+
},
276+
{
277+
isAnonymousAction: false,
278+
textTranslateKey: 'iou.hold',
279+
icon: Expensicons.Stopwatch,
280+
shouldShow: (type, reportAction) =>
281+
type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canEditReportAction(reportAction) && ReportUtils.canHoldUnholdReportAction(reportAction).canHoldRequest,
282+
onPress: (closePopover, {reportAction}) => {
283+
if (closePopover) {
284+
hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction));
285+
return;
286+
}
287+
288+
// No popover to hide, call changeMoneyRequestHoldStatus immediately
289+
ReportUtils.changeMoneyRequestHoldStatus(reportAction);
290+
},
291+
getDescription: () => {},
292+
},
259293
{
260294
isAnonymousAction: false,
261295
textTranslateKey: 'reportActionContextMenu.joinThread',

0 commit comments

Comments
 (0)