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>
This commit is contained in:
Josip Matić
2023-09-07 12:21:03 +02:00
committed by GitHub
parent 09d97fd05e
commit c7b149a7bc
3 changed files with 102 additions and 1 deletions

View File

@@ -0,0 +1,6 @@
---
"@medusajs/medusa": patch
"medusa-fulfillment-webshipper": patch
---
feat(medusa-fulfillment-webshipper): Create webshipper return order

View File

@@ -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) => {

View File

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