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

Hide approve/pay buttons if the report contains violations #51133

Merged
10 changes: 7 additions & 3 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,11 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
const isPayAtEndExpense = TransactionUtils.isPayAtEndExpense(transaction);
const isArchivedReport = ReportUtils.isArchivedRoomWithID(moneyRequestReport?.reportID);
const [archiveReason] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${moneyRequestReport?.reportID ?? '-1'}`, {selector: ReportUtils.getArchiveReason});
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);

const getCanIOUBePaid = useCallback(
(onlyShowPayElsewhere = false) => IOU.canIOUBePaid(moneyRequestReport, chatReport, policy, transaction ? [transaction] : undefined, onlyShowPayElsewhere),
[moneyRequestReport, chatReport, policy, transaction],
(onlyShowPayElsewhere = false) => IOU.canIOUBePaid(moneyRequestReport, chatReport, policy, transactionViolations, transaction ? [transaction] : undefined, onlyShowPayElsewhere),
[moneyRequestReport, chatReport, policy, transaction, transactionViolations],
);
const canIOUBePaid = useMemo(() => getCanIOUBePaid(), [getCanIOUBePaid]);

Expand All @@ -135,7 +136,10 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea

const shouldShowPayButton = canIOUBePaid || onlyShowPayElsewhere;

const shouldShowApproveButton = useMemo(() => IOU.canApproveIOU(moneyRequestReport, policy) && !hasOnlyPendingTransactions, [moneyRequestReport, policy, hasOnlyPendingTransactions]);
const shouldShowApproveButton = useMemo(
() => IOU.canApproveIOU(moneyRequestReport, policy, transactionViolations) && !hasOnlyPendingTransactions,
[moneyRequestReport, policy, hasOnlyPendingTransactions, transactionViolations],
);

const shouldDisableApproveButton = shouldShowApproveButton && !ReportUtils.isAllowedToApproveExpenseReport(moneyRequestReport);

Expand Down
6 changes: 3 additions & 3 deletions src/components/ReportActionItem/ReportPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -330,14 +330,14 @@ function ReportPreview({

const bankAccountRoute = ReportUtils.getBankAccountRoute(chatReport);
const getCanIOUBePaid = useCallback(
(onlyShowPayElsewhere = false) => IOU.canIOUBePaid(iouReport, chatReport, policy, allTransactions, onlyShowPayElsewhere),
[iouReport, chatReport, policy, allTransactions],
(onlyShowPayElsewhere = false) => IOU.canIOUBePaid(iouReport, chatReport, policy, transactionViolations, allTransactions, onlyShowPayElsewhere),
[iouReport, chatReport, policy, allTransactions, transactionViolations],
);

const canIOUBePaid = useMemo(() => getCanIOUBePaid(), [getCanIOUBePaid]);
const onlyShowPayElsewhere = useMemo(() => !canIOUBePaid && getCanIOUBePaid(true), [canIOUBePaid, getCanIOUBePaid]);
const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere;
const shouldShowApproveButton = useMemo(() => IOU.canApproveIOU(iouReport, policy), [iouReport, policy]);
const shouldShowApproveButton = useMemo(() => IOU.canApproveIOU(iouReport, policy, transactionViolations), [iouReport, policy, transactionViolations]);

const shouldDisableApproveButton = shouldShowApproveButton && !ReportUtils.isAllowedToApproveExpenseReport(iouReport);

Expand Down
16 changes: 12 additions & 4 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6741,7 +6741,11 @@ function sendMoneyWithWallet(report: OnyxEntry<OnyxTypes.Report>, amount: number
Report.notifyNewAction(params.chatReportID, managerID);
}

function canApproveIOU(iouReport: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Report>, policy: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Policy>) {
function canApproveIOU(
iouReport: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Report>,
policy: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Policy>,
violations: OnyxCollection<OnyxTypes.TransactionViolation[]>,
) {
// Only expense reports can be approved
const isPaidGroupPolicy = policy && PolicyUtils.isPaidGroupPolicy(policy);
if (!isPaidGroupPolicy) {
Expand All @@ -6760,6 +6764,7 @@ function canApproveIOU(iouReport: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Report>,
const iouSettled = ReportUtils.isSettled(iouReport?.reportID);
const reportNameValuePairs = ReportUtils.getReportNameValuePairs(iouReport?.reportID);
const isArchivedReport = ReportUtils.isArchivedRoom(iouReport, reportNameValuePairs);
const hasViolations = ReportUtils.hasViolations(iouReport?.reportID ?? '-1', violations);
let isTransactionBeingScanned = false;
const reportTransactions = TransactionUtils.getAllReportTransactions(iouReport?.reportID);
for (const transaction of reportTransactions) {
Expand All @@ -6772,13 +6777,14 @@ function canApproveIOU(iouReport: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Report>,
}
}

return isCurrentUserManager && !isOpenExpenseReport && !isApproved && !iouSettled && !isArchivedReport && !isTransactionBeingScanned;
return isCurrentUserManager && !isOpenExpenseReport && !isApproved && !iouSettled && !isArchivedReport && !isTransactionBeingScanned && !hasViolations;
}

function canIOUBePaid(
iouReport: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Report>,
chatReport: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Report>,
policy: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Policy>,
violations: OnyxCollection<OnyxTypes.TransactionViolation[]>,
transactions?: OnyxTypes.Transaction[],
onlyShowPayElsewhere = false,
) {
Expand Down Expand Up @@ -6823,7 +6829,8 @@ function canIOUBePaid(

const {reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(iouReport);
const isAutoReimbursable = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES ? false : ReportUtils.canBeAutoReimbursed(iouReport, policy);
const shouldBeApproved = canApproveIOU(iouReport, policy);
const shouldBeApproved = canApproveIOU(iouReport, policy, violations);
const hasViolations = ReportUtils.hasViolations(iouReport?.reportID ?? '-1', violations);

const isPayAtEndExpenseReport = ReportUtils.isPayAtEndExpenseReport(iouReport?.reportID, transactions);
return (
Expand All @@ -6835,6 +6842,7 @@ function canIOUBePaid(
!isChatReportArchived &&
!isAutoReimbursable &&
!shouldBeApproved &&
!hasViolations &&
!isPayAtEndExpenseReport
);
}
Expand All @@ -6845,7 +6853,7 @@ function getIOUReportActionToApproveOrPay(chatReport: OnyxEntry<OnyxTypes.Report
return Object.values(chatReportActions).find((action) => {
const iouReport = ReportUtils.getReportOrDraftReport(action.childReportID ?? '-1');
const policy = PolicyUtils.getPolicy(iouReport?.policyID);
const shouldShowSettlementButton = canIOUBePaid(iouReport, chatReport, policy) || canApproveIOU(iouReport, policy);
const shouldShowSettlementButton = canIOUBePaid(iouReport, chatReport, policy, allTransactionViolations) || canApproveIOU(iouReport, policy, allTransactionViolations);
return action.childReportID?.toString() !== excludedIOUReportID && action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW && shouldShowSettlementButton;
});
}
Expand Down
Loading