Skip to content
Closed
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
14 changes: 7 additions & 7 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,22 +520,22 @@ function isPolicyFeatureEnabled(policy: OnyxEntry<Policy>, featureName: PolicyFe
return !!policy?.[featureName];
}

function getApprovalWorkflow(policy: OnyxEntry<Policy> | SearchPolicy): ValueOf<typeof CONST.POLICY.APPROVAL_MODE> {
function getApprovalWorkflow(policy: OnyxEntry<Policy>): ValueOf<typeof CONST.POLICY.APPROVAL_MODE> {
if (policy?.type === CONST.POLICY.TYPE.PERSONAL) {
return CONST.POLICY.APPROVAL_MODE.OPTIONAL;
}

return policy?.approvalMode ?? CONST.POLICY.APPROVAL_MODE.ADVANCED;
}

function getDefaultApprover(policy: OnyxEntry<Policy> | SearchPolicy): string {
function getDefaultApprover(policy: OnyxEntry<Policy>): string {
return policy?.approver ?? policy?.owner ?? '';
}

/**
* Returns the accountID to whom the given expenseReport submits reports to in the given Policy.
*/
function getSubmitToAccountID(policy: OnyxEntry<Policy> | SearchPolicy, expenseReport: OnyxEntry<Report>): number {
function getSubmitToAccountID(policy: OnyxEntry<Policy>, expenseReport: OnyxEntry<Report>): number {
const employeeAccountID = expenseReport?.ownerAccountID ?? -1;
const employeeLogin = getLoginsByAccountIDs([employeeAccountID]).at(0) ?? '';
const defaultApprover = getDefaultApprover(policy);
Expand All @@ -555,8 +555,8 @@ function getSubmitToAccountID(policy: OnyxEntry<Policy> | SearchPolicy, expenseR
return getAccountIDsByLogins([categoryAppover]).at(0) ?? -1;
}

if (!tagApprover && getTagApproverRule(policy ?? '-1', tag)?.approver) {
tagApprover = getTagApproverRule(policy ?? '-1', tag)?.approver;
if (!tagApprover && getTagApproverRule(policy?.id ?? '-1', tag)?.approver) {
tagApprover = getTagApproverRule(policy?.id ?? '-1', tag)?.approver;
}
}

Expand Down Expand Up @@ -1084,8 +1084,8 @@ function hasVBBA(policyID: string) {
return !!policy?.achAccount?.bankAccountID;
}

function getTagApproverRule(policyOrID: string | SearchPolicy | OnyxEntry<Policy>, tagName: string) {
const policy = typeof policyOrID === 'string' ? getPolicy(policyOrID) : policyOrID;
function getTagApproverRule(policyID: string, tagName: string) {
const policy = getPolicy(policyID);

const approvalRules = policy?.rules?.approvalRules ?? [];
const approverRule = approvalRules.find((rule) =>
Expand Down
4 changes: 0 additions & 4 deletions src/libs/SearchUIUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,6 @@ function getAction(data: OnyxTypes.SearchResults['data'], key: string): SearchTr
return CONST.SEARCH.ACTION_TYPES.APPROVE;
}

if (IOU.canSubmitReport(report, policy)) {
return CONST.SEARCH.ACTION_TYPES.SUBMIT;
}

return CONST.SEARCH.ACTION_TYPES.VIEW;
}

Expand Down
12 changes: 0 additions & 12 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7200,17 +7200,6 @@ function canIOUBePaid(
);
}

function canSubmitReport(report: OnyxEntry<OnyxTypes.Report> | SearchReport, policy: OnyxEntry<OnyxTypes.Policy> | SearchPolicy) {
const currentUserAccountID = Report.getCurrentUserAccountID();
const isOpenExpenseReport = ReportUtils.isOpenExpenseReport(report);
const {reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(report);
const isAdmin = policy?.role === CONST.POLICY.ROLE.ADMIN;

// This logic differs from the one in MoneyRequestHeader
// We are intentionally doing this for now because Auth violations are not ready and thus not returned by Search results. Additionally, the risk of a customer having either RTER or Broken connection violation is really small in the current cohort.
return isOpenExpenseReport && reimbursableSpend !== 0 && (report?.ownerAccountID === currentUserAccountID || isAdmin || report?.managerID === currentUserAccountID);
}

function getIOUReportActionToApproveOrPay(chatReport: OnyxEntry<OnyxTypes.Report>, excludedIOUReportID: string): OnyxEntry<ReportAction> {
const chatReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`] ?? {};

Expand Down Expand Up @@ -8844,6 +8833,5 @@ export {
getIOUReportActionToApproveOrPay,
getNavigationUrlOnMoneyRequestDelete,
getNavigationUrlAfterTrackExpenseDelete,
canSubmitReport,
};
export type {GPSPoint as GpsPoint, IOURequestType};
41 changes: 2 additions & 39 deletions src/libs/actions/Search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,19 @@ import type {FormOnyxValues} from '@components/Form/types';
import type {PaymentData, SearchQueryJSON} from '@components/Search/types';
import type {ReportListItemType, TransactionListItemType} from '@components/SelectionList/types';
import * as API from '@libs/API';
import type {ExportSearchItemsToCSVParams, SubmitReportParams} from '@libs/API/parameters';
import type {ExportSearchItemsToCSVParams} from '@libs/API/parameters';
import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import * as ApiUtils from '@libs/ApiUtils';
import fileDownload from '@libs/fileDownload';
import enhanceParameters from '@libs/Network/enhanceParameters';
import {rand64} from '@libs/NumberUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import {isReportListItemType, isTransactionListItemType} from '@libs/SearchUIUtils';
import playSound, {SOUNDS} from '@libs/Sound';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import FILTER_KEYS from '@src/types/form/SearchAdvancedFiltersForm';
import type {LastPaymentMethod, SearchResults} from '@src/types/onyx';
import type {SearchPolicy, SearchReport, SearchTransaction} from '@src/types/onyx/SearchResults';
import type {SearchReport, SearchTransaction} from '@src/types/onyx/SearchResults';
import * as Report from './Report';

let currentUserEmail: string;
Expand Down Expand Up @@ -66,11 +64,6 @@ function handleActionButtonPress(hash: number, item: TransactionListItemType | R
case CONST.SEARCH.ACTION_TYPES.APPROVE:
approveMoneyRequestOnSearch(hash, [item.reportID], transactionID);
return;
case CONST.SEARCH.ACTION_TYPES.SUBMIT: {
const policy = (allSnapshots?.[`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`]?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${item.policyID}`] ?? {}) as SearchPolicy;
submitMoneyRequestOnSearch(hash, [item], [policy], transactionID);
return;
}
default:
goToItem();
}
Expand Down Expand Up @@ -243,35 +236,6 @@ function holdMoneyRequestOnSearch(hash: number, transactionIDList: string[], com
API.write(WRITE_COMMANDS.HOLD_MONEY_REQUEST_ON_SEARCH, {hash, transactionIDList, comment}, {optimisticData, finallyData});
}

function submitMoneyRequestOnSearch(hash: number, reportList: SearchReport[], policy: SearchPolicy[], transactionIDList?: string[]) {
const createActionLoadingData = (isLoading: boolean): OnyxUpdate[] => [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`,
value: {
data: transactionIDList
? (Object.fromEntries(
transactionIDList.map((transactionID) => [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {isActionLoading: isLoading}]),
) as Partial<SearchTransaction>)
: (Object.fromEntries(reportList.map((report) => [`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, {isActionLoading: isLoading}])) as Partial<SearchReport>),
},
},
];
const optimisticData: OnyxUpdate[] = createActionLoadingData(true);
const finallyData: OnyxUpdate[] = createActionLoadingData(false);

