feat: Plug tax inclusivity in cart and order workflows (#8013)
This commit is contained in:
@@ -143,6 +143,12 @@ medusaIntegrationTestRunner({
|
||||
],
|
||||
})
|
||||
|
||||
await pricingModule.createPricePreferences({
|
||||
attribute: "currency_code",
|
||||
value: "usd",
|
||||
is_tax_inclusive: true,
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
@@ -200,6 +206,7 @@ medusaIntegrationTestRunner({
|
||||
expect.objectContaining({
|
||||
quantity: 1,
|
||||
unit_price: 3000,
|
||||
is_tax_inclusive: true,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
@@ -596,6 +603,12 @@ medusaIntegrationTestRunner({
|
||||
],
|
||||
})
|
||||
|
||||
await pricingModule.createPricePreferences({
|
||||
attribute: "currency_code",
|
||||
value: "usd",
|
||||
is_tax_inclusive: true,
|
||||
})
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
@@ -650,6 +663,7 @@ medusaIntegrationTestRunner({
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
unit_price: 3000,
|
||||
is_tax_inclusive: true,
|
||||
quantity: 1,
|
||||
title: "Test variant",
|
||||
}),
|
||||
@@ -1458,6 +1472,12 @@ medusaIntegrationTestRunner({
|
||||
priceSet = await pricingModule.createPriceSets({
|
||||
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||
})
|
||||
|
||||
await pricingModule.createPricePreferences({
|
||||
attribute: "currency_code",
|
||||
value: "usd",
|
||||
is_tax_inclusive: true,
|
||||
})
|
||||
})
|
||||
|
||||
it("should add shipping method to cart", async () => {
|
||||
@@ -1526,6 +1546,7 @@ medusaIntegrationTestRunner({
|
||||
shipping_methods: [
|
||||
expect.objectContaining({
|
||||
amount: 3000,
|
||||
is_tax_inclusive: true,
|
||||
name: "Test shipping option",
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -1280,6 +1280,16 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
])
|
||||
|
||||
await api.post(
|
||||
"/admin/price-preferences",
|
||||
{
|
||||
attribute: "currency_code",
|
||||
value: "usd",
|
||||
is_tax_inclusive: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const cart = await cartModule.createCarts({
|
||||
currency_code: "usd",
|
||||
customer_id: customer.id,
|
||||
@@ -1376,6 +1386,7 @@ medusaIntegrationTestRunner({
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
unit_price: 3000,
|
||||
is_tax_inclusive: true,
|
||||
quantity: 1,
|
||||
title: "Test variant",
|
||||
tax_lines: [
|
||||
@@ -1395,6 +1406,7 @@ medusaIntegrationTestRunner({
|
||||
}),
|
||||
expect.objectContaining({
|
||||
unit_price: 2000,
|
||||
is_tax_inclusive: false,
|
||||
quantity: 1,
|
||||
title: "Test item",
|
||||
tax_lines: [],
|
||||
@@ -1422,6 +1434,7 @@ medusaIntegrationTestRunner({
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
unit_price: 2000,
|
||||
is_tax_inclusive: true,
|
||||
quantity: 1,
|
||||
title: "Test variant default tax",
|
||||
tax_lines: [
|
||||
@@ -1734,6 +1747,16 @@ medusaIntegrationTestRunner({
|
||||
],
|
||||
})
|
||||
|
||||
await api.post(
|
||||
"/admin/price-preferences",
|
||||
{
|
||||
attribute: "currency_code",
|
||||
value: "usd",
|
||||
is_tax_inclusive: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const priceSet = await pricingModule.createPriceSets({
|
||||
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||
})
|
||||
@@ -1783,6 +1806,7 @@ medusaIntegrationTestRunner({
|
||||
{
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: 3000,
|
||||
is_tax_inclusive: true,
|
||||
id: expect.any(String),
|
||||
tax_lines: [],
|
||||
adjustments: [],
|
||||
|
||||
@@ -132,6 +132,16 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
])
|
||||
|
||||
await api.post(
|
||||
"/admin/price-preferences",
|
||||
{
|
||||
attribute: "currency_code",
|
||||
value: "usd",
|
||||
is_tax_inclusive: true,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
await remoteLink.create([
|
||||
{
|
||||
[Modules.PRODUCT]: {
|
||||
@@ -252,7 +262,7 @@ medusaIntegrationTestRunner({
|
||||
variant_option_values: null,
|
||||
requires_shipping: true,
|
||||
is_discountable: true,
|
||||
is_tax_inclusive: false,
|
||||
is_tax_inclusive: true,
|
||||
raw_compare_at_unit_price: null,
|
||||
raw_unit_price: expect.objectContaining({
|
||||
value: "3000",
|
||||
@@ -306,6 +316,7 @@ medusaIntegrationTestRunner({
|
||||
note: "reduced price",
|
||||
},
|
||||
unit_price: 200,
|
||||
is_tax_inclusive: true,
|
||||
quantity: 1,
|
||||
raw_quantity: expect.objectContaining({
|
||||
value: "1",
|
||||
|
||||
@@ -40,6 +40,7 @@ async function prepareDataFixtures({ container }) {
|
||||
ModuleRegistrationName.STOCK_LOCATION
|
||||
)
|
||||
const productModule = container.resolve(ModuleRegistrationName.PRODUCT)
|
||||
const pricingModule = container.resolve(ModuleRegistrationName.PRICING)
|
||||
const inventoryModule = container.resolve(ModuleRegistrationName.INVENTORY)
|
||||
|
||||
const shippingProfile = await fulfillmentService.createShippingProfiles({
|
||||
@@ -145,6 +146,19 @@ async function prepareDataFixtures({ container }) {
|
||||
},
|
||||
])
|
||||
|
||||
await pricingModule.createPricePreferences([
|
||||
{
|
||||
attribute: "currency_code",
|
||||
value: "usd",
|
||||
is_tax_inclusive: true,
|
||||
},
|
||||
{
|
||||
attribute: "region_id",
|
||||
value: region.id,
|
||||
is_tax_inclusive: true,
|
||||
},
|
||||
])
|
||||
|
||||
const shippingOptionData: FulfillmentWorkflow.CreateShippingOptionsWorkflowInput =
|
||||
{
|
||||
name: "Return shipping option",
|
||||
@@ -471,7 +485,7 @@ medusaIntegrationTestRunner({
|
||||
id: expect.any(String),
|
||||
name: shippingOption.name,
|
||||
description: null,
|
||||
is_tax_inclusive: false,
|
||||
is_tax_inclusive: true,
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: 10,
|
||||
order_id: expect.any(String),
|
||||
|
||||
@@ -105,6 +105,7 @@ export const productVariantsFields = [
|
||||
"product.collection",
|
||||
"product.handle",
|
||||
"calculated_price.calculated_amount",
|
||||
"calculated_price.is_calculated_price_tax_inclusive",
|
||||
"inventory_items.inventory_item_id",
|
||||
"inventory_items.required_quantity",
|
||||
"inventory_items.inventory.location_levels.stock_locations.id",
|
||||
|
||||
@@ -9,6 +9,7 @@ interface Input {
|
||||
quantity: BigNumberInput
|
||||
metadata?: Record<string, any>
|
||||
unitPrice: BigNumberInput
|
||||
isTaxInclusive?: boolean
|
||||
variant: ProductVariantDTO
|
||||
taxLines?: CreateOrderLineItemTaxLineDTO[]
|
||||
adjustments?: CreateOrderAdjustmentDTO[]
|
||||
@@ -19,6 +20,7 @@ export function prepareLineItemData(data: Input) {
|
||||
const {
|
||||
variant,
|
||||
unitPrice,
|
||||
isTaxInclusive,
|
||||
quantity,
|
||||
metadata,
|
||||
cartId,
|
||||
@@ -51,6 +53,7 @@ export function prepareLineItemData(data: Input) {
|
||||
variant_title: variant.title,
|
||||
|
||||
unit_price: unitPrice,
|
||||
is_tax_inclusive: !!isTaxInclusive,
|
||||
metadata,
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,12 @@ export const addShippingMethodToWorkflow = createWorkflow(
|
||||
|
||||
const shippingOptions = useRemoteQueryStep({
|
||||
entry_point: "shipping_option",
|
||||
fields: ["id", "name", "calculated_price.calculated_amount"],
|
||||
fields: [
|
||||
"id",
|
||||
"name",
|
||||
"calculated_price.calculated_amount",
|
||||
"calculated_price.is_calculated_price_tax_inclusive",
|
||||
],
|
||||
variables: {
|
||||
id: optionIds,
|
||||
calculated_price: {
|
||||
@@ -67,6 +72,9 @@ export const addShippingMethodToWorkflow = createWorkflow(
|
||||
return {
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: shippingOption.calculated_price.calculated_amount,
|
||||
is_tax_inclusive:
|
||||
!!shippingOption.calculated_price
|
||||
.is_calculated_price_tax_inclusive,
|
||||
data: option.data ?? {},
|
||||
name: shippingOption.name,
|
||||
cart_id: data.input.cart_id,
|
||||
|
||||
@@ -75,6 +75,8 @@ export const addToCartWorkflow = createWorkflow(
|
||||
return prepareLineItemData({
|
||||
variant: variant,
|
||||
unitPrice: variant.calculated_price.calculated_amount,
|
||||
isTaxInclusive:
|
||||
variant.calculated_price.is_calculated_price_tax_inclusive,
|
||||
quantity: item.quantity,
|
||||
metadata: item?.metadata ?? {},
|
||||
cartId: data.input.cart.id,
|
||||
|
||||
@@ -122,6 +122,8 @@ export const createCartWorkflow = createWorkflow(
|
||||
return prepareLineItemData({
|
||||
variant: variant,
|
||||
unitPrice: data.priceSets[item.variant_id].calculated_amount,
|
||||
isTaxInclusive:
|
||||
data.priceSets[item.variant_id].is_calculated_price_tax_inclusive,
|
||||
quantity: item.quantity,
|
||||
metadata: item?.metadata ?? {},
|
||||
})
|
||||
|
||||
@@ -42,6 +42,7 @@ export const listShippingOptionsForCartWorkflow = createWorkflow(
|
||||
"stock_locations.fulfillment_sets.service_zones.shipping_options.provider.is_enabled",
|
||||
|
||||
"stock_locations.fulfillment_sets.service_zones.shipping_options.calculated_price.calculated_amount",
|
||||
"stock_locations.fulfillment_sets.service_zones.shipping_options.calculated_price.is_calculated_price_tax_inclusive",
|
||||
],
|
||||
variables: {
|
||||
id: input.sales_channel_id,
|
||||
@@ -88,6 +89,8 @@ export const listShippingOptionsForCartWorkflow = createWorkflow(
|
||||
return {
|
||||
...options,
|
||||
amount: calculated_price?.calculated_amount,
|
||||
is_tax_inclusive:
|
||||
!!calculated_price?.is_calculated_price_tax_inclusive,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -71,6 +71,8 @@ export const updateLineItemInCartWorkflow = createWorkflow(
|
||||
data: {
|
||||
...data.input.update,
|
||||
unit_price: variant.calculated_price.calculated_amount,
|
||||
is_tax_inclusive:
|
||||
!!variant.calculated_price.is_calculated_price_tax_inclusive,
|
||||
},
|
||||
selector: {
|
||||
id: item.id,
|
||||
|
||||
@@ -4,6 +4,7 @@ interface Input {
|
||||
quantity: BigNumberInput
|
||||
metadata?: Record<string, any>
|
||||
unitPrice: BigNumberInput
|
||||
isTaxInclusive?: boolean
|
||||
variant: {
|
||||
title: string
|
||||
sku?: string
|
||||
@@ -18,11 +19,12 @@ interface Output {
|
||||
variant_barcode?: string
|
||||
variant_title?: string
|
||||
unit_price: BigNumberInput
|
||||
is_tax_inclusive: boolean
|
||||
metadata?: Record<string, any>
|
||||
}
|
||||
|
||||
export function prepareCustomLineItemData(data: Input): Output {
|
||||
const { variant, unitPrice, quantity, metadata } = data
|
||||
const { variant, unitPrice, isTaxInclusive, quantity, metadata } = data
|
||||
|
||||
const lineItem: any = {
|
||||
quantity,
|
||||
@@ -32,6 +34,7 @@ export function prepareCustomLineItemData(data: Input): Output {
|
||||
variant_title: variant.title,
|
||||
|
||||
unit_price: unitPrice,
|
||||
is_tax_inclusive: !!isTaxInclusive,
|
||||
metadata,
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ function prepareLineItems(data) {
|
||||
...item,
|
||||
},
|
||||
unitPrice: MathBN.max(0, item.unit_price),
|
||||
isTaxInclusive: item.is_tax_inclusive,
|
||||
quantity: item.quantity as number,
|
||||
metadata: item?.metadata ?? {},
|
||||
})
|
||||
@@ -39,6 +40,9 @@ function prepareLineItems(data) {
|
||||
0,
|
||||
item.unit_price ?? data.priceSets[item.variant_id!]?.calculated_amount
|
||||
),
|
||||
isTaxInclusive:
|
||||
item.is_tax_inclusive ??
|
||||
data.priceSets[item.variant_id!]?.is_calculated_price_tax_inclusive,
|
||||
quantity: item.quantity as number,
|
||||
metadata: item?.metadata ?? {},
|
||||
taxLines: item.tax_lines || [],
|
||||
|
||||
@@ -109,6 +109,7 @@ function prepareShippingMethodData({
|
||||
order_id: orderId,
|
||||
shipping_option_id: returnShippingOption.id,
|
||||
amount: 0,
|
||||
is_tax_inclusive: false,
|
||||
data: {},
|
||||
// Computed later in the flow
|
||||
tax_lines: [],
|
||||
@@ -122,6 +123,9 @@ function prepareShippingMethodData({
|
||||
// TODO: retrieve calculated price and assign to amount
|
||||
} else {
|
||||
obj.amount = returnShippingOption.calculated_price.calculated_amount
|
||||
obj.is_tax_inclusive =
|
||||
!!returnShippingOption.calculated_price
|
||||
.is_calculated_price_tax_inclusive
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,6 +321,7 @@ export const createReturnOrderWorkflow = createWorkflow(
|
||||
"name",
|
||||
"provider_id",
|
||||
"calculated_price.calculated_amount",
|
||||
"calculated_price.is_calculated_price_tax_inclusive",
|
||||
"service_zone.fulfillment_set.location.id",
|
||||
],
|
||||
variables: returnShippingOptionsVariables,
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
export interface WithCalculatedPrice {
|
||||
calculated_price: { calculated_amount: number }
|
||||
calculated_price: {
|
||||
calculated_amount: number
|
||||
is_calculated_price_tax_inclusive?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +212,7 @@ export interface CreateOrderShippingMethodDTO {
|
||||
exchange_id?: string
|
||||
version?: number
|
||||
amount: BigNumberInput
|
||||
is_tax_inclusive?: boolean
|
||||
shipping_option_id?: string
|
||||
data?: Record<string, unknown>
|
||||
tax_lines?: CreateOrderTaxLineDTO[]
|
||||
|
||||
@@ -16,20 +16,20 @@ export interface DecorateCartLikeInputDTO {
|
||||
items?: {
|
||||
id?: string
|
||||
unit_price: BigNumberInput
|
||||
is_tax_inclusive?: boolean
|
||||
quantity: BigNumberInput
|
||||
adjustments?: { amount: BigNumberInput }[]
|
||||
tax_lines?: {
|
||||
rate: BigNumberInput
|
||||
is_tax_inclusive?: boolean
|
||||
}[]
|
||||
}[]
|
||||
shipping_methods?: {
|
||||
id?: string
|
||||
amount: BigNumberInput
|
||||
is_tax_inclusive?: boolean
|
||||
adjustments?: { amount: BigNumberInput }[]
|
||||
tax_lines?: {
|
||||
rate: BigNumberInput
|
||||
is_tax_inclusive?: boolean
|
||||
}[]
|
||||
}[]
|
||||
region?: {
|
||||
|
||||
@@ -51,6 +51,7 @@ export const defaultStoreCartFields = [
|
||||
"items.title",
|
||||
"items.quantity",
|
||||
"items.unit_price",
|
||||
"items.is_tax_inclusive",
|
||||
"items.tax_lines.id",
|
||||
"items.tax_lines.description",
|
||||
"items.tax_lines.code",
|
||||
@@ -69,6 +70,7 @@ export const defaultStoreCartFields = [
|
||||
"shipping_methods.tax_lines.rate",
|
||||
"shipping_methods.tax_lines.provider_id",
|
||||
"shipping_methods.amount",
|
||||
"shipping_methods.is_tax_inclusive",
|
||||
"shipping_methods.adjustments.id",
|
||||
"shipping_methods.adjustments.code",
|
||||
"shipping_methods.adjustments.amount",
|
||||
|
||||
Reference in New Issue
Block a user