From c7b149a7bc87dc4df1c78edccb36b45f19ee8e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josip=20Mati=C4=87?= Date: Thu, 7 Sep 2023 12:21:03 +0200 Subject: [PATCH] feat(medusa-fulfillment-webshipper): Create webshipper return order (#4846) Adds option to create a webshipper return order if return_portal is defined through webshipper options. Return order allows additional features in webshipper, such as marking the return as "Arrived" or "Processed" which enables us to create a webhook and automatically mark return as received in medusa. Note: Return portal is a "required" relationship in webshipper when doing a return order POST request, hence it should be defined in options prior to using this feature. Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> --- .changeset/polite-zoos-hammer.md | 6 ++ .../src/services/webshipper-fulfillment.js | 81 ++++++++++++++++++- .../src/utils/webshipper.js | 16 ++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 .changeset/polite-zoos-hammer.md diff --git a/.changeset/polite-zoos-hammer.md b/.changeset/polite-zoos-hammer.md new file mode 100644 index 0000000000..bf02e0ca6f --- /dev/null +++ b/.changeset/polite-zoos-hammer.md @@ -0,0 +1,6 @@ +--- +"@medusajs/medusa": patch +"medusa-fulfillment-webshipper": patch +--- + +feat(medusa-fulfillment-webshipper): Create webshipper return order diff --git a/packages/medusa-fulfillment-webshipper/src/services/webshipper-fulfillment.js b/packages/medusa-fulfillment-webshipper/src/services/webshipper-fulfillment.js index 0f13e15b6b..c4ba118f0a 100644 --- a/packages/medusa-fulfillment-webshipper/src/services/webshipper-fulfillment.js +++ b/packages/medusa-fulfillment-webshipper/src/services/webshipper-fulfillment.js @@ -97,6 +97,75 @@ class WebshipperFulfillmentService extends AbstractFulfillmentService { // Calculate prices } + /** + * Creates a return order in webshipper and links it to an existing shipment. + */ + async createReturnOrder(shipment, fromOrder) { + const fulfillmentData = fromOrder.fulfillments[0]?.data + + if (!shipment?.id || !fulfillmentData?.id) { + return + } + + const customsLines = shipment.attributes?.packages?.[0]?.customs_lines + + if (!customsLines?.length) { + return + } + + const returnOrderData = { + type: "returns", + attributes: { + status: "pending", + return_lines: customsLines.map(({ ext_ref, quantity }) => ({ + order_line_id: fulfillmentData.attributes?.order_lines?.find( + (order_line) => order_line.ext_ref === ext_ref + )?.id, + cause_id: this.options_.return_portal?.cause_id || "1", + quantity: quantity, + })), + }, + relationships: { + order: { + data: { + id: fulfillmentData.id, + type: "orders", + }, + }, + portal: { + data: { + id: this.options_.return_portal.id || "1", + type: "return_portals", + }, + }, + refund_method: { + data: { + id: this.options_.return_portal.refund_method_id || "1", + type: "return_refund_methods", + }, + }, + shipping_method: { + data: { + id: shipment.shipping_method?.data?.webshipper_id || "1", + type: "return_shipping_methods", + }, + }, + shipment: { + data: { + id: shipment.id, + type: "shipments", + }, + }, + }, + } + + this.client_.returns.create(returnOrderData) + } + + /** + * Creates a return shipment in webshipper using the given method data, and + * return lines. + */ async createReturn(returnOrder) { let orderId if (returnOrder.order_id) { @@ -109,7 +178,13 @@ class WebshipperFulfillmentService extends AbstractFulfillmentService { const fromOrder = await this.orderService_.retrieve(orderId, { select: ["total"], - relations: ["discounts", "discounts.rule", "shipping_address", "returns"], + relations: [ + "discounts", + "discounts.rule", + "shipping_address", + "returns", + "fulfillments", + ], }) const methodData = returnOrder.shipping_method.data @@ -204,6 +279,10 @@ class WebshipperFulfillmentService extends AbstractFulfillmentService { return this.client_.shipments .create(returnShipment) .then((result) => { + if (this.options_.return_portal?.id) { + this.createReturnOrder(result.data, fromOrder) + } + return result.data }) .catch((err) => { diff --git a/packages/medusa-fulfillment-webshipper/src/utils/webshipper.js b/packages/medusa-fulfillment-webshipper/src/utils/webshipper.js index e93b2d2204..6c8955c571 100644 --- a/packages/medusa-fulfillment-webshipper/src/utils/webshipper.js +++ b/packages/medusa-fulfillment-webshipper/src/utils/webshipper.js @@ -16,6 +16,7 @@ class Webshipper { this.shippingRates = this.buildShippingRateEndpoints_() this.orders = this.buildOrderEndpoints_() this.shipments = this.buildShipmentEndpoints_() + this.returns = this.buildReturnEndpoints_() } async request(data) { @@ -124,6 +125,21 @@ class Webshipper { }, } } + + buildReturnEndpoints_ = () => { + return { + create: async (data) => { + const path = `/v2/returns` + return this.client_({ + method: "POST", + url: path, + data: { + data, + }, + }).then(({ data }) => data) + }, + } + } } export default Webshipper