Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create DeleteMoneyRequest command #17583

Merged
merged 28 commits into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6077316
rename cancelMoneyRequest to deleteMoneyRequest
luacmartins Apr 18, 2023
37985d3
fix typo
luacmartins Apr 18, 2023
7dc4e9a
add system message for deleted request
luacmartins Apr 18, 2023
cd46125
rm type param, update logic in updateIOUOwnerAndTotal, change error copy
luacmartins Apr 18, 2023
e69ab36
rename debtor to payer
luacmartins Apr 18, 2023
37abc13
display delete button
luacmartins Apr 18, 2023
b9a55af
replace hardcoded values with consts
luacmartins Apr 18, 2023
79922e5
update logic for pending deleted request in different currency, rm de…
luacmartins Apr 18, 2023
8a8477e
rm request action and add rollback
luacmartins Apr 18, 2023
5650b4a
revert update amount logic
luacmartins Apr 18, 2023
bf7b439
update comments
luacmartins Apr 18, 2023
2025bcc
fix test
luacmartins Apr 18, 2023
e475190
update comments
luacmartins Apr 18, 2023
d3d9816
update comment
luacmartins Apr 18, 2023
6ff57d3
optimistically rm transaction from onyx
luacmartins Apr 20, 2023
18c7b29
add failure data
luacmartins Apr 20, 2023
1562b43
update var declaration
luacmartins Apr 20, 2023
b62b3ac
update api params
luacmartins Apr 20, 2023
c789367
return early if transaction is null
luacmartins Apr 20, 2023
0459471
leave created iou action
luacmartins Apr 20, 2023
852a080
hide delete button for deleted request
luacmartins Apr 20, 2023
30028e8
lower case iou messages
luacmartins Apr 20, 2023
0145b3d
rename var
luacmartins Apr 24, 2023
67c76f6
address comments
luacmartins Apr 24, 2023
fe87207
rm comment
luacmartins Apr 28, 2023
7eb88dd
dont mutate original object
luacmartins Apr 28, 2023
ab10ad5
resolve conflicts
luacmartins May 2, 2023
14ef884
resolve conflicts
luacmartins May 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,7 @@ const CONST = {
SPLIT: 'split',
DECLINE: 'decline',
CANCEL: 'cancel',
DELETE: 'delete',
},
AMOUNT_MAX_LENGTH: 10,
},
Expand Down
30 changes: 13 additions & 17 deletions src/components/ReportTransaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
}

Expand Down Expand Up @@ -84,13 +80,13 @@ class ReportTransaction extends Component {
{this.props.action.message[0].text}
</Text>
</ReportActionItemSingle>
{this.props.canBeRejected && (
{this.props.canBeDeleted && (
<View style={[styles.flexRow, styles.justifyContentStart]}>
<Button
small
text={this.props.translate(`common.${this.props.rejectButtonType}`)}
text={this.props.translate('common.delete')}
style={[styles.mb3, styles.chatItemComposeSecondaryRowOffset]}
onPress={this.cancelMoneyRequest}
onPress={this.deleteMoneyRequest}
/>
</View>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
2 changes: 1 addition & 1 deletion src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
17 changes: 9 additions & 8 deletions src/libs/IOUUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
*
Expand Down Expand Up @@ -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;
}

Expand Down
23 changes: 10 additions & 13 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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}
Expand Down
72 changes: 51 additions & 21 deletions src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand All @@ -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;
Expand All @@ -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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if the transaction detail view should be pending too, ie if you could still load the page and it would be disabled essentially.

Thats probably too complicated though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably load the page with the optimistic data. Not sure what you mean by disabled?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You ill have a transaction details page with $10 request for example and you will delete this transaction. Now the detailed page (/r/:reportID/t/:transactionID) can still be accessed as the thread, but how will we display it? the transaction data is null so we cannot show anything in the description or amount field.

I assume we will only have to show the original thread

},
];
const successData = [
{
Expand All @@ -607,25 +621,41 @@ function cancelMoneyRequest(chatReportID, iouReportID, type, moneyRequestAction,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`,
value: {
[optimisticReportAction.reportActionID]: {
pendingAction: null,
luacmartins marked this conversation as resolved.
Show resolved Hide resolved
errors: {
[DateUtils.getMicroseconds()]: Localize.translateLocal('iou.error.genericCancelFailureMessage', {type}),
[DateUtils.getMicroseconds()]: Localize.translateLocal('iou.error.genericDeleteFailureMessage'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we forgot to put the error report preview action, which created the issue #33535

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a regression from this PR. We already added the report action in the optimistic data so we didn't need to add it in the failure data.

App/src/libs/actions/IOU.js

Lines 580 to 590 in 14ef884

const optimisticData = [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`,
value: {
[optimisticReportAction.reportActionID]: {
...optimisticReportAction,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
},
},

},
},
},
},
{
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));
}
}
Expand Down Expand Up @@ -1005,7 +1035,7 @@ function payMoneyRequestViaPaypal(chatReport, iouReport, recipient) {
}

export {
cancelMoneyRequest,
deleteMoneyRequest,
splitBill,
splitBillAndOpenReport,
requestMoney,
Expand Down
Loading
Loading