Skip to content

Commit

Permalink
Merge pull request #4329 from Expensify/vit-createAndPayIOU
Browse files Browse the repository at this point in the history
Adjusting IOUModal and adding createAndPayIOU
  • Loading branch information
Nicholas Murray authored Dec 27, 2021
2 parents 7116b6e + ca34f19 commit 149ed21
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 31 deletions.
7 changes: 5 additions & 2 deletions src/components/IOUConfirmationList.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const propTypes = {
/** Callback to inform parent modal of success */
onConfirm: PropTypes.func.isRequired,

/** Callback to to parent modal to send money */
onSendMoney: PropTypes.func.isRequired,

// Callback to update comment from IOUModal
onUpdateComment: PropTypes.func,

Expand Down Expand Up @@ -149,7 +152,7 @@ class IOUConfirmationList extends Component {
onPress(value) {
if (this.props.iouType === CONST.IOU.IOU_TYPE.SEND) {
Log.info(`[IOU] Sending money via: ${value}`);
this.props.onConfirm();
this.props.onSendMoney(value);
} else {
Log.info(`[IOU] Requesting money via: ${value}`);
this.props.onConfirm(this.getSplits());
Expand Down Expand Up @@ -387,7 +390,7 @@ class IOUConfirmationList extends Component {
onPress={this.onPress}
shouldShowPaypal={Boolean(recipient.payPalMeAddress)}
recipientPhoneNumber={recipient.phoneNumber}
currency={this.props.localCurrencyCode}
currency={this.props.iou.selectedCurrencyCode}
/>
) : (
<ButtonWithMenu
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ function Graphite_Timer(parameters) {
* @param {Object} parameters
* @param {Number} parameters.reportID
* @param {String} parameters.paymentMethodType
* @param {Object} [parameters.newIOUReportDetails]
* @returns {Promise}
*/
function PayIOU(parameters) {
Expand All @@ -541,6 +542,7 @@ function PayIOU(parameters) {
/**
* @param {Object} parameters
* @param {Number} parameters.reportID
* @param {Object} [parameters.newIOUReportDetails]
* @returns {Promise}
*/
function PayWithWallet(parameters) {
Expand Down
33 changes: 25 additions & 8 deletions src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,25 +246,36 @@ function buildPayPalPaymentUrl(amount, submitterPayPalMeAddress, currency) {
* @param {String} params.paymentMethodType - one of CONST.IOU.PAYMENT_TYPE
* @param {Number} params.amount
* @param {String} params.currency
* @param {String} [params.submitterPhoneNumber] - used for Venmo
* @param {String} [params.submitterPayPalMeAddress]
* @param {String} [params.requestorPhoneNumber] - used for Venmo
* @param {String} [params.requestorPayPalMeAddress]
* @param {String} [params.newIOUReportDetails] - Extra details required only for send money flow
* @param {Boolean} [params.shouldRedirectToChatReport]
*/
function payIOUReport({
chatReportID, reportID, paymentMethodType, amount, currency, submitterPhoneNumber, submitterPayPalMeAddress,
chatReportID,
reportID,
paymentMethodType,
amount,
currency,
requestorPhoneNumber,
requestorPayPalMeAddress,
newIOUReportDetails,
shouldRedirectToChatReport = false,
}) {
Onyx.merge(ONYXKEYS.IOU, {loading: true, error: false});

const payIOUPromise = paymentMethodType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY
? API.PayWithWallet({reportID})
: API.PayIOU({reportID, paymentMethodType});
? API.PayWithWallet({reportID, newIOUReportDetails})
: API.PayIOU({reportID, paymentMethodType, newIOUReportDetails});

// Build the url for the user's platform of choice if they have
// selected something other than a manual settlement or Expensify Wallet e.g. Venmo or PayPal.me
let url;
if (paymentMethodType === CONST.IOU.PAYMENT_TYPE.PAYPAL_ME) {
url = buildPayPalPaymentUrl(amount, submitterPayPalMeAddress, currency);
url = buildPayPalPaymentUrl(amount, requestorPayPalMeAddress, currency);
}
if (paymentMethodType === CONST.IOU.PAYMENT_TYPE.VENMO) {
url = buildVenmoPaymentURL(amount, submitterPhoneNumber);
url = buildVenmoPaymentURL(amount, requestorPhoneNumber);
}

asyncOpenURL(payIOUPromise
Expand All @@ -291,7 +302,13 @@ function payIOUReport({
}
Onyx.merge(ONYXKEYS.IOU, {error: true});
})
.finally(() => Onyx.merge(ONYXKEYS.IOU, {loading: false})),
.finally(() => {
Onyx.merge(ONYXKEYS.IOU, {loading: false});

if (shouldRedirectToChatReport) {
Navigation.navigate(ROUTES.REPORT);
}
}),
url);
}

Expand Down
77 changes: 60 additions & 17 deletions src/pages/iou/IOUModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class IOUModal extends Component {
this.addParticipants = this.addParticipants.bind(this);
this.createTransaction = this.createTransaction.bind(this);
this.updateComment = this.updateComment.bind(this);
this.sendMoney = this.sendMoney.bind(this);
const participants = lodashGet(props, 'report.participants', []);
const participantsWithDetails = _.map(OptionsListUtils.getPersonalDetailsForLogins(participants, props.personalDetails), personalDetails => ({
login: personalDetails.login,
Expand All @@ -121,8 +122,6 @@ class IOUModal extends Component {
payPalMeAddress: lodashGet(personalDetails, 'payPalMeAddress', ''),
phoneNumber: lodashGet(personalDetails, 'phoneNumber', ''),
}));
this.isSendRequest = props.iouType === CONST.IOU.IOU_TYPE.SEND;
this.hasGoldWallet = props.userWallet.tierName && props.userWallet.tiername === CONST.WALLET.TIER_NAME.GOLD;

this.state = {
previousStepIndex: 0,
Expand Down Expand Up @@ -192,14 +191,15 @@ class IOUModal extends Component {
*/
getTitleForStep() {
const currentStepIndex = this.state.currentStepIndex;
const isSendingMoney = this.props.iouType === CONST.IOU.IOU_TYPE.SEND;
if (currentStepIndex === 1 || currentStepIndex === 2) {
const formattedAmount = this.props.numberFormat(
this.state.amount, {
style: 'currency',
currency: this.props.iou.selectedCurrencyCode,
},
);
if (this.isSendRequest) {
if (isSendingMoney) {
return this.props.translate('iou.send', {
amount: formattedAmount,
});
Expand All @@ -211,7 +211,7 @@ class IOUModal extends Component {
);
}
if (currentStepIndex === 0) {
if (this.isSendRequest) {
if (isSendingMoney) {
return this.props.translate('iou.sendMoney');
}
return this.props.translate(this.props.hasMultipleParticipants ? 'iou.splitBill' : 'iou.requestMoney');
Expand All @@ -220,6 +220,22 @@ class IOUModal extends Component {
return this.props.translate(this.steps[currentStepIndex]) || '';
}

/**
* Update comment whenever user enters any new text
*
* @param {String} comment
*/
updateComment(comment) {
this.setState({
comment,
});
}

/**
* Update participants whenever user selects the payment recipient
*
* @param {Array} participants
*/
addParticipants(participants) {
this.setState({
participants,
Expand All @@ -246,35 +262,61 @@ class IOUModal extends Component {
if (this.state.currentStepIndex >= this.steps.length - 1) {
return;
}

this.setState(prevState => ({
previousStepIndex: prevState.currentStepIndex,
currentStepIndex: prevState.currentStepIndex + 1,
}));
}

/**
* Update comment whenever user enters any new text
* Checks if user has a GOLD wallet then creates a paid IOU report on the fly
*
* @param {String} comment
* @param {String} paymentMethodType
*/
updateComment(comment) {
this.setState({
sendMoney(paymentMethodType) {
const hasGoldWallet = this.props.userWallet.tierName && this.props.userWallet.tierName === CONST.WALLET.TIER_NAME.GOLD;

// If the user is trying to send money, then they need to upgrade to a GOLD wallet
if (!hasGoldWallet) {
Navigation.navigate(ROUTES.IOU_ENABLE_PAYMENTS);
return;
}

const amount = Math.round(this.state.amount * 100);
const currency = this.props.iou.selectedCurrencyCode;
const comment = this.state.comment;

const newIOUReportDetails = JSON.stringify({
amount,
currency,
requestorEmail: this.state.participants[0].login,
comment,
idempotencyKey: Str.guid(),
});

IOU.payIOUReport({
chatReportID: lodashGet(this.props, 'route.params.reportID', ''),
reportID: 0,
paymentMethodType,
amount,
currency,
requestorPayPalMeAddress: this.state.participants[0].payPalMeAddress,
requestorPhoneNumber: this.state.participants[0].phoneNumber,
comment,
newIOUReportDetails,
shouldRedirectToChatReport: true,
});
}

/**
* Create the IOU transaction
*
* @param {Array} [splits]
*/
createTransaction(splits) {
const reportID = lodashGet(this.props, 'route.params.reportID', '');

// If the user is trying to send money, then they need to upgrade to a GOLD wallet
if (this.isSendRequest && !this.hasGoldWallet) {
Navigation.navigate(ROUTES.IOU_ENABLE_PAYMENTS);
return;
}

// Only splits from a group DM has a reportID
// Check if reportID is a number
if (splits && CONST.REGEX.NUMBER.test(reportID)) {
Expand All @@ -289,11 +331,12 @@ class IOUModal extends Component {
});
return;
}

if (splits) {
IOU.createIOUSplit({
comment: this.state.comment,

// should send in cents to API
// Send in cents to API.
amount: Math.round(this.state.amount * 100),
currency: this.props.iou.selectedCurrencyCode,
splits,
Expand All @@ -304,7 +347,7 @@ class IOUModal extends Component {
IOU.createIOUTransaction({
comment: this.state.comment,

// should send in cents to API
// Send in cents to API.
amount: Math.round(this.state.amount * 100),
currency: this.props.iou.selectedCurrencyCode,
debtorEmail: OptionsListUtils.addSMSDomainIfPhoneNumber(this.state.participants[0].login),
Expand Down Expand Up @@ -397,13 +440,13 @@ class IOUModal extends Component {
>
<IOUConfirmPage
onConfirm={this.createTransaction}
onSendMoney={this.sendMoney}
hasMultipleParticipants={this.props.hasMultipleParticipants}
participants={this.state.participants}
iouAmount={this.state.amount}
comment={this.state.comment}
onUpdateComment={this.updateComment}
iouType={this.props.iouType}
localCurrencyCode={this.props.myPersonalDetails.localCurrencyCode}
isGroupSplit={this.steps.length === 2}
/>
</AnimatedStep>
Expand Down
8 changes: 4 additions & 4 deletions src/pages/iou/steps/IOUConfirmPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const propTypes = {
/** Callback to inform parent modal of success */
onConfirm: PropTypes.func.isRequired,

/** Callback to to parent modal to send money */
onSendMoney: PropTypes.func.isRequired,

/** Callback to update comment from IOUModal */
onUpdateComment: PropTypes.func,

Expand All @@ -19,8 +22,6 @@ const propTypes = {
/** IOU amount */
iouAmount: PropTypes.string.isRequired,

localCurrencyCode: PropTypes.string,

/** Selected participants from IOUMOdal with login */
participants: PropTypes.arrayOf(PropTypes.shape({
login: PropTypes.string.isRequired,
Expand Down Expand Up @@ -49,7 +50,6 @@ const defaultProps = {
onUpdateComment: null,
comment: '',
iouType: CONST.IOU.IOU_TYPE.REQUEST,
localCurrencyCode: CONST.CURRENCY.USD,
};

const IOUConfirmPage = props => (
Expand All @@ -60,8 +60,8 @@ const IOUConfirmPage = props => (
onUpdateComment={props.onUpdateComment}
iouAmount={props.iouAmount}
onConfirm={props.onConfirm}
onSendMoney={props.onSendMoney}
iouType={props.iouType}
localCurrencyCode={props.localCurrencyCode}
isGroupSplit={props.isGroupSplit}
/>
);
Expand Down
2 changes: 2 additions & 0 deletions src/pages/iou/steps/IOUParticipantsPage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const propTypes = {
isPinned: PropTypes.bool,
isUnread: PropTypes.bool,
reportID: PropTypes.number,
phoneNumber: PropTypes.string,
payPalMeAddress: PropTypes.string,
})),

/* Onyx Props */
Expand Down

0 comments on commit 149ed21

Please sign in to comment.