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: 0 additions & 2 deletions src/hooks/useReceiptScanDrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ function useReceiptScanDrop() {
parentReport: undefined,
newIouRequestType: CONST.IOU.REQUEST_TYPE.SCAN,
currentDate,
currentUserPersonalDetails,
hasOnlyPersonalPolicies,
draftTransactionIDs,
});
Expand All @@ -72,7 +71,6 @@ function useReceiptScanDrop() {
? (initialTransaction as Partial<Transaction>)
: buildOptimisticTransactionAndCreateDraft({
initialTransaction: initialTransaction as Partial<Transaction>,
currentUserPersonalDetails,
reportID: newReportID,
});
const transactionID = transaction.transactionID ?? CONST.IOU.OPTIMISTIC_TRANSACTION_ID;
Expand Down
3 changes: 0 additions & 3 deletions src/hooks/useResetIOUType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {validTransactionDraftIDsSelector} from '@selectors/TransactionDraft';
import {useRef} from 'react';
import {Keyboard} from 'react-native';

import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
import useDefaultParticipants from './useDefaultParticipants';
import useOdometerDraftHydrator from './useOdometerDraftHydrator';
import useOnyx from './useOnyx';
Expand Down Expand Up @@ -84,7 +83,6 @@ function useResetIOUType({
const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector});

const personalPolicy = usePersonalPolicy();
const currentUserPersonalDetails = useCurrentUserPersonalDetails();

const hydrateOdometerOnLanding = useOdometerDraftHydrator({
transaction,
Expand Down Expand Up @@ -135,7 +133,6 @@ function useResetIOUType({
parentReport,
currentDate,
lastSelectedDistanceRates,
currentUserPersonalDetails,
hasOnlyPersonalPolicies: hasOnlyPersonalPolicies ?? true,
draftTransactionIDs,
defaultParticipants: isSelfDMDefault ? undefined : defaultParticipants,
Expand Down
14 changes: 13 additions & 1 deletion src/hooks/useSearchBulkActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2207,7 +2207,19 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
text: translate('common.merge'),
icon: expensifyIcons.ArrowCollapse,
value: CONST.SEARCH.BULK_ACTION_TYPES.MERGE,
onSelected: () => setupMergeTransactionDataAndNavigate(transactionID, searchedTransactions, localeCompare, getCurrencyDecimals, reports, false, true),
onSelected: () =>
setupMergeTransactionDataAndNavigate(
transactionID,
searchedTransactions,
localeCompare,
getCurrencyDecimals,
reports,
false,
true,
undefined,
accountID,
personalDetails,
),
});
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/hooks/useSelectedTransactionsActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ function useSelectedTransactionsActions({
const {isBetaEnabled} = usePermissions();
const {deleteTransactions, shouldOpenSplitExpenseEditFlowOnDelete} = useDeleteTransactions({report, reportActions, policy});
const {login, accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
const defaultExpensePolicy = useDefaultExpensePolicy();
const {isProduction} = useEnvironment();

Expand Down Expand Up @@ -486,6 +487,8 @@ function useSelectedTransactionsActions({
false,
isOnSearch,
selectedTransactionsList.length > 1 ? [policy, policy] : undefined,
currentUserAccountID,
personalDetails,
),
});
}
Expand Down
9 changes: 7 additions & 2 deletions src/libs/MergeTransactionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,17 @@ function getMergeableDataAndConflictFields(
searchReports: Array<OnyxEntry<Report>> = [],
targetTransactionPolicy?: OnyxEntry<Policy>,
sourceTransactionPolicy?: OnyxEntry<Policy>,
targetReportOwnerAsAttendee?: Attendee,
sourceReportOwnerAsAttendee?: Attendee,
) {
const conflictFields: string[] = [];
const mergeableData: Record<string, unknown> = {};

const targetTransactionDetails = getTransactionDetails(targetTransaction);
const sourceTransactionDetails = getTransactionDetails(sourceTransaction);
// Resolve the report-owner fallback the same way the display path (buildMergeFieldsData) does, so an expense
// with no stored attendee is compared as [owner] instead of [] and doesn't produce a false attendee conflict
// against an expense whose attendee is that same owner.
const targetTransactionDetails = getTransactionDetails(targetTransaction, undefined, undefined, undefined, undefined, targetReportOwnerAsAttendee);
const sourceTransactionDetails = getTransactionDetails(sourceTransaction, undefined, undefined, undefined, undefined, sourceReportOwnerAsAttendee);

for (const field of getMergeFields(targetTransaction)) {
const targetValue = getMergeFieldValue(targetTransactionDetails, targetTransaction, field);
Expand Down
9 changes: 2 additions & 7 deletions src/libs/actions/IOU/MoneyRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {WRITE_COMMANDS} from '@libs/API/types';
import DateUtils from '@libs/DateUtils';
import DistanceRequestUtils from '@libs/DistanceRequestUtils';
import {getGPSRoutes, getGPSWaypoints} from '@libs/GPSDraftDetailsUtils';
import {formatCurrentUserToAttendee, getExistingTransactionID} from '@libs/IOUUtils';
import {getExistingTransactionID} from '@libs/IOUUtils';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import {getParticipantsOption, getReportOption} from '@libs/OptionsListUtils';
Expand Down Expand Up @@ -57,7 +57,6 @@ import type {
} from '@src/types/onyx';
import type {ReportAttributesDerivedValue} from '@src/types/onyx/DerivedValues';
import type {Accountant, Attendee, Participant} from '@src/types/onyx/IOU';
import type {CurrentUserPersonalDetails} from '@src/types/onyx/PersonalDetails';
import type {Unit} from '@src/types/onyx/Policy';
import type {Comment, Receipt} from '@src/types/onyx/Transaction';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
Expand Down Expand Up @@ -277,7 +276,6 @@ type InitMoneyRequestParams = {
parentReport: OnyxEntry<Report>;
currentDate: string | undefined;
lastSelectedDistanceRates?: OnyxEntry<LastSelectedDistanceRates>;
currentUserPersonalDetails: CurrentUserPersonalDetails;
isTrackDistanceExpense?: boolean;
hasOnlyPersonalPolicies: boolean;
draftTransactionIDs?: string[];
Expand Down Expand Up @@ -308,7 +306,6 @@ function initMoneyRequest({
parentReport,
currentDate,
lastSelectedDistanceRates,
currentUserPersonalDetails,
hasOnlyPersonalPolicies,
draftTransactionIDs,
defaultParticipants,
Expand Down Expand Up @@ -337,9 +334,7 @@ function initMoneyRequest({
return;
}

const comment: Comment = {
attendees: formatCurrentUserToAttendee(currentUserPersonalDetails),
};
const comment: Comment = {};
let requestCategory: string | null = null;

// Set up initial distance expense state
Expand Down
23 changes: 21 additions & 2 deletions src/libs/actions/MergeTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ import {
} from '@libs/ReportUtils';

import CONST from '@src/CONST';
import {isDistanceRequest, isTransactionPendingDelete} from '@src/libs/TransactionUtils';
import {getReportOwnerAccountIDAsAttendee, getReportOwnerAsAttendee, isDistanceRequest, isTransactionPendingDelete} from '@src/libs/TransactionUtils';
import ONYXKEYS from '@src/ONYXKEYS';
import {DYNAMIC_ROUTES} from '@src/ROUTES';
import type {CardList, MergeTransaction, Policy, PolicyCategories, PolicyTagLists, Report, ReportActions, Transaction, TransactionViolations} from '@src/types/onyx';
import type {CardList, MergeTransaction, PersonalDetailsList, Policy, PolicyCategories, PolicyTagLists, Report, ReportActions, Transaction, TransactionViolations} from '@src/types/onyx';
import type {Attendee} from '@src/types/onyx/IOU';

import type {OnyxCollection, OnyxEntry, OnyxMergeInput, OnyxUpdate} from 'react-native-onyx';

Expand All @@ -47,6 +48,20 @@ import {getCleanUpTransactionThreadReportOnyxData} from './IOU/DeleteMoneyReques
import {getDeleteTrackExpenseInformation} from './IOU/TrackExpense';
import {getUpdateMoneyRequestParams, getUpdateTrackExpenseParams} from './IOU/UpdateMoneyRequest';

/**
* Resolve a transaction's report owner as a default attendee, mirroring the `useReportOwnerAsAttendee` hook so the
* non-React merge entry point can apply the same empty-attendee fallback the details/receipt pages use. The Onyx data
* is passed in by the caller rather than read from a module subscription.
*/
function getReportOwnerAsAttendeeForTransaction(
transaction: OnyxEntry<Transaction>,
currentUserAccountID: number | undefined,
personalDetails: OnyxEntry<PersonalDetailsList>,
): Attendee | undefined {
const ownerAccountID = getReportOwnerAccountIDAsAttendee(transaction, currentUserAccountID);
return getReportOwnerAsAttendee(ownerAccountID ? (personalDetails?.[ownerAccountID] ?? undefined) : undefined);
Comment thread
FitseTLT marked this conversation as resolved.
}

/**
* Setup merge transaction data for merging flow
*/
Expand Down Expand Up @@ -91,6 +106,8 @@ function setupMergeTransactionDataAndNavigate(
isSelectingSourceTransaction?: boolean,
isOnSearch?: boolean,
policies?: Array<OnyxEntry<Policy>>,
currentUserAccountID?: number,
personalDetails?: OnyxEntry<PersonalDetailsList>,
) {
if (!transactions.length || transactions.length > 2) {
return;
Expand Down Expand Up @@ -139,6 +156,8 @@ function setupMergeTransactionDataAndNavigate(
searchReports,
targetTransactionPolicy,
sourceTransactionPolicy,
getReportOwnerAsAttendeeForTransaction(targetTransaction, currentUserAccountID, personalDetails),
getReportOwnerAsAttendeeForTransaction(sourceTransaction, currentUserAccountID, personalDetails),
);
if (!conflictFields.length) {
// If there are no conflict fields, we should set mergeable data and navigate to the confirmation page
Expand Down
7 changes: 2 additions & 5 deletions src/libs/actions/TransactionEdit.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {formatCurrentUserToAttendee} from '@libs/IOUUtils';
import revokeOdometerImageUri from '@libs/OdometerUtils';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetails, Transaction} from '@src/types/onyx';
import type {Transaction} from '@src/types/onyx';

import type {Connection, OnyxEntry} from 'react-native-onyx';

Expand Down Expand Up @@ -170,18 +169,16 @@ function removeTransactionReceipt(transactionID: string | undefined) {

type BuildOptimisticTransactionParams = {
initialTransaction: Partial<Transaction>;
currentUserPersonalDetails: PersonalDetails;
reportID: string;
};

function buildOptimisticTransactionAndCreateDraft({initialTransaction, currentUserPersonalDetails, reportID}: BuildOptimisticTransactionParams): Transaction {
function buildOptimisticTransactionAndCreateDraft({initialTransaction, reportID}: BuildOptimisticTransactionParams): Transaction {
const newTransactionID = generateTransactionID();
const {currency, iouRequestType, isFromGlobalCreate, isFromFloatingActionButton} = initialTransaction ?? {};
const newTransaction = {
amount: 0,
created: format(new Date(), 'yyyy-MM-dd'),
currency,
comment: {attendees: formatCurrentUserToAttendee(currentUserPersonalDetails)},
iouRequestType,
reportID,
transactionID: newTransactionID,
Expand Down
3 changes: 1 addition & 2 deletions src/pages/Share/SubmitDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,13 @@ function SubmitDetailsPage({
report,
parentReport,
currentDate,
currentUserPersonalDetails,
hasOnlyPersonalPolicies,
draftTransactionIDs,
});
// Populate transaction.participants so IOURequestStepReport can highlight the destination (mirrors other expense flows).
setMoneyRequestParticipantsFromReport(CONST.IOU.OPTIMISTIC_TRANSACTION_ID, report, currentUserPersonalDetails.accountID);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [reportOrAccountID, policy, personalPolicy, report, parentReport, currentDate, currentUserPersonalDetails, hasOnlyPersonalPolicies]);
}, [reportOrAccountID, policy, personalPolicy, report, parentReport, currentDate, currentUserPersonalDetails.accountID, hasOnlyPersonalPolicies]);

// Use the branch-aware values computed above: for a share that needs conversion (e.g. HEIC), these resolve to the
// converted JPEG from VALIDATED_FILE_OBJECT; otherwise they fall back to the raw attachment. Re-deriving from
Expand Down
4 changes: 4 additions & 0 deletions src/pages/TransactionMerge/DynamicDetailsReviewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ function DynamicDetailsReviewPage({route}: DynamicDetailsReviewPageProps) {
[targetTransactionReport, sourceTransactionReport],
targetTransactionPolicy,
sourceTransactionPolicy,
targetReportOwnerAsAttendee,
sourceReportOwnerAsAttendee,
);

setMergeTransactionKey(transactionID, mergeableData);
Expand All @@ -91,6 +93,8 @@ function DynamicDetailsReviewPage({route}: DynamicDetailsReviewPageProps) {
targetTransactionPolicy,
sourceTransactionPolicy,
getCurrencyDecimals,
targetReportOwnerAsAttendee,
sourceReportOwnerAsAttendee,
]);

// Handle selection
Expand Down
5 changes: 5 additions & 0 deletions src/pages/TransactionMerge/DynamicReceiptReviewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import useDynamicBackPath from '@hooks/useDynamicBackPath';
import useLocalize from '@hooks/useLocalize';
import useMergeTransactions from '@hooks/useMergeTransactions';
import useOnyx from '@hooks/useOnyx';
import useReportOwnerAsAttendee from '@hooks/useReportOwnerAsAttendee';
import useThemeStyles from '@hooks/useThemeStyles';

import {setMergeTransactionKey} from '@libs/actions/MergeTransaction';
Expand Down Expand Up @@ -45,6 +46,8 @@ function DynamicReceiptReviewPage({route}: DynamicReceiptReviewPageProps) {

const [mergeTransaction, mergeTransactionMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.MERGE_TRANSACTION}${getNonEmptyStringOnyxID(transactionID)}`);
const {targetTransaction, sourceTransaction, targetTransactionPolicy, sourceTransactionPolicy} = useMergeTransactions({mergeTransaction});
const targetReportOwnerAsAttendee = useReportOwnerAsAttendee(targetTransaction);
const sourceReportOwnerAsAttendee = useReportOwnerAsAttendee(sourceTransaction);

const transactions = [targetTransaction, sourceTransaction].filter((transaction): transaction is Transaction => !!transaction);

Expand All @@ -65,6 +68,8 @@ function DynamicReceiptReviewPage({route}: DynamicReceiptReviewPageProps) {
[],
targetTransactionPolicy,
sourceTransactionPolicy,
targetReportOwnerAsAttendee,
sourceReportOwnerAsAttendee,
);
if (!conflictFields.length) {
// If there are no conflict fields, we should set mergeable data and navigate to the confirmation page
Expand Down
17 changes: 13 additions & 4 deletions src/pages/TransactionMerge/MergeTransactionsListContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ function MergeTransactionsListContent({transactionID, mergeTransaction}: MergeTr
const [searchValue, debouncedSearchValue, setSearchValue] = useDebouncedState('');

const [session] = useOnyx(ONYXKEYS.SESSION);
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
const currentUserLogin = session?.email;
const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION);
const {isOffline} = useNetwork();
Expand Down Expand Up @@ -163,10 +164,18 @@ function MergeTransactionsListContent({transactionID, mergeTransaction}: MergeTr
}

const reports = targetTransactionReport && sourceTransactionReport ? [targetTransactionReport, sourceTransactionReport] : undefined;
setupMergeTransactionDataAndNavigate(transactionID, [targetTransaction, sourceTransaction], localeCompare, getCurrencyDecimals, reports, true, undefined, [
targetTransactionPolicy,
sourceTransactionPolicy,
]);
setupMergeTransactionDataAndNavigate(
transactionID,
[targetTransaction, sourceTransaction],
localeCompare,
getCurrencyDecimals,
reports,
true,
undefined,
[targetTransactionPolicy, sourceTransactionPolicy],
session?.accountID,
personalDetails,
);
};

const confirmButtonOptions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ function useReceiptDrop({reportID, report, shouldAddOrReplaceReceipt, transactio
report,
parentReport: newParentReport,
currentDate,
currentUserPersonalDetails,
hasOnlyPersonalPolicies,
draftTransactionIDs,
});
Expand All @@ -88,7 +87,6 @@ function useReceiptDrop({reportID, report, shouldAddOrReplaceReceipt, transactio
? (initialTransaction as Partial<OnyxTypes.Transaction>)
: buildOptimisticTransactionAndCreateDraft({
initialTransaction: initialTransaction as Partial<OnyxTypes.Transaction>,
currentUserPersonalDetails,
reportID,
});
const newTransactionID = newTransaction?.transactionID ?? CONST.IOU.OPTIMISTIC_TRANSACTION_ID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ function ScanFromReport({report, iouType, reportID, transactionID, transaction,
getFileSource,
initialTransaction: transaction,
initialTransactionID: transactionID,
currentUserPersonalDetails,
reportID,
shouldAcceptMultipleFiles: true,
isMultiScanEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function ScanGlobalCreate({iouType, backToReport, ...innerProps}: ScanGlobalCrea

type ScanGlobalCreateInnerProps = Omit<ScanGlobalCreateProps, 'iouType' | 'backToReport'>;

function ScanGlobalCreateInner({reportID, transactionID, transaction, currentUserPersonalDetails}: ScanGlobalCreateInnerProps) {
function ScanGlobalCreateInner({reportID, transactionID, transaction}: ScanGlobalCreateInnerProps) {
const navigateGlobalCreate = useNavigateGlobalCreate();
const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {
selector: validTransactionDraftIDsSelector,
Expand All @@ -76,7 +76,6 @@ function ScanGlobalCreateInner({reportID, transactionID, transaction, currentUse
getFileSource,
initialTransaction: transaction,
initialTransactionID: transactionID,
currentUserPersonalDetails,
reportID,
shouldAcceptMultipleFiles: true,
isMultiScanEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,6 @@ function ScanSkipConfirmation({report, action, iouType, reportID, transactionID,
getFileSource,
initialTransaction: transaction,
initialTransactionID: transactionID,
currentUserPersonalDetails,
reportID,
shouldAcceptMultipleFiles: true,
isMultiScanEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type {ReceiptFile} from '@pages/iou/request/step/IOURequestStepScan/types
import {setMoneyRequestReceipt} from '@userActions/IOU/Receipt';
import {buildOptimisticTransactionAndCreateDraft, removeDraftTransactionsByIDs} from '@userActions/TransactionEdit';

import type {CurrentUserPersonalDetails} from '@src/types/onyx/PersonalDetails';
import type Transaction from '@src/types/onyx/Transaction';
import type {FileObject} from '@src/types/utils/Attachment';

Expand All @@ -18,7 +17,6 @@ type BuildReceiptFilesParams = {
getFileSource: (file: FileObject) => string;
initialTransaction: OnyxEntry<Transaction>;
initialTransactionID: string;
currentUserPersonalDetails: CurrentUserPersonalDetails;
reportID: string;
shouldAcceptMultipleFiles: boolean;
isMultiScanEnabled: boolean;
Expand All @@ -43,7 +41,6 @@ function buildReceiptFiles({
getFileSource,
initialTransaction,
initialTransactionID,
currentUserPersonalDetails,
reportID,
shouldAcceptMultipleFiles,
isMultiScanEnabled,
Expand All @@ -67,7 +64,6 @@ function buildReceiptFiles({
? initialTransaction
: buildOptimisticTransactionAndCreateDraft({
initialTransaction: initialTransaction as Partial<Transaction>,
currentUserPersonalDetails,
reportID,
});

Expand Down
Loading
Loading