Skip to content

Commit

Permalink
Merge pull request #20821 from Expensify/nat-iouw
Browse files Browse the repository at this point in the history
Handle isWaitingOnBankAccount for IOU requests
  • Loading branch information
luacmartins authored Jul 25, 2023
2 parents abfbefa + 6462b40 commit cd86b16
Show file tree
Hide file tree
Showing 26 changed files with 354 additions and 160 deletions.
1 change: 1 addition & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ const CONST = {
TASKEDITED: 'TASKEDITED',
TASKCANCELLED: 'TASKCANCELLED',
IOU: 'IOU',
REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED',
RENAMED: 'RENAMED',
CHRONOSOOOLIST: 'CHRONOSOOOLIST',
TASKCOMPLETED: 'TASKCOMPLETED',
Expand Down
2 changes: 1 addition & 1 deletion src/components/AddPlaidBankAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class AddPlaidBankAccount extends React.Component {
token={token}
onSuccess={({publicToken, metadata}) => {
Log.info('[PlaidLink] Success!');
BankAccounts.openPlaidBankAccountSelector(publicToken, metadata.institution.name, this.props.allowDebit);
BankAccounts.openPlaidBankAccountSelector(publicToken, metadata.institution.name, this.props.allowDebit, this.props.bankAccountID);
}}
onError={(error) => {
Log.hmmm('[PlaidLink] Error: ', error.message);
Expand Down
3 changes: 2 additions & 1 deletion src/components/LHNOptionsList/OptionRowLHN.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import PressableWithSecondaryInteraction from '../PressableWithSecondaryInteract
import * as ReportActionContextMenu from '../../pages/home/report/ContextMenu/ReportActionContextMenu';
import * as ContextMenuActions from '../../pages/home/report/ContextMenu/ContextMenuActions';
import * as OptionsListUtils from '../../libs/OptionsListUtils';
import * as ReportUtils from '../../libs/ReportUtils';
import useLocalize from '../../hooks/useLocalize';

const propTypes = {
Expand Down Expand Up @@ -90,7 +91,7 @@ function OptionRowLHN(props) {
const shouldShowGreenDotIndicator =
!hasBrickError &&
(optionItem.isUnreadWithMention ||
(optionItem.hasOutstandingIOU && !optionItem.isIOUReportOwner) ||
ReportUtils.isWaitingForIOUActionFromCurrentUser(optionItem) ||
(optionItem.isTaskReport && optionItem.isTaskAssignee && !optionItem.isCompletedTaskReport && !optionItem.isArchivedRoom));

/**
Expand Down
2 changes: 1 addition & 1 deletion src/components/MoneyReportHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function MoneyReportHeader(props) {
const policy = props.policies[`${ONYXKEYS.COLLECTION.POLICY}${props.report.policyID}`];
const isPayer =
Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(props.session, 'accountID', null) === moneyRequestReport.managerID);
const shouldShowSettlementButton = !isSettled && isPayer;
const shouldShowSettlementButton = !isSettled && isPayer && !moneyRequestReport.isWaitingOnBankAccount;
const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport);
const shouldShowPaypal = Boolean(lodashGet(props.personalDetails, [moneyRequestReport.managerID, 'payPalMeAddress']));
const formattedAmount = CurrencyUtils.convertToDisplayString(ReportUtils.getMoneyRequestTotal(props.report), props.report.currency);
Expand Down
11 changes: 9 additions & 2 deletions src/components/MoneyRequestDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,16 @@ function MoneyRequestDetails(props) {
: UserUtils.getAvatar(lodashGet(props.personalDetails, [moneyRequestReport.managerID, 'avatar']), moneyRequestReport.managerID);
const isPayer =
Policy.isAdminOfFreePolicy([props.policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(props.session, 'accountID', null) === moneyRequestReport.managerID);
const shouldShowSettlementButton = !isSettled && !props.isSingleTransactionView && isPayer;
const shouldShowSettlementButton = moneyRequestReport.reportID && !isSettled && !props.isSingleTransactionView && isPayer && !moneyRequestReport.isWaitingOnBankAccount;
const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport);
const shouldShowPaypal = Boolean(lodashGet(props.personalDetails, [moneyRequestReport.ownerAccountID, 'payPalMeAddress']));
let description = `${props.translate('iou.amount')}${props.translate('iou.cash')}`;
if (isSettled) {
description += ` • ${props.translate('iou.settledExpensify')}`;
} else if (props.report.isWaitingOnBankAccount) {
description += ` • ${props.translate('iou.pending')}`;
}

const {addWorkspaceRoomOrChatPendingAction, addWorkspaceRoomOrChatErrors} = ReportUtils.getReportOfflinePendingActionAndErrors(props.report);
return (
<OfflineWithFeedback
Expand Down Expand Up @@ -174,7 +181,7 @@ function MoneyRequestDetails(props) {
title={formattedTransactionAmount}
shouldShowTitleIcon={isSettled}
titleIcon={Expensicons.Checkmark}
description={`${props.translate('iou.amount')}${props.translate('iou.cash')}${isSettled ? ` • ${props.translate('iou.settledExpensify')}` : ''}`}
description={description}
titleStyle={styles.newKansasLarge}
disabled={isSettled}
// Note: These options are temporarily disabled while we figure out the required API changes
Expand Down
10 changes: 8 additions & 2 deletions src/components/ReportActionItem/IOUPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,13 @@ function IOUPreview(props) {
return props.translate('iou.split');
}

return `${props.translate('iou.cash')}${!props.iouReport.hasOutstandingIOU ? ` • ${props.translate('iou.settledExpensify')}` : ''}`;
let message = props.translate('iou.cash');
if (props.iouReport.isWaitingOnBankAccount) {
message += ` • ${props.translate('iou.pending')}`;
} else if (ReportUtils.isSettled(props.iouReport.reportID)) {
message += ` • ${props.translate('iou.settledExpensify')}`;
}
return message;
};

const childContainer = (
Expand Down Expand Up @@ -200,7 +206,7 @@ function IOUPreview(props) {
<View style={[styles.flexRow]}>
<View style={[styles.flex1, styles.flexRow, styles.alignItemsCenter]}>
<Text style={styles.textHeadline}>{CurrencyUtils.convertToDisplayString(requestAmount, requestCurrency)}</Text>
{!props.iouReport.hasOutstandingIOU && !props.isBillSplit && (
{ReportUtils.isSettled(props.iouReport.reportID) && !props.isBillSplit && (
<View style={styles.defaultCheckmarkWrapper}>
<Icon
src={Expensicons.Checkmark}
Expand Down
6 changes: 2 additions & 4 deletions src/components/ReportActionItem/MoneyRequestAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import * as ReportActionsUtils from '../../libs/ReportActionsUtils';
import refPropTypes from '../refPropTypes';
import * as PersonalDetailsUtils from '../../libs/PersonalDetailsUtils';
import reportPropTypes from '../../pages/reportPropTypes';

const propTypes = {
/** All the data of the action */
Expand All @@ -43,10 +44,7 @@ const propTypes = {

/* Onyx Props */
/** chatReport associated with iouReport */
chatReport: PropTypes.shape({
/** Whether the chat report has an outstanding IOU */
hasOutstandingIOU: PropTypes.bool.isRequired,
}),
chatReport: reportPropTypes,

/** IOU report data object */
iouReport: iouReportPropTypes,
Expand Down
30 changes: 24 additions & 6 deletions src/components/ReportActionItem/ReportPreview.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import _ from 'underscore';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
Expand Down Expand Up @@ -60,6 +61,9 @@ const propTypes = {

/** Does the iouReport have an outstanding IOU? */
hasOutstandingIOU: PropTypes.bool,

/** Is the iouReport waiting for the submitter to add a credit bank account? */
isWaitingOnBankAccount: PropTypes.bool,
}),

/** Session info for the currently logged in user. */
Expand Down Expand Up @@ -89,11 +93,27 @@ const defaultProps = {
};

function ReportPreview(props) {
const managerID = props.iouReport.managerID || 0;
const managerID = props.iouReport.managerID || props.action.actorAccountID || 0;
const isCurrentUserManager = managerID === lodashGet(props.session, 'accountID');
const reportAmount = CurrencyUtils.convertToDisplayString(ReportUtils.getMoneyRequestTotal(props.iouReport), props.iouReport.currency);
let reportAmount = ReportUtils.getMoneyRequestTotal(props.iouReport);
if (reportAmount) {
reportAmount = CurrencyUtils.convertToDisplayString(reportAmount, props.iouReport.currency);
} else {
// If iouReport is not available, get amount from the action message (Ex: "Domain20821's Workspace owes $33.00" or "paid ₫60" or "paid -₫60 elsewhere")
reportAmount = '';
const actionMessage = lodashGet(props.action, ['message', 0, 'text'], '');
const splits = actionMessage.split(' ');
for (let i = 0; i < splits.length; i++) {
if (/\d/.test(splits[i])) {
reportAmount = splits[i];
}
}
}

const managerName = ReportUtils.isPolicyExpenseChat(props.chatReport) ? ReportUtils.getPolicyName(props.chatReport) : ReportUtils.getDisplayNameForParticipant(managerID, true);
const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport);
const previewMessage = props.translate(ReportUtils.isSettled(props.iouReportID) || props.iouReport.isWaitingOnBankAccount ? 'iou.payerPaid' : 'iou.payerOwes', {payer: managerName});

return (
<View style={[styles.chatItemMessage, ...props.containerStyles]}>
<PressableWithoutFeedback
Expand All @@ -110,9 +130,7 @@ function ReportPreview(props) {
<View style={[styles.iouPreviewBox, props.isHovered ? styles.iouPreviewBoxHover : undefined]}>
<View style={styles.flexRow}>
<View style={[styles.flex1, styles.flexRow, styles.alignItemsCenter]}>
<Text style={[styles.textLabelSupporting, styles.mb1, styles.lh16]}>
{props.translate(ReportUtils.isSettled(props.iouReportID) ? 'iou.payerPaid' : 'iou.payerOwes', {payer: managerName})}
</Text>
<Text style={[styles.textLabelSupporting, styles.mb1, styles.lh16]}>{previewMessage}</Text>
</View>
</View>
<View style={styles.flexRow}>
Expand All @@ -128,7 +146,7 @@ function ReportPreview(props) {
)}
</View>
</View>
{isCurrentUserManager && !ReportUtils.isSettled(props.iouReport.reportID) && (
{!_.isEmpty(props.iouReport) && isCurrentUserManager && !ReportUtils.isSettled(props.iouReportID) && !props.iouReport.isWaitingOnBankAccount && (
<SettlementButton
currency={props.iouReport.currency}
policyID={props.iouReport.policyID}
Expand Down
3 changes: 3 additions & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ export default {
sendMoney: 'Send money',
pay: 'Pay',
viewDetails: 'View details',
pending: 'Pending',
settledExpensify: 'Paid',
settledElsewhere: 'Paid elsewhere',
settledPaypalMe: 'Paid using Paypal.me',
Expand All @@ -367,6 +368,8 @@ export default {
payerPaidAmount: ({payer, amount}) => `${payer} paid ${amount}`,
payerPaid: ({payer}) => `${payer} paid: `,
payerSettled: ({amount}) => `paid ${amount}`,
waitingOnBankAccount: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a bank account`,
settledAfterAddedBankAccount: ({submitterDisplayName, amount}) => `${submitterDisplayName} added a bank account. The ${amount} payment has been made.`,
paidElsewhereWithAmount: ({amount}) => `paid ${amount} elsewhere`,
paidUsingPaypalWithAmount: ({amount}) => `paid ${amount} using Paypal.me`,
paidUsingExpensifyWithAmount: ({amount}) => `paid ${amount} using Expensify`,
Expand Down
3 changes: 3 additions & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ export default {
sendMoney: 'Enviar dinero',
pay: 'Pagar',
viewDetails: 'Ver detalles',
pending: 'Pendiente',
settledExpensify: 'Pagado',
settledElsewhere: 'Pagado de otra forma',
settledPaypalMe: 'Pagado con PayPal.me',
Expand All @@ -366,6 +367,8 @@ export default {
payerPaidAmount: ({payer, amount}) => `${payer} pagó ${amount}`,
payerPaid: ({payer}) => `${payer} pagó: `,
payerSettled: ({amount}) => `pagó ${amount}`,
waitingOnBankAccount: ({submitterDisplayName}) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} agregue una Cuenta bancaria`,
settledAfterAddedBankAccount: ({submitterDisplayName, amount}) => `${submitterDisplayName} agregó una cuenta bancaria. El pago de ${amount} se ha realizado.`,
paidElsewhereWithAmount: ({amount}) => `pagó ${amount} de otra forma`,
paidUsingPaypalWithAmount: ({amount}) => `pagó ${amount} con PayPal.me`,
paidUsingExpensifyWithAmount: ({amount}) => `pagó ${amount} con Expensify`,
Expand Down
33 changes: 10 additions & 23 deletions src/libs/OptionsListUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,6 @@ Onyx.connect({
},
});

const expenseReports = {};
const iouReports = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
callback: (report, key) => {
if (!report || !key || !_.isNumber(report.ownerAccountID)) {
return;
}

if (ReportUtils.isExpenseReport(report)) {
expenseReports[key] = report;
return;
}

if (ReportUtils.isIOUReport(report)) {
iouReports[key] = report;
}
},
});

const lastReportActions = {};
const allSortedReportActions = {};
Onyx.connect({
Expand Down Expand Up @@ -451,6 +431,7 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, {
isDefaultRoom: false,
isPinned: false,
hasOutstandingIOU: false,
isWaitingOnBankAccount: false,
iouReportID: null,
isIOUReportOwner: null,
iouReportAmount: 0,
Expand Down Expand Up @@ -492,6 +473,7 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, {
result.keyForList = String(report.reportID);
result.tooltipText = ReportUtils.getReportParticipantsTitle(report.participantAccountIDs || []);
result.hasOutstandingIOU = report.hasOutstandingIOU;
result.isWaitingOnBankAccount = report.isWaitingOnBankAccount;

hasMultipleParticipants = personalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat;
subtitle = ReportUtils.getChatRoomSubtitle(report);
Expand Down Expand Up @@ -527,8 +509,8 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, {
result.alternateText = LocalePhoneNumber.formatPhoneNumber(lodashGet(personalDetails, [accountIDs[0], 'login'], ''));
}

result.isIOUReportOwner = ReportUtils.isIOUOwnedByCurrentUser(result, iouReports);
result.iouReportAmount = ReportUtils.getMoneyRequestTotal(result, iouReports);
result.isIOUReportOwner = ReportUtils.isIOUOwnedByCurrentUser(result);
result.iouReportAmount = ReportUtils.getMoneyRequestTotal(result);

if (!hasMultipleParticipants) {
result.login = personalDetail.login;
Expand Down Expand Up @@ -648,7 +630,7 @@ function getOptions(
const searchValue = parsedPhoneNumber.possible ? parsedPhoneNumber.number.e164 : searchInputValue.toLowerCase();

// Filter out all the reports that shouldn't be displayed
const filteredReports = _.filter(reports, (report) => ReportUtils.shouldReportBeInOptionList(report, Navigation.getTopmostReportId(), false, iouReports, betas, policies));
const filteredReports = _.filter(reports, (report) => ReportUtils.shouldReportBeInOptionList(report, Navigation.getTopmostReportId(), false, null, betas, policies));

// Sorting the reports works like this:
// - Order everything by the last message timestamp (descending)
Expand Down Expand Up @@ -691,6 +673,11 @@ function getOptions(
return;
}

// In case user needs to add credit bank account, don't allow them to request more money from the workspace.
if (includeOwnedWorkspaceChats && ReportUtils.hasIOUWaitingOnCurrentUserBankAccount(report)) {
return;
}

// Save the report in the map if this is a single participant so we can associate the reportID with the
// personal detail option later. Individuals should not be associated with single participant
// policyExpenseChats or chatRooms since those are not people.
Expand Down
Loading

0 comments on commit cd86b16

Please sign in to comment.