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
2 changes: 1 addition & 1 deletion Mobile-Expensify
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1009023201
versionName "9.2.32-1"
versionCode 1009023203
versionName "9.2.32-3"
// Supported language variants must be declared here to avoid from being removed during the compilation.
// This also helps us to not include unnecessary language variants in the APK.
resConfigs "en", "es"
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>9.2.32.1</string>
<string>9.2.32.3</string>
<key>FullStory</key>
<dict>
<key>OrgId</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/NotificationServiceExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<key>CFBundleShortVersionString</key>
<string>9.2.32</string>
<key>CFBundleVersion</key>
<string>9.2.32.1</string>
<string>9.2.32.3</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/ShareViewController/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<key>CFBundleShortVersionString</key>
<string>9.2.32</string>
<key>CFBundleVersion</key>
<string>9.2.32.1</string>
<string>9.2.32.3</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
"version": "9.2.32-1",
"version": "9.2.32-3",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Expand Down
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 @@ -4324,12 +4323,6 @@ function getNextApproverAccountID(report: OnyxEntry<Report>, isUnapproved = fals
// eslint-disable-next-line deprecation/deprecation
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 @@ -4347,8 +4340,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 @@ -11478,42 +11470,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
35 changes: 16 additions & 19 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 @@ -10101,6 +10100,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 @@ -10121,26 +10127,17 @@ function approveMoneyRequest(expenseReport: OnyxEntry<OnyxTypes.Report>, full?:
const optimisticApprovedReportAction = buildOptimisticApprovedReportAction(total, expenseReport.currency ?? '', expenseReport.reportID);

// This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850
// eslint-disable-next-line deprecation/deprecation
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;
// eslint-disable-next-line @typescript-eslint/no-deprecated
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 = {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`,
Expand Down
Loading