Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add edit fields for tax tracking #33927

Merged
merged 196 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
196 commits
Select commit Hold shift + click to select a range
d60ca6c
remove unused split transaction draft
teneeto Jan 4, 2024
d849ea3
use StepScreenWrapper and backTo for back navigation
teneeto Jan 4, 2024
f558497
use StepScreenWrapper and backTo for back navigation
teneeto Jan 4, 2024
de255d7
remove unused transaction prop
teneeto Jan 4, 2024
b1df50f
use policyTaxRates directly in taxPicker
teneeto Jan 4, 2024
22c290e
add EditRequestTaxAmount Page
teneeto Jan 4, 2024
42f79ba
add EditRequestTaxRate Page
teneeto Jan 4, 2024
3226d9c
add edit Tax amount and rate page to edit request page
teneeto Jan 4, 2024
9130f73
add edit Tax amount and rate fields and route to pages
teneeto Jan 4, 2024
4b8a102
fix lint
teneeto Jan 4, 2024
1f6966a
remove is editing check
teneeto Jan 4, 2024
74f63f2
complete types for policyTaxRates and Transaction
teneeto Jan 4, 2024
f2503f4
add getDefaultTaxName func. in TransactionUtils
teneeto Jan 4, 2024
f10e413
use getDefaultTaxName
teneeto Jan 4, 2024
13dccd8
remove unused Navigation import
teneeto Jan 4, 2024
f7acd15
resolve conflicts
teneeto Jan 4, 2024
7c154f1
remove tax amount calculation implementation from requestStepAmount
teneeto Jan 4, 2024
d501ad7
set tax Amount
teneeto Jan 4, 2024
13deb83
add Tax amount and Code API for updates
teneeto Jan 4, 2024
084c73f
Merge branch 'main' of github.com:teneeto/App into feat/31672/add-edi…
teneeto Jan 4, 2024
af7deed
Merge branch 'main' of github.com:teneeto/App into feat/31672/add-edi…
teneeto Jan 8, 2024
3615446
Merge branch 'main' of github.com:teneeto/App into feat/31672/add-edi…
teneeto Jan 8, 2024
fc3e593
add function to check if tax rate has enabled options
teneeto Jan 8, 2024
a6daa02
add defaults for tax rate and amount and amount title
teneeto Jan 8, 2024
91205da
add defaults for tax rate and amount and amount title
teneeto Jan 8, 2024
24e7c07
add update functions to taxAmount and taxRate
teneeto Jan 8, 2024
101aa5b
update default amount and taxAmount
teneeto Jan 8, 2024
199c68a
Merge branch 'main' of github.com:teneeto/App into feat/31672/add-edi…
teneeto Jan 8, 2024
61bf476
use function for tax policy
teneeto Jan 9, 2024
e859129
make isTaxTrackingEnabled optional
teneeto Jan 9, 2024
48bdafb
Merge branch 'main' of github.com:teneeto/App into feat/31672/add-edi…
teneeto Jan 9, 2024
fab2391
add tax amount and code type to Transaction types
teneeto Jan 10, 2024
9fd85f9
get tax amount abs value and tax code
teneeto Jan 10, 2024
33cf5c4
add new fields in getTransactionDetails
teneeto Jan 10, 2024
9d6e5b0
get and use new tax amount and code fields from getTransactionDetails
teneeto Jan 10, 2024
25cb89e
add getTaxName to TransactionUtils
teneeto Jan 10, 2024
9a9b182
use getTaxName
teneeto Jan 10, 2024
f723d0f
Update src/components/MoneyTemporaryForRefactorRequestConfirmationLis…
teneeto Jan 10, 2024
cc2831e
Update src/libs/TransactionUtils.ts
teneeto Jan 10, 2024
1270f49
Update src/libs/TransactionUtils.ts
teneeto Jan 10, 2024
37d6513
Update src/types/onyx/Policy.ts
teneeto Jan 10, 2024
584df42
Update src/pages/EditRequestPage.js
teneeto Jan 10, 2024
a7e48a5
Merge branch 'main' of github.com:teneeto/App into feat/31672/add-edi…
teneeto Jan 16, 2024
1e8ffbc
fix prettier
teneeto Jan 16, 2024
a5d5c80
Merge branch 'main' of github.com:teneeto/App into feat/31672/add-edi…
teneeto Jan 17, 2024
dd1104c
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Jan 19, 2024
b889c2d
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Jan 31, 2024
fb08033
remove duplicate identifier
teneeto Jan 31, 2024
70c02fd
fix lint and tsc
teneeto Jan 31, 2024
8bb0b34
migrate EditRequestTaxAmountPage to tsc
teneeto Jan 31, 2024
1f1df34
migrate EditRequestTaxRatePage to tsc
teneeto Jan 31, 2024
cff7f1b
fix tsc errors
teneeto Jan 31, 2024
348e4b3
fix lint
teneeto Jan 31, 2024
22fd57a
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 4, 2024
a73e36e
export tax rates types in onyx types
teneeto Feb 4, 2024
3e19f56
add PolicyTaxRates to ONYX KEYS
teneeto Feb 5, 2024
ec6cf4f
fix typescript
teneeto Feb 5, 2024
568b8c0
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 5, 2024
0e91974
use optional chaining
teneeto Feb 5, 2024
e16f07c
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 7, 2024
b3dbe26
add tax amount API types
teneeto Feb 7, 2024
0bdef87
update tax request types
teneeto Feb 7, 2024
3293311
add taxCode and taxAmount to getUpdatedTransaction
teneeto Feb 7, 2024
9abeb11
update Tax Amount Menu Item Description in ConfirmationList
teneeto Feb 7, 2024
5976882
update Tax Amount Menu Item Description in MoneyRequestView
teneeto Feb 7, 2024
a649fd2
add pending action for taxCode
teneeto Feb 7, 2024
c1bd0a5
add pending action for taxAmount
teneeto Feb 7, 2024
d8e7425
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 19, 2024
68ef4f5
fix bad merge for IOURequestStepAmount
teneeto Feb 19, 2024
a105896
fix bad merge for EditRequestPage
teneeto Feb 19, 2024
58af4ad
use trackingEnabled for chrcking if tax tracking is enabled
teneeto Feb 19, 2024
81fb82c
fix prettier
teneeto Feb 19, 2024
88c0914
fix lint
teneeto Feb 19, 2024
0381cb3
fix typecheck
teneeto Feb 19, 2024
b479e69
use taxRates from policy key for MoneyTemporaryForRefactorRequestConf…
teneeto Feb 20, 2024
c915047
use taxRates from policy key for MoneyTemporaryForRefactorRequestConf…
teneeto Feb 20, 2024
4e57d4a
add taxRates propTypes to policy for MoneyTemporaryForRefactorRequest…
teneeto Feb 20, 2024
17281f6
remove unused Fragment import for MoneyTemporaryForRefactorRequestCon…
teneeto Feb 20, 2024
9b3ac12
update taxAmount Description for MoneyTemporaryForRefactorRequestConf…
teneeto Feb 20, 2024
af4783a
use taxRates from policy key for MoneyRequestRequestConfirmationList
teneeto Feb 20, 2024
dbd68de
remove policyTaxRates props and ONYX key for MoneyRequestConfirmation…
teneeto Feb 20, 2024
dfb486a
update taxRates propTypes to policy for MoneyTemporaryForRefactorRequ…
teneeto Feb 20, 2024
e252453
update taxRates propTypes to policy for MoneyRequestConfirmationList
teneeto Feb 20, 2024
a811a81
add taxRates types to policy
teneeto Feb 20, 2024
b4e61f4
use taxRates from policy key for MoneyRequestView
teneeto Feb 20, 2024
0cd0f45
remove policyTaxRates props and ONYX key for MoneyRequestView
teneeto Feb 20, 2024
a175dac
fix lint warning for MoneyRequestView
teneeto Feb 20, 2024
8480869
use taxRates from policy key for taxPicker
teneeto Feb 20, 2024
dc0ec64
update TaxPicker PropTypes
teneeto Feb 20, 2024
94a2e3f
fix prettier
teneeto Feb 20, 2024
3d5af3b
use taxRates from policy key for EditRequestPage
teneeto Feb 21, 2024
446c7c8
remove undefined props usage for EditRequestPage
teneeto Feb 21, 2024
3e4c6c6
use taxRates from policy key for IOURequestStepTaxAmountPage
teneeto Feb 21, 2024
7a1cb79
add taxRates propTypes to policy for IOURequestStepTaxAmountPage
teneeto Feb 21, 2024
7376d2e
add missing imports for IOURequestStepTaxAmountPage
teneeto Feb 21, 2024
cd2883c
add policy onyx props for IOURequestStepTaxRatePage
teneeto Feb 21, 2024
7c88b5d
use taxRates from policy key for IOURequestStepTaxRatePage
teneeto Feb 21, 2024
3d18ec4
remove taxRates props for IOURequestStepTaxRatePage
teneeto Feb 21, 2024
3c8c714
add policy props types for IOURequestStepTaxRatePage
teneeto Feb 21, 2024
1df6ec5
remove policyTaxRates onyx keys for IOURequestStepTaxRatePage
teneeto Feb 21, 2024
30ddf52
add missing proptypes for IOURequestStepTaxRatePage
teneeto Feb 21, 2024
e54d9bf
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 21, 2024
aa08326
remove tax rates types and keys
teneeto Feb 21, 2024
be1c293
use BaseTextInputRef for text input ref
teneeto Feb 21, 2024
5e2f603
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 22, 2024
8266baf
update Tax picker prop Types
teneeto Feb 22, 2024
7abbcb9
remove unexoected token
teneeto Feb 22, 2024
78f8232
update tax rates var
teneeto Feb 22, 2024
60ab450
update tax rate name
teneeto Feb 22, 2024
1622a12
update tax rate name
teneeto Feb 22, 2024
1127e7c
update tax rate name
teneeto Feb 22, 2024
e7be70e
add taxRates types to Policy
teneeto Feb 22, 2024
76cd4d0
export policy tax rates types from onyx types
teneeto Feb 22, 2024
b831569
@update getFiltered options for taxRates
teneeto Feb 22, 2024
45ea252
destructure taxRatesOptions from options utils
teneeto Feb 22, 2024
b3f55a8
update OptionsListUtils tax rate types
teneeto Feb 22, 2024
09364ce
update TransactionUtils tax rate types
teneeto Feb 22, 2024
5f123ff
update getDefaultTaxName parameter name
teneeto Feb 22, 2024
071ff8b
update taxRates in policy types
teneeto Feb 22, 2024
84c51b0
update taxRates name in OptionListUtilsTest
teneeto Feb 22, 2024
f8b66da
add taxRate and oldTaxRate to ExpenseOriginalMessage
teneeto Feb 22, 2024
2527914
add taxRate system message
teneeto Feb 22, 2024
4f051e6
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 26, 2024
2fdb828
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 26, 2024
c0cc219
fix lint
teneeto Feb 26, 2024
834f55b
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 28, 2024
0fd03c0
add taxAmount and oldTaxAmount types to ExpenseOriginalMessage
teneeto Feb 28, 2024
8b212f5
add taxAmount edit request system message
teneeto Feb 28, 2024
f05fdfe
use taxAmount
teneeto Feb 28, 2024
5f96627
add allReports from Onyx
teneeto Feb 28, 2024
d04d366
add getTaxAmount Func
teneeto Feb 28, 2024
91aa036
use getTaxAmount for taxAmount
teneeto Feb 28, 2024
dc5fc19
use getTaxAmount for oldTaxAmount
teneeto Feb 28, 2024
70f9cde
format string with currency for taxAmount
teneeto Feb 28, 2024
184a4e1
format string with currency for oldTaxAmount
teneeto Feb 28, 2024
55886f3
set valueInQuotes to false
teneeto Feb 28, 2024
9d9703a
fix duplicate import
teneeto Feb 28, 2024
e8e279b
handle oldTaxAmount
teneeto Feb 28, 2024
d783a3c
add isCurrencyPressable prop
teneeto Feb 28, 2024
823770b
use isCurrencyPressable prop to hide currency dropdown
teneeto Feb 28, 2024
bddbd10
make onCurrencyButtonPress optional
teneeto Feb 28, 2024
c3c4a07
remove onCurrencyButtonPress and props values
teneeto Feb 28, 2024
687d846
remove onNavigateToCurrency to Props
teneeto Feb 28, 2024
61e28f7
update Tax Amount Params
teneeto Feb 28, 2024
64408ca
update getTaxAmount args...
teneeto Feb 28, 2024
211308e
remove duplicate getTaxAmount
teneeto Feb 28, 2024
5de645f
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Feb 28, 2024
e720881
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 4, 2024
9dd9dad
remove ts-expect-error
teneeto Mar 4, 2024
16c422e
fix tax picker types
teneeto Mar 4, 2024
8401018
add useCallback for updateTaxAmount and updateTaxRate
teneeto Mar 6, 2024
484c8ca
add tax types to OriginalMessageModifiedExpense
teneeto Mar 6, 2024
e7e62a8
update getTaxAmount func
teneeto Mar 6, 2024
450f849
add optimistic data for tax amount and code
teneeto Mar 6, 2024
d03d84a
update modified tax amount
teneeto Mar 6, 2024
452e0e0
fix prettier
teneeto Mar 6, 2024
9f65680
select tax value and pass to original message
teneeto Mar 6, 2024
f1e1f92
pass polciy props
teneeto Mar 6, 2024
89358cb
fix lint
teneeto Mar 6, 2024
14b7ef0
avoid redundant API call if same tax rate is selected
teneeto Mar 7, 2024
f1179ce
avoid redundant API call if same tax amount inputed is selected
teneeto Mar 7, 2024
8fb87b1
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 7, 2024
4058346
do not update taxAmount more than default taxAmount based on actual e…
teneeto Mar 7, 2024
5021d91
remove optional chaining
teneeto Mar 7, 2024
b52b28c
check and return if same tax rate is selected
teneeto Mar 12, 2024
5626316
add option for transaction draft
teneeto Mar 12, 2024
9ecc983
optimistically update tax amount when expense amount is edited
teneeto Mar 12, 2024
dea2b66
add isDraft option for IOU.setMoneyRequestTaxAmount
teneeto Mar 12, 2024
72e7b68
add useCallback missing deps
teneeto Mar 12, 2024
69a99ab
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 12, 2024
0cdee35
pass isDraft argument
teneeto Mar 13, 2024
6a849bf
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 13, 2024
b3bffa6
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 15, 2024
33e4ad7
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 15, 2024
4cae9b2
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 21, 2024
635c74b
No taxRates props needed for taxPicker
teneeto Mar 21, 2024
9abf7f5
remove duplicate taxRates
teneeto Mar 22, 2024
9289221
remove duplicate onyxTypes import
teneeto Mar 22, 2024
c15a61c
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 22, 2024
9d8c337
fix taxAmount validation showing negative
teneeto Mar 22, 2024
90fb9a1
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 25, 2024
00d5cea
fix Taxpicker
teneeto Mar 25, 2024
c0b17f5
fix taxpicker options list utils
teneeto Mar 26, 2024
23c3ff3
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 26, 2024
1e71039
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Mar 27, 2024
a514dbb
fix money request tax amount edit issue
teneeto Mar 28, 2024
b8cfc54
update transformedTaxRates
teneeto Mar 28, 2024
7eab667
remove selectedTaxRate from taxPicker sections
teneeto Mar 28, 2024
0e0c2ee
update getDefaultTaxName
teneeto Mar 28, 2024
e0868f6
requestMoney should send correct taxCode payload
teneeto Mar 28, 2024
54b8b9f
update taxRate title
teneeto Mar 28, 2024
3a12074
fix lint
teneeto Mar 28, 2024
136898c
use modified expense amount
teneeto Mar 28, 2024
ce6466b
read currency from reportActionOriginalMessage
teneeto Mar 29, 2024
be58144
fix lint
teneeto Mar 29, 2024
3188357
Merge branch 'main' of github.com:teneeto/Expensify into feat/31672/a…
teneeto Apr 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1827,6 +1827,8 @@ const CONST = {
RECEIPT: 'receipt',
DISTANCE: 'distance',
TAG: 'tag',
TAX_RATE: 'taxRate',
TAX_AMOUNT: 'taxAmount',
},
FOOTER: {
EXPENSE_MANAGEMENT_URL: `${USE_EXPENSIFY_URL}/expense-management`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
import usePermissions from '@hooks/usePermissions';
import usePrevious from '@hooks/usePrevious';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
Expand All @@ -21,6 +22,7 @@ import * as MoneyRequestUtils from '@libs/MoneyRequestUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import {isTaxPolicyEnabled} from '@libs/PolicyUtils';
import * as ReceiptUtils from '@libs/ReceiptUtils';
import * as ReportUtils from '@libs/ReportUtils';
import playSound, {SOUNDS} from '@libs/Sound';
Expand Down Expand Up @@ -204,6 +206,11 @@ const defaultProps = {
isPolicyExpenseChat: false,
};

const getTaxAmount = (transaction, defaultTaxValue) => {
const percentage = (transaction.taxRate ? transaction.taxRate.data.value : defaultTaxValue) || '';
return TransactionUtils.calculateTaxAmount(percentage, transaction.amount);
};

function MoneyTemporaryForRefactorRequestConfirmationList({
bankAccountRoute,
canModifyParticipants,
Expand Down Expand Up @@ -277,7 +284,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
const shouldShowTags = useMemo(() => isPolicyExpenseChat && OptionsListUtils.hasEnabledTags(policyTagLists), [isPolicyExpenseChat, policyTagLists]);

// A flag for showing tax rate
const shouldShowTax = isPolicyExpenseChat && policy && lodashGet(policy, 'tax.trackingEnabled', policy.isTaxTrackingEnabled);
const shouldShowTax = isTaxPolicyEnabled(isPolicyExpenseChat, policy);

// A flag for showing the billable field
const shouldShowBillable = !lodashGet(policy, 'disabledFields.defaultBillable', true);
Expand All @@ -292,9 +299,9 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
);
const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction.taxAmount, iouCurrencyCode);

const defaultTaxKey = taxRates.defaultExternalID;
const defaultTaxName = (defaultTaxKey && `${taxRates.taxes[defaultTaxKey].name} (${taxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || '';
const taxRateTitle = (transaction.taxRate && transaction.taxRate.text) || defaultTaxName;
const taxRateTitle = TransactionUtils.getDefaultTaxName(taxRates, transaction);

const previousTransactionAmount = usePrevious(transaction.amount);

const isFocused = useIsFocused();
const [formError, setFormError] = useState('');
Expand Down Expand Up @@ -362,6 +369,18 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
IOU.setMoneyRequestAmount_temporaryForRefactor(transaction.transactionID, amount, currency);
}, [shouldCalculateDistanceAmount, distance, rate, unit, transaction, currency]);

// Calculate and set tax amount in transaction draft
useEffect(() => {
const taxAmount = getTaxAmount(transaction, taxRates.defaultValue);
const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount));

if (transaction.taxAmount && previousTransactionAmount === transaction.amount) {
return IOU.setMoneyRequestTaxAmount(transaction.transactionID, transaction.taxAmount, true);
}

IOU.setMoneyRequestTaxAmount(transaction.transactionID, amountInSmallestCurrencyUnits, true);
}, [taxRates.defaultValue, transaction, previousTransactionAmount]);

/**
* Returns the participants with amount
* @param {Array} participants
Expand Down Expand Up @@ -855,7 +874,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
key={`${taxRates.name}${formattedTaxAmount}`}
shouldShowRightIcon={!isReadOnly}
title={formattedTaxAmount}
description={taxRates.name}
description={translate('iou.taxAmount')}
style={[styles.moneyRequestMenuItem]}
titleStyle={styles.flex1}
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams()))}
Expand Down
40 changes: 40 additions & 0 deletions src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import * as CardUtils from '@libs/CardUtils';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import {isTaxPolicyEnabled} from '@libs/PolicyUtils';
import * as ReceiptUtils from '@libs/ReceiptUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
Expand Down Expand Up @@ -100,6 +101,8 @@ function MoneyRequestView({
const {
created: transactionDate,
amount: transactionAmount,
taxAmount: transactionTaxAmount,
taxCode: transactionTaxCode,
currency: transactionCurrency,
comment: transactionDescription,
merchant: transactionMerchant,
Expand All @@ -119,6 +122,15 @@ function MoneyRequestView({
const isCardTransaction = TransactionUtils.isCardTransaction(transaction);
const cardProgramName = isCardTransaction && transactionCardID !== undefined ? CardUtils.getCardDescription(transactionCardID) : '';
const isApproved = ReportUtils.isReportApproved(moneyRequestReport);
const taxRates = policy?.taxRates;
const formattedTaxAmount = transactionTaxAmount ? CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency) : '';

const taxRatesDescription = taxRates?.name;
const taxRateTitle =
taxRates &&
(transactionTaxCode === taxRates?.defaultExternalID
? transaction && TransactionUtils.getDefaultTaxName(taxRates, transaction)
: transactionTaxCode && TransactionUtils.getTaxName(taxRates?.taxes, transactionTaxCode));

// Flags for allowing or disallowing editing a money request
const isSettled = ReportUtils.isSettled(moneyRequestReport?.reportID);
Expand Down Expand Up @@ -147,6 +159,9 @@ function MoneyRequestView({
const shouldShowTag = isPolicyExpenseChat && (transactionTag || OptionsListUtils.hasEnabledTags(policyTagLists));
const shouldShowBillable = isPolicyExpenseChat && (!!transactionBillable || !(policy?.disabledFields?.defaultBillable ?? true));

// A flag for showing tax rate
const shouldShowTax = isTaxPolicyEnabled(isPolicyExpenseChat, policy) && transactionTaxCode && transactionTaxAmount;

const {getViolationsForField} = useViolations(transactionViolations ?? []);
const hasViolations = useCallback(
(field: ViolationField, data?: OnyxTypes.TransactionViolation['data']): boolean => !!canUseViolations && getViolationsForField(field, data).length > 0,
Expand Down Expand Up @@ -423,6 +438,31 @@ function MoneyRequestView({
/>
</OfflineWithFeedback>
)}
{shouldShowTax && (
<OfflineWithFeedback pendingAction={getPendingFieldAction('taxCode')}>
<MenuItemWithTopDescription
title={taxRateTitle ?? ''}
description={taxRatesDescription}
interactive={canEdit}
shouldShowRightIcon={canEdit}
titleStyle={styles.flex1}
onPress={() => Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.TAX_RATE))}
/>
</OfflineWithFeedback>
)}

{shouldShowTax && (
<OfflineWithFeedback pendingAction={getPendingFieldAction('taxAmount')}>
<MenuItemWithTopDescription
title={formattedTaxAmount ? formattedTaxAmount.toString() : ''}
description={translate('iou.taxAmount')}
interactive={canEdit}
shouldShowRightIcon={canEdit}
titleStyle={styles.flex1}
onPress={() => Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.TAX_AMOUNT))}
/>
</OfflineWithFeedback>
)}
{shouldShowBillable && (
<View style={[styles.flexRow, styles.optionRow, styles.justifyContentBetween, styles.alignItemsCenter, styles.ml5, styles.mr8]}>
<View>
Expand Down
53 changes: 32 additions & 21 deletions src/components/TaxPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import React, {useCallback, useMemo, useState} from 'react';
import React, {useMemo, useState} from 'react';
import {withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import type {EdgeInsets} from 'react-native-safe-area-context';
import useLocalize from '@hooks/useLocalize';
import useStyleUtils from '@hooks/useStyleUtils';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import CONST from '@src/CONST';
import type {TaxRatesWithDefault} from '@src/types/onyx';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Policy} from '@src/types/onyx';
import SelectionList from './SelectionList';
import RadioListItem from './SelectionList/RadioListItem';
import type {ListItem} from './SelectionList/types';

type TaxPickerProps = {
/** Collection of tax rates attached to a policy */
taxRates?: TaxRatesWithDefault;
type TaxPickerOnyxProps = {
/** The policy which the user has access to and which the report is tied to */
policy: OnyxEntry<Policy>;
};

type TaxPickerProps = TaxPickerOnyxProps & {
/** The selected tax rate of an expense */
selectedTaxRate?: string;

/** ID of the policy */
// eslint-disable-next-line react/no-unused-prop-types
policyID?: string;

/**
* Safe area insets required for reflecting the portion of the view,
* that is not covered by navigation bars, tab bars, toolbars, and other ancestor views.
Expand All @@ -27,55 +36,57 @@ type TaxPickerProps = {
onSubmit: (tax: ListItem) => void;
};

function TaxPicker({selectedTaxRate = '', taxRates, insets, onSubmit}: TaxPickerProps) {
function TaxPicker({selectedTaxRate = '', policy, insets, onSubmit}: TaxPickerProps) {
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const [searchValue, setSearchValue] = useState('');

const taxRates = policy?.taxRates;
const taxRatesCount = TransactionUtils.getEnabledTaxRateCount(taxRates?.taxes ?? {});
const isTaxRatesCountBelowThreshold = taxRatesCount < CONST.TAX_RATES_LIST_THRESHOLD;

const shouldShowTextInput = !isTaxRatesCountBelowThreshold;

const getTaxName = useCallback((key: string) => taxRates?.taxes[key]?.name, [taxRates?.taxes]);

const selectedOptions = useMemo(() => {
if (!selectedTaxRate) {
return [];
}

return [
{
name: getTaxName(selectedTaxRate),
name: selectedTaxRate,
enabled: true,
accountID: null,
},
];
}, [selectedTaxRate, getTaxName]);
}, [selectedTaxRate]);

const sections = useMemo(
() => OptionsListUtils.getTaxRatesSection(taxRates, selectedOptions as OptionsListUtils.Category[], searchValue, selectedTaxRate),
[taxRates, searchValue, selectedOptions, selectedTaxRate],
);
const sections = useMemo(() => OptionsListUtils.getTaxRatesSection(taxRates, selectedOptions as OptionsListUtils.Category[], searchValue), [taxRates, searchValue, selectedOptions]);

const headerMessage = OptionsListUtils.getHeaderMessageForNonUserList(sections[0].data.length > 0, searchValue);

const selectedOptionKey = useMemo(() => sections?.[0]?.data?.find((taxRate) => taxRate.searchText === selectedTaxRate)?.keyForList, [sections, selectedTaxRate]);

return (
<SelectionList
ListItem={RadioListItem}
onSelectRow={onSubmit}
initiallyFocusedOptionKey={selectedTaxRate}
sections={sections}
containerStyle={{paddingBottom: StyleUtils.getSafeAreaMargins(insets).marginBottom}}
textInputLabel={shouldShowTextInput ? translate('common.search') : undefined}
isRowMultilineSupported
headerMessage={headerMessage}
textInputValue={searchValue}
textInputLabel={shouldShowTextInput ? translate('common.search') : undefined}
onChangeText={setSearchValue}
onSelectRow={onSubmit}
ListItem={RadioListItem}
initiallyFocusedOptionKey={selectedOptionKey ?? undefined}
isRowMultilineSupported
containerStyle={{paddingBottom: StyleUtils.getSafeAreaMargins(insets).marginBottom}}
/>
);
}

TaxPicker.displayName = 'TaxPicker';

export default TaxPicker;
export default withOnyx<TaxPickerProps, TaxPickerOnyxProps>({
policy: {
key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
},
})(TaxPicker);
4 changes: 4 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ const WRITE_COMMANDS = {
UPDATE_MONEY_REQUEST_BILLABLE: 'UpdateMoneyRequestBillable',
UPDATE_MONEY_REQUEST_MERCHANT: 'UpdateMoneyRequestMerchant',
UPDATE_MONEY_REQUEST_TAG: 'UpdateMoneyRequestTag',
UPDATE_MONEY_REQUEST_TAX_AMOUNT: 'UpdateMoneyRequestTaxAmount',
UPDATE_MONEY_REQUEST_TAX_RATE: 'UpdateMoneyRequestTaxRate',
UPDATE_MONEY_REQUEST_DISTANCE: 'UpdateMoneyRequestDistance',
UPDATE_MONEY_REQUEST_CATEGORY: 'UpdateMoneyRequestCategory',
UPDATE_MONEY_REQUEST_DESCRIPTION: 'UpdateMoneyRequestDescription',
Expand Down Expand Up @@ -329,6 +331,8 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_MERCHANT]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_BILLABLE]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAG]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_AMOUNT]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_RATE]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_CATEGORY]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION]: Parameters.UpdateMoneyRequestParams;
Expand Down
32 changes: 32 additions & 0 deletions src/libs/ModifiedExpenseMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ function buildMessageFragmentForValue(
}
}

/**
* Get the absolute value for a tax amount.
*/
function getTaxAmountAbsValue(taxAmount: number): number {
// IOU requests cannot have negative values but they can be stored as negative values, let's return absolute value
return Math.abs(taxAmount ?? 0);
}

/**
* Get the message line for a modified expense.
*/
Expand Down Expand Up @@ -116,6 +124,7 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr
'currency' in reportActionOriginalMessage;

const hasModifiedMerchant = reportActionOriginalMessage && 'oldMerchant' in reportActionOriginalMessage && 'merchant' in reportActionOriginalMessage;

if (hasModifiedAmount) {
const oldCurrency = reportActionOriginalMessage?.oldCurrency ?? '';
const oldAmountValue = reportActionOriginalMessage?.oldAmount ?? 0;
Expand Down Expand Up @@ -216,6 +225,29 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr
});
}

const hasModifiedTaxAmount = reportActionOriginalMessage && 'oldTaxAmount' in reportActionOriginalMessage && 'taxAmount' in reportActionOriginalMessage;
if (hasModifiedTaxAmount) {
const currency = reportActionOriginalMessage?.currency;

const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmountAbsValue(reportActionOriginalMessage?.taxAmount ?? 0), currency);
const oldTaxAmountValue = getTaxAmountAbsValue(reportActionOriginalMessage?.oldTaxAmount ?? 0);
const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(oldTaxAmountValue, currency) : '';
buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), false, setFragments, removalFragments, changeFragments);
}

const hasModifiedTaxRate = reportActionOriginalMessage && 'oldTaxRate' in reportActionOriginalMessage && 'taxRate' in reportActionOriginalMessage;
if (hasModifiedTaxRate) {
buildMessageFragmentForValue(
reportActionOriginalMessage?.taxRate ?? '',
reportActionOriginalMessage?.oldTaxRate ?? '',
Localize.translateLocal('iou.taxRate'),
false,
setFragments,
removalFragments,
changeFragments,
);
}

const hasModifiedBillable = reportActionOriginalMessage && 'oldBillable' in reportActionOriginalMessage && 'billable' in reportActionOriginalMessage;
if (hasModifiedBillable) {
buildMessageFragmentForValue(
Expand Down
10 changes: 5 additions & 5 deletions src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1191,8 +1191,8 @@ function hasEnabledTags(policyTagList: Array<PolicyTagList[keyof PolicyTagList]>
* @param taxRates - The original tax rates object.
* @returns The transformed tax rates object.g
*/
function transformedTaxRates(taxRates: TaxRatesWithDefault | undefined, defaultKey?: string): Record<string, TaxRate> {
const defaultTaxKey = defaultKey ?? taxRates?.defaultExternalID;
function transformedTaxRates(taxRates: TaxRatesWithDefault | undefined): Record<string, TaxRate> {
const defaultTaxKey = taxRates?.defaultExternalID;
const getModifiedName = (data: TaxRate, code: string) => `${data.name} (${data.value})${defaultTaxKey === code ? ` • ${Localize.translateLocal('common.default')}` : ''}`;
const taxes = Object.fromEntries(Object.entries(taxRates?.taxes ?? {}).map(([code, data]) => [code, {...data, code, modifiedName: getModifiedName(data, code), name: data.name}]));
return taxes;
Expand All @@ -1212,7 +1212,7 @@ function sortTaxRates(taxRates: TaxRates): TaxRate[] {
function getTaxRatesOptions(taxRates: Array<Partial<TaxRate>>): Option[] {
return taxRates.map((taxRate) => ({
text: taxRate.modifiedName,
keyForList: taxRate.code,
keyForList: taxRate.modifiedName,
searchText: taxRate.modifiedName,
tooltipText: taxRate.modifiedName,
isDisabled: taxRate.isDisabled,
Expand All @@ -1223,10 +1223,10 @@ function getTaxRatesOptions(taxRates: Array<Partial<TaxRate>>): Option[] {
/**
* Builds the section list for tax rates
*/
function getTaxRatesSection(taxRates: TaxRatesWithDefault | undefined, selectedOptions: Category[], searchInputValue: string, defaultTaxKey?: string): CategorySection[] {
function getTaxRatesSection(taxRates: TaxRatesWithDefault | undefined, selectedOptions: Category[], searchInputValue: string): CategorySection[] {
const policyRatesSections = [];

const taxes = transformedTaxRates(taxRates, defaultTaxKey);
const taxes = transformedTaxRates(taxRates);

const sortedTaxRates = sortTaxRates(taxes);
const enabledTaxRates = sortedTaxRates.filter((taxRate) => !taxRate.isDisabled);
Expand Down
Loading
Loading