@@ -131,6 +131,7 @@ import {
131131 buildOptimisticUnHoldReportAction ,
132132 canBeAutoReimbursed ,
133133 canUserPerformWriteAction as canUserPerformWriteActionReportUtils ,
134+ findSelfDMReportID ,
134135 getAllHeldTransactions as getAllHeldTransactionsReportUtils ,
135136 getAllPolicyReports ,
136137 getApprovalChain ,
@@ -145,6 +146,7 @@ import {
145146 getPersonalDetailsForAccountID ,
146147 getReportNotificationPreference ,
147148 getReportOrDraftReport ,
149+ getReportRecipientAccountIDs ,
148150 getReportTransactions ,
149151 getTransactionDetails ,
150152 hasHeldExpenses as hasHeldExpensesReportUtils ,
@@ -5074,6 +5076,161 @@ function convertTrackedExpenseToRequest(convertTrackedExpenseParams: ConvertTrac
50745076 API . write ( WRITE_COMMANDS . CONVERT_TRACKED_EXPENSE_TO_REQUEST , parameters , { optimisticData, successData, failureData} ) ;
50755077}
50765078
5079+ /**
5080+ * Move multiple tracked expenses from self-DM to an IOU report
5081+ */
5082+ function convertBulkTrackedExpensesToIOU ( transactionIDs : string [ ] , targetReportID : string ) {
5083+ const iouReport = allReports ?. [ `${ ONYXKEYS . COLLECTION . REPORT } ${ targetReportID } ` ] ;
5084+
5085+ if ( ! iouReport || ! isMoneyRequestReportReportUtils ( iouReport ) ) {
5086+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Invalid IOU report' , { targetReportID} ) ;
5087+ return ;
5088+ }
5089+
5090+ const chatReportID = iouReport . chatReportID ;
5091+ if ( ! chatReportID ) {
5092+ Log . warn ( '[convertBulkTrackedExpensesToIOU] No chat report found for IOU' , { targetReportID} ) ;
5093+ return ;
5094+ }
5095+
5096+ const chatReport = allReports ?. [ `${ ONYXKEYS . COLLECTION . REPORT } ${ chatReportID } ` ] ;
5097+ if ( ! chatReport ) {
5098+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Chat report not found' , { chatReportID} ) ;
5099+ return ;
5100+ }
5101+
5102+ const participantAccountIDs = getReportRecipientAccountIDs ( iouReport , userAccountID ) ;
5103+ const payerAccountID = participantAccountIDs . at ( 0 ) ;
5104+
5105+ if ( ! payerAccountID ) {
5106+ Log . warn ( '[convertBulkTrackedExpensesToIOU] No payer found' , { targetReportID, participantAccountIDs} ) ;
5107+ return ;
5108+ }
5109+
5110+ const payerEmail = personalDetailsList ?. [ payerAccountID ] ?. login ?? '' ;
5111+ const selfDMReportID = findSelfDMReportID ( ) ;
5112+
5113+ if ( ! selfDMReportID ) {
5114+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Self DM not found' ) ;
5115+ return ;
5116+ }
5117+
5118+ const selfDMReportActions = getAllReportActions ( selfDMReportID ) ;
5119+
5120+ transactionIDs . forEach ( ( transactionID ) => {
5121+ const transaction = allTransactions ?. [ `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ transactionID } ` ] ;
5122+ if ( ! transaction ) {
5123+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Transaction not found' , { transactionID} ) ;
5124+ return ;
5125+ }
5126+
5127+ const linkedTrackedExpenseReportAction = Object . values ( selfDMReportActions ) . find ( ( action ) => {
5128+ if ( ! isMoneyRequestAction ( action ) ) {
5129+ return false ;
5130+ }
5131+ const originalMessage = getOriginalMessage ( action ) ;
5132+ return originalMessage ?. IOUTransactionID === transactionID ;
5133+ } ) ;
5134+
5135+ if ( ! linkedTrackedExpenseReportAction ) {
5136+ Log . warn ( '[convertBulkTrackedExpensesToIOU] Tracked expense IOU action not found' , { transactionID} ) ;
5137+ return ;
5138+ }
5139+
5140+ const actionableWhisperReportActionID = getTrackExpenseActionableWhisper ( transactionID , selfDMReportID ) ?. reportActionID ;
5141+
5142+ const commentText = typeof transaction . comment === 'string' ? transaction . comment : ( transaction . comment ?. comment ?? '' ) ;
5143+ const parsedComment = getParsedComment ( commentText ) ;
5144+
5145+ const attendees = transaction . comment ?. attendees ;
5146+
5147+ const transactionThreadReportID = ( linkedTrackedExpenseReportAction as OnyxTypes . ReportAction ) . childReportID ;
5148+
5149+ if ( ! transactionThreadReportID ) {
5150+ Log . warn ( '[convertBulkTrackedExpensesToIOU] No transaction thread found for tracked expense, skipping' , {
5151+ transactionID,
5152+ actionReportActionID : ( linkedTrackedExpenseReportAction as OnyxTypes . ReportAction ) . reportActionID ,
5153+ } ) ;
5154+ return ;
5155+ }
5156+
5157+ const participantParams = {
5158+ payeeAccountID : userAccountID ,
5159+ payeeEmail : currentUserEmail ,
5160+ participant : {
5161+ accountID : payerAccountID ,
5162+ login : payerEmail ,
5163+ } ,
5164+ } ;
5165+
5166+ const transactionParams = {
5167+ amount : getAmount ( transaction ) ,
5168+ currency : getCurrency ( transaction ) ,
5169+ comment : parsedComment ,
5170+ merchant : getMerchant ( transaction ) ,
5171+ created : transaction . created ,
5172+ attendees,
5173+ actionableWhisperReportActionID,
5174+ linkedTrackedExpenseReportAction,
5175+ linkedTrackedExpenseReportID : selfDMReportID ,
5176+ } ;
5177+
5178+ const {
5179+ payerAccountID : moneyRequestPayerAccountID ,
5180+ payerEmail : moneyRequestPayerEmail ,
5181+ iouReport : moneyRequestIOUReport ,
5182+ chatReport : moneyRequestChatReport ,
5183+ transaction : moneyRequestTransaction ,
5184+ iouAction,
5185+ createdChatReportActionID,
5186+ createdIOUReportActionID,
5187+ reportPreviewAction,
5188+ transactionThreadReportID : moneyRequestTransactionThreadReportID ,
5189+ onyxData,
5190+ } = getMoneyRequestInformation ( {
5191+ parentChatReport : chatReport ,
5192+ participantParams,
5193+ transactionParams,
5194+ moneyRequestReportID : targetReportID ,
5195+ existingTransactionID : transactionID ,
5196+ existingTransaction : transaction ,
5197+ } ) ;
5198+
5199+ const convertParams : ConvertTrackedExpenseToRequestParams = {
5200+ payerParams : {
5201+ accountID : moneyRequestPayerAccountID ,
5202+ email : moneyRequestPayerEmail ,
5203+ } ,
5204+ transactionParams : {
5205+ amount : getAmount ( transaction ) ,
5206+ currency : getCurrency ( transaction ) ,
5207+ comment : parsedComment ,
5208+ merchant : getMerchant ( transaction ) ,
5209+ created : transaction . created ,
5210+ attendees,
5211+ transactionID : moneyRequestTransaction . transactionID ,
5212+ actionableWhisperReportActionID,
5213+ linkedTrackedExpenseReportAction,
5214+ linkedTrackedExpenseReportID : selfDMReportID ,
5215+ transactionThreadReportID : moneyRequestTransactionThreadReportID ,
5216+ } ,
5217+ chatParams : {
5218+ reportID : moneyRequestChatReport . reportID ,
5219+ createdReportActionID : createdChatReportActionID ,
5220+ reportPreviewReportActionID : reportPreviewAction . reportActionID ,
5221+ } ,
5222+ iouParams : {
5223+ reportID : moneyRequestIOUReport . reportID ,
5224+ createdReportActionID : createdIOUReportActionID ,
5225+ reportActionID : iouAction . reportActionID ,
5226+ } ,
5227+ onyxData,
5228+ } ;
5229+
5230+ convertTrackedExpenseToRequest ( convertParams ) ;
5231+ } ) ;
5232+ }
5233+
50775234function categorizeTrackedExpense ( trackedExpenseParams : TrackedExpenseParams ) {
50785235 const { onyxData, reportInformation, transactionParams, policyParams, createdWorkspaceParams} = trackedExpenseParams ;
50795236 const { optimisticData, successData, failureData} = onyxData ?? { } ;
@@ -11902,6 +12059,7 @@ export {
1190212059 dismissModalAndOpenReportInInboxTab ,
1190312060 navigateToStartStepIfScanFileCannotBeRead ,
1190412061 completePaymentOnboarding ,
12062+ convertBulkTrackedExpensesToIOU ,
1190512063 payInvoice ,
1190612064 payMoneyRequest ,
1190712065 putOnHold ,
0 commit comments