feat: Plug tax inclusivity in cart and order workflows (#8013)

This commit is contained in:
Stevche Radevski
2024-07-09 11:10:42 +02:00
committed by GitHub
parent b86812f615
commit db6969578f
18 changed files with 116 additions and 7 deletions

View File

@@ -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",
}),
],

View File

@@ -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: [],

View File

@@ -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",

View File

@@ -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),

View File

@@ -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",

View File

@@ -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,
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 ?? {},
})

View File

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

View File

@@ -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,

View File

@@ -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,
}

View File

@@ -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 || [],

View File

@@ -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,

View File

@@ -1,3 +1,6 @@
export interface WithCalculatedPrice {
calculated_price: { calculated_amount: number }
calculated_price: {
calculated_amount: number
is_calculated_price_tax_inclusive?: boolean
}
}

View File

@@ -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[]

View File

@@ -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?: {

View File

@@ -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",