diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 3f5a3c50f6cc..4e1301bee476 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -10,6 +10,7 @@ import useWindowDimensions from '@hooks/useWindowDimensions'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import * as HeaderUtils from '@libs/HeaderUtils'; import Navigation from '@libs/Navigation/Navigation'; +import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as IOU from '@userActions/IOU'; import * as Link from '@userActions/Link'; @@ -65,6 +66,8 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money isPolicyAdmin && (isApproved || isManager) : isPolicyAdmin || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && isManager); const isDraft = ReportUtils.isDraftExpenseReport(moneyRequestReport); + const isOnInstantSubmitPolicy = PolicyUtils.isInstantSubmitEnabled(policy); + const isOnSubmitAndClosePolicy = PolicyUtils.isSubmitAndClose(policy); const shouldShowPayButton = useMemo( () => isPayer && !isDraft && !isSettled && !moneyRequestReport.isWaitingOnBankAccount && reimbursableSpend !== 0 && !ReportUtils.isArchivedRoom(chatReport) && !isAutoReimbursable, [isPayer, isDraft, isSettled, moneyRequestReport, reimbursableSpend, chatReport, isAutoReimbursable], @@ -73,8 +76,11 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money if (!isPaidGroupPolicy) { return false; } + if (isOnInstantSubmitPolicy && isOnSubmitAndClosePolicy) { + return false; + } return isManager && !isDraft && !isApproved && !isSettled; - }, [isPaidGroupPolicy, isManager, isDraft, isApproved, isSettled]); + }, [isPaidGroupPolicy, isManager, isDraft, isApproved, isSettled, isOnInstantSubmitPolicy, isOnSubmitAndClosePolicy]); const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton; const shouldShowSubmitButton = isDraft && reimbursableSpend !== 0; const isFromPaidPolicy = policyType === CONST.POLICY.TYPE.TEAM || policyType === CONST.POLICY.TYPE.CORPORATE; diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index f12c6d9bea31..311e63332f5c 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -19,6 +19,7 @@ import ControlSelection from '@libs/ControlSelection'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import Navigation from '@libs/Navigation/Navigation'; +import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportActionUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -213,6 +214,8 @@ function ReportPreview({ ? // In a paid group policy, the admin approver can pay the report directly by skipping the approval step isPolicyAdmin && (isApproved || isCurrentUserManager) : isPolicyAdmin || (isMoneyRequestReport && isCurrentUserManager); + const isOnInstantSubmitPolicy = PolicyUtils.isInstantSubmitEnabled(policy); + const isOnSubmitAndClosePolicy = PolicyUtils.isSubmitAndClose(policy); const shouldShowPayButton = useMemo( () => isPayer && !isDraftExpenseReport && !iouSettled && !iouReport?.isWaitingOnBankAccount && reimbursableSpend !== 0 && !iouCanceled && !isAutoReimbursable, [isPayer, isDraftExpenseReport, iouSettled, reimbursableSpend, iouCanceled, isAutoReimbursable, iouReport], @@ -221,8 +224,11 @@ function ReportPreview({ if (!isPaidGroupPolicy) { return false; } + if (isOnInstantSubmitPolicy && isOnSubmitAndClosePolicy) { + return false; + } return isCurrentUserManager && !isDraftExpenseReport && !isApproved && !iouSettled; - }, [isPaidGroupPolicy, isCurrentUserManager, isDraftExpenseReport, isApproved, iouSettled]); + }, [isPaidGroupPolicy, isCurrentUserManager, isDraftExpenseReport, isApproved, isOnInstantSubmitPolicy, isOnSubmitAndClosePolicy, iouSettled]); const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton; /* diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index d9e57f5e3bb8..0a7a2d40e0f6 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -204,6 +204,21 @@ function isPaidGroupPolicy(policy: OnyxEntry | EmptyObject): boolean { return policy?.type === CONST.POLICY.TYPE.TEAM || policy?.type === CONST.POLICY.TYPE.CORPORATE; } +/** + * Checks if policy's scheduled submit / auto reporting frequency is "instant". + * Note: Free policies have "instant" submit always enabled. + */ +function isInstantSubmitEnabled(policy: OnyxEntry): boolean { + return policy?.autoReportingFrequency === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT || policy?.type === CONST.POLICY.TYPE.FREE; +} + +/** + * Checks if policy's approval mode is "optional", a.k.a. "Submit & Close" + */ +function isSubmitAndClose(policy: OnyxEntry): boolean { + return policy?.approvalMode === CONST.POLICY.APPROVAL_MODE.OPTIONAL; +} + function extractPolicyIDFromPath(path: string) { return path.match(CONST.REGEX.POLICY_ID_FROM_PATH)?.[1]; } @@ -232,7 +247,9 @@ export { shouldShowPolicy, isExpensifyTeam, isExpensifyGuideTeam, + isInstantSubmitEnabled, isPolicyAdmin, + isSubmitAndClose, getMemberAccountIDsForWorkspace, getIneligibleInvitees, getTag,