From bccd150adff8e5bbb071f4c937289ccbbeed9ef4 Mon Sep 17 00:00:00 2001 From: truph01 Date: Wed, 24 Jun 2026 16:07:17 +0700 Subject: [PATCH] feat: Add Tax, Billable, and Reimbursable selectors in the Split --- .../API/parameters/SplitTransactionParams.ts | 3 + src/libs/actions/IOU/SplitExpenseItems.ts | 18 ++++ .../actions/IOU/SplitTransactionUpdate.ts | 3 + src/pages/iou/SplitExpenseEditPage.tsx | 86 ++++++++++++++++++- src/types/onyx/IOU.ts | 9 ++ 5 files changed, 115 insertions(+), 4 deletions(-) diff --git a/src/libs/API/parameters/SplitTransactionParams.ts b/src/libs/API/parameters/SplitTransactionParams.ts index e7e9c45870dd..5932c766ef19 100644 --- a/src/libs/API/parameters/SplitTransactionParams.ts +++ b/src/libs/API/parameters/SplitTransactionParams.ts @@ -14,6 +14,9 @@ type SplitTransactionSplitParam = { modifiedExpenseReportActionID?: string; reimbursable?: boolean; billable?: boolean; + taxCode?: string; + taxAmount?: number; + taxValue?: string; reportID?: string; quantity?: number; customUnitRateID?: string; diff --git a/src/libs/actions/IOU/SplitExpenseItems.ts b/src/libs/actions/IOU/SplitExpenseItems.ts index aca25c7e3b5d..979f5ca6c28f 100644 --- a/src/libs/actions/IOU/SplitExpenseItems.ts +++ b/src/libs/actions/IOU/SplitExpenseItems.ts @@ -192,6 +192,9 @@ function initSplitExpenseItemData( reportID: reportID ?? transaction?.reportID ?? String(CONST.DEFAULT_NUMBER_ID), reimbursable: transactionDetails?.reimbursable, billable: transactionDetails?.billable, + taxCode: transactionDetails?.taxCode, + taxAmount: transactionDetails?.taxAmount, + taxValue: transactionDetails?.taxValue, customUnit: customUnit ?? transaction?.comment?.customUnit ?? undefined, waypoints: transaction?.comment?.waypoints ?? undefined, odometerStart: transaction?.comment?.odometerStart ?? undefined, @@ -230,6 +233,11 @@ function initDraftSplitExpenseDataForEdit(draftTransaction: OnyxEntry) { + Onyx.merge(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`, fields); +} + export { updateSplitExpenseDistanceFromAmount, initSplitExpenseItemData, @@ -731,4 +748,5 @@ export { updateSplitExpenseField, updateSplitExpenseAmountField, clearSplitTransactionDraftErrors, + updateSplitExpenseDraftField, }; diff --git a/src/libs/actions/IOU/SplitTransactionUpdate.ts b/src/libs/actions/IOU/SplitTransactionUpdate.ts index 45b1f71b6466..0c6a424b7088 100644 --- a/src/libs/actions/IOU/SplitTransactionUpdate.ts +++ b/src/libs/actions/IOU/SplitTransactionUpdate.ts @@ -258,6 +258,9 @@ function updateSplitTransactions({ }, reimbursable: split?.reimbursable, billable: split?.billable, + taxCode: split?.taxCode, + taxAmount: split?.taxAmount, + taxValue: split?.taxValue, quantity: split.customUnit?.quantity ?? undefined, customUnitRateID: split.customUnit?.customUnitRateID, odometerStart: split.odometerStart, diff --git a/src/pages/iou/SplitExpenseEditPage.tsx b/src/pages/iou/SplitExpenseEditPage.tsx index f9fa600f70ee..9371f6d8b4b5 100644 --- a/src/pages/iou/SplitExpenseEditPage.tsx +++ b/src/pages/iou/SplitExpenseEditPage.tsx @@ -9,6 +9,8 @@ import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import {useSearchResultsContext} from '@components/Search/SearchContext'; +import Switch from '@components/Switch'; +import Text from '@components/Text'; import useAllTransactions from '@hooks/useAllTransactions'; import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; @@ -24,24 +26,25 @@ import useReportOrReportDraft from '@hooks/useReportOrReportDraft'; import useSplitEffectivePolicy from '@hooks/useSplitEffectivePolicy'; import useThemeStyles from '@hooks/useThemeStyles'; import type {ViolationField} from '@hooks/useViolations'; -import {initDraftSplitExpenseDataForEdit, removeSplitExpenseField, updateSplitExpenseField} from '@libs/actions/IOU/SplitExpenseItems'; +import {initDraftSplitExpenseDataForEdit, removeSplitExpenseField, updateSplitExpenseDraftField, updateSplitExpenseField} from '@libs/actions/IOU/SplitExpenseItems'; import {openPolicyCategoriesPage} from '@libs/actions/Policy/Category'; import {openPolicyTagsPage} from '@libs/actions/Policy/Tag'; import {getDecodedLeafCategoryName, isCategoryDescriptionRequired, isCategoryMissing} from '@libs/CategoryUtils'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; +import {isBillableEnabledOnPolicy} from '@libs/MoneyRequestReportUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SplitExpenseParamList} from '@libs/Navigation/types'; import {hasEnabledOptions} from '@libs/OptionsListUtils'; import Parser from '@libs/Parser'; -import {getDistanceRateCustomUnitRate, getTagLists, hasAnyPaidPolicy, isGroupPolicyByType} from '@libs/PolicyUtils'; +import {getDistanceRateCustomUnitRate, getTagLists, hasAnyPaidPolicy, isGroupPolicyByType, isTaxTrackingEnabled} from '@libs/PolicyUtils'; import {getReportName} from '@libs/ReportNameUtils'; import {isSplitAction} from '@libs/ReportSecondaryActionUtils'; import type {TransactionDetails} from '@libs/ReportUtils'; import {getParsedComment, getReportOrDraftReport, getTransactionDetails, isSelfDM} from '@libs/ReportUtils'; import {getTagVisibility, hasEnabledTags} from '@libs/TagsOptionsListUtils'; -import {getDistanceInMeters, getRateID, getTag, getTagForDisplay, isDistanceRequest, isManualDistanceRequest, isOdometerDistanceRequest} from '@libs/TransactionUtils'; +import {getDistanceInMeters, getRateID, getTag, getTagForDisplay, getTaxName, isDistanceRequest, isManualDistanceRequest, isOdometerDistanceRequest} from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -63,7 +66,7 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) { const [originalTransactionDraft] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${splitExpenseDraftTransaction?.comment?.originalTransactionID}`, undefined, [ splitExpenseDraftTransaction?.comment?.originalTransactionID, ]); - + console.log('>>>>>>>>>>>>>>>>>>', splitExpenseDraftTransaction); const splitExpenseDraftTransactionDetails = useMemo>(() => getTransactionDetails(splitExpenseDraftTransaction) ?? {}, [splitExpenseDraftTransaction]); const allTransactions = useAllTransactions(); @@ -164,6 +167,13 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) { const previousTagsVisibility = usePrevious(tagVisibility.map((v) => v.shouldShow)) ?? []; + const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat || isExpenseUnreported, effectivePolicy, isDistanceRequest(splitExpenseDraftTransaction), false, false); + const taxRatesDescription = effectivePolicy?.taxRates?.name; + const taxRateTitle = getTaxName(effectivePolicy, splitExpenseDraftTransaction); + + const shouldShowBillable = (isPolicyExpenseChat || isExpenseUnreported) && (!!splitExpenseDraftTransactionDetails?.billable || isBillableEnabledOnPolicy(effectivePolicy)); + const shouldShowReimbursable = (isPolicyExpenseChat || (isExpenseUnreported && !!effectivePolicy)) && effectivePolicy?.disabledFields?.reimbursable !== true; + const isDistance = isDistanceRequest(splitExpenseDraftTransaction); const isManualDistance = isManualDistanceRequest(splitExpenseDraftTransaction); const isOdometerDistance = isOdometerDistanceRequest(splitExpenseDraftTransaction); @@ -424,6 +434,74 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) { style={[styles.moneyRequestMenuItem]} titleStyle={styles.flex1} /> + {shouldShowTax && ( + { + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute( + CONST.IOU.ACTION.EDIT, + CONST.IOU.TYPE.SPLIT, + CONST.IOU.OPTIMISTIC_TRANSACTION_ID, + reportID, + Navigation.getActiveRoute(), + ), + ); + }} + style={[styles.moneyRequestMenuItem]} + titleStyle={styles.flex1} + /> + )} + {shouldShowTax && ( + { + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute( + CONST.IOU.ACTION.EDIT, + CONST.IOU.TYPE.SPLIT, + CONST.IOU.OPTIMISTIC_TRANSACTION_ID, + reportID, + Navigation.getActiveRoute(), + ), + ); + }} + style={[styles.moneyRequestMenuItem]} + titleStyle={styles.flex1} + /> + )} + {shouldShowReimbursable && ( + + {translate('common.reimbursable')} + { + updateSplitExpenseDraftField({reimbursable: value}); + }} + /> + + )} + {shouldShowBillable && ( + + {translate('common.billable')} + { + updateSplitExpenseDraftField({billable: value}); + }} + /> + + )}