Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
e8f91d6
add the approve report action type
marcochavezf Oct 6, 2023
ba6a799
add onyx key reportNextStep_
marcochavezf Oct 6, 2023
f5323e3
move approve button to settlement button
marcochavezf Oct 6, 2023
8cbedc0
only show approve button if that's only option available
marcochavezf Oct 6, 2023
dc9d510
adapt settlement button to show approve button in report preview
marcochavezf Oct 7, 2023
6ad33ff
only show approve button if user cannot pay in report preview
marcochavezf Oct 7, 2023
8ccd619
fix propTypes for nextStepButtons
marcochavezf Oct 9, 2023
4dcd3e6
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Oct 10, 2023
f75fbf6
show the approved message
marcochavezf Oct 10, 2023
238d074
add type for message where manager approved a money request
marcochavezf Oct 10, 2023
6fd3c42
add messages for managerApprovedAmount
marcochavezf Oct 10, 2023
b24a0a0
add approved message to report name for money requests
marcochavezf Oct 10, 2023
e29e619
display the workspace name for approved reports
marcochavezf Oct 10, 2023
32b2828
add thumbs-up svg
marcochavezf Oct 10, 2023
c41c509
add thumbs-up image as icon for approve button
marcochavezf Oct 10, 2023
35715d7
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Oct 11, 2023
e62259b
clear next step for approved/paid report
marcochavezf Oct 11, 2023
eef5854
select first option if the selected item is no longer available
marcochavezf Oct 11, 2023
257e54f
fix propType for nextStepButtons in report preview
marcochavezf Oct 11, 2023
1f5aa19
fix display issue with the pay button
marcochavezf Oct 11, 2023
6c4463a
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Oct 11, 2023
64481a9
fix props error
marcochavezf Oct 11, 2023
82e1362
re-compute if some of next step buttons changed
marcochavezf Oct 11, 2023
5a91cb2
fix styles
marcochavezf Oct 11, 2023
3355f18
create ts types for report next steps Onyx object
marcochavezf Oct 11, 2023
2dfeadb
import ReportNextSteps in OnyxKeys
marcochavezf Oct 11, 2023
3c7db13
include report next step types in OnyxValues type
marcochavezf Oct 11, 2023
5595e79
fix style for next step type
marcochavezf Oct 12, 2023
7579f12
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Oct 17, 2023
0ed35bf
return empty object as default for nextStepButtons
marcochavezf Oct 17, 2023
264c9fb
fix typo for payerOrApproverName
marcochavezf Oct 17, 2023
846e710
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Oct 18, 2023
1c6e756
fix style
marcochavezf Oct 18, 2023
f65129e
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Oct 19, 2023
e98f261
update nextStepButtons for nextSteps
marcochavezf Oct 19, 2023
235a271
fix types for nextStep buttons
marcochavezf Oct 19, 2023
d861e74
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Oct 19, 2023
516f0cc
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Oct 20, 2023
e29d407
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Oct 31, 2023
cccdfb5
fix linting
marcochavezf Nov 1, 2023
0f41e95
check policy type to show pay button in free policies
marcochavezf Nov 1, 2023
28de2c1
change nextStepButtons to nextStep
marcochavezf Nov 1, 2023
28b3d32
fix linting
marcochavezf Nov 1, 2023
9c273f5
add policy to default props
marcochavezf Nov 1, 2023
5a4779c
fix key generation for nextStep in ReportPreview
marcochavezf Nov 5, 2023
c1c32e6
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Nov 9, 2023
64ca6f4
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Nov 11, 2023
70fe9ff
add nextStep prop to MoneyReportHeader
marcochavezf Nov 11, 2023
1efdd33
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Nov 15, 2023
55d1716
fix settlement button for IOUs
marcochavezf Nov 16, 2023
1c0d6fb
fix settlement button for IOUs in money report header
marcochavezf Nov 16, 2023
7bd8233
update logic to check if the report is iou or from free plan
marcochavezf Nov 16, 2023
785fd16
fix missing import
marcochavezf Nov 16, 2023
8887d86
fix lint errors
marcochavezf Nov 16, 2023
b898da5
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Nov 16, 2023
da7d29e
Check if the linked money request is approved to create a new one
marcochavezf Nov 17, 2023
67f4eec
Fix lint error
marcochavezf Nov 17, 2023
5b81b63
Remove unused import
marcochavezf Nov 17, 2023
9988511
Update SettlementButton to pass shouldShowApproveButton as props
marcochavezf Nov 21, 2023
00fd837
Update MoneyRequestHeader logic to use report state instead of NextStep
marcochavezf Nov 21, 2023
36f14d7
Add isGroupPolicyExpenseReport function
marcochavezf Nov 21, 2023
57d88ea
Add isGroupPolicyExpenseChat function
marcochavezf Nov 21, 2023
3f887bd
Refactor MoneyRequestPreview.js to include group
marcochavezf Nov 21, 2023
9320a90
Update ReportPreview to use report state and status instead of NextSt…
marcochavezf Nov 21, 2023
e17d75b
Fix lint error
marcochavezf Nov 21, 2023
d72d9c6
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Nov 30, 2023
793b2f8
Fix type for ManagerApprovedAmountParams
marcochavezf Nov 30, 2023
7b510b0
Include isGroupPolicyExpenseChat in ReportUtils
marcochavezf Nov 30, 2023
e1c5982
Refactor isGroupPolicyExpenseChat and
marcochavezf Nov 30, 2023
f81e743
Fix wording
marcochavezf Nov 30, 2023
4e73080
Hide payment options if the only option available is approval
marcochavezf Nov 30, 2023
2fd3579
Fix lint errors
marcochavezf Nov 30, 2023
60685f3
Show Pay & Approve options for admin approver
marcochavezf Nov 30, 2023
e05e34a
Restore again isApproved for ReportPreview
marcochavezf Nov 30, 2023
455dbaf
Revert nextStep type changes
marcochavezf Nov 30, 2023
8e5644c
Revert optimistic data changes for report nextStep
marcochavezf Nov 30, 2023
faf147b
Avoid creating a new report if linked report is approved
marcochavezf Nov 30, 2023
12b405f
Fix lint error
marcochavezf Nov 30, 2023
2159282
Remove unused onyx keys for nextStep data
marcochavezf Nov 30, 2023
778e349
Remove duplicated code
marcochavezf Nov 30, 2023
634c431
Allow admins to pay request directly
marcochavezf Nov 30, 2023
e8a4484
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Dec 1, 2023
70c60c1
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Dec 1, 2023
977852b
Fix type for nextStep.buttons
marcochavezf Dec 1, 2023
11cb327
Only show pay button when approver is admin
marcochavezf Dec 1, 2023
0f451e0
Only show the pay button for non-approver admins if the report is app…
marcochavezf Dec 1, 2023
32151d0
Only show the pay button in report preview for non-approver admins if…
marcochavezf Dec 1, 2023
25769ef
Re-use same logic from MoneyReportHeader to show the pay button
marcochavezf Dec 1, 2023
5747565
Show "Finished" as next step title when report is reimbursed
marcochavezf Dec 1, 2023
cf823e9
Check the message is approved message is displayed in paid policies
marcochavezf Dec 4, 2023
8dd0057
Display the correct message for approved requests in LHN
marcochavezf Dec 4, 2023
a59f4ec
Show subscript avatar for approved reports
marcochavezf Dec 4, 2023
bbfd56b
Disable money request if report is approved
marcochavezf Dec 4, 2023
73f5a2d
Add text for clipboard value in approved reports
marcochavezf Dec 5, 2023
9efe3e2
Add clipboard value to getIOUReportActionDisplayMessage for approved …
marcochavezf Dec 5, 2023
37502f6
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Dec 5, 2023
6b3cf50
Fix lint errors
marcochavezf Dec 5, 2023
ff2703e
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Dec 6, 2023
91ea177
Include subscript avatar for submitted report actions
marcochavezf Dec 6, 2023
65fd180
Fix lint errors
marcochavezf Dec 6, 2023
ae787de
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Dec 7, 2023
b1ead6d
Update src/libs/ReportUtils.ts
marcochavezf Dec 8, 2023
02c7526
Update src/libs/ReportUtils.ts
marcochavezf Dec 8, 2023
3cce8d4
Update src/libs/ReportUtils.ts
marcochavezf Dec 8, 2023
16fd5a5
Update src/libs/ReportUtils.ts
marcochavezf Dec 8, 2023
52c421d
Update src/libs/ReportUtils.ts
marcochavezf Dec 8, 2023
1584932
Update src/components/ReportActionItem/ReportPreview.js
marcochavezf Dec 8, 2023
6275670
Update src/components/MoneyReportHeader.js
marcochavezf Dec 8, 2023
398a2f3
Move next step finished to CONST
marcochavezf Dec 8, 2023
e4e8cce
Fix lint errors
marcochavezf Dec 8, 2023
da0fe2b
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Dec 11, 2023
1128243
Merge branch 'main' into marco-approveButtonCollectPolicies
marcochavezf Dec 12, 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
8 changes: 8 additions & 0 deletions assets/images/thumbs-up.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,9 @@ const CONST = {
OWNER_ACCOUNT_ID_FAKE: 0,
DEFAULT_REPORT_NAME: 'Chat Report',
},
NEXT_STEP: {
FINISHED: 'Finished!',
},
COMPOSER: {
MAX_LINES: 16,
MAX_LINES_SMALL_SCREEN: 6,
Expand Down Expand Up @@ -1167,6 +1170,7 @@ const CONST = {
DECLINE: 'decline',
CANCEL: 'cancel',
DELETE: 'delete',
APPROVE: 'approve',
},
AMOUNT_MAX_LENGTH: 10,
RECEIPT_STATE: {
Expand Down
2 changes: 1 addition & 1 deletion src/components/ButtonWithDropdownMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function ButtonWithDropdownMenu(props) {
const [popoverAnchorPosition, setPopoverAnchorPosition] = useState(null);
const {windowWidth, windowHeight} = useWindowDimensions();
const caretButton = useRef(null);
const selectedItem = props.options[selectedItemIndex];
const selectedItem = props.options[selectedItemIndex] || _.first(props.options);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What's the case where we might pass an incorrect index?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah since we're now showing the Approve option in the settlement button, there's a case where an admin manager approves the report and immediately we show the Pay options. Given the Approve button is the last selected index and it's not available anymore, the selectedItem can be undefined causing an error. So in this case we default to the first available Pay option.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hmm tbh I really wouldn't be able to tell that from looking at this fallback. Is there some way we can make that more explicit so it feels less like a guard against some unknown number of scenarios?

e.g. could the report state be used to track that the report was approved and now needs to be paid? Or something like that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Now that I'm looking at it with more attention, you're right that this line of code is not explicit about that edge case. I like the idea of using the report state to change the behavior of the payment options here. Given the PR is already tested and approved, and also we're planning to make the Approve button "sticky" (it was not included here because it was considered a premature optimization), we can revise this later. Meanwhile, I will merge this PR so we can test the collect approvers flow more thoroughly.

const innerStyleDropButton = StyleUtils.getDropDownButtonHeight(props.buttonSize);
const isButtonSizeLarge = props.buttonSize === CONST.DROPDOWN_BUTTON_SIZE.LARGE;

Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Expensicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ import Youtube from '@assets/images/social-youtube.svg';
import Sync from '@assets/images/sync.svg';
import Task from '@assets/images/task.svg';
import ThreeDots from '@assets/images/three-dots.svg';
import ThumbsUp from '@assets/images/thumbs-up.svg';
import Transfer from '@assets/images/transfer.svg';
import Trashcan from '@assets/images/trashcan.svg';
import Unlock from '@assets/images/unlock.svg';
Expand Down Expand Up @@ -242,6 +243,7 @@ export {
Shield,
Sync,
Task,
ThumbsUp,
ThreeDots,
Transfer,
Trashcan,
Expand Down
39 changes: 13 additions & 26 deletions src/components/MoneyReportHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,24 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);
const policyType = lodashGet(policy, 'type');
const isPolicyAdmin = policyType !== CONST.POLICY.TYPE.PERSONAL && lodashGet(policy, 'role') === CONST.POLICY.ROLE.ADMIN;
const isGroupPolicy = _.contains([CONST.POLICY.TYPE.CORPORATE, CONST.POLICY.TYPE.TEAM], policyType);
const isManager = ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID;
const isPayer = policyType === CONST.POLICY.TYPE.CORPORATE ? isPolicyAdmin && isApproved : isPolicyAdmin || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && isManager);

@marcochavezf marcochavezf Nov 30, 2023 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I removed the condition isApproved since now admins can Pay a request by skipping the Approve state in paid policies (control/corporate and collect/team).

In this way, we can show both the Pay options and the Approve button in both ReportPreview and MoneyReportHeader:

Screenshot 2023-11-29 at 8 59 27 p m

const isPayer = isGroupPolicy
? // In a group policy, the admin approver can pay the report directly by skipping the approval step
isPolicyAdmin && (isApproved || isManager)
Comment thread
marcochavezf marked this conversation as resolved.
: isPolicyAdmin || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && isManager);
const isDraft = ReportUtils.isDraftExpenseReport(moneyRequestReport);
const shouldShowSettlementButton = useMemo(
const shouldShowPayButton = useMemo(
() => isPayer && !isDraft && !isSettled && !moneyRequestReport.isWaitingOnBankAccount && reimbursableTotal !== 0 && !ReportUtils.isArchivedRoom(chatReport),
[isPayer, isDraft, isSettled, moneyRequestReport, reimbursableTotal, chatReport],
);
const shouldShowApproveButton = useMemo(() => {
if (policyType !== CONST.POLICY.TYPE.CORPORATE) {
if (!isGroupPolicy) {
return false;
}
return isManager && !isDraft && !isApproved && !isSettled;
}, [policyType, isManager, isDraft, isApproved, isSettled]);
}, [isGroupPolicy, isManager, isDraft, isApproved, isSettled]);
const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton;
const shouldShowSubmitButton = isDraft && reimbursableTotal !== 0;
const isFromPaidPolicy = policyType === CONST.POLICY.TYPE.TEAM || policyType === CONST.POLICY.TYPE.CORPORATE;
const shouldShowNextSteps = isFromPaidPolicy && nextStep && !_.isEmpty(nextStep.message);
Expand Down Expand Up @@ -120,22 +125,13 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
onPress={(paymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)}
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
addBankAccountRoute={bankAccountRoute}
shouldHidePaymentOptions={!shouldShowPayButton}
shouldShowApproveButton={shouldShowApproveButton}
style={[styles.pv2]}
formattedAmount={formattedAmount}
/>
</View>
)}
{shouldShowApproveButton && !isSmallScreenWidth && (
<View style={styles.pv2}>
<Button
success
medium
text={translate('iou.approve')}
style={[styles.mnw120, styles.pv2, styles.pr0]}
onPress={() => IOU.approveMoneyRequest(moneyRequestReport)}
/>
</View>
)}
{shouldShowSubmitButton && !isSmallScreenWidth && (
<View style={styles.pv2}>
<Button
Expand All @@ -159,21 +155,12 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
onPress={(paymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)}
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
addBankAccountRoute={bankAccountRoute}
shouldHidePaymentOptions={!shouldShowPayButton}
shouldShowApproveButton={shouldShowApproveButton}
formattedAmount={formattedAmount}
/>
</View>
)}
{shouldShowApproveButton && isSmallScreenWidth && (
<View style={[styles.ph5, styles.pb2]}>
<Button
success
medium
text={translate('iou.approve')}
style={[styles.w100, styles.pr0]}
onPress={() => IOU.approveMoneyRequest(moneyRequestReport)}
/>
</View>
)}
{shouldShowSubmitButton && isSmallScreenWidth && (
<View style={[styles.ph5, styles.pb2]}>
<Button
Expand Down
3 changes: 2 additions & 1 deletion src/components/MoneyReportHeaderStatusBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useLocalize from '@hooks/useLocalize';
import * as NextStepUtils from '@libs/NextStepUtils';
import nextStepPropTypes from '@pages/nextStepPropTypes';
import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import RenderHTML from './RenderHTML';

const propTypes = {
Expand All @@ -27,7 +28,7 @@ function MoneyReportHeaderStatusBar({nextStep}) {
return (
<View style={[styles.dFlex, styles.flexRow, styles.alignItemsCenter, styles.overflowHidden, styles.w100]}>
<View style={styles.moneyRequestHeaderStatusBarBadge}>
<Text style={[styles.textLabel, styles.textMicroBold]}>{translate('iou.nextSteps')}</Text>
<Text style={[styles.textLabel, styles.textMicroBold]}>{translate(nextStep.title === CONST.NEXT_STEP.FINISHED ? 'iou.finished' : 'iou.nextSteps')}</Text>
</View>
<View style={[styles.dFlex, styles.flexRow, styles.flexShrink1]}>
<RenderHTML html={messageContent} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReportActionItem/MoneyRequestPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ function MoneyRequestPreview(props) {
}

let message = props.translate('iou.cash');
if (ReportUtils.isControlPolicyExpenseReport(props.iouReport) && ReportUtils.isReportApproved(props.iouReport) && !ReportUtils.isSettled(props.iouReport)) {
if (ReportUtils.isGroupPolicyExpenseReport(props.iouReport) && ReportUtils.isReportApproved(props.iouReport) && !ReportUtils.isSettled(props.iouReport)) {
message += ` • ${props.translate('iou.approved')}`;
} else if (props.iouReport.isWaitingOnBankAccount) {
message += ` • ${props.translate('iou.pending')}`;
Expand Down
4 changes: 3 additions & 1 deletion src/components/ReportActionItem/MoneyRequestView.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate
if (!isDistanceRequest) {
amountDescription += ` • ${translate('iou.cash')}`;
}
if (isCancelled) {
if (ReportUtils.isReportApproved(report)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Coming from #35666
As @marcochavezf pointed out in this comment, we were getting the 'Approved' status from the wrong report (transaction report) instead of the money request
It should be ReportUtils.isReportApproved(moneyRequestReport)

amountDescription += ` • ${translate('iou.approved')}`;
} else if (isCancelled) {
amountDescription += ` • ${translate('iou.canceled')}`;
} else if (isSettled) {
amountDescription += ` • ${translate('iou.settledExpensify')}`;
Expand Down
46 changes: 39 additions & 7 deletions src/components/ReportActionItem/ReportPreview.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import React from 'react';
import React, {useMemo} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
Expand Down Expand Up @@ -47,6 +47,18 @@ const propTypes = {
/** The report's policyID, used for Onyx subscription */
policyID: PropTypes.string.isRequired,

/** The policy tied to the money request report */
policy: PropTypes.shape({
/** Name of the policy */
name: PropTypes.string,

/** Type of the policy */
type: PropTypes.string,

/** The role of the current user in the policy */
role: PropTypes.string,
}),

/* Onyx Props */
/** chatReport associated with iouReport */
chatReport: reportPropTypes,
Expand Down Expand Up @@ -101,6 +113,7 @@ const defaultProps = {
accountID: null,
},
isWhisper: false,
policy: {},
};

function ReportPreview(props) {
Expand All @@ -111,14 +124,16 @@ function ReportPreview(props) {
const managerID = props.iouReport.managerID || 0;
const isCurrentUserManager = managerID === lodashGet(props.session, 'accountID');
const {totalDisplaySpend, reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(props.iouReport);
const policyType = lodashGet(props.policy, 'type');

const iouSettled = ReportUtils.isSettled(props.iouReportID);
const iouCanceled = ReportUtils.isArchivedRoom(props.chatReport);
const numberOfRequests = ReportActionUtils.getNumberOfMoneyRequests(props.action);
const moneyRequestComment = lodashGet(props.action, 'childLastMoneyRequestComment', '');
const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(props.chatReport);
const isDraftExpenseReport = isPolicyExpenseChat && ReportUtils.isDraftExpenseReport(props.iouReport);

const isApproved = ReportUtils.isReportApproved(props.iouReport);
const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(props.iouReport);
const transactionsWithReceipts = ReportUtils.getTransactionsWithReceipts(props.iouReportID);
const numberOfScanningReceipts = _.filter(transactionsWithReceipts, (transaction) => TransactionUtils.isReceiptBeingScanned(transaction)).length;
const hasReceipts = transactionsWithReceipts.length > 0;
Expand Down Expand Up @@ -172,8 +187,9 @@ function ReportPreview(props) {
if (isScanning) {
return props.translate('common.receipt');
}
if (ReportUtils.isControlPolicyExpenseChat(props.chatReport) && ReportUtils.isReportApproved(props.iouReport)) {
return props.translate('iou.managerApproved', {manager: ReportUtils.getDisplayNameForParticipant(managerID, true)});
const payerOrApproverName = isPolicyExpenseChat ? ReportUtils.getPolicyName(props.chatReport) : ReportUtils.getDisplayNameForParticipant(managerID, true);
if (isApproved) {
return props.translate('iou.managerApproved', {manager: payerOrApproverName});
}
const managerName = isPolicyExpenseChat ? ReportUtils.getPolicyName(props.chatReport) : ReportUtils.getDisplayNameForParticipant(managerID, true);
let paymentVerb = hasNonReimbursableTransactions ? 'iou.payerSpent' : 'iou.payerOwes';
Expand All @@ -184,10 +200,24 @@ function ReportPreview(props) {
};

const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport);
const shouldShowSettlementButton = ReportUtils.isControlPolicyExpenseChat(props.chatReport)
? props.policy.role === CONST.POLICY.ROLE.ADMIN && ReportUtils.isReportApproved(props.iouReport) && !iouSettled && !iouCanceled

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Similarly here, ReportUtils.isReportApproved was removed to optimize for Payment directly

: !_.isEmpty(props.iouReport) && isCurrentUserManager && !isDraftExpenseReport && !iouSettled && !iouCanceled && !props.iouReport.isWaitingOnBankAccount && reimbursableSpend !== 0;

const isGroupPolicy = ReportUtils.isGroupPolicyExpenseChat(props.chatReport);
const isPolicyAdmin = policyType !== CONST.POLICY.TYPE.PERSONAL && lodashGet(props.policy, 'role') === CONST.POLICY.ROLE.ADMIN;
const isPayer = isGroupPolicy
? // In a group policy, the admin approver can pay the report directly by skipping the approval step
isPolicyAdmin && (isApproved || isCurrentUserManager)
Comment thread
marcochavezf marked this conversation as resolved.
: isPolicyAdmin || (isMoneyRequestReport && isCurrentUserManager);
const shouldShowPayButton = useMemo(
() => isPayer && !isDraftExpenseReport && !iouSettled && !props.iouReport.isWaitingOnBankAccount && reimbursableSpend !== 0 && !iouCanceled,
[isPayer, isDraftExpenseReport, iouSettled, reimbursableSpend, iouCanceled, props.iouReport],
);
const shouldShowApproveButton = useMemo(() => {
if (!isGroupPolicy) {
return false;
}
return isCurrentUserManager && !isDraftExpenseReport && !isApproved && !iouSettled;
}, [isGroupPolicy, isCurrentUserManager, isDraftExpenseReport, isApproved, iouSettled]);
const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton;
return (
<View style={[styles.chatItemMessage, ...props.containerStyles]}>
<PressableWithoutFeedback
Expand Down Expand Up @@ -251,6 +281,8 @@ function ReportPreview(props) {
onPress={(paymentType) => IOU.payMoneyRequest(paymentType, props.chatReport, props.iouReport)}
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
addBankAccountRoute={bankAccountRoute}
shouldHidePaymentOptions={!shouldShowPayButton}
shouldShowApproveButton={shouldShowApproveButton}
style={[styles.mt3]}
kycWallAnchorAlignment={{
horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT,
Expand Down
32 changes: 31 additions & 1 deletion src/components/SettlementButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import compose from '@libs/compose';
import * as ReportUtils from '@libs/ReportUtils';
import iouReportPropTypes from '@pages/iouReportPropTypes';
import * as BankAccounts from '@userActions/BankAccounts';
import * as IOU from '@userActions/IOU';
import * as PaymentMethods from '@userActions/PaymentMethods';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand Down Expand Up @@ -36,6 +37,12 @@ const propTypes = {
/** The route to redirect if user does not have a payment method setup */
enablePaymentsRoute: PropTypes.string.isRequired,

/** Should we show the approve button? */
shouldHidePaymentOptions: PropTypes.bool,

/** Should we show the payment options? */
shouldShowApproveButton: PropTypes.bool,

/** The last payment method used per policy */
nvp_lastPaymentMethod: PropTypes.objectOf(PropTypes.string),

Expand Down Expand Up @@ -89,6 +96,8 @@ const defaultProps = {
// hook from being recreated unnecessarily, hence the use of CONST.EMPTY_ARRAY and CONST.EMPTY_OBJECT
iouReport: CONST.EMPTY_OBJECT,
nvp_lastPaymentMethod: CONST.EMPTY_OBJECT,
shouldHidePaymentOptions: false,
shouldShowApproveButton: false,
style: [],
policyID: '',
formattedAmount: '',
Expand Down Expand Up @@ -120,6 +129,8 @@ function SettlementButton({
onPress,
pressOnEnter,
policyID,
shouldHidePaymentOptions,
shouldShowApproveButton,
style,
}) {
const {translate} = useLocalize();
Expand Down Expand Up @@ -149,8 +160,18 @@ function SettlementButton({
value: CONST.IOU.PAYMENT_TYPE.ELSEWHERE,
},
};
const approveButtonOption = {
text: translate('iou.approve'),
icon: Expensicons.ThumbsUp,
value: CONST.IOU.REPORT_ACTION_TYPE.APPROVE,
};
const canUseWallet = !isExpenseReport && currency === CONST.CURRENCY.USD;

// Only show the Approve button if the user cannot pay the request
if (shouldHidePaymentOptions && shouldShowApproveButton) {
return [approveButtonOption];
}

// To achieve the one tap pay experience we need to choose the correct payment type as default,
// if user already paid for some request or expense, let's use the last payment method or use default.
const paymentMethod = nvp_lastPaymentMethod[policyID] || '';
Expand All @@ -162,12 +183,16 @@ function SettlementButton({
}
buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]);

if (shouldShowApproveButton) {
buttonOptions.push(approveButtonOption);
}

// Put the preferred payment method to the front of the array so its shown as default
if (paymentMethod) {
return _.sortBy(buttonOptions, (method) => (method.value === paymentMethod ? 0 : 1));
}
return buttonOptions;
}, [currency, formattedAmount, iouReport, nvp_lastPaymentMethod, policyID, translate]);
}, [currency, formattedAmount, iouReport, nvp_lastPaymentMethod, policyID, translate, shouldHidePaymentOptions, shouldShowApproveButton]);

const selectPaymentType = (event, iouPaymentType, triggerKYCFlow) => {
if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA) {
Expand All @@ -176,6 +201,11 @@ function SettlementButton({
return;
}

if (iouPaymentType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) {
IOU.approveMoneyRequest(iouReport);
return;
}

onPress(iouPaymentType);
};

Expand Down
Loading