fix(medusa): calculates correct taxes and totals on order with gift cards (#1807)
**What** Since the release of the Tax API the line item totals calculations on orders with gift cards have been wrong. To understand the bug consider the below order: Region: - tax_rate: 25% - gift_cards_taxable: true Order: - applied gift card: 1000 - items: - A: unit_price: 1000 - B: unit_price: 500 - Subtotal: 1500 **Previous calculation method** 1. Determine how much of the gift card is used for each item using `item_total / subtotal * gift_card_amount`: - Item A: 1000/1500 * 1000 = 666.67 - Item B: 500/1500 * 1000 = 333.33 2. Calculate line item totals including taxes using `(unit_price - gift_card) * (1 + tax_rate)` - Item A: 1000 - 666.67 = 333.33; vat amount -> 83.33 - Item B: 500 - 333.33 = 166.67; vat amount -> 41.67 3. Add up the line item totals: order subtotal = 500; vat amount = 125; total = 625 This is all correct at the totals level; but at the line item level we should still use the "original prices" i.e. the line item total for item a should be (1000 * 1.25) = 1250 with a tax amount of 250. **New calculation method** 1. Use default totals calculations - Item A: subtotal: 1000, tax_total: 250, total: 1250 - Item B: subtotal: 500, tax_total: 125, total: 625 2. Add up the line item totals: subtotal: 1500, tax_total: 375, total: 1875 3. Reduce total with gift card: subtotal: 1500 - 1000 = 500, tax_total: 375 - 250 = 125, total = 625 Totals can now be forwarded correctly to accounting plugins. Fixes CORE-310.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
export * from "./simple-gift-card-factory"
|
||||
export * from "./simple-payment-factory"
|
||||
export * from "./simple-batch-job-factory"
|
||||
export * from "./simple-discount-factory"
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { GiftCard } from "@medusajs/medusa"
|
||||
import faker from "faker"
|
||||
import { Connection } from "typeorm"
|
||||
|
||||
export type GiftCardFactoryData = {
|
||||
id?: string
|
||||
code?: string
|
||||
region_id: string
|
||||
value: number
|
||||
balance: number
|
||||
}
|
||||
|
||||
export const simpleGiftCardFactory = async (
|
||||
connection: Connection,
|
||||
data: GiftCardFactoryData,
|
||||
seed?: number
|
||||
): Promise<GiftCard> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
const toSave = manager.create(GiftCard, {
|
||||
id: data.id,
|
||||
code: data.code ?? "TESTGCCODE",
|
||||
region_id: data.region_id,
|
||||
value: data.value,
|
||||
balance: data.balance,
|
||||
})
|
||||
|
||||
return await manager.save(toSave)
|
||||
}
|
||||
@@ -112,5 +112,9 @@ export const simpleProductFactory = async (
|
||||
await simpleProductVariantFactory(connection, factoryData)
|
||||
}
|
||||
|
||||
return manager.findOne(Product, { id: prodId }, { relations: ["tags", "variants", "variants.prices"] })
|
||||
return manager.findOne(
|
||||
Product,
|
||||
{ id: prodId },
|
||||
{ relations: ["tags", "variants", "variants.prices"] }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ export type RegionFactoryData = {
|
||||
tax_rate?: number
|
||||
countries?: string[]
|
||||
automatic_taxes?: boolean
|
||||
gift_cards_taxable?: boolean
|
||||
}
|
||||
|
||||
export const simpleRegionFactory = async (
|
||||
@@ -29,6 +30,7 @@ export const simpleRegionFactory = async (
|
||||
currency_code: data.currency_code || "usd",
|
||||
tax_rate: data.tax_rate || 0,
|
||||
payment_providers: [{ id: "test-pay" }],
|
||||
gift_cards_taxable: data.gift_cards_taxable ?? true,
|
||||
automatic_taxes:
|
||||
typeof data.automatic_taxes !== "undefined" ? data.automatic_taxes : true,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user