@@ -129,6 +129,7 @@ import {
129129 buildOptimisticUnHoldReportAction ,
130130 canBeAutoReimbursed ,
131131 canUserPerformWriteAction as canUserPerformWriteActionReportUtils ,
132+ findSelfDMReportID ,
132133 getAllHeldTransactions as getAllHeldTransactionsReportUtils ,
133134 getAllPolicyReports ,
134135 getApprovalChain ,
@@ -143,6 +144,7 @@ import {
143144 getPersonalDetailsForAccountID ,
144145 getReportNotificationPreference ,
145146 getReportOrDraftReport ,
147+ getReportRecipientAccountIDs ,
146148 getReportTransactions ,
147149 getTransactionDetails ,
148150 hasHeldExpenses as hasHeldExpensesReportUtils ,
@@ -5059,6 +5061,161 @@ function convertTrackedExpenseToRequest(convertTrackedExpenseParams: ConvertTrac
50595061 API . write ( WRITE_COMMANDS . CONVERT_TRACKED_EXPENSE_TO_REQUEST , parameters , { optimisticData, successData, failureData} ) ;
50605062}
50615063
5064+ /**
5065+ * Move multiple tracked expenses from self-DM to an IOU report
5066+ */
5067+ function convertBulkTrackedExpensesToIOU ( transactionIDs : string [ ] , targetReportID : string ) {
5068+ const iouReport = allReports ?. [ `${ ONYXKEYS . COLLECTION . REPORT } ${ targetReportID } ` ] ;
5069+
5070+ if ( ! iouReport || ! isMoneyRequestReportReportUtils ( iouReport ) ) {
5071+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Invalid IOU report' , { targetReportID} ) ;
5072+ return ;
5073+ }
5074+
5075+ const chatReportID = iouReport . chatReportID ;
5076+ if ( ! chatReportID ) {
5077+ Log . warn ( '[convertBulkTrackedExpensesToIOU] No chat report found for IOU' , { targetReportID} ) ;
5078+ return ;
5079+ }
5080+
5081+ const chatReport = allReports ?. [ `${ ONYXKEYS . COLLECTION . REPORT } ${ chatReportID } ` ] ;
5082+ if ( ! chatReport ) {
5083+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Chat report not found' , { chatReportID} ) ;
5084+ return ;
5085+ }
5086+
5087+ const participantAccountIDs = getReportRecipientAccountIDs ( iouReport , userAccountID ) ;
5088+ const payerAccountID = participantAccountIDs . at ( 0 ) ;
5089+
5090+ if ( ! payerAccountID ) {
5091+ Log . warn ( '[convertBulkTrackedExpensesToIOU] No payer found' , { targetReportID, participantAccountIDs} ) ;
5092+ return ;
5093+ }
5094+
5095+ const payerEmail = personalDetailsList ?. [ payerAccountID ] ?. login ?? '' ;
5096+ const selfDMReportID = findSelfDMReportID ( ) ;
5097+
5098+ if ( ! selfDMReportID ) {
5099+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Self DM not found' ) ;
5100+ return ;
5101+ }
5102+
5103+ const selfDMReportActions = getAllReportActions ( selfDMReportID ) ;
5104+
5105+ transactionIDs . forEach ( ( transactionID ) => {
5106+ const transaction = allTransactions ?. [ `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ transactionID } ` ] ;
5107+ if ( ! transaction ) {
5108+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Transaction not found' , { transactionID} ) ;
5109+ return ;
5110+ }
5111+
5112+ const linkedTrackedExpenseReportAction = Object . values ( selfDMReportActions ) . find ( ( action ) => {
5113+ if ( ! isMoneyRequestAction ( action ) ) {
5114+ return false ;
5115+ }
5116+ const originalMessage = getOriginalMessage ( action ) ;
5117+ return originalMessage ?. IOUTransactionID === transactionID ;
5118+ } ) ;
5119+
5120+ if ( ! linkedTrackedExpenseReportAction ) {
5121+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Tracked expense IOU action not found' , { transactionID} ) ;
5122+ return ;
5123+ }
5124+
5125+ const actionableWhisperReportActionID = getTrackExpenseActionableWhisper ( transactionID , selfDMReportID ) ?. reportActionID ;
5126+
5127+ const commentText = typeof transaction . comment === 'string' ? transaction . comment : ( transaction . comment ?. comment ?? '' ) ;
5128+ const parsedComment = getParsedComment ( commentText ) ;
5129+
5130+ const attendees = transaction . comment ?. attendees ;
5131+
5132+ const transactionThreadReportID = ( linkedTrackedExpenseReportAction as OnyxTypes . ReportAction ) . childReportID ;
5133+
5134+ if ( ! transactionThreadReportID ) {
5135+ Log . warn ( '[convertBulkTrackedExpensesToIOU] No transaction thread found for tracked expense, skipping' , {
5136+ transactionID,
5137+ actionReportActionID : ( linkedTrackedExpenseReportAction as OnyxTypes . ReportAction ) . reportActionID ,
5138+ } ) ;
5139+ return ;
5140+ }
5141+
5142+ const participantParams = {
5143+ payeeAccountID : userAccountID ,
5144+ payeeEmail : currentUserEmail ,
5145+ participant : {
5146+ accountID : payerAccountID ,
5147+ login : payerEmail ,
5148+ } ,
5149+ } ;
5150+
5151+ const transactionParams = {
5152+ amount : getAmount ( transaction ) ,
5153+ currency : getCurrency ( transaction ) ,
5154+ comment : parsedComment ,
5155+ merchant : getMerchant ( transaction ) ,
5156+ created : transaction . created ,
5157+ attendees,
5158+ actionableWhisperReportActionID,
5159+ linkedTrackedExpenseReportAction,
5160+ linkedTrackedExpenseReportID : selfDMReportID ,
5161+ } ;
5162+
5163+ const {
5164+ payerAccountID : moneyRequestPayerAccountID ,
5165+ payerEmail : moneyRequestPayerEmail ,
5166+ iouReport : moneyRequestIOUReport ,
5167+ chatReport : moneyRequestChatReport ,
5168+ transaction : moneyRequestTransaction ,
5169+ iouAction,
5170+ createdChatReportActionID,
5171+ createdIOUReportActionID,
5172+ reportPreviewAction,
5173+ transactionThreadReportID : moneyRequestTransactionThreadReportID ,
5174+ onyxData,
5175+ } = getMoneyRequestInformation ( {
5176+ parentChatReport : chatReport ,
5177+ participantParams,
5178+ transactionParams,
5179+ moneyRequestReportID : targetReportID ,
5180+ existingTransactionID : transactionID ,
5181+ existingTransaction : transaction ,
5182+ } ) ;
5183+
5184+ const convertParams : ConvertTrackedExpenseToRequestParams = {
5185+ payerParams : {
5186+ accountID : moneyRequestPayerAccountID ,
5187+ email : moneyRequestPayerEmail ,
5188+ } ,
5189+ transactionParams : {
5190+ amount : getAmount ( transaction ) ,
5191+ currency : getCurrency ( transaction ) ,
5192+ comment : parsedComment ,
5193+ merchant : getMerchant ( transaction ) ,
5194+ created : transaction . created ,
5195+ attendees,
5196+ transactionID : moneyRequestTransaction . transactionID ,
5197+ actionableWhisperReportActionID,
5198+ linkedTrackedExpenseReportAction,
5199+ linkedTrackedExpenseReportID : selfDMReportID ,
5200+ transactionThreadReportID : moneyRequestTransactionThreadReportID ,
5201+ } ,
5202+ chatParams : {
5203+ reportID : moneyRequestChatReport . reportID ,
5204+ createdReportActionID : createdChatReportActionID ,
5205+ reportPreviewReportActionID : reportPreviewAction . reportActionID ,
5206+ } ,
5207+ iouParams : {
5208+ reportID : moneyRequestIOUReport . reportID ,
5209+ createdReportActionID : createdIOUReportActionID ,
5210+ reportActionID : iouAction . reportActionID ,
5211+ } ,
5212+ onyxData,
5213+ } ;
5214+
5215+ convertTrackedExpenseToRequest ( convertParams ) ;
5216+ } ) ;
5217+ }
5218+
50625219function categorizeTrackedExpense ( trackedExpenseParams : TrackedExpenseParams ) {
50635220 const { onyxData, reportInformation, transactionParams, policyParams, createdWorkspaceParams} = trackedExpenseParams ;
50645221 const { optimisticData, successData, failureData} = onyxData ?? { } ;
@@ -11846,6 +12003,7 @@ export {
1184612003 dismissModalAndOpenReportInInboxTab ,
1184712004 navigateToStartStepIfScanFileCannotBeRead ,
1184812005 completePaymentOnboarding ,
12006+ convertBulkTrackedExpensesToIOU ,
1184912007 payInvoice ,
1185012008 payMoneyRequest ,
1185112009 putOnHold ,
0 commit comments