diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index cba2359eb25..6448a62639d 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -5,6 +5,7 @@ import {format} from 'date-fns'; import _ from 'underscore'; import {View} from 'react-native'; import lodashGet from 'lodash/get'; +import Text from './Text'; import styles from '../styles/styles'; import * as ReportUtils from '../libs/ReportUtils'; import * as OptionsListUtils from '../libs/OptionsListUtils'; @@ -30,6 +31,7 @@ import Image from './Image'; import useLocalize from '../hooks/useLocalize'; import * as ReceiptUtils from '../libs/ReceiptUtils'; import categoryPropTypes from './categoryPropTypes'; +import Switch from './Switch'; import tagPropTypes from './tagPropTypes'; import ConfirmedRoute from './ConfirmedRoute'; import transactionPropTypes from './transactionPropTypes'; @@ -531,6 +533,16 @@ function MoneyRequestConfirmationList(props) { disabled={didConfirm || props.isReadOnly} /> )} + {canUseTags && !lodashGet(props.policy, 'disabledFields.defaultBillable', true) && ( + + {translate('common.billable')} + + + )} )} @@ -562,5 +574,8 @@ export default compose( transaction: { key: ({transactionID}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, }, + policy: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + }, }), )(MoneyRequestConfirmationList); diff --git a/src/languages/en.ts b/src/languages/en.ts index c31e39319a9..f9f6f1b130b 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -244,6 +244,7 @@ export default { showMore: 'Show more', merchant: 'Merchant', category: 'Category', + billable: 'Billable', tag: 'Tag', receipt: 'Receipt', replace: 'Replace', diff --git a/src/languages/es.ts b/src/languages/es.ts index d83104ff85e..2130c68d20c 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -234,6 +234,7 @@ export default { showMore: 'Mostrar más', merchant: 'Comerciante', category: 'Categoría', + billable: 'Facturable', tag: 'Etiqueta', receipt: 'Recibo', replace: 'Sustituir', diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index dccabd74772..c7553a22cb5 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -34,6 +34,7 @@ Onyx.connect({ * @param {String} [filename] * @param {String} [existingTransactionID] When creating a distance request, an empty transaction has already been created with a transactionID. In that case, the transaction here needs to have it's transactionID match what was already generated. * @param {String} [category] + * @param {Boolean} [billable] * @returns {Object} */ function buildOptimisticTransaction( @@ -49,6 +50,7 @@ function buildOptimisticTransaction( filename = '', existingTransactionID = null, category = '', + billable = false, ) { // transactionIDs are random, positive, 64-bit numeric strings. // Because JS can only handle 53-bit numbers, transactionIDs are strings in the front-end (just like reportActionID) @@ -77,6 +79,7 @@ function buildOptimisticTransaction( receipt, filename, category, + billable, }; } diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 3cefcd00ed6..8bbcb58f71f 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -98,6 +98,7 @@ function resetMoneyRequestInfo(id = '') { receiptPath: '', receiptSource: '', transactionID: '', + billable: null, }); } @@ -341,6 +342,7 @@ function buildOnyxDataForMoneyRequest( * @param {Object} [receipt] * @param {String} [existingTransactionID] * @param {String} [category] + * @param {Boolean} [billable] * @returns {Object} data * @returns {String} data.payerEmail * @returns {Object} data.iouReport @@ -368,6 +370,7 @@ function getMoneyRequestInformation( receipt = undefined, existingTransactionID = undefined, category = undefined, + billable = undefined, ) { const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login); const payerAccountID = Number(participant.accountID); @@ -433,6 +436,7 @@ function getMoneyRequestInformation( filename, existingTransactionID, category, + billable, ); const uniquePolicyRecentlyUsedCategories = allRecentlyUsedCategories @@ -600,8 +604,9 @@ function createDistanceRequest(report, participant, comment, created, transactio * @param {String} comment * @param {Object} [receipt] * @param {String} [category] + * @param {Boolean} [billable] */ -function requestMoney(report, amount, currency, created, merchant, payeeEmail, payeeAccountID, participant, comment, receipt = undefined, category = undefined) { +function requestMoney(report, amount, currency, created, merchant, payeeEmail, payeeAccountID, participant, comment, receipt = undefined, category = undefined, billable = undefined) { // If the report is iou or expense report, we should get the linked chat report to be passed to the getMoneyRequestInformation function const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report); const currentChatReport = isMoneyRequestReport ? ReportUtils.getReport(report.chatReportID) : report; @@ -618,6 +623,7 @@ function requestMoney(report, amount, currency, created, merchant, payeeEmail, p receipt, undefined, category, + billable, ); API.write( @@ -638,6 +644,7 @@ function requestMoney(report, amount, currency, created, merchant, payeeEmail, p reportPreviewReportActionID: reportPreviewAction.reportActionID, receipt, category, + billable, }, onyxData, ); @@ -1948,6 +1955,13 @@ function resetMoneyRequestCategory() { Onyx.merge(ONYXKEYS.IOU, {category: ''}); } +/** + * @param {Boolean} billable + */ +function setMoneyRequestBillable(billable) { + Onyx.merge(ONYXKEYS.IOU, {billable}); +} + /** * @param {Object[]} participants */ @@ -2032,6 +2046,7 @@ export { setMoneyRequestMerchant, setMoneyRequestCategory, resetMoneyRequestCategory, + setMoneyRequestBillable, setMoneyRequestParticipants, setMoneyRequestReceipt, createEmptyTransaction, diff --git a/src/pages/iou/steps/MoneyRequestConfirmPage.js b/src/pages/iou/steps/MoneyRequestConfirmPage.js index 38a5b9c82c0..fedcec8adad 100644 --- a/src/pages/iou/steps/MoneyRequestConfirmPage.js +++ b/src/pages/iou/steps/MoneyRequestConfirmPage.js @@ -77,6 +77,10 @@ function MoneyRequestConfirmPage(props) { if (policyExpenseChat) { Policy.openDraftWorkspaceRequest(policyExpenseChat.policyID); } + // Verification to reset billable with a default value, when value in IOU was changed + if (typeof props.iou.billable !== 'boolean') { + IOU.setMoneyRequestBillable(lodashGet(props.policy, 'defaultBillable', false)); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -135,6 +139,7 @@ function MoneyRequestConfirmPage(props) { trimmedComment, receipt, props.iou.category, + props.iou.billable, ); }, [ @@ -146,6 +151,7 @@ function MoneyRequestConfirmPage(props) { props.currentUserPersonalDetails.login, props.currentUserPersonalDetails.accountID, props.iou.category, + props.iou.billable, ], ); @@ -295,6 +301,8 @@ function MoneyRequestConfirmPage(props) { iouAmount={props.iou.amount} iouComment={props.iou.comment} iouCurrencyCode={props.iou.currency} + iouIsBillable={props.iou.billable} + onToggleBillable={IOU.setMoneyRequestBillable} iouCategory={props.iou.category} iouTag={props.iou.tag} onConfirm={createTransaction} @@ -364,4 +372,9 @@ export default compose( key: `${ONYXKEYS.COLLECTION.SELECTED_TAB}${CONST.TAB.RECEIPT_TAB_ID}`, }, }), + withOnyx({ + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, + }, + }), )(MoneyRequestConfirmPage);