Skip to content
Open
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
c618237
Add main change for the feature
ZhenjaHorbach Mar 6, 2026
24fcc89
Fix 0 reportID for new selfDM splits
ZhenjaHorbach Mar 6, 2026
b8a221b
Fix lint issues and revert reportID changes for selfDM splits
ZhenjaHorbach Mar 9, 2026
6cb08e4
Fix conflicts
ZhenjaHorbach Mar 13, 2026
1bc30c6
Fix prettier
ZhenjaHorbach Mar 13, 2026
f6aa247
Fix lint issues
ZhenjaHorbach Mar 13, 2026
6f491d6
Fix optimistic issues during reverting
ZhenjaHorbach Mar 13, 2026
3d4369c
Fix conflicts
ZhenjaHorbach Mar 19, 2026
6cc1cd7
Fix getChildTransactions using
ZhenjaHorbach Mar 20, 2026
4e00ea6
Fix conflicts
ZhenjaHorbach Mar 20, 2026
45820dc
Fix issues with selfDMReportIDs
ZhenjaHorbach Mar 20, 2026
58f960e
Fix conflicts
ZhenjaHorbach Mar 23, 2026
0886cb7
Fix issues with dublication transactions
ZhenjaHorbach Mar 23, 2026
83f7ab9
Fix conflicts
ZhenjaHorbach Mar 25, 2026
89b53d1
Fix a few issues with selfDm splits
ZhenjaHorbach Mar 25, 2026
33e4079
Fix a few issues with selfDm splits x2
ZhenjaHorbach Mar 25, 2026
d449ec3
Fix conflicts
ZhenjaHorbach Mar 25, 2026
2b926a6
Fix lint issues
ZhenjaHorbach Mar 25, 2026
2264cd4
Fix comments
ZhenjaHorbach Mar 26, 2026
b00ae30
Fix conflicts
ZhenjaHorbach Mar 31, 2026
5ebfe73
Fix issues with removing splits on selfdm screen
ZhenjaHorbach Apr 1, 2026
dc77015
Fix issue with negative original amount
ZhenjaHorbach Apr 1, 2026
18a4ae7
Fix issue with expenses on report screen
ZhenjaHorbach Apr 1, 2026
569001e
Fix issue with successData for original transaction
ZhenjaHorbach Apr 2, 2026
24ef703
Fix conflicts
ZhenjaHorbach Apr 2, 2026
3e25c21
Fix conflicts x2
ZhenjaHorbach Apr 2, 2026
65e4c64
Fix issues with search hash
ZhenjaHorbach Apr 2, 2026
76c7e3f
Fix conflicts
ZhenjaHorbach Apr 2, 2026
590cbd6
Fix issues with selfDM splits
ZhenjaHorbach Apr 2, 2026
0823ee8
Merge branch 'main' into add-support-unreported-expenses-for-splits
ZhenjaHorbach Apr 4, 2026
358ff06
Fix conflicts
ZhenjaHorbach Apr 6, 2026
51c4210
Fix comments
ZhenjaHorbach Apr 8, 2026
72642b0
Fix bugs
ZhenjaHorbach Apr 8, 2026
7f53154
Fix conflicts
ZhenjaHorbach Apr 8, 2026
ca80c27
Fix rate issues
ZhenjaHorbach Apr 8, 2026
cbf3239
Merge branch 'main' into add-support-unreported-expenses-for-splits
ZhenjaHorbach Apr 10, 2026
d5d1995
Fix issues with map distances for selfDM splits
ZhenjaHorbach Apr 10, 2026
c9c2fec
Fix conflicts
ZhenjaHorbach Apr 13, 2026
34712f6
Fix comments
ZhenjaHorbach Apr 13, 2026
a9b4002
Fix rates
ZhenjaHorbach Apr 13, 2026
a2e211b
Fix issue with revert negative ammounts
ZhenjaHorbach Apr 13, 2026
c1619b0
Fix spellcheck
ZhenjaHorbach Apr 13, 2026
4a5ef95
Fix issue with revert selfDM split amount
ZhenjaHorbach Apr 13, 2026
87888f3
Fix conflicts
ZhenjaHorbach Apr 16, 2026
bf82460
Fix few issues
ZhenjaHorbach Apr 17, 2026
b82cc4a
Update tests
ZhenjaHorbach Apr 17, 2026
06d2017
Fix shanpshot ids for splits
ZhenjaHorbach Apr 17, 2026
0eaeaa1
Update tags and categories logic for selfDM splits
ZhenjaHorbach Apr 17, 2026
9ec5989
Fix conflicts
ZhenjaHorbach Apr 21, 2026
43d732d
Fix conflicts x2
ZhenjaHorbach Apr 21, 2026
620f97f
Merge branch 'main' into add-support-unreported-expenses-for-splits
ZhenjaHorbach Apr 22, 2026
4ca2e67
Fix few bugs
ZhenjaHorbach Apr 22, 2026
0891539
Fix tests and update comment counts
ZhenjaHorbach Apr 22, 2026
2c1cbe4
Fix counter for selfDM splits
ZhenjaHorbach Apr 23, 2026
20c3fed
Fix conflicts
ZhenjaHorbach Apr 23, 2026
0c9c7d6
Fix tests
ZhenjaHorbach Apr 23, 2026
43c85b9
Merge branch 'main' into add-support-unreported-expenses-for-splits
ZhenjaHorbach Apr 24, 2026
43ddd15
Fix bug with empty report after removing last split in this report
ZhenjaHorbach Apr 24, 2026
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
22 changes: 12 additions & 10 deletions src/components/MoneyRequestHeaderSecondaryActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
// Per-key Onyx subscriptions
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`);
const [grandParentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${parentReport?.parentReportID}`);
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`);
const [parentReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID}`, {canEvict: false});
const parentReportAction = report?.parentReportActionID ? parentReportActions?.[report.parentReportActionID] : undefined;
Expand Down Expand Up @@ -266,18 +267,19 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
if (!transaction || !parentReportAction || !parentReport) {
return [];
}
return getSecondaryTransactionThreadActions(
currentUserLogin ?? '',
accountID,
return getSecondaryTransactionThreadActions({
currentUserLogin: currentUserLogin ?? '',
currentUserAccountID: accountID,
parentReport,
transaction,
parentReportAction,
reportTransaction: transaction,
reportAction: parentReportAction,
originalTransaction,
policy,
report,
transactionThreadReport: report,
outstandingReportsByPolicyID,
isChatIOUReportArchived,
);
isChatReportArchived: isChatIOUReportArchived,
grandParentReport,
});
})();

