feat(medusa): Swaps on swaps (#229)
Co-authored-by: Sebastian Rindom <skrindom@gmail.com>
This commit is contained in:
co-authored by
Sebastian Rindom
parent
2f3e3fde80
commit
f8f1f57fa1
@@ -51,6 +51,7 @@ const defaultFields = [
|
||||
"updated_at",
|
||||
"metadata",
|
||||
"items.refundable",
|
||||
"swaps.additional_items.refundable",
|
||||
"shipping_total",
|
||||
"discount_total",
|
||||
"tax_total",
|
||||
@@ -58,6 +59,7 @@ const defaultFields = [
|
||||
"gift_card_total",
|
||||
"subtotal",
|
||||
"total",
|
||||
"paid_total",
|
||||
"refundable_amount",
|
||||
]
|
||||
|
||||
|
||||
@@ -37,21 +37,18 @@ describe("POST /admin/orders/:id/return", () => {
|
||||
|
||||
it("calls OrderService return", () => {
|
||||
expect(ReturnService.create).toHaveBeenCalledTimes(1)
|
||||
expect(ReturnService.create).toHaveBeenCalledWith(
|
||||
{
|
||||
order_id: IdMap.getId("test-order"),
|
||||
idempotency_key: "testkey",
|
||||
items: [
|
||||
{
|
||||
item_id: IdMap.getId("existingLine"),
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
refund_amount: 10,
|
||||
shipping_method: undefined,
|
||||
},
|
||||
orders.testOrder
|
||||
)
|
||||
expect(ReturnService.create).toHaveBeenCalledWith({
|
||||
order_id: IdMap.getId("test-order"),
|
||||
idempotency_key: "testkey",
|
||||
items: [
|
||||
{
|
||||
item_id: IdMap.getId("existingLine"),
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
refund_amount: 10,
|
||||
shipping_method: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -88,21 +85,18 @@ describe("POST /admin/orders/:id/return", () => {
|
||||
|
||||
it("calls OrderService return", () => {
|
||||
expect(ReturnService.create).toHaveBeenCalledTimes(1)
|
||||
expect(ReturnService.create).toHaveBeenCalledWith(
|
||||
{
|
||||
order_id: IdMap.getId("test-order"),
|
||||
idempotency_key: "testkey",
|
||||
items: [
|
||||
{
|
||||
item_id: IdMap.getId("existingLine"),
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
refund_amount: 0,
|
||||
shipping_method: undefined,
|
||||
},
|
||||
orders.testOrder
|
||||
)
|
||||
expect(ReturnService.create).toHaveBeenCalledWith({
|
||||
order_id: IdMap.getId("test-order"),
|
||||
idempotency_key: "testkey",
|
||||
items: [
|
||||
{
|
||||
item_id: IdMap.getId("existingLine"),
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
refund_amount: 0,
|
||||
shipping_method: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -139,21 +133,18 @@ describe("POST /admin/orders/:id/return", () => {
|
||||
|
||||
it("calls OrderService return", () => {
|
||||
expect(ReturnService.create).toHaveBeenCalledTimes(1)
|
||||
expect(ReturnService.create).toHaveBeenCalledWith(
|
||||
{
|
||||
order_id: IdMap.getId("test-order"),
|
||||
idempotency_key: "testkey",
|
||||
items: [
|
||||
{
|
||||
item_id: IdMap.getId("existingLine"),
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
refund_amount: 0,
|
||||
shipping_method: undefined,
|
||||
},
|
||||
orders.testOrder
|
||||
)
|
||||
expect(ReturnService.create).toHaveBeenCalledWith({
|
||||
order_id: IdMap.getId("test-order"),
|
||||
idempotency_key: "testkey",
|
||||
items: [
|
||||
{
|
||||
item_id: IdMap.getId("existingLine"),
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
refund_amount: 0,
|
||||
shipping_method: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -194,24 +185,21 @@ describe("POST /admin/orders/:id/return", () => {
|
||||
|
||||
it("calls OrderService return", () => {
|
||||
expect(ReturnService.create).toHaveBeenCalledTimes(1)
|
||||
expect(ReturnService.create).toHaveBeenCalledWith(
|
||||
{
|
||||
order_id: IdMap.getId("test-order"),
|
||||
idempotency_key: "testkey",
|
||||
items: [
|
||||
{
|
||||
item_id: IdMap.getId("existingLine"),
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
refund_amount: 100,
|
||||
shipping_method: {
|
||||
option_id: "opt_1234",
|
||||
price: 12,
|
||||
expect(ReturnService.create).toHaveBeenCalledWith({
|
||||
order_id: IdMap.getId("test-order"),
|
||||
idempotency_key: "testkey",
|
||||
items: [
|
||||
{
|
||||
item_id: IdMap.getId("existingLine"),
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
refund_amount: 100,
|
||||
shipping_method: {
|
||||
option_id: "opt_1234",
|
||||
price: 12,
|
||||
},
|
||||
orders.testOrder
|
||||
)
|
||||
})
|
||||
|
||||
expect(ReturnService.fulfill).toHaveBeenCalledTimes(1)
|
||||
expect(ReturnService.fulfill).toHaveBeenCalledWith("return")
|
||||
|
||||
@@ -124,7 +124,7 @@ export default async (req, res) => {
|
||||
.withTransaction(manager)
|
||||
.retrieve(id, {
|
||||
select: ["refunded_total", "total"],
|
||||
relations: ["items", "swaps"],
|
||||
relations: ["items", "swaps", "swaps.additional_items"],
|
||||
})
|
||||
|
||||
const swap = await swapService
|
||||
|
||||
@@ -78,14 +78,6 @@ export default app => {
|
||||
middlewares.wrap(require("./request-return").default)
|
||||
)
|
||||
|
||||
/**
|
||||
* Register a requested return
|
||||
*/
|
||||
route.post(
|
||||
"/:id/return/:return_id/receive",
|
||||
middlewares.wrap(require("./receive-return").default)
|
||||
)
|
||||
|
||||
/**
|
||||
* Cancel an order.
|
||||
*/
|
||||
@@ -234,6 +226,7 @@ export const defaultFields = [
|
||||
"updated_at",
|
||||
"metadata",
|
||||
"items.refundable",
|
||||
"swaps.additional_items.refundable",
|
||||
"shipping_total",
|
||||
"discount_total",
|
||||
"tax_total",
|
||||
@@ -241,6 +234,7 @@ export const defaultFields = [
|
||||
"gift_card_total",
|
||||
"subtotal",
|
||||
"total",
|
||||
"paid_total",
|
||||
"refundable_amount",
|
||||
]
|
||||
|
||||
@@ -267,6 +261,7 @@ export const allowedFields = [
|
||||
"subtotal",
|
||||
"gift_card_total",
|
||||
"total",
|
||||
"paid_total",
|
||||
"refundable_amount",
|
||||
]
|
||||
|
||||
|
||||
@@ -123,13 +123,6 @@ export default async (req, res) => {
|
||||
const { key, error } = await idempotencyKeyService.workStage(
|
||||
idempotencyKey.idempotency_key,
|
||||
async manager => {
|
||||
const order = await orderService
|
||||
.withTransaction(manager)
|
||||
.retrieve(id, {
|
||||
select: ["refunded_total", "total"],
|
||||
relations: ["items"],
|
||||
})
|
||||
|
||||
const returnObj = {
|
||||
order_id: id,
|
||||
idempotency_key: idempotencyKey.idempotency_key,
|
||||
@@ -150,7 +143,7 @@ export default async (req, res) => {
|
||||
|
||||
const createdReturn = await returnService
|
||||
.withTransaction(manager)
|
||||
.create(returnObj, order)
|
||||
.create(returnObj)
|
||||
|
||||
if (value.return_shipping) {
|
||||
await returnService
|
||||
@@ -208,7 +201,7 @@ export default async (req, res) => {
|
||||
|
||||
order = await returnService
|
||||
.withTransaction(manager)
|
||||
.receiveReturn(order.id, ret.id, value.items, value.refund)
|
||||
.receive(ret.id, value.items, value.refund)
|
||||
}
|
||||
|
||||
order = await orderService.withTransaction(manager).retrieve(id, {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { OrderServiceMock } from "../../../../../services/__mocks__/order"
|
||||
import { ReturnService } from "../../../../../services/__mocks__/return"
|
||||
|
||||
describe("POST /admin/returns/:id/receive", () => {
|
||||
describe("successfully receives a return", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/returns/${IdMap.getId("test-return")}/receive`,
|
||||
{
|
||||
payload: {
|
||||
items: [
|
||||
{
|
||||
item_id: IdMap.getId("test"),
|
||||
quantity: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls ReturnService receive", () => {
|
||||
expect(ReturnService.receive).toHaveBeenCalledTimes(1)
|
||||
expect(ReturnService.receive).toHaveBeenCalledWith(
|
||||
IdMap.getId("test-return"),
|
||||
[{ item_id: IdMap.getId("test"), quantity: 2 }],
|
||||
undefined,
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
it("calls OrderService registerReturnReceived", () => {
|
||||
expect(OrderServiceMock.registerReturnReceived).toHaveBeenCalledTimes(1)
|
||||
expect(OrderServiceMock.registerReturnReceived).toHaveBeenCalledWith(
|
||||
IdMap.getId("test-order"),
|
||||
{
|
||||
id: IdMap.getId("test-return"),
|
||||
order_id: IdMap.getId("test-order"),
|
||||
},
|
||||
undefined
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -11,5 +11,10 @@ export default app => {
|
||||
*/
|
||||
route.get("/", middlewares.wrap(require("./list-returns").default))
|
||||
|
||||
route.post(
|
||||
"/:id/receive",
|
||||
middlewares.wrap(require("./receive-return").default)
|
||||
)
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
+38
-25
@@ -1,14 +1,12 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
import { defaultRelations, defaultFields } from "./"
|
||||
|
||||
/**
|
||||
* @oas [post] /orders/{id}/returns/{return_id}/receive
|
||||
* operationId: "PostOrdersOrderReturnsReturnReceive"
|
||||
* @oas [post] /returns/{id}receive
|
||||
* operationId: "PostReturnsReturnReceive"
|
||||
* summary: "Receive a Return"
|
||||
* description: "Registers a Return as received."
|
||||
* description: "Registers a Return as received. Updates statuses on Orders and Swaps accordingly."
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Order.
|
||||
* - (path) return_id=* {string} The id of the Return.
|
||||
* - (path) id=* {string} The id of the Return.
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
@@ -29,7 +27,7 @@ import { defaultRelations, defaultFields } from "./"
|
||||
* description: The amount to refund.
|
||||
* type: integer
|
||||
* tags:
|
||||
* - Order
|
||||
* - Return
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
@@ -37,11 +35,11 @@ import { defaultRelations, defaultFields } from "./"
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* order:
|
||||
* $ref: "#/components/schemas/order"
|
||||
* return:
|
||||
* $ref: "#/components/schemas/return"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id, return_id } = req.params
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
items: Validator.array()
|
||||
@@ -61,28 +59,43 @@ export default async (req, res) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const returnService = req.scope.resolve("returnService")
|
||||
const orderService = req.scope.resolve("orderService")
|
||||
const swapService = req.scope.resolve("swapService")
|
||||
const entityManager = req.scope.resolve("manager")
|
||||
|
||||
let refundAmount = value.refund
|
||||
let receivedReturn
|
||||
await entityManager.transaction(async manager => {
|
||||
let refundAmount = value.refund
|
||||
|
||||
if (typeof value.refund !== "undefined" && value.refund < 0) {
|
||||
refundAmount = 0
|
||||
}
|
||||
if (typeof value.refund !== "undefined" && value.refund < 0) {
|
||||
refundAmount = 0
|
||||
}
|
||||
|
||||
let order = await orderService.receiveReturn(
|
||||
id,
|
||||
return_id,
|
||||
value.items,
|
||||
refundAmount,
|
||||
true
|
||||
)
|
||||
receivedReturn = await returnService
|
||||
.withTransaction(manager)
|
||||
.receive(id, value.items, refundAmount, true)
|
||||
|
||||
order = await orderService.retrieve(id, {
|
||||
select: defaultFields,
|
||||
relations: defaultRelations,
|
||||
if (receivedReturn.order_id) {
|
||||
await orderService
|
||||
.withTransaction(manager)
|
||||
.registerReturnReceived(
|
||||
receivedReturn.order_id,
|
||||
receivedReturn,
|
||||
refundAmount
|
||||
)
|
||||
}
|
||||
|
||||
if (receivedReturn.swap_id) {
|
||||
await swapService
|
||||
.withTransaction(manager)
|
||||
.registerReceived(receivedReturn.swap_id)
|
||||
}
|
||||
})
|
||||
|
||||
res.status(200).json({ order })
|
||||
receivedReturn = await returnService.retrieve(id, { relations: ["swap"] })
|
||||
|
||||
res.status(200).json({ return: receivedReturn })
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
Reference in New Issue
Block a user