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
6 changes: 0 additions & 6 deletions src/libs/API/parameters/BulkHoldRequestParams.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ export type {default as SubmitReportParams} from './SubmitReportParams';
export type {default as DetachReceiptParams} from './DetachReceiptParams';
export type {default as PayMoneyRequestParams} from './PayMoneyRequestParams';
export type {default as HoldMoneyRequestParams} from './HoldMoneyRequestParams';
export type {default as BulkHoldRequestParams} from './BulkHoldRequestParams';
export type {default as UnHoldMoneyRequestParams} from './UnHoldMoneyRequestParams';
export type {default as CancelPaymentParams} from './CancelPaymentParams';
export type {default as AcceptACHContractForBankAccount} from './AcceptACHContractForBankAccount';
Expand Down
2 changes: 0 additions & 2 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,6 @@ const WRITE_COMMANDS = {
UPDATE_MONEY_REQUEST_DESCRIPTION: 'UpdateMoneyRequestDescription',
UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY: 'UpdateMoneyRequestAmountAndCurrency',
HOLD_MONEY_REQUEST: 'HoldRequest',
BULK_HOLD_MONEY_REQUEST: 'BulkHoldRequest',
UPDATE_BILLING_CARD_CURRENCY: 'UpdateBillingCardCurrency',
UNHOLD_MONEY_REQUEST: 'UnHoldRequest',
REQUEST_MONEY: 'RequestMoney',
Expand Down Expand Up @@ -675,7 +674,6 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_CATEGORY]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.HOLD_MONEY_REQUEST]: Parameters.HoldMoneyRequestParams;
[WRITE_COMMANDS.BULK_HOLD_MONEY_REQUEST]: Parameters.BulkHoldRequestParams;
[WRITE_COMMANDS.UNHOLD_MONEY_REQUEST]: Parameters.UnHoldMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.REQUEST_MONEY]: Parameters.RequestMoneyParams;
Expand Down
256 changes: 7 additions & 249 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@
} from '@libs/PolicyUtils';
import {
getAllReportActions,
getIOUActionForReportID,
getIOUActionForTransactionID,

Check failure on line 87 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / ESLint check

'getIOUActionForTransactionID' is defined but never used

Check failure on line 87 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'getIOUActionForTransactionID' is defined but never used

Check failure on line 87 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'getIOUActionForTransactionID' is defined but never used
getIOUReportIDFromReportActionPreview,
getLastVisibleAction,
getLastVisibleMessage,
Expand Down Expand Up @@ -124,7 +125,7 @@
buildOptimisticSubmittedReportAction,
buildOptimisticUnapprovedReportAction,
buildOptimisticUnHoldReportAction,
buildTransactionThread,

Check failure on line 128 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / ESLint check

'buildTransactionThread' is defined but never used

Check failure on line 128 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'buildTransactionThread' is defined but never used

Check failure on line 128 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'buildTransactionThread' is defined but never used
canBeAutoReimbursed,
canUserPerformWriteAction as canUserPerformWriteActionReportUtils,
getAllHeldTransactions as getAllHeldTransactionsReportUtils,
Expand Down Expand Up @@ -358,13 +359,6 @@
failureData: OnyxUpdate[];
};

type HoldDataEntry = {
transactionThreadReportID?: string;
transactionThreadCreatedReportActionID?: string;
holdReportActionID: string;
commentReportActionID: string;
};

type SendMoneyParamsData = {
params: SendMoneyParams;
optimisticData: OnyxUpdate[];
Expand Down Expand Up @@ -10781,250 +10775,14 @@
Navigation.setNavigationActionToMicrotaskQueue(() => notifyNewAction(currentReportID, userAccountID));
}

/**
* Put expenses on HOLD in bulk
*/
function bulkHold(transactionIDs: string[], comment: string, reportID: string, searchHash?: number) {
const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
const iouReportActions = Object.values(getAllReportActions(reportID));
const iouReportOptimisticData: Partial<OnyxTypes.Report> = {};
const holdData: Record<string, HoldDataEntry> = {};
const optimisticData: OnyxUpdate[] = [];
const successData: OnyxUpdate[] = [];
const failureData: OnyxUpdate[] = [];

transactionIDs.forEach((transactionID) => {
const iouAction = getIOUActionForTransactionID(iouReportActions, transactionID);

if (!iouAction) {
function putTransactionsOnHold(transactionsID: string[], comment: string, reportID: string) {
transactionsID.forEach((transactionID) => {
const {childReportID} = getIOUActionForReportID(reportID, transactionID) ?? {};
if (!childReportID) {
return;
}

const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];

if (iouReport && iouReport.currency === transaction?.currency) {
const isExpenseReportLocal = isExpenseReport(iouReport);
const coefficient = isExpenseReportLocal ? -1 : 1;
const transactionAmount = getAmount(transaction, isExpenseReportLocal) * coefficient;
iouReportOptimisticData.unheldTotal = (iouReportOptimisticData.unheldTotal ?? 0) - transactionAmount;
iouReportOptimisticData.unheldNonReimbursableTotal = !transaction?.reimbursable
? (iouReportOptimisticData.unheldNonReimbursableTotal ?? 0) - transactionAmount
: iouReportOptimisticData.unheldNonReimbursableTotal;
}

const transactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`] ?? [];
const newViolation = {name: CONST.VIOLATIONS.HOLD, type: CONST.VIOLATION_TYPES.VIOLATION, showInReview: true};
const updatedViolations = [...transactionViolations, newViolation];

const currentTime = DateUtils.getDBTime();
const createdReportAction = buildOptimisticHoldReportAction(currentTime);
const createdReportActionComment = buildOptimisticHoldReportActionComment(comment, DateUtils.addMillisecondsFromDateTime(currentTime, 1));

holdData[transactionID] = {
holdReportActionID: createdReportAction.reportActionID,
commentReportActionID: createdReportActionComment.reportActionID,
};

let transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouAction?.childReportID}`];
if (!transactionThreadReport) {
const optimisticTransactionThread = buildTransactionThread(iouAction, iouReport);
const optimisticCreatedActionForTransactionThread = buildOptimisticCreatedReportAction(currentUserEmail);

// If the transactionThread is optimistic, we need the transactionThreadReportID and transactionThreadCreatedReportActionID in the holdData.
holdData[transactionID].transactionThreadReportID = optimisticTransactionThread.reportID;
holdData[transactionID].transactionThreadCreatedReportActionID = optimisticCreatedActionForTransactionThread.reportActionID;

transactionThreadReport = optimisticTransactionThread;

optimisticData.push(
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticTransactionThread.reportID}`,
value: {...optimisticTransactionThread, pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticTransactionThread.reportID}`,
value: {[optimisticCreatedActionForTransactionThread.reportActionID]: optimisticCreatedActionForTransactionThread},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
value: {[iouAction.reportActionID]: {childReportID: optimisticTransactionThread.reportID}},
},
);

successData.push(
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticTransactionThread.reportID}`,
value: {pendingAction: null},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticTransactionThread.reportID}`,
value: {[optimisticCreatedActionForTransactionThread.reportActionID]: {pendingAction: null}},
},
);

failureData.push(
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticTransactionThread.reportID}`,
value: null,
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticTransactionThread.reportID}`,
value: {[optimisticCreatedActionForTransactionThread.reportActionID]: null},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
value: {[iouAction.reportActionID]: {childReportID: null}},
},
);
}

