Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
46 changes: 1 addition & 45 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ import {
getReportActionMessageText,
getReportActionText,
getRetractedMessage,
getSortedReportActions,
getTravelUpdateMessage,
getWorkspaceCurrencyUpdateMessage,
getWorkspaceFrequencyUpdateMessage,
Expand Down Expand Up @@ -4328,12 +4327,6 @@ function getNextApproverAccountID(report: OnyxEntry<Report>, isUnapproved = fals
// eslint-disable-next-line @typescript-eslint/no-deprecated
const policy = getPolicy(report?.policyID);

// If the current user took control, then they are the final approver and we don't have a next approver
const bypassApprover = getBypassApproverIfTakenControl(report);
if (bypassApprover === currentUserAccountID) {
return undefined;
}

const approvalChain = getApprovalChain(policy, report);
const submitToAccountID = getSubmitToAccountID(policy, report);

Expand All @@ -4351,8 +4344,7 @@ function getNextApproverAccountID(report: OnyxEntry<Report>, isUnapproved = fals

const nextApproverEmail = approvalChain.length === 1 ? approvalChain.at(0) : approvalChain.at(approvalChain.indexOf(currentUserEmail ?? '') + 1);
if (!nextApproverEmail) {
// If there's no next approver in the chain, return undefined to indicate the current user is the final approver
return undefined;
return submitToAccountID;
}

return getAccountIDsByLogins([nextApproverEmail]).at(0);
Expand Down Expand Up @@ -11482,42 +11474,6 @@ function isWorkspaceEligibleForReportChange(submitterEmail: string | undefined,
return isPaidGroupPolicyPolicyUtils(newPolicy) && !!newPolicy.role;
}

/**
* Checks if someone took control of the report and if that take control is still valid
* A take control is invalidated if there's a SUBMITTED action after it
*/
function getBypassApproverIfTakenControl(expenseReport: OnyxEntry<Report>): number | null {
if (!expenseReport?.reportID) {
return null;
}

if (!isProcessingReport(expenseReport)) {
return null;
}

const reportActions = getAllReportActions(expenseReport.reportID);
if (!reportActions) {
return null;
}

// Sort actions by created timestamp to get chronological order
const sortedActions = getSortedReportActions(Object.values(reportActions ?? {}), true);

// Look through actions in reverse chronological order (newest first)
// If we find a SUBMITTED action, there's no valid take control since any take control would be older
for (const action of sortedActions) {
if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED)) {
return null;
}

if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.TAKE_CONTROL)) {
return action.actorAccountID ?? null;
}
}

return null;
}

function getApprovalChain(policy: OnyxEntry<Policy>, expenseReport: OnyxEntry<Report>): string[] {
const approvalChain: string[] = [];
const fullApprovalChain: string[] = [];
Expand Down
32 changes: 14 additions & 18 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ import Log from '@libs/Log';
import isReportOpenInRHP from '@libs/Navigation/helpers/isReportOpenInRHP';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
import Navigation, {navigationRef} from '@libs/Navigation/Navigation';
import {buildNextStep, buildNextStepNew} from '@libs/NextStepUtils';
import {buildNextStep} from '@libs/NextStepUtils';
import * as NumberUtils from '@libs/NumberUtils';
import {getManagerMcTestParticipant, getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils';
import Parser from '@libs/Parser';
Expand Down Expand Up @@ -170,7 +170,6 @@ import {
hasOutstandingChildRequest,
hasReportBeenReopened,
hasReportBeenRetracted,
hasViolations as hasViolationsReportUtils,
isArchivedReport,
isClosedReport as isClosedReportUtil,
isDraftReport,
Expand Down Expand Up @@ -10110,6 +10109,13 @@ function getIOUReportActionToApproveOrPay(chatReport: OnyxEntry<OnyxTypes.Report
});
}

function isLastApprover(approvalChain: string[]): boolean {
if (approvalChain.length === 0) {
return true;
}
return approvalChain.at(-1) === currentUserEmail;
}

function approveMoneyRequest(expenseReport: OnyxEntry<OnyxTypes.Report>, full?: boolean) {
if (!expenseReport) {
return;
Expand All @@ -10131,23 +10137,13 @@ function approveMoneyRequest(expenseReport: OnyxEntry<OnyxTypes.Report>, full?:

// This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850
// eslint-disable-next-line @typescript-eslint/no-deprecated
const policy = getPolicy(expenseReport.policyID);
const nextApproverAccountID = getNextApproverAccountID(expenseReport);
const predictedNextStatus = !nextApproverAccountID ? CONST.REPORT.STATUS_NUM.APPROVED : CONST.REPORT.STATUS_NUM.SUBMITTED;
const predictedNextState = !nextApproverAccountID ? CONST.REPORT.STATE_NUM.APPROVED : CONST.REPORT.STATE_NUM.SUBMITTED;
const managerID = !nextApproverAccountID ? expenseReport.managerID : nextApproverAccountID;
const approvalChain = getApprovalChain(getPolicy(expenseReport.policyID), expenseReport);

const hasViolations = hasViolationsReportUtils(expenseReport.reportID, allTransactionViolations);
const isASAPSubmitBetaEnabled = Permissions.isBetaEnabled(CONST.BETAS.ASAP_SUBMIT, allBetas);
const optimisticNextStep = buildNextStepNew({
report: expenseReport,
policy,
currentUserAccountIDParam: userAccountID,
currentUserEmailParam: currentUserEmail,
hasViolations,
isASAPSubmitBetaEnabled,
predictedNextStatus,
});
const predictedNextStatus = isLastApprover(approvalChain) ? CONST.REPORT.STATUS_NUM.APPROVED : CONST.REPORT.STATUS_NUM.SUBMITTED;
const predictedNextState = isLastApprover(approvalChain) ? CONST.REPORT.STATE_NUM.APPROVED : CONST.REPORT.STATE_NUM.SUBMITTED;
const managerID = isLastApprover(approvalChain) ? expenseReport.managerID : getNextApproverAccountID(expenseReport);

const optimisticNextStep = buildNextStep(expenseReport, predictedNextStatus);
const chatReport = getReportOrDraftReport(expenseReport.chatReportID);

const optimisticReportActionsData: OnyxUpdate = {
Expand Down
Loading
Loading