@@ -1604,6 +1604,208 @@ describe('updateSplitTransactionsFromSplitExpensesFlow', () => {
16041604 expect ( searchSnapshot ?. data ?. [ `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ splitTransactionID1 } ` ] ) . toBeDefined ( ) ;
16051605 expect ( searchSnapshot ?. data ?. [ `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ splitTransactionID2 } ` ] ) . toBeDefined ( ) ;
16061606 } ) ;
1607+
1608+ it ( 'should mark the report for deletion when reverting a split and the single expense moves to a different report' , async ( ) => {
1609+ const amount = 10000 ;
1610+ let expenseReport : OnyxEntry < Report > ;
1611+ let chatReport : OnyxEntry < Report > ;
1612+ let originalTransactionID : string | undefined ;
1613+
1614+ // Create workspace and expense
1615+ const policyID = generatePolicyID ( ) ;
1616+ createWorkspace ( {
1617+ policyOwnerEmail : CARLOS_EMAIL ,
1618+ makeMeAdmin : true ,
1619+ policyName : "Carlos's Workspace" ,
1620+ policyID,
1621+ introSelected : { choice : CONST . ONBOARDING_CHOICES . MANAGE_TEAM } ,
1622+ currentUserAccountIDParam : CARLOS_ACCOUNT_ID ,
1623+ currentUserEmailParam : CARLOS_EMAIL ,
1624+ } ) ;
1625+ setWorkspaceApprovalMode ( policyID , CARLOS_EMAIL , CONST . POLICY . APPROVAL_MODE . BASIC ) ;
1626+ await waitForBatchedUpdates ( ) ;
1627+
1628+ await getOnyxData ( {
1629+ key : ONYXKEYS . COLLECTION . REPORT ,
1630+ waitForCollectionCallback : true ,
1631+ callback : ( allReports ) => {
1632+ chatReport = Object . values ( allReports ?? { } ) . find ( ( report ) => report ?. chatType === CONST . REPORT . CHAT_TYPE . POLICY_EXPENSE_CHAT ) ;
1633+ } ,
1634+ } ) ;
1635+
1636+ requestMoney ( {
1637+ report : chatReport ,
1638+ betas : [ CONST . BETAS . ALL ] ,
1639+ participantParams : {
1640+ payeeEmail : RORY_EMAIL ,
1641+ payeeAccountID : RORY_ACCOUNT_ID ,
1642+ participant : { login : CARLOS_EMAIL , accountID : CARLOS_ACCOUNT_ID , isPolicyExpenseChat : true , reportID : chatReport ?. reportID } ,
1643+ } ,
1644+ transactionParams : {
1645+ amount,
1646+ attendees : [ ] ,
1647+ currency : CONST . CURRENCY . USD ,
1648+ created : '' ,
1649+ merchant : 'TestMerchant' ,
1650+ comment : 'test comment' ,
1651+ } ,
1652+ shouldGenerateTransactionThreadReport : true ,
1653+ isASAPSubmitBetaEnabled : false ,
1654+ currentUserAccountIDParam : RORY_ACCOUNT_ID ,
1655+ currentUserEmailParam : RORY_EMAIL ,
1656+ transactionViolations : { } ,
1657+ policyRecentlyUsedCurrencies : [ ] ,
1658+ quickAction : undefined ,
1659+ isSelfTourViewed : false ,
1660+ personalDetails : { } ,
1661+ } ) ;
1662+ await waitForBatchedUpdates ( ) ;
1663+
1664+ await getOnyxData ( {
1665+ key : ONYXKEYS . COLLECTION . REPORT ,
1666+ waitForCollectionCallback : true ,
1667+ callback : ( allReports ) => {
1668+ expenseReport = Object . values ( allReports ?? { } ) . find ( ( report ) => report ?. type === CONST . REPORT . TYPE . EXPENSE ) ;
1669+ } ,
1670+ } ) ;
1671+ await getOnyxData ( {
1672+ key : `${ ONYXKEYS . COLLECTION . REPORT_ACTIONS } ${ expenseReport ?. reportID } ` ,
1673+ waitForCollectionCallback : false ,
1674+ callback : ( allReportActions ) => {
1675+ const iouActions = Object . values ( allReportActions ?? { } ) . filter ( ( reportAction ) : reportAction is ReportAction < typeof CONST . REPORT . ACTIONS . TYPE . IOU > =>
1676+ isMoneyRequestAction ( reportAction ) ,
1677+ ) ;
1678+ const originalMessage = isMoneyRequestAction ( iouActions ?. at ( 0 ) ) ? getOriginalMessage ( iouActions ?. at ( 0 ) ) : undefined ;
1679+ originalTransactionID = originalMessage ?. IOUTransactionID ;
1680+ } ,
1681+ } ) ;
1682+
1683+ const originalTransaction = await getOnyxValue ( `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ originalTransactionID } ` ) ;
1684+ const originalReportID = originalTransaction ?. reportID ;
1685+
1686+ // Step 1: Split into 2 (creates child transactions via creation path)
1687+ const splitTransactionID1 = rand64 ( ) ;
1688+ const splitTransactionID2 = rand64 ( ) ;
1689+
1690+ let allTransactions : OnyxCollection < Transaction > ;
1691+ let allReports : OnyxCollection < Report > ;
1692+ let allReportNameValuePairs : OnyxCollection < ReportNameValuePairs > ;
1693+ await getOnyxData ( {
1694+ key : ONYXKEYS . COLLECTION . TRANSACTION ,
1695+ waitForCollectionCallback : true ,
1696+ callback : ( value ) => {
1697+ allTransactions = value ;
1698+ } ,
1699+ } ) ;
1700+ await getOnyxData ( {
1701+ key : ONYXKEYS . COLLECTION . REPORT ,
1702+ waitForCollectionCallback : true ,
1703+ callback : ( value ) => {
1704+ allReports = value ;
1705+ } ,
1706+ } ) ;
1707+ await getOnyxData ( {
1708+ key : ONYXKEYS . COLLECTION . REPORT_NAME_VALUE_PAIRS ,
1709+ waitForCollectionCallback : true ,
1710+ callback : ( value ) => {
1711+ allReportNameValuePairs = value ;
1712+ } ,
1713+ } ) ;
1714+
1715+ updateSplitTransactionsFromSplitExpensesFlow ( {
1716+ allTransactionsList : allTransactions ,
1717+ betas : [ CONST . BETAS . ALL ] ,
1718+ allReportsList : allReports ,
1719+ allReportNameValuePairsList : allReportNameValuePairs ,
1720+ transactionData : {
1721+ reportID : originalReportID ?? String ( CONST . DEFAULT_NUMBER_ID ) ,
1722+ originalTransactionID : originalTransactionID ?? String ( CONST . DEFAULT_NUMBER_ID ) ,
1723+ splitExpenses : [
1724+ { transactionID : splitTransactionID1 , amount : amount / 2 , created : DateUtils . getDBTime ( ) } ,
1725+ { transactionID : splitTransactionID2 , amount : amount / 2 , created : DateUtils . getDBTime ( ) } ,
1726+ ] ,
1727+ } ,
1728+ policyCategories : undefined ,
1729+ policy : undefined ,
1730+ policyRecentlyUsedCategories : [ ] ,
1731+ iouReport : expenseReport ,
1732+ firstIOU : undefined ,
1733+ isASAPSubmitBetaEnabled : false ,
1734+ currentUserPersonalDetails,
1735+ transactionViolations : { } ,
1736+ policyRecentlyUsedCurrencies : [ ] ,
1737+ quickAction : undefined ,
1738+ iouReportNextStep : undefined ,
1739+ } ) ;
1740+ await waitForBatchedUpdates ( ) ;
1741+
1742+ // Verify child transactions were created (prerequisite for isReverseSplitOperation in step 2)
1743+ await getOnyxData ( {
1744+ key : ONYXKEYS . COLLECTION . TRANSACTION ,
1745+ waitForCollectionCallback : true ,
1746+ callback : ( value ) => {
1747+ allTransactions = value ;
1748+ } ,
1749+ } ) ;
1750+ const childTxs = Object . values ( allTransactions ?? { } ) . filter ( ( tx ) => tx ?. comment ?. originalTransactionID === originalTransactionID ) ;
1751+ expect ( childTxs . length ) . toBeGreaterThan ( 0 ) ;
1752+
1753+ // Step 2: Revert to 1 split expense, moving it to a different report
1754+ // This should trigger isReverseSplitOperation (1 split + existing children)
1755+ const differentReportID = rand64 ( ) ;
1756+ await getOnyxData ( {
1757+ key : ONYXKEYS . COLLECTION . REPORT ,
1758+ waitForCollectionCallback : true ,
1759+ callback : ( value ) => {
1760+ allReports = value ;
1761+ } ,
1762+ } ) ;
1763+ await getOnyxData ( {
1764+ key : ONYXKEYS . COLLECTION . REPORT_NAME_VALUE_PAIRS ,
1765+ waitForCollectionCallback : true ,
1766+ callback : ( value ) => {
1767+ allReportNameValuePairs = value ;
1768+ } ,
1769+ } ) ;
1770+
1771+ updateSplitTransactionsFromSplitExpensesFlow ( {
1772+ allTransactionsList : allTransactions ,
1773+ betas : [ CONST . BETAS . ALL ] ,
1774+ allReportsList : allReports ,
1775+ allReportNameValuePairsList : allReportNameValuePairs ,
1776+ transactionData : {
1777+ reportID : originalReportID ?? String ( CONST . DEFAULT_NUMBER_ID ) ,
1778+ originalTransactionID : originalTransactionID ?? String ( CONST . DEFAULT_NUMBER_ID ) ,
1779+ splitExpenses : [ { transactionID : splitTransactionID1 , amount, created : DateUtils . getDBTime ( ) , reportID : differentReportID } ] ,
1780+ } ,
1781+ policyCategories : undefined ,
1782+ policy : undefined ,
1783+ policyRecentlyUsedCategories : [ ] ,
1784+ iouReport : expenseReport ,
1785+ firstIOU : undefined ,
1786+ isASAPSubmitBetaEnabled : false ,
1787+ currentUserPersonalDetails,
1788+ transactionViolations : { } ,
1789+ policyRecentlyUsedCurrencies : [ ] ,
1790+ quickAction : undefined ,
1791+ iouReportNextStep : undefined ,
1792+ } ) ;
1793+ await waitForBatchedUpdates ( ) ;
1794+
1795+ // After success, the report should be removed (set to null) since no split expenses remain in the same report
1796+ const report = await new Promise < OnyxEntry < Report > > ( ( resolve ) => {
1797+ const connection = Onyx . connect ( {
1798+ key : `${ ONYXKEYS . COLLECTION . REPORT } ${ differentReportID } ` ,
1799+ callback : ( val ) => {
1800+ Onyx . disconnect ( connection ) ;
1801+ resolve ( val ) ;
1802+ } ,
1803+ } ) ;
1804+ } ) ;
1805+ // The report should be null/undefined (removed by successData) or marked for deletion (optimistic)
1806+ const isDeleted = report === null || report === undefined || report ?. pendingFields ?. preview === CONST . RED_BRICK_ROAD_PENDING_ACTION . DELETE ;
1807+ expect ( isDeleted ) . toBe ( true ) ;
1808+ } ) ;
16071809} ) ;
16081810
16091811describe ( 'updateSplitTransactionsFromSplitExpensesFlow' , ( ) => {
0 commit comments