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

Allow requesting money when expensify account owns workspace #30019

Merged
merged 9 commits into from
Nov 1, 2023
41 changes: 35 additions & 6 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,33 @@ function isExpensifyOnlyParticipantInReport(report) {
return reportParticipants.length === 1 && _.some(reportParticipants, (accountID) => _.contains(CONST.EXPENSIFY_ACCOUNT_IDS, accountID));
}

/**
* Checks if the policy that the report is on is owned by one of the special Expensify accounts
*
* @param {Object} report
* @returns {Boolean}
*/
function doExpensifyAccountsOwnPolicy(report) {
Copy link
Contributor

@youssef-lr youssef-lr Oct 31, 2023

Choose a reason for hiding this comment

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

NAB but I feel like this is slightly clearer (at least to me :D)

Suggested change
function doExpensifyAccountsOwnPolicy(report) {
function isPolicyOwnedByExpensifyAccounts(report) {

Also, I think this might be better placed in actions/Policy.js (the file already contains similar helper functions) and can just take a policyID, we already have allPolicies in that file as well. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

A cleanup idea for later is to remove those helper functions from actions/Policy.js and into PolicyUtils

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good points. Though actually, I'm going to refactor the canCreateTaskInReport function below, which means we'll no longer need this function.

Copy link
Contributor

@youssef-lr youssef-lr Oct 31, 2023

Choose a reason for hiding this comment

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

You're using it here as well, or will you also refactor this bit?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's the only place it'll be used, so no need to be a separate function is my thinking. Do you agree? I updated the PR so you can see how I'm doing it now.

const policyID = lodashGet(report, 'policyID', '');
const policyOwnerAccountID = lodashGet(allPolicies, [`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, 'ownerAccountID'], 0);
return CONST.EXPENSIFY_ACCOUNT_IDS.includes(policyOwnerAccountID);
}

/**
* Returns whether a given report can have tasks created in it.
* @param {Object} report
* @returns {Boolean}
*/
function canCreateTaskInReport(report) {
// Tasks cannot be created in DMs with special Expensify accounts but they can be created in policy rooms that are owned by them.
// So we check if Expensify accounts are the only other participant and also whether or not we are in a room owned by them.
if (isExpensifyOnlyParticipantInReport(report) && !doExpensifyAccountsOwnPolicy(report)) {
return false;
}
grgia marked this conversation as resolved.
Show resolved Hide resolved

return true;
}

/**
* Returns true if there are any Expensify accounts (i.e. with domain 'expensify.com') in the set of accountIDs
* by cross-referencing the accountIDs with personalDetails.
Expand Down Expand Up @@ -3650,15 +3677,15 @@ function getMoneyRequestOptions(report, reportParticipants) {

const participants = _.filter(reportParticipants, (accountID) => currentUserPersonalDetails.accountID !== accountID);

// Verify if there is any of the expensify accounts amongst the participants in which case user cannot take IOU actions on such report
const hasExcludedIOUAccountIDs = lodashIntersection(reportParticipants, CONST.EXPENSIFY_ACCOUNT_IDS).length > 0;
const hasSingleParticipantInReport = participants.length === 1;
const hasMultipleParticipants = participants.length > 1;

if (hasExcludedIOUAccountIDs) {
// We don't allow IOU actions if an Expensify account is a participant of the report, unless the policy that the report is on is owned by an Expensify account
puneetlath marked this conversation as resolved.
Show resolved Hide resolved
const doParticipantsIncludeExpensifyAccounts = lodashIntersection(reportParticipants, CONST.EXPENSIFY_ACCOUNT_IDS).length > 0;
if (doParticipantsIncludeExpensifyAccounts && !doExpensifyAccountsOwnPolicy(report)) {
return [];
}

const hasSingleParticipantInReport = participants.length === 1;
const hasMultipleParticipants = participants.length > 1;

// User created policy rooms and default rooms like #admins or #announce will always have the Split Bill option
// unless there are no participants at all (e.g. #admins room for a policy with only 1 admin)
// DM chats will have the Split Bill option only when there are at least 3 people in the chat.
Expand Down Expand Up @@ -4147,6 +4174,8 @@ export {
getPolicyType,
isArchivedRoom,
isExpensifyOnlyParticipantInReport,
doExpensifyAccountsOwnPolicy,
canCreateTaskInReport,
isPolicyExpenseChatAdmin,
isPolicyAdmin,
isPublicRoom,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ function AttachmentPickerWithMenuItems({
*/
const taskOption = useMemo(() => {
// We only prevent the task option from showing if it's a DM and the other user is an Expensify default email
if (!Permissions.canUseTasks(betas) || ReportUtils.isExpensifyOnlyParticipantInReport(report)) {
if (!Permissions.canUseTasks(betas) || !ReportUtils.canCreateTaskInReport(report)) {
return [];
}

Expand Down
2 changes: 1 addition & 1 deletion src/pages/tasks/TaskShareDestinationSelectorModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function TaskShareDestinationSelectorModal(props) {
_.keys(props.reports).forEach((reportKey) => {
if (
ReportUtils.shouldDisableWriteActions(props.reports[reportKey]) ||
ReportUtils.isExpensifyOnlyParticipantInReport(props.reports[reportKey]) ||
!ReportUtils.canCreateTaskInReport(props.reports[reportKey]) ||
ReportUtils.isCanceledTaskReport(props.reports[reportKey])
) {
return;
Expand Down