diff --git a/src/components/ReportWelcomeText.js b/src/components/ReportWelcomeText.js index 560c93813819..3c6dc7a763af 100644 --- a/src/components/ReportWelcomeText.js +++ b/src/components/ReportWelcomeText.js @@ -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 ( <> @@ -132,7 +132,7 @@ const ReportWelcomeText = (props) => { ))} )} - {(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)) && ( {/* Need to confirm copy for the below with marketing, and then add to translations. */} {props.translate('reportActionsView.usePlusButton')} diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 43ba811e914d..752ceddd79f8 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -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] : []), ]; } @@ -1712,5 +1723,6 @@ export { getParsedComment, getFullSizeAvatar, getSmallSizeAvatar, - getIOUOptions, + getMoneyRequestOptions, + canRequestMoney, }; diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 4e57dba3b159..c8352a6fa69b 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -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); @@ -332,7 +332,7 @@ class ReportActionCompose extends React.Component { * @param {Array} reportParticipants * @returns {Array} */ - getIOUOptions(reportParticipants) { + getMoneyRequestOptions(reportParticipants) { const options = { [CONST.IOU.IOU_TYPE.SPLIT]: { icon: Expensicons.Receipt, @@ -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]); } /** @@ -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'), diff --git a/tests/unit/ReportUtilsTest.js b/tests/unit/ReportUtilsTest.js index b4383b3c0fd4..1701793edfd1 100644 --- a/tests/unit/ReportUtilsTest.js +++ b/tests/unit/ReportUtilsTest.js @@ -308,7 +308,7 @@ describe('ReportUtils', () => { }); }); - describe('getIOUOptions', () => { + describe('getMoneyRequestOptions', () => { const participants = _.keys(participantsPersonalDetails); beforeAll(() => { @@ -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); }); }); @@ -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); }); });