Skip to content

Commit 0ae7feb

Browse files
authored
Merge pull request #42737 from Expensify/revert-42670-revert-40240-monil-splitBillTaxUpdate
Revert "Revert "Handle tax for split requests"" and fix reported bugs
2 parents 198b473 + 62169f6 commit 0ae7feb

15 files changed

+188
-60
lines changed

src/components/MoneyRequestConfirmationList.tsx

+13-16
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,6 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps &
179179

180180
type MoneyRequestConfirmationListItem = Participant | ReportUtils.OptionData;
181181

182-
const getTaxAmount = (transaction: OnyxEntry<OnyxTypes.Transaction>, policy: OnyxEntry<OnyxTypes.Policy>, isDistanceRequest: boolean) => {
183-
if (isDistanceRequest) {
184-
return DistanceRequestUtils.calculateTaxAmount(policy, transaction, TransactionUtils.getRateID(transaction) ?? '');
185-
}
186-
const defaultTaxCode = TransactionUtils.getDefaultTaxCode(policy, transaction) ?? '';
187-
const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, transaction?.taxCode ?? defaultTaxCode) ?? '';
188-
return TransactionUtils.calculateTaxAmount(taxPercentage, transaction?.amount ?? 0);
189-
};
190-
191182
function MoneyRequestConfirmationList({
192183
transaction = null,
193184
onSendMoney,
@@ -376,15 +367,21 @@ function MoneyRequestConfirmationList({
376367

377368
// Calculate and set tax amount in transaction draft
378369
useEffect(() => {
379-
const taxAmount = getTaxAmount(transaction, policy, isDistanceRequest).toString();
380-
const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount));
381-
382-
if (transaction?.taxAmount && previousTransactionAmount === transaction?.amount && previousTransactionCurrency === transaction?.currency) {
383-
return IOU.setMoneyRequestTaxAmount(transactionID, transaction?.taxAmount ?? 0, true);
370+
if (!shouldShowTax || (transaction?.taxAmount !== undefined && previousTransactionAmount === transaction?.amount && previousTransactionCurrency === transaction?.currency)) {
371+
return;
384372
}
385373

386-
IOU.setMoneyRequestTaxAmount(transactionID, amountInSmallestCurrencyUnits, true);
387-
}, [policy, transaction, transactionID, previousTransactionAmount, previousTransactionCurrency, isDistanceRequest]);
374+
let taxAmount;
375+
if (isDistanceRequest) {
376+
taxAmount = DistanceRequestUtils.calculateTaxAmount(policy, transaction, TransactionUtils.getRateID(transaction) ?? '');
377+
} else {
378+
const defaultTaxCode = TransactionUtils.getDefaultTaxCode(policy, transaction) ?? '';
379+
const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, transaction?.taxCode ?? defaultTaxCode) ?? '';
380+
taxAmount = TransactionUtils.calculateTaxAmount(taxPercentage, transaction?.amount ?? 0);
381+
}
382+
const taxAmountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount.toString()));
383+
IOU.setMoneyRequestTaxAmount(transaction?.transactionID ?? '', taxAmountInSmallestCurrencyUnits);
384+
}, [policy, shouldShowTax, previousTransactionAmount, previousTransactionCurrency, transaction, isDistanceRequest]);
388385

