diff --git a/.changeset/kind-singers-travel.md b/.changeset/kind-singers-travel.md new file mode 100644 index 0000000000..26dc5a773e --- /dev/null +++ b/.changeset/kind-singers-travel.md @@ -0,0 +1,6 @@ +--- +"medusa-fulfillment-webshipper": patch +"@medusajs/medusa": patch +--- + +fix(medusa,medusa-fulfillment-webshipper): Add missing variant + product relation on items diff --git a/packages/medusa-fulfillment-webshipper/src/services/__tests__/webshipper-fulfillment.js b/packages/medusa-fulfillment-webshipper/src/services/__tests__/webshipper-fulfillment.js index 71cbe37e95..2a277bbc7a 100644 --- a/packages/medusa-fulfillment-webshipper/src/services/__tests__/webshipper-fulfillment.js +++ b/packages/medusa-fulfillment-webshipper/src/services/__tests__/webshipper-fulfillment.js @@ -11,6 +11,19 @@ describe("WebshipperFulfillmentService", () => { createShipment: jest.fn(), } + const totalsService = { + getLineItemTotals: jest.fn().mockImplementation(() => { + return { + unit_price: 1000, + tax_lines: [ + { + rate: 20, + }, + ], + } + }), + } + describe("handleWebhook", () => { beforeEach(() => { jest.clearAllMocks() @@ -208,4 +221,107 @@ describe("WebshipperFulfillmentService", () => { ) }) }) + + describe("buildWebshipperItem", () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + const medusaItem = { + id: "item_id", + title: "item_title", + quantity: 1, + } + + const order = { + currency_code: "dkk", + } + + it("builds a webshipper item", async () => { + const webshipper = new WebshipperFulfillmentService( + { + totalsService, + }, + {} + ) + + let item + try { + item = await webshipper.buildWebshipperItem(medusaItem, 1, order) + } catch (error) { + console.log(error) + } + + expect(item).toEqual({ + ext_ref: "item_id", + description: "item_title", + quantity: 1, + unit_price: 10, + vat_percent: 20, + }) + }) + + it("builds a webshipper item with additional props from variant", async () => { + const webshipper = new WebshipperFulfillmentService( + { + totalsService, + }, + {} + ) + + medusaItem.variant = {} + medusaItem.variant.origin_country = "DK" + medusaItem.variant.sku = "sku" + medusaItem.variant.hs_code = "hs" + + let item + try { + item = await webshipper.buildWebshipperItem(medusaItem, 1, order) + } catch (error) { + console.log(error) + } + + expect(item).toEqual({ + ext_ref: "item_id", + description: "item_title", + quantity: 1, + unit_price: 10, + vat_percent: 20, + country_of_origin: "DK", + sku: "sku", + tarif_number: "hs", + }) + }) + + it("builds a webshipper item with additional props from product", async () => { + const webshipper = new WebshipperFulfillmentService( + { + totalsService, + }, + {} + ) + + medusaItem.variant = {} + medusaItem.variant.product = {} + medusaItem.variant.product.origin_country = "DK" + medusaItem.variant.product.hs_code = "test" + + let item + try { + item = await webshipper.buildWebshipperItem(medusaItem, 1, order) + } catch (error) { + console.log(error) + } + + expect(item).toEqual({ + ext_ref: "item_id", + description: "item_title", + quantity: 1, + unit_price: 10, + vat_percent: 20, + country_of_origin: "DK", + tarif_number: "test", + }) + }) + }) }) diff --git a/packages/medusa-fulfillment-webshipper/src/services/webshipper-fulfillment.js b/packages/medusa-fulfillment-webshipper/src/services/webshipper-fulfillment.js index 6c0324428c..986590da5b 100644 --- a/packages/medusa-fulfillment-webshipper/src/services/webshipper-fulfillment.js +++ b/packages/medusa-fulfillment-webshipper/src/services/webshipper-fulfillment.js @@ -173,32 +173,14 @@ class WebshipperFulfillmentService extends FulfillmentService { }, customs_lines: await Promise.all( returnOrder.items.map(async ({ item, quantity }) => { - const totals = await this.totalsService_.getLineItemTotals( + const customLine = await this.buildWebshipperItem( item, - fromOrder, - { - include_tax: true, - use_tax_lines: true, - } + quantity, + fromOrder ) + return { - ext_ref: item.id, - sku: item.variant.sku, - description: item.title, - quantity: quantity, - country_of_origin: - item.variant.origin_country || - item.variant.product.origin_country, - tarif_number: - item.variant.hs_code || item.variant.product.hs_code, - unit_price: humanizeAmount( - totals.unit_price, - fromOrder.currency_code - ), - vat_percent: totals.tax_lines.reduce( - (acc, next) => acc + next.rate, - 0 - ), + ...customLine, currency: fromOrder.currency_code.toUpperCase(), } }) @@ -350,34 +332,13 @@ class WebshipperFulfillmentService extends FulfillmentService { visible_ref, order_lines: await Promise.all( fulfillmentItems.map(async (item) => { - const totals = await this.totalsService_.getLineItemTotals( + const orderLine = await this.buildWebshipperItem( item, - fromOrder, - { - include_tax: true, - use_tax_lines: true, - } + item.quantity, + fromOrder ) - return { - ext_ref: item.id, - sku: item.variant.sku, - description: item.title, - quantity: item.quantity, - country_of_origin: - item.variant.origin_country || - item.variant.product.origin_country, - tarif_number: - item.variant.hs_code || item.variant.product.hs_code, - unit_price: humanizeAmount( - totals.unit_price, - fromOrder.currency_code - ), - vat_percent: totals.tax_lines.reduce( - (acc, next) => acc + next.rate, - 0 - ), - } + return orderLine }) ), delivery_address: { @@ -637,6 +598,41 @@ class WebshipperFulfillmentService extends FulfillmentService { }, }) } + + async buildWebshipperItem(item, quantity, order) { + const totals = await this.totalsService_.getLineItemTotals(item, order, { + include_tax: true, + use_tax_lines: true, + }) + + const webShipperItem = { + ext_ref: item.id, + description: item.title, + quantity: quantity, + unit_price: humanizeAmount(totals.unit_price, order.currency_code), + vat_percent: totals.tax_lines.reduce((acc, next) => acc + next.rate, 0), + } + + const coo = + item?.variant?.origin_country || item?.variant?.product?.origin_country + const sku = item?.variant?.sku + const tarifNumber = + item?.variant?.hs_code || item?.variant?.product?.hs_code + + if (coo) { + webShipperItem.country_of_origin = coo + } + + if (sku) { + webShipperItem.sku = sku + } + + if (tarifNumber) { + webShipperItem.tarif_number = tarifNumber + } + + return webShipperItem + } } export default WebshipperFulfillmentService diff --git a/packages/medusa/src/api/routes/store/swaps/create-swap.ts b/packages/medusa/src/api/routes/store/swaps/create-swap.ts index e79eb939f7..02febe8bd6 100644 --- a/packages/medusa/src/api/routes/store/swaps/create-swap.ts +++ b/packages/medusa/src/api/routes/store/swaps/create-swap.ts @@ -9,13 +9,13 @@ import { } from "class-validator" import { defaultStoreSwapFields, defaultStoreSwapRelations } from "." +import { Type } from "class-transformer" +import { MedusaError } from "medusa-core-utils" import { EntityManager } from "typeorm" import IdempotencyKeyService from "../../../../services/idempotency-key" -import { MedusaError } from "medusa-core-utils" import OrderService from "../../../../services/order" import ReturnService from "../../../../services/return" import SwapService from "../../../../services/swap" -import { Type } from "class-transformer" import { validator } from "../../../../utils/validator" /** @@ -145,6 +145,7 @@ export default async (req, res) => { "swaps", "swaps.additional_items", "swaps.additional_items.variant", + "swaps.additional_items.variant.product", "swaps.additional_items.tax_lines", ], }) diff --git a/packages/medusa/src/services/claim.ts b/packages/medusa/src/services/claim.ts index 06c0a872b2..dee72aab6b 100644 --- a/packages/medusa/src/services/claim.ts +++ b/packages/medusa/src/services/claim.ts @@ -527,6 +527,8 @@ export default class ClaimService extends TransactionBaseService { relations: [ "additional_items", "additional_items.tax_lines", + "additional_items.variant", + "additional_items.variant.product", "shipping_methods", "shipping_methods.tax_lines", "shipping_address", diff --git a/packages/medusa/src/services/swap.ts b/packages/medusa/src/services/swap.ts index 44b4d73dfc..070bb367b3 100644 --- a/packages/medusa/src/services/swap.ts +++ b/packages/medusa/src/services/swap.ts @@ -913,6 +913,8 @@ class SwapService extends TransactionBaseService { "shipping_address", "additional_items", "additional_items.tax_lines", + "additional_items.variant", + "additional_items.variant.product", "shipping_methods", "shipping_methods.tax_lines", "order",