fix(medusa): RMA on items from swaps and claims (#1182)
This commit is contained in:
@@ -4,6 +4,7 @@ const {
|
||||
Order,
|
||||
LineItem,
|
||||
CustomShippingOption,
|
||||
ShippingMethod,
|
||||
} = require("@medusajs/medusa")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
@@ -914,6 +915,215 @@ describe("/admin/orders", () => {
|
||||
])
|
||||
})
|
||||
|
||||
it("creates a claim on a claim additional item", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/orders/test-order/claims",
|
||||
{
|
||||
type: "replace",
|
||||
shipping_methods: [
|
||||
{
|
||||
id: "test-method",
|
||||
},
|
||||
],
|
||||
claim_items: [
|
||||
{
|
||||
item_id: "test-item",
|
||||
quantity: 1,
|
||||
reason: "production_failure",
|
||||
tags: ["fluff"],
|
||||
images: ["https://test.image.com"],
|
||||
},
|
||||
],
|
||||
additional_items: [
|
||||
{
|
||||
variant_id: "test-variant",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const cid = response.data.order.claims[0].id
|
||||
const fulRes = await api.post(
|
||||
`/admin/orders/test-order/claims/${cid}/fulfillments`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const claimItemIdToClaim =
|
||||
fulRes.data.order.claims[0].additional_items[0].id
|
||||
|
||||
const claimRes = await api
|
||||
.post(
|
||||
"/admin/orders/test-order/claims",
|
||||
{
|
||||
type: "replace",
|
||||
shipping_methods: [
|
||||
{
|
||||
id: "test-method",
|
||||
},
|
||||
],
|
||||
claim_items: [
|
||||
{
|
||||
item_id: claimItemIdToClaim,
|
||||
quantity: 1,
|
||||
reason: "production_failure",
|
||||
tags: ["fluff"],
|
||||
images: ["https://test.image2.com"],
|
||||
},
|
||||
],
|
||||
additional_items: [
|
||||
{
|
||||
variant_id: "test-variant-2",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(claimRes.status).toEqual(200)
|
||||
expect(claimRes.data.order.claims.length).toEqual(2)
|
||||
|
||||
const newClaim = claimRes.data.order.claims.find(
|
||||
(c) => c.fulfillment_status === "not_fulfilled"
|
||||
)
|
||||
|
||||
expect(newClaim.claim_items[0].item.id).toEqual(claimItemIdToClaim)
|
||||
})
|
||||
|
||||
it("creates a claim on a swap additional item", async () => {
|
||||
const api = useApi()
|
||||
|
||||
// create a swap
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/orders/test-order/swaps",
|
||||
{
|
||||
custom_shipping_options: [{ option_id: "test-option", price: 0 }],
|
||||
return_items: [
|
||||
{
|
||||
item_id: "test-item",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
additional_items: [{ variant_id: "test-variant-2", quantity: 1 }],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e))
|
||||
|
||||
const sid = response.data.order.swaps[0].id
|
||||
const manager = dbConnection.manager
|
||||
|
||||
// add a shipping method so we can fulfill the swap
|
||||
const sm = await manager.create(ShippingMethod, {
|
||||
id: "test-method-swap-cart",
|
||||
swap_id: sid,
|
||||
shipping_option_id: "test-option",
|
||||
price: 0,
|
||||
data: {},
|
||||
})
|
||||
|
||||
await manager.save(sm)
|
||||
|
||||
// fulfill the swap
|
||||
const fulRes = await api
|
||||
.post(
|
||||
`/admin/orders/test-order/swaps/${sid}/fulfillments`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e))
|
||||
|
||||
// ship the swap
|
||||
await api
|
||||
.post(
|
||||
`/admin/orders/test-order/swaps/${sid}/shipments`,
|
||||
{
|
||||
fulfillment_id: fulRes.data.order.swaps[0].fulfillments[0].id,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e))
|
||||
|
||||
const claimItemIdToClaim =
|
||||
fulRes.data.order.swaps[0].additional_items[0].id
|
||||
|
||||
// create a claim on the exchange
|
||||
const claimRes = await api
|
||||
.post(
|
||||
"/admin/orders/test-order/claims",
|
||||
{
|
||||
type: "replace",
|
||||
claim_items: [
|
||||
{
|
||||
item_id: claimItemIdToClaim,
|
||||
quantity: 1,
|
||||
reason: "production_failure",
|
||||
tags: ["fluff"],
|
||||
images: ["https://test.image2.com"],
|
||||
},
|
||||
],
|
||||
additional_items: [
|
||||
{
|
||||
variant_id: "test-variant-2",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(claimRes.status).toEqual(200)
|
||||
expect(claimRes.data.order.claims.length).toEqual(1)
|
||||
|
||||
const newClaim = claimRes.data.order.claims[0]
|
||||
|
||||
expect(newClaim.claim_items[0].item.id).toEqual(claimItemIdToClaim)
|
||||
})
|
||||
|
||||
it("Only allow canceling claim after canceling fulfillments", async () => {
|
||||
const order_id = "order-with-claim"
|
||||
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
const path = require("path")
|
||||
import { ReturnReason, ShippingMethod } from "@medusajs/medusa"
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const orderSeeder = require("../../helpers/order-seeder")
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/admin/returns", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("POST /admin/returns/:id", () => {
|
||||
let rrId
|
||||
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
await orderSeeder(dbConnection)
|
||||
|
||||
const created = dbConnection.manager.create(ReturnReason, {
|
||||
value: "too_big",
|
||||
label: "Too Big",
|
||||
})
|
||||
const resultRR = await dbConnection.manager.save(created)
|
||||
rrId = resultRR.id
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should receive a return on an item added through swap additional items", async () => {
|
||||
const api = useApi()
|
||||
|
||||
// create a swap
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/orders/test-order/swaps",
|
||||
{
|
||||
custom_shipping_options: [{ option_id: "test-option", price: 0 }],
|
||||
return_items: [
|
||||
{
|
||||
item_id: "test-item",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
additional_items: [{ variant_id: "test-variant-2", quantity: 1 }],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e))
|
||||
|
||||
const sid = response.data.order.swaps[0].id
|
||||
const manager = dbConnection.manager
|
||||
|
||||
// add a shipping method so we can fulfill the swap
|
||||
const sm = await manager.create(ShippingMethod, {
|
||||
id: "test-method-swap-cart",
|
||||
swap_id: sid,
|
||||
shipping_option_id: "test-option",
|
||||
price: 0,
|
||||
data: {},
|
||||
})
|
||||
|
||||
await manager.save(sm)
|
||||
|
||||
// fulfill the swap
|
||||
const fulRes = await api
|
||||
.post(
|
||||
`/admin/orders/test-order/swaps/${sid}/fulfillments`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e))
|
||||
|
||||
// ship the swap
|
||||
await api
|
||||
.post(
|
||||
`/admin/orders/test-order/swaps/${sid}/shipments`,
|
||||
{
|
||||
fulfillment_id: fulRes.data.order.swaps[0].fulfillments[0].id,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e))
|
||||
|
||||
const swapItemId = fulRes.data.order.swaps[0].additional_items[0].id
|
||||
|
||||
// request a return
|
||||
const returnRes = await api
|
||||
.post(
|
||||
`/admin/orders/test-order/return`,
|
||||
{
|
||||
items: [
|
||||
{
|
||||
item_id: swapItemId,
|
||||
quantity: 1,
|
||||
reason_id: rrId,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e.response))
|
||||
|
||||
const returnId = returnRes.data.order.returns[0].id
|
||||
|
||||
const receiveRes = await api
|
||||
.post(
|
||||
`/admin/returns/${returnId}/receive`,
|
||||
{
|
||||
items: [
|
||||
{
|
||||
item_id: swapItemId,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e.response))
|
||||
|
||||
expect(receiveRes.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("should receive a return on an item added through claim additional items", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/orders/test-order/claims",
|
||||
{
|
||||
type: "replace",
|
||||
shipping_methods: [
|
||||
{
|
||||
id: "test-method",
|
||||
},
|
||||
],
|
||||
claim_items: [
|
||||
{
|
||||
item_id: "test-item",
|
||||
quantity: 1,
|
||||
reason: "production_failure",
|
||||
tags: ["fluff"],
|
||||
images: ["https://test.image.com"],
|
||||
},
|
||||
],
|
||||
additional_items: [
|
||||
{
|
||||
variant_id: "test-variant",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const cid = response.data.order.claims[0].id
|
||||
const fulRes = await api.post(
|
||||
`/admin/orders/test-order/claims/${cid}/fulfillments`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const claimItemId = fulRes.data.order.claims[0].additional_items[0].id
|
||||
|
||||
// request a return
|
||||
const returnRes = await api
|
||||
.post(
|
||||
`/admin/orders/test-order/return`,
|
||||
{
|
||||
items: [
|
||||
{
|
||||
item_id: claimItemId,
|
||||
quantity: 1,
|
||||
reason_id: rrId,
|
||||
},
|
||||
],
|
||||
return_shipping: {
|
||||
option_id: "test-option",
|
||||
price: 0,
|
||||
}
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e.response))
|
||||
|
||||
const returnId = returnRes.data.order.returns[0].id
|
||||
|
||||
const receiveRes = await api
|
||||
.post(
|
||||
`/admin/returns/${returnId}/receive`,
|
||||
{
|
||||
items: [
|
||||
{
|
||||
item_id: claimItemId,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((e) => console.log(e.response))
|
||||
|
||||
expect(receiveRes.status).toEqual(200)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -153,6 +153,7 @@ module.exports = async (connection, data = {}) => {
|
||||
currency_code: "usd",
|
||||
amount_refunded: 0,
|
||||
provider_id: "test-pay",
|
||||
captured_at: new Date(),
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { Type } from "class-transformer"
|
||||
import {
|
||||
IsArray,
|
||||
IsOptional,
|
||||
ValidateNested,
|
||||
IsBoolean,
|
||||
IsObject,
|
||||
IsString,
|
||||
IsEnum,
|
||||
IsInt,
|
||||
IsNotEmpty,
|
||||
IsEnum,
|
||||
IsObject,
|
||||
IsOptional,
|
||||
IsString,
|
||||
ValidateNested,
|
||||
} from "class-validator"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { defaultAdminOrdersRelations, defaultAdminOrdersFields } from "."
|
||||
import { defaultAdminOrdersFields, defaultAdminOrdersRelations } from "."
|
||||
import { AddressPayload } from "../../../../types/common"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
|
||||
@@ -177,6 +177,12 @@ export default async (req, res) => {
|
||||
"items.tax_lines",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"claims",
|
||||
"claims.additional_items",
|
||||
"claims.additional_items.tax_lines",
|
||||
"swaps",
|
||||
"swaps.additional_items",
|
||||
"swaps.additional_items.tax_lines",
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
@@ -230,7 +230,35 @@ class ClaimService extends BaseService {
|
||||
let toRefund = refund_amount
|
||||
if (type === "refund" && typeof refund_amount === "undefined") {
|
||||
const lines = claim_items.map((ci) => {
|
||||
const orderItem = order.items.find((oi) => oi.id === ci.item_id)
|
||||
const allOrderItems = order.items
|
||||
|
||||
if (order.swaps?.length) {
|
||||
for (const swap of order.swaps) {
|
||||
swap.additional_items.forEach((it) => {
|
||||
if (
|
||||
it.shipped_quantity ||
|
||||
it.shipped_quantity === it.fulfilled_quantity
|
||||
) {
|
||||
allOrderItems.push(it)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (order.claims?.length) {
|
||||
for (const claim of order.claims) {
|
||||
claim.additional_items.forEach((it) => {
|
||||
if (
|
||||
it.shipped_quantity ||
|
||||
it.shipped_quantity === it.fulfilled_quantity
|
||||
) {
|
||||
allOrderItems.push(it)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const orderItem = allOrderItems.find((oi) => oi.id === ci.item_id)
|
||||
return {
|
||||
...orderItem,
|
||||
quantity: ci.quantity,
|
||||
|
||||
@@ -563,6 +563,8 @@ class ReturnService extends BaseService {
|
||||
"region",
|
||||
"swaps",
|
||||
"swaps.additional_items",
|
||||
"claims",
|
||||
"claims.additional_items",
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user