From 37492799b784a714aa0c005e66c1286bc1ff3108 Mon Sep 17 00:00:00 2001 From: Mateus Nardo Date: Tue, 9 Jan 2024 12:03:49 +0100 Subject: [PATCH] fix: fix nontaxable prices --- src/__tests__/fixtures/price.samples.ts | 29 ++++++++++++++++ src/pricing.test.ts | 44 +++++++++++++++++++++++++ src/pricing.ts | 4 +-- 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/__tests__/fixtures/price.samples.ts b/src/__tests__/fixtures/price.samples.ts index e3e8268..092b2e6 100644 --- a/src/__tests__/fixtures/price.samples.ts +++ b/src/__tests__/fixtures/price.samples.ts @@ -205,6 +205,35 @@ export const priceItemNonTaxable: PriceItemDto = { pricing_model: 'per_unit', }; +export const priceItemNonTaxable2: PriceItemDto = { + quantity: 1, + product_id: 'prod-id#12325', + price_id: 'price#4', + _price: { + _id: 'price#4', + unit_amount: 2000, + unit_amount_currency: 'EUR', + unit_amount_decimal: '20.00', + type: 'recurring', + billing_period: 'monthly', + billing_duration_amount: 1, + billing_duration_unit: 'years', + notice_time_amount: 1, + notice_time_unit: 'months', + termination_time_amount: 2, + termination_time_unit: 'weeks', + renewal_duration_amount: 1, + renewal_duration_unit: 'years', + tax: null!, + is_tax_inclusive: true, + description: 'Winter Lease 2', + _title: 'Winter Lease 2', + pricing_model: 'per_unit', + }, + _product: {}, + pricing_model: 'per_unit', +}; + export const compositePrice: CompositePriceItemDto = { price_id: 'price#4', product_id: 'prod-id#1234', diff --git a/src/pricing.test.ts b/src/pricing.test.ts index 8ccf64e..38ee477 100644 --- a/src/pricing.test.ts +++ b/src/pricing.test.ts @@ -106,6 +106,50 @@ describe('computeAggregatedAndPriceTotals', () => { ); }); + it('should return the right result when multiple prices are nontaxable', () => { + const priceItems = [samples.priceItemNonTaxable, samples.priceItemNonTaxable2]; + + const result = computeAggregatedAndPriceTotals(priceItems); + + expect(result).toEqual( + expect.objectContaining({ + amount_subtotal: 3000, + amount_total: 3000, + items: expect.arrayContaining([ + expect.objectContaining({ + amount_subtotal: 1000, + amount_total: 1000, + unit_amount_decimal: '10.00', + unit_amount_gross: 1000, + unit_amount_net: 1000, + taxes: [ + { + amount: 0, + rate: 'nontaxable', + rateValue: 0, + }, + ], + }), + expect.objectContaining({ + amount_subtotal: 2000, + amount_total: 2000, + unit_amount_decimal: '20.00', + unit_amount_gross: 2000, + unit_amount_net: 2000, + taxes: [ + { + amount: 0, + rate: 'nontaxable', + rateValue: 0, + }, + ], + }), + ]), + total_details: expect.objectContaining({ amount_tax: 0 }), + }), + ); + }); + it('should return the right result when quantity=0', () => { const priceItems = [{ ...samples.priceItem1, quantity: 0 }]; diff --git a/src/pricing.ts b/src/pricing.ts index 5c871cd..b999294 100644 --- a/src/pricing.ts +++ b/src/pricing.ts @@ -438,7 +438,7 @@ const recomputeDetailTotals = (details: PricingDetails, price: Price, priceItemT recurrence.amount_tax = taxAmount.add(priceTax).getAmount(); } - const recurrenceTax = !tax && itemTax ? taxes.at(-1) : tax; + const recurrenceTax = !tax && itemTax ? taxes?.[taxes?.length - 1] : tax; if (!recurrenceByTax) { const type = price?.type || priceItemToAppend?.type; @@ -449,7 +449,7 @@ const recomputeDetailTotals = (details: PricingDetails, price: Price, priceItemT amount_total: priceTotal.getAmount(), amount_subtotal: priceSubtotal.getAmount(), amount_tax: priceTax.getAmount(), - tax: recurrenceTax, + tax: recurrenceTax ?? { amount: 0, rate: 'nontaxable', rateValue: 0, tax: { rate: 0 } }, }); } else { const totalAmount = d(recurrenceByTax.amount_total);