feat(order): create claim and exchange (#7734)

This commit is contained in:
Carlos R. L. Rodrigues
2024-06-18 08:08:16 -03:00
committed by GitHub
parent e0b14519f1
commit cfa983001b
45 changed files with 2571 additions and 437 deletions
@@ -0,0 +1,242 @@
import { Modules } from "@medusajs/modules-sdk"
import { CreateOrderDTO, IOrderModuleService } from "@medusajs/types"
import { ClaimType } from "@medusajs/utils"
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
jest.setTimeout(100000)
moduleIntegrationTestRunner({
moduleName: Modules.ORDER,
testSuite: ({ service }: SuiteOptions<IOrderModuleService>) => {
describe("Order Module Service - Claim flows", () => {
const input = {
email: "foo@bar.com",
items: [
{
title: "Item 1",
subtitle: "Subtitle 1",
thumbnail: "thumbnail1.jpg",
quantity: 1,
product_id: "product1",
product_title: "Product 1",
product_description: "Description 1",
product_subtitle: "Product Subtitle 1",
product_type: "Type 1",
product_collection: "Collection 1",
product_handle: "handle1",
variant_id: "variant1",
variant_sku: "SKU1",
variant_barcode: "Barcode1",
variant_title: "Variant 1",
variant_option_values: {
color: "Red",
size: "Large",
},
requires_shipping: true,
is_discountable: true,
is_tax_inclusive: true,
compare_at_unit_price: 10,
unit_price: 8,
tax_lines: [
{
description: "Tax 1",
tax_rate_id: "tax_usa",
code: "code",
rate: 0.1,
provider_id: "taxify_master",
},
],
adjustments: [
{
code: "VIP_10",
amount: 10,
description: "VIP discount",
promotion_id: "prom_123",
provider_id: "coupon_kings",
},
],
},
{
title: "Item 2",
quantity: 2,
unit_price: 5,
},
{
title: "Item 3",
quantity: 1,
unit_price: 30,
},
],
sales_channel_id: "test",
shipping_address: {
first_name: "Test",
last_name: "Test",
address_1: "Test",
city: "Test",
country_code: "US",
postal_code: "12345",
phone: "12345",
},
billing_address: {
first_name: "Test",
last_name: "Test",
address_1: "Test",
city: "Test",
country_code: "US",
postal_code: "12345",
},
shipping_methods: [
{
name: "Test shipping method",
amount: 10,
},
],
transactions: [
{
amount: 58,
currency_code: "USD",
reference: "payment",
reference_id: "pay_123",
},
],
currency_code: "usd",
customer_id: "joe",
} as CreateOrderDTO
it("should claim an item and add two new items to the order", async function () {
const createdOrder = await service.create(input)
// Fullfilment
await service.registerFulfillment({
order_id: createdOrder.id,
items: createdOrder.items!.map((item) => {
return {
id: item.id,
quantity: item.quantity,
}
}),
})
// Shipment
await service.registerShipment({
order_id: createdOrder.id,
reference: Modules.FULFILLMENT,
items: createdOrder.items!.map((item) => {
return {
id: item.id,
quantity: item.quantity,
}
}),
})
// Claim
const orderClaim = await service.createClaim({
order_id: createdOrder.id,
type: ClaimType.REPLACE,
description: "Claim all the items",
internal_note: "user wants to return all items",
shipping_methods: [
{
name: "Claim method",
amount: 35,
provider_id: "dhl",
},
],
claim_items: [
{
id: createdOrder.items![1].id,
quantity: 1,
reason: "production_failure",
},
],
additional_items: [
{
id: createdOrder.items![2].id,
quantity: 1,
},
{
unit_price: 20,
quantity: 1,
title: "New item",
},
],
return_amount: 5,
return_shipping: {
name: "return shipping method",
amount: 10,
provider_id: "test_provider_id",
},
})
expect(orderClaim).toEqual(
expect.objectContaining({
id: orderClaim.id,
order_id: createdOrder.id,
return: expect.objectContaining({
order_id: createdOrder.id,
claim_id: orderClaim.id,
status: "requested",
items: expect.arrayContaining([
expect.objectContaining({
item_id: createdOrder.items![1].id,
quantity: 1,
}),
]),
}),
type: "replace",
additional_items: expect.arrayContaining([
expect.objectContaining({
claim_id: orderClaim.id,
is_additional_item: true,
quantity: 1,
item: expect.objectContaining({
title: "New item",
}),
detail: expect.objectContaining({
quantity: 1,
}),
}),
expect.objectContaining({
claim_id: orderClaim.id,
item_id: createdOrder.items![2].id,
is_additional_item: true,
quantity: 1,
item: expect.objectContaining({
title: "Item 3",
}),
detail: expect.objectContaining({
quantity: 2,
}),
}),
]),
claim_items: [
expect.objectContaining({
reason: "production_failure",
claim_id: orderClaim.id,
is_additional_item: false,
quantity: 1,
item: expect.objectContaining({
title: "Item 2",
}),
detail: expect.objectContaining({
quantity: 2,
}),
}),
],
shipping_methods: [
expect.objectContaining({
name: "return shipping method",
amount: 10,
}),
expect.objectContaining({
name: "Claim method",
amount: 35,
}),
],
refund_amount: null,
})
)
})
})
},
})
@@ -142,6 +142,7 @@ moduleIntegrationTestRunner({
createdOrder.items![0].unit_price *
createdOrder.items![0].quantity,
details: {
reference_id: createdOrder.items![0].id,
quantity: 1,
},
},
@@ -155,6 +156,7 @@ moduleIntegrationTestRunner({
createdOrder.items![1].unit_price *
createdOrder.items![1].quantity,
details: {
reference_id: createdOrder.items![1].id,
quantity: 3,
},
},
@@ -351,6 +353,7 @@ moduleIntegrationTestRunner({
createdOrder.items![0].unit_price *
createdOrder.items![0].quantity,
details: {
reference_id: createdOrder.items![0].id,
quantity: 1,
},
},
@@ -362,6 +365,7 @@ moduleIntegrationTestRunner({
createdOrder.items![1].unit_price *
createdOrder.items![1].quantity,
details: {
reference_id: createdOrder.items![1].id,
quantity: 3,
},
},
@@ -412,9 +416,7 @@ moduleIntegrationTestRunner({
await expect(
service.confirmOrderChange(orderChange.id)
).rejects.toThrowError(
`Order Change cannot be modified: ${orderChange.id}`
)
).rejects.toThrow(`Order Change cannot be modified: ${orderChange.id}`)
const modified = await service.retrieve(createdOrder.id, {
select: [
@@ -570,6 +572,7 @@ moduleIntegrationTestRunner({
createdOrder.items![0].unit_price *
createdOrder.items![0].quantity,
details: {
reference_id: createdOrder.items![0].id,
quantity: 1,
},
},
@@ -581,9 +584,9 @@ moduleIntegrationTestRunner({
canceled_by: "cx_agent_123",
})
await expect(
service.cancelOrderChange(orderChange.id)
).rejects.toThrowError("Order Change cannot be modified")
await expect(service.cancelOrderChange(orderChange.id)).rejects.toThrow(
"Order Change cannot be modified"
)
await service.declineOrderChange({
id: orderChange2.id,
@@ -593,7 +596,7 @@ moduleIntegrationTestRunner({
await expect(
service.declineOrderChange(orderChange2.id)
).rejects.toThrowError("Order Change cannot be modified")
).rejects.toThrow("Order Change cannot be modified")
const [change1, change2] = await service.listOrderChanges(
{
@@ -0,0 +1,230 @@
import { Modules } from "@medusajs/modules-sdk"
import { CreateOrderDTO, IOrderModuleService } from "@medusajs/types"
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
jest.setTimeout(100000)
moduleIntegrationTestRunner({
moduleName: Modules.ORDER,
testSuite: ({ service }: SuiteOptions<IOrderModuleService>) => {
describe("Order Module Service - Exchange flows", () => {
const input = {
email: "foo@bar.com",
items: [
{
title: "Item 1",
subtitle: "Subtitle 1",
thumbnail: "thumbnail1.jpg",
quantity: 1,
product_id: "product1",
product_title: "Product 1",
product_description: "Description 1",
product_subtitle: "Product Subtitle 1",
product_type: "Type 1",
product_collection: "Collection 1",
product_handle: "handle1",
variant_id: "variant1",
variant_sku: "SKU1",
variant_barcode: "Barcode1",
variant_title: "Variant 1",
variant_option_values: {
color: "Red",
size: "Large",
},
requires_shipping: true,
is_discountable: true,
is_tax_inclusive: true,
compare_at_unit_price: 10,
unit_price: 8,
tax_lines: [
{
description: "Tax 1",
tax_rate_id: "tax_usa",
code: "code",
rate: 0.1,
provider_id: "taxify_master",
},
],
adjustments: [
{
code: "VIP_10",
amount: 10,
description: "VIP discount",
promotion_id: "prom_123",
provider_id: "coupon_kings",
},
],
},
{
title: "Item 2",
quantity: 2,
unit_price: 5,
},
{
title: "Item 3",
quantity: 1,
unit_price: 30,
},
],
sales_channel_id: "test",
shipping_address: {
first_name: "Test",
last_name: "Test",
address_1: "Test",
city: "Test",
country_code: "US",
postal_code: "12345",
phone: "12345",
},
billing_address: {
first_name: "Test",
last_name: "Test",
address_1: "Test",
city: "Test",
country_code: "US",
postal_code: "12345",
},
shipping_methods: [
{
name: "Test shipping method",
amount: 10,
},
],
transactions: [
{
amount: 58,
currency_code: "USD",
reference: "payment",
reference_id: "pay_123",
},
],
currency_code: "usd",
customer_id: "joe",
} as CreateOrderDTO
it("should exchange an item and add two new items to the order", async function () {
const createdOrder = await service.create(input)
// Fullfilment
await service.registerFulfillment({
order_id: createdOrder.id,
items: createdOrder.items!.map((item) => {
return {
id: item.id,
quantity: item.quantity,
}
}),
})
// Shipment
await service.registerShipment({
order_id: createdOrder.id,
reference: Modules.FULFILLMENT,
items: createdOrder.items!.map((item) => {
return {
id: item.id,
quantity: item.quantity,
}
}),
})
// Exchange
const reason = await service.createReturnReasons({
value: "wrong-size",
label: "Wrong Size",
})
const orderExchange = await service.createExchange({
order_id: createdOrder.id,
description: "Exchange all the items",
internal_note: "user wants to return all items",
difference_due: 14,
shipping_methods: [
{
name: "Exchange method",
amount: 35,
provider_id: "dhl",
},
],
return_items: [
{
id: createdOrder.items![0].id,
reason_id: reason.id,
quantity: 1,
note: "I don't need this",
},
],
additional_items: [
{
id: createdOrder.items![2].id,
quantity: 1,
},
{
unit_price: 20,
quantity: 1,
title: "New item",
},
],
return_amount: 5,
return_shipping: {
name: "return shipping method",
amount: 10,
provider_id: "test_provider_id",
},
})
expect(orderExchange).toEqual(
expect.objectContaining({
id: orderExchange.id,
order_id: createdOrder.id,
return: expect.objectContaining({
order_id: createdOrder.id,
exchange_id: orderExchange.id,
status: "requested",
items: expect.arrayContaining([
expect.objectContaining({
item_id: createdOrder.items![0].id,
quantity: 1,
}),
]),
}),
additional_items: expect.arrayContaining([
expect.objectContaining({
exchange_id: orderExchange.id,
quantity: 1,
item: expect.objectContaining({
title: "New item",
}),
detail: expect.objectContaining({
quantity: 1,
}),
}),
expect.objectContaining({
exchange_id: orderExchange.id,
item_id: createdOrder.items![2].id,
quantity: 1,
item: expect.objectContaining({
title: "Item 3",
}),
detail: expect.objectContaining({
quantity: 2,
}),
}),
]),
shipping_methods: [
expect.objectContaining({
name: "return shipping method",
amount: 10,
}),
expect.objectContaining({
name: "Exchange method",
amount: 35,
}),
],
difference_due: 14,
})
)
})
})
},
})
@@ -2,7 +2,7 @@ import { Modules } from "@medusajs/modules-sdk"
import { CreateOrderDTO, IOrderModuleService } from "@medusajs/types"
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
jest.setTimeout(100000)
jest.setTimeout(1000000)
moduleIntegrationTestRunner({
moduleName: Modules.ORDER,
@@ -135,12 +135,10 @@ moduleIntegrationTestRunner({
expect(serializedOrder).toEqual(
expect.objectContaining({
version: 2,
items: [
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 2,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 0,
@@ -149,7 +147,6 @@ moduleIntegrationTestRunner({
expect.objectContaining({
quantity: 2,
detail: expect.objectContaining({
version: 2,
quantity: 2,
fulfilled_quantity: 2,
shipped_quantity: 0,
@@ -158,7 +155,6 @@ moduleIntegrationTestRunner({
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 2,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 0,
@@ -199,12 +195,10 @@ moduleIntegrationTestRunner({
expect(serializedOrder).toEqual(
expect.objectContaining({
version: 3,
items: [
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 3,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
@@ -213,7 +207,6 @@ moduleIntegrationTestRunner({
expect.objectContaining({
quantity: 2,
detail: expect.objectContaining({
version: 3,
quantity: 2,
fulfilled_quantity: 2,
shipped_quantity: 2,
@@ -222,7 +215,6 @@ moduleIntegrationTestRunner({
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 3,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
@@ -233,6 +225,15 @@ moduleIntegrationTestRunner({
)
// Return
const reason = await service.createReturnReasons({
value: "wrong-size",
label: "Wrong Size",
})
const reason2 = await service.createReturnReasons({
value: "disliked",
label: "Disliled",
})
const orderReturn = await service.createReturn({
order_id: createdOrder.id,
reference: Modules.FULFILLMENT,
@@ -245,11 +246,29 @@ moduleIntegrationTestRunner({
items: createdOrder.items!.map((item) => {
return {
id: item.id,
quantity: item.quantity,
quantity: 1,
reason_id: reason.id,
}
}),
})
const secondReturn = await service.createReturn({
order_id: createdOrder.id,
reference: Modules.FULFILLMENT,
description: "Return remaining item",
shipping_method: {
name: "Return method",
amount: 5,
},
items: [
{
id: createdOrder.items![1].id,
quantity: 1,
reason_id: reason2.id,
},
],
})
getOrder = await service.retrieve(createdOrder.id, {
select: [
"id",
@@ -270,12 +289,10 @@ moduleIntegrationTestRunner({
expect(serializedOrder).toEqual(
expect.objectContaining({
version: 4,
items: [
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 4,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
@@ -285,7 +302,6 @@ moduleIntegrationTestRunner({
expect.objectContaining({
quantity: 2,
detail: expect.objectContaining({
version: 4,
quantity: 2,
fulfilled_quantity: 2,
shipped_quantity: 2,
@@ -295,7 +311,6 @@ moduleIntegrationTestRunner({
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 4,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
@@ -310,10 +325,11 @@ moduleIntegrationTestRunner({
const allItems = createdOrder.items!.map((item) => {
return {
id: item.id,
quantity: item.quantity,
quantity: 1,
}
})
const lastItem = allItems.pop()!
const receive = await service.receiveReturn({
return_id: orderReturn.id,
internal_note: "received some items",
@@ -326,6 +342,30 @@ moduleIntegrationTestRunner({
items: [lastItem],
})
const receiveSecond = await service.receiveReturn({
return_id: secondReturn.id,
internal_note: "received some items",
items: [
{
id: createdOrder.items![1].id,
quantity: 1,
},
],
})
expect(receiveSecond).toEqual(
expect.objectContaining({
status: "received",
received_at: expect.any(Date),
items: expect.arrayContaining([
expect.objectContaining({
item_id: createdOrder.items![1].id,
received_quantity: 1,
}),
]),
})
)
expect(receive).toEqual(
expect.objectContaining({
id: orderReturn.id,
@@ -333,17 +373,17 @@ moduleIntegrationTestRunner({
received_at: null,
items: expect.arrayContaining([
expect.objectContaining({
id: allItems[0].id,
item_id: allItems[0].id,
detail: expect.objectContaining({
return_requested_quantity: 0,
return_received_quantity: 1,
}),
}),
expect.objectContaining({
id: allItems[1].id,
item_id: allItems[1].id,
detail: expect.objectContaining({
return_requested_quantity: 0,
return_received_quantity: 2,
return_requested_quantity: 1,
return_received_quantity: 1,
}),
}),
]),
@@ -357,21 +397,21 @@ moduleIntegrationTestRunner({
received_at: expect.any(Date),
items: expect.arrayContaining([
expect.objectContaining({
id: allItems[0].id,
item_id: allItems[0].id,
detail: expect.objectContaining({
return_requested_quantity: 0,
return_received_quantity: 1,
}),
}),
expect.objectContaining({
id: allItems[1].id,
item_id: allItems[1].id,
detail: expect.objectContaining({
return_requested_quantity: 0,
return_received_quantity: 2,
return_requested_quantity: 1,
return_received_quantity: 1,
}),
}),
expect.objectContaining({
id: lastItem.id,
item_id: lastItem.id,
detail: expect.objectContaining({
return_requested_quantity: 0,
return_received_quantity: 1,
@@ -402,12 +442,10 @@ moduleIntegrationTestRunner({
expect(serializedOrder).toEqual(
expect.objectContaining({
version: 6,
items: [
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 6,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
@@ -418,7 +456,6 @@ moduleIntegrationTestRunner({
expect.objectContaining({
quantity: 2,
detail: expect.objectContaining({
version: 6,
quantity: 2,
fulfilled_quantity: 2,
shipped_quantity: 2,
@@ -429,7 +466,6 @@ moduleIntegrationTestRunner({
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 6,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,