const parentReportActionOptimistic = getOptimisticDataForParentReportAction(
transactionThreadReport.reportID,
createdReportActionComment.created,
CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
);

optimisticData.push(
...parentReportActionOptimistic.filter((parentActionData): parentActionData is OnyxUpdate => parentActionData !== null),
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`,
value: {
[createdReportAction.reportActionID]: createdReportAction as ReportAction,
[createdReportActionComment.reportActionID]: createdReportActionComment as ReportAction,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`,
value: {
lastVisibleActionCreated: createdReportActionComment.created,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`,
value: {
[createdReportAction.reportActionID]: null,
[createdReportActionComment.reportActionID]: null,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: {
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
comment: {
hold: createdReportAction.reportActionID,
},
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`,
value: updatedViolations,
},
);

successData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: {
pendingAction: null,
},
});

failureData.push(
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: {
pendingAction: null,
comment: {
hold: null,
},
errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericHoldExpenseFailureMessage'),
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`,
value: {
lastVisibleActionCreated: transactionThreadReport?.lastVisibleActionCreated,
},
},

{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`,
value: transactionViolations,
},
);

// If we are holding from the search page, we optimistically update the snapshot data that search uses so that it is kept in sync
if (searchHash) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${searchHash}`,
value: {
data: {
[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: {
canHold: false,
canUnhold: true,
},
},
} as Record<string, Record<string, Partial<SearchTransaction>>>,
});

failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${searchHash}`,
value: {
data: {
[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: {
canHold: true,
canUnhold: false,
},
},
} as Record<string, Record<string, Partial<SearchTransaction>>>,
});
}
putOnHold(transactionID, comment, childReportID);
});

optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: iouReportOptimisticData,
});

failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
unheldTotal: iouReport?.unheldTotal,
unheldNonReimbursableTotal: iouReport?.unheldNonReimbursableTotal,
},
});

API.write(
WRITE_COMMANDS.BULK_HOLD_MONEY_REQUEST,
{
holdData: JSON.stringify(holdData),
comment,
},
{optimisticData, successData, failureData},
);

const currentReportID = getDisplayedReportID(reportID);
Navigation.setNavigationActionToMicrotaskQueue(() => notifyNewAction(currentReportID, userAccountID));
}

/**
Expand Down Expand Up @@ -12036,7 +11794,7 @@
payInvoice,
payMoneyRequest,
putOnHold,
bulkHold,
putTransactionsOnHold,
replaceReceipt,
requestMoney,
resetSplitShares,
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Search/SearchHoldReasonPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig
import {getFieldRequiredErrors} from '@libs/ValidationUtils';
import type {SearchReportParamList} from '@navigation/types';
import HoldReasonFormView from '@pages/iou/HoldReasonFormView';
import {bulkHold} from '@userActions/IOU';
import {putTransactionsOnHold} from '@userActions/IOU';
import ONYXKEYS from '@src/ONYXKEYS';
import SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/MoneyRequestHoldReasonForm';
Expand All @@ -22,7 +22,7 @@ function SearchHoldReasonPage({route}: PlatformStackScreenProps<Omit<SearchRepor
const onSubmit = useCallback(
({comment}: FormOnyxValues<typeof ONYXKEYS.FORMS.MONEY_REQUEST_HOLD_FORM>) => {
if (route.name === SCREENS.SEARCH.MONEY_REQUEST_REPORT_HOLD_TRANSACTIONS) {
bulkHold(context.selectedTransactionIDs, comment, reportID, context.currentSearchHash);
putTransactionsOnHold(context.selectedTransactionIDs, comment, reportID);
context.clearSelectedTransactions(true);
} else {
holdMoneyRequestOnSearch(context.currentSearchHash, Object.keys(context.selectedTransactions), comment);
Expand Down
Loading