From 24638882894a9077d6d9ca7af75a6dc0cbca4177 Mon Sep 17 00:00:00 2001 From: Alberto Date: Fri, 22 Sep 2023 16:30:53 +0800 Subject: [PATCH 01/15] Use the new property --- src/libs/ReportUtils.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 2f9bd39d03c7..f7286465546a 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2274,7 +2274,7 @@ function buildOptimisticReportPreview(chatReport, iouReport, comment = '', trans actorAccountID: hasReceipt ? currentUserAccountID : iouReport.managerID || 0, childMoneyRequestCount: 1, childLastMoneyRequestComment: comment, - childLastReceiptTransactionIDs: hasReceipt ? transaction.transactionID : '', + childRecentReceiptTransactionIDs: hasReceipt ? {transaction.transactionID = transaction.transactionID} : [], whisperedToAccountIDs: hasReceipt ? [currentUserAccountID] : [], }; } @@ -2333,7 +2333,7 @@ function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransa */ function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = false, comment = '', transaction = undefined) { const hasReceipt = TransactionUtils.hasReceipt(transaction); - const lastReceiptTransactionIDs = lodashGet(reportPreviewAction, 'childLastReceiptTransactionIDs', ''); + const recentReceiptTransactionIDs = lodashGet(reportPreviewAction, 'childRecentReceiptTransactionIDs', {}); const previousTransactionIDs = lastReceiptTransactionIDs.split(',').slice(0, 2); const message = getReportPreviewMessage(iouReport, reportPreviewAction); @@ -2350,7 +2350,10 @@ function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = fals ], childLastMoneyRequestComment: comment || reportPreviewAction.childLastMoneyRequestComment, childMoneyRequestCount: reportPreviewAction.childMoneyRequestCount + (isPayRequest ? 0 : 1), - childLastReceiptTransactionIDs: hasReceipt ? [transaction.transactionID, ...previousTransactionIDs].join(',') : lastReceiptTransactionIDs, + childRecentReceiptTransactionIDs: hasReceipt ? { + [transaction.transactionID]: transaction.transactionID, + ...previousTransactionIDs + } : recentReceiptTransactionIDs, // As soon as we add a transaction without a receipt to the report, it will have ready money requests, // so we remove the whisper whisperedToAccountIDs: hasReceipt ? reportPreviewAction.whisperedToAccountIDs : [], @@ -3547,7 +3550,7 @@ function getTaskAssigneeChatOnyxData(accountID, assigneeEmail, assigneeAccountID * @returns {Object} */ function getReportPreviewDisplayTransactions(reportPreviewAction) { - const transactionIDs = lodashGet(reportPreviewAction, ['childLastReceiptTransactionIDs'], '').split(','); + const transactionIDs = lodashGet(reportPreviewAction, ['childRecentReceiptTransactionIDs']); return _.reduce( transactionIDs, (transactions, transactionID) => { From 797915a232340ebbfbadf9e309a101e03948bbac Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 25 Sep 2023 16:32:33 +0800 Subject: [PATCH 02/15] handle new object --- src/libs/ReportUtils.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index dba94413caa7..85a4493dc9d5 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2288,6 +2288,7 @@ function buildOptimisticReportPreview(chatReport, iouReport, comment = '', trans const hasReceipt = TransactionUtils.hasReceipt(transaction); const isReceiptBeingScanned = hasReceipt && TransactionUtils.isReceiptBeingScanned(transaction); const message = getReportPreviewMessage(iouReport); + const created = DateUtils.getDBTime(); return { reportActionID: NumberUtils.rand64(), reportID: chatReport.reportID, @@ -2304,13 +2305,13 @@ function buildOptimisticReportPreview(chatReport, iouReport, comment = '', trans type: CONST.REPORT.MESSAGE.TYPE.COMMENT, }, ], - created: DateUtils.getDBTime(), + created, accountID: iouReport.managerID || 0, // The preview is initially whispered if created with a receipt, so the actor is the current user as well actorAccountID: hasReceipt ? currentUserAccountID : iouReport.managerID || 0, childMoneyRequestCount: 1, childLastMoneyRequestComment: comment, - childRecentReceiptTransactionIDs: hasReceipt ? {transaction.transactionID = transaction.transactionID} : [], + childRecentReceiptTransactionIDs: hasReceipt ? {[transaction.transactionID] : created} : [], whisperedToAccountIDs: isReceiptBeingScanned ? [currentUserAccountID] : [], }; } @@ -2370,7 +2371,10 @@ function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransa function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = false, comment = '', transaction = undefined) { const hasReceipt = TransactionUtils.hasReceipt(transaction); const recentReceiptTransactionIDs = lodashGet(reportPreviewAction, 'childRecentReceiptTransactionIDs', {}); - const previousTransactionIDs = lastReceiptTransactionIDs.split(',').slice(0, 2); + const oldestTransaction = _.reduce(_.keys(recentReceiptTransactionIDs), (transactionID, oldestTransactionID) => { + return new Date(recentReceiptTransactionIDs[transactionID]) > new Date(recentReceiptTransactionIDs[transactionID]) ? transactionID : oldestTransactionID; + }); + const previousTransactions = _.omit(recentReceiptTransactionIDs, oldestTransaction); const message = getReportPreviewMessage(iouReport, reportPreviewAction); return { @@ -2387,8 +2391,8 @@ function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = fals childLastMoneyRequestComment: comment || reportPreviewAction.childLastMoneyRequestComment, childMoneyRequestCount: reportPreviewAction.childMoneyRequestCount + (isPayRequest ? 0 : 1), childRecentReceiptTransactionIDs: hasReceipt ? { - [transaction.transactionID]: transaction.transactionID, - ...previousTransactionIDs + [transaction.transactionID]: transaction.created, + ...previousTransactions } : recentReceiptTransactionIDs, // As soon as we add a transaction without a receipt to the report, it will have ready money requests, // so we remove the whisper @@ -3588,7 +3592,7 @@ function getTaskAssigneeChatOnyxData(accountID, assigneeEmail, assigneeAccountID function getReportPreviewDisplayTransactions(reportPreviewAction) { const transactionIDs = lodashGet(reportPreviewAction, ['childRecentReceiptTransactionIDs']); return _.reduce( - transactionIDs, + _.keys(transactionIDs), (transactions, transactionID) => { const transaction = TransactionUtils.getTransaction(transactionID); if (TransactionUtils.hasReceipt(transaction)) { From 25ed751386566185ebd7d86fc79c2eb36b4eefa0 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 26 Sep 2023 13:49:25 +0800 Subject: [PATCH 03/15] better handle everything --- src/libs/ReportUtils.js | 21 +++++++++++++-------- src/libs/TransactionUtils.js | 7 +++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 85a4493dc9d5..d87dac4573d0 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2370,11 +2370,14 @@ function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransa */ function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = false, comment = '', transaction = undefined) { const hasReceipt = TransactionUtils.hasReceipt(transaction); - const recentReceiptTransactionIDs = lodashGet(reportPreviewAction, 'childRecentReceiptTransactionIDs', {}); - const oldestTransaction = _.reduce(_.keys(recentReceiptTransactionIDs), (transactionID, oldestTransactionID) => { - return new Date(recentReceiptTransactionIDs[transactionID]) > new Date(recentReceiptTransactionIDs[transactionID]) ? transactionID : oldestTransactionID; + const recentReceiptTransactions = lodashGet(reportPreviewAction, 'childRecentReceiptTransactionIDs', {}); + const transactionsToKeep = TransactionUtils.getLatestTransactions(recentReceiptTransactions); + let previousTransactions =_.mapObject(recentReceiptTransactions, (value, key) => { + if (_.contains(transactionsToKeep, key)) { + return value; + } + return null; }); - const previousTransactions = _.omit(recentReceiptTransactionIDs, oldestTransaction); const message = getReportPreviewMessage(iouReport, reportPreviewAction); return { @@ -2393,7 +2396,7 @@ function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = fals childRecentReceiptTransactionIDs: hasReceipt ? { [transaction.transactionID]: transaction.created, ...previousTransactions - } : recentReceiptTransactionIDs, + } : recentReceiptTransactions, // As soon as we add a transaction without a receipt to the report, it will have ready money requests, // so we remove the whisper whisperedToAccountIDs: hasReceipt ? reportPreviewAction.whisperedToAccountIDs : [], @@ -3594,9 +3597,11 @@ function getReportPreviewDisplayTransactions(reportPreviewAction) { return _.reduce( _.keys(transactionIDs), (transactions, transactionID) => { - const transaction = TransactionUtils.getTransaction(transactionID); - if (TransactionUtils.hasReceipt(transaction)) { - transactions.push(transaction); + if (transactionIDs[transactionID] !== null) { + const transaction = TransactionUtils.getTransaction(transactionID); + if (TransactionUtils.hasReceipt(transaction)) { + transactions.push(transaction); + } } return transactions; }, diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 5dcfbc467c20..11e61bdf0bc1 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -389,6 +389,12 @@ function getValidWaypoints(waypoints, reArrangeIndexes = false) { return validWaypoints; } +function getLatestTransactions (transactions, total = 2) { + return _.sortBy(_.keys(transactions), (transaction) => { + return -new Date(transactions[transaction]); + }).slice(0, total); +} + export { buildOptimisticTransaction, getUpdatedTransaction, @@ -409,4 +415,5 @@ export { hasMissingSmartscanFields, getWaypointIndex, waypointHasValidAddress, + getLatestTransactions, }; From 29b84d1ebd4a9aad47328ac73ef660be3ce64163 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 26 Sep 2023 15:33:22 +0800 Subject: [PATCH 04/15] style --- src/libs/ReportUtils.js | 7 ++----- src/libs/TransactionUtils.js | 10 +++++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index d87dac4573d0..1895a81d48f0 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2372,11 +2372,8 @@ function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = fals const hasReceipt = TransactionUtils.hasReceipt(transaction); const recentReceiptTransactions = lodashGet(reportPreviewAction, 'childRecentReceiptTransactionIDs', {}); const transactionsToKeep = TransactionUtils.getLatestTransactions(recentReceiptTransactions); - let previousTransactions =_.mapObject(recentReceiptTransactions, (value, key) => { - if (_.contains(transactionsToKeep, key)) { - return value; - } - return null; + const previousTransactions =_.mapObject(recentReceiptTransactions, (value, key) => { + return _.contains(transactionsToKeep, key) ? value : null; }); const message = getReportPreviewMessage(iouReport, reportPreviewAction); diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 11e61bdf0bc1..d7ea7a9ff4ef 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -389,10 +389,14 @@ function getValidWaypoints(waypoints, reArrangeIndexes = false) { return validWaypoints; } +/** + * Returns the most recent transactions in an object + * @param {Object} transactions - Shaped with transctions as keys and inserted dated as values + * @param {Number} total + * @returns {Array} + */ function getLatestTransactions (transactions, total = 2) { - return _.sortBy(_.keys(transactions), (transaction) => { - return -new Date(transactions[transaction]); - }).slice(0, total); + return _.sortBy(_.keys(transactions), transaction => -new Date(transactions[transaction])).slice(0, total); } export { From dc25ec762c478c320bdbb8b359e1aefcdb01cf07 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 26 Sep 2023 16:11:32 +0800 Subject: [PATCH 05/15] lint --- src/libs/ReportUtils.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 1895a81d48f0..3a9a4d08edb6 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2372,9 +2372,7 @@ function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = fals const hasReceipt = TransactionUtils.hasReceipt(transaction); const recentReceiptTransactions = lodashGet(reportPreviewAction, 'childRecentReceiptTransactionIDs', {}); const transactionsToKeep = TransactionUtils.getLatestTransactions(recentReceiptTransactions); - const previousTransactions =_.mapObject(recentReceiptTransactions, (value, key) => { - return _.contains(transactionsToKeep, key) ? value : null; - }); + const previousTransactions =_.mapObject(recentReceiptTransactions, (value, key) => _.contains(transactionsToKeep, key) ? value : null); const message = getReportPreviewMessage(iouReport, reportPreviewAction); return { From e356ada1df51562e88253849f7b763edca0d4e60 Mon Sep 17 00:00:00 2001 From: Alberto Date: Wed, 27 Sep 2023 08:55:59 +0800 Subject: [PATCH 06/15] prettier --- src/libs/ReportUtils.js | 14 ++++++++------ src/libs/TransactionUtils.js | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 3a9a4d08edb6..48875d6f81bf 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2311,7 +2311,7 @@ function buildOptimisticReportPreview(chatReport, iouReport, comment = '', trans actorAccountID: hasReceipt ? currentUserAccountID : iouReport.managerID || 0, childMoneyRequestCount: 1, childLastMoneyRequestComment: comment, - childRecentReceiptTransactionIDs: hasReceipt ? {[transaction.transactionID] : created} : [], + childRecentReceiptTransactionIDs: hasReceipt ? {[transaction.transactionID]: created} : [], whisperedToAccountIDs: isReceiptBeingScanned ? [currentUserAccountID] : [], }; } @@ -2372,7 +2372,7 @@ function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = fals const hasReceipt = TransactionUtils.hasReceipt(transaction); const recentReceiptTransactions = lodashGet(reportPreviewAction, 'childRecentReceiptTransactionIDs', {}); const transactionsToKeep = TransactionUtils.getLatestTransactions(recentReceiptTransactions); - const previousTransactions =_.mapObject(recentReceiptTransactions, (value, key) => _.contains(transactionsToKeep, key) ? value : null); + const previousTransactions = _.mapObject(recentReceiptTransactions, (value, key) => (_.contains(transactionsToKeep, key) ? value : null)); const message = getReportPreviewMessage(iouReport, reportPreviewAction); return { @@ -2388,10 +2388,12 @@ function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = fals ], childLastMoneyRequestComment: comment || reportPreviewAction.childLastMoneyRequestComment, childMoneyRequestCount: reportPreviewAction.childMoneyRequestCount + (isPayRequest ? 0 : 1), - childRecentReceiptTransactionIDs: hasReceipt ? { - [transaction.transactionID]: transaction.created, - ...previousTransactions - } : recentReceiptTransactions, + childRecentReceiptTransactionIDs: hasReceipt + ? { + [transaction.transactionID]: transaction.created, + ...previousTransactions, + } + : recentReceiptTransactions, // As soon as we add a transaction without a receipt to the report, it will have ready money requests, // so we remove the whisper whisperedToAccountIDs: hasReceipt ? reportPreviewAction.whisperedToAccountIDs : [], diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index d7ea7a9ff4ef..8d4f3c70f0fa 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -395,8 +395,8 @@ function getValidWaypoints(waypoints, reArrangeIndexes = false) { * @param {Number} total * @returns {Array} */ -function getLatestTransactions (transactions, total = 2) { - return _.sortBy(_.keys(transactions), transaction => -new Date(transactions[transaction])).slice(0, total); +function getLatestTransactions(transactions, total = 2) { + return _.sortBy(_.keys(transactions), (transaction) => -new Date(transactions[transaction])).slice(0, total); } export { From 0923e741efc9a115c9b2053504712484af90d8a9 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 3 Oct 2023 22:12:06 +0800 Subject: [PATCH 07/15] use new ts --- src/libs/ReportUtils.js | 2 +- src/libs/TransactionUtils.js | 423 ----------------------------------- src/libs/TransactionUtils.ts | 9 + 3 files changed, 10 insertions(+), 424 deletions(-) delete mode 100644 src/libs/TransactionUtils.js diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index f0f52180b7d3..d830e83453c8 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2449,7 +2449,7 @@ function buildOptimisticModifiedExpenseReportAction(transactionThread, oldTransa function updateReportPreview(iouReport, reportPreviewAction, isPayRequest = false, comment = '', transaction = undefined) { const hasReceipt = TransactionUtils.hasReceipt(transaction); const recentReceiptTransactions = lodashGet(reportPreviewAction, 'childRecentReceiptTransactionIDs', {}); - const transactionsToKeep = TransactionUtils.getLatestTransactions(recentReceiptTransactions); + const transactionsToKeep = TransactionUtils.getRecentTransactions(recentReceiptTransactions); const previousTransactions = _.mapObject(recentReceiptTransactions, (value, key) => (_.contains(transactionsToKeep, key) ? value : null)); const message = getReportPreviewMessage(iouReport, reportPreviewAction); diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js deleted file mode 100644 index 8d4f3c70f0fa..000000000000 --- a/src/libs/TransactionUtils.js +++ /dev/null @@ -1,423 +0,0 @@ -import Onyx from 'react-native-onyx'; -import {format, parseISO, isValid} from 'date-fns'; -import lodashGet from 'lodash/get'; -import _ from 'underscore'; -import CONST from '../CONST'; -import ONYXKEYS from '../ONYXKEYS'; -import DateUtils from './DateUtils'; -import * as NumberUtils from './NumberUtils'; - -let allTransactions = {}; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.TRANSACTION, - waitForCollectionCallback: true, - callback: (val) => { - if (!val) { - return; - } - allTransactions = _.pick(val, (transaction) => transaction); - }, -}); - -/** - * Optimistically generate a transaction. - * - * @param {Number} amount – in cents - * @param {String} currency - * @param {String} reportID - * @param {String} [comment] - * @param {String} [created] - * @param {String} [source] - * @param {String} [originalTransactionID] - * @param {String} [merchant] - * @param {Object} [receipt] - * @param {String} [filename] - * @param {String} [existingTransactionID] When creating a distance request, an empty transaction has already been created with a transactionID. In that case, the transaction here needs to have it's transactionID match what was already generated. - * @param {String} [category] - * @param {String} [tag] - * @param {Boolean} [billable] - * @returns {Object} - */ -function buildOptimisticTransaction( - amount, - currency, - reportID, - comment = '', - created = '', - source = '', - originalTransactionID = '', - merchant = '', - receipt = {}, - filename = '', - existingTransactionID = null, - category = '', - tag = '', - billable = false, -) { - // transactionIDs are random, positive, 64-bit numeric strings. - // Because JS can only handle 53-bit numbers, transactionIDs are strings in the front-end (just like reportActionID) - const transactionID = existingTransactionID || NumberUtils.rand64(); - - const commentJSON = {comment}; - if (source) { - commentJSON.source = source; - } - if (originalTransactionID) { - commentJSON.originalTransactionID = originalTransactionID; - } - - // For the SmartScan to run successfully, we need to pass the merchant field empty to the API - const defaultMerchant = _.isEmpty(receipt) ? CONST.TRANSACTION.DEFAULT_MERCHANT : ''; - - return { - transactionID, - amount, - currency, - reportID, - comment: commentJSON, - merchant: merchant || defaultMerchant, - created: created || DateUtils.getDBTime(), - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - receipt, - filename, - category, - tag, - billable, - }; -} - -/** - * @param {Object|null} transaction - * @returns {Boolean} - */ -function hasReceipt(transaction) { - return lodashGet(transaction, 'receipt.state', '') !== ''; -} - -/** - * @param {Object} transaction - * @returns {Boolean} - */ -function areRequiredFieldsEmpty(transaction) { - return ( - transaction.modifiedMerchant === CONST.TRANSACTION.UNKNOWN_MERCHANT || - transaction.modifiedMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT || - (transaction.modifiedMerchant === '' && - (transaction.merchant === CONST.TRANSACTION.UNKNOWN_MERCHANT || transaction.merchant === '' || transaction.merchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT)) || - (transaction.modifiedAmount === 0 && transaction.amount === 0) || - (transaction.modifiedCreated === '' && transaction.created === '') - ); -} - -/** - * Given the edit made to the money request, return an updated transaction object. - * - * @param {Object} transaction - * @param {Object} transactionChanges - * @param {Object} isFromExpenseReport - * @returns {Object} - */ -function getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) { - // Only changing the first level fields so no need for deep clone now - const updatedTransaction = _.clone(transaction); - let shouldStopSmartscan = false; - - // The comment property does not have its modifiedComment counterpart - if (_.has(transactionChanges, 'comment')) { - updatedTransaction.comment = { - ...updatedTransaction.comment, - comment: transactionChanges.comment, - }; - } - if (_.has(transactionChanges, 'created')) { - updatedTransaction.modifiedCreated = transactionChanges.created; - shouldStopSmartscan = true; - } - if (_.has(transactionChanges, 'amount')) { - updatedTransaction.modifiedAmount = isFromExpenseReport ? -transactionChanges.amount : transactionChanges.amount; - shouldStopSmartscan = true; - } - if (_.has(transactionChanges, 'currency')) { - updatedTransaction.modifiedCurrency = transactionChanges.currency; - shouldStopSmartscan = true; - } - - if (_.has(transactionChanges, 'merchant')) { - updatedTransaction.modifiedMerchant = transactionChanges.merchant; - shouldStopSmartscan = true; - } - - if (_.has(transactionChanges, 'category')) { - updatedTransaction.category = transactionChanges.category; - } - - if (shouldStopSmartscan && _.has(transaction, 'receipt') && !_.isEmpty(transaction.receipt) && lodashGet(transaction, 'receipt.state') !== CONST.IOU.RECEIPT_STATE.OPEN) { - updatedTransaction.receipt.state = CONST.IOU.RECEIPT_STATE.OPEN; - } - - updatedTransaction.pendingFields = { - ...(_.has(transactionChanges, 'comment') && {comment: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), - ...(_.has(transactionChanges, 'created') && {created: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), - ...(_.has(transactionChanges, 'amount') && {amount: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), - ...(_.has(transactionChanges, 'currency') && {currency: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), - ...(_.has(transactionChanges, 'merchant') && {merchant: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), - ...(_.has(transactionChanges, 'category') && {category: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), - }; - - return updatedTransaction; -} - -/** - * Retrieve the particular transaction object given its ID. - * - * @param {String} transactionID - * @returns {Object} - * @deprecated Use withOnyx() or Onyx.connect() instead - */ -function getTransaction(transactionID) { - return lodashGet(allTransactions, `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {}); -} - -/** - * 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 - * @returns {String} - */ -function getDescription(transaction) { - return lodashGet(transaction, 'comment.comment', ''); -} - -/** - * Return the amount field from the transaction, return the modifiedAmount if present. - * - * @param {Object} transaction - * @param {Boolean} isFromExpenseReport - * @returns {Number} - */ -function getAmount(transaction, isFromExpenseReport) { - // IOU requests cannot have negative values but they can be stored as negative values, let's return absolute value - if (!isFromExpenseReport) { - const amount = lodashGet(transaction, 'modifiedAmount', 0); - if (amount) { - return Math.abs(amount); - } - return Math.abs(lodashGet(transaction, 'amount', 0)); - } - - // Expense report case: - // The amounts are stored using an opposite sign and negative values can be set, - // we need to return an opposite sign than is saved in the transaction object - let amount = lodashGet(transaction, 'modifiedAmount', 0); - if (amount) { - return -amount; - } - - // To avoid -0 being shown, lets only change the sign if the value is other than 0. - amount = lodashGet(transaction, 'amount', 0); - return amount ? -amount : 0; -} - -/** - * Return the currency field from the transaction, return 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', CONST.CURRENCY.USD); -} - -/** - * Return the merchant field from the transaction, return the modifiedMerchant if present. - * - * @param {Object} transaction - * @returns {String} - */ -function getMerchant(transaction) { - return lodashGet(transaction, 'modifiedMerchant', null) || lodashGet(transaction, 'merchant', ''); -} - -/** - * Return the category from the transaction. This "category" field has no "modified" complement. - * - * @param {Object} transaction - * @return {String} - */ -function getCategory(transaction) { - return lodashGet(transaction, 'category', ''); -} - -/** - * Return the created field from the transaction, return the modifiedCreated if present. - * - * @param {Object} transaction - * @returns {String} - */ -function getCreated(transaction) { - const created = lodashGet(transaction, 'modifiedCreated', '') || lodashGet(transaction, 'created', ''); - const createdDate = parseISO(created); - if (isValid(createdDate)) { - return format(createdDate, CONST.DATE.FNS_FORMAT_STRING); - } - - return ''; -} - -/* - * @param {Object} transaction - * @param {Object} transaction.comment - * @param {String} transaction.comment.type - * @param {Object} [transaction.comment.customUnit] - * @param {String} [transaction.comment.customUnit.name] - * @returns {Boolean} - */ -function isDistanceRequest(transaction) { - const type = lodashGet(transaction, 'comment.type'); - const customUnitName = lodashGet(transaction, 'comment.customUnit.name'); - return type === CONST.TRANSACTION.TYPE.CUSTOM_UNIT && customUnitName === CONST.CUSTOM_UNITS.NAME_DISTANCE; -} - -function isReceiptBeingScanned(transaction) { - return _.contains([CONST.IOU.RECEIPT_STATE.SCANREADY, CONST.IOU.RECEIPT_STATE.SCANNING], transaction.receipt.state); -} - -/** - * Check if the transaction has a non-smartscanning receipt and is missing required fields - * - * @param {Object} transaction - * @returns {Boolean} - */ -function hasMissingSmartscanFields(transaction) { - return hasReceipt(transaction) && !isDistanceRequest(transaction) && !isReceiptBeingScanned(transaction) && areRequiredFieldsEmpty(transaction); -} - -/** - * Check if the transaction has a defined route - * - * @param {Object} transaction - * @returns {Boolean} - */ -function hasRoute(transaction) { - return !!lodashGet(transaction, 'routes.route0.geometry.coordinates'); -} - -/** - * Get the transactions related to a report preview with receipts - * Get the details linked to the IOU reportAction - * - * @param {Object} reportAction - * @returns {Object} - * @deprecated Use Onyx.connect() or withOnyx() instead - */ -function getLinkedTransaction(reportAction = {}) { - const transactionID = lodashGet(reportAction, ['originalMessage', 'IOUTransactionID'], ''); - return allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] || {}; -} - -function getAllReportTransactions(reportID) { - // `reportID` from the `/CreateDistanceRequest` endpoint return's number instead of string for created `transaction`. - // For reference, https://github.com/Expensify/App/pull/26536#issuecomment-1703573277. - // We will update this in a follow-up Issue. According to this comment: https://github.com/Expensify/App/pull/26536#issuecomment-1703591019. - return _.filter(allTransactions, (transaction) => `${transaction.reportID}` === `${reportID}`); -} - -/** - * Checks if a waypoint has a valid address - * @param {Object} waypoint - * @returns {Boolean} Returns true if the address is valid - */ -function waypointHasValidAddress(waypoint) { - if (!waypoint || !waypoint.address || typeof waypoint.address !== 'string' || waypoint.address.trim() === '') { - return false; - } - return true; -} - -/** - * Converts the key of a waypoint to its index - * @param {String} key - * @returns {Number} waypoint index - */ -function getWaypointIndex(key) { - return Number(key.replace('waypoint', '')); -} - -/** - * Filters the waypoints which are valid and returns those - * @param {Object} waypoints - * @param {Boolean} reArrangeIndexes - * @returns {Object} validated waypoints - */ -function getValidWaypoints(waypoints, reArrangeIndexes = false) { - const sortedIndexes = _.map(_.keys(waypoints), (key) => getWaypointIndex(key)).sort(); - const waypointValues = _.map(sortedIndexes, (index) => waypoints[`waypoint${index}`]); - // Ensure the number of waypoints is between 2 and 25 - if (waypointValues.length < 2 || waypointValues.length > 25) { - return {}; - } - - let lastWaypointIndex = -1; - - const validWaypoints = _.reduce( - waypointValues, - (acc, currentWaypoint, index) => { - const previousWaypoint = waypointValues[lastWaypointIndex]; - // Check if the waypoint has a valid address - if (!waypointHasValidAddress(currentWaypoint)) { - return acc; - } - - // Check for adjacent waypoints with the same address - if (previousWaypoint && currentWaypoint.address === previousWaypoint.address) { - return acc; - } - - const validatedWaypoints = {...acc, [`waypoint${reArrangeIndexes ? lastWaypointIndex + 1 : index}`]: currentWaypoint}; - - lastWaypointIndex += 1; - - return validatedWaypoints; - }, - {}, - ); - return validWaypoints; -} - -/** - * Returns the most recent transactions in an object - * @param {Object} transactions - Shaped with transctions as keys and inserted dated as values - * @param {Number} total - * @returns {Array} - */ -function getLatestTransactions(transactions, total = 2) { - return _.sortBy(_.keys(transactions), (transaction) => -new Date(transactions[transaction])).slice(0, total); -} - -export { - buildOptimisticTransaction, - getUpdatedTransaction, - getTransaction, - getDescription, - getAmount, - getCurrency, - getMerchant, - getCreated, - getCategory, - getLinkedTransaction, - getAllReportTransactions, - hasReceipt, - hasRoute, - isReceiptBeingScanned, - getValidWaypoints, - isDistanceRequest, - hasMissingSmartscanFields, - getWaypointIndex, - waypointHasValidAddress, - getLatestTransactions, -}; diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 4a9ab448546a..d2d83b99d696 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -6,6 +6,7 @@ import DateUtils from './DateUtils'; import * as NumberUtils from './NumberUtils'; import {RecentWaypoint, ReportAction, Transaction} from '../types/onyx'; import {Receipt, Comment, WaypointCollection} from '../types/onyx/Transaction'; +import _ from "underscore"; type AdditionalTransactionChanges = {comment?: string; waypoints?: WaypointCollection}; @@ -360,6 +361,13 @@ function getValidWaypoints(waypoints: WaypointCollection, reArrangeIndexes = fal }, {}); } +/** + * Returns the most recent transactions in an object + */ +function getRecentTransactions(transactions: Object, total = 2): Array { + return _.sortBy(_.keys(transactions), (transactionID) => -new Date(transactions[transactionID])).slice(0, total); +} + export { buildOptimisticTransaction, getUpdatedTransaction, @@ -383,4 +391,5 @@ export { hasMissingSmartscanFields, getWaypointIndex, waypointHasValidAddress, + getRecentTransactions, }; From bc7ac6bdd965e896c03aa96cece59cb2d2a8bcff Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 3 Oct 2023 22:13:07 +0800 Subject: [PATCH 08/15] renaming --- src/libs/TransactionUtils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index d2d83b99d696..065cfb28f727 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -6,7 +6,7 @@ import DateUtils from './DateUtils'; import * as NumberUtils from './NumberUtils'; import {RecentWaypoint, ReportAction, Transaction} from '../types/onyx'; import {Receipt, Comment, WaypointCollection} from '../types/onyx/Transaction'; -import _ from "underscore"; +import _ from 'underscore'; type AdditionalTransactionChanges = {comment?: string; waypoints?: WaypointCollection}; @@ -364,8 +364,8 @@ function getValidWaypoints(waypoints: WaypointCollection, reArrangeIndexes = fal /** * Returns the most recent transactions in an object */ -function getRecentTransactions(transactions: Object, total = 2): Array { - return _.sortBy(_.keys(transactions), (transactionID) => -new Date(transactions[transactionID])).slice(0, total); +function getRecentTransactions(transactions: Object, size = 2): Array { + return _.sortBy(_.keys(transactions), (transactionID) => -new Date(transactions[transactionID])).slice(0, size); } export { From 47b61d093791b69b4f1f26658ab500ccf648d626 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 3 Oct 2023 22:40:01 +0800 Subject: [PATCH 09/15] object type --- src/libs/TransactionUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 065cfb28f727..bb8b530ad1be 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -364,7 +364,7 @@ function getValidWaypoints(waypoints: WaypointCollection, reArrangeIndexes = fal /** * Returns the most recent transactions in an object */ -function getRecentTransactions(transactions: Object, size = 2): Array { +function getRecentTransactions(transactions: {[index: string]: string}, size = 2): Array { return _.sortBy(_.keys(transactions), (transactionID) => -new Date(transactions[transactionID])).slice(0, size); } From e214beedc1254e1bf63d25731d3a215fc263246b Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 3 Oct 2023 23:28:59 +0800 Subject: [PATCH 10/15] lint --- src/libs/TransactionUtils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index bb8b530ad1be..ce44895730d6 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -6,7 +6,7 @@ import DateUtils from './DateUtils'; import * as NumberUtils from './NumberUtils'; import {RecentWaypoint, ReportAction, Transaction} from '../types/onyx'; import {Receipt, Comment, WaypointCollection} from '../types/onyx/Transaction'; -import _ from 'underscore'; +import _ from 'lodash'; type AdditionalTransactionChanges = {comment?: string; waypoints?: WaypointCollection}; @@ -364,8 +364,8 @@ function getValidWaypoints(waypoints: WaypointCollection, reArrangeIndexes = fal /** * Returns the most recent transactions in an object */ -function getRecentTransactions(transactions: {[index: string]: string}, size = 2): Array { - return _.sortBy(_.keys(transactions), (transactionID) => -new Date(transactions[transactionID])).slice(0, size); +function getRecentTransactions(transactions: Record, size = 2): unknown[] { + return _.sortBy(Object.keys(transactions), (transactionID) => -new Date(transactions[transactionID])).slice(0, size); } export { From 246e123f3661b9b627d838887e3bce4c7712a59b Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 3 Oct 2023 23:44:41 +0800 Subject: [PATCH 11/15] order imports --- src/libs/TransactionUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index ce44895730d6..3096b8e1eea5 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -1,12 +1,12 @@ import Onyx, {OnyxCollection} from 'react-native-onyx'; import {format, parseISO, isValid} from 'date-fns'; +import _ from 'lodash'; import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; import DateUtils from './DateUtils'; import * as NumberUtils from './NumberUtils'; import {RecentWaypoint, ReportAction, Transaction} from '../types/onyx'; import {Receipt, Comment, WaypointCollection} from '../types/onyx/Transaction'; -import _ from 'lodash'; type AdditionalTransactionChanges = {comment?: string; waypoints?: WaypointCollection}; From bea73c2ded817960ce7c4e1840b8a0d8dd621330 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 9 Oct 2023 15:58:33 +0200 Subject: [PATCH 12/15] use native sort --- src/libs/TransactionUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index b5d880f8c268..16a450902970 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -379,7 +379,7 @@ function getValidWaypoints(waypoints: WaypointCollection, reArrangeIndexes = fal * Returns the most recent transactions in an object */ function getRecentTransactions(transactions: Record, size = 2): unknown[] { - return _.sortBy(Object.keys(transactions), (transactionID) => -new Date(transactions[transactionID])).slice(0, size); + return Object.keys(transactions).sort((transactionID1, transactionID2) => new Date(transactions[transactionID1]) > new Date(transactions[transactionID2]) ? 1 : -1 ).slice(0, size); } export { From 5b844ea426773984cfb2a1d5dd6f2269b6a0b102 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 10 Oct 2023 12:03:03 +0200 Subject: [PATCH 13/15] correct order --- src/libs/TransactionUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 16a450902970..8041ffd3685e 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -379,7 +379,7 @@ function getValidWaypoints(waypoints: WaypointCollection, reArrangeIndexes = fal * Returns the most recent transactions in an object */ function getRecentTransactions(transactions: Record, size = 2): unknown[] { - return Object.keys(transactions).sort((transactionID1, transactionID2) => new Date(transactions[transactionID1]) > new Date(transactions[transactionID2]) ? 1 : -1 ).slice(0, size); + return Object.keys(transactions).sort((transactionID1, transactionID2) => new Date(transactions[transactionID1]) < new Date(transactions[transactionID2]) ? 1 : -1 ).slice(0, size); } export { From e7c9adc59f3b22873f513f191085dab1029ab7a7 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 10 Oct 2023 12:03:43 +0200 Subject: [PATCH 14/15] correct return --- src/libs/TransactionUtils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 8041ffd3685e..b9c124621c16 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -1,6 +1,5 @@ import Onyx, {OnyxCollection} from 'react-native-onyx'; import {format, parseISO, isValid} from 'date-fns'; -import _ from 'lodash'; import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; import DateUtils from './DateUtils'; @@ -378,7 +377,7 @@ function getValidWaypoints(waypoints: WaypointCollection, reArrangeIndexes = fal /** * Returns the most recent transactions in an object */ -function getRecentTransactions(transactions: Record, size = 2): unknown[] { +function getRecentTransactions(transactions: Record, size = 2): string[] { return Object.keys(transactions).sort((transactionID1, transactionID2) => new Date(transactions[transactionID1]) < new Date(transactions[transactionID2]) ? 1 : -1 ).slice(0, size); } From 0a6e1f30c5379d9dcdb654cedcb70645fc7a22aa Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 10 Oct 2023 12:33:01 +0200 Subject: [PATCH 15/15] prettier --- src/libs/TransactionUtils.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index b9c124621c16..b5b8271c35a3 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -378,7 +378,9 @@ function getValidWaypoints(waypoints: WaypointCollection, reArrangeIndexes = fal * Returns the most recent transactions in an object */ function getRecentTransactions(transactions: Record, size = 2): string[] { - return Object.keys(transactions).sort((transactionID1, transactionID2) => new Date(transactions[transactionID1]) < new Date(transactions[transactionID2]) ? 1 : -1 ).slice(0, size); + return Object.keys(transactions) + .sort((transactionID1, transactionID2) => (new Date(transactions[transactionID1]) < new Date(transactions[transactionID2]) ? 1 : -1)) + .slice(0, size); } export {