From f8196565c1dbfe5ec6c543d03d87d914e1f60bda Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 27 Jul 2023 01:05:06 +0100 Subject: [PATCH 01/45] Add the editTransaction method --- src/libs/actions/IOU.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index b7713c6224d2..1a8d6eec788a 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -771,6 +771,27 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou Report.notifyNewAction(groupData.chatReportID, currentUserAccountID); } +/** + * @param {String} transactionID + * @param {String} transactionThreadReportID + */ +function editTransaction(transactionID, transactionThreadReportID) { + // STEP 1: Get all collections we're updating + let transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; + const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; + const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`]; + const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(iouReport.chatReportID, iouReport.reportID); + const chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`]; + API.write( + 'DeleteMoneyRequest', + { + transactionID, + reportActionID: reportAction.reportActionID, + }, + {optimisticData, successData, failureData}, + ); +} + /** * @param {String} transactionID * @param {Object} reportAction - the money request reportAction we are deleting @@ -1489,6 +1510,7 @@ function setMoneyRequestParticipants(participants) { } export { + editTransaction, deleteMoneyRequest, splitBill, splitBillAndOpenReport, From 9eb3ef71f1a60cb8e12db06be4be6786aaeb194c Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 27 Jul 2023 02:12:55 +0100 Subject: [PATCH 02/45] Adding skeleton for the optimistic data --- src/languages/en.js | 1 + src/languages/es.js | 1 + src/libs/actions/IOU.js | 8 ++++++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index b7a130addf18..32a5f4503c24 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -382,6 +382,7 @@ export default { other: 'Unexpected error, please try again later', genericCreateFailureMessage: 'Unexpected error requesting money, please try again later', genericDeleteFailureMessage: 'Unexpected error deleting the money request, please try again later', + genericEditFailureMessage: 'Unexpected error editing the money request, please try again later', }, }, notificationPreferencesPage: { diff --git a/src/languages/es.js b/src/languages/es.js index 4006f559eb1f..cc9f1d532d67 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -381,6 +381,7 @@ export default { other: 'Error inesperado, por favor inténtalo más tarde', genericCreateFailureMessage: 'Error inesperado solicitando dinero, Por favor, inténtalo más tarde', genericDeleteFailureMessage: 'Error inesperado eliminando la solicitud de dinero. Por favor, inténtalo más tarde', + genericEditFailureMessage: 'Unexpected error editing the money request, please try again later', }, }, notificationPreferencesPage: { diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 1a8d6eec788a..e379a7e735c9 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -775,7 +775,7 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou * @param {String} transactionID * @param {String} transactionThreadReportID */ -function editTransaction(transactionID, transactionThreadReportID) { +function editIOUTransaction(transactionID, transactionThreadReportID) { // STEP 1: Get all collections we're updating let transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; @@ -783,10 +783,14 @@ function editTransaction(transactionID, transactionThreadReportID) { const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(iouReport.chatReportID, iouReport.reportID); const chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`]; API.write( - 'DeleteMoneyRequest', + 'EditIOUTransaction', { transactionID, reportActionID: reportAction.reportActionID, + created: transaction.created, + amount: transaction.amount, + currency: transaction.currency, + comment: transaction.comment, }, {optimisticData, successData, failureData}, ); From d8d632a9728312b13939de96372d5e1037a90136 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 16:34:08 +0100 Subject: [PATCH 03/45] Add modified expense action type --- src/CONST.js | 1 + src/libs/OptionsListUtils.js | 3 +++ src/libs/ReportActionsUtils.js | 9 ++++++++ src/libs/ReportUtils.js | 41 ++++++++++++++++++++++++++++++++++ src/libs/actions/IOU.js | 2 +- 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/CONST.js b/src/CONST.js index 06bc1873431f..4277fc0fb2f9 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -491,6 +491,7 @@ const CONST = { TASKEDITED: 'TASKEDITED', TASKCANCELLED: 'TASKCANCELLED', IOU: 'IOU', + MODIFIEDEXPENSE: 'MODIFIEDEXPENSE', REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED', RENAMED: 'RENAMED', CHRONOSOOOLIST: 'CHRONOSOOOLIST', diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 7eff3904ea16..a6a7700bc51a 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -386,6 +386,9 @@ function getLastMessageTextForReport(report) { } else if (ReportActionUtils.isReportPreviewAction(lastReportAction)) { const iouReport = ReportUtils.getReport(ReportActionUtils.getIOUReportIDFromReportActionPreview(lastReportAction)); lastMessageTextFromReport = ReportUtils.getReportPreviewMessage(iouReport, lastReportAction); + } else if (ReportActionUtils.isModifiedExpenseAction(lastReportAction)) { + const iouReport = ReportUtils.getParentReport(report); getReport(ReportActionUtils.getIOUReportIDFromReportActionPreview(lastReportAction)); + lastMessageTextFromReport = ReportUtils.getModifiedExpenseMessage(iouReport, report, lastReportAction); } else { lastMessageTextFromReport = report ? report.lastMessageText || '' : ''; diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 3cd5621e5e32..dff0f1cf61d8 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -93,6 +93,14 @@ function isReportPreviewAction(reportAction) { return lodashGet(reportAction, 'actionName', '') === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW; } +/** + * @param {Object} reportAction + * @returns {Boolean} + */ +function isModifiedExpenseAction(reportAction) { + return lodashGet(reportAction, 'actionName', '') === CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE; +} + function isWhisperAction(action) { return (action.whisperedToAccountIDs || []).length > 0; } @@ -588,6 +596,7 @@ export { isSentMoneyReportAction, isDeletedParentAction, isReportPreviewAction, + isModifiedExpenseAction, getIOUReportIDFromReportActionPreview, isMessageDeleted, isWhisperAction, diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 0050aa4fc989..09f997f42a11 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1231,6 +1231,46 @@ function getReportPreviewMessage(report, reportAction = {}) { return Localize.translateLocal('iou.payerOwesAmount', {payer: payerName, amount: formattedAmount}); } +/** + * Get the report action message when expense has been modified + * + * @param {Object} iouReport + * @param {Object} transactionThreadReport + * @param {Object} [reportAction={}] + * @returns {String} + */ +function getModifiedExpenseMessage(iouReport, transactionThreadReport, reportAction = {}) { + const reportActionMessage = lodashGet(reportAction, 'message[0].html', ''); + + if (_.isEmpty(report) || !report.reportID) { + // The iouReport is not found locally after SignIn because the OpenApp API won't return iouReports if they're settled + // As a temporary solution until we know how to solve this the best, we just use the message that returned from BE + return reportActionMessage; + } + + const totalAmount = getMoneyRequestTotal(report); + const payerName = isExpenseReport(report) ? getPolicyName(report) : getDisplayNameForParticipant(report.managerID, true); + const formattedAmount = CurrencyUtils.convertToDisplayString(totalAmount, report.currency); + + if (isSettled(report.reportID)) { + // A settled report preview message can come in three formats "paid ... using Paypal.me", "paid ... elsewhere" or "paid ... using Expensify" + let translatePhraseKey = 'iou.paidElsewhereWithAmount'; + if (reportActionMessage.match(/ Paypal.me$/)) { + translatePhraseKey = 'iou.paidUsingPaypalWithAmount'; + } else if (reportActionMessage.match(/ using Expensify$/)) { + translatePhraseKey = 'iou.paidUsingExpensifyWithAmount'; + } + return Localize.translateLocal(translatePhraseKey, {amount: formattedAmount}); + } + + if (report.isWaitingOnBankAccount) { + const submitterDisplayName = getDisplayNameForParticipant(report.ownerAccountID, true); + return Localize.translateLocal('iou.waitingOnBankAccount', {submitterDisplayName}); + } + + return Localize.translateLocal('iou.payerOwesAmount', {payer: payerName, amount: formattedAmount}); +} + /** * Get the title for a report. * @@ -2875,6 +2915,7 @@ export { getBankAccountRoute, getParentReport, getReportPreviewMessage, + getModifiedExpenseMessage, shouldHideComposer, getOriginalReportID, canAccessReport, diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 425fcf8d38a6..446e42dcf686 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -1504,7 +1504,7 @@ function setMoneyRequestParticipants(participants) { } export { - editTransaction, + editIOUTransaction, deleteMoneyRequest, splitBill, splitBillAndOpenReport, From 6dbfcef0a66ed5e3f6a40bd64ccb99bd2e1e8640 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 19:40:50 +0100 Subject: [PATCH 04/45] Compose the last message for modified expenses --- src/libs/OptionsListUtils.js | 3 +-- src/libs/ReportUtils.js | 44 +++++++++++------------------------- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index a6a7700bc51a..52dcf2f5e746 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -387,8 +387,7 @@ function getLastMessageTextForReport(report) { const iouReport = ReportUtils.getReport(ReportActionUtils.getIOUReportIDFromReportActionPreview(lastReportAction)); lastMessageTextFromReport = ReportUtils.getReportPreviewMessage(iouReport, lastReportAction); } else if (ReportActionUtils.isModifiedExpenseAction(lastReportAction)) { - const iouReport = ReportUtils.getParentReport(report); getReport(ReportActionUtils.getIOUReportIDFromReportActionPreview(lastReportAction)); - lastMessageTextFromReport = ReportUtils.getModifiedExpenseMessage(iouReport, report, lastReportAction); + lastMessageTextFromReport = ReportUtils.getModifiedExpenseMessage(lastReportAction); } else { lastMessageTextFromReport = report ? report.lastMessageText || '' : ''; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 09f997f42a11..2150ad39f788 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1234,41 +1234,23 @@ function getReportPreviewMessage(report, reportAction = {}) { /** * Get the report action message when expense has been modified * - * @param {Object} iouReport - * @param {Object} transactionThreadReport - * @param {Object} [reportAction={}] - * @returns {String} + * @param {Object} reportAction + * @returns {String} */ -function getModifiedExpenseMessage(iouReport, transactionThreadReport, reportAction = {}) { - const reportActionMessage = lodashGet(reportAction, 'message[0].html', ''); - - if (_.isEmpty(report) || !report.reportID) { - // The iouReport is not found locally after SignIn because the OpenApp API won't return iouReports if they're settled - // As a temporary solution until we know how to solve this the best, we just use the message that returned from BE - return reportActionMessage; - } +function getModifiedExpenseMessage(reportAction) { + const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', []); + if (reportActionOriginalMessage.oldAmount && reportActionOriginalMessage.oldCurrency && reportActionOriginalMessage.amount && reportActionOriginalMessage.currency) { + const oldCurrency = reportActionOriginalMessage.oldCurrency; + const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); + const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', oldCurrency}); - const totalAmount = getMoneyRequestTotal(report); - const payerName = isExpenseReport(report) ? getPolicyName(report) : getDisplayNameForParticipant(report.managerID, true); - const formattedAmount = CurrencyUtils.convertToDisplayString(totalAmount, report.currency); + const currency = reportActionOriginalMessage.currency; + const currencyUnit = CurrencyUtils.getCurrencyUnit(currency); + const amount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.amount) / currencyUnit, {style: 'currency', currency}); - if (isSettled(report.reportID)) { - // A settled report preview message can come in three formats "paid ... using Paypal.me", "paid ... elsewhere" or "paid ... using Expensify" - let translatePhraseKey = 'iou.paidElsewhereWithAmount'; - if (reportActionMessage.match(/ Paypal.me$/)) { - translatePhraseKey = 'iou.paidUsingPaypalWithAmount'; - } else if (reportActionMessage.match(/ using Expensify$/)) { - translatePhraseKey = 'iou.paidUsingExpensifyWithAmount'; - } - return Localize.translateLocal(translatePhraseKey, {amount: formattedAmount}); + return `changed the request to ${amount} (previously ${oldAmount})`; } - - if (report.isWaitingOnBankAccount) { - const submitterDisplayName = getDisplayNameForParticipant(report.ownerAccountID, true); - return Localize.translateLocal('iou.waitingOnBankAccount', {submitterDisplayName}); - } - - return Localize.translateLocal('iou.payerOwesAmount', {payer: payerName, amount: formattedAmount}); + return `changed the request`; } /** From 29ab603e1cef623e9e84239f27f4c45c2432de55 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 19:53:11 +0100 Subject: [PATCH 05/45] Deconstruct the props and use localize and translate hooks --- src/components/MoneyRequestDetails.js | 71 ++++++++++++++------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/src/components/MoneyRequestDetails.js b/src/components/MoneyRequestDetails.js index 5bb7c029d44b..c55e572f1dee 100644 --- a/src/components/MoneyRequestDetails.js +++ b/src/components/MoneyRequestDetails.js @@ -13,7 +13,6 @@ import Avatar from './Avatar'; import styles from '../styles/styles'; import themeColors from '../styles/themes/default'; import CONST from '../CONST'; -import withWindowDimensions from './withWindowDimensions'; import compose from '../libs/compose'; import ROUTES from '../ROUTES'; import Icon from './Icon'; @@ -27,6 +26,8 @@ import DateUtils from '../libs/DateUtils'; import reportPropTypes from '../pages/reportPropTypes'; import * as UserUtils from '../libs/UserUtils'; import OfflineWithFeedback from './OfflineWithFeedback'; +import useWindowDimensions from '../hooks/useWindowDimensions'; +import useLocalize from '../hooks/useLocalize'; const propTypes = { /** The report currently being looked at */ @@ -72,34 +73,38 @@ const defaultProps = { policy: null, }; -function MoneyRequestDetails(props) { +function MoneyRequestDetails({isSingleTransactionView, report, chatReport, session, parentReport, policy, parentReportAction, personalDetails}) { + const {isSmallScreenWidth} = useWindowDimensions(); + const {translate} = useLocalize(); + // These are only used for the single transaction view and not for expense and iou reports - const {amount: transactionAmount, currency: transactionCurrency, comment: transactionDescription} = ReportUtils.getMoneyRequestAction(props.parentReportAction); + const {amount: transactionAmount, currency: transactionCurrency, comment: transactionDescription} = ReportUtils.getMoneyRequestAction(parentReportAction); const formattedTransactionAmount = transactionAmount && transactionCurrency && CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); - const transactionDate = lodashGet(props.parentReportAction, ['created']); + const transactionDate = lodashGet(parentReportAction, ['created']); const formattedTransactionDate = DateUtils.getDateStringFromISOTimestamp(transactionDate); - const formattedAmount = CurrencyUtils.convertToDisplayString(ReportUtils.getMoneyRequestTotal(props.report), props.report.currency); - const moneyRequestReport = props.isSingleTransactionView ? props.parentReport : props.report; + const formattedAmount = CurrencyUtils.convertToDisplayString(ReportUtils.getMoneyRequestTotal(report), report.currency); + const moneyRequestReport = isSingleTransactionView ? parentReport : report; const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); const isExpenseReport = ReportUtils.isExpenseReport(moneyRequestReport); const payeeName = isExpenseReport ? ReportUtils.getPolicyName(moneyRequestReport) : ReportUtils.getDisplayNameForParticipant(moneyRequestReport.managerID); const payeeAvatar = isExpenseReport - ? ReportUtils.getWorkspaceAvatar(moneyRequestReport) - : UserUtils.getAvatar(lodashGet(props.personalDetails, [moneyRequestReport.managerID, 'avatar']), moneyRequestReport.managerID); + ? ReportUtils.getWorkspaceAvatar(moneyRequestReport) + : UserUtils.getAvatar(lodashGet(personalDetails, [moneyRequestReport.managerID, 'avatar']), moneyRequestReport.managerID); const isPayer = - Policy.isAdminOfFreePolicy([props.policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(props.session, 'accountID', null) === moneyRequestReport.managerID); - const shouldShowSettlementButton = moneyRequestReport.reportID && !isSettled && !props.isSingleTransactionView && isPayer && !moneyRequestReport.isWaitingOnBankAccount; - const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport); - const shouldShowPaypal = Boolean(lodashGet(props.personalDetails, [moneyRequestReport.ownerAccountID, 'payPalMeAddress'])); - let description = `${props.translate('iou.amount')} • ${props.translate('iou.cash')}`; + Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID); + const canEdit = !isSettled && (isExpenseReport || (ReportUtils.isIOUReport(moneyRequestReport) && !isPayer)) + const shouldShowSettlementButton = moneyRequestReport.reportID && !isSettled && !isSingleTransactionView && isPayer && !moneyRequestReport.isWaitingOnBankAccount; + const bankAccountRoute = ReportUtils.getBankAccountRoute(chatReport); + const shouldShowPaypal = Boolean(lodashGet(personalDetails, [moneyRequestReport.ownerAccountID, 'payPalMeAddress'])); + let description = `${translate('iou.amount')} • ${translate('iou.cash')}`; if (isSettled) { - description += ` • ${props.translate('iou.settledExpensify')}`; - } else if (props.report.isWaitingOnBankAccount) { - description += ` • ${props.translate('iou.pending')}`; + description += ` • ${translate('iou.settledExpensify')}`; + } else if (report.isWaitingOnBankAccount) { + description += ` • ${translate('iou.pending')}`; } - const {addWorkspaceRoomOrChatPendingAction, addWorkspaceRoomOrChatErrors} = ReportUtils.getReportOfflinePendingActionAndErrors(props.report); + const {addWorkspaceRoomOrChatPendingAction, addWorkspaceRoomOrChatErrors} = ReportUtils.getReportOfflinePendingActionAndErrors(report); return ( - {props.translate('common.to')} + {translate('common.to')} - {props.translate('workspace.common.workspace')} + {translate('workspace.common.workspace')} )} - {!props.isSingleTransactionView && {formattedAmount}} - {!props.isSingleTransactionView && isSettled && ( + {!isSingleTransactionView && {formattedAmount}} + {!isSingleTransactionView && isSettled && ( )} - {shouldShowSettlementButton && !props.isSmallScreenWidth && ( + {shouldShowSettlementButton && !isSmallScreenWidth && ( - {shouldShowSettlementButton && props.isSmallScreenWidth && ( + {shouldShowSettlementButton && isSmallScreenWidth && ( )} - {props.isSingleTransactionView && ( + {isSingleTransactionView && ( <> Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} + shouldShowRightIcon={canEdit} + onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} /> Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} + shouldShowRightIcon={canEdit} + onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} /> Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} + shouldShowRightIcon={canEdit} + onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} /> )} @@ -213,7 +217,6 @@ MoneyRequestDetails.propTypes = propTypes; MoneyRequestDetails.defaultProps = defaultProps; export default compose( - withWindowDimensions, withLocalize, withOnyx({ chatReport: { From e48c8feec1de89d67310cf75b26bf51e91b476d8 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 19:57:00 +0100 Subject: [PATCH 06/45] Enable the edit request routes --- src/components/MoneyRequestDetails.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestDetails.js b/src/components/MoneyRequestDetails.js index c55e572f1dee..c4f407ebcc4e 100644 --- a/src/components/MoneyRequestDetails.js +++ b/src/components/MoneyRequestDetails.js @@ -188,20 +188,21 @@ function MoneyRequestDetails({isSingleTransactionView, report, chatReport, sessi titleIcon={Expensicons.Checkmark} description={description} titleStyle={styles.newKansasLarge} - disabled={isSettled} + disabled={canEdit} shouldShowRightIcon={canEdit} onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} /> Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} /> Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} /> From 1748961f464e62de21e3394954bcbb7781864b99 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 19:59:35 +0100 Subject: [PATCH 07/45] Fix variable name --- src/pages/home/report/ReportActionItem.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 62a90b0bcd62..9c316f100b3e 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -447,8 +447,8 @@ function ReportActionItem(props) { }; if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) { - const parentReport = ReportActionsUtils.getParentReportAction(props.report); - if (ReportActionsUtils.isTransactionThread(parentReport)) { + const parentReportAction = ReportActionsUtils.getParentReportAction(props.report); + if (ReportActionsUtils.isTransactionThread(parentReportAction)) { return ( Date: Mon, 31 Jul 2023 20:03:40 +0100 Subject: [PATCH 08/45] Deconstruct the props in the MoneyRequestView --- .../ReportActionItem/MoneyRequestView.js | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 06cb6465fccd..0a0f62fe08cf 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -20,6 +20,7 @@ import DateUtils from '../../libs/DateUtils'; import * as CurrencyUtils from '../../libs/CurrencyUtils'; import EmptyStateBackgroundImage from '../../../assets/images/empty-state_background-fade.png'; import useLocalize from '../../hooks/useLocalize'; +import useWindowDimensions from '../../hooks/useWindowDimensions'; const propTypes = { /** The report currently being looked at */ @@ -38,20 +39,22 @@ const defaultProps = { parentReport: {}, }; -function MoneyRequestView(props) { - const parentReportAction = ReportActionsUtils.getParentReportAction(props.report); +function MoneyRequestView({report, parentReport, shouldShowHorizontalRule}) { + const {isSmallScreenWidth} = useWindowDimensions(); + + const parentReportAction = ReportActionsUtils.getParentReportAction(report); const {amount: transactionAmount, currency: transactionCurrency, comment: transactionDescription} = ReportUtils.getMoneyRequestAction(parentReportAction); const formattedTransactionAmount = transactionAmount && transactionCurrency && CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); const transactionDate = lodashGet(parentReportAction, ['created']); const formattedTransactionDate = DateUtils.getDateStringFromISOTimestamp(transactionDate); - const moneyRequestReport = props.parentReport; + const moneyRequestReport = parentReport; const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); const {translate} = useLocalize(); return ( - + Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} + shouldShowRightIcon={!isSettled} + onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} /> Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} + shouldShowRightIcon={!isSettled} + onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} /> Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} + shouldShowRightIcon={!isSettled} + onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} /> - {props.shouldShowHorizontalRule && } + {shouldShowHorizontalRule && } ); } @@ -92,11 +94,10 @@ MoneyRequestView.defaultProps = defaultProps; MoneyRequestView.displayName = 'MoneyRequestView'; export default compose( - withWindowDimensions, withCurrentUserPersonalDetails, withOnyx({ parentReport: { - key: (props) => `${ONYXKEYS.COLLECTION.REPORT}${props.report.parentReportID}`, + key: (props) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, }, }), )(MoneyRequestView); From 1406d02e534d1eac7f6fda7a9731ebcf9dbd6641 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 20:08:08 +0100 Subject: [PATCH 09/45] Update money request view to use canEdit --- .../ReportActionItem/MoneyRequestView.js | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 0a0f62fe08cf..2b1a9856bc67 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -5,7 +5,7 @@ import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; import reportPropTypes from '../../pages/reportPropTypes'; import ONYXKEYS from '../../ONYXKEYS'; -import withWindowDimensions from '../withWindowDimensions'; +import * as Policy from '../libs/actions/Policy'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '../withCurrentUserPersonalDetails'; import compose from '../../libs/compose'; import MenuItemWithTopDescription from '../MenuItemWithTopDescription'; @@ -29,6 +29,21 @@ const propTypes = { /** The expense report or iou report (only will have a value if this is a transaction thread) */ parentReport: iouReportPropTypes, + /** The policy object for the current route */ + policy: PropTypes.shape({ + /** The name of the policy */ + name: PropTypes.string, + + /** The URL for the policy avatar */ + avatar: PropTypes.string, + }), + + /** Session info for the currently logged in user. */ + session: PropTypes.shape({ + /** Currently logged in user email */ + email: PropTypes.string, + }), + /** Whether we should display the horizontal rule below the component */ shouldShowHorizontalRule: PropTypes.bool.isRequired, @@ -37,6 +52,10 @@ const propTypes = { const defaultProps = { parentReport: {}, + policy: null, + session: { + email: null, + }, }; function MoneyRequestView({report, parentReport, shouldShowHorizontalRule}) { @@ -50,6 +69,9 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule}) { const moneyRequestReport = parentReport; const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); + const isPayer = + Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID); + const canEdit = !isSettled && (ReportUtils.isExpenseReport(moneyRequestReport) || (ReportUtils.isIOUReport(moneyRequestReport) && !isPayer)) const {translate} = useLocalize(); return ( @@ -68,20 +90,20 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule}) { description={`${translate('iou.amount')} • ${translate('iou.cash')}${isSettled ? ` • ${translate('iou.settledExpensify')}` : ''}`} titleStyle={styles.newKansasLarge} disabled={isSettled} - shouldShowRightIcon={!isSettled} + shouldShowRightIcon={!canEdit} onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} /> Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} /> Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} /> {shouldShowHorizontalRule && } @@ -97,7 +119,10 @@ export default compose( withCurrentUserPersonalDetails, withOnyx({ parentReport: { - key: (props) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, + }, + session: { + key: ONYXKEYS.SESSION, }, }), )(MoneyRequestView); From 0f1054e405a4d4407e001c74088f4c108f2f0af0 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 20:14:24 +0100 Subject: [PATCH 10/45] Remove the MoneyRequestDetails component which is unused and add policy to the MoneyRequestView component --- src/components/MoneyRequestDetails.js | 233 ------------------ .../ReportActionItem/MoneyRequestView.js | 16 +- 2 files changed, 13 insertions(+), 236 deletions(-) delete mode 100644 src/components/MoneyRequestDetails.js diff --git a/src/components/MoneyRequestDetails.js b/src/components/MoneyRequestDetails.js deleted file mode 100644 index c4f407ebcc4e..000000000000 --- a/src/components/MoneyRequestDetails.js +++ /dev/null @@ -1,233 +0,0 @@ -import React from 'react'; -import {withOnyx} from 'react-native-onyx'; -import {View} from 'react-native'; -import PropTypes from 'prop-types'; -import lodashGet from 'lodash/get'; -import iouReportPropTypes from '../pages/iouReportPropTypes'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; -import * as ReportUtils from '../libs/ReportUtils'; -import * as Expensicons from './Icon/Expensicons'; -import Text from './Text'; -import participantPropTypes from './participantPropTypes'; -import Avatar from './Avatar'; -import styles from '../styles/styles'; -import themeColors from '../styles/themes/default'; -import CONST from '../CONST'; -import compose from '../libs/compose'; -import ROUTES from '../ROUTES'; -import Icon from './Icon'; -import SettlementButton from './SettlementButton'; -import * as Policy from '../libs/actions/Policy'; -import ONYXKEYS from '../ONYXKEYS'; -import * as IOU from '../libs/actions/IOU'; -import * as CurrencyUtils from '../libs/CurrencyUtils'; -import MenuItemWithTopDescription from './MenuItemWithTopDescription'; -import DateUtils from '../libs/DateUtils'; -import reportPropTypes from '../pages/reportPropTypes'; -import * as UserUtils from '../libs/UserUtils'; -import OfflineWithFeedback from './OfflineWithFeedback'; -import useWindowDimensions from '../hooks/useWindowDimensions'; -import useLocalize from '../hooks/useLocalize'; - -const propTypes = { - /** The report currently being looked at */ - report: iouReportPropTypes.isRequired, - - /** The expense report or iou report (only will have a value if this is a transaction thread) */ - parentReport: iouReportPropTypes, - - /** The policy object for the current route */ - policy: PropTypes.shape({ - /** The name of the policy */ - name: PropTypes.string, - - /** The URL for the policy avatar */ - avatar: PropTypes.string, - }), - - /** The chat report this report is linked to */ - chatReport: reportPropTypes, - - /** Personal details so we can get the ones for the report participants */ - personalDetails: PropTypes.objectOf(participantPropTypes).isRequired, - - /** Whether we're viewing a report with a single transaction in it */ - isSingleTransactionView: PropTypes.bool, - - /** Session info for the currently logged in user. */ - session: PropTypes.shape({ - /** Currently logged in user email */ - email: PropTypes.string, - }), - - ...withLocalizePropTypes, -}; - -const defaultProps = { - isSingleTransactionView: false, - chatReport: {}, - session: { - email: null, - }, - parentReport: {}, - policy: null, -}; - -function MoneyRequestDetails({isSingleTransactionView, report, chatReport, session, parentReport, policy, parentReportAction, personalDetails}) { - const {isSmallScreenWidth} = useWindowDimensions(); - const {translate} = useLocalize(); - - // These are only used for the single transaction view and not for expense and iou reports - const {amount: transactionAmount, currency: transactionCurrency, comment: transactionDescription} = ReportUtils.getMoneyRequestAction(parentReportAction); - const formattedTransactionAmount = transactionAmount && transactionCurrency && CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); - const transactionDate = lodashGet(parentReportAction, ['created']); - const formattedTransactionDate = DateUtils.getDateStringFromISOTimestamp(transactionDate); - - const formattedAmount = CurrencyUtils.convertToDisplayString(ReportUtils.getMoneyRequestTotal(report), report.currency); - const moneyRequestReport = isSingleTransactionView ? parentReport : report; - const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); - const isExpenseReport = ReportUtils.isExpenseReport(moneyRequestReport); - const payeeName = isExpenseReport ? ReportUtils.getPolicyName(moneyRequestReport) : ReportUtils.getDisplayNameForParticipant(moneyRequestReport.managerID); - const payeeAvatar = isExpenseReport - ? ReportUtils.getWorkspaceAvatar(moneyRequestReport) - : UserUtils.getAvatar(lodashGet(personalDetails, [moneyRequestReport.managerID, 'avatar']), moneyRequestReport.managerID); - const isPayer = - Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID); - const canEdit = !isSettled && (isExpenseReport || (ReportUtils.isIOUReport(moneyRequestReport) && !isPayer)) - const shouldShowSettlementButton = moneyRequestReport.reportID && !isSettled && !isSingleTransactionView && isPayer && !moneyRequestReport.isWaitingOnBankAccount; - const bankAccountRoute = ReportUtils.getBankAccountRoute(chatReport); - const shouldShowPaypal = Boolean(lodashGet(personalDetails, [moneyRequestReport.ownerAccountID, 'payPalMeAddress'])); - let description = `${translate('iou.amount')} • ${translate('iou.cash')}`; - if (isSettled) { - description += ` • ${translate('iou.settledExpensify')}`; - } else if (report.isWaitingOnBankAccount) { - description += ` • ${translate('iou.pending')}`; - } - - const {addWorkspaceRoomOrChatPendingAction, addWorkspaceRoomOrChatErrors} = ReportUtils.getReportOfflinePendingActionAndErrors(report); - return ( - - - - {translate('common.to')} - - - - - - {payeeName} - - {isExpenseReport && ( - - {translate('workspace.common.workspace')} - - )} - - - - {!isSingleTransactionView && {formattedAmount}} - {!isSingleTransactionView && isSettled && ( - - - - )} - {shouldShowSettlementButton && !isSmallScreenWidth && ( - - IOU.payMoneyRequest(paymentType, props.chatReport, props.report)} - enablePaymentsRoute={ROUTES.BANK_ACCOUNT_NEW} - addBankAccountRoute={bankAccountRoute} - shouldShowPaymentOptions - /> - - )} - - - {shouldShowSettlementButton && isSmallScreenWidth && ( - IOU.payMoneyRequest(paymentType, props.chatReport, props.report)} - enablePaymentsRoute={ROUTES.BANK_ACCOUNT_NEW} - addBankAccountRoute={bankAccountRoute} - shouldShowPaymentOptions - /> - )} - - {isSingleTransactionView && ( - <> - Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} - /> - Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} - /> - Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} - /> - - )} - - - ); -} - -MoneyRequestDetails.displayName = 'MoneyRequestDetails'; -MoneyRequestDetails.propTypes = propTypes; -MoneyRequestDetails.defaultProps = defaultProps; - -export default compose( - withLocalize, - withOnyx({ - chatReport: { - key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`, - }, - session: { - key: ONYXKEYS.SESSION, - }, - parentReport: { - key: (props) => `${ONYXKEYS.COLLECTION.REPORT}${props.report.parentReportID}`, - }, - }), -)(MoneyRequestDetails); diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 2b1a9856bc67..cb026dd823dd 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -58,8 +58,9 @@ const defaultProps = { }, }; -function MoneyRequestView({report, parentReport, shouldShowHorizontalRule}) { +function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, policy}) { const {isSmallScreenWidth} = useWindowDimensions(); + const {translate} = useLocalize(); const parentReportAction = ReportActionsUtils.getParentReportAction(report); const {amount: transactionAmount, currency: transactionCurrency, comment: transactionDescription} = ReportUtils.getMoneyRequestAction(parentReportAction); @@ -72,7 +73,13 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule}) { const isPayer = Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID); const canEdit = !isSettled && (ReportUtils.isExpenseReport(moneyRequestReport) || (ReportUtils.isIOUReport(moneyRequestReport) && !isPayer)) - const {translate} = useLocalize(); + + let description = `${translate('iou.amount')} • ${translate('iou.cash')}`; + if (isSettled) { + description += ` • ${translate('iou.settledExpensify')}`; + } else if (report.isWaitingOnBankAccount) { + description += ` • ${translate('iou.pending')}`; + } return ( @@ -87,7 +94,7 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule}) { title={formattedTransactionAmount} shouldShowTitleIcon={isSettled} titleIcon={Expensicons.Checkmark} - description={`${translate('iou.amount')} • ${translate('iou.cash')}${isSettled ? ` • ${translate('iou.settledExpensify')}` : ''}`} + description={description} titleStyle={styles.newKansasLarge} disabled={isSettled} shouldShowRightIcon={!canEdit} @@ -121,6 +128,9 @@ export default compose( parentReport: { key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, }, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, + }, session: { key: ONYXKEYS.SESSION, }, From e149e81a4264df992934e0db4f8359869575966b Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 20:19:59 +0100 Subject: [PATCH 11/45] Deconstruct the EditRequestPage props --- src/pages/EditRequestPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index d2280ec78fd7..04046ce2cc4a 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -35,8 +35,8 @@ const defaultProps = { report: {}, }; -function EditRequestPage(props) { - const parentReportAction = ReportActionsUtils.getParentReportAction(props.report); +function EditRequestPage({report}) { + const parentReportAction = ReportActionsUtils.getParentReportAction(report); const moneyRequestReportAction = ReportUtils.getMoneyRequestAction(parentReportAction); const transactionDescription = moneyRequestReportAction.comment; const field = lodashGet(props, ['route', 'params', 'field'], ''); From 7ca8874216a1a001c832e5382dff0ff3fd7a0bce Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 20:23:15 +0100 Subject: [PATCH 12/45] useLocalize for EditRequestDescriptionPage and clean up the props --- src/pages/EditRequestDescriptionPage.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/pages/EditRequestDescriptionPage.js b/src/pages/EditRequestDescriptionPage.js index 34f88f29dc28..e46c27283f27 100644 --- a/src/pages/EditRequestDescriptionPage.js +++ b/src/pages/EditRequestDescriptionPage.js @@ -2,7 +2,6 @@ import React, {useRef} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import TextInput from '../components/TextInput'; -import withLocalize, {withLocalizePropTypes} from '../components/withLocalize'; import ScreenWrapper from '../components/ScreenWrapper'; import HeaderWithBackButton from '../components/HeaderWithBackButton'; import Form from '../components/Form'; @@ -10,6 +9,7 @@ import ONYXKEYS from '../ONYXKEYS'; import styles from '../styles/styles'; import Navigation from '../libs/Navigation/Navigation'; import CONST from '../CONST'; +import useLocalize from '../hooks/useLocalize'; const propTypes = { ...withLocalizePropTypes, @@ -21,7 +21,8 @@ const propTypes = { onSubmit: PropTypes.func.isRequired, }; -function EditRequestDescriptionPage(props) { +function EditRequestDescriptionPage({defaultDescription, onSubmit}) { + const {translate} = useLocalize(); const descriptionInputRef = useRef(null); return ( descriptionInputRef.current && descriptionInputRef.current.focus()} > Navigation.goBack()} />
@@ -59,4 +60,4 @@ function EditRequestDescriptionPage(props) { EditRequestDescriptionPage.propTypes = propTypes; EditRequestDescriptionPage.displayName = 'EditRequestDescriptionPage'; -export default withLocalize(EditRequestDescriptionPage); +export default EditRequestDescriptionPage; From 292a682f075d59c42971de4a391cda1a41b8df1d Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 20:23:53 +0100 Subject: [PATCH 13/45] Clean up the EditRequestDescriptionPage props --- src/pages/EditRequestDescriptionPage.js | 2 -- src/pages/EditRequestPage.js | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/pages/EditRequestDescriptionPage.js b/src/pages/EditRequestDescriptionPage.js index e46c27283f27..d83c0da55c62 100644 --- a/src/pages/EditRequestDescriptionPage.js +++ b/src/pages/EditRequestDescriptionPage.js @@ -12,8 +12,6 @@ import CONST from '../CONST'; import useLocalize from '../hooks/useLocalize'; const propTypes = { - ...withLocalizePropTypes, - /** Transaction description default value */ defaultDescription: PropTypes.string.isRequired, diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 04046ce2cc4a..98087c385da0 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -5,7 +5,6 @@ import {withOnyx} from 'react-native-onyx'; import CONST from '../CONST'; import Navigation from '../libs/Navigation/Navigation'; import compose from '../libs/compose'; -import withLocalize, {withLocalizePropTypes} from '../components/withLocalize'; import ONYXKEYS from '../ONYXKEYS'; import * as ReportActionsUtils from '../libs/ReportActionsUtils'; import EditRequestDescriptionPage from './EditRequestDescriptionPage'; @@ -13,8 +12,6 @@ import reportPropTypes from './reportPropTypes'; import * as ReportUtils from '../libs/ReportUtils'; const propTypes = { - ...withLocalizePropTypes, - /** Route from navigation */ route: PropTypes.shape({ /** Params from the route */ @@ -68,7 +65,6 @@ EditRequestPage.displayName = 'EditRequestPage'; EditRequestPage.propTypes = propTypes; EditRequestPage.defaultProps = defaultProps; export default compose( - withLocalize, withOnyx({ report: { key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.threadReportID}`, From 487212081f0657a5cb76d936b8c60e981e1cacb9 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 20:36:16 +0100 Subject: [PATCH 14/45] Add util for retrieving transaction objects --- src/libs/TransactionUtils.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 266720bc631f..dba9e9a1d33d 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -1,6 +1,23 @@ +import Onyx from 'react-native-onyx'; +import lodashGet from 'lodash/get'; import CONST from '../CONST'; +import ONYXKEYS from '../ONYXKEYS'; import DateUtils from './DateUtils'; import * as NumberUtils from './NumberUtils'; +import * as CollectionUtils from './CollectionUtils'; + +const allTransactions = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + callback: (transaction, key) => { + if (!key || !transaction) { + return; + } + + const transactionID = CollectionUtils.extractCollectionItemID(key); + allTransactions[transactionID] = transaction; + }, +}); /** * Optimistically generate a transaction. @@ -39,6 +56,17 @@ function buildOptimisticTransaction(amount, currency, reportID, comment = '', so }; } +/** + * Retrieve the particular transaction object given its ID. + * + * @param {String} transactionID + * @returns {Object} + */ +function getTransaction(transactionID) { + return lodashGet(allTransactions, [transactionID], {}); +} + export default { buildOptimisticTransaction, + getTransaction, }; From 135d6b0b1502f53ceb4595775a5410218801deb8 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 20:56:11 +0100 Subject: [PATCH 15/45] Add helper methods to pull the transaction details from the store --- src/libs/TransactionUtils.js | 59 +++++++++++++++++++++++++++++++++++- src/libs/actions/IOU.js | 2 +- src/pages/EditRequestPage.js | 4 ++- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index dba9e9a1d33d..e306e5494fa5 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -66,7 +66,64 @@ function getTransaction(transactionID) { return lodashGet(allTransactions, [transactionID], {}); } -export default { +/** + * Return the comment (in other words description) from the transaction object. + * The comment does not have its modifiedComment counterpart. + * + * @param {Object} transaction + * @returns {String} + */ +function getDescription(transaction) { + return lodashGet(transaction, 'comment', ''); +} + +/** + * Return the amount from the transaction, take the modifiedAmount if present. + * + * @param {Object} transaction + * @returns {Number} + */ +function getAmount(transaction) { + const amount = lodashGet(transaction, 'modifiedAmount', ''); + if (amount) { + return amount; + } + return lodashGet(transaction, 'amount', 0); +} + +/** + * Return the currency from the transaction, take the modifiedCurrency if present. + * + * @param {Object} transaction + * @returns {String} + */ +function getCurrency(transaction) { + const currency = lodashGet(transaction, 'modifiedCurrency', ''); + if (currency) { + return currency; + } + return lodashGet(transaction, 'currency', 0); +} + +/** + * Return the created from the transaction, take the modifiedCreated if present. + * + * @param {Object} transaction + * @returns {String} + */ +function getCreated(transaction) { + const created = lodashGet(transaction, 'modifiedCreated', ''); + if (created) { + return created; + } + return lodashGet(transaction, 'created', 0); +} + +export { buildOptimisticTransaction, getTransaction, + getDescription, + getAmount, + getCurrency, + getCreated, }; diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 446e42dcf686..e31fa6e6a779 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -15,7 +15,7 @@ import * as ReportActionsUtils from '../ReportActionsUtils'; import * as IOUUtils from '../IOUUtils'; import * as OptionsListUtils from '../OptionsListUtils'; import DateUtils from '../DateUtils'; -import TransactionUtils from '../TransactionUtils'; +import * as TransactionUtils from '../TransactionUtils'; import * as ErrorUtils from '../ErrorUtils'; import * as UserUtils from '../UserUtils'; import * as Report from './Report'; diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 98087c385da0..51905487d348 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -7,6 +7,7 @@ import Navigation from '../libs/Navigation/Navigation'; import compose from '../libs/compose'; import ONYXKEYS from '../ONYXKEYS'; import * as ReportActionsUtils from '../libs/ReportActionsUtils'; +import * as TransactionUtils from '../libs/TransactionUtils'; import EditRequestDescriptionPage from './EditRequestDescriptionPage'; import reportPropTypes from './reportPropTypes'; import * as ReportUtils from '../libs/ReportUtils'; @@ -34,7 +35,8 @@ const defaultProps = { function EditRequestPage({report}) { const parentReportAction = ReportActionsUtils.getParentReportAction(report); - const moneyRequestReportAction = ReportUtils.getMoneyRequestAction(parentReportAction); + const transactionID = ReportActionsUtils.getLinkedTransactionID(ReportUtils.getParentReport(report), parentReportAction) + const transaction = TransactionUtils.getTransaction(transactionID); const transactionDescription = moneyRequestReportAction.comment; const field = lodashGet(props, ['route', 'params', 'field'], ''); From b60bef78eff78b19520dc4647dbd1711081866be Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 21:24:03 +0100 Subject: [PATCH 16/45] Fix the missing imports --- src/components/ReportActionItem/MoneyRequestView.js | 6 ++++-- src/pages/EditRequestPage.js | 9 ++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index cb026dd823dd..869993d7b1d3 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -5,7 +5,9 @@ import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; import reportPropTypes from '../../pages/reportPropTypes'; import ONYXKEYS from '../../ONYXKEYS'; -import * as Policy from '../libs/actions/Policy'; +import ROUTES from '../../ROUTES'; +import * as Policy from '../../libs/actions/Policy'; +import Navigation from '../../libs/Navigation/Navigation'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '../withCurrentUserPersonalDetails'; import compose from '../../libs/compose'; import MenuItemWithTopDescription from '../MenuItemWithTopDescription'; @@ -58,7 +60,7 @@ const defaultProps = { }, }; -function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, policy}) { +function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, policy, session}) { const {isSmallScreenWidth} = useWindowDimensions(); const {translate} = useLocalize(); diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 51905487d348..c832a2c4cd24 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -33,12 +33,15 @@ const defaultProps = { report: {}, }; -function EditRequestPage({report}) { +function EditRequestPage({report, route}) { const parentReportAction = ReportActionsUtils.getParentReportAction(report); const transactionID = ReportActionsUtils.getLinkedTransactionID(ReportUtils.getParentReport(report), parentReportAction) const transaction = TransactionUtils.getTransaction(transactionID); - const transactionDescription = moneyRequestReportAction.comment; - const field = lodashGet(props, ['route', 'params', 'field'], ''); + const transactionDescription = TransactionUtils.getDescription(transaction); + const transactionAmount = TransactionUtils.getAmount(transaction); + const transactionCurrency = TransactionUtils.getCurrency(transaction); + const transactionCreated = TransactionUtils.getCreated(transaction); + const field = lodashGet(route, ['params', 'field'], ''); function updateTransactionWithChanges(changes) { // Update the transaction... From 183e26c8c2c7ce50db197104bf8410580f58ab65 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 21:44:35 +0100 Subject: [PATCH 17/45] Add new EditRequestCreatedPage page and start working on the optimistic edit iou transaction work --- src/libs/ReportUtils.js | 34 ++++++++++++++ src/libs/actions/IOU.js | 30 ++++++++++-- src/pages/EditRequestCreatedPage.js | 61 +++++++++++++++++++++++++ src/pages/EditRequestDescriptionPage.js | 5 +- src/pages/EditRequestPage.js | 10 ++++ 5 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 src/pages/EditRequestCreatedPage.js diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 2150ad39f788..c3f520d3dbbe 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1812,6 +1812,39 @@ function buildOptimisticReportPreview(chatReport, iouReport) { }; } +/** + * Builds an optimistic report preview action with a randomly generated reportActionID. + * + * @param {Object} transactionThread + * @param {Object} iouReport + * + * @returns {Object} + */ +function buildOptimisticModifiedExpenseReportAction(transactionThread, iouReport) { + const message = getReportPreviewMessage(iouReport); + return { + reportActionID: NumberUtils.rand64(), + reportID: transactionThread.reportID, + actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE, + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + originalMessage: { + linkedReportID: iouReport.reportID, + }, + message: [ + { + html: message, + text: message, + isEdited: false, + type: CONST.REPORT.MESSAGE.TYPE.COMMENT, + }, + ], + created: DateUtils.getDBTime(), + accountID: iouReport.managerID || 0, + actorAccountID: iouReport.managerID || 0, + }; +} + + /** * Updates a report preview action that exists for an IOU report. * @@ -2849,6 +2882,7 @@ export { buildOptimisticExpenseReport, buildOptimisticIOUReportAction, buildOptimisticReportPreview, + buildOptimisticModifiedExpenseReportAction, updateReportPreview, buildOptimisticTaskReportAction, buildOptimisticAddCommentReportAction, diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index e31fa6e6a779..c8f5e3266f39 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -767,15 +767,39 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou /** * @param {String} transactionID - * @param {String} transactionThreadReportID + * @param {Number} transactionThreadReportID + * @param {Object} updatedTransaction */ -function editIOUTransaction(transactionID, transactionThreadReportID) { +function editIOUTransaction(transactionID, transactionThreadReportID, updatedTransaction) { // STEP 1: Get all collections we're updating - let transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; + const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`]; const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(iouReport.chatReportID, iouReport.reportID); const chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`]; + + // STEP 2: Build new modified expense report action. + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread); + + // STEP 3: Compose the data for the API command + const optimisticData = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`, + value: { + [reportAction.reportActionID]: {pendingAction: null}, + }, + }, + ]; + + const failureData = [ + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + value: transaction, + }, + ] + API.write( 'EditIOUTransaction', { diff --git a/src/pages/EditRequestCreatedPage.js b/src/pages/EditRequestCreatedPage.js new file mode 100644 index 000000000000..9619be70e9d9 --- /dev/null +++ b/src/pages/EditRequestCreatedPage.js @@ -0,0 +1,61 @@ +import React, {useRef} from 'react'; +import {View} from 'react-native'; +import PropTypes from 'prop-types'; +import TextInput from '../components/TextInput'; +import ScreenWrapper from '../components/ScreenWrapper'; +import HeaderWithBackButton from '../components/HeaderWithBackButton'; +import Form from '../components/Form'; +import ONYXKEYS from '../ONYXKEYS'; +import styles from '../styles/styles'; +import Navigation from '../libs/Navigation/Navigation'; +import CONST from '../CONST'; +import useLocalize from '../hooks/useLocalize'; + +const propTypes = { + /** Transaction created default value */ + defaultCreated: PropTypes.string.isRequired, + + /** Callback to fire when the Save button is pressed */ + onSubmit: PropTypes.func.isRequired, +}; + +function EditRequestCreatedPage({defaultDescription, onSubmit}) { + const {translate} = useLocalize(); + const descriptionInputRef = useRef(null); + return ( + descriptionInputRef.current && descriptionInputRef.current.focus()} + > + Navigation.goBack()} + /> + + + + + + + ); +} + +EditRequestCreatedPage.propTypes = propTypes; +EditRequestCreatedPage.displayName = 'EditRequestCreatedPage'; + +export default EditRequestCreatedPage; diff --git a/src/pages/EditRequestDescriptionPage.js b/src/pages/EditRequestDescriptionPage.js index d83c0da55c62..57d4e3c7c387 100644 --- a/src/pages/EditRequestDescriptionPage.js +++ b/src/pages/EditRequestDescriptionPage.js @@ -41,8 +41,9 @@ function EditRequestDescriptionPage({defaultDescription, onSubmit}) { > ); + } else if (field === CONST.EDIT_REQUEST_FIELD.DATE) { + return ( + { + updateTransactionWithChanges(changes); + }} + /> + ); } return null; From 9908020b4ba98327a83536a0385e7795ff1defe9 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 31 Jul 2023 22:35:30 +0100 Subject: [PATCH 18/45] Add Calendar to the Edit created page --- src/ONYXKEYS.js | 2 ++ src/libs/actions/IOU.js | 10 +++++++ src/pages/EditRequestCreatedPage.js | 46 +++++++++++++++++------------ 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index dd73bde936f9..bb2eb02d74df 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -210,6 +210,8 @@ export default { NEW_TASK_FORM: 'newTaskForm', EDIT_TASK_FORM: 'editTaskForm', MONEY_REQUEST_DESCRIPTION_FORM: 'moneyRequestDescriptionForm', + MONEY_REQUEST_AMOUNT_FORM: 'moneyRequestAmountForm', + MONEY_REQUEST_CREATED_FORM: 'moneyRequestCreatedForm', NEW_CONTACT_METHOD_FORM: 'newContactMethodForm', PAYPAL_FORM: 'payPalForm', }, diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index c8f5e3266f39..40f7b6968ca1 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -792,6 +792,16 @@ function editIOUTransaction(transactionID, transactionThreadReportID, updatedTra }, ]; + const successData = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`, + value: { + [reportAction.reportActionID]: {pendingAction: null}, + }, + }, + ]; + const failureData = [ { onyxMethod: Onyx.METHOD.SET, diff --git a/src/pages/EditRequestCreatedPage.js b/src/pages/EditRequestCreatedPage.js index 9619be70e9d9..e96fc84b2330 100644 --- a/src/pages/EditRequestCreatedPage.js +++ b/src/pages/EditRequestCreatedPage.js @@ -1,15 +1,14 @@ import React, {useRef} from 'react'; -import {View} from 'react-native'; import PropTypes from 'prop-types'; -import TextInput from '../components/TextInput'; import ScreenWrapper from '../components/ScreenWrapper'; import HeaderWithBackButton from '../components/HeaderWithBackButton'; import Form from '../components/Form'; import ONYXKEYS from '../ONYXKEYS'; import styles from '../styles/styles'; import Navigation from '../libs/Navigation/Navigation'; -import CONST from '../CONST'; import useLocalize from '../hooks/useLocalize'; +import NewDatePicker from '../components/NewDatePicker'; +import * as ValidationUtils from '../libs/ValidationUtils'; const propTypes = { /** Transaction created default value */ @@ -19,37 +18,46 @@ const propTypes = { onSubmit: PropTypes.func.isRequired, }; -function EditRequestCreatedPage({defaultDescription, onSubmit}) { +function EditRequestCreatedPage({defaultCreated, onSubmit}) { const {translate} = useLocalize(); - const descriptionInputRef = useRef(null); + + /** + * @param {Object} values + * @param {String} values.dob - date of birth + * @returns {Object} - An object containing the errors for each inputID + */ + const validate = useCallback((values) => { + const errors = {}; + + if (!values.dob || !ValidationUtils.isValidDate(values.dob)) { + errors.dob = 'common.error.fieldRequired'; + } + + return errors; + }, []); + return ( descriptionInputRef.current && descriptionInputRef.current.focus()} > Navigation.goBack()} />
- - - +
); From da59c363fe246ee4a84f71d3e5e818d4fe4c3d42 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 3 Aug 2023 19:36:04 +0100 Subject: [PATCH 19/45] Add getModifiedExpenseOriginalMessage method --- src/components/MoneyRequestDetails.js | 229 -------------------------- src/libs/ReportUtils.js | 51 +++++- src/libs/actions/IOU.js | 5 +- src/pages/EditRequestPage.js | 5 + 4 files changed, 53 insertions(+), 237 deletions(-) delete mode 100644 src/components/MoneyRequestDetails.js diff --git a/src/components/MoneyRequestDetails.js b/src/components/MoneyRequestDetails.js deleted file mode 100644 index 5bb7c029d44b..000000000000 --- a/src/components/MoneyRequestDetails.js +++ /dev/null @@ -1,229 +0,0 @@ -import React from 'react'; -import {withOnyx} from 'react-native-onyx'; -import {View} from 'react-native'; -import PropTypes from 'prop-types'; -import lodashGet from 'lodash/get'; -import iouReportPropTypes from '../pages/iouReportPropTypes'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; -import * as ReportUtils from '../libs/ReportUtils'; -import * as Expensicons from './Icon/Expensicons'; -import Text from './Text'; -import participantPropTypes from './participantPropTypes'; -import Avatar from './Avatar'; -import styles from '../styles/styles'; -import themeColors from '../styles/themes/default'; -import CONST from '../CONST'; -import withWindowDimensions from './withWindowDimensions'; -import compose from '../libs/compose'; -import ROUTES from '../ROUTES'; -import Icon from './Icon'; -import SettlementButton from './SettlementButton'; -import * as Policy from '../libs/actions/Policy'; -import ONYXKEYS from '../ONYXKEYS'; -import * as IOU from '../libs/actions/IOU'; -import * as CurrencyUtils from '../libs/CurrencyUtils'; -import MenuItemWithTopDescription from './MenuItemWithTopDescription'; -import DateUtils from '../libs/DateUtils'; -import reportPropTypes from '../pages/reportPropTypes'; -import * as UserUtils from '../libs/UserUtils'; -import OfflineWithFeedback from './OfflineWithFeedback'; - -const propTypes = { - /** The report currently being looked at */ - report: iouReportPropTypes.isRequired, - - /** The expense report or iou report (only will have a value if this is a transaction thread) */ - parentReport: iouReportPropTypes, - - /** The policy object for the current route */ - policy: PropTypes.shape({ - /** The name of the policy */ - name: PropTypes.string, - - /** The URL for the policy avatar */ - avatar: PropTypes.string, - }), - - /** The chat report this report is linked to */ - chatReport: reportPropTypes, - - /** Personal details so we can get the ones for the report participants */ - personalDetails: PropTypes.objectOf(participantPropTypes).isRequired, - - /** Whether we're viewing a report with a single transaction in it */ - isSingleTransactionView: PropTypes.bool, - - /** Session info for the currently logged in user. */ - session: PropTypes.shape({ - /** Currently logged in user email */ - email: PropTypes.string, - }), - - ...withLocalizePropTypes, -}; - -const defaultProps = { - isSingleTransactionView: false, - chatReport: {}, - session: { - email: null, - }, - parentReport: {}, - policy: null, -}; - -function MoneyRequestDetails(props) { - // These are only used for the single transaction view and not for expense and iou reports - const {amount: transactionAmount, currency: transactionCurrency, comment: transactionDescription} = ReportUtils.getMoneyRequestAction(props.parentReportAction); - const formattedTransactionAmount = transactionAmount && transactionCurrency && CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); - const transactionDate = lodashGet(props.parentReportAction, ['created']); - const formattedTransactionDate = DateUtils.getDateStringFromISOTimestamp(transactionDate); - - const formattedAmount = CurrencyUtils.convertToDisplayString(ReportUtils.getMoneyRequestTotal(props.report), props.report.currency); - const moneyRequestReport = props.isSingleTransactionView ? props.parentReport : props.report; - const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); - const isExpenseReport = ReportUtils.isExpenseReport(moneyRequestReport); - const payeeName = isExpenseReport ? ReportUtils.getPolicyName(moneyRequestReport) : ReportUtils.getDisplayNameForParticipant(moneyRequestReport.managerID); - const payeeAvatar = isExpenseReport - ? ReportUtils.getWorkspaceAvatar(moneyRequestReport) - : UserUtils.getAvatar(lodashGet(props.personalDetails, [moneyRequestReport.managerID, 'avatar']), moneyRequestReport.managerID); - const isPayer = - Policy.isAdminOfFreePolicy([props.policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(props.session, 'accountID', null) === moneyRequestReport.managerID); - const shouldShowSettlementButton = moneyRequestReport.reportID && !isSettled && !props.isSingleTransactionView && isPayer && !moneyRequestReport.isWaitingOnBankAccount; - const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport); - const shouldShowPaypal = Boolean(lodashGet(props.personalDetails, [moneyRequestReport.ownerAccountID, 'payPalMeAddress'])); - let description = `${props.translate('iou.amount')} • ${props.translate('iou.cash')}`; - if (isSettled) { - description += ` • ${props.translate('iou.settledExpensify')}`; - } else if (props.report.isWaitingOnBankAccount) { - description += ` • ${props.translate('iou.pending')}`; - } - - const {addWorkspaceRoomOrChatPendingAction, addWorkspaceRoomOrChatErrors} = ReportUtils.getReportOfflinePendingActionAndErrors(props.report); - return ( - - - - {props.translate('common.to')} - - - - - - {payeeName} - - {isExpenseReport && ( - - {props.translate('workspace.common.workspace')} - - )} - - - - {!props.isSingleTransactionView && {formattedAmount}} - {!props.isSingleTransactionView && isSettled && ( - - - - )} - {shouldShowSettlementButton && !props.isSmallScreenWidth && ( - - IOU.payMoneyRequest(paymentType, props.chatReport, props.report)} - enablePaymentsRoute={ROUTES.BANK_ACCOUNT_NEW} - addBankAccountRoute={bankAccountRoute} - shouldShowPaymentOptions - /> - - )} - - - {shouldShowSettlementButton && props.isSmallScreenWidth && ( - IOU.payMoneyRequest(paymentType, props.chatReport, props.report)} - enablePaymentsRoute={ROUTES.BANK_ACCOUNT_NEW} - addBankAccountRoute={bankAccountRoute} - shouldShowPaymentOptions - /> - )} - - {props.isSingleTransactionView && ( - <> - Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} - /> - Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} - /> - Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} - /> - - )} - - - ); -} - -MoneyRequestDetails.displayName = 'MoneyRequestDetails'; -MoneyRequestDetails.propTypes = propTypes; -MoneyRequestDetails.defaultProps = defaultProps; - -export default compose( - withWindowDimensions, - withLocalize, - withOnyx({ - chatReport: { - key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`, - }, - session: { - key: ONYXKEYS.SESSION, - }, - parentReport: { - key: (props) => `${ONYXKEYS.COLLECTION.REPORT}${props.report.parentReportID}`, - }, - }), -)(MoneyRequestDetails); diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 8fe4e8f355c1..4cb1ab6f8b76 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1287,13 +1287,15 @@ function getReportPreviewMessage(report, reportAction = {}) { } /** - * Get the report action message when expense has been modified + * Get the report action message when expense has been modified. + * User either reportAction or the originalMessage object. * - * @param {Object} reportAction + * @param {Object} [reportAction] + * @param {Object} [originalMessage] * @returns {String} */ -function getModifiedExpenseMessage(reportAction) { - const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', []); +function getModifiedExpenseMessage(reportAction = {}, originalMessage = {}) { + const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', originalMessage); if (reportActionOriginalMessage.oldAmount && reportActionOriginalMessage.oldCurrency && reportActionOriginalMessage.amount && reportActionOriginalMessage.currency) { const oldCurrency = reportActionOriginalMessage.oldCurrency; const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); @@ -1308,6 +1310,41 @@ function getModifiedExpenseMessage(reportAction) { return `changed the request`; } +/** + * Given the updates user made to the request, compose the originalMessage + * object of the modified expense action. + * + * At the moment, we only allow changing one transaction field at the time. + * + * @param {Object} oldTransaction + * @param {Object} transactionChanges + * @returns {Object} + */ +function getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges) { + const originalMessage = {}; + + // Remark: Comment field is the only one which has new/old prefixes for the keys (newComment/ oldComment), + // all others have old/- pattern such as oldCreated/created + if (_.has(transactionChanges, 'comment')) { + originalMessage['oldComment'] = oldTransaction.comment.comment; + originalMessage['newComment'] = transactionChanges.comment; + } + if (_.has(transactionChanges, 'created')) { + originalMessage['oldCreated'] = oldTransaction.created; + originalMessage['created'] = transactionChanges.created; + } + if (_.has(transactionChanges, 'amount')) { + originalMessage['oldAmount'] = oldTransaction.amount; + originalMessage['amount'] = transactionChanges.amount; + } + if (_.has(transactionChanges, 'currency')) { + originalMessage['oldCurrency'] = oldTransaction.currency; + originalMessage['currency'] = transactionChanges.currency; + } + + return originalMessage; +} + /** * Get the title for a report. * @@ -1872,11 +1909,13 @@ function buildOptimisticReportPreview(chatReport, iouReport) { * * @param {Object} transactionThread * @param {Object} iouReport + * @param {Object} transactionChanges * * @returns {Object} */ -function buildOptimisticModifiedExpenseReportAction(transactionThread, iouReport) { - const message = getReportPreviewMessage(iouReport); +function buildOptimisticModifiedExpenseReportAction(transactionThread, iouReport, transactionChanges) { + const originalMessage = getModifiedExpenseOriginalMessage(transactionChanges); + const message = getModifiedExpenseMessage(originalMessage); return { reportActionID: NumberUtils.rand64(), reportID: transactionThread.reportID, diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 4b8d07baf1ef..2606dbfc350f 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -783,8 +783,9 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou * @param {String} transactionID * @param {Number} transactionThreadReportID * @param {Object} updatedTransaction + * @param {Object} transactionChanges */ -function editIOUTransaction(transactionID, transactionThreadReportID, updatedTransaction) { +function editIOUTransaction(transactionID, transactionThreadReportID, transactionChanges) { // STEP 1: Get all collections we're updating const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; @@ -793,7 +794,7 @@ function editIOUTransaction(transactionID, transactionThreadReportID, updatedTra const chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`]; // STEP 2: Build new modified expense report action. - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread); + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges); // STEP 3: Compose the data for the API command const optimisticData = [ diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 575f4db3ee77..2b9b116e6fbc 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -12,6 +12,7 @@ import EditRequestDescriptionPage from './EditRequestDescriptionPage'; import EditRequestCreatedPage from './EditRequestCreatedPage'; import reportPropTypes from './reportPropTypes'; import * as ReportUtils from '../libs/ReportUtils'; +import * as IOU from '../libs/actions/IOU'; const propTypes = { /** Route from navigation */ @@ -49,6 +50,8 @@ function EditRequestPage({report, route}) { // eslint-disable-next-line no-console console.log({changes}); + IOU.editIOUTransaction(transactionID, report.reportID, ); + // Note: The "modal" we are dismissing is the MoneyRequestAmountPage Navigation.dismissModal(); } @@ -71,6 +74,8 @@ function EditRequestPage({report, route}) { }} /> ); + } else if (field === CONST.EDIT_REQUEST_FIELD.AMOUNT) { + return null; } return null; From 0ddb17cf8f9c336f41e620ea2b21c5352c1a4129 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 3 Aug 2023 19:57:28 +0100 Subject: [PATCH 20/45] Create the buildOptimisticModifiedExpenseReportAction method --- src/libs/ReportUtils.js | 52 +++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 4cb1ab6f8b76..8011d9edc7e1 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1288,15 +1288,13 @@ function getReportPreviewMessage(report, reportAction = {}) { /** * Get the report action message when expense has been modified. - * User either reportAction or the originalMessage object. * - * @param {Object} [reportAction] - * @param {Object} [originalMessage] + * @param {Object} reportAction * @returns {String} */ -function getModifiedExpenseMessage(reportAction = {}, originalMessage = {}) { - const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', originalMessage); - if (reportActionOriginalMessage.oldAmount && reportActionOriginalMessage.oldCurrency && reportActionOriginalMessage.amount && reportActionOriginalMessage.currency) { +function getModifiedExpenseMessage(reportAction) { + const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', {}); + if (!_.isEmpty(reportActionOriginalMessage) && reportActionOriginalMessage.oldAmount && reportActionOriginalMessage.oldCurrency && reportActionOriginalMessage.amount && reportActionOriginalMessage.currency) { const oldCurrency = reportActionOriginalMessage.oldCurrency; const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', oldCurrency}); @@ -1908,33 +1906,41 @@ function buildOptimisticReportPreview(chatReport, iouReport) { * Builds an optimistic report preview action with a randomly generated reportActionID. * * @param {Object} transactionThread - * @param {Object} iouReport + * @param {Object} oldTransaction * @param {Object} transactionChanges * * @returns {Object} */ -function buildOptimisticModifiedExpenseReportAction(transactionThread, iouReport, transactionChanges) { - const originalMessage = getModifiedExpenseOriginalMessage(transactionChanges); - const message = getModifiedExpenseMessage(originalMessage); +function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransaction, transactionChanges) { + const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges); return { - reportActionID: NumberUtils.rand64(), - reportID: transactionThread.reportID, actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE, - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - originalMessage: { - linkedReportID: iouReport.reportID, - }, + actorAccountID: currentUserAccountID, + automatic: false, + avatar: lodashGet(currentUserPersonalDetails, 'avatar', UserUtils.getDefaultAvatar(currentUserAccountID)), + created: DateUtils.getDBTime(), + isAttachment: false, message: [ { - html: message, - text: message, - isEdited: false, - type: CONST.REPORT.MESSAGE.TYPE.COMMENT, + // Currently we are composing the message from the originalMessage and message is only used in OldDot, + // so this message is not used in the App + text: 'You', + style: 'strong', + type: CONST.REPORT.MESSAGE.TYPE.TEXT, }, ], - created: DateUtils.getDBTime(), - accountID: iouReport.managerID || 0, - actorAccountID: iouReport.managerID || 0, + originalMessage, + person: [ + { + style: 'strong', + text: lodashGet(currentUserPersonalDetails, 'displayName', currentUserAccountID), + type: 'TEXT', + }, + ], + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + reportActionID: NumberUtils.rand64(), + reportID: transactionThread.reportID, + shouldShow: true, }; } From f3f9834fabddbde21d37099f3d7ced3f9dc95105 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 3 Aug 2023 20:12:40 +0100 Subject: [PATCH 21/45] Create updateTransaction method --- src/libs/ReportUtils.js | 11 ++++++----- src/libs/TransactionUtils.js | 35 +++++++++++++++++++++++++++++++---- src/libs/actions/IOU.js | 4 +++- src/pages/EditRequestPage.js | 4 ++-- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 8011d9edc7e1..03f8e48fb4f3 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -13,6 +13,7 @@ import ROUTES from '../ROUTES'; import * as NumberUtils from './NumberUtils'; import * as NumberFormatUtils from './NumberFormatUtils'; import * as ReportActionsUtils from './ReportActionsUtils'; +import * as TransactionUtils from '../libs/TransactionUtils'; import Permissions from './Permissions'; import DateUtils from './DateUtils'; import linkingConfig from './Navigation/linkingConfig'; @@ -1324,19 +1325,19 @@ function getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges) { // Remark: Comment field is the only one which has new/old prefixes for the keys (newComment/ oldComment), // all others have old/- pattern such as oldCreated/created if (_.has(transactionChanges, 'comment')) { - originalMessage['oldComment'] = oldTransaction.comment.comment; + originalMessage['oldComment'] = TransactionUtils.getDescription(oldTransaction); originalMessage['newComment'] = transactionChanges.comment; } if (_.has(transactionChanges, 'created')) { - originalMessage['oldCreated'] = oldTransaction.created; + originalMessage['oldCreated'] = TransactionUtils.getCreated(oldTransaction); originalMessage['created'] = transactionChanges.created; } if (_.has(transactionChanges, 'amount')) { - originalMessage['oldAmount'] = oldTransaction.amount; + originalMessage['oldAmount'] = TransactionUtils.getAmount(oldTransaction); originalMessage['amount'] = transactionChanges.amount; } if (_.has(transactionChanges, 'currency')) { - originalMessage['oldCurrency'] = oldTransaction.currency; + originalMessage['oldCurrency'] = TransactionUtils.getCurrency(oldTransaction); originalMessage['currency'] = transactionChanges.currency; } @@ -1903,7 +1904,7 @@ function buildOptimisticReportPreview(chatReport, iouReport) { } /** - * Builds an optimistic report preview action with a randomly generated reportActionID. + * Builds an optimistic modified expense action with a randomly generated reportActionID. * * @param {Object} transactionThread * @param {Object} oldTransaction diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index e306e5494fa5..f4666bf8f4cc 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -56,6 +56,32 @@ function buildOptimisticTransaction(amount, currency, reportID, comment = '', so }; } +/** + * Given the edit made to the money request, return an updated transaction object. + * + * @param {Object} transaction + * @param {Object} transactionChanges + * @returns {Object} + */ +function updateTransaction(transaction, transactionChanges) { + const updatedTransaction = {...transaction}; + + if (_.has(transactionChanges, 'comment')) { + updatedTransaction['comment'] = {'comment': transactionChanges.comment}; + } + if (_.has(transactionChanges, 'created')) { + updatedTransaction['modifiedCreated'] = transactionChanges.created; + } + if (_.has(transactionChanges, 'amount')) { + updatedTransaction['modifiedAmount'] = transactionChanges.amount; + } + if (_.has(transactionChanges, 'currency')) { + updatedTransaction['modifiedCurrency'] = transactionChanges.currency; + } + + return updatedTransaction; +} + /** * Retrieve the particular transaction object given its ID. * @@ -74,7 +100,7 @@ function getTransaction(transactionID) { * @returns {String} */ function getDescription(transaction) { - return lodashGet(transaction, 'comment', ''); + return lodashGet(transaction, 'comment.comment', ''); } /** @@ -84,7 +110,7 @@ function getDescription(transaction) { * @returns {Number} */ function getAmount(transaction) { - const amount = lodashGet(transaction, 'modifiedAmount', ''); + const amount = lodashGet(transaction, 'modifiedAmount', 0); if (amount) { return amount; } @@ -102,7 +128,7 @@ function getCurrency(transaction) { if (currency) { return currency; } - return lodashGet(transaction, 'currency', 0); + return lodashGet(transaction, 'currency', ''); } /** @@ -116,11 +142,12 @@ function getCreated(transaction) { if (created) { return created; } - return lodashGet(transaction, 'created', 0); + return lodashGet(transaction, 'created', ''); } export { buildOptimisticTransaction, + updateTransaction, getTransaction, getDescription, getAmount, diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 2606dbfc350f..de7eabef155e 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -796,13 +796,15 @@ function editIOUTransaction(transactionID, transactionThreadReportID, transactio // STEP 2: Build new modified expense report action. const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges); + const updatedTransaction = TransactionUtils.updatedTransaction(transaction, transactionChanges); + // STEP 3: Compose the data for the API command const optimisticData = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`, value: { - [reportAction.reportActionID]: {pendingAction: null}, + [updatedReportAction.reportActionID]: {pendingAction: null}, }, }, ]; diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 2b9b116e6fbc..f81d7d6847af 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -50,7 +50,7 @@ function EditRequestPage({report, route}) { // eslint-disable-next-line no-console console.log({changes}); - IOU.editIOUTransaction(transactionID, report.reportID, ); + IOU.editIOUTransaction(transactionID, report.reportID, changes); // Note: The "modal" we are dismissing is the MoneyRequestAmountPage Navigation.dismissModal(); @@ -68,7 +68,7 @@ function EditRequestPage({report, route}) { } else if (field === CONST.EDIT_REQUEST_FIELD.DATE) { return ( { updateTransactionWithChanges(changes); }} From beae42da14943dcd37e5e123357f0558c271ce80 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 4 Aug 2023 01:46:54 +0300 Subject: [PATCH 22/45] Add helper functions for manipulating the transaction --- src/libs/ReportUtils.js | 3 +- src/libs/TransactionUtils.js | 10 +++-- src/libs/actions/IOU.js | 74 ++++++++++++++++++++++++++++++------ src/pages/EditRequestPage.js | 2 +- 4 files changed, 72 insertions(+), 17 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 03f8e48fb4f3..d799b6611314 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1923,8 +1923,7 @@ function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransa isAttachment: false, message: [ { - // Currently we are composing the message from the originalMessage and message is only used in OldDot, - // so this message is not used in the App + // Currently we are composing the message from the originalMessage and message is only used in OldDot and not in the App text: 'You', style: 'strong', type: CONST.REPORT.MESSAGE.TYPE.TEXT, diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index f4666bf8f4cc..a11c966fed09 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -63,11 +63,15 @@ function buildOptimisticTransaction(amount, currency, reportID, comment = '', so * @param {Object} transactionChanges * @returns {Object} */ -function updateTransaction(transaction, transactionChanges) { +function getUpdatedTransaction(transaction, transactionChanges) { const updatedTransaction = {...transaction}; + // The comment property does not have its modifiedComment counterpart if (_.has(transactionChanges, 'comment')) { - updatedTransaction['comment'] = {'comment': transactionChanges.comment}; + updatedTransaction['comment'] = { + ...updatedTransaction.comment, + 'comment': transactionChanges.comment, + }; } if (_.has(transactionChanges, 'created')) { updatedTransaction['modifiedCreated'] = transactionChanges.created; @@ -147,7 +151,7 @@ function getCreated(transaction) { export { buildOptimisticTransaction, - updateTransaction, + getUpdatedTransaction, getTransaction, getDescription, getAmount, diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index de7eabef155e..1910e42672de 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -785,7 +785,7 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou * @param {Object} updatedTransaction * @param {Object} transactionChanges */ -function editIOUTransaction(transactionID, transactionThreadReportID, transactionChanges) { +function editMoneyRequest(transactionID, transactionThreadReportID, transactionChanges) { // STEP 1: Get all collections we're updating const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; @@ -796,7 +796,33 @@ function editIOUTransaction(transactionID, transactionThreadReportID, transactio // STEP 2: Build new modified expense report action. const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges); - const updatedTransaction = TransactionUtils.updatedTransaction(transaction, transactionChanges); + const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges); + + let updatedIOUReport = null; + let updatedReportPreviewAction = null; + // In case the amount or currency being edited, we need to update the IOU report total + // and report preview message accordingly. + if (_.has(transactionChanges, 'amount') || _.has(transactionChanges, 'currency')) { + if (ReportUtils.isExpenseReport(iouReport.reportID)) { + updatedIOUReport = {...iouReport}; + + // Because of the Expense reports are stored as negative values, we add the total from the amount + updatedIOUReport.total += reportAction.originalMessage.amount; + } else { + updatedIOUReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, reportAction.actorAccountID, reportAction.originalMessage.amount, reportAction.originalMessage.currency, true); + } + + updatedIOUReport.lastMessageText = iouReportLastMessageText; + updatedIOUReport.lastVisibleActionCreated = lastVisibleAction.created; + + updatedReportPreviewAction = {...reportPreviewAction}; + const messageText = Localize.translateLocal('iou.payerOwesAmount', { + payer: updatedIOUReport.managerEmail, + amount: CurrencyUtils.convertToDisplayString(updatedIOUReport.total, updatedIOUReport.currency), + }); + updatedReportPreviewAction.message[0].text = messageText; + updatedReportPreviewAction.message[0].html = messageText; + } // STEP 3: Compose the data for the API command const optimisticData = [ @@ -804,7 +830,14 @@ function editIOUTransaction(transactionID, transactionThreadReportID, transactio onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`, value: { - [updatedReportAction.reportActionID]: {pendingAction: null}, + [updatedReportAction.reportActionID]: updatedReportAction, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + value: { + [transactionID]: updatedTransaction, }, }, ]; @@ -821,21 +854,40 @@ function editIOUTransaction(transactionID, transactionThreadReportID, transactio const failureData = [ { - onyxMethod: Onyx.METHOD.SET, + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`, + value: { + [updatedReportAction.reportActionID]: updatedReportAction, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, - value: transaction, + value: { + transaction, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.report}`, + value: { + iouReport, + }, }, ] + // STEP 6: Call the API endpoint API.write( - 'EditIOUTransaction', + 'EditMoneyRequest', { transactionID, reportActionID: reportAction.reportActionID, - created: transaction.created, - amount: transaction.amount, - currency: transaction.currency, - comment: transaction.comment, + + // Using the getter methods here to ensure we pass modified field if present + created: TransactionUtils.getCreated(updatedTransaction), + amount: TransactionUtils.getAmount(updatedTransaction), + currency: TransactionUtils.getCurrency(updatedTransaction), + comment: TransactionUtils.getComment(updatedTransaction), }, {optimisticData, successData, failureData}, ); @@ -1599,7 +1651,7 @@ function navigateToNextPage(iou, iouType, reportID, report) { } export { - editIOUTransaction, + editMoneyRequest, deleteMoneyRequest, splitBill, splitBillAndOpenReport, diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index f81d7d6847af..80de647c7210 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -50,7 +50,7 @@ function EditRequestPage({report, route}) { // eslint-disable-next-line no-console console.log({changes}); - IOU.editIOUTransaction(transactionID, report.reportID, changes); + IOU.editMoneyRequest(transactionID, report.reportID, changes); // Note: The "modal" we are dismissing is the MoneyRequestAmountPage Navigation.dismissModal(); From 2e5cb6295d71c6e73bfa71bb2aa97766900efe88 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 4 Aug 2023 02:35:38 +0300 Subject: [PATCH 23/45] Improving the edit money request command --- .../ReportActionItem/MoneyRequestView.js | 5 +-- src/libs/ReportUtils.js | 11 +++-- src/libs/TransactionUtils.js | 15 ++----- src/libs/actions/IOU.js | 43 ++++--------------- src/pages/EditRequestPage.js | 2 +- 5 files changed, 24 insertions(+), 52 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 63c0cf7be60c..f41c7e3ed157 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -72,9 +72,8 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic const moneyRequestReport = parentReport; const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); - const isPayer = - Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID); - const canEdit = !isSettled && (ReportUtils.isExpenseReport(moneyRequestReport) || (ReportUtils.isIOUReport(moneyRequestReport) && !isPayer)) + const isPayer = Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID); + const canEdit = !isSettled && (ReportUtils.isExpenseReport(moneyRequestReport) || (ReportUtils.isIOUReport(moneyRequestReport) && !isPayer)); let description = `${translate('iou.amount')} • ${translate('iou.cash')}`; if (isSettled) { diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index d799b6611314..c3e2731cdfcf 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1295,7 +1295,13 @@ function getReportPreviewMessage(report, reportAction = {}) { */ function getModifiedExpenseMessage(reportAction) { const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', {}); - if (!_.isEmpty(reportActionOriginalMessage) && reportActionOriginalMessage.oldAmount && reportActionOriginalMessage.oldCurrency && reportActionOriginalMessage.amount && reportActionOriginalMessage.currency) { + if ( + !_.isEmpty(reportActionOriginalMessage) && + reportActionOriginalMessage.oldAmount && + reportActionOriginalMessage.oldCurrency && + reportActionOriginalMessage.amount && + reportActionOriginalMessage.currency + ) { const oldCurrency = reportActionOriginalMessage.oldCurrency; const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', oldCurrency}); @@ -1312,7 +1318,7 @@ function getModifiedExpenseMessage(reportAction) { /** * Given the updates user made to the request, compose the originalMessage * object of the modified expense action. - * + * * At the moment, we only allow changing one transaction field at the time. * * @param {Object} oldTransaction @@ -1944,7 +1950,6 @@ function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransa }; } - /** * Updates a report preview action that exists for an IOU report. * diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index a11c966fed09..ccdf401a460f 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -70,7 +70,7 @@ function getUpdatedTransaction(transaction, transactionChanges) { if (_.has(transactionChanges, 'comment')) { updatedTransaction['comment'] = { ...updatedTransaction.comment, - 'comment': transactionChanges.comment, + comment: transactionChanges.comment, }; } if (_.has(transactionChanges, 'created')) { @@ -82,7 +82,8 @@ function getUpdatedTransaction(transaction, transactionChanges) { if (_.has(transactionChanges, 'currency')) { updatedTransaction['modifiedCurrency'] = transactionChanges.currency; } - + updatedTransaction['pendingAction'] = CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE; + return updatedTransaction; } @@ -149,12 +150,4 @@ function getCreated(transaction) { return lodashGet(transaction, 'created', ''); } -export { - buildOptimisticTransaction, - getUpdatedTransaction, - getTransaction, - getDescription, - getAmount, - getCurrency, - getCreated, -}; +export {buildOptimisticTransaction, getUpdatedTransaction, getTransaction, getDescription, getAmount, getCurrency, getCreated}; diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 1910e42672de..0fe8bdb209cf 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -790,41 +790,13 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`]; - const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(iouReport.chatReportID, iouReport.reportID); - const chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`]; // STEP 2: Build new modified expense report action. const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges); - const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges); + // STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct - let updatedIOUReport = null; - let updatedReportPreviewAction = null; - // In case the amount or currency being edited, we need to update the IOU report total - // and report preview message accordingly. - if (_.has(transactionChanges, 'amount') || _.has(transactionChanges, 'currency')) { - if (ReportUtils.isExpenseReport(iouReport.reportID)) { - updatedIOUReport = {...iouReport}; - - // Because of the Expense reports are stored as negative values, we add the total from the amount - updatedIOUReport.total += reportAction.originalMessage.amount; - } else { - updatedIOUReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, reportAction.actorAccountID, reportAction.originalMessage.amount, reportAction.originalMessage.currency, true); - } - - updatedIOUReport.lastMessageText = iouReportLastMessageText; - updatedIOUReport.lastVisibleActionCreated = lastVisibleAction.created; - - updatedReportPreviewAction = {...reportPreviewAction}; - const messageText = Localize.translateLocal('iou.payerOwesAmount', { - payer: updatedIOUReport.managerEmail, - amount: CurrencyUtils.convertToDisplayString(updatedIOUReport.total, updatedIOUReport.currency), - }); - updatedReportPreviewAction.message[0].text = messageText; - updatedReportPreviewAction.message[0].html = messageText; - } - - // STEP 3: Compose the data for the API command + // STEP 4: Compose the optimistic data const optimisticData = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -836,9 +808,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, - value: { - [transactionID]: updatedTransaction, - }, + value: {updatedTransaction}, }, ]; @@ -850,6 +820,11 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC [reportAction.reportActionID]: {pendingAction: null}, }, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + value: {pendingAction: null}, + }, ]; const failureData = [ @@ -874,7 +849,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC iouReport, }, }, - ] + ]; // STEP 6: Call the API endpoint API.write( diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 80de647c7210..bdde4367b94e 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -37,7 +37,7 @@ const defaultProps = { function EditRequestPage({report, route}) { const parentReportAction = ReportActionsUtils.getParentReportAction(report); - const transactionID = ReportActionsUtils.getLinkedTransactionID(ReportUtils.getParentReport(report), parentReportAction) + const transactionID = ReportActionsUtils.getLinkedTransactionID(ReportUtils.getParentReport(report), parentReportAction); const transaction = TransactionUtils.getTransaction(transactionID); const transactionDescription = TransactionUtils.getDescription(transaction); const transactionAmount = TransactionUtils.getAmount(transaction); From ca7001ddf218d6099da76fd45c1a8ec00f4ac00c Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 4 Aug 2023 02:39:06 +0300 Subject: [PATCH 24/45] Add modified expense report action to reportActionItem --- src/pages/home/report/ReportActionItem.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index b2e95771c547..e52741677f9d 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -308,6 +308,10 @@ function ReportActionItem(props) { ) : null} ); + } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE) { + children = ( + + ); } else { const message = _.last(lodashGet(props.action, 'message', [{}])); const hasBeenFlagged = !_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], moderationDecision); From 0485d042229fd6f1049ef70bcf3dff4df2f6d423 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Sun, 6 Aug 2023 20:21:10 +0300 Subject: [PATCH 25/45] Use getDescription --- src/libs/actions/IOU.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 0fe8bdb209cf..eaf8fb4d107e 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -862,7 +862,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC created: TransactionUtils.getCreated(updatedTransaction), amount: TransactionUtils.getAmount(updatedTransaction), currency: TransactionUtils.getCurrency(updatedTransaction), - comment: TransactionUtils.getComment(updatedTransaction), + comment: TransactionUtils.getDescription(updatedTransaction), }, {optimisticData, successData, failureData}, ); From f89ddfda1b1d7b085ca9f88e9dce6d9f58a72685 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Sun, 6 Aug 2023 21:58:17 +0300 Subject: [PATCH 26/45] Uptating the transactions and report utils --- src/libs/ReportUtils.js | 120 +++++++++++++++-------------------- src/libs/TransactionUtils.js | 10 +-- 2 files changed, 55 insertions(+), 75 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 728d30899963..351b354c8c5b 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -406,6 +406,17 @@ function isOptimisticPersonalDetail(accountID) { return _.isEmpty(allPersonalDetails[accountID]) || !!allPersonalDetails[accountID].isOptimisticPersonalDetail; } +/** + * Check if report is a DM and personal detail of participant is optimistic data + * @param {String} report + * @returns {Boolean} + */ +function shouldDisableDetailPage(report) { + const participants = lodashGet(report, 'participantAccountIDs', []); + const isMultipleParticipant = participants.length > 1; + return !isMultipleParticipant && isOptimisticPersonalDetail(participants[0]) && !report.parentReportID; +} + /** * Checks if a report is a task report from a policy expense chat. * @@ -450,35 +461,6 @@ function isConciergeChatReport(report) { return lodashGet(report, 'participantAccountIDs', []).length === 1 && Number(report.participantAccountIDs[0]) === CONST.ACCOUNT_ID.CONCIERGE && !isChatThread(report); } -/** - * Check if the report is a single chat report that isn't a thread - * and personal detail of participant is optimistic data - * @param {Object} report - * @param {Array} report.participantAccountIDs - * @returns {Boolean} - */ -function shouldDisableDetailPage(report) { - const participantAccountIDs = lodashGet(report, 'participantAccountIDs', []); - - if (isChatRoom(report) || isPolicyExpenseChat(report) || isChatThread(report)) { - return false; - } - if (participantAccountIDs.length === 1) { - return isOptimisticPersonalDetail(participantAccountIDs[0]); - } - return false; -} - -/** - * Returns true if this report has only one participant and it's an Expensify account. - * @param {Object} report - * @returns {Boolean} - */ -function isExpensifyOnlyParticipantInReport(report) { - const reportParticipants = _.without(lodashGet(report, 'participantAccountIDs', []), currentUserAccountID); - return lodashGet(report, 'participantAccountIDs', []).length === 1 && _.some(reportParticipants, (accountID) => _.contains(CONST.EXPENSIFY_ACCOUNT_IDS, accountID)); -} - /** * Returns true if there are any Expensify accounts (i.e. with domain 'expensify.com') in the set of accountIDs * by cross-referencing the accountIDs with personalDetails. @@ -1313,22 +1295,34 @@ function getReportPreviewMessage(report, reportAction = {}) { */ function getModifiedExpenseMessage(reportAction) { const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', {}); - if ( - !_.isEmpty(reportActionOriginalMessage) && - reportActionOriginalMessage.oldAmount && - reportActionOriginalMessage.oldCurrency && - reportActionOriginalMessage.amount && - reportActionOriginalMessage.currency - ) { - const oldCurrency = reportActionOriginalMessage.oldCurrency; - const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); - const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', oldCurrency}); + if (!_.isEmpty(reportActionOriginalMessage)) { + if (reportActionOriginalMessage.oldAmount && + reportActionOriginalMessage.oldCurrency && + reportActionOriginalMessage.amount && + reportActionOriginalMessage.currency + ) { + const oldCurrency = reportActionOriginalMessage.oldCurrency; + const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); + const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', oldCurrency}); - const currency = reportActionOriginalMessage.currency; - const currencyUnit = CurrencyUtils.getCurrencyUnit(currency); - const amount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.amount) / currencyUnit, {style: 'currency', currency}); + const currency = reportActionOriginalMessage.currency; + const currencyUnit = CurrencyUtils.getCurrencyUnit(currency); + const amount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.amount) / currencyUnit, {style: 'currency', currency}); - return `changed the request to ${amount} (previously ${oldAmount})`; + return `changed the request to ${amount} (previously ${oldAmount})`; + } + + if (reportActionOriginalMessage.oldComment && + reportActionOriginalMessage.newComment + ) { + return `changed the request description to ${reportActionOriginalMessage.newComment} (previously ${reportActionOriginalMessage.oldComment})`; + } + + if (reportActionOriginalMessage.oldCreated && + reportActionOriginalMessage.created + ) { + return `changed the request date to ${reportActionOriginalMessage.created} (previously ${reportActionOriginalMessage.oldCreated})`; + } } return `changed the request`; } @@ -1349,20 +1343,21 @@ function getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges) { // Remark: Comment field is the only one which has new/old prefixes for the keys (newComment/ oldComment), // all others have old/- pattern such as oldCreated/created if (_.has(transactionChanges, 'comment')) { - originalMessage['oldComment'] = TransactionUtils.getDescription(oldTransaction); - originalMessage['newComment'] = transactionChanges.comment; + originalMessage.oldComment = TransactionUtils.getDescription(oldTransaction); + originalMessage.newComment = transactionChanges.comment; } if (_.has(transactionChanges, 'created')) { - originalMessage['oldCreated'] = TransactionUtils.getCreated(oldTransaction); - originalMessage['created'] = transactionChanges.created; - } - if (_.has(transactionChanges, 'amount')) { - originalMessage['oldAmount'] = TransactionUtils.getAmount(oldTransaction); - originalMessage['amount'] = transactionChanges.amount; + originalMessage.oldCreated = TransactionUtils.getCreated(oldTransaction); + originalMessage.created = transactionChanges.created; } - if (_.has(transactionChanges, 'currency')) { - originalMessage['oldCurrency'] = TransactionUtils.getCurrency(oldTransaction); - originalMessage['currency'] = transactionChanges.currency; + + // The amount is always a combination of the currency and the number value so when one changes we need to store both + // to match how we handle the modified expense action in oldDot + if (_.has(transactionChanges, 'amount') || _.has(transactionChanges, 'currency')) { + originalMessage.oldAmount = TransactionUtils.getAmount(oldTransaction); + originalMessage.amount = lodashGet(transactionChanges, 'amount', originalMessage.oldAmount); + originalMessage.oldCurrency = TransactionUtils.getCurrency(oldTransaction); + originalMessage.currency = lodashGet(transactionChanges, 'currency', originalMessage.oldCurrency);; } return originalMessage; @@ -1844,22 +1839,9 @@ function getIOUReportActionMessage(type, total, comment, currency, paymentType = * @param {String} [iouReportID] - Only required if the IOUReportActions type is oneOf(decline, cancel, pay). Generates a randomID as default. * @param {Boolean} [isSettlingUp] - Whether we are settling up an IOU. * @param {Boolean} [isSendMoneyFlow] - Whether this is send money flow - * @param {Object} [receipt] * @returns {Object} */ -function buildOptimisticIOUReportAction( - type, - amount, - currency, - comment, - participants, - transactionID, - paymentType = '', - iouReportID = '', - isSettlingUp = false, - isSendMoneyFlow = false, - receipt = {}, -) { +function buildOptimisticIOUReportAction(type, amount, currency, comment, participants, transactionID, paymentType = '', iouReportID = '', isSettlingUp = false, isSendMoneyFlow = false) { const IOUReportID = iouReportID || generateReportID(); const originalMessage = { @@ -1905,7 +1887,6 @@ function buildOptimisticIOUReportAction( shouldShow: true, created: DateUtils.getDBTime(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - receipt, }; } @@ -2985,7 +2966,6 @@ export { getPolicyName, getPolicyType, isArchivedRoom, - isExpensifyOnlyParticipantInReport, isPolicyExpenseChatAdmin, isPolicyAdmin, isPublicRoom, diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index ce55a29f0da6..52aae4852dd0 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -70,21 +70,21 @@ function getUpdatedTransaction(transaction, transactionChanges) { // The comment property does not have its modifiedComment counterpart if (_.has(transactionChanges, 'comment')) { - updatedTransaction['comment'] = { + updatedTransaction.comment = { ...updatedTransaction.comment, comment: transactionChanges.comment, }; } if (_.has(transactionChanges, 'created')) { - updatedTransaction['modifiedCreated'] = transactionChanges.created; + updatedTransaction.modifiedCreated = transactionChanges.created; } if (_.has(transactionChanges, 'amount')) { - updatedTransaction['modifiedAmount'] = transactionChanges.amount; + updatedTransaction.modifiedAmount = transactionChanges.amount; } if (_.has(transactionChanges, 'currency')) { - updatedTransaction['modifiedCurrency'] = transactionChanges.currency; + updatedTransaction.modifiedCurrency = transactionChanges.currency; } - updatedTransaction['pendingAction'] = CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE; + updatedTransaction.pendingAction = CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE; return updatedTransaction; } From 538a813ee87af7633e6cb4eb543e391572a67731 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 7 Aug 2023 15:34:57 +0100 Subject: [PATCH 27/45] Revert incorrect main merge --- src/libs/ReportUtils.js | 43 +++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 75644f06c111..c3762ac9e438 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -13,7 +13,7 @@ import ROUTES from '../ROUTES'; import * as NumberUtils from './NumberUtils'; import * as NumberFormatUtils from './NumberFormatUtils'; import * as ReportActionsUtils from './ReportActionsUtils'; -import * as TransactionUtils from '../libs/TransactionUtils'; +import * as TransactionUtils from './TransactionUtils'; import Permissions from './Permissions'; import DateUtils from './DateUtils'; import linkingConfig from './Navigation/linkingConfig'; @@ -406,17 +406,6 @@ function isOptimisticPersonalDetail(accountID) { return _.isEmpty(allPersonalDetails[accountID]) || !!allPersonalDetails[accountID].isOptimisticPersonalDetail; } -/** - * Check if report is a DM and personal detail of participant is optimistic data - * @param {String} report - * @returns {Boolean} - */ -function shouldDisableDetailPage(report) { - const participants = lodashGet(report, 'participantAccountIDs', []); - const isMultipleParticipant = participants.length > 1; - return !isMultipleParticipant && isOptimisticPersonalDetail(participants[0]) && !report.parentReportID; -} - /** * Checks if a report is a task report from a policy expense chat. * @@ -461,6 +450,35 @@ function isConciergeChatReport(report) { return lodashGet(report, 'participantAccountIDs', []).length === 1 && Number(report.participantAccountIDs[0]) === CONST.ACCOUNT_ID.CONCIERGE && !isChatThread(report); } +/** + * Check if the report is a single chat report that isn't a thread + * and personal detail of participant is optimistic data + * @param {Object} report + * @param {Array} report.participantAccountIDs + * @returns {Boolean} + */ +function shouldDisableDetailPage(report) { + const participantAccountIDs = lodashGet(report, 'participantAccountIDs', []); + + if (isChatRoom(report) || isPolicyExpenseChat(report) || isChatThread(report)) { + return false; + } + if (participantAccountIDs.length === 1) { + return isOptimisticPersonalDetail(participantAccountIDs[0]); + } + return false; +} + +/** + * Returns true if this report has only one participant and it's an Expensify account. + * @param {Object} report + * @returns {Boolean} + */ +function isExpensifyOnlyParticipantInReport(report) { + const reportParticipants = _.without(lodashGet(report, 'participantAccountIDs', []), currentUserAccountID); + return lodashGet(report, 'participantAccountIDs', []).length === 1 && _.some(reportParticipants, (accountID) => _.contains(CONST.EXPENSIFY_ACCOUNT_IDS, accountID)); +} + /** * Returns true if there are any Expensify accounts (i.e. with domain 'expensify.com') in the set of accountIDs * by cross-referencing the accountIDs with personalDetails. @@ -2966,6 +2984,7 @@ export { getPolicyName, getPolicyType, isArchivedRoom, + isExpensifyOnlyParticipantInReport, isPolicyExpenseChatAdmin, isPolicyAdmin, isPublicRoom, From c64fddce58b956b6d71e54377bc4e23e38cb1d98 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 7 Aug 2023 15:42:27 +0100 Subject: [PATCH 28/45] Improvement --- src/libs/actions/IOU.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 923f876c4d73..847b8e743150 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -791,14 +791,13 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou /** * @param {String} transactionID * @param {Number} transactionThreadReportID - * @param {Object} updatedTransaction * @param {Object} transactionChanges */ function editMoneyRequest(transactionID, transactionThreadReportID, transactionChanges) { // STEP 1: Get all collections we're updating const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; - const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`]; + const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.parentReportID}`]; // STEP 2: Build new modified expense report action. const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges); @@ -826,7 +825,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`, value: { - [reportAction.reportActionID]: {pendingAction: null}, + [updatedReportAction.reportActionID]: {pendingAction: null}, }, }, { @@ -865,7 +864,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC 'EditMoneyRequest', { transactionID, - reportActionID: reportAction.reportActionID, + reportActionID: updatedReportAction.reportActionID, // Using the getter methods here to ensure we pass modified field if present created: TransactionUtils.getCreated(updatedTransaction), From cb3d210ec28ab236ae4fed312863cbb185e08589 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Wed, 9 Aug 2023 15:34:47 +0100 Subject: [PATCH 29/45] Fixes to the description and created edit money request flow --- src/CONST.js | 1 + src/libs/ReportUtils.js | 25 ++++++++++++------- src/libs/TransactionUtils.js | 4 ++- src/libs/actions/IOU.js | 15 +++++------- src/pages/EditRequestCreatedPage.js | 4 +-- src/pages/EditRequestPage.js | 38 ++++++++++++++--------------- 6 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index e57a801b9e02..a40ce5adca9e 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -1316,6 +1316,7 @@ const CONST = { AMOUNT: 'amount', DATE: 'date', DESCRIPTION: 'description', + MERCHANT: 'merchant', }, FOOTER: { EXPENSE_MANAGEMENT_URL: `${USE_EXPENSIFY_URL}/expense-management`, diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index dc8382a3b2be..d19170f18513 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1313,11 +1313,12 @@ function getReportPreviewMessage(report, reportAction = {}) { */ function getModifiedExpenseMessage(reportAction) { const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', {}); + console.log('reportActionOriginalMessage: ', reportActionOriginalMessage); if (!_.isEmpty(reportActionOriginalMessage)) { - if (reportActionOriginalMessage.oldAmount && - reportActionOriginalMessage.oldCurrency && - reportActionOriginalMessage.amount && - reportActionOriginalMessage.currency + if (_.has(reportActionOriginalMessage, 'oldAmount') && + _.has(reportActionOriginalMessage, 'oldCurrency') && + _.has(reportActionOriginalMessage, 'amount') && + _.has(reportActionOriginalMessage, 'currency') ) { const oldCurrency = reportActionOriginalMessage.oldCurrency; const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); @@ -1330,17 +1331,23 @@ function getModifiedExpenseMessage(reportAction) { return `changed the request to ${amount} (previously ${oldAmount})`; } - if (reportActionOriginalMessage.oldComment && - reportActionOriginalMessage.newComment + if (_.has(reportActionOriginalMessage, 'oldComment') && + _.has(reportActionOriginalMessage, 'newComment') ) { - return `changed the request description to ${reportActionOriginalMessage.newComment} (previously ${reportActionOriginalMessage.oldComment})`; + return `changed the request description to "${reportActionOriginalMessage.newComment}" (previously "${reportActionOriginalMessage.oldComment}")`; } - if (reportActionOriginalMessage.oldCreated && - reportActionOriginalMessage.created + if (_.has(reportActionOriginalMessage, 'oldCreated') && + _.has(reportActionOriginalMessage, 'created') ) { return `changed the request date to ${reportActionOriginalMessage.created} (previously ${reportActionOriginalMessage.oldCreated})`; } + + if (_.has(reportActionOriginalMessage, 'oldMerchant') && + _.has(reportActionOriginalMessage, 'merchant') + ) { + return `changed the request merchant to "${reportActionOriginalMessage.merchant}" (previously "${reportActionOriginalMessage.oldMerchant}")`; + } } return `changed the request`; } diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 52aae4852dd0..78a4ab65c46d 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -1,5 +1,6 @@ import Onyx from 'react-native-onyx'; import lodashGet from 'lodash/get'; +import _ from 'underscore'; import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; import DateUtils from './DateUtils'; @@ -66,7 +67,8 @@ function buildOptimisticTransaction(amount, currency, reportID, comment = '', so * @returns {Object} */ function getUpdatedTransaction(transaction, transactionChanges) { - const updatedTransaction = {...transaction}; + // Only changing the first level fields so no need for deep clone now + const updatedTransaction = _.clone(transaction); // The comment property does not have its modifiedComment counterpart if (_.has(transactionChanges, 'comment')) { diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index cbd89dbc1e5a..2e968ea26d6c 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -795,16 +795,17 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou * @param {Object} transactionChanges */ function editMoneyRequest(transactionID, transactionThreadReportID, transactionChanges) { + console.log("transactionID: ", transactionID); + console.log("transactionThreadReportID: ", transactionThreadReportID); // STEP 1: Get all collections we're updating const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.parentReportID}`]; - + debugger; // STEP 2: Build new modified expense report action. const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges); const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges); // STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct - // STEP 4: Compose the optimistic data const optimisticData = [ { @@ -817,7 +818,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, - value: {updatedTransaction}, + value: updatedTransaction, }, ]; @@ -847,16 +848,12 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, - value: { - transaction, - }, + value: transaction, }, { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.report}`, - value: { - iouReport, - }, + value: iouReport, }, ]; diff --git a/src/pages/EditRequestCreatedPage.js b/src/pages/EditRequestCreatedPage.js index e96fc84b2330..f7c2d68054f9 100644 --- a/src/pages/EditRequestCreatedPage.js +++ b/src/pages/EditRequestCreatedPage.js @@ -1,4 +1,4 @@ -import React, {useRef} from 'react'; +import React, {useCallback} from 'react'; import PropTypes from 'prop-types'; import ScreenWrapper from '../components/ScreenWrapper'; import HeaderWithBackButton from '../components/HeaderWithBackButton'; @@ -54,7 +54,7 @@ function EditRequestCreatedPage({defaultCreated, onSubmit}) { enabledWhenOffline > diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index bdde4367b94e..9c56947c9236 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -4,7 +4,6 @@ import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; import CONST from '../CONST'; import Navigation from '../libs/Navigation/Navigation'; -import compose from '../libs/compose'; import ONYXKEYS from '../ONYXKEYS'; import * as ReportActionsUtils from '../libs/ReportActionsUtils'; import * as TransactionUtils from '../libs/TransactionUtils'; @@ -37,20 +36,19 @@ const defaultProps = { function EditRequestPage({report, route}) { const parentReportAction = ReportActionsUtils.getParentReportAction(report); - const transactionID = ReportActionsUtils.getLinkedTransactionID(ReportUtils.getParentReport(report), parentReportAction); + const transactionID = lodashGet(parentReportAction, 'originalMessage.IOUTransactionID', ''); const transaction = TransactionUtils.getTransaction(transactionID); const transactionDescription = TransactionUtils.getDescription(transaction); - const transactionAmount = TransactionUtils.getAmount(transaction); - const transactionCurrency = TransactionUtils.getCurrency(transaction); + // const transactionAmount = TransactionUtils.getAmount(transaction); + // const transactionCurrency = TransactionUtils.getCurrency(transaction); const transactionCreated = TransactionUtils.getCreated(transaction); const field = lodashGet(route, ['params', 'field'], ''); - - function updateTransactionWithChanges(changes) { + function editTransaction(transactionChanges) { // Update the transaction... // eslint-disable-next-line no-console - console.log({changes}); + console.log({transactionChanges}); - IOU.editMoneyRequest(transactionID, report.reportID, changes); + IOU.editMoneyRequest(transactionID, report.reportID, transactionChanges); // Note: The "modal" we are dismissing is the MoneyRequestAmountPage Navigation.dismissModal(); @@ -61,20 +59,24 @@ function EditRequestPage({report, route}) { { - updateTransactionWithChanges(changes); + editTransaction(changes); }} /> ); - } else if (field === CONST.EDIT_REQUEST_FIELD.DATE) { + } + + if (field === CONST.EDIT_REQUEST_FIELD.DATE) { return ( { - updateTransactionWithChanges(changes); + editTransaction(changes); }} /> ); - } else if (field === CONST.EDIT_REQUEST_FIELD.AMOUNT) { + } + + if (field === CONST.EDIT_REQUEST_FIELD.AMOUNT) { return null; } @@ -84,10 +86,8 @@ function EditRequestPage({report, route}) { EditRequestPage.displayName = 'EditRequestPage'; EditRequestPage.propTypes = propTypes; EditRequestPage.defaultProps = defaultProps; -export default compose( - withOnyx({ - report: { - key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.threadReportID}`, - }, - }), -)(EditRequestPage); +export default withOnyx({ + report: { + key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.threadReportID}`, + }, +})(EditRequestPage); From 437dbdc2b2d594e1e95006556b61263fc3c6ffa6 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Wed, 9 Aug 2023 17:15:01 +0100 Subject: [PATCH 30/45] Enable amount editting --- src/CONST.js | 1 + src/components/CurrencySymbolButton.js | 21 ++++-- src/components/TextInputWithCurrencySymbol.js | 5 ++ src/libs/ReportUtils.js | 3 +- src/libs/actions/IOU.js | 2 +- src/pages/EditRequestAmountPage.js | 70 +++++++++++++++++++ src/pages/EditRequestCreatedPage.js | 2 +- src/pages/EditRequestDescriptionPage.js | 2 +- src/pages/EditRequestPage.js | 29 +++++--- src/pages/iou/IOUCurrencySelection.js | 1 + src/pages/iou/steps/MoneyRequestAmountForm.js | 8 ++- 11 files changed, 124 insertions(+), 20 deletions(-) create mode 100644 src/pages/EditRequestAmountPage.js diff --git a/src/CONST.js b/src/CONST.js index a40ce5adca9e..9e0d5bf13a96 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -1314,6 +1314,7 @@ const CONST = { }, EDIT_REQUEST_FIELD: { AMOUNT: 'amount', + CURRENCY: 'currency', DATE: 'date', DESCRIPTION: 'description', MERCHANT: 'merchant', diff --git a/src/components/CurrencySymbolButton.js b/src/components/CurrencySymbolButton.js index 0c19ce0f63b3..167f1da0083c 100644 --- a/src/components/CurrencySymbolButton.js +++ b/src/components/CurrencySymbolButton.js @@ -6,6 +6,7 @@ import Tooltip from './Tooltip'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback'; import CONST from '../CONST'; +import useLocalize from '../hooks/useLocalize'; const propTypes = { /** Currency symbol of selected currency */ @@ -14,18 +15,27 @@ const propTypes = { /** Function to call when currency button is pressed */ onCurrencyButtonPress: PropTypes.func.isRequired, + /** Flag to indicate if the button should be disabled */ + disabled: PropTypes.bool, + ...withLocalizePropTypes, }; -function CurrencySymbolButton(props) { +const defaultProps = { + disabled: false, +}; + +function CurrencySymbolButton({onCurrencyButtonPress, currencySymbol, disabled}) { + const {translate} = useLocalize(); return ( - + - {props.currencySymbol} + {currencySymbol} ); @@ -33,5 +43,6 @@ function CurrencySymbolButton(props) { CurrencySymbolButton.propTypes = propTypes; CurrencySymbolButton.displayName = 'CurrencySymbolButton'; +CurrencySymbolButton.defaultProps = defaultProps; export default withLocalize(CurrencySymbolButton); diff --git a/src/components/TextInputWithCurrencySymbol.js b/src/components/TextInputWithCurrencySymbol.js index f6f2014b50b3..87215f4fe3bf 100644 --- a/src/components/TextInputWithCurrencySymbol.js +++ b/src/components/TextInputWithCurrencySymbol.js @@ -31,6 +31,9 @@ const propTypes = { /** Function to call when selection in text input is changed */ onSelectionChange: PropTypes.func, + + /** Flag to indicate if the button should be disabled */ + disabled: PropTypes.bool, }; const defaultProps = { @@ -39,6 +42,7 @@ const defaultProps = { onCurrencyButtonPress: () => {}, selection: undefined, onSelectionChange: () => {}, + disabled: false, }; function TextInputWithCurrencySymbol(props) { @@ -49,6 +53,7 @@ function TextInputWithCurrencySymbol(props) { ); diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index d19170f18513..4529df63de99 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1313,7 +1313,6 @@ function getReportPreviewMessage(report, reportAction = {}) { */ function getModifiedExpenseMessage(reportAction) { const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', {}); - console.log('reportActionOriginalMessage: ', reportActionOriginalMessage); if (!_.isEmpty(reportActionOriginalMessage)) { if (_.has(reportActionOriginalMessage, 'oldAmount') && _.has(reportActionOriginalMessage, 'oldCurrency') && @@ -1322,7 +1321,7 @@ function getModifiedExpenseMessage(reportAction) { ) { const oldCurrency = reportActionOriginalMessage.oldCurrency; const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); - const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', oldCurrency}); + const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', currency: oldCurrency}); const currency = reportActionOriginalMessage.currency; const currencyUnit = CurrencyUtils.getCurrencyUnit(currency); diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 2e968ea26d6c..e18392bae792 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -801,7 +801,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.parentReportID}`]; - debugger; + // STEP 2: Build new modified expense report action. const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges); const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges); diff --git a/src/pages/EditRequestAmountPage.js b/src/pages/EditRequestAmountPage.js new file mode 100644 index 000000000000..15f17504ec04 --- /dev/null +++ b/src/pages/EditRequestAmountPage.js @@ -0,0 +1,70 @@ +import React, {useCallback, useRef} from 'react'; +import {InteractionManager} from 'react-native'; +import {useFocusEffect} from '@react-navigation/native'; +import PropTypes from 'prop-types'; +import ScreenWrapper from '../components/ScreenWrapper'; +import HeaderWithBackButton from '../components/HeaderWithBackButton'; +import Navigation from '../libs/Navigation/Navigation'; +import useLocalize from '../hooks/useLocalize'; +import MoneyRequestAmountForm from './iou/steps/MoneyRequestAmountForm'; + +const propTypes = { + /** Transaction default amount value */ + defaultAmount: PropTypes.string.isRequired, + + /** Transaction default currency value */ + defaultCurrency: PropTypes.string.isRequired, + + /** Callback to fire when the Save button is pressed */ + onSubmit: PropTypes.func.isRequired, +}; + +function EditRequestAmountPage({defaultAmount, defaultCurrency, onSubmit}) { + const {translate} = useLocalize(); + const textInput = useRef(null); + + const focusTextInput = () => { + // Component may not be initialized due to navigation transitions + // Wait until interactions are complete before trying to focus + InteractionManager.runAfterInteractions(() => { + // Focus text input + if (!textInput.current) { + return; + } + + textInput.current.focus(); + }); + }; + + useFocusEffect( + useCallback(() => { + focusTextInput(); + }, []), + ); + + return ( + + Navigation.goBack()} + /> + (textInput.current = e)} + onCurrencyButtonPress={() => null} + onSubmitButtonPress={onSubmit} + /> + + ); +} + +EditRequestAmountPage.propTypes = propTypes; +EditRequestAmountPage.displayName = 'EditRequestAmountPage'; + +export default EditRequestAmountPage; diff --git a/src/pages/EditRequestCreatedPage.js b/src/pages/EditRequestCreatedPage.js index f7c2d68054f9..be7a7f3533b3 100644 --- a/src/pages/EditRequestCreatedPage.js +++ b/src/pages/EditRequestCreatedPage.js @@ -11,7 +11,7 @@ import NewDatePicker from '../components/NewDatePicker'; import * as ValidationUtils from '../libs/ValidationUtils'; const propTypes = { - /** Transaction created default value */ + /** Transaction defailt created value */ defaultCreated: PropTypes.string.isRequired, /** Callback to fire when the Save button is pressed */ diff --git a/src/pages/EditRequestDescriptionPage.js b/src/pages/EditRequestDescriptionPage.js index 57d4e3c7c387..eb909e8cc9b4 100644 --- a/src/pages/EditRequestDescriptionPage.js +++ b/src/pages/EditRequestDescriptionPage.js @@ -12,7 +12,7 @@ import CONST from '../CONST'; import useLocalize from '../hooks/useLocalize'; const propTypes = { - /** Transaction description default value */ + /** Transaction default description value */ defaultDescription: PropTypes.string.isRequired, /** Callback to fire when the Save button is pressed */ diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 9c56947c9236..e05aa47e443a 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -9,9 +9,10 @@ import * as ReportActionsUtils from '../libs/ReportActionsUtils'; import * as TransactionUtils from '../libs/TransactionUtils'; import EditRequestDescriptionPage from './EditRequestDescriptionPage'; import EditRequestCreatedPage from './EditRequestCreatedPage'; +import EditRequestAmountPage from './EditRequestAmountPage'; import reportPropTypes from './reportPropTypes'; -import * as ReportUtils from '../libs/ReportUtils'; import * as IOU from '../libs/actions/IOU'; +import * as CurrencyUtils from '../libs/CurrencyUtils'; const propTypes = { /** Route from navigation */ @@ -39,8 +40,8 @@ function EditRequestPage({report, route}) { const transactionID = lodashGet(parentReportAction, 'originalMessage.IOUTransactionID', ''); const transaction = TransactionUtils.getTransaction(transactionID); const transactionDescription = TransactionUtils.getDescription(transaction); - // const transactionAmount = TransactionUtils.getAmount(transaction); - // const transactionCurrency = TransactionUtils.getCurrency(transaction); + const transactionAmount = TransactionUtils.getAmount(transaction); + const transactionCurrency = TransactionUtils.getCurrency(transaction); const transactionCreated = TransactionUtils.getCreated(transaction); const field = lodashGet(route, ['params', 'field'], ''); function editTransaction(transactionChanges) { @@ -58,8 +59,8 @@ function EditRequestPage({report, route}) { return ( { - editTransaction(changes); + onSubmit={(transactionChanges) => { + editTransaction(transactionChanges); }} /> ); @@ -69,15 +70,27 @@ function EditRequestPage({report, route}) { return ( { - editTransaction(changes); + onSubmit={(transactionChanges) => { + editTransaction(transactionChanges); }} /> ); } if (field === CONST.EDIT_REQUEST_FIELD.AMOUNT) { - return null; + return ( + { + editTransaction({ + 'amount': CurrencyUtils.convertToSmallestUnit(transactionCurrency, Number.parseFloat(transactionChanges)), + 'currency': transactionCurrency, + }); + }} + /> + ); } return null; diff --git a/src/pages/iou/IOUCurrencySelection.js b/src/pages/iou/IOUCurrencySelection.js index 44a7fba5d487..90bd883bffed 100644 --- a/src/pages/iou/IOUCurrencySelection.js +++ b/src/pages/iou/IOUCurrencySelection.js @@ -86,6 +86,7 @@ function IOUCurrencySelection(props) { // When we refresh the web, the money request route gets cleared from the navigation stack. // Navigating to "backTo" will result in forward navigation instead, causing disruption to the currency selection. // To prevent any negative experience, we have made the decision to simply close the currency selection page. + console.log("props.navigation.getState().routes: ", props.navigation.getState().routes); if (_.isEmpty(backTo) || props.navigation.getState().routes.length === 1) { Navigation.goBack(); } else { diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js index 7178ed0e0158..ed6066972119 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.js +++ b/src/pages/iou/steps/MoneyRequestAmountForm.js @@ -31,6 +31,9 @@ const propTypes = { /** Fired when submit button pressed, saves the given amount and navigates to the next page */ onSubmitButtonPress: PropTypes.func.isRequired, + + /** Flag to indicate if the button should be disabled */ + disableCurrency: PropTypes.bool, }; const defaultProps = { @@ -38,6 +41,7 @@ const defaultProps = { currency: CONST.CURRENCY.USD, forwardedRef: null, isEditing: false, + disableCurrency: false, }; /** @@ -57,7 +61,7 @@ const AMOUNT_VIEW_ID = 'amountView'; const NUM_PAD_CONTAINER_VIEW_ID = 'numPadContainerView'; const NUM_PAD_VIEW_ID = 'numPadView'; -function MoneyRequestAmountForm({amount, currency, isEditing, forwardedRef, onCurrencyButtonPress, onSubmitButtonPress}) { +function MoneyRequestAmountForm({amount, currency, isEditing, forwardedRef, onCurrencyButtonPress, onSubmitButtonPress, disableCurrency}) { const {translate, toLocaleDigit, fromLocaleDigit, numberFormat} = useLocalize(); const textInput = useRef(null); @@ -188,7 +192,6 @@ function MoneyRequestAmountForm({amount, currency, isEditing, forwardedRef, onCu /** * Submit amount and navigate to a proper page - * */ const submitAndNavigateToNextPage = useCallback(() => { onSubmitButtonPress(currentAmount); @@ -226,6 +229,7 @@ function MoneyRequestAmountForm({amount, currency, isEditing, forwardedRef, onCu } setSelection(e.nativeEvent.selection); }} + disabled={disableCurrency} />
Date: Wed, 9 Aug 2023 17:20:34 +0100 Subject: [PATCH 31/45] Clean up --- src/libs/ReportUtils.js | 17 ++++++----------- src/libs/actions/IOU.js | 2 -- src/pages/EditRequestPage.js | 21 +++++++++------------ src/pages/home/report/ReportActionItem.js | 4 +--- src/pages/iou/IOUCurrencySelection.js | 1 - 5 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 4529df63de99..90d99949b94d 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1314,7 +1314,8 @@ function getReportPreviewMessage(report, reportAction = {}) { function getModifiedExpenseMessage(reportAction) { const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', {}); if (!_.isEmpty(reportActionOriginalMessage)) { - if (_.has(reportActionOriginalMessage, 'oldAmount') && + if ( + _.has(reportActionOriginalMessage, 'oldAmount') && _.has(reportActionOriginalMessage, 'oldCurrency') && _.has(reportActionOriginalMessage, 'amount') && _.has(reportActionOriginalMessage, 'currency') @@ -1330,21 +1331,15 @@ function getModifiedExpenseMessage(reportAction) { return `changed the request to ${amount} (previously ${oldAmount})`; } - if (_.has(reportActionOriginalMessage, 'oldComment') && - _.has(reportActionOriginalMessage, 'newComment') - ) { + if (_.has(reportActionOriginalMessage, 'oldComment') && _.has(reportActionOriginalMessage, 'newComment')) { return `changed the request description to "${reportActionOriginalMessage.newComment}" (previously "${reportActionOriginalMessage.oldComment}")`; } - if (_.has(reportActionOriginalMessage, 'oldCreated') && - _.has(reportActionOriginalMessage, 'created') - ) { + if (_.has(reportActionOriginalMessage, 'oldCreated') && _.has(reportActionOriginalMessage, 'created')) { return `changed the request date to ${reportActionOriginalMessage.created} (previously ${reportActionOriginalMessage.oldCreated})`; } - if (_.has(reportActionOriginalMessage, 'oldMerchant') && - _.has(reportActionOriginalMessage, 'merchant') - ) { + if (_.has(reportActionOriginalMessage, 'oldMerchant') && _.has(reportActionOriginalMessage, 'merchant')) { return `changed the request merchant to "${reportActionOriginalMessage.merchant}" (previously "${reportActionOriginalMessage.oldMerchant}")`; } } @@ -1381,7 +1376,7 @@ function getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges) { originalMessage.oldAmount = TransactionUtils.getAmount(oldTransaction); originalMessage.amount = lodashGet(transactionChanges, 'amount', originalMessage.oldAmount); originalMessage.oldCurrency = TransactionUtils.getCurrency(oldTransaction); - originalMessage.currency = lodashGet(transactionChanges, 'currency', originalMessage.oldCurrency);; + originalMessage.currency = lodashGet(transactionChanges, 'currency', originalMessage.oldCurrency); } return originalMessage; diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index e18392bae792..6ffe05e9673d 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -795,8 +795,6 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou * @param {Object} transactionChanges */ function editMoneyRequest(transactionID, transactionThreadReportID, transactionChanges) { - console.log("transactionID: ", transactionID); - console.log("transactionThreadReportID: ", transactionThreadReportID); // STEP 1: Get all collections we're updating const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index e05aa47e443a..adb4f8d69c68 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -43,19 +43,15 @@ function EditRequestPage({report, route}) { const transactionAmount = TransactionUtils.getAmount(transaction); const transactionCurrency = TransactionUtils.getCurrency(transaction); const transactionCreated = TransactionUtils.getCreated(transaction); - const field = lodashGet(route, ['params', 'field'], ''); - function editTransaction(transactionChanges) { - // Update the transaction... - // eslint-disable-next-line no-console - console.log({transactionChanges}); + const fieldToEdit = lodashGet(route, ['params', 'field'], ''); + // Update the transaction object and close the modal + function editTransaction(transactionChanges) { IOU.editMoneyRequest(transactionID, report.reportID, transactionChanges); - - // Note: The "modal" we are dismissing is the MoneyRequestAmountPage Navigation.dismissModal(); } - if (field === CONST.EDIT_REQUEST_FIELD.DESCRIPTION) { + if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.DESCRIPTION) { return ( { + // Temporarily disabling currency editing and it will be enabled as a quick follow up editTransaction({ - 'amount': CurrencyUtils.convertToSmallestUnit(transactionCurrency, Number.parseFloat(transactionChanges)), - 'currency': transactionCurrency, + amount: CurrencyUtils.convertToSmallestUnit(transactionCurrency, Number.parseFloat(transactionChanges)), + currency: transactionCurrency, }); }} /> diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 5ef13df55140..d316602f6154 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -316,9 +316,7 @@ function ReportActionItem(props) { ); } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE) { - children = ( - - ); + children = ; } else { const message = _.last(lodashGet(props.action, 'message', [{}])); const hasBeenFlagged = !_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], moderationDecision); diff --git a/src/pages/iou/IOUCurrencySelection.js b/src/pages/iou/IOUCurrencySelection.js index 90bd883bffed..44a7fba5d487 100644 --- a/src/pages/iou/IOUCurrencySelection.js +++ b/src/pages/iou/IOUCurrencySelection.js @@ -86,7 +86,6 @@ function IOUCurrencySelection(props) { // When we refresh the web, the money request route gets cleared from the navigation stack. // Navigating to "backTo" will result in forward navigation instead, causing disruption to the currency selection. // To prevent any negative experience, we have made the decision to simply close the currency selection page. - console.log("props.navigation.getState().routes: ", props.navigation.getState().routes); if (_.isEmpty(backTo) || props.navigation.getState().routes.length === 1) { Navigation.goBack(); } else { From 22f4aee469e2277a43dc5e90854e043e6608ae99 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Wed, 9 Aug 2023 17:49:59 +0100 Subject: [PATCH 32/45] PR review feedback --- src/components/CurrencySymbolButton.js | 5 +-- src/libs/ReportUtils.js | 55 ++++++++++++++------------ src/libs/TransactionUtils.js | 8 ++-- src/pages/EditRequestCreatedPage.js | 20 +--------- src/pages/EditRequestPage.js | 11 +++--- 5 files changed, 41 insertions(+), 58 deletions(-) diff --git a/src/components/CurrencySymbolButton.js b/src/components/CurrencySymbolButton.js index 167f1da0083c..bd94e5334e9b 100644 --- a/src/components/CurrencySymbolButton.js +++ b/src/components/CurrencySymbolButton.js @@ -3,7 +3,6 @@ import PropTypes from 'prop-types'; import Text from './Text'; import styles from '../styles/styles'; import Tooltip from './Tooltip'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback'; import CONST from '../CONST'; import useLocalize from '../hooks/useLocalize'; @@ -17,8 +16,6 @@ const propTypes = { /** Flag to indicate if the button should be disabled */ disabled: PropTypes.bool, - - ...withLocalizePropTypes, }; const defaultProps = { @@ -45,4 +42,4 @@ CurrencySymbolButton.propTypes = propTypes; CurrencySymbolButton.displayName = 'CurrencySymbolButton'; CurrencySymbolButton.defaultProps = defaultProps; -export default withLocalize(CurrencySymbolButton); +export default CurrencySymbolButton; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 90d99949b94d..29385f8bb358 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1313,37 +1313,41 @@ function getReportPreviewMessage(report, reportAction = {}) { */ function getModifiedExpenseMessage(reportAction) { const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', {}); - if (!_.isEmpty(reportActionOriginalMessage)) { - if ( - _.has(reportActionOriginalMessage, 'oldAmount') && - _.has(reportActionOriginalMessage, 'oldCurrency') && - _.has(reportActionOriginalMessage, 'amount') && - _.has(reportActionOriginalMessage, 'currency') - ) { - const oldCurrency = reportActionOriginalMessage.oldCurrency; - const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); - const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', currency: oldCurrency}); + if (_.isEmpty(reportActionOriginalMessage)) { + return `changed the request`; + } - const currency = reportActionOriginalMessage.currency; - const currencyUnit = CurrencyUtils.getCurrencyUnit(currency); - const amount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.amount) / currencyUnit, {style: 'currency', currency}); + const hasModifiedAmount = + _.has(reportActionOriginalMessage, 'oldAmount') && + _.has(reportActionOriginalMessage, 'oldCurrency') && + _.has(reportActionOriginalMessage, 'amount') && + _.has(reportActionOriginalMessage, 'currency'); + if (hasModifiedAmount) { + const oldCurrency = reportActionOriginalMessage.oldCurrency; + const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); + const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', currency: oldCurrency}); - return `changed the request to ${amount} (previously ${oldAmount})`; - } + const currency = reportActionOriginalMessage.currency; + const currencyUnit = CurrencyUtils.getCurrencyUnit(currency); + const amount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.amount) / currencyUnit, {style: 'currency', currency}); - if (_.has(reportActionOriginalMessage, 'oldComment') && _.has(reportActionOriginalMessage, 'newComment')) { - return `changed the request description to "${reportActionOriginalMessage.newComment}" (previously "${reportActionOriginalMessage.oldComment}")`; - } + return `changed the request to ${amount} (previously ${oldAmount})`; + } - if (_.has(reportActionOriginalMessage, 'oldCreated') && _.has(reportActionOriginalMessage, 'created')) { - return `changed the request date to ${reportActionOriginalMessage.created} (previously ${reportActionOriginalMessage.oldCreated})`; - } + const hasModifiedComment = _.has(reportActionOriginalMessage, 'oldComment') && _.has(reportActionOriginalMessage, 'newComment'); + if (hasModifiedComment) { + return `changed the request description to "${reportActionOriginalMessage.newComment}" (previously "${reportActionOriginalMessage.oldComment}")`; + } - if (_.has(reportActionOriginalMessage, 'oldMerchant') && _.has(reportActionOriginalMessage, 'merchant')) { - return `changed the request merchant to "${reportActionOriginalMessage.merchant}" (previously "${reportActionOriginalMessage.oldMerchant}")`; - } + const hasModifiedCreated = _.has(reportActionOriginalMessage, 'oldCreated') && _.has(reportActionOriginalMessage, 'created'); + if (hasModifiedCreated) { + return `changed the request date to ${reportActionOriginalMessage.created} (previously ${reportActionOriginalMessage.oldCreated})`; + } + + const hasModifiedMerchant = _.has(reportActionOriginalMessage, 'oldMerchant') && _.has(reportActionOriginalMessage, 'merchant'); + if (hasModifiedMerchant) { + return `changed the request merchant to "${reportActionOriginalMessage.merchant}" (previously "${reportActionOriginalMessage.oldMerchant}")`; } - return `changed the request`; } /** @@ -1952,7 +1956,6 @@ function buildOptimisticReportPreview(chatReport, iouReport, comment = '') { * @param {Object} transactionThread * @param {Object} oldTransaction * @param {Object} transactionChanges - * * @returns {Object} */ function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransaction, transactionChanges) { diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 78a4ab65c46d..c5d2a3ca461f 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -102,7 +102,7 @@ function getTransaction(transactionID) { } /** - * Return the comment (in other words description) from the transaction object. + * Return the comment field (referred to as description in the App) from the transaction. * The comment does not have its modifiedComment counterpart. * * @param {Object} transaction @@ -113,7 +113,7 @@ function getDescription(transaction) { } /** - * Return the amount from the transaction, take the modifiedAmount if present. + * Return the amount field from the transaction, return the modifiedAmount if present. * * @param {Object} transaction * @returns {Number} @@ -127,7 +127,7 @@ function getAmount(transaction) { } /** - * Return the currency from the transaction, take the modifiedCurrency if present. + * Return the currency field from the transaction, return the modifiedCurrency if present. * * @param {Object} transaction * @returns {String} @@ -141,7 +141,7 @@ function getCurrency(transaction) { } /** - * Return the created from the transaction, take the modifiedCreated if present. + * Return the created field from the transaction, return the modifiedCreated if present. * * @param {Object} transaction * @returns {String} diff --git a/src/pages/EditRequestCreatedPage.js b/src/pages/EditRequestCreatedPage.js index be7a7f3533b3..ac7172d29ab8 100644 --- a/src/pages/EditRequestCreatedPage.js +++ b/src/pages/EditRequestCreatedPage.js @@ -1,4 +1,4 @@ -import React, {useCallback} from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import ScreenWrapper from '../components/ScreenWrapper'; import HeaderWithBackButton from '../components/HeaderWithBackButton'; @@ -8,7 +8,6 @@ import styles from '../styles/styles'; import Navigation from '../libs/Navigation/Navigation'; import useLocalize from '../hooks/useLocalize'; import NewDatePicker from '../components/NewDatePicker'; -import * as ValidationUtils from '../libs/ValidationUtils'; const propTypes = { /** Transaction defailt created value */ @@ -21,21 +20,6 @@ const propTypes = { function EditRequestCreatedPage({defaultCreated, onSubmit}) { const {translate} = useLocalize(); - /** - * @param {Object} values - * @param {String} values.dob - date of birth - * @returns {Object} - An object containing the errors for each inputID - */ - const validate = useCallback((values) => { - const errors = {}; - - if (!values.dob || !ValidationUtils.isValidDate(values.dob)) { - errors.dob = 'common.error.fieldRequired'; - } - - return errors; - }, []); - return ( { - editTransaction(transactionChanges); + editMoneyRequest(transactionChanges); }} /> ); @@ -67,7 +66,7 @@ function EditRequestPage({report, route}) { { - editTransaction(transactionChanges); + editMoneyRequest(transactionChanges); }} /> ); @@ -81,7 +80,7 @@ function EditRequestPage({report, route}) { reportID={report.reportID} onSubmit={(transactionChanges) => { // Temporarily disabling currency editing and it will be enabled as a quick follow up - editTransaction({ + editMoneyRequest({ amount: CurrencyUtils.convertToSmallestUnit(transactionCurrency, Number.parseFloat(transactionChanges)), currency: transactionCurrency, }); From 39a4ea1080618f80e14cc9c6e1d64564f0f74c5a Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Wed, 9 Aug 2023 18:05:34 +0100 Subject: [PATCH 33/45] Dont make API requests if transaction field hasnt been changed --- src/pages/EditRequestAmountPage.js | 2 +- src/pages/EditRequestPage.js | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/pages/EditRequestAmountPage.js b/src/pages/EditRequestAmountPage.js index 15f17504ec04..cb4817bbaaf3 100644 --- a/src/pages/EditRequestAmountPage.js +++ b/src/pages/EditRequestAmountPage.js @@ -10,7 +10,7 @@ import MoneyRequestAmountForm from './iou/steps/MoneyRequestAmountForm'; const propTypes = { /** Transaction default amount value */ - defaultAmount: PropTypes.string.isRequired, + defaultAmount: PropTypes.number.isRequired, /** Transaction default currency value */ defaultCurrency: PropTypes.string.isRequired, diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index f26f61753463..7c2379644125 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -1,4 +1,5 @@ import React from 'react'; +import _ from 'underscore'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; @@ -55,6 +56,11 @@ function EditRequestPage({report, route}) { { + // In case the comment hasn't been changed, do not make the API request. + if (transactionChanges.comment === transactionDescription) { + Navigation.dismissModal(); + return; + } editMoneyRequest(transactionChanges); }} /> @@ -66,6 +72,11 @@ function EditRequestPage({report, route}) { { + // In case the date hasn't been changed, do not make the API request. + if (transactionChanges.created === transactionCreated) { + Navigation.dismissModal(); + return; + } editMoneyRequest(transactionChanges); }} /> @@ -79,9 +90,15 @@ function EditRequestPage({report, route}) { defaultCurrency={transactionCurrency} reportID={report.reportID} onSubmit={(transactionChanges) => { + const amount = CurrencyUtils.convertToSmallestUnit(transactionCurrency, Number.parseFloat(transactionChanges)); + // In case the amount hasn't been changed, do not make the API request. + if (amount === transactionAmount) { + Navigation.dismissModal(); + return; + } // Temporarily disabling currency editing and it will be enabled as a quick follow up editMoneyRequest({ - amount: CurrencyUtils.convertToSmallestUnit(transactionCurrency, Number.parseFloat(transactionChanges)), + amount, currency: transactionCurrency, }); }} From f03580f0774ae33e67967f95b594b609747bf25d Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Wed, 9 Aug 2023 18:32:30 +0100 Subject: [PATCH 34/45] Fix linter --- src/pages/EditRequestPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 7c2379644125..1f4ef90e32fa 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -1,5 +1,4 @@ import React from 'react'; -import _ from 'underscore'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; From 9c60897c833181162a1326493b18a2224c529662 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 10 Aug 2023 10:45:56 +0100 Subject: [PATCH 35/45] Fix the logic of who can edit --- .../ReportActionItem/MoneyRequestView.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index f41c7e3ed157..598fe8d096d9 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -72,8 +72,9 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic const moneyRequestReport = parentReport; const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); - const isPayer = Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID); - const canEdit = !isSettled && (ReportUtils.isExpenseReport(moneyRequestReport) || (ReportUtils.isIOUReport(moneyRequestReport) && !isPayer)); + const isAdmin = Policy.isAdminOfFreePolicy([policy]) && ReportUtils.isExpenseReport(moneyRequestReport); + const isRequestor = ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === parentReportAction.actorAccountID; + const canEdit = !isSettled && (isAdmin || isRequestor); let description = `${translate('iou.amount')} • ${translate('iou.cash')}`; if (isSettled) { @@ -97,22 +98,22 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic titleIcon={Expensicons.Checkmark} description={description} titleStyle={styles.newKansasLarge} - disabled={isSettled} - shouldShowRightIcon={!canEdit} + disabled={isSettled || !canEdit} + shouldShowRightIcon={canEdit} onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} /> Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} /> Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} /> {shouldShowHorizontalRule && } From d3db0b8b7bf85dc63174898ad299e5057c2774c8 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 10 Aug 2023 11:03:17 +0100 Subject: [PATCH 36/45] Trim the desccription --- src/pages/EditRequestPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 1f4ef90e32fa..a30350a68ac2 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -56,11 +56,11 @@ function EditRequestPage({report, route}) { defaultDescription={transactionDescription} onSubmit={(transactionChanges) => { // In case the comment hasn't been changed, do not make the API request. - if (transactionChanges.comment === transactionDescription) { + if (transactionChanges.comment.trim() === transactionDescription) { Navigation.dismissModal(); return; } - editMoneyRequest(transactionChanges); + editMoneyRequest({comment: transactionChanges.comment.trim()}); }} /> ); From 607729277b541439df39073a1f84fb2d02a8c41a Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 10 Aug 2023 11:16:51 +0100 Subject: [PATCH 37/45] Use the short date for the form if edit money request --- src/pages/EditRequestPage.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index a30350a68ac2..6c5a5677c505 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; +import {format} from 'date-fns'; import CONST from '../CONST'; import Navigation from '../libs/Navigation/Navigation'; import ONYXKEYS from '../ONYXKEYS'; @@ -41,7 +42,10 @@ function EditRequestPage({report, route}) { const transactionDescription = TransactionUtils.getDescription(transaction); const transactionAmount = TransactionUtils.getAmount(transaction); const transactionCurrency = TransactionUtils.getCurrency(transaction); - const transactionCreated = TransactionUtils.getCreated(transaction); + + // Take only the YYYY-MM-DD value + const transactionCreatedDate = new Date(TransactionUtils.getCreated(transaction)); + const transactionCreated = format(transactionCreatedDate, CONST.DATE.FNS_FORMAT_STRING); const fieldToEdit = lodashGet(route, ['params', 'field'], ''); // Update the transaction object and close the modal From 7361e14497064e4b32b9b2d0d78689d93b9fed69 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 10 Aug 2023 11:35:15 +0100 Subject: [PATCH 38/45] Fix the timestamp in message --- src/libs/ReportUtils.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index c1bf1b544bc9..807a2976e5fe 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1,4 +1,5 @@ import _ from 'underscore'; +import {format} from 'date-fns'; import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import lodashIntersection from 'lodash/intersection'; @@ -1341,7 +1342,10 @@ function getModifiedExpenseMessage(reportAction) { const hasModifiedCreated = _.has(reportActionOriginalMessage, 'oldCreated') && _.has(reportActionOriginalMessage, 'created'); if (hasModifiedCreated) { - return `changed the request date to ${reportActionOriginalMessage.created} (previously ${reportActionOriginalMessage.oldCreated})`; + // Take only the YYYY-MM-DD value as the original date includes timestamp + let formattedOldCreated = new Date(reportActionOriginalMessage.oldCreated); + formattedOldCreated = format(formattedOldCreated, CONST.DATE.FNS_FORMAT_STRING); + return `changed the request date to ${reportActionOriginalMessage.created} (previously ${formattedOldCreated})`; } const hasModifiedMerchant = _.has(reportActionOriginalMessage, 'oldMerchant') && _.has(reportActionOriginalMessage, 'merchant'); From e3af9acea9fed64a13cbd5f05d14362c790e4ece Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 11 Aug 2023 09:33:54 +0100 Subject: [PATCH 39/45] Update how we get the currency value --- src/languages/es.js | 2 +- src/libs/ReportUtils.js | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/languages/es.js b/src/languages/es.js index 836064827713..3aed5acd1e5d 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -410,7 +410,7 @@ export default { other: 'Error inesperado, por favor inténtalo más tarde', genericCreateFailureMessage: 'Error inesperado solicitando dinero, Por favor, inténtalo más tarde', genericDeleteFailureMessage: 'Error inesperado eliminando la solicitud de dinero. Por favor, inténtalo más tarde', - genericEditFailureMessage: 'Unexpected error editing the money request, please try again later', + genericEditFailureMessage: 'Error inesperado al guardar la solicitud de dinero. Por favor, inténtalo más tarde', }, }, notificationPreferencesPage: { diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 807a2976e5fe..8de8ac76c659 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1325,12 +1325,10 @@ function getModifiedExpenseMessage(reportAction) { _.has(reportActionOriginalMessage, 'currency'); if (hasModifiedAmount) { const oldCurrency = reportActionOriginalMessage.oldCurrency; - const oldCurrencyUnit = CurrencyUtils.getCurrencyUnit(oldCurrency); - const oldAmount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.oldAmount) / oldCurrencyUnit, {style: 'currency', currency: oldCurrency}); + const oldAmount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage.oldAmount, oldCurrency); const currency = reportActionOriginalMessage.currency; - const currencyUnit = CurrencyUtils.getCurrencyUnit(currency); - const amount = NumberFormatUtils.format(preferredLocale, Math.abs(reportActionOriginalMessage.amount) / currencyUnit, {style: 'currency', currency}); + const amount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage.amount, currency); return `changed the request to ${amount} (previously ${oldAmount})`; } @@ -1358,7 +1356,7 @@ function getModifiedExpenseMessage(reportAction) { * Given the updates user made to the request, compose the originalMessage * object of the modified expense action. * - * At the moment, we only allow changing one transaction field at the time. + * At the moment, we only allow changing one transaction field at a time. * * @param {Object} oldTransaction * @param {Object} transactionChanges From 406c38e170fd7c71beebdb428b2c15c79e420c8b Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 11 Aug 2023 10:03:59 +0100 Subject: [PATCH 40/45] Fix the negative amount for expense reports --- src/libs/ReportUtils.js | 14 +++++++++----- src/libs/TransactionUtils.js | 30 ++++++++++++++++-------------- src/libs/actions/IOU.js | 7 ++++--- src/pages/EditRequestPage.js | 3 ++- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 8de8ac76c659..d23eb360c9af 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1360,9 +1360,10 @@ function getModifiedExpenseMessage(reportAction) { * * @param {Object} oldTransaction * @param {Object} transactionChanges + * @param {Boolen} isFromExpenseReport * @returns {Object} */ -function getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges) { +function getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges, isFromExpenseReport) { const originalMessage = {}; // Remark: Comment field is the only one which has new/old prefixes for the keys (newComment/ oldComment), @@ -1379,7 +1380,7 @@ function getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges) { // The amount is always a combination of the currency and the number value so when one changes we need to store both // to match how we handle the modified expense action in oldDot if (_.has(transactionChanges, 'amount') || _.has(transactionChanges, 'currency')) { - originalMessage.oldAmount = TransactionUtils.getAmount(oldTransaction); + originalMessage.oldAmount = TransactionUtils.getAmount(oldTransaction, isFromExpenseReport); originalMessage.amount = lodashGet(transactionChanges, 'amount', originalMessage.oldAmount); originalMessage.oldCurrency = TransactionUtils.getCurrency(oldTransaction); originalMessage.currency = lodashGet(transactionChanges, 'currency', originalMessage.oldCurrency); @@ -1866,9 +1867,10 @@ function getIOUReportActionMessage(type, total, comment, currency, paymentType = * @param {String} [iouReportID] - Only required if the IOUReportActions type is oneOf(decline, cancel, pay). Generates a randomID as default. * @param {Boolean} [isSettlingUp] - Whether we are settling up an IOU. * @param {Boolean} [isSendMoneyFlow] - Whether this is send money flow + * @param {Object} [receipt] * @returns {Object} */ -function buildOptimisticIOUReportAction(type, amount, currency, comment, participants, transactionID, paymentType = '', iouReportID = '', isSettlingUp = false, isSendMoneyFlow = false) { +function buildOptimisticIOUReportAction(type, amount, currency, comment, participants, transactionID, paymentType = '', iouReportID = '', isSettlingUp = false, isSendMoneyFlow = false, receipt = {}) { const IOUReportID = iouReportID || generateReportID(); const originalMessage = { @@ -1914,6 +1916,7 @@ function buildOptimisticIOUReportAction(type, amount, currency, comment, partici shouldShow: true, created: DateUtils.getDBTime(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + receipt, }; } @@ -1958,10 +1961,11 @@ function buildOptimisticReportPreview(chatReport, iouReport, comment = '') { * @param {Object} transactionThread * @param {Object} oldTransaction * @param {Object} transactionChanges + * @param {Object} isFromExpenseReport * @returns {Object} */ -function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransaction, transactionChanges) { - const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges); +function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransaction, transactionChanges, isFromExpenseReport) { + const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges, isFromExpenseReport); return { actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE, actorAccountID: currentUserAccountID, diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index c5d2a3ca461f..92b83e7b8735 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -5,18 +5,16 @@ import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; import DateUtils from './DateUtils'; import * as NumberUtils from './NumberUtils'; -import * as CollectionUtils from './CollectionUtils'; -const allTransactions = {}; +let allTransactions = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.TRANSACTION, - callback: (transaction, key) => { - if (!key || !transaction) { + waitForCollectionCallback: true, + callback: (val) => { + if (!val) { return; } - - const transactionID = CollectionUtils.extractCollectionItemID(key); - allTransactions[transactionID] = transaction; + allTransactions = val; }, }); @@ -64,9 +62,10 @@ function buildOptimisticTransaction(amount, currency, reportID, comment = '', so * * @param {Object} transaction * @param {Object} transactionChanges + * @param {Object} isFromExpenseReport * @returns {Object} */ -function getUpdatedTransaction(transaction, transactionChanges) { +function getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) { // Only changing the first level fields so no need for deep clone now const updatedTransaction = _.clone(transaction); @@ -81,7 +80,7 @@ function getUpdatedTransaction(transaction, transactionChanges) { updatedTransaction.modifiedCreated = transactionChanges.created; } if (_.has(transactionChanges, 'amount')) { - updatedTransaction.modifiedAmount = transactionChanges.amount; + updatedTransaction.modifiedAmount = isFromExpenseReport ? -transactionChanges.amount : transactionChanges.amount; } if (_.has(transactionChanges, 'currency')) { updatedTransaction.modifiedCurrency = transactionChanges.currency; @@ -98,7 +97,7 @@ function getUpdatedTransaction(transaction, transactionChanges) { * @returns {Object} */ function getTransaction(transactionID) { - return lodashGet(allTransactions, [transactionID], {}); + return lodashGet(allTransactions, `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {}); } /** @@ -115,15 +114,18 @@ function getDescription(transaction) { /** * Return the amount field from the transaction, return the modifiedAmount if present. * - * @param {Object} transaction + * @param {Object} transaction + * @param {Boolean} isFromExpenseReport * @returns {Number} */ -function getAmount(transaction) { +function getAmount(transaction, isFromExpenseReport) { + // In case of expense reports, the amounts are stored using an opposite sign + const multiplier = isFromExpenseReport ? -1 : 1; const amount = lodashGet(transaction, 'modifiedAmount', 0); if (amount) { - return amount; + return multiplier * amount; } - return lodashGet(transaction, 'amount', 0); + return multiplier * lodashGet(transaction, 'amount', 0); } /** diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 6ffe05e9673d..02e4265577bc 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -799,10 +799,11 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.parentReportID}`]; + const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); // STEP 2: Build new modified expense report action. - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges); - const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges); + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport); + const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport); // STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct // STEP 4: Compose the optimistic data const optimisticData = [ @@ -864,7 +865,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC // Using the getter methods here to ensure we pass modified field if present created: TransactionUtils.getCreated(updatedTransaction), - amount: TransactionUtils.getAmount(updatedTransaction), + amount: TransactionUtils.getAmount(updatedTransaction, isFromExpenseReport), currency: TransactionUtils.getCurrency(updatedTransaction), comment: TransactionUtils.getDescription(updatedTransaction), }, diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 6c5a5677c505..971ad056ae7e 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -7,6 +7,7 @@ import CONST from '../CONST'; import Navigation from '../libs/Navigation/Navigation'; import ONYXKEYS from '../ONYXKEYS'; import * as ReportActionsUtils from '../libs/ReportActionsUtils'; +import * as ReportUtils from '../libs/ReportUtils'; import * as TransactionUtils from '../libs/TransactionUtils'; import EditRequestDescriptionPage from './EditRequestDescriptionPage'; import EditRequestCreatedPage from './EditRequestCreatedPage'; @@ -40,7 +41,7 @@ function EditRequestPage({report, route}) { const transactionID = lodashGet(ReportActionsUtils.getParentReportAction(report), 'originalMessage.IOUTransactionID', ''); const transaction = TransactionUtils.getTransaction(transactionID); const transactionDescription = TransactionUtils.getDescription(transaction); - const transactionAmount = TransactionUtils.getAmount(transaction); + const transactionAmount = TransactionUtils.getAmount(transaction, ReportUtils.isExpenseReport(ReportUtils.getParentReport(report))); const transactionCurrency = TransactionUtils.getCurrency(transaction); // Take only the YYYY-MM-DD value From 319d5d53e9d40ae13e9b32d7b3cf33d89f9906ea Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 11 Aug 2023 10:04:28 +0100 Subject: [PATCH 41/45] prettier --- src/libs/ReportUtils.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index d23eb360c9af..2bb9cbee79c3 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1870,7 +1870,19 @@ function getIOUReportActionMessage(type, total, comment, currency, paymentType = * @param {Object} [receipt] * @returns {Object} */ -function buildOptimisticIOUReportAction(type, amount, currency, comment, participants, transactionID, paymentType = '', iouReportID = '', isSettlingUp = false, isSendMoneyFlow = false, receipt = {}) { +function buildOptimisticIOUReportAction( + type, + amount, + currency, + comment, + participants, + transactionID, + paymentType = '', + iouReportID = '', + isSettlingUp = false, + isSendMoneyFlow = false, + receipt = {}, +) { const IOUReportID = iouReportID || generateReportID(); const originalMessage = { From 3c37f2649ddb8330ba9b2de7f96bab61bbc2766e Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 11 Aug 2023 10:22:46 +0100 Subject: [PATCH 42/45] review feedback --- src/pages/EditRequestAmountPage.js | 2 +- src/pages/EditRequestCreatedPage.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/EditRequestAmountPage.js b/src/pages/EditRequestAmountPage.js index cb4817bbaaf3..b04de9ebfd5a 100644 --- a/src/pages/EditRequestAmountPage.js +++ b/src/pages/EditRequestAmountPage.js @@ -49,7 +49,7 @@ function EditRequestAmountPage({defaultAmount, defaultCurrency, onSubmit}) { > Navigation.goBack()} + onBackButtonPress={Navigation.goBack} /> Navigation.goBack()} + onBackButtonPress={Navigation.goBack} />
Date: Mon, 14 Aug 2023 14:47:44 +0100 Subject: [PATCH 43/45] Swap the order of the messages --- src/libs/ReportUtils.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 8d6632135bde..aa72fc88d8cc 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1338,6 +1338,11 @@ function getModifiedExpenseMessage(reportAction) { return `changed the request description to "${reportActionOriginalMessage.newComment}" (previously "${reportActionOriginalMessage.oldComment}")`; } + const hasModifiedMerchant = _.has(reportActionOriginalMessage, 'oldMerchant') && _.has(reportActionOriginalMessage, 'merchant'); + if (hasModifiedMerchant) { + return `changed the request merchant to "${reportActionOriginalMessage.merchant}" (previously "${reportActionOriginalMessage.oldMerchant}")`; + } + const hasModifiedCreated = _.has(reportActionOriginalMessage, 'oldCreated') && _.has(reportActionOriginalMessage, 'created'); if (hasModifiedCreated) { // Take only the YYYY-MM-DD value as the original date includes timestamp @@ -1345,11 +1350,6 @@ function getModifiedExpenseMessage(reportAction) { formattedOldCreated = format(formattedOldCreated, CONST.DATE.FNS_FORMAT_STRING); return `changed the request date to ${reportActionOriginalMessage.created} (previously ${formattedOldCreated})`; } - - const hasModifiedMerchant = _.has(reportActionOriginalMessage, 'oldMerchant') && _.has(reportActionOriginalMessage, 'merchant'); - if (hasModifiedMerchant) { - return `changed the request merchant to "${reportActionOriginalMessage.merchant}" (previously "${reportActionOriginalMessage.oldMerchant}")`; - } } /** From b774de1ae4491b3fea5a389501646025e80364b5 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 14 Aug 2023 16:22:23 +0100 Subject: [PATCH 44/45] Formate the transaction created date withouth timestamp --- src/libs/TransactionUtils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 92b83e7b8735..76cb47f2a444 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -1,4 +1,5 @@ import Onyx from 'react-native-onyx'; +import {format} from 'date-fns'; import lodashGet from 'lodash/get'; import _ from 'underscore'; import CONST from '../CONST'; @@ -151,9 +152,9 @@ function getCurrency(transaction) { function getCreated(transaction) { const created = lodashGet(transaction, 'modifiedCreated', ''); if (created) { - return created; + return format(new Date(created), CONST.DATE.FNS_FORMAT_STRING); } - return lodashGet(transaction, 'created', ''); + return format(new Date(lodashGet(transaction, 'created', '')), CONST.DATE.FNS_FORMAT_STRING) } export {buildOptimisticTransaction, getUpdatedTransaction, getTransaction, getDescription, getAmount, getCurrency, getCreated}; From 61d0f2f4d4482d1a14c8681acef9bf5c34c414e0 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 14 Aug 2023 16:22:57 +0100 Subject: [PATCH 45/45] Fix style --- src/libs/TransactionUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 76cb47f2a444..a05cd377514c 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -154,7 +154,7 @@ function getCreated(transaction) { if (created) { return format(new Date(created), CONST.DATE.FNS_FORMAT_STRING); } - return format(new Date(lodashGet(transaction, 'created', '')), CONST.DATE.FNS_FORMAT_STRING) + return format(new Date(lodashGet(transaction, 'created', '')), CONST.DATE.FNS_FORMAT_STRING); } export {buildOptimisticTransaction, getUpdatedTransaction, getTransaction, getDescription, getAmount, getCurrency, getCreated};