const secondaryActionsImplementation: Partial<
Expand Down Expand Up @@ -329,7 +331,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
icon: expensifyIcons.ArrowSplit,
value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.SPLIT,
onSelected: () => {
initSplitExpense(transaction, policy);
initSplitExpense(transaction, policy, report);
},
},
[CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.MERGE]: {
Expand Down Expand Up @@ -418,7 +420,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
}
const backToRoute = route.params?.backTo ?? Navigation.getActiveRoute();
setDeleteTransactionNavigateBackUrl(backToRoute);
if (isTrackExpenseAction(parentReportAction)) {
if (isTrackExpenseAction(parentReportAction) && !isExpenseSplit) {
deleteTrackExpense({
chatReportID: report?.parentReportID,
chatReport: parentReport,
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ function MoneyRequestView({
}

if (shouldShowSplitIndicator && isSplitAvailable) {
initSplitExpense(transaction, policy);
initSplitExpense(transaction, policy, moneyRequestReport);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useDeleteTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ function useDeleteTransactions({report, reportActions, policy}: UseDeleteTransac

for (const transactionID of Object.keys(splitTransactionsByOriginalTransactionID)) {
const splitIDs = new Set((splitTransactionsByOriginalTransactionID[transactionID] ?? []).map((transaction) => transaction.transactionID));
const childTransactions = getChildTransactions(allTransactions, allReports, transactionID).filter(
const childTransactions = getChildTransactions(allTransactions, transactionID).filter(
(transaction) => !splitIDs.has(transaction?.transactionID ?? String(CONST.DEFAULT_NUMBER_ID)),
);

Expand Down
5 changes: 2 additions & 3 deletions src/hooks/useExpenseActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
// Global collections
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION);
const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
const [allTransactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
const [allPolicyCategories] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CATEGORIES);
const [allPolicyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {selector: passthroughPolicyTagListSelector});
Expand Down Expand Up @@ -169,7 +168,7 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic

// Split indicator
const {isExpenseSplit} = getOriginalTransactionWithSplitInfo(transaction, originalTransaction);
const hasMultipleSplits = !!transaction?.comment?.originalTransactionID && getChildTransactions(allTransactions, allReports, transaction.comment.originalTransactionID).length > 1;
const hasMultipleSplits = !!transaction?.comment?.originalTransactionID && getChildTransactions(allTransactions, transaction.comment.originalTransactionID).length > 1;
const isReportOpen = isOpenReport(moneyRequestReport);
const hasSplitIndicator = isExpenseSplit && (hasMultipleSplits || isReportOpen);

Expand Down Expand Up @@ -297,7 +296,7 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
if (transactions.length !== 1) {
return;
}
initSplitExpense(currentTransaction, policy);
initSplitExpense(currentTransaction, policy, moneyRequestReport);
},
},
[CONST.REPORT.SECONDARY_ACTIONS.MERGE]: {
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSearchBulkActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
icon: expensifyIcons.ArrowSplit,
value: CONST.SEARCH.BULK_ACTION_TYPES.SPLIT,
onSelected: () => {
initSplitExpense(firstTransaction, firstTransactionPolicy);
initSplitExpense(firstTransaction, firstTransactionPolicy, firstTransactionReport);
},
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSelectedTransactionsActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ function useSelectedTransactionsActions({
icon: expensifyIcons.ArrowSplit,
value: SPLIT,
onSelected: () => {
initSplitExpense(firstTransaction, policy);
initSplitExpense(firstTransaction, policy, report);
},
});
}
Expand Down
48 changes: 34 additions & 14 deletions src/libs/ReportSecondaryActionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ function isSplitAction(
currentUserLogin: string,
currentUserAccountID: number,
policy?: OnyxEntry<Policy>,
parentReport?: OnyxEntry<Report>,
): boolean {
if (Number(reportTransactions?.length) !== 1 || !report) {
return false;
Expand Down Expand Up @@ -143,6 +144,10 @@ function isSplitAction(
return false;
}

if (isSelfDMReportUtils(report) || isSelfDMReportUtils(parentReport)) {
return true;
}

if (!isExpenseReportUtils(report)) {
return false;
}
Expand Down Expand Up @@ -851,6 +856,7 @@ function getSecondaryReportActions({
policies,
outstandingReportsByPolicyID,
isChatReportArchived = false,
parentReport,
}: {
currentUserLogin: string;
currentUserAccountID: number;
Expand All @@ -868,6 +874,7 @@ function getSecondaryReportActions({
outstandingReportsByPolicyID?: OutstandingReportsByPolicyIDDerivedValue;
canUseNewDotSplits?: boolean;
isChatReportArchived?: boolean;
parentReport?: OnyxEntry<Report>;
}): Array<ValueOf<typeof CONST.REPORT.SECONDARY_ACTIONS>> {
const options: Array<ValueOf<typeof CONST.REPORT.SECONDARY_ACTIONS>> = [];

Expand Down Expand Up @@ -962,7 +969,7 @@ function getSecondaryReportActions({
options.push(CONST.REPORT.SECONDARY_ACTIONS.REJECT);
}

if (isSplitAction(report, reportTransactions, originalTransaction, currentUserLogin, currentUserAccountID, policy)) {
if (isSplitAction(report, reportTransactions, originalTransaction, currentUserLogin, currentUserAccountID, policy, parentReport)) {
options.push(CONST.REPORT.SECONDARY_ACTIONS.SPLIT);
}

Expand Down Expand Up @@ -1048,18 +1055,31 @@ function getSecondaryExportReportActions(
return options;
}

function getSecondaryTransactionThreadActions(
currentUserLogin: string,
currentUserAccountID: number,
parentReport: Report,
reportTransaction: Transaction,
reportAction: ReportAction | undefined,
originalTransaction: OnyxEntry<Transaction>,
policy: OnyxEntry<Policy>,
transactionThreadReport?: OnyxEntry<Report>,
outstandingReportsByPolicyID?: OutstandingReportsByPolicyIDDerivedValue,
isChatReportArchived?: boolean,
): Array<ValueOf<typeof CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS>> {
function getSecondaryTransactionThreadActions({
currentUserLogin,
currentUserAccountID,
parentReport,
reportTransaction,
reportAction,
originalTransaction,
policy,
transactionThreadReport,
outstandingReportsByPolicyID,
isChatReportArchived,
grandParentReport,
}: {
currentUserLogin: string;
currentUserAccountID: number;
parentReport: Report;
reportTransaction: Transaction;
reportAction: ReportAction | undefined;
originalTransaction: OnyxEntry<Transaction>;
policy: OnyxEntry<Policy>;
transactionThreadReport?: OnyxEntry<Report>;
outstandingReportsByPolicyID?: OutstandingReportsByPolicyIDDerivedValue;
isChatReportArchived?: boolean;
grandParentReport?: OnyxEntry<Report>;
}): Array<ValueOf<typeof CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS>> {
const options: Array<ValueOf<typeof CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS>> = [];

if (!!reportAction && isHoldActionForTransaction(parentReport, reportTransaction, reportAction, policy, currentUserAccountID)) {
Expand All @@ -1074,7 +1094,7 @@ function getSecondaryTransactionThreadActions(
options.push(CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.REJECT);
}

if (isSplitAction(parentReport, [reportTransaction], originalTransaction, currentUserLogin, currentUserAccountID, policy)) {
if (isSplitAction(parentReport, [reportTransaction], originalTransaction, currentUserLogin, currentUserAccountID, policy, grandParentReport)) {
options.push(CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.SPLIT);
}

Expand Down
2 changes: 1 addition & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1037,7 +1037,7 @@
};

let conciergeReportIDOnyxConnect: OnyxEntry<string>;
Onyx.connect({

Check warning on line 1040 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.CONCIERGE_REPORT_ID,
callback: (value) => {
conciergeReportIDOnyxConnect = value;
Expand All @@ -1045,7 +1045,7 @@
});

const defaultAvatarBuildingIconTestID = 'SvgDefaultAvatarBuilding Icon';
Onyx.connect({

Check warning on line 1048 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
// When signed out, val is undefined
Expand All @@ -1063,7 +1063,7 @@
let allPersonalDetails: OnyxEntry<PersonalDetailsList>;
let allPersonalDetailLogins: string[];
let currentUserPersonalDetails: OnyxEntry<PersonalDetails>;
Onyx.connect({

Check warning on line 1066 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
if (deprecatedCurrentUserAccountID) {
Expand All @@ -1075,7 +1075,7 @@
});

let allReportsDraft: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 1078 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_DRAFT,
waitForCollectionCallback: true,
callback: (value) => (allReportsDraft = value),
Expand All @@ -1083,7 +1083,7 @@

let allPolicies: OnyxCollection<Policy>;
let policiesArray: Policy[] = [];
Onyx.connect({

Check warning on line 1086 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -1093,7 +1093,7 @@
});

let allPolicyDrafts: OnyxCollection<Policy>;
Onyx.connect({

Check warning on line 1096 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY_DRAFTS,
waitForCollectionCallback: true,
callback: (value) => (allPolicyDrafts = value),
Expand All @@ -1101,7 +1101,7 @@

let deprecatedAllReports: OnyxCollection<Report>;
let deprecatedReportsByPolicyID: ReportByPolicyMap;
Onyx.connect({

Check warning on line 1104 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand Down Expand Up @@ -1137,14 +1137,14 @@
});

let betaConfiguration: OnyxEntry<BetaConfiguration> = {};
Onyx.connect({

Check warning on line 1140 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.BETA_CONFIGURATION,
callback: (value) => (betaConfiguration = value ?? {}),
});

let deprecatedAllTransactions: OnyxCollection<Transaction> = {};
let deprecatedReportsTransactions: Record<string, Transaction[]> = {};
Onyx.connect({

Check warning on line 1147 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION,
waitForCollectionCallback: true,
callback: (value) => {
Expand Down Expand Up @@ -7216,7 +7216,7 @@

if (type !== CONST.IOU.REPORT_ACTION_TYPE.PAY) {
// Split expense made from a policy expense chat only have the payee's accountID as the participant because the payer could be any policy admin
if (isOwnPolicyExpenseChat && type === CONST.IOU.REPORT_ACTION_TYPE.SPLIT) {
if ((isOwnPolicyExpenseChat && type === CONST.IOU.REPORT_ACTION_TYPE.SPLIT) || isPersonalTrackingExpense) {
originalMessage.participantAccountIDs = deprecatedCurrentUserAccountID ? [deprecatedCurrentUserAccountID] : [];
} else {
originalMessage.participantAccountIDs = deprecatedCurrentUserAccountID
Expand Down
12 changes: 3 additions & 9 deletions src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2688,20 +2688,14 @@ function isTransactionPendingDelete(transaction: OnyxEntry<Transaction>): boolea

/**
* Retrieves all "child" transactions associated with a given original transaction.
* By default excludes orphaned transactions (reportID '0'). Use includeOrphaned=true for counting.
*/
function getChildTransactions(transactions: OnyxCollection<Transaction>, reports: OnyxCollection<Report>, originalTransactionID: string | undefined, includeOrphaned = false) {
function getChildTransactions(transactions: OnyxCollection<Transaction>, originalTransactionID: string | undefined) {
return Object.values(transactions ?? {}).filter((currentTransaction) => {
const isSplitChild = currentTransaction?.comment?.originalTransactionID === originalTransactionID;
if (!isSplitChild || currentTransaction?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) {
return false;
}
const isOrphaned = currentTransaction?.reportID === CONST.REPORT.UNREPORTED_REPORT_ID;
if (isOrphaned) {
return includeOrphaned;
}
const currentReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${currentTransaction?.reportID}`];
return !!currentReport || currentTransaction?.comment?.source === CONST.IOU.TYPE.SPLIT;
return currentTransaction?.comment?.source === CONST.IOU.TYPE.SPLIT;
});
}

Expand All @@ -2712,7 +2706,7 @@ function hasMultipleSplitChildren(transactions: OnyxCollection<Transaction>, rep
if (!originalTransactionID) {
return false;
}
return getChildTransactions(transactions, reports, originalTransactionID).length > 1;
return getChildTransactions(transactions, originalTransactionID).length > 1;
}

/**
Expand Down
Loading
Loading