const report = (reportList.at(0) ?? {}) as SearchReport;
const parameters: SubmitReportParams = {
reportID: report.reportID,
managerAccountID: PolicyUtils.getSubmitToAccountID(policy.at(0), report) ?? report?.managerID,
reportActionID: rand64(),
};

// The SubmitReport command is not 1:1:1 yet, which means creating a separate SubmitMoneyRequestOnSearch command is not feasible until https://github.com/Expensify/Expensify/issues/451223 is done.
// In the meantime, we'll call SubmitReport which works for a single expense only, so not bulk actions are possible.
API.write(WRITE_COMMANDS.SUBMIT_REPORT, parameters, {optimisticData, finallyData});
}

function approveMoneyRequestOnSearch(hash: number, reportIDList: string[], transactionIDList?: string[]) {
const createActionLoadingData = (isLoading: boolean): OnyxUpdate[] => [
{
Expand Down Expand Up @@ -405,5 +369,4 @@ export {
payMoneyRequestOnSearch,
approveMoneyRequestOnSearch,
handleActionButtonPress,
submitMoneyRequestOnSearch,
};
17 changes: 1 addition & 16 deletions src/types/onyx/SearchResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type TransactionListItem from '@components/SelectionList/Search/Transacti
import type {ReportActionListItemType, ReportListItemType, TransactionListItemType} from '@components/SelectionList/types';
import type CONST from '@src/CONST';
import type ONYXKEYS from '@src/ONYXKEYS';
import type {ACHAccount, ApprovalRule, ExpenseRule} from './Policy';
import type {ACHAccount} from './Policy';
import type {InvoiceReceiver} from './Report';
import type ReportActionName from './ReportActionName';
import type ReportNameValuePairs from './ReportNameValuePairs';
Expand Down Expand Up @@ -230,21 +230,6 @@ type SearchPolicy = {

/** Whether the self approval or submitting is enabled */
preventSelfApproval?: boolean;

/** The email of the policy owner */
owner: string;

/** The approver of the policy */
approver?: string;

/** A set of rules related to the workpsace */
rules?: {
/** A set of rules related to the workpsace approvals */
approvalRules?: ApprovalRule[];

/** A set of rules related to the workpsace expenses */
expenseRules?: ExpenseRule[];
};
};

/** Model of transaction search result */
Expand Down