Feat/nested return reasons (#418)
* api endpoints for nested return_reasons * add nested return reasons to database * add parent reason to update * integration tests * add children relation * integration tests for nested returns and failing doubly nesting returns * add delete-route and nested relations * delete return reason route * doubly nested return reason creation check and deletion * nested return reasons migration * list only parent reasons * removed null filter * remove empty migration * add return reason filter to get list of categories with children * removed console log * corrected delete route * return reason testing * return reasons query * listREasonsFromIDs * create return testing * listReasonsFromIds * return reason tests * failing if returnreason has child on return * integration tests * cascading deletes on return reasons * more elegant checking for children of return reasons when creating a return * remove console.log * pr adjust Co-authored-by: Philip Korsholm <phko@MacBook-Pro.localdomain>
This commit is contained in:
1 parent
4db860f9ab
commit
42cdfde6d9
15 files changed
+744
-95
No files matched your search
@@ -0,0 +1,16 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`/admin/return-reasons POST /admin/return-reasons creates a return_reason 1`] = `
|
||||||
|
Object {
|
||||||
|
"created_at": Any<String>,
|
||||||
|
"deleted_at": null,
|
||||||
|
"description": "Use this if the size was too big",
|
||||||
|
"id": Any<String>,
|
||||||
|
"label": "Too Big",
|
||||||
|
"parent_return_reason": null,
|
||||||
|
"parent_return_reason_id": null,
|
||||||
|
"return_reason_children": Array [],
|
||||||
|
"updated_at": Any<String>,
|
||||||
|
"value": "too_big",
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -1,53 +1,55 @@
|
|||||||
const path = require("path");
|
const { match } = require("assert")
|
||||||
|
const path = require("path")
|
||||||
|
const { RepositoryNotTreeError } = require("typeorm")
|
||||||
|
|
||||||
const setupServer = require("../../../helpers/setup-server");
|
const setupServer = require("../../../helpers/setup-server")
|
||||||
const { useApi } = require("../../../helpers/use-api");
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
const { initDb, useDb } = require("../../../helpers/use-db");
|
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||||
|
|
||||||
const adminSeeder = require("../../helpers/admin-seeder");
|
const adminSeeder = require("../../helpers/admin-seeder")
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
describe("/admin/return-reasons", () => {
|
describe("/admin/return-reasons", () => {
|
||||||
let medusaProcess;
|
let medusaProcess
|
||||||
let dbConnection;
|
let dbConnection
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const cwd = path.resolve(path.join(__dirname, "..", ".."));
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
dbConnection = await initDb({ cwd });
|
dbConnection = await initDb({ cwd })
|
||||||
medusaProcess = await setupServer({ cwd });
|
medusaProcess = await setupServer({ cwd })
|
||||||
});
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
const db = useDb();
|
const db = useDb()
|
||||||
await db.shutdown();
|
await db.shutdown()
|
||||||
|
|
||||||
medusaProcess.kill();
|
medusaProcess.kill()
|
||||||
});
|
})
|
||||||
|
|
||||||
describe("POST /admin/return-reasons", () => {
|
describe("POST /admin/return-reasons", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
try {
|
try {
|
||||||
await adminSeeder(dbConnection);
|
await adminSeeder(dbConnection)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err)
|
||||||
throw err;
|
throw err
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
const db = useDb();
|
const db = useDb()
|
||||||
await db.teardown();
|
await db.teardown()
|
||||||
});
|
})
|
||||||
|
|
||||||
it("creates a return_reason", async () => {
|
it("creates a return_reason", async () => {
|
||||||
const api = useApi();
|
const api = useApi()
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
label: "Too Big",
|
label: "Too Big",
|
||||||
description: "Use this if the size was too big",
|
description: "Use this if the size was too big",
|
||||||
value: "too_big",
|
value: "too_big",
|
||||||
};
|
}
|
||||||
|
|
||||||
const response = await api
|
const response = await api
|
||||||
.post("/admin/return-reasons", payload, {
|
.post("/admin/return-reasons", payload, {
|
||||||
@@ -56,10 +58,172 @@ describe("/admin/return-reasons", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err)
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(response.status).toEqual(200);
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(response.data.return_reason).toMatchSnapshot({
|
||||||
|
id: expect.any(String),
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
parent_return_reason: null,
|
||||||
|
parent_return_reason_id: null,
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("creates a nested return reason", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
label: "Wrong size",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "wrong_size",
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/admin/return-reasons", payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(response.data.return_reason).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
label: "Wrong size",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "wrong_size",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const nested_payload = {
|
||||||
|
parent_return_reason_id: response.data.return_reason.id,
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
}
|
||||||
|
|
||||||
|
const nested_response = await api
|
||||||
|
.post("/admin/return-reasons", nested_payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(nested_response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(nested_response.data.return_reason).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
parent_return_reason_id: response.data.return_reason.id,
|
||||||
|
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails to create a doubly nested return reason", async () => {
|
||||||
|
expect.assertions(5)
|
||||||
|
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
label: "Wrong size",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "wrong_size",
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/admin/return-reasons", payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(response.data.return_reason).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
label: "Wrong size",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "wrong_size",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const nested_payload = {
|
||||||
|
parent_return_reason_id: response.data.return_reason.id,
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
}
|
||||||
|
|
||||||
|
const nested_response = await api
|
||||||
|
.post("/admin/return-reasons", nested_payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
const dbl_nested_payload = {
|
||||||
|
parent_return_reason_id: nested_response.data.return_reason.id,
|
||||||
|
label: "Too large size",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "large_size",
|
||||||
|
}
|
||||||
|
|
||||||
|
const dbl_nested_response = await api
|
||||||
|
.post("/admin/return-reasons", dbl_nested_payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
expect(err.response.status).toEqual(400)
|
||||||
|
expect(err.response.data.type).toEqual("invalid_data")
|
||||||
|
expect(err.response.data.message).toEqual(
|
||||||
|
"Doubly nested return reasons is not supported"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("deletes a return_reason", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/admin/return-reasons", payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
expect(response.data.return_reason).toEqual(
|
expect(response.data.return_reason).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -67,17 +231,37 @@ describe("/admin/return-reasons", () => {
|
|||||||
description: "Use this if the size was too big",
|
description: "Use this if the size was too big",
|
||||||
value: "too_big",
|
value: "too_big",
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
});
|
|
||||||
|
const deleteResponse = await api
|
||||||
|
.delete(`/admin/return-reasons/${response.data.return_reason.id}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(deleteResponse.data).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: response.data.return_reason.id,
|
||||||
|
object: "return_reason",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it("update a return reason", async () => {
|
it("update a return reason", async () => {
|
||||||
const api = useApi();
|
const api = useApi()
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
label: "Too Big Typo",
|
label: "Too Big Typo",
|
||||||
description: "Use this if the size was too big",
|
description: "Use this if the size was too big",
|
||||||
value: "too_big",
|
value: "too_big",
|
||||||
};
|
}
|
||||||
|
|
||||||
const response = await api
|
const response = await api
|
||||||
.post("/admin/return-reasons", payload, {
|
.post("/admin/return-reasons", payload, {
|
||||||
@@ -86,10 +270,10 @@ describe("/admin/return-reasons", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err)
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(response.status).toEqual(200);
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
expect(response.data.return_reason).toEqual(
|
expect(response.data.return_reason).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -97,7 +281,7 @@ describe("/admin/return-reasons", () => {
|
|||||||
description: "Use this if the size was too big",
|
description: "Use this if the size was too big",
|
||||||
value: "too_big",
|
value: "too_big",
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
|
|
||||||
const newResponse = await api
|
const newResponse = await api
|
||||||
.post(
|
.post(
|
||||||
@@ -113,8 +297,8 @@ describe("/admin/return-reasons", () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err)
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(newResponse.data.return_reason).toEqual(
|
expect(newResponse.data.return_reason).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -122,17 +306,81 @@ describe("/admin/return-reasons", () => {
|
|||||||
description: "new desc",
|
description: "new desc",
|
||||||
value: "too_big",
|
value: "too_big",
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
|
|
||||||
|
it("lists nested return reasons", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
label: "Wrong size",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "wrong_size",
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/admin/return-reasons", payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
const nested_payload = {
|
||||||
|
parent_return_reason_id: response.data.return_reason.id,
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
}
|
||||||
|
|
||||||
|
const resp = await api
|
||||||
|
.post("/admin/return-reasons", nested_payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
const nested_response = await api
|
||||||
|
.get("/admin/return-reasons", {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(nested_response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(nested_response.data.return_reasons).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
label: "Wrong size",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "wrong_size",
|
||||||
|
return_reason_children: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
it("list return reasons", async () => {
|
it("list return reasons", async () => {
|
||||||
const api = useApi();
|
const api = useApi()
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
label: "Too Big Typo",
|
label: "Too Big Typo",
|
||||||
description: "Use this if the size was too big",
|
description: "Use this if the size was too big",
|
||||||
value: "too_big",
|
value: "too_big",
|
||||||
};
|
}
|
||||||
|
|
||||||
await api
|
await api
|
||||||
.post("/admin/return-reasons", payload, {
|
.post("/admin/return-reasons", payload, {
|
||||||
@@ -141,8 +389,8 @@ describe("/admin/return-reasons", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err)
|
||||||
});
|
})
|
||||||
|
|
||||||
const response = await api
|
const response = await api
|
||||||
.get("/admin/return-reasons", {
|
.get("/admin/return-reasons", {
|
||||||
@@ -151,15 +399,191 @@ describe("/admin/return-reasons", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err)
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(response.status).toEqual(200);
|
expect(response.status).toEqual(200)
|
||||||
expect(response.data.return_reasons).toEqual([
|
expect(response.data.return_reasons).toEqual([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
value: "too_big",
|
value: "too_big",
|
||||||
}),
|
}),
|
||||||
]);
|
])
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
describe("DELETE /admin/return-reasons", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
try {
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("deletes single return reason", async () => {
|
||||||
|
expect.assertions(6)
|
||||||
|
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/admin/return-reasons", payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(response.data.return_reason).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const deleteResult = await api.delete(
|
||||||
|
`/admin/return-reasons/${response.data.return_reason.id}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(deleteResult.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(deleteResult.data).toEqual({
|
||||||
|
id: response.data.return_reason.id,
|
||||||
|
object: "return_reason",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const getResult = await api
|
||||||
|
.get(`/admin/return-reasons/${response.data.return_reason.id}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
expect(err.response.status).toEqual(404)
|
||||||
|
expect(err.response.data.type).toEqual("not_found")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("deletes cascade through nested return reasons", async () => {
|
||||||
|
expect.assertions(10)
|
||||||
|
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
label: "Wrong Size",
|
||||||
|
description: "Use this if the size was wrong",
|
||||||
|
value: "wrong_size",
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/admin/return-reasons", payload, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(response.data.return_reason).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
label: "Wrong Size",
|
||||||
|
description: "Use this if the size was wrong",
|
||||||
|
value: "wrong_size",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const payload_child = {
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
parent_return_reason_id: response.data.return_reason.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
const response_child = await api
|
||||||
|
.post("/admin/return-reasons", payload_child, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response_child.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(response_child.data.return_reason).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
label: "Too Big",
|
||||||
|
description: "Use this if the size was too big",
|
||||||
|
value: "too_big",
|
||||||
|
parent_return_reason_id: response.data.return_reason.id,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const deleteResult = await api
|
||||||
|
.delete(`/admin/return-reasons/${response.data.return_reason.id}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err.response.data)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(deleteResult.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(deleteResult.data).toEqual({
|
||||||
|
id: response.data.return_reason.id,
|
||||||
|
object: "return_reason",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
await api
|
||||||
|
.get(`/admin/return-reasons/${response.data.return_reason.id}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
expect(err.response.status).toEqual(404)
|
||||||
|
expect(err.response.data.type).toEqual("not_found")
|
||||||
|
})
|
||||||
|
|
||||||
|
await api
|
||||||
|
.get(`/admin/return-reasons/${response_child.data.return_reason.id}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
expect(err.response.status).toEqual(404)
|
||||||
|
expect(err.response.data.type).toEqual("not_found")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -26,16 +26,35 @@ describe("/store/return-reasons", () => {
|
|||||||
|
|
||||||
describe("GET /store/return-reasons", () => {
|
describe("GET /store/return-reasons", () => {
|
||||||
let rrId;
|
let rrId;
|
||||||
|
let rrId_1;
|
||||||
|
let rrId_2;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
try {
|
try {
|
||||||
const created = dbConnection.manager.create(ReturnReason, {
|
const created = dbConnection.manager.create(ReturnReason, {
|
||||||
value: "too_big",
|
value: "wrong_size",
|
||||||
label: "Too Big",
|
label: "Wrong size",
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await dbConnection.manager.save(created);
|
const result = await dbConnection.manager.save(created);
|
||||||
rrId = result.id;
|
rrId = result.id;
|
||||||
|
|
||||||
|
const created_child = dbConnection.manager.create(ReturnReason, {
|
||||||
|
value: "too_big",
|
||||||
|
label: "Too Big",
|
||||||
|
parent_return_reason_id: rrId
|
||||||
|
});
|
||||||
|
|
||||||
|
const result_child = await dbConnection.manager.save(created_child);
|
||||||
|
rrId_1 = result_child.id;
|
||||||
|
|
||||||
|
const created_2 = dbConnection.manager.create(ReturnReason, {
|
||||||
|
value: "too_big_1",
|
||||||
|
label: "Too Big 1",
|
||||||
|
});
|
||||||
|
|
||||||
|
const result_2 = await dbConnection.manager.save(created_2);
|
||||||
|
rrId_2 = result_2.id;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
throw err;
|
throw err;
|
||||||
@@ -59,7 +78,15 @@ describe("/store/return-reasons", () => {
|
|||||||
expect(response.data.return_reasons).toEqual([
|
expect(response.data.return_reasons).toEqual([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: rrId,
|
id: rrId,
|
||||||
value: "too_big",
|
value: "wrong_size",
|
||||||
|
return_reason_children:[expect.objectContaining({
|
||||||
|
id: rrId_1,
|
||||||
|
value: "too_big",
|
||||||
|
}),]
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: rrId_2,
|
||||||
|
value: "too_big_1",
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const {
|
|||||||
Product,
|
Product,
|
||||||
ProductVariant,
|
ProductVariant,
|
||||||
ShippingOption,
|
ShippingOption,
|
||||||
|
FulfillmentProvider,
|
||||||
LineItem,
|
LineItem,
|
||||||
Discount,
|
Discount,
|
||||||
DiscountRule,
|
DiscountRule,
|
||||||
@@ -37,6 +38,8 @@ describe("/store/carts", () => {
|
|||||||
|
|
||||||
describe("POST /store/returns", () => {
|
describe("POST /store/returns", () => {
|
||||||
let rrId;
|
let rrId;
|
||||||
|
let rrId_child;
|
||||||
|
let rrResult;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const manager = dbConnection.manager;
|
const manager = dbConnection.manager;
|
||||||
@@ -44,13 +47,17 @@ describe("/store/carts", () => {
|
|||||||
`ALTER SEQUENCE order_display_id_seq RESTART WITH 111`
|
`ALTER SEQUENCE order_display_id_seq RESTART WITH 111`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||||
|
type: "default",
|
||||||
|
});
|
||||||
|
|
||||||
await manager.insert(Region, {
|
await manager.insert(Region, {
|
||||||
id: "region",
|
id: "region",
|
||||||
name: "Test Region",
|
name: "Test Region",
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
tax_rate: 0,
|
tax_rate: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
await manager.insert(Customer, {
|
await manager.insert(Customer, {
|
||||||
id: "cus_1234",
|
id: "cus_1234",
|
||||||
email: "test@email.com",
|
email: "test@email.com",
|
||||||
@@ -98,10 +105,6 @@ describe("/store/carts", () => {
|
|||||||
|
|
||||||
await manager.save(ord);
|
await manager.save(ord);
|
||||||
|
|
||||||
const defaultProfile = await manager.findOne(ShippingProfile, {
|
|
||||||
type: "default",
|
|
||||||
});
|
|
||||||
|
|
||||||
await manager.insert(Product, {
|
await manager.insert(Product, {
|
||||||
id: "test-product",
|
id: "test-product",
|
||||||
title: "test product",
|
title: "test product",
|
||||||
@@ -147,12 +150,23 @@ describe("/store/carts", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const created = dbConnection.manager.create(ReturnReason, {
|
const created = dbConnection.manager.create(ReturnReason, {
|
||||||
value: "too_big",
|
value: "wrong_size",
|
||||||
label: "Too Big",
|
label: "Wrong Size",
|
||||||
});
|
});
|
||||||
const result = await dbConnection.manager.save(created);
|
const result = await dbConnection.manager.save(created);
|
||||||
|
|
||||||
|
rrResult = result
|
||||||
rrId = result.id;
|
rrId = result.id;
|
||||||
|
|
||||||
|
const created_1 = dbConnection.manager.create(ReturnReason, {
|
||||||
|
value: "too_big",
|
||||||
|
label: "Too Big",
|
||||||
|
parent_return_reason_id: rrId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result_1 = await dbConnection.manager.save(created_1);
|
||||||
|
|
||||||
|
rrId_child = result_1.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@@ -181,6 +195,59 @@ describe("/store/carts", () => {
|
|||||||
expect(response.data.return.refund_amount).toEqual(8000);
|
expect(response.data.return.refund_amount).toEqual(8000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("failes to create a return with a reason category", async () => {
|
||||||
|
const api = useApi();
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/store/returns", {
|
||||||
|
order_id: "order_test",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
reason_id: rrId,
|
||||||
|
note: "TOO small",
|
||||||
|
item_id: "test-item",
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
return err.response;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(response.status).toEqual(400);
|
||||||
|
expect(response.data.message).toEqual('Cannot apply return reason category')
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("creates a return with reasons", async () => {
|
||||||
|
const api = useApi();
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post("/store/returns", {
|
||||||
|
order_id: "order_test",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
reason_id: rrId_child,
|
||||||
|
note: "TOO small",
|
||||||
|
item_id: "test-item",
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err.response)
|
||||||
|
return err.response;
|
||||||
|
});
|
||||||
|
expect(response.status).toEqual(200);
|
||||||
|
|
||||||
|
expect(response.data.return.items).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
reason_id: rrId_child,
|
||||||
|
note: "TOO small",
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it("creates a return with discount and non-discountable item", async () => {
|
it("creates a return with discount and non-discountable item", async () => {
|
||||||
const api = useApi();
|
const api = useApi();
|
||||||
|
|
||||||
@@ -234,32 +301,5 @@ describe("/store/carts", () => {
|
|||||||
expect(response.data.return.refund_amount).toEqual(7000);
|
expect(response.data.return.refund_amount).toEqual(7000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("creates a return with reasons", async () => {
|
|
||||||
const api = useApi();
|
|
||||||
|
|
||||||
const response = await api
|
|
||||||
.post("/store/returns", {
|
|
||||||
order_id: "order_test",
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
reason_id: rrId,
|
|
||||||
note: "TOO small",
|
|
||||||
item_id: "test-item",
|
|
||||||
quantity: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
return err.response;
|
|
||||||
});
|
|
||||||
expect(response.status).toEqual(200);
|
|
||||||
|
|
||||||
expect(response.data.return.items).toEqual([
|
|
||||||
expect.objectContaining({
|
|
||||||
reason_id: rrId,
|
|
||||||
note: "TOO small",
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -39,6 +39,7 @@ export default async (req, res) => {
|
|||||||
const schema = Validator.object().keys({
|
const schema = Validator.object().keys({
|
||||||
value: Validator.string().required(),
|
value: Validator.string().required(),
|
||||||
label: Validator.string().required(),
|
label: Validator.string().required(),
|
||||||
|
parent_return_reason_id: Validator.string().optional(),
|
||||||
description: Validator.string()
|
description: Validator.string()
|
||||||
.optional()
|
.optional()
|
||||||
.allow(""),
|
.allow(""),
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @oas [delete] /return-reason/{id}
|
||||||
|
* operationId: "DeleteReturnReason"
|
||||||
|
* summary: "Delete a return reason"
|
||||||
|
* description: "Deletes a return reason."
|
||||||
|
* parameters:
|
||||||
|
* - (path) id=* {string} The id of the return reason
|
||||||
|
* tags:
|
||||||
|
* - Return Reason
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: OK
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* id:
|
||||||
|
* type: string
|
||||||
|
* description: The id of the deleted return reason
|
||||||
|
* object:
|
||||||
|
* type: string
|
||||||
|
* description: The type of the object that was deleted.
|
||||||
|
* deleted:
|
||||||
|
* type: boolean
|
||||||
|
*/
|
||||||
|
export default async (req, res) => {
|
||||||
|
const { id } = req.params
|
||||||
|
|
||||||
|
try {
|
||||||
|
const returnReasonService = req.scope.resolve("returnReasonService")
|
||||||
|
await returnReasonService.delete(id)
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
id: id,
|
||||||
|
object: "return_reason",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,11 @@ export default app => {
|
|||||||
*/
|
*/
|
||||||
route.post("/:id", middlewares.wrap(require("./update-reason").default))
|
route.post("/:id", middlewares.wrap(require("./update-reason").default))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a reason
|
||||||
|
*/
|
||||||
|
route.delete("/:id", middlewares.wrap(require("./delete-reason").default))
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,10 +38,14 @@ export const defaultFields = [
|
|||||||
"id",
|
"id",
|
||||||
"value",
|
"value",
|
||||||
"label",
|
"label",
|
||||||
|
"parent_return_reason_id",
|
||||||
"description",
|
"description",
|
||||||
"created_at",
|
"created_at",
|
||||||
"updated_at",
|
"updated_at",
|
||||||
"deleted_at",
|
"deleted_at",
|
||||||
]
|
]
|
||||||
|
|
||||||
export const defaultRelations = []
|
export const defaultRelations = [
|
||||||
|
"parent_return_reason",
|
||||||
|
"return_reason_children",
|
||||||
|
]
|
||||||
@@ -24,7 +24,7 @@ export default async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const returnReasonService = req.scope.resolve("returnReasonService")
|
const returnReasonService = req.scope.resolve("returnReasonService")
|
||||||
|
|
||||||
const query = {}
|
const query = { parent_return_reason_id: null }
|
||||||
const data = await returnReasonService.list(query, {
|
const data = await returnReasonService.list(query, {
|
||||||
select: defaultFields,
|
select: defaultFields,
|
||||||
relations: defaultRelations,
|
relations: defaultRelations,
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
const schema = Validator.object().keys({
|
const schema = Validator.object().keys({
|
||||||
label: Validator.string().optional(),
|
label: Validator.string().optional(),
|
||||||
|
parent_return_reason_id: Validator.string().optional(),
|
||||||
description: Validator.string()
|
description: Validator.string()
|
||||||
.optional()
|
.optional()
|
||||||
.allow(""),
|
.allow(""),
|
||||||
|
|||||||
@@ -23,10 +23,14 @@ export const defaultFields = [
|
|||||||
"id",
|
"id",
|
||||||
"value",
|
"value",
|
||||||
"label",
|
"label",
|
||||||
|
"parent_return_reason_id",
|
||||||
"description",
|
"description",
|
||||||
"created_at",
|
"created_at",
|
||||||
"updated_at",
|
"updated_at",
|
||||||
"deleted_at",
|
"deleted_at",
|
||||||
]
|
]
|
||||||
|
|
||||||
export const defaultRelations = []
|
export const defaultRelations = [
|
||||||
|
"parent_return_reason",
|
||||||
|
"return_reason_children",
|
||||||
|
]
|
||||||
@@ -24,7 +24,7 @@ export default async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const returnReasonService = req.scope.resolve("returnReasonService")
|
const returnReasonService = req.scope.resolve("returnReasonService")
|
||||||
|
|
||||||
const query = {}
|
const query = { parent_return_reason_id: null}
|
||||||
const data = await returnReasonService.list(query, {
|
const data = await returnReasonService.list(query, {
|
||||||
select: defaultFields,
|
select: defaultFields,
|
||||||
relations: defaultRelations,
|
relations: defaultRelations,
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class nestedReturnReasons1631800727788 implements MigrationInterface {
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "return_reason" ADD "parent_return_reason_id" character varying`
|
||||||
|
|
||||||
|
)
|
||||||
|
await queryRunner.query(`ALTER TABLE "return_reason" ADD CONSTRAINT "FK_2250c5d9e975987ab212f61a657" FOREIGN KEY ("parent_return_reason_id") REFERENCES "return_reason"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "return_reason" DROP COLUMN "parent_return_reason_id"`
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,6 +7,9 @@ import {
|
|||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
UpdateDateColumn,
|
UpdateDateColumn,
|
||||||
PrimaryColumn,
|
PrimaryColumn,
|
||||||
|
ManyToOne,
|
||||||
|
OneToMany,
|
||||||
|
JoinColumn
|
||||||
} from "typeorm"
|
} from "typeorm"
|
||||||
import { ulid } from "ulid"
|
import { ulid } from "ulid"
|
||||||
import { resolveDbType, DbAwareColumn } from "../utils/db-aware-column"
|
import { resolveDbType, DbAwareColumn } from "../utils/db-aware-column"
|
||||||
@@ -26,6 +29,21 @@ export class ReturnReason {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
description: string
|
description: string
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
parent_return_reason_id: string
|
||||||
|
|
||||||
|
@ManyToOne(() => ReturnReason, {cascade: ['soft-remove']}
|
||||||
|
)
|
||||||
|
@JoinColumn({ name: "parent_return_reason_id" })
|
||||||
|
parent_return_reason: ReturnReason
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
() => ReturnReason,
|
||||||
|
return_reason => return_reason.parent_return_reason,
|
||||||
|
{ cascade: ["insert", 'soft-remove'] }
|
||||||
|
)
|
||||||
|
return_reason_children: ReturnReason[]
|
||||||
|
|
||||||
@CreateDateColumn({ type: resolveDbType("timestamptz") })
|
@CreateDateColumn({ type: resolveDbType("timestamptz") })
|
||||||
created_at: Date
|
created_at: Date
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import _ from "lodash"
|
|
||||||
import { Validator, MedusaError } from "medusa-core-utils"
|
import { Validator, MedusaError } from "medusa-core-utils"
|
||||||
import { BaseService } from "medusa-interfaces"
|
import { BaseService } from "medusa-interfaces"
|
||||||
|
import { In } from "typeorm"
|
||||||
|
|
||||||
class ReturnReasonService extends BaseService {
|
class ReturnReasonService extends BaseService {
|
||||||
constructor({ manager, returnReasonRepository }) {
|
constructor({ manager, returnReasonRepository }) {
|
||||||
@@ -32,6 +32,17 @@ class ReturnReasonService extends BaseService {
|
|||||||
return this.atomicPhase_(async manager => {
|
return this.atomicPhase_(async manager => {
|
||||||
const rrRepo = manager.getCustomRepository(this.retReasonRepo_)
|
const rrRepo = manager.getCustomRepository(this.retReasonRepo_)
|
||||||
|
|
||||||
|
if (data.parent_return_reason_id && data.parent_return_reason_id !== "") {
|
||||||
|
const parentReason = await this.retrieve(data.parent_return_reason_id)
|
||||||
|
|
||||||
|
if (parentReason.parent_return_reason_id) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
"Doubly nested return reasons is not supported"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const created = rrRepo.create(data)
|
const created = rrRepo.create(data)
|
||||||
|
|
||||||
const result = await rrRepo.save(created)
|
const result = await rrRepo.save(created)
|
||||||
@@ -44,14 +55,20 @@ class ReturnReasonService extends BaseService {
|
|||||||
const rrRepo = manager.getCustomRepository(this.retReasonRepo_)
|
const rrRepo = manager.getCustomRepository(this.retReasonRepo_)
|
||||||
const reason = await this.retrieve(id)
|
const reason = await this.retrieve(id)
|
||||||
|
|
||||||
if ("description" in data) {
|
const { description, label, parent_return_reason_id } = data
|
||||||
|
|
||||||
|
if (description) {
|
||||||
reason.description = data.description
|
reason.description = data.description
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("label" in data) {
|
if (label) {
|
||||||
reason.label = data.label
|
reason.label = data.label
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parent_return_reason_id) {
|
||||||
|
reason.parent_return_reason_id = parent_return_reason_id
|
||||||
|
}
|
||||||
|
|
||||||
await rrRepo.save(reason)
|
await rrRepo.save(reason)
|
||||||
|
|
||||||
return reason
|
return reason
|
||||||
@@ -92,6 +109,25 @@ class ReturnReasonService extends BaseService {
|
|||||||
|
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async delete(returnReasonId) {
|
||||||
|
return this.atomicPhase_(async manager => {
|
||||||
|
const rrRepo = manager.getCustomRepository(this.retReasonRepo_)
|
||||||
|
|
||||||
|
// We include the relation 'return_reason_children' to enable cascading deletes of return reasons if a parent is removed
|
||||||
|
const reason = await this.retrieve(returnReasonId, {
|
||||||
|
relations: ["return_reason_children"],
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!reason) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
await rrRepo.softRemove(reason)
|
||||||
|
|
||||||
|
return Promise.resolve()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ReturnReasonService
|
export default ReturnReasonService
|
||||||
@@ -374,6 +374,18 @@ class ReturnService extends BaseService {
|
|||||||
refund_amount: Math.floor(toRefund),
|
refund_amount: Math.floor(toRefund),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const returnReasons = await this.returnReasonService_.list(
|
||||||
|
{ id: [...returnLines.map(rl => rl.reason_id)] },
|
||||||
|
{ relations: ["return_reason_children"] }
|
||||||
|
)
|
||||||
|
|
||||||
|
if (returnReasons.some(rr => rr.return_reason_children?.length > 0)) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
"Cannot apply return reason category"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const rItemRepo = manager.getCustomRepository(this.returnItemRepository_)
|
const rItemRepo = manager.getCustomRepository(this.returnItemRepository_)
|
||||||
returnObject.items = returnLines.map(i =>
|
returnObject.items = returnLines.map(i =>
|
||||||
rItemRepo.create({
|
rItemRepo.create({
|
||||||
|
|||||||
Reference in new issue
Block a user