Skip to content

Commit

Permalink
Merge pull request #16670 from Expensify/cmartins-allowMoneyRequestIn…
Browse files Browse the repository at this point in the history
…WorkspaceChat

Allow money request in workspace chat
  • Loading branch information
mountiny authored Mar 30, 2023
2 parents b3f6dda + 154ba07 commit f327eb0
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 34 deletions.
4 changes: 2 additions & 2 deletions src/components/ReportWelcomeText.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const ReportWelcomeText = (props) => {
isMultipleParticipant,
);
const roomWelcomeMessage = ReportUtils.getRoomWelcomeMessage(props.report, props.policies);
const iouOptions = ReportUtils.getIOUOptions(props.report, participants, props.betas);
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(props.report, participants, props.betas);
return (
<>
<View>
Expand Down Expand Up @@ -132,7 +132,7 @@ const ReportWelcomeText = (props) => {
))}
</Text>
)}
{(iouOptions.includes(CONST.IOU.IOU_TYPE.SEND) || iouOptions.includes(CONST.IOU.IOU_TYPE.REQUEST)) && (
{(moneyRequestOptions.includes(CONST.IOU.IOU_TYPE.SEND) || moneyRequestOptions.includes(CONST.IOU.IOU_TYPE.REQUEST)) && (
<Text>
{/* Need to confirm copy for the below with marketing, and then add to translations. */}
{props.translate('reportActionsView.usePlusButton')}
Expand Down
24 changes: 18 additions & 6 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1587,32 +1587,43 @@ function getReportIDFromLink(url) {
return reportID;
}

/**
* Users can request money in policy expense chats only if they are in a role of a member in the chat (in other words, if it's their policy expense chat)
*
* @param {Object} report
* @returns {Boolean}
*/
function canRequestMoney(report) {
return (!isPolicyExpenseChat(report) || report.isOwnPolicyExpenseChat);
}

/**
* @param {Object} report
* @param {Array} reportParticipants
* @param {Array} betas
* @returns {Array}
*/
function getIOUOptions(report, reportParticipants, betas) {
function getMoneyRequestOptions(report, reportParticipants, betas) {
const participants = _.filter(reportParticipants, email => currentUserPersonalDetails.login !== email);
const hasExcludedIOUEmails = lodashIntersection(reportParticipants, CONST.EXPENSIFY_EMAILS).length > 0;
const hasMultipleParticipants = participants.length > 1;

if (hasExcludedIOUEmails || participants.length === 0 || !Permissions.canUseIOU(betas)) {
if (hasExcludedIOUEmails || (participants.length === 0 && !report.isOwnPolicyExpenseChat) || !Permissions.canUseIOU(betas)) {
return [];
}

// 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 and workspace chats will have the Split Bill option only when there are at least 3 people in the chat.
if (isChatRoom(report) || hasMultipleParticipants) {
// DM chats will have the Split Bill option only when there are at least 3 people in the chat.
// There is no Split Bill option for Workspace chats
if (isChatRoom(report) || (hasMultipleParticipants && !isPolicyExpenseChat(report))) {
return [CONST.IOU.IOU_TYPE.SPLIT];
}

// DM chats that only have 2 people will see the Send / Request money options.
// Workspace chats should only see the Request money option, as "easy overages" is not available.
return [
CONST.IOU.IOU_TYPE.REQUEST,
...(canRequestMoney(report) ? [CONST.IOU.IOU_TYPE.REQUEST] : []),
...(Permissions.canUseIOUSend(betas) && !isPolicyExpenseChat(report) ? [CONST.IOU.IOU_TYPE.SEND] : []),
];
}
Expand Down Expand Up @@ -1712,5 +1723,6 @@ export {
getParsedComment,
getFullSizeAvatar,
getSmallSizeAvatar,
getIOUOptions,
getMoneyRequestOptions,
canRequestMoney,
};
8 changes: 4 additions & 4 deletions src/pages/home/report/ReportActionCompose.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ class ReportActionCompose extends React.Component {
this.isEmojiCode = this.isEmojiCode.bind(this);
this.setTextInputRef = this.setTextInputRef.bind(this);
this.getInputPlaceholder = this.getInputPlaceholder.bind(this);
this.getIOUOptions = this.getIOUOptions.bind(this);
this.getMoneyRequestOptions = this.getMoneyRequestOptions.bind(this);
this.addAttachment = this.addAttachment.bind(this);
this.insertSelectedEmoji = this.insertSelectedEmoji.bind(this);
this.setExceededMaxCommentLength = this.setExceededMaxCommentLength.bind(this);
Expand Down Expand Up @@ -332,7 +332,7 @@ class ReportActionCompose extends React.Component {
* @param {Array} reportParticipants
* @returns {Array<object>}
*/
getIOUOptions(reportParticipants) {
getMoneyRequestOptions(reportParticipants) {
const options = {
[CONST.IOU.IOU_TYPE.SPLIT]: {
icon: Expensicons.Receipt,
Expand All @@ -350,7 +350,7 @@ class ReportActionCompose extends React.Component {
onSelected: () => Navigation.navigate(ROUTES.getIOUSendRoute(this.props.reportID)),
},
};
return _.map(ReportUtils.getIOUOptions(this.props.report, reportParticipants, this.props.betas), option => options[option]);
return _.map(ReportUtils.getMoneyRequestOptions(this.props.report, reportParticipants, this.props.betas), option => options[option]);
}

/**
Expand Down Expand Up @@ -780,7 +780,7 @@ class ReportActionCompose extends React.Component {
onClose={() => this.setMenuVisibility(false)}
onItemSelected={() => this.setMenuVisibility(false)}
anchorPosition={styles.createMenuPositionReportActionCompose}
menuItems={[...this.getIOUOptions(reportParticipants),
menuItems={[...this.getMoneyRequestOptions(reportParticipants),
{
icon: Expensicons.Paperclip,
text: this.props.translate('reportActionCompose.addAttachment'),
Expand Down
45 changes: 23 additions & 22 deletions tests/unit/ReportUtilsTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ describe('ReportUtils', () => {
});
});

describe('getIOUOptions', () => {
describe('getMoneyRequestOptions', () => {
const participants = _.keys(participantsPersonalDetails);

beforeAll(() => {
Expand All @@ -324,20 +324,20 @@ describe('ReportUtils', () => {
describe('return empty iou options if', () => {
it('participants contains excluded iou emails', () => {
const allEmpty = _.every(CONST.EXPENSIFY_EMAILS, (email) => {
const iouOptions = ReportUtils.getIOUOptions({}, [currentUserEmail, email], [CONST.BETAS.IOU]);
return iouOptions.length === 0;
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions({}, [currentUserEmail, email], [CONST.BETAS.IOU]);
return moneyRequestOptions.length === 0;
});
expect(allEmpty).toBe(true);
});

it('no participants except self', () => {
const iouOptions = ReportUtils.getIOUOptions({}, [currentUserEmail], [CONST.BETAS.IOU]);
expect(iouOptions.length).toBe(0);
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions({}, [currentUserEmail], [CONST.BETAS.IOU]);
expect(moneyRequestOptions.length).toBe(0);
});

it('no iou permission', () => {
const iouOptions = ReportUtils.getIOUOptions({}, [currentUserEmail, participants], []);
expect(iouOptions.length).toBe(0);
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions({}, [currentUserEmail, participants], []);
expect(moneyRequestOptions.length).toBe(0);
});
});

Expand All @@ -353,42 +353,43 @@ describe('ReportUtils', () => {
...LHNTestUtils.getFakeReport(),
chatType,
};
const iouOptions = ReportUtils.getIOUOptions(report, [currentUserEmail, participants[0]], [CONST.BETAS.IOU]);
return iouOptions.length === 1 && iouOptions.includes(CONST.IOU.IOU_TYPE.SPLIT);
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, [currentUserEmail, participants[0]], [CONST.BETAS.IOU]);
return moneyRequestOptions.length === 1 && moneyRequestOptions.includes(CONST.IOU.IOU_TYPE.SPLIT);
});
expect(onlyHaveSplitOption).toBe(true);
});

it('has multiple participants exclude self', () => {
const iouOptions = ReportUtils.getIOUOptions({}, [currentUserEmail, ...participants], [CONST.BETAS.IOU]);
expect(iouOptions.length).toBe(1);
expect(iouOptions.includes(CONST.IOU.IOU_TYPE.SPLIT)).toBe(true);
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions({}, [currentUserEmail, ...participants], [CONST.BETAS.IOU]);
expect(moneyRequestOptions.length).toBe(1);
expect(moneyRequestOptions.includes(CONST.IOU.IOU_TYPE.SPLIT)).toBe(true);
});
});

describe('return only iou request option if', () => {
it(' does not have iou send permission', () => {
const iouOptions = ReportUtils.getIOUOptions({}, [currentUserEmail, participants], [CONST.BETAS.IOU]);
expect(iouOptions.length).toBe(1);
expect(iouOptions.includes(CONST.IOU.IOU_TYPE.REQUEST)).toBe(true);
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions({}, [currentUserEmail, participants], [CONST.BETAS.IOU]);
expect(moneyRequestOptions.length).toBe(1);
expect(moneyRequestOptions.includes(CONST.IOU.IOU_TYPE.REQUEST)).toBe(true);
});

it('a policy expense chat', () => {
const report = {
...LHNTestUtils.getFakeReport(),
chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
isOwnPolicyExpenseChat: true,
};
const iouOptions = ReportUtils.getIOUOptions(report, [currentUserEmail, participants], [CONST.BETAS.IOU, CONST.BETAS.IOU_SEND]);
expect(iouOptions.length).toBe(1);
expect(iouOptions.includes(CONST.IOU.IOU_TYPE.REQUEST)).toBe(true);
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, [currentUserEmail, participants], [CONST.BETAS.IOU, CONST.BETAS.IOU_SEND]);
expect(moneyRequestOptions.length).toBe(1);
expect(moneyRequestOptions.includes(CONST.IOU.IOU_TYPE.REQUEST)).toBe(true);
});
});

it('return both iou send and request money', () => {
const iouOptions = ReportUtils.getIOUOptions({}, [currentUserEmail, participants], [CONST.BETAS.IOU, CONST.BETAS.IOU_SEND]);
expect(iouOptions.length).toBe(2);
expect(iouOptions.includes(CONST.IOU.IOU_TYPE.REQUEST)).toBe(true);
expect(iouOptions.includes(CONST.IOU.IOU_TYPE.SEND)).toBe(true);
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions({}, [currentUserEmail, participants], [CONST.BETAS.IOU, CONST.BETAS.IOU_SEND]);
expect(moneyRequestOptions.length).toBe(2);
expect(moneyRequestOptions.includes(CONST.IOU.IOU_TYPE.REQUEST)).toBe(true);
expect(moneyRequestOptions.includes(CONST.IOU.IOU_TYPE.SEND)).toBe(true);
});
});

Expand Down

0 comments on commit f327eb0

Please sign in to comment.