Skip to content

Commit

Permalink
fix(core): Add surcharge taxLines to taxSummary (#2798)
Browse files Browse the repository at this point in the history
  • Loading branch information
tschortsch authored Apr 22, 2024
1 parent 55f6878 commit d0166a2
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 6 deletions.
74 changes: 73 additions & 1 deletion packages/core/src/entity/order/order.entity.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { beforeAll, describe, expect, it } from 'vitest';
import { ensureConfigLoaded } from '../../config/config-helpers';
import { createOrder, createRequestContext, taxCategoryStandard } from '../../testing/order-test-utils';
import { ShippingLine } from '../shipping-line/shipping-line.entity';
import { Surcharge } from '../surcharge/surcharge.entity';

import { Order } from './order.entity';

Expand Down Expand Up @@ -324,6 +325,73 @@ describe('Order entity methods', () => {
]);
assertOrderTaxesAddsUp(order);
});

it('with surcharge', () => {
const ctx = createRequestContext({ pricesIncludeTax: false });
const order = createOrder({
ctx,
lines: [
{
listPrice: 300,
taxCategory: taxCategoryStandard,
quantity: 2,
},
{
listPrice: 1000,
taxCategory: taxCategoryStandard,
quantity: 1,
},
],
surcharges: [
new Surcharge({
description: 'Special surcharge',
listPrice: 400,
listPriceIncludesTax: ctx.channel.pricesIncludeTax,
taxLines: [
{ description: 'Special surcharge tax', taxRate: 50 },
{ description: 'Special surcharge second tax', taxRate: 20 },
],
sku: 'special-surcharge',
}),
new Surcharge({
description: 'Other surcharge',
listPrice: 500,
listPriceIncludesTax: ctx.channel.pricesIncludeTax,
taxLines: [{ description: 'Other surcharge tax', taxRate: 0 }],
sku: 'other-surcharge',
}),
],
});
order.lines.forEach(i => (i.taxLines = [{ taxRate: 5, description: 'tax a' }]));

expect(order.taxSummary).toEqual([
{
description: 'tax a',
taxRate: 5,
taxBase: 1600,
taxTotal: 80,
},
{
description: 'Special surcharge tax',
taxRate: 50,
taxBase: 400,
taxTotal: 200,
},
{
description: 'Special surcharge second tax',
taxRate: 20,
taxBase: 400,
taxTotal: 80,
},
{
description: 'Other surcharge tax',
taxRate: 0,
taxBase: 500,
taxTotal: 0,
},
]);
assertOrderTaxesAddsUp(order);
});
});
});

Expand All @@ -332,5 +400,9 @@ function assertOrderTaxesAddsUp(order: Order) {
const lineTotal = summate(order.lines, 'proratedLinePrice');
const lineTotalWithTax = summate(order.lines, 'proratedLinePriceWithTax');
const shippingTax = (order.shippingWithTax ?? 0) - (order.shipping ?? 0);
expect(lineTotalWithTax - lineTotal + shippingTax).toBe(summaryTaxTotal);
const surchargesTotal = summate(order.surcharges, 'price');
const surchargesTotalWithTax = summate(order.surcharges, 'priceWithTax');
expect(lineTotalWithTax - lineTotal + shippingTax + (surchargesTotalWithTax - surchargesTotal)).toBe(
summaryTaxTotal,
);
}
19 changes: 16 additions & 3 deletions packages/core/src/entity/order/order.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,17 +299,30 @@ export class Order extends VendureEntity implements ChannelAware, HasCustomField
{ rate: number; base: number; tax: number; description: string }
>();
const taxId = (taxLine: TaxLine): string => `${taxLine.description}:${taxLine.taxRate}`;
const taxableLines = [...(this.lines ?? []), ...(this.shippingLines ?? [])];
const taxableLines = [
...(this.lines ?? []),
...(this.shippingLines ?? []),
...(this.surcharges ?? []),
];
for (const line of taxableLines) {
const taxRateTotal = summate(line.taxLines, 'taxRate');
for (const taxLine of line.taxLines) {
const id = taxId(taxLine);
const row = taxRateMap.get(id);
const proportionOfTotalRate = 0 < taxLine.taxRate ? taxLine.taxRate / taxRateTotal : 0;

const lineBase = line instanceof OrderLine ? line.proratedLinePrice : line.discountedPrice;
const lineBase =
line instanceof OrderLine
? line.proratedLinePrice
: line instanceof Surcharge
? line.price
: line.discountedPrice;
const lineWithTax =
line instanceof OrderLine ? line.proratedLinePriceWithTax : line.discountedPriceWithTax;
line instanceof OrderLine
? line.proratedLinePriceWithTax
: line instanceof Surcharge
? line.priceWithTax
: line.discountedPriceWithTax;
const amount = Math.round((lineWithTax - lineBase) * proportionOfTotalRate);
if (row) {
row.tax += amount;
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/testing/order-test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Omit } from '@vendure/common/lib/omit';
import { ID } from '@vendure/common/lib/shared-types';

import { RequestContext } from '../api/common/request-context';
import { Surcharge } from '../entity';
import { Channel } from '../entity/channel/channel.entity';
import { Order } from '../entity/order/order.entity';
import { OrderLine } from '../entity/order-line/order-line.entity';
Expand Down Expand Up @@ -130,13 +131,14 @@ export class MockTaxRateService {
}

export function createOrder(
orderConfig: Partial<Omit<Order, 'lines'>> & {
orderConfig: Partial<Omit<Order, 'lines', 'surcharges'>> & {
ctx: RequestContext;
lines: Array<{
listPrice: number;
taxCategory: TaxCategory;
quantity: number;
}>;
surcharges?: Surcharge[];
},
): Order {
const lines = orderConfig.lines.map(
Expand All @@ -156,7 +158,7 @@ export function createOrder(
couponCodes: [],
lines,
shippingLines: [],
surcharges: [],
surcharges: orderConfig.surcharges || [],
modifications: [],
});
}

0 comments on commit d0166a2

Please sign in to comment.