diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 966f5f4340a7..da64c5b7f168 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'; @@ -530,6 +532,16 @@ function MoneyRequestConfirmationList(props) { disabled={didConfirm || props.isReadOnly} /> )} + {canUseTags && !lodashGet(props.policy, 'disabledFields.defaultBillable', true) && ( + + {translate('common.billable')} + + + )} )} @@ -561,5 +573,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 03adaa1e66b1..38048204c6ff 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 7315c42cebab..23b83a847f66 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 4ca8b48d284e..e426148dac30 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 8f18119203be..490f78442df2 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -95,6 +95,7 @@ function resetMoneyRequestInfo(id = '') { receiptPath: '', receiptSource: '', transactionID: '', + billable: null, }); } @@ -338,6 +339,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 @@ -365,6 +367,7 @@ function getMoneyRequestInformation( receipt = undefined, existingTransactionID = undefined, category = undefined, + billable = undefined, ) { const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login); const payerAccountID = Number(participant.accountID); @@ -430,6 +433,7 @@ function getMoneyRequestInformation( filename, existingTransactionID, category, + billable, ); const uniquePolicyRecentlyUsedCategories = allRecentlyUsedCategories @@ -597,8 +601,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; @@ -615,6 +620,7 @@ function requestMoney(report, amount, currency, created, merchant, payeeEmail, p receipt, undefined, category, + billable, ); API.write( @@ -635,6 +641,7 @@ function requestMoney(report, amount, currency, created, merchant, payeeEmail, p reportPreviewReportActionID: reportPreviewAction.reportActionID, receipt, category, + billable, }, onyxData, ); @@ -1945,6 +1952,13 @@ function resetMoneyRequestCategory() { Onyx.merge(ONYXKEYS.IOU, {category: ''}); } +/** + * @param {Boolean} billable + */ +function setMoneyRequestBillable(billable) { + Onyx.merge(ONYXKEYS.IOU, {billable}); +} + /** * @param {Object[]} participants */ @@ -2027,6 +2041,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 1c653271ea7d..e3ceae70fc53 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, ], ); @@ -283,6 +289,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} @@ -352,4 +360,9 @@ export default compose( key: `${ONYXKEYS.COLLECTION.SELECTED_TAB}${CONST.TAB.RECEIPT_TAB_ID}`, }, }), + withOnyx({ + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, + }, + }), )(MoneyRequestConfirmPage);