389386
// If completing a split expense fails, set didConfirm to false to allow the user to edit the fields again
390387
if (isEditingSplitBill && didConfirm) {

src/components/TaxPicker.tsx

+18-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, {useMemo, useState} from 'react';
22
import {withOnyx} from 'react-native-onyx';
33
import type {OnyxEntry} from 'react-native-onyx';
44
import type {EdgeInsets} from 'react-native-safe-area-context';
5+
import type {ValueOf} from 'type-fest';
56
import useLocalize from '@hooks/useLocalize';
67
import useStyleUtils from '@hooks/useStyleUtils';
78
import * as IOUUtils from '@libs/IOUUtils';
@@ -11,6 +12,7 @@ import CONST from '@src/CONST';
1112
import type {IOUAction} from '@src/CONST';
1213
import ONYXKEYS from '@src/ONYXKEYS';
1314
import type {Policy, Transaction} from '@src/types/onyx';
15+
import {isEmptyObject} from '@src/types/utils/EmptyObject';
1416
import SelectionList from './SelectionList';
1517
import RadioListItem from './SelectionList/RadioListItem';
1618

@@ -20,6 +22,9 @@ type TaxPickerOnyxProps = {
2022

2123
/** All the data for the transaction */
2224
transaction: OnyxEntry<Transaction>;
25+
26+
/** The draft transaction that holds data to be persisted on the current split transaction */
27+
splitDraftTransaction: OnyxEntry<Transaction>;
2328
};
2429

2530
type TaxPickerProps = TaxPickerOnyxProps & {
@@ -46,13 +51,20 @@ type TaxPickerProps = TaxPickerOnyxProps & {
4651
/** The action to take */
4752
// eslint-disable-next-line react/no-unused-prop-types
4853
action?: IOUAction;
54+
55+
/** The type of IOU */
56+
iouType?: ValueOf<typeof CONST.IOU.TYPE>;
4957
};
5058

51-
function TaxPicker({selectedTaxRate = '', policy, transaction, insets, onSubmit}: TaxPickerProps) {
59+
function TaxPicker({selectedTaxRate = '', policy, transaction, insets, onSubmit, action, splitDraftTransaction, iouType}: TaxPickerProps) {
5260
const StyleUtils = useStyleUtils();
5361
const {translate} = useLocalize();
5462
const [searchValue, setSearchValue] = useState('');
5563

64+
const isEditing = action === CONST.IOU.ACTION.EDIT;
65+
const isEditingSplitBill = isEditing && iouType === CONST.IOU.TYPE.SPLIT;
66+
const currentTransaction = isEditingSplitBill && !isEmptyObject(splitDraftTransaction) ? splitDraftTransaction : transaction;
67+
5668
const taxRates = policy?.taxRates;
5769
const taxRatesCount = TransactionUtils.getEnabledTaxRateCount(taxRates?.taxes ?? {});
5870
const isTaxRatesCountBelowThreshold = taxRatesCount < CONST.TAX_RATES_LIST_THRESHOLD;
@@ -74,8 +86,8 @@ function TaxPicker({selectedTaxRate = '', policy, transaction, insets, onSubmit}
7486
}, [selectedTaxRate]);
7587

7688
const sections = useMemo(
77-
() => OptionsListUtils.getTaxRatesSection(policy, selectedOptions as OptionsListUtils.Tax[], searchValue, transaction),
78-
[searchValue, selectedOptions, policy, transaction],
89+
() => OptionsListUtils.getTaxRatesSection(policy, selectedOptions as OptionsListUtils.Tax[], searchValue, currentTransaction),
90+
[searchValue, selectedOptions, policy, currentTransaction],
7991
);
8092

8193
const headerMessage = OptionsListUtils.getHeaderMessageForNonUserList(sections[0].data.length > 0, searchValue);
@@ -112,4 +124,7 @@ export default withOnyx<TaxPickerProps, TaxPickerOnyxProps>({
112124
return `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`;
113125
},
114126
},
127+
splitDraftTransaction: {
128+
key: ({transactionID}) => `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`,
129+
},
115130
})(TaxPicker);

src/libs/API/parameters/CompleteSplitBillParams.ts

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ type CompleteSplitBillParams = {
88
category?: string;
99
tag?: string;
1010
splits: string;
11+
taxCode?: string;
12+
taxAmount?: number;
1113
};
1214

1315
export default CompleteSplitBillParams;

src/libs/API/parameters/SplitBillParams.ts

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ type SplitBillParams = {
1515
policyID: string | undefined;
1616
chatType: string | undefined;
1717
splitPayerAccountIDs: number[];
18+
taxCode: string;
19+
taxAmount: number;
1820
};
1921

2022
export default SplitBillParams;

src/libs/API/parameters/StartSplitBillParams.ts

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ type StartSplitBillParams = {
1414
createdReportActionID?: string;
1515
billable: boolean;
1616
chatType?: string;
17+
taxCode?: string;
18+
taxAmount?: number;
1719
};
1820

1921
export default StartSplitBillParams;

src/libs/actions/IOU.ts

+42-11
Original file line numberDiff line numberDiff line change
@@ -3786,6 +3786,8 @@ function createSplitsAndOnyxData(
37863786
existingSplitChatReportID = '',
37873787
billable = false,
37883788
iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL,
3789+
taxCode = '',
3790+
taxAmount = 0,
37893791
): SplitsAndOnyxData {
37903792
const currentUserEmailForIOUSplit = PhoneNumber.addSMSDomainIfPhoneNumber(currentUserLogin);
37913793
const participantAccountIDs = participants.map((participant) => Number(participant.accountID));
@@ -3807,8 +3809,8 @@ function createSplitsAndOnyxData(
38073809
undefined,
38083810
category,
38093811
tag,
3810-
undefined,
3811-
undefined,
3812+
taxCode,
3813+
taxAmount,
38123814
billable,
38133815
);
38143816

@@ -3963,14 +3965,16 @@ function createSplitsAndOnyxData(
39633965

39643966
// Loop through participants creating individual chats, iouReports and reportActionIDs as needed
39653967
const currentUserAmount = splitShares?.[currentUserAccountID]?.amount ?? IOUUtils.calculateAmount(participants.length, amount, currency, true);
3968+
const currentUserTaxAmount = IOUUtils.calculateAmount(participants.length, taxAmount, currency, true);
39663969

3967-
const splits: Split[] = [{email: currentUserEmailForIOUSplit, accountID: currentUserAccountID, amount: currentUserAmount}];
3970+
const splits: Split[] = [{email: currentUserEmailForIOUSplit, accountID: currentUserAccountID, amount: currentUserAmount, taxAmount: currentUserTaxAmount}];
39683971

39693972
const hasMultipleParticipants = participants.length > 1;
39703973
participants.forEach((participant) => {
39713974
// In a case when a participant is a workspace, even when a current user is not an owner of the workspace
39723975
const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(participant);
39733976
const splitAmount = splitShares?.[participant.accountID ?? -1]?.amount ?? IOUUtils.calculateAmount(participants.length, amount, currency, false);
3977+
const splitTaxAmount = IOUUtils.calculateAmount(participants.length, taxAmount, currency, false);
39743978

39753979
// To exclude someone from a split, the amount can be 0. The scenario for this is when creating a split from a group chat, we have remove the option to deselect users to exclude them.
39763980
// We can input '0' next to someone we want to exclude.
@@ -4040,8 +4044,8 @@ function createSplitsAndOnyxData(
40404044
undefined,
40414045
category,
40424046
tag,
4043-
undefined,
4044-
undefined,
4047+
taxCode,
4048+
ReportUtils.isExpenseReport(oneOnOneIOUReport) ? -splitTaxAmount : splitTaxAmount,
40454049
billable,
40464050
);
40474051

@@ -4132,6 +4136,7 @@ function createSplitsAndOnyxData(
41324136
reportPreviewReportActionID: oneOnOneReportPreviewAction.reportActionID,
41334137
transactionThreadReportID: optimisticTransactionThread.reportID,
41344138
createdReportActionIDForThread: optimisticCreatedActionForTransactionThread.reportActionID,
4139+
taxAmount: splitTaxAmount,
41354140
};
41364141

41374142
splits.push(individualSplit);
@@ -4185,6 +4190,8 @@ type SplitBillActionsParams = {
41854190
existingSplitChatReportID?: string;
41864191
splitShares?: SplitShares;
41874192
splitPayerAccountIDs?: number[];
4193+
taxCode?: string;
4194+
taxAmount?: number;
41884195
};
41894196

41904197
/**
@@ -4207,6 +4214,8 @@ function splitBill({
42074214
existingSplitChatReportID = '',
42084215
splitShares = {},
42094216
splitPayerAccountIDs = [],
4217+
taxCode = '',
4218+
taxAmount = 0,
42104219
}: SplitBillActionsParams) {
42114220
const currentCreated = DateUtils.enrichMoneyRequestTimestamp(created);
42124221
const {splitData, splits, onyxData} = createSplitsAndOnyxData(
@@ -4224,6 +4233,8 @@ function splitBill({
42244233
existingSplitChatReportID,
42254234
billable,
42264235
iouRequestType,
4236+
taxCode,
4237+
taxAmount,
42274238
);
42284239

42294240
const parameters: SplitBillParams = {
@@ -4243,6 +4254,8 @@ function splitBill({
42434254
policyID: splitData.policyID,
42444255
chatType: splitData.chatType,
42454256
splitPayerAccountIDs,
4257+
taxCode,
4258+
taxAmount,
42464259
};
42474260

42484261
API.write(WRITE_COMMANDS.SPLIT_BILL, parameters, onyxData);
@@ -4269,6 +4282,8 @@ function splitBillAndOpenReport({
42694282
iouRequestType = CONST.IOU.REQUEST_TYPE.MANUAL,
42704283
splitShares = {},
42714284
splitPayerAccountIDs = [],
4285+
taxCode = '',
4286+
taxAmount = 0,
42724287
}: SplitBillActionsParams) {
42734288
const currentCreated = DateUtils.enrichMoneyRequestTimestamp(created);
42744289
const {splitData, splits, onyxData} = createSplitsAndOnyxData(
@@ -4286,6 +4301,8 @@ function splitBillAndOpenReport({
42864301
'',
42874302
billable,
42884303
iouRequestType,
4304+
taxCode,
4305+
taxAmount,
42894306
);
42904307

42914308
const parameters: SplitBillParams = {
@@ -4305,6 +4322,8 @@ function splitBillAndOpenReport({
43054322
policyID: splitData.policyID,
43064323
chatType: splitData.chatType,
43074324
splitPayerAccountIDs,
4325+
taxCode,
4326+
taxAmount,
43084327
};
43094328

43104329
API.write(WRITE_COMMANDS.SPLIT_BILL_AND_OPEN_REPORT, parameters, onyxData);
@@ -4324,6 +4343,8 @@ type StartSplitBilActionParams = {
43244343
category: string | undefined;
43254344
tag: string | undefined;
43264345
currency: string;
4346+
taxCode: string;
4347+
taxAmount: number;
43274348
};
43284349

43294350
/** Used exclusively for starting a split expense request that contains a receipt, the split request will be completed once the receipt is scanned
@@ -4342,6 +4363,8 @@ function startSplitBill({
43424363
category = '',
43434364
tag = '',
43444365
currency,
4366+
taxCode = '',
4367+
taxAmount = 0,
43454368
}: StartSplitBilActionParams) {
43464369
const currentUserEmailForIOUSplit = PhoneNumber.addSMSDomainIfPhoneNumber(currentUserLogin);
43474370
const participantAccountIDs = participants.map((participant) => Number(participant.accountID));
@@ -4366,8 +4389,8 @@ function startSplitBill({
43664389
undefined,
43674390
category,
43684391
tag,
4369-
undefined,
4370-
undefined,
4392+
taxCode,
4393+
taxAmount,
43714394
billable,
43724395
);
43734396

@@ -4609,6 +4632,8 @@ function startSplitBill({
46094632
billable,
46104633
...(existingSplitChatReport ? {} : {createdReportActionID: splitChatCreatedReportAction.reportActionID}),
46114634
chatType: splitChatReport?.chatType,
4635+
taxCode,
4636+
taxAmount,
46124637
};
46134638

46144639
API.write(WRITE_COMMANDS.START_SPLIT_BILL, parameters, {optimisticData, successData, failureData});
@@ -4693,9 +4718,11 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA
46934718
const splitParticipants: Split[] = updatedTransaction?.comment.splits ?? [];
46944719
const amount = updatedTransaction?.modifiedAmount;
46954720
const currency = updatedTransaction?.modifiedCurrency;
4721+
console.debug(updatedTransaction);
46964722

46974723
// Exclude the current user when calculating the split amount, `calculateAmount` takes it into account
46984724
const splitAmount = IOUUtils.calculateAmount(splitParticipants.length - 1, amount ?? 0, currency ?? '', false);
4725+
const splitTaxAmount = IOUUtils.calculateAmount(splitParticipants.length - 1, updatedTransaction?.taxAmount ?? 0, currency ?? '', false);
46994726

47004727
const splits: Split[] = [{email: currentUserEmailForIOUSplit}];
47014728
splitParticipants.forEach((participant) => {
@@ -4759,8 +4786,8 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA
47594786
undefined,
47604787
updatedTransaction?.category,
47614788
updatedTransaction?.tag,
4762-
undefined,
4763-
undefined,
4789+
updatedTransaction?.taxCode,
4790+
isPolicyExpenseChat ? -splitTaxAmount : splitAmount,
47644791
updatedTransaction?.billable,
47654792
);
47664793

@@ -4834,6 +4861,8 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA
48344861
comment: transactionComment,
48354862
category: transactionCategory,
48364863
tag: transactionTag,
4864+
taxCode: transactionTaxCode,
4865+
taxAmount: transactionTaxAmount,
48374866
} = ReportUtils.getTransactionDetails(updatedTransaction) ?? {};
48384867

48394868
const parameters: CompleteSplitBillParams = {
@@ -4846,6 +4875,8 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA
48464875
category: transactionCategory,
48474876
tag: transactionTag,
48484877
splits: JSON.stringify(splits),
4878+
taxCode: transactionTaxCode,
4879+
taxAmount: transactionTaxAmount,
48494880
};
48504881

48514882
API.write(WRITE_COMMANDS.COMPLETE_SPLIT_BILL, parameters, {optimisticData, successData, failureData});
@@ -6607,8 +6638,8 @@ function setMoneyRequestTaxRate(transactionID: string, taxCode: string) {
66076638
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxCode});
66086639
}
66096640

6610-
function setMoneyRequestTaxAmount(transactionID: string, taxAmount: number, isDraft: boolean) {
6611-
Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {taxAmount});
6641+
function setMoneyRequestTaxAmount(transactionID: string, taxAmount: number | null) {
6642+
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxAmount});
66126643
}
66136644

66146645
function setShownHoldUseExplanation() {

0 commit comments

Comments
 (0)