fix: Product type tax overrides (#9951)

* fix: Make product type tax override work

* fix: Make product type tax override work
This commit is contained in:
Oli Juhl
2024-11-06 20:33:40 +01:00
committed by GitHub
parent aa78fbf546
commit 505768dd9f
35 changed files with 479 additions and 309 deletions
@@ -1,142 +0,0 @@
import {
CartLineItemDTO,
CartShippingMethodDTO,
CartWorkflowDTO,
ITaxModuleService,
ItemTaxLineDTO,
ShippingTaxLineDTO,
TaxCalculationContext,
TaxableItemDTO,
TaxableShippingDTO,
} from "@medusajs/framework/types"
import { MedusaError, Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
export interface GetItemTaxLinesStepInput {
cart: CartWorkflowDTO
items: CartLineItemDTO[]
shipping_methods: CartShippingMethodDTO[]
force_tax_calculation?: boolean
is_return?: boolean
}
function normalizeTaxModuleContext(
cart: CartWorkflowDTO,
forceTaxCalculation: boolean,
isReturn?: boolean
): TaxCalculationContext | null {
const address = cart.shipping_address
const shouldCalculateTax = forceTaxCalculation || cart.region?.automatic_taxes
if (!shouldCalculateTax) {
return null
}
if (forceTaxCalculation && !address?.country_code) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`country code is required to calculate taxes`
)
}
if (!address?.country_code) {
return null
}
const customer = cart.customer
? {
id: cart.customer.id,
email: cart.customer.email,
customer_groups: cart.customer.groups?.map((g) => g.id) || [],
}
: undefined
return {
address: {
country_code: address.country_code,
province_code: address.province,
address_1: address.address_1,
address_2: address.address_2,
city: address.city,
postal_code: address.postal_code,
},
customer,
is_return: isReturn ?? false,
}
}
function normalizeLineItemsForTax(
cart: CartWorkflowDTO,
items: CartLineItemDTO[]
): TaxableItemDTO[] {
return items.map((item) => ({
id: item.id,
product_id: item.product_id!,
product_name: item.variant_title,
product_sku: item.variant_sku,
product_type: item.product_type,
product_type_id: item.product_type,
quantity: item.quantity,
unit_price: item.unit_price,
currency_code: cart.currency_code,
}))
}
function normalizeLineItemsForShipping(
cart: CartWorkflowDTO,
shippingMethods: CartShippingMethodDTO[]
): TaxableShippingDTO[] {
return shippingMethods.map((shippingMethod) => ({
id: shippingMethod.id,
shipping_option_id: shippingMethod.shipping_option_id!,
unit_price: shippingMethod.amount,
currency_code: cart.currency_code,
}))
}
export const getItemTaxLinesStepId = "get-item-tax-lines"
/**
* This step retrieves the tax lines of the specified line items in a cart.
*/
export const getItemTaxLinesStep = createStep(
getItemTaxLinesStepId,
async (data: GetItemTaxLinesStepInput, { container }) => {
const {
cart,
items,
shipping_methods: shippingMethods,
force_tax_calculation: forceTaxCalculation = false,
is_return: isReturn = false,
} = data
const taxService = container.resolve<ITaxModuleService>(Modules.TAX)
const taxContext = normalizeTaxModuleContext(
cart,
forceTaxCalculation,
isReturn
)
if (!taxContext) {
return new StepResponse({
lineItemTaxLines: [],
shippingMethodsTaxLines: [],
})
}
const lineItemTaxLines = (await taxService.getTaxLines(
normalizeLineItemsForTax(cart, items),
taxContext
)) as ItemTaxLineDTO[]
const shippingMethodsTaxLines = (await taxService.getTaxLines(
normalizeLineItemsForShipping(cart, shippingMethods),
taxContext
)) as ShippingTaxLineDTO[]
return new StepResponse({
lineItemTaxLines,
shippingMethodsTaxLines,
})
}
)
@@ -9,7 +9,6 @@ export * from "./find-one-or-any-region"
export * from "./find-or-create-customer"
export * from "./find-sales-channel"
export * from "./get-actions-to-compute-from-promotions"
export * from "./get-item-tax-lines"
export * from "./get-line-item-actions"
export * from "./get-promotion-codes-to-apply"
export * from "./get-variant-price-sets"
@@ -28,3 +27,4 @@ export * from "./update-line-items"
export * from "./validate-cart-payments"
export * from "./validate-cart-shipping-options"
export * from "./validate-variant-prices"
@@ -114,6 +114,7 @@ export const productVariantsFields = [
"product.subtitle",
"product.thumbnail",
"product.type.value",
"product.type.id",
"product.collection.title",
"product.handle",
"product.discountable",
@@ -86,6 +86,7 @@ export function prepareLineItemData(data: Input) {
variant.product.description ?? item?.product_description,
product_subtitle: variant.product.subtitle ?? item?.product_subtitle,
product_type: variant.product.type?.value ?? item?.product_type ?? null,
product_type_id: variant.product.type?.id ?? item?.product_type_id ?? null,
product_collection:
variant.product.collection?.title ?? item?.product_collection ?? null,
product_handle: variant.product.handle ?? item?.product_handle,
@@ -8,7 +8,8 @@ import {
transform,
} from "@medusajs/framework/workflows-sdk"
import { useRemoteQueryStep } from "../../common"
import { getItemTaxLinesStep, setTaxLinesForItemsStep } from "../steps"
import { getItemTaxLinesStep } from "../../tax/steps/get-item-tax-lines"
import { setTaxLinesForItemsStep } from "../steps"
const cartFields = [
"id",
@@ -23,6 +24,7 @@ const cartFields = [
"items.product_description",
"items.product_subtitle",
"items.product_type",
"items.product_type_id",
"items.product_collection",
"items.product_handle",
"items.variant_sku",
@@ -81,7 +83,7 @@ export const updateTaxLinesWorkflow = createWorkflow(
const taxLineItems = getItemTaxLinesStep(
transform({ input, cart }, (data) => ({
cart: data.cart,
orderOrCart: data.cart,
items: data.input.items || data.cart.items,
shipping_methods:
data.input.shipping_methods || data.cart.shipping_methods,
@@ -20,7 +20,6 @@ export * from "./exchange/cancel-exchange"
export * from "./exchange/create-exchange"
export * from "./exchange/create-exchange-items-from-actions"
export * from "./exchange/delete-exchanges"
export * from "./get-item-tax-lines"
export * from "./preview-order-change"
export * from "./register-fulfillment"
export * from "./register-shipment"
@@ -35,3 +34,4 @@ export * from "./update-order-change-actions"
export * from "./update-order-changes"
export * from "./update-order-exchanges"
export * from "./update-shipping-methods"
@@ -6,10 +6,8 @@ import {
when,
} from "@medusajs/framework/workflows-sdk"
import { useRemoteQueryStep } from "../../common"
import {
getOrderItemTaxLinesStep,
setOrderTaxLinesForItemsStep,
} from "../steps"
import { getItemTaxLinesStep } from "../../tax/steps/get-item-tax-lines"
import { setOrderTaxLinesForItemsStep } from "../steps"
const completeOrderFields = [
"id",
@@ -174,7 +172,7 @@ export const updateOrderTaxLinesWorkflow = createWorkflow(
}).config({ name: "query-order-shipping-methods" })
})
const taxLineItems = getOrderItemTaxLinesStep(
const taxLineItems = getItemTaxLinesStep(
transform(
{ input, order, items, shippingMethods, isFullOrder },
(data) => {
@@ -187,7 +185,7 @@ export const updateOrderTaxLinesWorkflow = createWorkflow(
: data.items ?? []
return {
order: data.order,
orderOrCart: data.order,
items: lineItems,
shipping_methods: shippingMethods,
force_tax_calculation: data.input.force_tax_calculation,
@@ -1,4 +1,7 @@
import {
CartLineItemDTO,
CartShippingMethodDTO,
CartWorkflowDTO,
ITaxModuleService,
ItemTaxLineDTO,
OrderLineItemDTO,
@@ -12,24 +15,24 @@ import {
import { MedusaError, Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
export interface GetOrderItemTaxLinesStepInput {
order: OrderWorkflowDTO
items: OrderLineItemDTO[]
shipping_methods: OrderShippingMethodDTO[]
export interface GetItemTaxLinesStepInput {
orderOrCart: OrderWorkflowDTO | CartWorkflowDTO
items: OrderLineItemDTO[] | CartLineItemDTO[]
shipping_methods: OrderShippingMethodDTO[] | CartShippingMethodDTO[]
force_tax_calculation?: boolean
is_return?: boolean
shipping_address?: OrderWorkflowDTO["shipping_address"]
}
function normalizeTaxModuleContext(
order: OrderWorkflowDTO,
orderOrCart: OrderWorkflowDTO | CartWorkflowDTO,
forceTaxCalculation: boolean,
isReturn?: boolean,
shippingAddress?: OrderWorkflowDTO["shipping_address"]
): TaxCalculationContext | null {
const address = shippingAddress ?? order.shipping_address
const address = shippingAddress ?? orderOrCart.shipping_address
const shouldCalculateTax =
forceTaxCalculation || order.region?.automatic_taxes
forceTaxCalculation || orderOrCart.region?.automatic_taxes
if (!shouldCalculateTax) {
return null
@@ -46,10 +49,10 @@ function normalizeTaxModuleContext(
return null
}
const customer = order.customer && {
id: order.customer.id,
email: order.customer.email,
customer_groups: order.customer.groups?.map((g) => g.id) || [],
const customer = orderOrCart.customer && {
id: orderOrCart.customer.id,
email: orderOrCart.customer.email,
customer_groups: orderOrCart.customer.groups?.map((g) => g.id) || [],
}
return {
@@ -67,28 +70,25 @@ function normalizeTaxModuleContext(
}
function normalizeLineItemsForTax(
order: OrderWorkflowDTO,
items: OrderLineItemDTO[]
orderOrCart: OrderWorkflowDTO | CartWorkflowDTO,
items: OrderLineItemDTO[] | CartLineItemDTO[]
): TaxableItemDTO[] {
return items.map(
(item) =>
({
id: item.id,
product_id: item.product_id!,
product_name: item.variant_title,
product_sku: item.variant_sku,
product_type: item.product_type,
product_type_id: item.product_type,
product_type_id: item.product_type_id,
quantity: item.quantity,
unit_price: item.unit_price,
currency_code: order.currency_code,
currency_code: orderOrCart.currency_code,
} as TaxableItemDTO)
)
}
function normalizeLineItemsForShipping(
order: OrderWorkflowDTO,
shippingMethods: OrderShippingMethodDTO[]
orderOrCart: OrderWorkflowDTO | CartWorkflowDTO,
shippingMethods: OrderShippingMethodDTO[] | CartShippingMethodDTO[]
): TaxableShippingDTO[] {
return shippingMethods.map(
(shippingMethod) =>
@@ -96,20 +96,20 @@ function normalizeLineItemsForShipping(
id: shippingMethod.id,
shipping_option_id: shippingMethod.shipping_option_id!,
unit_price: shippingMethod.amount,
currency_code: order.currency_code,
currency_code: orderOrCart.currency_code,
} as TaxableShippingDTO)
)
}
export const getOrderItemTaxLinesStepId = "get-order-item-tax-lines"
export const getItemTaxLinesStepId = "get-item-tax-lines"
/**
* This step retrieves the tax lines for an order's line items and shipping methods.
*/
export const getOrderItemTaxLinesStep = createStep(
getOrderItemTaxLinesStepId,
async (data: GetOrderItemTaxLinesStepInput, { container }) => {
export const getItemTaxLinesStep = createStep(
getItemTaxLinesStepId,
async (data: GetItemTaxLinesStepInput, { container }) => {
const {
order,
orderOrCart,
items = [],
shipping_methods: shippingMethods = [],
force_tax_calculation: forceTaxCalculation = false,
@@ -119,7 +119,7 @@ export const getOrderItemTaxLinesStep = createStep(
const taxService = container.resolve<ITaxModuleService>(Modules.TAX)
const taxContext = normalizeTaxModuleContext(
order,
orderOrCart,
forceTaxCalculation,
isReturn,
shippingAddress
@@ -136,14 +136,14 @@ export const getOrderItemTaxLinesStep = createStep(
if (items.length) {
stepResponseData.lineItemTaxLines = (await taxService.getTaxLines(
normalizeLineItemsForTax(order, items),
normalizeLineItemsForTax(orderOrCart, items),
taxContext
)) as ItemTaxLineDTO[]
}
if (shippingMethods.length) {
stepResponseData.shippingMethodsTaxLines = (await taxService.getTaxLines(
normalizeLineItemsForShipping(order, shippingMethods),
normalizeLineItemsForShipping(orderOrCart, shippingMethods),
taxContext
)) as ShippingTaxLineDTO[]
}