diff --git a/docs/context.xml b/docs/context.xml index b38e1a5f9e8a..f62520153883 100644 --- a/docs/context.xml +++ b/docs/context.xml @@ -25,7 +25,7 @@ - + diff --git a/package-lock.json b/package-lock.json index acfa4a420290..1ce9aee50531 100644 --- a/package-lock.json +++ b/package-lock.json @@ -113,7 +113,7 @@ "react-web-config": "^1.0.0", "react-window": "^1.8.9", "save": "^2.4.0", - "semver": "^7.3.8", + "semver": "^7.5.2", "shim-keyboard-event-key": "^1.0.3", "underscore": "^1.13.1" }, diff --git a/package.json b/package.json index 03773ecd9f91..252b45912502 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,7 @@ "react-web-config": "^1.0.0", "react-window": "^1.8.9", "save": "^2.4.0", - "semver": "^7.3.8", + "semver": "^7.5.2", "shim-keyboard-event-key": "^1.0.3", "underscore": "^1.13.1" }, diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 7ef5c68c3850..5a00c49db0a0 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -221,8 +221,9 @@ export default { NEW_TASK_FORM: 'newTaskForm', EDIT_TASK_FORM: 'editTaskForm', MONEY_REQUEST_DESCRIPTION_FORM: 'moneyRequestDescriptionForm', + MONEY_REQUEST_MERCHANT_FORM: 'moneyRequestMerchantForm', MONEY_REQUEST_AMOUNT_FORM: 'moneyRequestAmountForm', - MONEY_REQUEST_CREATED_FORM: 'moneyRequestCreatedForm', + MONEY_REQUEST_DATE_FORM: 'moneyRequestCreatedForm', NEW_CONTACT_METHOD_FORM: 'newContactMethodForm', PAYPAL_FORM: 'payPalForm', WAYPOINT_FORM: 'waypointForm', diff --git a/src/ROUTES.js b/src/ROUTES.js index 9063cd275d68..3f96d77d477e 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -89,8 +89,10 @@ export default { MONEY_REQUEST_AMOUNT: ':iouType/new/amount/:reportID?', MONEY_REQUEST_PARTICIPANTS: ':iouType/new/participants/:reportID?', MONEY_REQUEST_CONFIRMATION: ':iouType/new/confirmation/:reportID?', + MONEY_REQUEST_DATE: ':iouType/new/date/:reportID?', MONEY_REQUEST_CURRENCY: ':iouType/new/currency/:reportID?', MONEY_REQUEST_DESCRIPTION: ':iouType/new/description/:reportID?', + MONEY_REQUEST_MERCHANT: ':iouType/new/merchant/:reportID?', MONEY_REQUEST_MANUAL_TAB: ':iouType/new/:reportID?/manual', MONEY_REQUEST_SCAN_TAB: ':iouType/new/:reportID?/scan', MONEY_REQUEST_DISTANCE_TAB: ':iouType/new/:reportID?/distance', @@ -102,8 +104,10 @@ export default { getMoneyRequestAmountRoute: (iouType, reportID = '') => `${iouType}/new/amount/${reportID}`, getMoneyRequestParticipantsRoute: (iouType, reportID = '') => `${iouType}/new/participants/${reportID}`, getMoneyRequestConfirmationRoute: (iouType, reportID = '') => `${iouType}/new/confirmation/${reportID}`, + getMoneyRequestCreatedRoute: (iouType, reportID = '') => `${iouType}/new/date/${reportID}`, getMoneyRequestCurrencyRoute: (iouType, reportID = '', currency, backTo) => `${iouType}/new/currency/${reportID}?currency=${currency}&backTo=${backTo}`, getMoneyRequestDescriptionRoute: (iouType, reportID = '') => `${iouType}/new/description/${reportID}`, + getMoneyRequestMerchantRoute: (iouType, reportID = '') => `${iouType}/new/merchant/${reportID}`, getMoneyRequestDistanceTabRoute: (iouType, reportID = '') => `${iouType}/new/${reportID}/distance`, getMoneyRequestWaypointRoute: (iouType, waypointIndex) => `${iouType}/new/waypoint/${waypointIndex}`, SPLIT_BILL_DETAILS: `r/:reportID/split/:reportActionID`, diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 2cc458d0e4ad..832be75c1317 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -1,6 +1,7 @@ import React, {useCallback, useMemo, useReducer, useState} from 'react'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; +import {format} from 'date-fns'; import _ from 'underscore'; import {View} from 'react-native'; import Str from 'expensify-common/lib/str'; @@ -58,7 +59,7 @@ const propTypes = { iouType: PropTypes.string, /** IOU date */ - iouDate: PropTypes.string, + iouCreated: PropTypes.string, /** IOU merchant */ iouMerchant: PropTypes.string, @@ -125,6 +126,7 @@ function MoneyRequestConfirmationList(props) { // A flag and a toggler for showing the rest of the form fields const [showAllFields, toggleShowAllFields] = useReducer((state) => !state, false); + const isTypeRequest = props.iouType === CONST.IOU.MONEY_REQUEST_TYPE.REQUEST; /** * Returns the participants with amount @@ -406,18 +408,20 @@ function MoneyRequestConfirmationList(props) { {showAllFields && ( <> Navigation.navigate(ROUTES.getMoneyRequestCreatedRoute(props.iouType, props.reportID))} + disabled={didConfirm || props.isReadOnly || !isTypeRequest} /> Navigation.navigate(ROUTES.getMoneyRequestMerchantRoute(props.iouType, props.reportID))} + disabled={didConfirm || props.isReadOnly || !isTypeRequest} /> )} diff --git a/src/components/OfflineWithFeedback.js b/src/components/OfflineWithFeedback.js index 820cce252205..2f99b21b6523 100644 --- a/src/components/OfflineWithFeedback.js +++ b/src/components/OfflineWithFeedback.js @@ -94,10 +94,10 @@ function OfflineWithFeedback(props) { const errorMessages = _.omit(props.errors, (e) => e === null); const hasErrorMessages = !_.isEmpty(errorMessages); const isOfflinePendingAction = props.network.isOffline && props.pendingAction; - const isUpdateOrDeleteError = hasErrors && (props.pendingAction === 'delete' || props.pendingAction === 'update'); - const isAddError = hasErrors && props.pendingAction === 'add'; + const isUpdateOrDeleteError = hasErrors && (props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + const isAddError = hasErrors && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD; const needsOpacity = (isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError; - const needsStrikeThrough = props.network.isOffline && props.pendingAction === 'delete'; + const needsStrikeThrough = props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; const hideChildren = props.shouldHideOnDelete && !props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !hasErrors; let children = props.children; diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 0d8a38ede4e2..c36eaf5db368 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -23,6 +23,7 @@ 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'; +import OfflineWithFeedback from '../OfflineWithFeedback'; const propTypes = { /** The report currently being looked at */ @@ -67,7 +68,13 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic const parentReportAction = ReportActionsUtils.getParentReportAction(report); const moneyRequestReport = parentReport; const transaction = TransactionUtils.getLinkedTransaction(parentReportAction); - const {created: transactionDate, amount: transactionAmount, currency: transactionCurrency, comment: transactionDescription} = ReportUtils.getTransactionDetails(transaction); + const { + created: transactionDate, + amount: transactionAmount, + currency: transactionCurrency, + comment: transactionDescription, + merchant: transactionMerchant, + } = ReportUtils.getTransactionDetails(transaction); const formattedTransactionAmount = transactionAmount && transactionCurrency && CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); @@ -97,30 +104,44 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic style={[StyleUtils.getReportWelcomeBackgroundImageStyle(true)]} /> - 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))} - /> + + 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 && } ); diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index d1ac97d09e9c..aa4fcc02c906 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -69,6 +69,13 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator([ }, name: 'Money_Request_Currency', }, + { + getComponent: () => { + const MoneyRequestDatePage = require('../../../pages/iou/MoneyRequestDatePage').default; + return MoneyRequestDatePage; + }, + name: 'Money_Request_Date', + }, { getComponent: () => { const MoneyRequestDescriptionPage = require('../../../pages/iou/MoneyRequestDescriptionPage').default; @@ -76,6 +83,13 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator([ }, name: 'Money_Request_Description', }, + { + getComponent: () => { + const MoneyRequestMerchantPage = require('../../../pages/iou/MoneyRequestMerchantPage').default; + return MoneyRequestMerchantPage; + }, + name: 'Money_Request_Merchant', + }, { getComponent: () => { const AddPersonalBankAccountPage = require('../../../pages/AddPersonalBankAccountPage').default; diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 573eb71836d3..a76ebbf776da 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -307,8 +307,10 @@ export default { Money_Request_Amount: ROUTES.MONEY_REQUEST_AMOUNT, Money_Request_Participants: ROUTES.MONEY_REQUEST_PARTICIPANTS, Money_Request_Confirmation: ROUTES.MONEY_REQUEST_CONFIRMATION, + Money_Request_Date: ROUTES.MONEY_REQUEST_DATE, Money_Request_Currency: ROUTES.MONEY_REQUEST_CURRENCY, Money_Request_Description: ROUTES.MONEY_REQUEST_DESCRIPTION, + Money_Request_Merchant: ROUTES.MONEY_REQUEST_MERCHANT, Money_Request_Waypoint: ROUTES.MONEY_REQUEST_WAYPOINT, IOU_Send_Enable_Payments: ROUTES.IOU_SEND_ENABLE_PAYMENTS, IOU_Send_Add_Bank_Account: ROUTES.IOU_SEND_ADD_BANK_ACCOUNT, diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 654bc7054cb2..a5185d8352aa 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -758,8 +758,17 @@ function getOptions( // Finally check to see if this option is a match for the provided search string if we have one const {searchText, participantsList, isChatRoom} = reportOption; const participantNames = getParticipantNames(participantsList); - if (searchValue && !isSearchStringMatch(searchValue, searchText, participantNames, isChatRoom)) { - continue; + + if (searchValue) { + // Determine if the search is happening within a chat room and starts with the report ID + const isReportIdSearch = isChatRoom && Str.startsWith(reportOption.reportID, searchValue); + + // Check if the search string matches the search text or participant names considering the type of the room + const isSearchMatch = isSearchStringMatch(searchValue, searchText, participantNames, isChatRoom); + + if (!isReportIdSearch && !isSearchMatch) { + continue; + } } recentReportOptions.push(reportOption); @@ -1044,7 +1053,7 @@ function getHeaderMessage(hasSelectableOptions, hasUserToInvite, searchValue, ma const isValidEmail = Str.isValidEmail(searchValue); - if (searchValue && CONST.REGEX.DIGITS_AND_PLUS.test(searchValue) && !isValidPhone) { + if (searchValue && CONST.REGEX.DIGITS_AND_PLUS.test(searchValue) && !isValidPhone && !hasSelectableOptions) { return Localize.translate(preferredLocale, 'messages.errorMessageInvalidPhone'); } diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index b24a5ea37aa0..0b96c1d1120b 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1,5 +1,5 @@ import _ from 'underscore'; -import {format} from 'date-fns'; +import {format, parseISO} from 'date-fns'; import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import lodashIntersection from 'lodash/intersection'; @@ -1205,7 +1205,10 @@ function getPolicyExpenseChatName(report, policy = undefined) { function getMoneyRequestReportName(report, policy = undefined) { const formattedAmount = CurrencyUtils.convertToDisplayString(getMoneyRequestTotal(report), report.currency); const payerName = isExpenseReport(report) ? getPolicyName(report, false, policy) : getDisplayNameForParticipant(report.managerID); - const payerPaidAmountMesssage = Localize.translateLocal('iou.payerPaidAmount', {payer: payerName, amount: formattedAmount}); + const payerPaidAmountMesssage = Localize.translateLocal('iou.payerPaidAmount', { + payer: payerName, + amount: formattedAmount, + }); if (report.isWaitingOnBankAccount) { return `${payerPaidAmountMesssage} • ${Localize.translateLocal('iou.pending')}`; @@ -1241,6 +1244,7 @@ function getTransactionDetails(transaction) { amount: TransactionUtils.getAmount(transaction, isExpenseReport(report)), currency: TransactionUtils.getCurrency(transaction), comment: TransactionUtils.getDescription(transaction), + merchant: TransactionUtils.getMerchant(transaction), }; } @@ -1303,6 +1307,29 @@ function getReportPreviewMessage(report, reportAction = {}) { return Localize.translateLocal('iou.payerOwesAmount', {payer: payerName, amount: formattedAmount}); } +/** + * Get the proper message schema for modified expense message. + * + * @param {String} newValue + * @param {String} oldValue + * @param {String} valueName + * @param {Boolean} valueInQuotes + * @returns {String} + */ + +function getProperSchemaForModifiedExpenseMessage(newValue, oldValue, valueName, valueInQuotes) { + const newValueToDisplay = valueInQuotes ? `"${newValue}"` : newValue; + const oldValueToDisplay = valueInQuotes ? `"${oldValue}"` : oldValue; + + if (!oldValue) { + return `set the ${valueName} to ${newValueToDisplay}`; + } + if (!newValue) { + return `removed the ${valueName} (previously ${oldValueToDisplay})`; + } + return `changed the ${valueName} to ${newValueToDisplay} (previously ${oldValueToDisplay})`; +} + /** * Get the report action message when expense has been modified. * @@ -1327,25 +1354,25 @@ function getModifiedExpenseMessage(reportAction) { const currency = reportActionOriginalMessage.currency; const amount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage.amount, currency); - return `changed the request to ${amount} (previously ${oldAmount})`; + return getProperSchemaForModifiedExpenseMessage(amount, oldAmount, 'amount', false); } const hasModifiedComment = _.has(reportActionOriginalMessage, 'oldComment') && _.has(reportActionOriginalMessage, 'newComment'); if (hasModifiedComment) { - return `changed the request description to "${reportActionOriginalMessage.newComment}" (previously "${reportActionOriginalMessage.oldComment}")`; + return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.newComment, reportActionOriginalMessage.oldComment, 'description', true); } const hasModifiedMerchant = _.has(reportActionOriginalMessage, 'oldMerchant') && _.has(reportActionOriginalMessage, 'merchant'); if (hasModifiedMerchant) { - return `changed the request merchant to "${reportActionOriginalMessage.merchant}" (previously "${reportActionOriginalMessage.oldMerchant}")`; + return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.merchant, reportActionOriginalMessage.oldMerchant, 'merchant', true); } const hasModifiedCreated = _.has(reportActionOriginalMessage, 'oldCreated') && _.has(reportActionOriginalMessage, 'created'); if (hasModifiedCreated) { // Take only the YYYY-MM-DD value as the original date includes timestamp - let formattedOldCreated = new Date(reportActionOriginalMessage.oldCreated); + let formattedOldCreated = parseISO(reportActionOriginalMessage.oldCreated); formattedOldCreated = format(formattedOldCreated, CONST.DATE.FNS_FORMAT_STRING); - return `changed the request date to ${reportActionOriginalMessage.created} (previously ${formattedOldCreated})`; + return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.created, formattedOldCreated, 'date', false); } } diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 90b6ca72bd4a..f7e3e644d7b8 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -1,5 +1,5 @@ import Onyx from 'react-native-onyx'; -import {format} from 'date-fns'; +import {format, parseISO, isValid} from 'date-fns'; import lodashGet from 'lodash/get'; import _ from 'underscore'; import CONST from '../CONST'; @@ -26,6 +26,7 @@ Onyx.connect({ * @param {String} currency * @param {String} reportID * @param {String} [comment] + * @param {String} [created] * @param {String} [source] * @param {String} [originalTransactionID] * @param {String} [merchant] @@ -38,6 +39,7 @@ function buildOptimisticTransaction( currency, reportID, comment = '', + created = '', source = '', originalTransactionID = '', merchant = CONST.REPORT.TYPE.IOU, @@ -62,8 +64,8 @@ function buildOptimisticTransaction( currency, reportID, comment: commentJSON, - merchant, - created: DateUtils.getDBTime(), + merchant: merchant || CONST.REPORT.TYPE.IOU, + created: created || DateUtils.getDBTime(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, receipt, }; @@ -97,7 +99,12 @@ function getUpdatedTransaction(transaction, transactionChanges, isFromExpenseRep if (_.has(transactionChanges, 'currency')) { updatedTransaction.modifiedCurrency = transactionChanges.currency; } - updatedTransaction.pendingAction = CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE; + 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}), + }; return updatedTransaction; } @@ -167,6 +174,16 @@ function getCurrency(transaction) { 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 created field from the transaction, return the modifiedCreated if present. * @@ -175,9 +192,11 @@ function getCurrency(transaction) { */ function getCreated(transaction) { const created = lodashGet(transaction, 'modifiedCreated', '') || lodashGet(transaction, 'created', ''); - if (created) { - return format(new Date(created), CONST.DATE.FNS_FORMAT_STRING); + const createdDate = parseISO(created); + if (isValid(createdDate)) { + return format(createdDate, CONST.DATE.FNS_FORMAT_STRING); } + return ''; } @@ -196,4 +215,4 @@ function getAllReportTransactions(reportID) { return _.filter(allTransactions, (transaction) => transaction.reportID === reportID); } -export {buildOptimisticTransaction, getUpdatedTransaction, getTransaction, getDescription, getAmount, getCurrency, getCreated, getLinkedTransaction, getAllReportTransactions}; +export {buildOptimisticTransaction, getUpdatedTransaction, getTransaction, getDescription, getAmount, getCurrency, getMerchant, getCreated, getLinkedTransaction, getAllReportTransactions}; diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index b6caac0345cd..7244d14fe273 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -72,7 +72,7 @@ Onyx.connect({ * @param {String} id */ function resetMoneyRequestInfo(id = '') { - const date = currentDate || moment().format('YYYY-MM-DD'); + const created = currentDate || moment().format('YYYY-MM-DD'); Onyx.merge(ONYXKEYS.IOU, { id, amount: 0, @@ -80,7 +80,7 @@ function resetMoneyRequestInfo(id = '') { comment: '', participants: [], merchant: '', - date, + created, receiptPath: '', receiptSource: '', }); @@ -310,6 +310,8 @@ function buildOnyxDataForMoneyRequest( * @param {String} comment * @param {Number} amount * @param {String} currency + * @param {String} created + * @param {String} merchant * @param {Number} payeeAccountID * @param {String} payeeEmail * @param {Object} [receipt] @@ -328,7 +330,7 @@ function buildOnyxDataForMoneyRequest( * @returns {Object} data.onyxData.failureData * @param {String} [existingTransactionID] */ -function getMoneyRequestInformation(report, participant, comment, amount, currency, payeeAccountID, payeeEmail, receipt = undefined, existingTransactionID = null) { +function getMoneyRequestInformation(report, participant, comment, amount, currency, created, merchant, payeeAccountID, payeeEmail, receipt = undefined, existingTransactionID = null) { const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login); const payerAccountID = Number(participant.accountID); const isPolicyExpenseChat = participant.isPolicyExpenseChat; @@ -383,9 +385,10 @@ function getMoneyRequestInformation(report, participant, comment, amount, curren currency, iouReport.reportID, comment, + created, '', '', - undefined, + merchant, receiptObject, existingTransactionID, ); @@ -495,6 +498,8 @@ function createDistanceRequest(report, payeeEmail, payeeAccountID, participant, comment, 0, 'USD', + created, + '', payeeAccountID, payeeEmail, null, @@ -526,19 +531,23 @@ function createDistanceRequest(report, payeeEmail, payeeAccountID, participant, * @param {Object} report * @param {Number} amount - always in the smallest unit of the currency * @param {String} currency + * @param {String} created + * @param {String} merchant * @param {String} payeeEmail * @param {Number} payeeAccountID * @param {Object} participant * @param {String} comment * @param {Object} [receipt] */ -function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, participant, comment, receipt = undefined) { +function requestMoney(report, amount, currency, created, merchant, payeeEmail, payeeAccountID, participant, comment, receipt = undefined) { const {payerEmail, iouReport, chatReport, transaction, iouAction, createdChatReportActionID, createdIOUReportActionID, reportPreviewAction, onyxData} = getMoneyRequestInformation( report, participant, comment, amount, currency, + created, + merchant, payeeAccountID, payeeEmail, receipt, @@ -551,6 +560,8 @@ function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, part amount, currency, comment, + created, + merchant, iouReportID: iouReport.reportID, chatReportID: chatReport.reportID, transactionID: transaction.transactionID, @@ -609,6 +620,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco comment, '', '', + '', `${Localize.translateLocal('iou.splitBill')} ${Localize.translateLocal('common.with')} ${formattedParticipants} [${DateUtils.getDBTime().slice(0, 10)}]`, ); @@ -782,6 +794,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco currency, oneOnOneIOUReport.reportID, comment, + '', CONST.IOU.MONEY_REQUEST_TYPE.SPLIT, splitTransaction.transactionID, ); @@ -982,7 +995,14 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, - value: {pendingAction: null}, + value: { + pendingFields: { + comment: null, + amount: null, + created: null, + currency: null, + }, + }, }, ]; @@ -1691,6 +1711,13 @@ function setMoneyRequestAmount(amount) { Onyx.merge(ONYXKEYS.IOU, {amount}); } +/** + * @param {String} created + */ +function setMoneyRequestCreated(created) { + Onyx.merge(ONYXKEYS.IOU, {created}); +} + /** * @param {String} currency */ @@ -1705,6 +1732,13 @@ function setMoneyRequestDescription(comment) { Onyx.merge(ONYXKEYS.IOU, {comment: comment.trim()}); } +/** + * @param {String} merchant + */ +function setMoneyRequestMerchant(merchant) { + Onyx.merge(ONYXKEYS.IOU, {merchant: merchant.trim()}); +} + /** * @param {Object[]} participants */ @@ -1778,8 +1812,10 @@ export { resetMoneyRequestInfo, setMoneyRequestId, setMoneyRequestAmount, + setMoneyRequestCreated, setMoneyRequestCurrency, setMoneyRequestDescription, + setMoneyRequestMerchant, setMoneyRequestParticipants, setMoneyRequestReceipt, createEmptyTransaction, diff --git a/src/pages/EditRequestCreatedPage.js b/src/pages/EditRequestCreatedPage.js index 4e4fce308e5b..79633c214486 100644 --- a/src/pages/EditRequestCreatedPage.js +++ b/src/pages/EditRequestCreatedPage.js @@ -31,7 +31,7 @@ function EditRequestCreatedPage({defaultCreated, onSubmit}) { />
() => { @@ -213,7 +215,6 @@ function ReportActionItem(props) { } setIsContextMenuActive(true); - const selection = SelectionScraper.getCurrentSelection(); ReportActionContextMenu.showContextMenu( ContextMenuActions.CONTEXT_MENU_TYPES.REPORT_ACTION, @@ -225,11 +226,11 @@ function ReportActionItem(props) { props.draftMessage, () => {}, toggleContextMenuFromActiveReportAction, - ReportUtils.isArchivedRoom(props.report), - ReportUtils.chatIncludesChronos(props.report), + ReportUtils.isArchivedRoom(originalReport), + ReportUtils.chatIncludesChronos(originalReport), ); }, - [props.draftMessage, props.action, props.report, toggleContextMenuFromActiveReportAction], + [props.draftMessage, props.action, props.report.reportID, toggleContextMenuFromActiveReportAction, originalReport], ); const toggleReaction = useCallback( @@ -468,12 +469,10 @@ function ReportActionItem(props) { const parentReportAction = ReportActionsUtils.getParentReportAction(props.report); if (ReportActionsUtils.isTransactionThread(parentReportAction)) { return ( - - - + ); } if (ReportUtils.isTaskReport(props.report)) { @@ -540,11 +539,11 @@ function ReportActionItem(props) { { + const moneyRequestId = `${iouType}${reportID}`; + const shouldReset = iou.id !== moneyRequestId; + if (shouldReset) { + IOU.resetMoneyRequestInfo(moneyRequestId); + } + + if (_.isEmpty(iou.participants) || (iou.amount === 0 && !iou.receiptPath) || shouldReset) { + Navigation.goBack(ROUTES.getMoneyRequestRoute(iouType, reportID), true); + } + }, [iou.id, iou.participants, iou.amount, iou.receiptPath, iouType, reportID]); + + function navigateBack() { + Navigation.goBack(ROUTES.getMoneyRequestConfirmationRoute(iouType, reportID)); + } + + /** + * Sets the money request comment by saving it to Onyx. + * + * @param {Object} value + * @param {String} value.moneyRequestCreated + */ + function updateDate(value) { + IOU.setMoneyRequestCreated(value.moneyRequestCreated); + navigateBack(); + } + + return ( + + navigateBack()} + /> + updateDate(value)} + submitButtonText={translate('common.save')} + enabledWhenOffline + > + + + + ); +} + +MoneyRequestDatePage.propTypes = propTypes; +MoneyRequestDatePage.defaultProps = defaultProps; + +export default withOnyx({ + iou: { + key: ONYXKEYS.IOU, + }, +})(MoneyRequestDatePage); diff --git a/src/pages/iou/MoneyRequestDescriptionPage.js b/src/pages/iou/MoneyRequestDescriptionPage.js index 07e4b295f85f..2e6e459f1d96 100644 --- a/src/pages/iou/MoneyRequestDescriptionPage.js +++ b/src/pages/iou/MoneyRequestDescriptionPage.js @@ -1,11 +1,10 @@ -import React, {Component} from 'react'; +import React, {useEffect, useRef} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; import _ from 'underscore'; import lodashGet from 'lodash/get'; 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'; @@ -13,14 +12,12 @@ import ONYXKEYS from '../../ONYXKEYS'; import styles from '../../styles/styles'; import Navigation from '../../libs/Navigation/Navigation'; import ROUTES from '../../ROUTES'; -import compose from '../../libs/compose'; import * as IOU from '../../libs/actions/IOU'; import optionPropTypes from '../../components/optionPropTypes'; import CONST from '../../CONST'; +import useLocalize from '../../hooks/useLocalize'; const propTypes = { - ...withLocalizePropTypes, - /** Onyx Props */ /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ iou: PropTypes.shape({ @@ -28,7 +25,20 @@ const propTypes = { amount: PropTypes.number, comment: PropTypes.string, participants: PropTypes.arrayOf(optionPropTypes), + receiptPath: PropTypes.string, }), + + /** Route from navigation */ + route: PropTypes.shape({ + /** Params from the route */ + params: PropTypes.shape({ + /** Which field we are editing */ + field: PropTypes.string, + + /** reportID for the "transaction thread" */ + threadReportID: PropTypes.string, + }), + }).isRequired, }; const defaultProps = { @@ -37,44 +47,30 @@ const defaultProps = { amount: 0, comment: '', participants: [], + receiptPath: '', }, }; -class MoneyRequestDescriptionPage extends Component { - constructor(props) { - super(props); +function MoneyRequestDescriptionPage({iou, route}) { + const {translate} = useLocalize(); + const inputRef = useRef(null); + const iouType = lodashGet(route, 'params.iouType', ''); + const reportID = lodashGet(route, 'params.reportID', ''); - this.updateComment = this.updateComment.bind(this); - this.navigateBack = this.navigateBack.bind(this); - this.iouType = lodashGet(props.route, 'params.iouType', ''); - this.reportID = lodashGet(props.route, 'params.reportID', ''); - } - - componentDidMount() { - const moneyRequestId = `${this.iouType}${this.reportID}`; - const shouldReset = this.props.iou.id !== moneyRequestId; + useEffect(() => { + const moneyRequestId = `${iouType}${reportID}`; + const shouldReset = iou.id !== moneyRequestId; if (shouldReset) { IOU.resetMoneyRequestInfo(moneyRequestId); } - if (_.isEmpty(this.props.iou.participants) || (this.props.iou.amount === 0 && !this.props.iou.receiptPath) || shouldReset) { - Navigation.goBack(ROUTES.getMoneyRequestRoute(this.iouType, this.reportID), true); + if (_.isEmpty(iou.participants) || (iou.amount === 0 && !iou.receiptPath) || shouldReset) { + Navigation.goBack(ROUTES.getMoneyRequestRoute(iouType, reportID), true); } - } + }, [iou.id, iou.participants, iou.amount, iou.receiptPath, iouType, reportID]); - // eslint-disable-next-line rulesdir/prefer-early-return - componentDidUpdate(prevProps) { - // ID in Onyx could change by initiating a new request in a separate browser tab or completing a request - if (_.isEmpty(this.props.iou.participants) || (this.props.iou.amount === 0 && !this.props.iou.receiptPath) || prevProps.iou.id !== this.props.iou.id) { - // The ID is cleared on completing a request. In that case, we will do nothing. - if (this.props.iou.id) { - Navigation.goBack(ROUTES.getMoneyRequestRoute(this.iouType, this.reportID), true); - } - } - } - - navigateBack() { - Navigation.goBack(ROUTES.getMoneyRequestConfirmationRoute(this.iouType, this.reportID)); + function navigateBack() { + Navigation.goBack(ROUTES.getMoneyRequestConfirmationRoute(iouType, reportID)); } /** @@ -83,52 +79,49 @@ class MoneyRequestDescriptionPage extends Component { * @param {Object} value * @param {String} value.moneyRequestComment */ - updateComment(value) { + function updateComment(value) { IOU.setMoneyRequestDescription(value.moneyRequestComment); - this.navigateBack(); + navigateBack(); } - render() { - return ( - this.descriptionInputRef && this.descriptionInputRef.focus()} + return ( + inputRef.current && inputRef.current.focus()} + > + navigateBack()} + /> +
updateComment(value)} + submitButtonText={translate('common.save')} + enabledWhenOffline > - - - - (this.descriptionInputRef = el)} - /> - - -
- ); - } + + (inputRef.current = el)} + /> + + +
+ ); } MoneyRequestDescriptionPage.propTypes = propTypes; MoneyRequestDescriptionPage.defaultProps = defaultProps; -export default compose( - withLocalize, - withOnyx({ - iou: {key: ONYXKEYS.IOU}, - }), -)(MoneyRequestDescriptionPage); +export default withOnyx({ + iou: { + key: ONYXKEYS.IOU, + }, +})(MoneyRequestDescriptionPage); diff --git a/src/pages/iou/MoneyRequestMerchantPage.js b/src/pages/iou/MoneyRequestMerchantPage.js new file mode 100644 index 000000000000..bec9bcb419f7 --- /dev/null +++ b/src/pages/iou/MoneyRequestMerchantPage.js @@ -0,0 +1,130 @@ +import React, {useEffect, useRef} from 'react'; +import {View} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import PropTypes from 'prop-types'; +import _ from 'underscore'; +import lodashGet from 'lodash/get'; +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 ROUTES from '../../ROUTES'; +import * as IOU from '../../libs/actions/IOU'; +import optionPropTypes from '../../components/optionPropTypes'; +import CONST from '../../CONST'; +import useLocalize from '../../hooks/useLocalize'; + +const propTypes = { + /** Onyx Props */ + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ + iou: PropTypes.shape({ + id: PropTypes.string, + amount: PropTypes.number, + comment: PropTypes.string, + created: PropTypes.string, + merchant: PropTypes.string, + participants: PropTypes.arrayOf(optionPropTypes), + receiptPath: PropTypes.string, + }), + + /** Route from navigation */ + route: PropTypes.shape({ + /** Params from the route */ + params: PropTypes.shape({ + /** Which field we are editing */ + field: PropTypes.string, + + /** reportID for the "transaction thread" */ + threadReportID: PropTypes.string, + }), + }).isRequired, +}; + +const defaultProps = { + iou: { + id: '', + amount: 0, + comment: '', + merchant: '', + participants: [], + receiptPath: '', + }, +}; + +function MoneyRequestMerchantPage({iou, route}) { + const {translate} = useLocalize(); + const inputRef = useRef(null); + const iouType = lodashGet(route, 'params.iouType', ''); + const reportID = lodashGet(route, 'params.reportID', ''); + + useEffect(() => { + const moneyRequestId = `${iouType}${reportID}`; + const shouldReset = iou.id !== moneyRequestId; + if (shouldReset) { + IOU.resetMoneyRequestInfo(moneyRequestId); + } + + if (_.isEmpty(iou.participants) || (iou.amount === 0 && !iou.receiptPath) || shouldReset) { + Navigation.goBack(ROUTES.getMoneyRequestRoute(iouType, reportID), true); + } + }, [iou.id, iou.participants, iou.amount, iou.receiptPath, iouType, reportID]); + + function navigateBack() { + Navigation.goBack(ROUTES.getMoneyRequestConfirmationRoute(iouType, reportID)); + } + + /** + * Sets the money request comment by saving it to Onyx. + * + * @param {Object} value + * @param {String} value.moneyRequestMerchant + */ + function updateMerchant(value) { + IOU.setMoneyRequestMerchant(value.moneyRequestMerchant); + navigateBack(); + } + + return ( + inputRef.current && inputRef.current.focus()} + > + navigateBack()} + /> +
updateMerchant(value)} + submitButtonText={translate('common.save')} + enabledWhenOffline + > + + (inputRef.current = el)} + /> + +
+
+ ); +} + +MoneyRequestMerchantPage.propTypes = propTypes; +MoneyRequestMerchantPage.defaultProps = defaultProps; + +export default withOnyx({ + iou: { + key: ONYXKEYS.IOU, + }, +})(MoneyRequestMerchantPage); diff --git a/src/pages/iou/ReceiptSelector/index.native.js b/src/pages/iou/ReceiptSelector/index.native.js index 7eeab6e493bd..730e5d1e1dfb 100644 --- a/src/pages/iou/ReceiptSelector/index.native.js +++ b/src/pages/iou/ReceiptSelector/index.native.js @@ -38,7 +38,9 @@ const propTypes = { iou: PropTypes.shape({ id: PropTypes.string, amount: PropTypes.number, - currency: PropTypes.string, + comment: PropTypes.string, + created: PropTypes.string, + merchant: PropTypes.string, participants: PropTypes.arrayOf(participantPropTypes), }), }; @@ -54,6 +56,8 @@ const defaultProps = { iou: { id: '', amount: 0, + merchant: '', + created: '', currency: CONST.CURRENCY.USD, participants: [], }, diff --git a/src/pages/iou/steps/MoneyRequestConfirmPage.js b/src/pages/iou/steps/MoneyRequestConfirmPage.js index a81e3a8bf825..c22a81cd7299 100644 --- a/src/pages/iou/steps/MoneyRequestConfirmPage.js +++ b/src/pages/iou/steps/MoneyRequestConfirmPage.js @@ -30,9 +30,10 @@ const propTypes = { iou: PropTypes.shape({ id: PropTypes.string, amount: PropTypes.number, - receiptPath: PropTypes.string, - currency: PropTypes.string, comment: PropTypes.string, + created: PropTypes.string, + currency: PropTypes.string, + merchant: PropTypes.string, participants: PropTypes.arrayOf( PropTypes.shape({ accountID: PropTypes.number, @@ -42,6 +43,7 @@ const propTypes = { selected: PropTypes.bool, }), ), + receiptPath: PropTypes.string, }), /** Personal details of all users */ @@ -58,6 +60,8 @@ const defaultProps = { amount: 0, currency: CONST.CURRENCY.USD, comment: '', + merchant: '', + created: '', participants: [], }, ...withCurrentUserPersonalDetailsDefaultProps, @@ -130,6 +134,8 @@ function MoneyRequestConfirmPage(props) { props.report, props.iou.amount, props.iou.currency, + props.iou.created, + props.iou.merchant, props.currentUserPersonalDetails.login, props.currentUserPersonalDetails.accountID, selectedParticipants[0], @@ -137,7 +143,7 @@ function MoneyRequestConfirmPage(props) { receipt, ); }, - [props.report, props.iou.amount, props.iou.currency, props.currentUserPersonalDetails.login, props.currentUserPersonalDetails.accountID], + [props.report, props.iou.amount, props.iou.currency, props.iou.created, props.iou.merchant, props.currentUserPersonalDetails.login, props.currentUserPersonalDetails.accountID], ); const createTransaction = useCallback( @@ -259,8 +265,7 @@ function MoneyRequestConfirmPage(props) { policyID={props.report.policyID} bankAccountRoute={ReportUtils.getBankAccountRoute(props.report)} iouMerchant={props.iou.merchant} - iouModifiedMerchant={props.iou.modifiedMerchant} - iouDate={props.iou.date} + iouCreated={props.iou.created} />
)} diff --git a/src/pages/iou/steps/NewRequestAmountPage.js b/src/pages/iou/steps/NewRequestAmountPage.js index 6eda79654e77..e0199d72b01a 100644 --- a/src/pages/iou/steps/NewRequestAmountPage.js +++ b/src/pages/iou/steps/NewRequestAmountPage.js @@ -37,6 +37,8 @@ const propTypes = { id: PropTypes.string, amount: PropTypes.number, currency: PropTypes.string, + merchant: PropTypes.string, + created: PropTypes.string, participants: PropTypes.arrayOf( PropTypes.shape({ accountID: PropTypes.number, @@ -60,6 +62,8 @@ const defaultProps = { iou: { id: '', amount: 0, + created: '', + merchant: '', currency: CONST.CURRENCY.USD, participants: [], }, diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.js b/src/pages/tasks/TaskAssigneeSelectorModal.js index 4803fc5b200e..37f9d8815324 100644 --- a/src/pages/tasks/TaskAssigneeSelectorModal.js +++ b/src/pages/tasks/TaskAssigneeSelectorModal.js @@ -76,6 +76,7 @@ function TaskAssigneeSelectorModal(props) { const [filteredPersonalDetails, setFilteredPersonalDetails] = useState([]); const [filteredUserToInvite, setFilteredUserToInvite] = useState(null); const [filteredCurrentUserOption, setFilteredCurrentUserOption] = useState(null); + const [isLoading, setIsLoading] = React.useState(true); const updateOptions = useCallback(() => { const {recentReports, personalDetails, userToInvite, currentUserOption} = OptionsListUtils.getNewChatOptions( @@ -94,7 +95,10 @@ function TaskAssigneeSelectorModal(props) { setFilteredRecentReports(recentReports); setFilteredPersonalDetails(personalDetails); setFilteredCurrentUserOption(currentUserOption); - }, [props, searchValue]); + if (isLoading) { + setIsLoading(false); + } + }, [props, searchValue, isLoading]); useEffect(() => { const debouncedSearch = _.debounce(updateOptions, 200); @@ -195,7 +199,7 @@ function TaskAssigneeSelectorModal(props) { onChangeText={onChangeText} headerMessage={headerMessage} showTitleTooltip - shouldShowOptions={didScreenTransitionEnd} + shouldShowOptions={didScreenTransitionEnd && !isLoading} textInputLabel={props.translate('optionsSelector.nameEmailOrPhoneNumber')} safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle} /> diff --git a/tests/actions/IOUTest.js b/tests/actions/IOUTest.js index 93648aa8ea74..bf32c2ef8f9a 100644 --- a/tests/actions/IOUTest.js +++ b/tests/actions/IOUTest.js @@ -35,12 +35,13 @@ describe('actions/IOU', () => { it('creates new chat if needed', () => { const amount = 10000; const comment = 'Giv money plz'; + const merchant = 'KFC'; let iouReportID; let createdAction; let iouAction; let transactionID; fetch.pause(); - IOU.requestMoney({}, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); + IOU.requestMoney({}, amount, CONST.CURRENCY.USD, '', merchant, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); return waitForPromisesToResolve() .then( () => @@ -141,7 +142,7 @@ describe('actions/IOU', () => { // The transactionID on the iou action should match the one from the transactions collection expect(iouAction.originalMessage.IOUTransactionID).toBe(transactionID); - expect(transaction.merchant).toBe(CONST.REPORT.TYPE.IOU); + expect(transaction.merchant).toBe(merchant); resolve(); }, @@ -205,7 +206,7 @@ describe('actions/IOU', () => { }), ) .then(() => { - IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); + IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); return waitForPromisesToResolve(); }) .then( @@ -396,7 +397,7 @@ describe('actions/IOU', () => { ) .then(() => Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${existingTransaction.transactionID}`, existingTransaction)) .then(() => { - IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); + IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); return waitForPromisesToResolve(); }) .then( @@ -528,7 +529,7 @@ describe('actions/IOU', () => { let iouAction; let transactionID; fetch.pause(); - IOU.requestMoney({}, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); + IOU.requestMoney({}, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); return ( waitForPromisesToResolve() .then( @@ -1183,7 +1184,7 @@ describe('actions/IOU', () => { let createIOUAction; let payIOUAction; let transaction; - IOU.requestMoney({}, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); + IOU.requestMoney({}, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); return waitForPromisesToResolve() .then( () =>