Skip to content
13 changes: 7 additions & 6 deletions src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -829,10 +829,11 @@ function getUpdatedTransaction({

if (Object.hasOwn(transactionChanges, 'category') && typeof transactionChanges.category === 'string') {
updatedTransaction.category = transactionChanges.category;
const {categoryTaxCode, categoryTaxAmount} = getCategoryTaxCodeAndAmount(transactionChanges.category, transaction, policy);
if (categoryTaxCode && categoryTaxAmount !== undefined) {
const {categoryTaxCode, categoryTaxAmount, categoryTaxValue} = getCategoryTaxDetails(transactionChanges.category, transaction, policy);
if (categoryTaxCode && categoryTaxAmount !== undefined && categoryTaxValue) {
updatedTransaction.taxCode = categoryTaxCode;
updatedTransaction.taxAmount = categoryTaxAmount;
updatedTransaction.taxValue = categoryTaxValue;
}
}

Expand Down Expand Up @@ -2586,10 +2587,10 @@ function buildMergeDuplicatesParams(
};
}

function getCategoryTaxCodeAndAmount(category: string, transaction: OnyxEntry<Transaction>, policy: OnyxEntry<Policy>) {
function getCategoryTaxDetails(category: string, transaction: OnyxEntry<Transaction>, policy: OnyxEntry<Policy>) {
const taxRules = policy?.rules?.expenseRules?.filter((rule) => rule.tax);
if (!taxRules || taxRules?.length === 0 || isDistanceRequest(transaction)) {
return {categoryTaxCode: undefined, categoryTaxAmount: undefined};
return {categoryTaxCode: undefined, categoryTaxAmount: undefined, categoryTaxValue: undefined};
}

const defaultTaxCode = getDefaultTaxCode(policy, transaction, getCurrency(transaction));
Expand All @@ -2601,7 +2602,7 @@ function getCategoryTaxCodeAndAmount(category: string, transaction: OnyxEntry<Tr
categoryTaxAmount = convertToBackendAmount(calculateTaxAmount(categoryTaxPercentage, getAmount(transaction), getCurrencyDecimals(getCurrency(transaction))));
}

return {categoryTaxCode, categoryTaxAmount};
return {categoryTaxCode, categoryTaxAmount, categoryTaxValue: categoryTaxPercentage};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we added categoryTaxValue on the return of getCategoryTaxCodeAndAmount I think we should change its name @MelvinBot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to getCategoryTaxDetails across all call sites (TransactionUtils, IOU, and tests).

}

/**
Expand Down Expand Up @@ -2907,7 +2908,7 @@ export {
shouldShowAttendees,
getAllSortedTransactions,
getFormattedPostedDate,
getCategoryTaxCodeAndAmount,
getCategoryTaxDetails,
isPerDiemRequest,
isViolationDismissed,
isPartialTransaction,
Expand Down
12 changes: 5 additions & 7 deletions src/libs/actions/IOU/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import {startSpan} from '@libs/telemetry/activeSpans';
import {
buildOptimisticTransaction,
getAmount,
getCategoryTaxCodeAndAmount,
getCategoryTaxDetails,
getCurrency,
getDistanceInMeters,
isDistanceRequest as isDistanceRequestTransactionUtils,
Expand Down Expand Up @@ -899,15 +899,13 @@ function setMoneyRequestCategory(transactionID: string, category: string, policy
return;
}
if (!policy) {
setMoneyRequestTaxRate(transactionID, '');
setMoneyRequestTaxAmount(transactionID, null);
setMoneyRequestTaxRateValues(transactionID, {taxCode: '', taxAmount: null, taxValue: null});
return;
}
const transaction = allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`];
const {categoryTaxCode, categoryTaxAmount} = getCategoryTaxCodeAndAmount(category, transaction, policy);
if (categoryTaxCode && categoryTaxAmount !== undefined) {
setMoneyRequestTaxRate(transactionID, categoryTaxCode);
setMoneyRequestTaxAmount(transactionID, categoryTaxAmount);
const {categoryTaxCode, categoryTaxAmount, categoryTaxValue} = getCategoryTaxDetails(category, transaction, policy);
if (categoryTaxCode && categoryTaxAmount !== undefined && categoryTaxValue) {
setMoneyRequestTaxRateValues(transactionID, {taxCode: categoryTaxCode, taxAmount: categoryTaxAmount, taxValue: categoryTaxValue});
}
}

Expand Down
28 changes: 17 additions & 11 deletions tests/unit/TransactionUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ describe('TransactionUtils', () => {
});
});

describe('getCategoryTaxCodeAndAmount', () => {
describe('getCategoryTaxDetails', () => {
it('should return the associated tax when the category matches the tax expense rules', () => {
// Given a policy with tax expense rules associated with a category
const category = 'Advertising';
Expand All @@ -204,11 +204,12 @@ describe('TransactionUtils', () => {
const transaction = generateTransaction();

// When retrieving the tax from the associated category
const {categoryTaxCode, categoryTaxAmount} = TransactionUtils.getCategoryTaxCodeAndAmount(category, transaction, fakePolicy);
const {categoryTaxCode, categoryTaxAmount, categoryTaxValue} = TransactionUtils.getCategoryTaxDetails(category, transaction, fakePolicy);

// Then it should return the associated tax code and amount
// Then it should return the associated tax code, amount, and value
expect(categoryTaxCode).toBe('id_TAX_RATE_1');
expect(categoryTaxAmount).toBe(5);
expect(categoryTaxValue).toBe('5%');
});

it("should return the default tax when the category doesn't match the tax expense rules", () => {
Expand All @@ -223,11 +224,12 @@ describe('TransactionUtils', () => {
const transaction = generateTransaction();

// When retrieving the tax from a category that is not associated with the tax expense rules
const {categoryTaxCode, categoryTaxAmount} = TransactionUtils.getCategoryTaxCodeAndAmount(selectedCategory, transaction, fakePolicy);
const {categoryTaxCode, categoryTaxAmount, categoryTaxValue} = TransactionUtils.getCategoryTaxDetails(selectedCategory, transaction, fakePolicy);

// Then it should return the default tax code and amount
// Then it should return the default tax code, amount, and value
expect(categoryTaxCode).toBe('id_TAX_EXEMPT');
expect(categoryTaxAmount).toBe(0);
expect(categoryTaxValue).toBe('0%');
});

it("should return the foreign default tax when the category doesn't match the tax expense rules and using a foreign currency", () => {
Expand All @@ -254,11 +256,12 @@ describe('TransactionUtils', () => {
const transaction = generateTransaction();

// When retrieving the tax from a category that is not associated with the tax expense rules
const {categoryTaxCode, categoryTaxAmount} = TransactionUtils.getCategoryTaxCodeAndAmount(selectedCategory, transaction, fakePolicy);
const {categoryTaxCode, categoryTaxAmount, categoryTaxValue} = TransactionUtils.getCategoryTaxDetails(selectedCategory, transaction, fakePolicy);

// Then it should return the default tax code and amount
// Then it should return the default tax code, amount, and value
expect(categoryTaxCode).toBe('id_TAX_RATE_2');
expect(categoryTaxAmount).toBe(9);
expect(categoryTaxValue).toBe('10%');
});

describe('should return undefined tax', () => {
Expand All @@ -276,11 +279,12 @@ describe('TransactionUtils', () => {
};

// When retrieving the tax from the associated category
const {categoryTaxCode, categoryTaxAmount} = TransactionUtils.getCategoryTaxCodeAndAmount(category, transaction, fakePolicy);
const {categoryTaxCode, categoryTaxAmount, categoryTaxValue} = TransactionUtils.getCategoryTaxDetails(category, transaction, fakePolicy);

// Then it should return undefined for both the tax code and the tax amount
// Then it should return undefined for the tax code, amount, and value
expect(categoryTaxCode).toBe(undefined);
expect(categoryTaxAmount).toBe(undefined);
expect(categoryTaxValue).toBe(undefined);
});

it('if there are no policy tax expense rules', () => {
Expand All @@ -294,11 +298,12 @@ describe('TransactionUtils', () => {
const transaction = generateTransaction();

// When retrieving the tax from a category
const {categoryTaxCode, categoryTaxAmount} = TransactionUtils.getCategoryTaxCodeAndAmount(category, transaction, fakePolicy);
const {categoryTaxCode, categoryTaxAmount, categoryTaxValue} = TransactionUtils.getCategoryTaxDetails(category, transaction, fakePolicy);

// Then it should return undefined for both the tax code and the tax amount
// Then it should return undefined for the tax code, amount, and value
expect(categoryTaxCode).toBe(undefined);
expect(categoryTaxAmount).toBe(undefined);
expect(categoryTaxValue).toBe(undefined);
});
});
});
Expand Down Expand Up @@ -327,6 +332,7 @@ describe('TransactionUtils', () => {
expect(updatedTransaction.category).toBe(category);
expect(updatedTransaction.taxCode).toBe(taxCode);
expect(updatedTransaction.taxAmount).toBe(5);
expect(updatedTransaction.taxValue).toBe('5%');
});

it('should update transaction when distance is changed', () => {
Expand Down
Loading