diff --git a/src/CONST.js b/src/CONST.js
index 7215f3b3972a..113911f61c41 100755
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -898,6 +898,7 @@ const CONST = {
SPLIT: 'split',
DECLINE: 'decline',
CANCEL: 'cancel',
+ DELETE: 'delete',
},
AMOUNT_MAX_LENGTH: 10,
},
diff --git a/src/components/ReportTransaction.js b/src/components/ReportTransaction.js
index f80c638a0f58..fe728146e4fa 100644
--- a/src/components/ReportTransaction.js
+++ b/src/components/ReportTransaction.js
@@ -24,37 +24,33 @@ const propTypes = {
/** The report action which we are displaying */
action: PropTypes.shape(reportActionPropTypes).isRequired,
- /** Can this transaction be rejected? */
- canBeRejected: PropTypes.bool,
+ /** Can this transaction be deleted? */
+ canBeDeleted: PropTypes.bool,
- /** Type of the reject transaction button */
- rejectButtonType: PropTypes.oneOf([CONST.IOU.REPORT_ACTION_TYPE.DECLINE, CONST.IOU.REPORT_ACTION_TYPE.CANCEL]).isRequired,
-
- /** Indicates whether pressing the reject button should hide the details sidebar */
- shouldCloseOnReject: PropTypes.bool,
+ /** Indicates whether pressing the delete button should hide the details sidebar */
+ shouldCloseOnDelete: PropTypes.bool,
...withLocalizePropTypes,
};
const defaultProps = {
- canBeRejected: false,
- shouldCloseOnReject: false,
+ canBeDeleted: false,
+ shouldCloseOnDelete: false,
};
class ReportTransaction extends Component {
constructor(props) {
super(props);
- this.cancelMoneyRequest = this.cancelMoneyRequest.bind(this);
+ this.deleteMoneyRequest = this.deleteMoneyRequest.bind(this);
}
- cancelMoneyRequest() {
- IOU.cancelMoneyRequest(
+ deleteMoneyRequest() {
+ IOU.deleteMoneyRequest(
this.props.chatReportID,
this.props.iouReportID,
- this.props.rejectButtonType,
this.props.action,
- this.props.shouldCloseOnReject,
+ this.props.shouldCloseOnDelete,
);
}
@@ -84,13 +80,13 @@ class ReportTransaction extends Component {
{this.props.action.message[0].text}
- {this.props.canBeRejected && (
+ {this.props.canBeDeleted && (
)}
diff --git a/src/languages/en.js b/src/languages/en.js
index 0e7a80620c88..7b45cca7cce8 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -329,7 +329,7 @@ export default {
invalidSplit: 'Split amounts do not equal total amount',
other: 'Unexpected error, please try again later',
genericCreateFailureMessage: 'Unexpected error requesting money, please try again later',
- genericCancelFailureMessage: ({type}) => `Unexpected error ${type === 'decline' ? 'declining' : 'cancelling'} the money request, please try again later`,
+ genericDeleteFailureMessage: 'Unexpected error deleting the money request, please try again later',
},
},
notificationPreferences: {
diff --git a/src/languages/es.js b/src/languages/es.js
index ef28a83e65b3..001687c1df06 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -328,7 +328,7 @@ export default {
invalidSplit: 'La suma de las partes no equivale al monto total',
other: 'Error inesperado, por favor inténtalo más tarde',
genericCreateFailureMessage: 'Error inesperado solicitando dinero, Por favor, inténtalo más tarde',
- genericCancelFailureMessage: ({type}) => `Error inesperado al ${type === 'decline' ? 'rechazar' : 'cancelar'} la solicitud de dinero. Por favor, inténtalo más tarde`,
+ genericDeleteFailureMessage: 'Error inesperado eliminando la solicitud de dinero. Por favor, inténtalo más tarde',
},
},
notificationPreferences: {
diff --git a/src/libs/IOUUtils.js b/src/libs/IOUUtils.js
index 1151f9c77225..1bfdb8f27f91 100644
--- a/src/libs/IOUUtils.js
+++ b/src/libs/IOUUtils.js
@@ -90,12 +90,13 @@ function updateIOUOwnerAndTotal(iouReport, actorEmail, amount, currency, type =
return iouReport;
}
+ // Make a copy so we don't mutate the original object
const iouReportUpdate = {...iouReport};
if (actorEmail === iouReport.ownerEmail) {
- iouReportUpdate.total += type === CONST.IOU.REPORT_ACTION_TYPE.CANCEL ? -amount : amount;
+ iouReportUpdate.total += type === CONST.IOU.REPORT_ACTION_TYPE.DELETE ? -amount : amount;
} else {
- iouReportUpdate.total += type === CONST.IOU.REPORT_ACTION_TYPE.CANCEL ? amount : -amount;
+ iouReportUpdate.total += type === CONST.IOU.REPORT_ACTION_TYPE.DELETE ? amount : -amount;
}
if (iouReportUpdate.total < 0) {
@@ -116,7 +117,7 @@ function updateIOUOwnerAndTotal(iouReport, actorEmail, amount, currency, type =
*
* @param {Array} reportActions
* @param {Object} iouReport
- * @param {String} type - iouReportAction type. Can be oneOf(create, decline, cancel, pay, split)
+ * @param {String} type - iouReportAction type. Can be oneOf(create, delete, pay, split)
* @param {String} pendingAction
* @param {Boolean} filterRequestsInDifferentCurrency
*
@@ -154,22 +155,22 @@ function isIOUReportPendingCurrencyConversion(reportActions, iouReport) {
.sort()
.value();
- // Pending cancelled money requests that are in a different currency
- const pendingCancelledRequestsInDifferentCurrency = _.chain(getIOUReportActions(
+ // Pending deleted money requests that are in a different currency
+ const pendingDeletedRequestsInDifferentCurrency = _.chain(getIOUReportActions(
reportActions,
iouReport,
- CONST.IOU.REPORT_ACTION_TYPE.CANCEL,
+ CONST.IOU.REPORT_ACTION_TYPE.DELETE,
CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
true,
)).map(action => action.originalMessage.IOUTransactionID)
.sort()
.value();
- const hasPendingRequests = Boolean(pendingRequestsInDifferentCurrency.length || pendingCancelledRequestsInDifferentCurrency.length);
+ const hasPendingRequests = Boolean(pendingRequestsInDifferentCurrency.length || pendingDeletedRequestsInDifferentCurrency.length);
// If we have pending money requests made offline, check if all of them have been cancelled offline
// In order to do that, we can grab transactionIDs of all the created and cancelled money requests and check if they're identical
- if (hasPendingRequests && _.isEqual(pendingRequestsInDifferentCurrency, pendingCancelledRequestsInDifferentCurrency)) {
+ if (hasPendingRequests && _.isEqual(pendingRequestsInDifferentCurrency, pendingDeletedRequestsInDifferentCurrency)) {
return false;
}
diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js
index 7e31d7fcc909..90c5ac9643f0 100644
--- a/src/libs/ReportUtils.js
+++ b/src/libs/ReportUtils.js
@@ -1054,7 +1054,7 @@ function buildOptimisticIOUReport(ownerEmail, userEmail, total, chatReportID, cu
}
/**
- * @param {String} type - IOUReportAction type. Can be oneOf(create, decline, cancel, pay, split)
+ * @param {String} type - IOUReportAction type. Can be oneOf(create, delete, pay, split)
* @param {Number} total - IOU total in cents
* @param {Array} participants - List of logins for the IOU participants, excluding the current user login
* @param {String} comment - IOU comment
@@ -1083,21 +1083,18 @@ function getIOUReportActionMessage(type, total, participants, comment, currency,
let iouMessage;
switch (type) {
case CONST.IOU.REPORT_ACTION_TYPE.CREATE:
- iouMessage = `Requested ${amount}${comment && ` for ${comment}`}`;
+ iouMessage = `requested ${amount}${comment && ` for ${comment}`}`;
break;
case CONST.IOU.REPORT_ACTION_TYPE.SPLIT:
- iouMessage = `Split ${amount}${comment && ` for ${comment}`}`;
+ iouMessage = `split ${amount}${comment && ` for ${comment}`}`;
break;
- case CONST.IOU.REPORT_ACTION_TYPE.CANCEL:
- iouMessage = `Cancelled the ${amount} request${comment && ` for ${comment}`}`;
- break;
- case CONST.IOU.REPORT_ACTION_TYPE.DECLINE:
- iouMessage = `Declined the ${amount} request${comment && ` for ${comment}`}`;
+ case CONST.IOU.REPORT_ACTION_TYPE.DELETE:
+ iouMessage = `deleted the ${amount} request${comment && ` for ${comment}`}`;
break;
case CONST.IOU.REPORT_ACTION_TYPE.PAY:
iouMessage = isSettlingUp
- ? `Settled up ${amount}${paymentMethodMessage}`
- : `Sent ${amount}${comment && ` for ${comment}`}${paymentMethodMessage}`;
+ ? `settled up ${amount}${paymentMethodMessage}`
+ : `sent ${amount}${comment && ` for ${comment}`}${paymentMethodMessage}`;
break;
default:
break;
@@ -1114,14 +1111,14 @@ function getIOUReportActionMessage(type, total, participants, comment, currency,
/**
* Builds an optimistic IOU reportAction object
*
- * @param {String} type - IOUReportAction type. Can be oneOf(create, decline, cancel, pay, split).
+ * @param {String} type - IOUReportAction type. Can be oneOf(create, delete, pay, split).
* @param {Number} amount - IOU amount in cents.
* @param {String} currency
* @param {String} comment - User comment for the IOU.
* @param {Array} participants - An array with participants details.
* @param {String} [paymentType] - Only required if the IOUReportAction type is 'pay'. Can be oneOf(elsewhere, payPal, Expensify).
- * @param {String} [iouTransactionID] - Only required if the IOUReportAction type is oneOf(cancel, decline). Generates a randomID as default.
- * @param {String} [iouReportID] - Only required if the IOUReportActions type is oneOf(decline, cancel, pay). Generates a randomID as default.
+ * @param {String} [iouTransactionID] - Only required if the IOUReportAction type is 'delete'. Generates a randomID as default.
+ * @param {String} [iouReportID] - Only required if the IOUReportActions type is oneOf(delete, pay). Generates a randomID as default.
* @param {Boolean} [isSettlingUp] - Whether we are settling up an IOU.
*
* @returns {Object}
diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js
index 0ee5f59f5b26..6dbd7ec6de3f 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.js
@@ -30,6 +30,18 @@ Onyx.connect({
},
});
+let transactions = {};
+Onyx.connect({
+ key: ONYXKEYS.COLLECTION.TRANSACTION,
+ waitForCollectionCallback: true,
+ callback: (val) => {
+ if (!val) {
+ return;
+ }
+ transactions = val;
+ },
+});
+
let preferredLocale = CONST.LOCALES.DEFAULT;
Onyx.connect({
key: ONYXKEYS.NVP_PREFERRED_LOCALE,
@@ -534,24 +546,22 @@ function splitBillAndOpenReport(participants, currentUserLogin, amount, comment,
}
/**
- * Cancels or declines a transaction in iouReport.
- * Declining and cancelling transactions are done via the same Auth command.
- *
* @param {String} chatReportID
* @param {String} iouReportID
- * @param {String} type - cancel|decline
- * @param {Object} moneyRequestAction - the create IOU reportAction we are cancelling
- * @param {Boolean} shouldCloseOnReject
+ * @param {Object} moneyRequestAction - the money request reportAction we are deleting
+ * @param {Boolean} shouldCloseOnDelete
*/
-function cancelMoneyRequest(chatReportID, iouReportID, type, moneyRequestAction, shouldCloseOnReject) {
- const chatReport = chatReports[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`];
+function deleteMoneyRequest(chatReportID, iouReportID, moneyRequestAction, shouldCloseOnDelete) {
const iouReport = iouReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`];
const transactionID = moneyRequestAction.originalMessage.IOUTransactionID;
- // Get the amount we are cancelling
+ // Make a copy of the chat report so we don't mutate the original one when updating its values
+ const chatReport = {...chatReports[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`]};
+
+ // Get the amount we are deleting
const amount = moneyRequestAction.originalMessage.amount;
const optimisticReportAction = ReportUtils.buildOptimisticIOUReportAction(
- type,
+ CONST.IOU.REPORT_ACTION_TYPE.DELETE,
amount,
moneyRequestAction.originalMessage.currency,
Str.htmlDecode(moneyRequestAction.originalMessage.comment),
@@ -562,8 +572,7 @@ function cancelMoneyRequest(chatReportID, iouReportID, type, moneyRequestAction,
);
const currentUserEmail = optimisticReportAction.actorEmail;
- const updatedIOUReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, currentUserEmail, amount, moneyRequestAction.originalMessage.currency, type);
-
+ const updatedIOUReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, currentUserEmail, amount, moneyRequestAction.originalMessage.currency, CONST.IOU.REPORT_ACTION_TYPE.DELETE);
chatReport.lastMessageText = optimisticReportAction.message[0].text;
chatReport.lastMessageHtml = optimisticReportAction.message[0].html;
chatReport.hasOutstandingIOU = updatedIOUReport.total !== 0;
@@ -589,6 +598,11 @@ function cancelMoneyRequest(chatReportID, iouReportID, type, moneyRequestAction,
key: `${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`,
value: updatedIOUReport,
},
+ {
+ onyxMethod: CONST.ONYX.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
+ value: null,
+ },
];
const successData = [
{
@@ -607,25 +621,41 @@ function cancelMoneyRequest(chatReportID, iouReportID, type, moneyRequestAction,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`,
value: {
[optimisticReportAction.reportActionID]: {
- pendingAction: null,
errors: {
- [DateUtils.getMicroseconds()]: Localize.translateLocal('iou.error.genericCancelFailureMessage', {type}),
+ [DateUtils.getMicroseconds()]: Localize.translateLocal('iou.error.genericDeleteFailureMessage'),
},
},
},
},
+ {
+ onyxMethod: CONST.ONYX.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`,
+ value: {
+ lastMessageText: chatReports[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`].lastMessageText,
+ lastMessageHtml: chatReports[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`].lastMessageHtml,
+ hasOutstandingIOU: iouReport.total !== 0,
+ },
+ },
+ {
+ onyxMethod: CONST.ONYX.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`,
+ value: iouReport,
+ },
+ {
+ onyxMethod: CONST.ONYX.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
+ value: transactions[transactionID],
+ },
];
- API.write('CancelMoneyRequest', {
+ API.write('DeleteMoneyRequest', {
transactionID,
- iouReportID: updatedIOUReport.reportID,
- comment: '',
- cancelMoneyRequestReportActionID: optimisticReportAction.reportActionID,
chatReportID,
- debtorEmail: chatReport.participants[0],
+ reportActionID: optimisticReportAction.reportActionID,
+ iouReportID: updatedIOUReport.reportID,
}, {optimisticData, successData, failureData});
- if (shouldCloseOnReject) {
+ if (shouldCloseOnDelete) {
Navigation.navigate(ROUTES.getReportRoute(chatReportID));
}
}
@@ -1005,7 +1035,7 @@ function payMoneyRequestViaPaypal(chatReport, iouReport, recipient) {
}
export {
- cancelMoneyRequest,
+ deleteMoneyRequest,
splitBill,
splitBillAndOpenReport,
requestMoney,
diff --git a/src/pages/iou/IOUTransactions.js b/src/pages/iou/IOUTransactions.js
index 7721a68e541c..e719a1a8965c 100644
--- a/src/pages/iou/IOUTransactions.js
+++ b/src/pages/iou/IOUTransactions.js
@@ -37,17 +37,17 @@ class IOUTransactions extends Component {
constructor(props) {
super(props);
- this.getRejectableTransactions = this.getRejectableTransactions.bind(this);
+ this.getDeletableTransactions = this.getDeletableTransactions.bind(this);
}
/**
- * Builds and returns the rejectableTransactionIDs array. A transaction must meet multiple requirements in order
- * to be rejectable. We must exclude transactions not associated with the iouReportID, actions which have already
- * been rejected, and those which are not of type 'create'.
+ * Builds and returns the deletableTransactionIDs array. A transaction must meet multiple requirements in order
+ * to be deletable. We must exclude transactions not associated with the iouReportID, actions which have already
+ * been deleted, and those which are not of type 'create'.
*
* @returns {Array}
*/
- getRejectableTransactions() {
+ getDeletableTransactions() {
if (this.props.isIOUSettled) {
return [];
}
@@ -56,15 +56,16 @@ class IOUTransactions extends Component {
const actionsForIOUReport = _.filter(this.props.reportActions, action => action.originalMessage
&& action.originalMessage.type && Number(action.originalMessage.IOUReportID) === Number(this.props.iouReportID));
- const rejectedTransactionIDs = _.chain(actionsForIOUReport)
- .filter(action => _.contains(['cancel', 'decline'], action.originalMessage.type))
- .map(rejectedAction => lodashGet(rejectedAction, 'originalMessage.IOUTransactionID', ''))
+ const deletedTransactionIDs = _.chain(actionsForIOUReport)
+ .filter(action => _.contains([CONST.IOU.REPORT_ACTION_TYPE.CANCEL, CONST.IOU.REPORT_ACTION_TYPE.DECLINE, CONST.IOU.REPORT_ACTION_TYPE.DELETE], action.originalMessage.type))
+ .map(deletedAction => lodashGet(deletedAction, 'originalMessage.IOUTransactionID', ''))
.compact()
.value();
return _.chain(actionsForIOUReport)
- .filter(action => action.originalMessage.type === 'create')
- .filter(action => !_.contains(rejectedTransactionIDs, action.originalMessage.IOUTransactionID))
+ .filter(action => action.originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.CREATE)
+ .filter(action => !_.contains(deletedTransactionIDs, action.originalMessage.IOUTransactionID))
+ .filter(action => this.props.userEmail === action.actorEmail)
.map(action => lodashGet(action, 'originalMessage.IOUTransactionID', ''))
.compact()
.value();
@@ -80,10 +81,9 @@ class IOUTransactions extends Component {
return;
}
- const rejectableTransactions = this.getRejectableTransactions();
- const canBeRejected = _.contains(rejectableTransactions,
+ const deletableTransactions = this.getDeletableTransactions();
+ const canBeDeleted = _.contains(deletableTransactions,
reportAction.originalMessage.IOUTransactionID);
- const isCurrentUserTransactionCreator = this.props.userEmail === reportAction.actorEmail;
return (
);
})}
diff --git a/tests/unit/IOUUtilsTest.js b/tests/unit/IOUUtilsTest.js
index 4ae4f3c5bc4b..025b08705456 100644
--- a/tests/unit/IOUUtilsTest.js
+++ b/tests/unit/IOUUtilsTest.js
@@ -30,9 +30,9 @@ function createIOUReportAction(type, amount, currency, {IOUTransactionID, isOnli
return moneyRequestAction;
}
-function cancelMoneyRequest(moneyRequestAction, {isOnline} = {}) {
+function deleteMoneyRequest(moneyRequestAction, {isOnline} = {}) {
createIOUReportAction(
- 'cancel',
+ CONST.IOU.REPORT_ACTION_TYPE.DELETE,
moneyRequestAction.originalMessage.amount,
moneyRequestAction.originalMessage.currency,
{
@@ -81,66 +81,66 @@ describe('isIOUReportPendingCurrencyConversion', () => {
expect(IOUUtils.isIOUReportPendingCurrencyConversion(reportActions, iouReport)).toBe(true);
});
- test('IOUReport is not pending conversion when all requests made offline have been cancelled', () => {
+ test('IOUReport is not pending conversion when all requests made offline have been deleted', () => {
// Create two requests offline
const moneyRequestA = createIOUReportAction('create', 1000, 'AED');
const moneyRequestB = createIOUReportAction('create', 1000, 'AED');
- // Cancel both requests
- cancelMoneyRequest(moneyRequestA);
- cancelMoneyRequest(moneyRequestB);
+ // Delete both requests
+ deleteMoneyRequest(moneyRequestA);
+ deleteMoneyRequest(moneyRequestB);
- // Both requests made offline have been cancelled, total won't update so no need to show a pending conversion message
+ // Both requests made offline have been deleted, total won't update so no need to show a pending conversion message
expect(IOUUtils.isIOUReportPendingCurrencyConversion(reportActions, iouReport)).toBe(false);
});
- test('Cancelling a request made online shows the preview', () => {
+ test('Deleting a request made online shows the preview', () => {
// Request money online in AED
const moneyRequest = createIOUReportAction('create', 1000, 'AED', {isOnline: true});
- // Cancel it offline
- cancelMoneyRequest(moneyRequest);
+ // Delete it offline
+ deleteMoneyRequest(moneyRequest);
// We don't know what the total is because we need to subtract the converted amount of the offline request from the total
expect(IOUUtils.isIOUReportPendingCurrencyConversion(reportActions, iouReport)).toBe(true);
});
- test('Cancelling a request made offline while there\'s a previous one made online will not show the pending conversion message', () => {
+ test('Deleting a request made offline while there\'s a previous one made online will not show the pending conversion message', () => {
// Request money online in AED
createIOUReportAction('create', 1000, 'AED', {isOnline: true});
// Another request offline
const moneyRequestOffline = createIOUReportAction('create', 1000, 'AED');
- // Cancel the request made offline
- cancelMoneyRequest(moneyRequestOffline);
+ // Delete the request made offline
+ deleteMoneyRequest(moneyRequestOffline);
expect(IOUUtils.isIOUReportPendingCurrencyConversion(reportActions, iouReport)).toBe(false);
});
- test('Cancelling a request made online while we have one made offline will show the pending conversion message', () => {
+ test('Deleting a request made online while we have one made offline will show the pending conversion message', () => {
// Request money online in AED
const moneyRequestOnline = createIOUReportAction('create', 1000, 'AED', {isOnline: true});
// Requet money again but offline
createIOUReportAction('create', 1000, 'AED');
- // Cancel the request made online
- cancelMoneyRequest(moneyRequestOnline);
+ // Delete the request made online
+ deleteMoneyRequest(moneyRequestOnline);
// We don't know what the total is because we need to subtract the converted amount of the offline request from the total
expect(IOUUtils.isIOUReportPendingCurrencyConversion(reportActions, iouReport)).toBe(true);
});
- test('Cancelling a request offline in the report\'s currency when we have requests in a different currency does not show the pending conversion message', () => {
+ test('Deleting a request offline in the report\'s currency when we have requests in a different currency does not show the pending conversion message', () => {
// Request money in the report's curreny (USD)
const onlineMoneyRequestInUSD = createIOUReportAction('create', 1000, 'USD', {isOnline: true});
// Request money online in a different currency
createIOUReportAction('create', 2000, 'AED', {isOnline: true});
- // Cancel the USD request offline
- cancelMoneyRequest(onlineMoneyRequestInUSD);
+ // Delete the USD request offline
+ deleteMoneyRequest(onlineMoneyRequestInUSD);
expect(IOUUtils.isIOUReportPendingCurrencyConversion(reportActions, iouReport)).toBe(false);
});