Преглед изворни кода

fix(core): Add surcharge taxLines to taxSummary (#2798)

Jürg Hunziker пре 1 година
родитељ
комит
d0166a2b79

+ 73 - 1
packages/core/src/entity/order/order.entity.spec.ts

@@ -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';
 
@@ -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);
+        });
     });
 });
 
@@ -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,
+    );
 }

+ 16 - 3
packages/core/src/entity/order/order.entity.ts

@@ -299,7 +299,11 @@ 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) {
@@ -307,9 +311,18 @@ export class Order extends VendureEntity implements ChannelAware, HasCustomField
                 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;

+ 4 - 2
packages/core/src/testing/order-test-utils.ts

@@ -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';
@@ -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(
@@ -156,7 +158,7 @@ export function createOrder(
         couponCodes: [],
         lines,
         shippingLines: [],
-        surcharges: [],
+        surcharges: orderConfig.surcharges || [],
         modifications: [],
     });
 }