@@ -69,6 +69,7 @@ import {handleUnvalidatedAccount, selectPaymentType} from '@libs/PaymentUtils';
6969import { getConnectedIntegration , getValidConnectedIntegration , hasDynamicExternalWorkflow , sortPoliciesByName } from '@libs/PolicyUtils' ;
7070import {
7171 getIOUActionForReportID ,
72+ getIOUActionForTransactionID ,
7273 getOriginalMessage ,
7374 getReportAction ,
7475 hasPendingDEWApprove ,
@@ -79,6 +80,8 @@ import {
7980import { getAllExpensesToHoldIfApplicable , getReportPrimaryAction , isMarkAsResolvedAction } from '@libs/ReportPrimaryActionUtils' ;
8081import { getSecondaryExportReportActions , getSecondaryReportActions } from '@libs/ReportSecondaryActionUtils' ;
8182import {
83+ canEditFieldOfMoneyRequest ,
84+ canUserPerformWriteAction as canUserPerformWriteActionReportUtils ,
8285 changeMoneyRequestHoldStatus ,
8386 generateReportID ,
8487 getAddExpenseDropdownOptions ,
@@ -298,6 +301,7 @@ function MoneyReportHeader({
298301 'Checkmark' ,
299302 'ReportCopy' ,
300303 'Printer' ,
304+ 'DocumentMerge' ,
301305 ] as const ) ;
302306 const [ lastDistanceExpenseType ] = useOnyx ( ONYXKEYS . NVP_LAST_DISTANCE_EXPENSE_TYPE ) ;
303307 const [ reportMetadata ] = useOnyx ( `${ ONYXKEYS . COLLECTION . REPORT_METADATA } ${ moneyRequestReport ?. reportID } ` ) ;
@@ -382,6 +386,7 @@ function MoneyReportHeader({
382386 const [ downloadErrorModalVisible , setDownloadErrorModalVisible ] = useState ( false ) ;
383387 const [ isPDFModalVisible , setIsPDFModalVisible ] = useState ( false ) ;
384388 const [ introSelected ] = useOnyx ( ONYXKEYS . NVP_INTRO_SELECTED ) ;
389+ const [ outstandingReportsByPolicyID ] = useOnyx ( ONYXKEYS . DERIVED . OUTSTANDING_REPORTS_BY_POLICY_ID ) ;
385390 const currentTransaction = transactions . at ( 0 ) ;
386391 const [ originalIOUTransaction ] = useOnyx ( `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ getNonEmptyStringOnyxID ( currentTransaction ?. comment ?. originalTransactionID ) } ` ) ;
387392 const [ originalTransaction ] = useOnyx ( `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ getNonEmptyStringOnyxID ( transaction ?. comment ?. originalTransactionID ) } ` ) ;
@@ -468,6 +473,24 @@ function MoneyReportHeader({
468473 const isArchivedReport = useReportIsArchived ( moneyRequestReport ?. reportID ) ;
469474 const isChatReportArchived = useReportIsArchived ( chatReport ?. reportID ) ;
470475
476+ const canMoveSingleExpense = useMemo ( ( ) => {
477+ if ( nonPendingDeleteTransactions . length !== 1 ) {
478+ return false ;
479+ }
480+
481+ const transactionToMove = nonPendingDeleteTransactions . at ( 0 ) ;
482+ if ( ! transactionToMove ) {
483+ return false ;
484+ }
485+
486+ const iouReportAction = getIOUActionForTransactionID ( reportActions , transactionToMove . transactionID ) ;
487+ const canMoveExpense = canEditFieldOfMoneyRequest ( iouReportAction , CONST . EDIT_REQUEST_FIELD . REPORT , undefined , isChatReportArchived , outstandingReportsByPolicyID ) ;
488+
489+ const canUserPerformWriteAction = canUserPerformWriteActionReportUtils ( moneyRequestReport , isChatReportArchived ) ;
490+
491+ return canMoveExpense && canUserPerformWriteAction ;
492+ } , [ nonPendingDeleteTransactions , reportActions , isChatReportArchived , outstandingReportsByPolicyID , moneyRequestReport ] ) ;
493+
471494 const [ archiveReason ] = useOnyx ( `${ ONYXKEYS . COLLECTION . REPORT_ACTIONS } ${ moneyRequestReport ?. reportID } ` , { selector : getArchiveReason } ) ;
472495
473496 const [ reportNameValuePairs ] = useOnyx ( `${ ONYXKEYS . COLLECTION . REPORT_NAME_VALUE_PAIRS } ${ moneyRequestReport ?. reportID } ` ) ;
@@ -508,7 +531,7 @@ function MoneyReportHeader({
508531 > | null > ( null ) ;
509532
510533 const { selectedTransactionIDs, currentSearchQueryJSON, currentSearchKey, currentSearchHash, currentSearchResults} = useSearchStateContext ( ) ;
511- const { removeTransaction, clearSelectedTransactions} = useSearchActionsContext ( ) ;
534+ const { removeTransaction, clearSelectedTransactions, setSelectedTransactions } = useSearchActionsContext ( ) ;
512535 const shouldCalculateTotals = useSearchShouldCalculateTotals ( currentSearchKey , currentSearchQueryJSON ?. hash , true ) ;
513536
514537 const [ shouldFailAllRequests ] = useOnyx ( ONYXKEYS . NETWORK , { selector : shouldFailAllRequestsSelector } ) ;
@@ -1481,6 +1504,7 @@ function MoneyReportHeader({
14811504 reportActions,
14821505 reportMetadata,
14831506 policies,
1507+ outstandingReportsByPolicyID,
14841508 isChatReportArchived,
14851509 } ) ;
14861510 } , [
@@ -1498,6 +1522,7 @@ function MoneyReportHeader({
14981522 policies ,
14991523 isChatReportArchived ,
15001524 bankAccountList ,
1525+ outstandingReportsByPolicyID ,
15011526 ] ) ;
15021527
15031528 const secondaryExportActions = useMemo ( ( ) => {
@@ -1862,6 +1887,24 @@ function MoneyReportHeader({
18621887 Navigation . navigate ( ROUTES . REPORT_WITH_ID_CHANGE_WORKSPACE . getRoute ( moneyRequestReport . reportID , Navigation . getActiveRoute ( ) ) ) ;
18631888 } ,
18641889 } ,
1890+ [ CONST . REPORT . SECONDARY_ACTIONS . MOVE_EXPENSE ] : {
1891+ text : translate ( 'iou.moveExpenses' ) ,
1892+ icon : expensifyIcons . DocumentMerge ,
1893+ value : CONST . REPORT . SECONDARY_ACTIONS . MOVE_EXPENSE ,
1894+ sentryLabel : CONST . SENTRY_LABEL . MORE_MENU . MOVE_EXPENSE ,
1895+ shouldShow : canMoveSingleExpense ,
1896+ onSelected : ( ) => {
1897+ if ( ! moneyRequestReport || nonPendingDeleteTransactions . length !== 1 ) {
1898+ return ;
1899+ }
1900+ const transactionToMove = nonPendingDeleteTransactions . at ( 0 ) ;
1901+ if ( ! transactionToMove ?. transactionID ) {
1902+ return ;
1903+ }
1904+ setSelectedTransactions ( [ transactionToMove . transactionID ] ) ;
1905+ Navigation . navigate ( ROUTES . MONEY_REQUEST_EDIT_REPORT . getRoute ( CONST . IOU . ACTION . EDIT , CONST . IOU . TYPE . SUBMIT , moneyRequestReport . reportID , true , Navigation . getActiveRoute ( ) ) ) ;
1906+ } ,
1907+ } ,
18651908 [ CONST . REPORT . SECONDARY_ACTIONS . CHANGE_APPROVER ] : {
18661909 text : translate ( 'iou.changeApprover.title' ) ,
18671910 icon : expensifyIcons . Workflows ,
0 commit comments