feat(medusa): Implement premises of order edit retrieval (#2183)
**What** - Implements the admin/store retrieval end point - Service implementation of the retrieve method - Service implementation of the computeLineItems method which aggregates the right line item based on the changes that are made - client - medusa-js api - medusa-react queries hooks **Tests** - Unit tests of the retrieval end points - Unit tests of the service retrieve method and computeLineItems - Integration tests for admin/store - client - medusa-js tests - medusa-react hooks tests FIXES CORE-492
This commit is contained in:
1 parent
3efeb6b84f
commit
f863d28b9a
36 files changed
+1317
-2
No files matched your search
@@ -0,0 +1,182 @@
|
|||||||
|
const path = require("path")
|
||||||
|
|
||||||
|
const startServerWithEnvironment =
|
||||||
|
require("../../../helpers/start-server-with-environment").default
|
||||||
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
|
const { useDb } = require("../../../helpers/use-db")
|
||||||
|
const adminSeeder = require("../../helpers/admin-seeder")
|
||||||
|
const {
|
||||||
|
simpleOrderEditFactory,
|
||||||
|
} = require("../../factories/simple-order-edit-factory")
|
||||||
|
const { IdMap } = require("medusa-test-utils")
|
||||||
|
const {
|
||||||
|
simpleOrderItemChangeFactory,
|
||||||
|
} = require("../../factories/simple-order-item-change-factory")
|
||||||
|
const {
|
||||||
|
simpleLineItemFactory,
|
||||||
|
simpleProductFactory,
|
||||||
|
simpleOrderFactory,
|
||||||
|
} = require("../../factories")
|
||||||
|
const { OrderEditItemChangeType } = require("@medusajs/medusa")
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
const adminHeaders = {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("[MEDUSA_FF_ORDER_EDITING] /admin/order-edits", () => {
|
||||||
|
let medusaProcess
|
||||||
|
let dbConnection
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
|
const [process, connection] = await startServerWithEnvironment({
|
||||||
|
cwd,
|
||||||
|
env: { MEDUSA_FF_ORDER_EDITING: true },
|
||||||
|
verbose: false,
|
||||||
|
})
|
||||||
|
dbConnection = connection
|
||||||
|
medusaProcess = process
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.shutdown()
|
||||||
|
|
||||||
|
medusaProcess.kill()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("GET /admin/order-edits/:id", () => {
|
||||||
|
const orderEditId = IdMap.getId("order-edit-1")
|
||||||
|
const prodId1 = IdMap.getId("prodId1")
|
||||||
|
const prodId2 = IdMap.getId("prodId2")
|
||||||
|
const prodId3 = IdMap.getId("prodId3")
|
||||||
|
const changeUpdateId = IdMap.getId("order-edit-1-change-update")
|
||||||
|
const changeCreateId = IdMap.getId("order-edit-1-change-create")
|
||||||
|
const changeRemoveId = IdMap.getId("order-edit-1-change-remove")
|
||||||
|
const lineItemId1 = IdMap.getId("line-item-1")
|
||||||
|
const lineItemId2 = IdMap.getId("line-item-2")
|
||||||
|
const lineItemCreateId = IdMap.getId("line-item-create")
|
||||||
|
const lineItemUpdateId = IdMap.getId("line-item-update")
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
|
||||||
|
const product1 = await simpleProductFactory(dbConnection, {
|
||||||
|
id: prodId1,
|
||||||
|
})
|
||||||
|
const product2 = await simpleProductFactory(dbConnection, {
|
||||||
|
id: prodId2,
|
||||||
|
})
|
||||||
|
const product3 = await simpleProductFactory(dbConnection, {
|
||||||
|
id: prodId3,
|
||||||
|
})
|
||||||
|
|
||||||
|
const order = await simpleOrderFactory(dbConnection, {
|
||||||
|
email: "test@testson.com",
|
||||||
|
tax_rate: null,
|
||||||
|
fulfillment_status: "fulfilled",
|
||||||
|
payment_status: "captured",
|
||||||
|
region: {
|
||||||
|
id: "test-region",
|
||||||
|
name: "Test region",
|
||||||
|
tax_rate: 12.5,
|
||||||
|
},
|
||||||
|
line_items: [
|
||||||
|
{
|
||||||
|
id: lineItemId1,
|
||||||
|
variant_id: product1.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
fulfilled_quantity: 1,
|
||||||
|
shipped_quantity: 1,
|
||||||
|
unit_price: 1000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: lineItemId2,
|
||||||
|
variant_id: product2.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
fulfilled_quantity: 1,
|
||||||
|
shipped_quantity: 1,
|
||||||
|
unit_price: 1000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const orderEdit = await simpleOrderEditFactory(dbConnection, {
|
||||||
|
id: orderEditId,
|
||||||
|
order_id: order.id,
|
||||||
|
created_by: "admin_user",
|
||||||
|
internal_note: "test internal note",
|
||||||
|
})
|
||||||
|
|
||||||
|
await simpleLineItemFactory(dbConnection, {
|
||||||
|
id: lineItemUpdateId,
|
||||||
|
order_id: orderEdit.order_id,
|
||||||
|
variant_id: product1.variants[0].id,
|
||||||
|
quantity: 2,
|
||||||
|
})
|
||||||
|
await simpleLineItemFactory(dbConnection, {
|
||||||
|
id: lineItemCreateId,
|
||||||
|
order_id: orderEdit.order_id,
|
||||||
|
variant_id: product3.variants[0].id,
|
||||||
|
quantity: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
await simpleOrderItemChangeFactory(dbConnection, {
|
||||||
|
id: changeCreateId,
|
||||||
|
type: OrderEditItemChangeType.ITEM_ADD,
|
||||||
|
line_item_id: lineItemCreateId,
|
||||||
|
order_edit_id: orderEdit.id,
|
||||||
|
})
|
||||||
|
await simpleOrderItemChangeFactory(dbConnection, {
|
||||||
|
id: changeUpdateId,
|
||||||
|
type: OrderEditItemChangeType.ITEM_UPDATE,
|
||||||
|
line_item_id: lineItemUpdateId,
|
||||||
|
original_line_item_id: lineItemId1,
|
||||||
|
order_edit_id: orderEdit.id,
|
||||||
|
})
|
||||||
|
await simpleOrderItemChangeFactory(dbConnection, {
|
||||||
|
id: changeRemoveId,
|
||||||
|
type: OrderEditItemChangeType.ITEM_REMOVE,
|
||||||
|
original_line_item_id: lineItemId2,
|
||||||
|
order_edit_id: orderEdit.id,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
return await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("gets order edit", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.get(
|
||||||
|
`/admin/order-edits/${orderEditId}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.order_edit).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: orderEditId,
|
||||||
|
created_by: "admin_user",
|
||||||
|
requested_by: null,
|
||||||
|
canceled_by: null,
|
||||||
|
confirmed_by: null,
|
||||||
|
internal_note: "test internal note",
|
||||||
|
items: expect.arrayContaining([
|
||||||
|
expect.objectContaining({ id: lineItemCreateId, quantity: 2 }),
|
||||||
|
expect.objectContaining({ id: lineItemId1, quantity: 2 }),
|
||||||
|
]),
|
||||||
|
removed_items: expect.arrayContaining([
|
||||||
|
expect.objectContaining({ id: lineItemId2, quantity: 1 }),
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
const path = require("path")
|
||||||
|
|
||||||
|
const startServerWithEnvironment =
|
||||||
|
require("../../../helpers/start-server-with-environment").default
|
||||||
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
|
const { useDb } = require("../../../helpers/use-db")
|
||||||
|
const adminSeeder = require("../../helpers/admin-seeder")
|
||||||
|
const {
|
||||||
|
simpleOrderEditFactory,
|
||||||
|
} = require("../../factories/simple-order-edit-factory")
|
||||||
|
const { IdMap } = require("medusa-test-utils")
|
||||||
|
const {
|
||||||
|
simpleOrderItemChangeFactory,
|
||||||
|
} = require("../../factories/simple-order-item-change-factory")
|
||||||
|
const {
|
||||||
|
simpleLineItemFactory,
|
||||||
|
simpleProductFactory,
|
||||||
|
simpleOrderFactory,
|
||||||
|
} = require("../../factories")
|
||||||
|
const { OrderEditItemChangeType } = require("@medusajs/medusa")
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
const adminHeaders = {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("[MEDUSA_FF_ORDER_EDITING] /store/order-edits", () => {
|
||||||
|
let medusaProcess
|
||||||
|
let dbConnection
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
|
const [process, connection] = await startServerWithEnvironment({
|
||||||
|
cwd,
|
||||||
|
env: { MEDUSA_FF_ORDER_EDITING: true },
|
||||||
|
verbose: false,
|
||||||
|
})
|
||||||
|
dbConnection = connection
|
||||||
|
medusaProcess = process
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.shutdown()
|
||||||
|
|
||||||
|
medusaProcess.kill()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("GET /store/order-edits/:id", () => {
|
||||||
|
const orderEditId = IdMap.getId("order-edit-1")
|
||||||
|
const prodId1 = IdMap.getId("prodId1")
|
||||||
|
const prodId2 = IdMap.getId("prodId2")
|
||||||
|
const prodId3 = IdMap.getId("prodId3")
|
||||||
|
const changeUpdateId = IdMap.getId("order-edit-1-change-update")
|
||||||
|
const changeCreateId = IdMap.getId("order-edit-1-change-create")
|
||||||
|
const changeRemoveId = IdMap.getId("order-edit-1-change-remove")
|
||||||
|
const lineItemId1 = IdMap.getId("line-item-1")
|
||||||
|
const lineItemId2 = IdMap.getId("line-item-2")
|
||||||
|
const lineItemCreateId = IdMap.getId("line-item-create")
|
||||||
|
const lineItemUpdateId = IdMap.getId("line-item-update")
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
|
||||||
|
const product1 = await simpleProductFactory(dbConnection, {
|
||||||
|
id: prodId1,
|
||||||
|
})
|
||||||
|
const product2 = await simpleProductFactory(dbConnection, {
|
||||||
|
id: prodId2,
|
||||||
|
})
|
||||||
|
const product3 = await simpleProductFactory(dbConnection, {
|
||||||
|
id: prodId3,
|
||||||
|
})
|
||||||
|
|
||||||
|
const order = await simpleOrderFactory(dbConnection, {
|
||||||
|
email: "test@testson.com",
|
||||||
|
tax_rate: null,
|
||||||
|
fulfillment_status: "fulfilled",
|
||||||
|
payment_status: "captured",
|
||||||
|
region: {
|
||||||
|
id: "test-region",
|
||||||
|
name: "Test region",
|
||||||
|
tax_rate: 12.5,
|
||||||
|
},
|
||||||
|
line_items: [
|
||||||
|
{
|
||||||
|
id: lineItemId1,
|
||||||
|
variant_id: product1.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
fulfilled_quantity: 1,
|
||||||
|
shipped_quantity: 1,
|
||||||
|
unit_price: 1000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: lineItemId2,
|
||||||
|
variant_id: product2.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
fulfilled_quantity: 1,
|
||||||
|
shipped_quantity: 1,
|
||||||
|
unit_price: 1000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const orderEdit = await simpleOrderEditFactory(dbConnection, {
|
||||||
|
id: orderEditId,
|
||||||
|
order_id: order.id,
|
||||||
|
created_by: "admin_user",
|
||||||
|
internal_note: "test internal note",
|
||||||
|
})
|
||||||
|
|
||||||
|
await simpleLineItemFactory(dbConnection, {
|
||||||
|
id: lineItemUpdateId,
|
||||||
|
order_id: orderEdit.order_id,
|
||||||
|
variant_id: product1.variants[0].id,
|
||||||
|
quantity: 2,
|
||||||
|
})
|
||||||
|
await simpleLineItemFactory(dbConnection, {
|
||||||
|
id: lineItemCreateId,
|
||||||
|
order_id: orderEdit.order_id,
|
||||||
|
variant_id: product3.variants[0].id,
|
||||||
|
quantity: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
await simpleOrderItemChangeFactory(dbConnection, {
|
||||||
|
id: changeCreateId,
|
||||||
|
type: OrderEditItemChangeType.ITEM_ADD,
|
||||||
|
line_item_id: lineItemCreateId,
|
||||||
|
order_edit_id: orderEdit.id,
|
||||||
|
})
|
||||||
|
await simpleOrderItemChangeFactory(dbConnection, {
|
||||||
|
id: changeUpdateId,
|
||||||
|
type: OrderEditItemChangeType.ITEM_UPDATE,
|
||||||
|
line_item_id: lineItemUpdateId,
|
||||||
|
original_line_item_id: lineItemId1,
|
||||||
|
order_edit_id: orderEdit.id,
|
||||||
|
})
|
||||||
|
await simpleOrderItemChangeFactory(dbConnection, {
|
||||||
|
id: changeRemoveId,
|
||||||
|
type: OrderEditItemChangeType.ITEM_REMOVE,
|
||||||
|
original_line_item_id: lineItemId2,
|
||||||
|
order_edit_id: orderEdit.id,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
return await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("gets order edit", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.get(`/store/order-edits/${orderEditId}`)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.order_edit).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: orderEditId,
|
||||||
|
requested_by: null,
|
||||||
|
items: expect.arrayContaining([
|
||||||
|
expect.objectContaining({ id: lineItemCreateId, quantity: 2 }),
|
||||||
|
expect.objectContaining({ id: lineItemId1, quantity: 2 }),
|
||||||
|
]),
|
||||||
|
removed_items: expect.arrayContaining([
|
||||||
|
expect.objectContaining({ id: lineItemId2, quantity: 1 }),
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.data.order_edit.internal_note).not.toBeDefined()
|
||||||
|
expect(response.data.order_edit.created_by).not.toBeDefined()
|
||||||
|
expect(response.data.order_edit.canceled_by).not.toBeDefined()
|
||||||
|
expect(response.data.order_edit.confirmed_by).not.toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { Connection } from "typeorm"
|
||||||
|
import { OrderFactoryData, simpleOrderFactory } from "./simple-order-factory"
|
||||||
|
import { OrderEdit } from "@medusajs/medusa"
|
||||||
|
|
||||||
|
export type OrderEditFactoryData = {
|
||||||
|
id?: string
|
||||||
|
order?: OrderFactoryData
|
||||||
|
order_id?: string
|
||||||
|
internal_note?: string
|
||||||
|
declined_reason?: string
|
||||||
|
confirmed_at?: Date | string
|
||||||
|
confirmed_by?: string
|
||||||
|
created_at?: Date | string
|
||||||
|
created_by?: string
|
||||||
|
requested_at?: Date | string
|
||||||
|
requested_by?: string
|
||||||
|
canceled_at?: Date | string
|
||||||
|
canceled_by?: string
|
||||||
|
declined_at?: Date | string
|
||||||
|
declined_by?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const simpleOrderEditFactory = async (
|
||||||
|
connection: Connection,
|
||||||
|
data: OrderEditFactoryData = {}
|
||||||
|
): Promise<OrderEdit> => {
|
||||||
|
const manager = connection.manager
|
||||||
|
|
||||||
|
if (!data.order_id) {
|
||||||
|
const order = await simpleOrderFactory(connection, data.order)
|
||||||
|
data.order_id = order.id
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderEdit = manager.create<OrderEdit>(OrderEdit, {
|
||||||
|
id: data.id,
|
||||||
|
order_id: data.order_id,
|
||||||
|
internal_note: data.internal_note,
|
||||||
|
declined_reason: data.declined_reason,
|
||||||
|
declined_at: data.declined_at,
|
||||||
|
declined_by: data.declined_by,
|
||||||
|
canceled_at: data.canceled_at,
|
||||||
|
canceled_by: data.canceled_by,
|
||||||
|
requested_at: data.requested_at,
|
||||||
|
requested_by: data.requested_by,
|
||||||
|
created_at: data.created_at,
|
||||||
|
created_by: data.created_by,
|
||||||
|
confirmed_at: data.confirmed_at,
|
||||||
|
confirmed_by: data.confirmed_by,
|
||||||
|
})
|
||||||
|
|
||||||
|
return await manager.save<OrderEdit>(orderEdit)
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import {
|
||||||
|
OrderEdit,
|
||||||
|
OrderEditItemChangeType,
|
||||||
|
OrderItemChange,
|
||||||
|
} from "@medusajs/medusa"
|
||||||
|
import { Connection } from "typeorm"
|
||||||
|
|
||||||
|
type OrderItemChangeData = {
|
||||||
|
id: string
|
||||||
|
type: OrderEditItemChangeType
|
||||||
|
order_edit_id: string
|
||||||
|
original_line_item_id?: string
|
||||||
|
line_item_id?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const simpleOrderItemChangeFactory = async (
|
||||||
|
connection: Connection,
|
||||||
|
data: OrderItemChangeData
|
||||||
|
) => {
|
||||||
|
const manager = connection.manager
|
||||||
|
const change = manager.create<OrderItemChange>(OrderItemChange, {
|
||||||
|
id: data.id,
|
||||||
|
type: data.type,
|
||||||
|
order_edit_id: data.order_edit_id,
|
||||||
|
line_item_id: data.line_item_id,
|
||||||
|
original_line_item_id: data.original_line_item_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
return await manager.save<OrderItemChange>(change)
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import CollectionsResource from "./resources/collections"
|
|||||||
import CustomersResource from "./resources/customers"
|
import CustomersResource from "./resources/customers"
|
||||||
import GiftCardsResource from "./resources/gift-cards"
|
import GiftCardsResource from "./resources/gift-cards"
|
||||||
import OrdersResource from "./resources/orders"
|
import OrdersResource from "./resources/orders"
|
||||||
|
import OrderEditsResource from "./resources/order-edits"
|
||||||
import PaymentMethodsResource from "./resources/payment-methods"
|
import PaymentMethodsResource from "./resources/payment-methods"
|
||||||
import ProductsResource from "./resources/products"
|
import ProductsResource from "./resources/products"
|
||||||
import RegionsResource from "./resources/regions"
|
import RegionsResource from "./resources/regions"
|
||||||
@@ -24,6 +25,7 @@ class Medusa {
|
|||||||
public customers: CustomersResource
|
public customers: CustomersResource
|
||||||
public errors: MedusaError
|
public errors: MedusaError
|
||||||
public orders: OrdersResource
|
public orders: OrdersResource
|
||||||
|
public orderEdits: OrderEditsResource
|
||||||
public products: ProductsResource
|
public products: ProductsResource
|
||||||
public regions: RegionsResource
|
public regions: RegionsResource
|
||||||
public returnReasons: ReturnReasonsResource
|
public returnReasons: ReturnReasonsResource
|
||||||
@@ -44,6 +46,7 @@ class Medusa {
|
|||||||
this.customers = new CustomersResource(this.client)
|
this.customers = new CustomersResource(this.client)
|
||||||
this.errors = new MedusaError()
|
this.errors = new MedusaError()
|
||||||
this.orders = new OrdersResource(this.client)
|
this.orders = new OrdersResource(this.client)
|
||||||
|
this.orderEdits = new OrderEditsResource(this.client)
|
||||||
this.products = new ProductsResource(this.client)
|
this.products = new ProductsResource(this.client)
|
||||||
this.regions = new RegionsResource(this.client)
|
this.regions = new RegionsResource(this.client)
|
||||||
this.returnReasons = new ReturnReasonsResource(this.client)
|
this.returnReasons = new ReturnReasonsResource(this.client)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import AdminInvitesResource from "./invites"
|
|||||||
import AdminNotesResource from "./notes"
|
import AdminNotesResource from "./notes"
|
||||||
import AdminNotificationsResource from "./notifications"
|
import AdminNotificationsResource from "./notifications"
|
||||||
import AdminOrdersResource from "./orders"
|
import AdminOrdersResource from "./orders"
|
||||||
|
import AdminOrderEditsResource from "./order-edits"
|
||||||
import AdminPriceListResource from "./price-lists"
|
import AdminPriceListResource from "./price-lists"
|
||||||
import AdminProductTagsResource from "./product-tags"
|
import AdminProductTagsResource from "./product-tags"
|
||||||
import AdminProductTypesResource from "./product-types"
|
import AdminProductTypesResource from "./product-types"
|
||||||
@@ -48,6 +49,7 @@ class Admin extends BaseResource {
|
|||||||
public users = new AdminUsersResource(this.client)
|
public users = new AdminUsersResource(this.client)
|
||||||
public returns = new AdminReturnsResource(this.client)
|
public returns = new AdminReturnsResource(this.client)
|
||||||
public orders = new AdminOrdersResource(this.client)
|
public orders = new AdminOrdersResource(this.client)
|
||||||
|
public orderEdits = new AdminOrderEditsResource(this.client)
|
||||||
public returnReasons = new AdminReturnReasonsResource(this.client)
|
public returnReasons = new AdminReturnReasonsResource(this.client)
|
||||||
public variants = new AdminVariantsResource(this.client)
|
public variants = new AdminVariantsResource(this.client)
|
||||||
public salesChannels = new AdminSalesChannelsResource(this.client)
|
public salesChannels = new AdminSalesChannelsResource(this.client)
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { AdminOrdersEditsRes } from "@medusajs/medusa"
|
||||||
|
import { ResponsePromise } from "../../typings"
|
||||||
|
import BaseResource from "../base"
|
||||||
|
|
||||||
|
class AdminOrderEditsResource extends BaseResource {
|
||||||
|
retrieve(
|
||||||
|
id: string,
|
||||||
|
customHeaders: Record<string, any> = {}
|
||||||
|
): ResponsePromise<AdminOrdersEditsRes> {
|
||||||
|
const path = `/admin/order-edits/${id}`
|
||||||
|
return this.client.request("GET", path, undefined, {}, customHeaders)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AdminOrderEditsResource
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { StoreOrderEditsRes } from "@medusajs/medusa"
|
||||||
|
import { ResponsePromise } from "../typings"
|
||||||
|
import BaseResource from "./base"
|
||||||
|
|
||||||
|
class OrderEditsResource extends BaseResource {
|
||||||
|
retrieve(
|
||||||
|
id: string,
|
||||||
|
customHeaders: Record<string, any> = {}
|
||||||
|
): ResponsePromise<StoreOrderEditsRes> {
|
||||||
|
const path = `/store/order-edits/${id}`
|
||||||
|
return this.client.request("GET", path, undefined, {}, customHeaders)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrderEditsResource
|
||||||
@@ -842,6 +842,34 @@
|
|||||||
"refunded_total": 0,
|
"refunded_total": 0,
|
||||||
"refundable_amount": 8200
|
"refundable_amount": 8200
|
||||||
},
|
},
|
||||||
|
"order_edit": {
|
||||||
|
"id": "oe_01F0YET7XPCMF8RZ0Y151NZV2V",
|
||||||
|
"order_id": "ord_01F0YET7XPCMF8RZ0Y151NZV2V",
|
||||||
|
"internal_note": "internal note",
|
||||||
|
"declined_reason": null,
|
||||||
|
"declined_at": null,
|
||||||
|
"declined_by": null,
|
||||||
|
"canceled_at": null,
|
||||||
|
"canceled_by": null,
|
||||||
|
"requested_at": null,
|
||||||
|
"requested_by": null,
|
||||||
|
"created_at": "2021-03-16T21:24:35.871Z",
|
||||||
|
"created_by_id": "admin_user",
|
||||||
|
"confirmed_at": null,
|
||||||
|
"confirmed_by": null
|
||||||
|
},
|
||||||
|
"store_order_edit": {
|
||||||
|
"id": "oe_01F0YET7XPCMF8RZ0Y151NZV2B",
|
||||||
|
"order_id": "ord_01F0YET7XPCMF8RZ0Y151NZV2V",
|
||||||
|
"declined_reason": null,
|
||||||
|
"declined_at": null,
|
||||||
|
"declined_by": null,
|
||||||
|
"canceled_at": null,
|
||||||
|
"requested_at": null,
|
||||||
|
"created_at": "2021-03-16T21:24:35.871Z",
|
||||||
|
"confirmed_at": null,
|
||||||
|
"confirmed_by": null
|
||||||
|
},
|
||||||
"return": {
|
"return": {
|
||||||
"id": "ret_01F0YET7XPCMF8RZ0Y151NZV2V",
|
"id": "ret_01F0YET7XPCMF8RZ0Y151NZV2V",
|
||||||
"status": "requested",
|
"status": "requested",
|
||||||
|
|||||||
@@ -1653,6 +1653,28 @@ export const adminHandlers = [
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
rest.get("/admin/order-edits/:id", (req, res, ctx) => {
|
||||||
|
const { id } = req.params
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
order_edit: fixtures.get("order_edit"),
|
||||||
|
id,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
|
||||||
|
rest.get("/store/order-edits/:id", (req, res, ctx) => {
|
||||||
|
const { id } = req.params
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
order_edit: fixtures.get("store_order_edit"),
|
||||||
|
id,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
|
||||||
rest.get("/admin/auth", (req, res, ctx) => {
|
rest.get("/admin/auth", (req, res, ctx) => {
|
||||||
return res(
|
return res(
|
||||||
ctx.status(200),
|
ctx.status(200),
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export * from "./invites"
|
|||||||
export * from "./notes"
|
export * from "./notes"
|
||||||
export * from "./notifications"
|
export * from "./notifications"
|
||||||
export * from "./orders"
|
export * from "./orders"
|
||||||
|
export * from "./order-edits"
|
||||||
export * from "./price-lists"
|
export * from "./price-lists"
|
||||||
export * from "./product-tags"
|
export * from "./product-tags"
|
||||||
export * from "./product-types"
|
export * from "./product-types"
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./queries"
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { AdminOrdersEditsRes } from "@medusajs/medusa"
|
||||||
|
import { queryKeysFactory } from "../../utils"
|
||||||
|
import { UseQueryOptionsWrapper } from "../../../types"
|
||||||
|
import { Response } from "@medusajs/medusa-js"
|
||||||
|
import { useMedusa } from "../../../contexts"
|
||||||
|
import { useQuery } from "react-query"
|
||||||
|
|
||||||
|
const ADMIN_ORDER_EDITS_QUERY_KEY = `admin_order_edits` as const
|
||||||
|
|
||||||
|
export const adminOrderEditsKeys = queryKeysFactory(ADMIN_ORDER_EDITS_QUERY_KEY)
|
||||||
|
type OrderEditQueryKeys = typeof adminOrderEditsKeys
|
||||||
|
|
||||||
|
export const useAdminOrderEdit = (
|
||||||
|
id: string,
|
||||||
|
options?: UseQueryOptionsWrapper<
|
||||||
|
Response<AdminOrdersEditsRes>,
|
||||||
|
Error,
|
||||||
|
ReturnType<OrderEditQueryKeys["detail"]>
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const { data, ...rest } = useQuery(
|
||||||
|
adminOrderEditsKeys.detail(id),
|
||||||
|
() => client.admin.orderEdits.retrieve(id),
|
||||||
|
options
|
||||||
|
)
|
||||||
|
return { ...data, ...rest } as const
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ export * from "./return-reasons/"
|
|||||||
export * from "./swaps/"
|
export * from "./swaps/"
|
||||||
export * from "./carts/"
|
export * from "./carts/"
|
||||||
export * from "./orders/"
|
export * from "./orders/"
|
||||||
|
export * from "./order-edits"
|
||||||
export * from "./customers/"
|
export * from "./customers/"
|
||||||
export * from "./returns/"
|
export * from "./returns/"
|
||||||
export * from "./gift-cards/"
|
export * from "./gift-cards/"
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./queries"
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { queryKeysFactory } from "../../utils"
|
||||||
|
import { StoreOrderEditsRes } from "@medusajs/medusa"
|
||||||
|
import { useQuery } from "react-query"
|
||||||
|
import { useMedusa } from "../../../contexts"
|
||||||
|
import { UseQueryOptionsWrapper } from "../../../types"
|
||||||
|
import { Response } from "@medusajs/medusa-js"
|
||||||
|
|
||||||
|
const ORDER_EDITS_QUERY_KEY = `orderEdit` as const
|
||||||
|
|
||||||
|
export const orderEditQueryKeys = queryKeysFactory<
|
||||||
|
typeof ORDER_EDITS_QUERY_KEY
|
||||||
|
>(ORDER_EDITS_QUERY_KEY)
|
||||||
|
|
||||||
|
type OrderQueryKey = typeof orderEditQueryKeys
|
||||||
|
|
||||||
|
export const useOrderEdit = (
|
||||||
|
id: string,
|
||||||
|
options?: UseQueryOptionsWrapper<
|
||||||
|
Response<StoreOrderEditsRes>,
|
||||||
|
Error,
|
||||||
|
ReturnType<OrderQueryKey["detail"]>
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const { data, ...rest } = useQuery(
|
||||||
|
orderEditQueryKeys.detail(id),
|
||||||
|
() => client.orderEdits.retrieve(id),
|
||||||
|
options
|
||||||
|
)
|
||||||
|
|
||||||
|
return { ...data, ...rest } as const
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { fixtures } from "../../../../mocks/data"
|
||||||
|
import { renderHook } from "@testing-library/react-hooks"
|
||||||
|
import { useAdminOrderEdit } from "../../../../src"
|
||||||
|
import { createWrapper } from "../../../utils"
|
||||||
|
|
||||||
|
describe("useAdminOrderEdit hook", () => {
|
||||||
|
test("returns an order edit", async () => {
|
||||||
|
const order_edit = fixtures.get("order_edit")
|
||||||
|
const { result, waitFor } = renderHook(
|
||||||
|
() => useAdminOrderEdit(order_edit.id),
|
||||||
|
{
|
||||||
|
wrapper: createWrapper(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await waitFor(() => result.current.isSuccess)
|
||||||
|
|
||||||
|
expect(result.current.response.status).toEqual(200)
|
||||||
|
expect(result.current.order_edit).toEqual(order_edit)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { renderHook } from "@testing-library/react-hooks"
|
||||||
|
import { fixtures } from "../../../../mocks/data"
|
||||||
|
import { createWrapper } from "../../../utils"
|
||||||
|
import { useOrderEdit } from "../../../../src/hooks/store/order-edits"
|
||||||
|
|
||||||
|
describe("useOrderEdit hook", () => {
|
||||||
|
test("returns an order", async () => {
|
||||||
|
const store_order_edit = fixtures.get("store_order_edit")
|
||||||
|
const { result, waitFor } = renderHook(
|
||||||
|
() => useOrderEdit(store_order_edit.id),
|
||||||
|
{
|
||||||
|
wrapper: createWrapper(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await waitFor(() => result.current.isSuccess)
|
||||||
|
|
||||||
|
expect(result.current.response.status).toEqual(200)
|
||||||
|
expect(result.current.order_edit).toEqual(store_order_edit)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -29,6 +29,7 @@ export * from "./routes/admin/invites"
|
|||||||
export * from "./routes/admin/notes"
|
export * from "./routes/admin/notes"
|
||||||
export * from "./routes/admin/notifications"
|
export * from "./routes/admin/notifications"
|
||||||
export * from "./routes/admin/orders"
|
export * from "./routes/admin/orders"
|
||||||
|
export * from "./routes/admin/order-edits"
|
||||||
export * from "./routes/admin/price-lists"
|
export * from "./routes/admin/price-lists"
|
||||||
export * from "./routes/admin/product-tags"
|
export * from "./routes/admin/product-tags"
|
||||||
export * from "./routes/admin/product-types"
|
export * from "./routes/admin/product-types"
|
||||||
@@ -52,6 +53,7 @@ export * from "./routes/store/collections"
|
|||||||
export * from "./routes/store/customers"
|
export * from "./routes/store/customers"
|
||||||
export * from "./routes/store/gift-cards"
|
export * from "./routes/store/gift-cards"
|
||||||
export * from "./routes/store/orders"
|
export * from "./routes/store/orders"
|
||||||
|
export * from "./routes/store/order-edits"
|
||||||
export * from "./routes/store/products"
|
export * from "./routes/store/products"
|
||||||
export * from "./routes/store/regions"
|
export * from "./routes/store/regions"
|
||||||
export * from "./routes/store/return-reasons"
|
export * from "./routes/store/return-reasons"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import inviteRoutes, { unauthenticatedInviteRoutes } from "./invites"
|
|||||||
import noteRoutes from "./notes"
|
import noteRoutes from "./notes"
|
||||||
import notificationRoutes from "./notifications"
|
import notificationRoutes from "./notifications"
|
||||||
import orderRoutes from "./orders"
|
import orderRoutes from "./orders"
|
||||||
|
import orderEditRoutes from "./order-edits"
|
||||||
import priceListRoutes from "./price-lists"
|
import priceListRoutes from "./price-lists"
|
||||||
import productTagRoutes from "./product-tags"
|
import productTagRoutes from "./product-tags"
|
||||||
import productTypesRoutes from "./product-types"
|
import productTypesRoutes from "./product-types"
|
||||||
@@ -79,6 +80,7 @@ export default (app, container, config) => {
|
|||||||
noteRoutes(route)
|
noteRoutes(route)
|
||||||
notificationRoutes(route)
|
notificationRoutes(route)
|
||||||
orderRoutes(route, featureFlagRouter)
|
orderRoutes(route, featureFlagRouter)
|
||||||
|
orderEditRoutes(route, featureFlagRouter)
|
||||||
priceListRoutes(route, featureFlagRouter)
|
priceListRoutes(route, featureFlagRouter)
|
||||||
productRoutes(route, featureFlagRouter)
|
productRoutes(route, featureFlagRouter)
|
||||||
productTagRoutes(route)
|
productTagRoutes(route)
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { IdMap } from "medusa-test-utils"
|
||||||
|
import { request } from "../../../../../helpers/test-request"
|
||||||
|
import { orderEditServiceMock } from "../../../../../services/__mocks__/order-edit"
|
||||||
|
import OrderEditingFeatureFlag from "../../../../../loaders/feature-flags/order-editing"
|
||||||
|
import {
|
||||||
|
defaultOrderEditFields,
|
||||||
|
defaultOrderEditRelations,
|
||||||
|
} from "../../../../../types/order-edit"
|
||||||
|
|
||||||
|
describe("GET /admin/order-edits/:id", () => {
|
||||||
|
describe("successfully gets an order edit", () => {
|
||||||
|
const orderEditId = IdMap.getId("testCreatedOrder")
|
||||||
|
let subject
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
subject = await request("GET", `/admin/order-edits/${orderEditId}`, {
|
||||||
|
adminSession: {
|
||||||
|
jwt: {
|
||||||
|
userId: IdMap.getId("admin_user"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: [OrderEditingFeatureFlag],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls orderService retrieve", () => {
|
||||||
|
expect(orderEditServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||||
|
expect(orderEditServiceMock.retrieve).toHaveBeenCalledWith(orderEditId, {
|
||||||
|
select: defaultOrderEditFields,
|
||||||
|
relations: defaultOrderEditRelations,
|
||||||
|
})
|
||||||
|
expect(orderEditServiceMock.computeLineItems).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns order", () => {
|
||||||
|
expect(subject.body.order_edit.id).toEqual(orderEditId)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { Request, Response } from "express"
|
||||||
|
import { OrderEditService } from "../../../../services"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @oas [get] /order-edits/{id}
|
||||||
|
* operationId: "GetOrderEditsOrderEdit"
|
||||||
|
* summary: "Retrieve an OrderEdit"
|
||||||
|
* description: "Retrieves a OrderEdit."
|
||||||
|
* x-authenticated: true
|
||||||
|
* parameters:
|
||||||
|
* - (path) id=* {string} The ID of the OrderEdit.
|
||||||
|
* x-codeSamples:
|
||||||
|
* - lang: JavaScript
|
||||||
|
* label: JS Client
|
||||||
|
* source: |
|
||||||
|
* import Medusa from "@medusajs/medusa-js"
|
||||||
|
* const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
|
||||||
|
* // must be previously logged in or use api token
|
||||||
|
* medusa.admin.orderEdit.retrieve(orderEditId)
|
||||||
|
* .then(({ order_edit }) => {
|
||||||
|
* console.log(order_edit.id);
|
||||||
|
* });
|
||||||
|
* - lang: Shell
|
||||||
|
* label: cURL
|
||||||
|
* source: |
|
||||||
|
* curl --location --request GET 'https://medusa-url.com/admin/order-edits/{id}' \
|
||||||
|
* --header 'Authorization: Bearer {api_token}'
|
||||||
|
* security:
|
||||||
|
* - api_token: []
|
||||||
|
* - cookie_auth: []
|
||||||
|
* tags:
|
||||||
|
* - OrderEdit
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: OK
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* order_edit:
|
||||||
|
* $ref: "#/components/schemas/order_edit"
|
||||||
|
* "400":
|
||||||
|
* $ref: "#/components/responses/400_error"
|
||||||
|
* "401":
|
||||||
|
* $ref: "#/components/responses/unauthorized"
|
||||||
|
* "404":
|
||||||
|
* $ref: "#/components/responses/not_found_error"
|
||||||
|
* "409":
|
||||||
|
* $ref: "#/components/responses/invalid_state_error"
|
||||||
|
* "422":
|
||||||
|
* $ref: "#/components/responses/invalid_request_error"
|
||||||
|
* "500":
|
||||||
|
* $ref: "#/components/responses/500_error"
|
||||||
|
*/
|
||||||
|
export default async (req: Request, res: Response) => {
|
||||||
|
const orderEditService: OrderEditService =
|
||||||
|
req.scope.resolve("orderEditService")
|
||||||
|
|
||||||
|
const { id } = req.params
|
||||||
|
const retrieveConfig = req.retrieveConfig
|
||||||
|
|
||||||
|
const orderEdit = await orderEditService.retrieve(id, retrieveConfig)
|
||||||
|
const { items, removedItems } = await orderEditService.computeLineItems(id)
|
||||||
|
orderEdit.items = items
|
||||||
|
orderEdit.removed_items = removedItems
|
||||||
|
|
||||||
|
return res.json({ order_edit: orderEdit })
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { Router } from "express"
|
||||||
|
import middlewares, { transformQuery } from "../../../middlewares"
|
||||||
|
import { EmptyQueryParams } from "../../../../types/common"
|
||||||
|
import { isFeatureFlagEnabled } from "../../../middlewares/feature-flag-enabled"
|
||||||
|
import OrderEditingFeatureFlag from "../../../../loaders/feature-flags/order-editing"
|
||||||
|
import {
|
||||||
|
defaultOrderEditFields,
|
||||||
|
defaultOrderEditRelations,
|
||||||
|
} from "../../../../types/order-edit"
|
||||||
|
import { OrderEdit } from "../../../../models"
|
||||||
|
|
||||||
|
const route = Router()
|
||||||
|
|
||||||
|
export default (app) => {
|
||||||
|
app.use(
|
||||||
|
"/order-edits",
|
||||||
|
isFeatureFlagEnabled(OrderEditingFeatureFlag.key),
|
||||||
|
route
|
||||||
|
)
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
"/:id",
|
||||||
|
transformQuery(EmptyQueryParams, {
|
||||||
|
defaultRelations: defaultOrderEditRelations,
|
||||||
|
defaultFields: defaultOrderEditFields,
|
||||||
|
isList: false,
|
||||||
|
}),
|
||||||
|
middlewares.wrap(require("./get-order-edit").default)
|
||||||
|
)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AdminOrdersEditsRes = {
|
||||||
|
order_edit: OrderEdit
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import collectionRoutes from "./collections"
|
|||||||
import customerRoutes from "./customers"
|
import customerRoutes from "./customers"
|
||||||
import giftCardRoutes from "./gift-cards"
|
import giftCardRoutes from "./gift-cards"
|
||||||
import orderRoutes from "./orders"
|
import orderRoutes from "./orders"
|
||||||
|
import orderEditRoutes from "./order-edits"
|
||||||
import productRoutes from "./products"
|
import productRoutes from "./products"
|
||||||
import regionRoutes from "./regions"
|
import regionRoutes from "./regions"
|
||||||
import returnReasonRoutes from "./return-reasons"
|
import returnReasonRoutes from "./return-reasons"
|
||||||
@@ -35,6 +36,7 @@ export default (app, container, config) => {
|
|||||||
customerRoutes(route, container)
|
customerRoutes(route, container)
|
||||||
productRoutes(route)
|
productRoutes(route)
|
||||||
orderRoutes(route)
|
orderRoutes(route)
|
||||||
|
orderEditRoutes(route)
|
||||||
cartRoutes(route, container)
|
cartRoutes(route, container)
|
||||||
shippingOptionRoutes(route)
|
shippingOptionRoutes(route)
|
||||||
regionRoutes(route)
|
regionRoutes(route)
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { IdMap } from "medusa-test-utils"
|
||||||
|
import { request } from "../../../../../helpers/test-request"
|
||||||
|
import { orderEditServiceMock } from "../../../../../services/__mocks__/order-edit"
|
||||||
|
import OrderEditingFeatureFlag from "../../../../../loaders/feature-flags/order-editing"
|
||||||
|
import {
|
||||||
|
defaultOrderEditFields,
|
||||||
|
defaultOrderEditRelations,
|
||||||
|
} from "../../../../../types/order-edit"
|
||||||
|
import { storeOrderEditNotAllowedFields } from "../index"
|
||||||
|
|
||||||
|
describe("GET /store/order-edits/:id", () => {
|
||||||
|
describe("successfully gets an order edit", () => {
|
||||||
|
const orderEditId = IdMap.getId("testCreatedOrder")
|
||||||
|
let subject
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
subject = await request("GET", `/store/order-edits/${orderEditId}`, {
|
||||||
|
flags: [OrderEditingFeatureFlag],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls orderService retrieve", () => {
|
||||||
|
expect(orderEditServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||||
|
expect(orderEditServiceMock.retrieve).toHaveBeenCalledWith(orderEditId, {
|
||||||
|
select: defaultOrderEditFields.filter(
|
||||||
|
(field) => !storeOrderEditNotAllowedFields.includes(field)
|
||||||
|
),
|
||||||
|
relations: defaultOrderEditRelations.filter(
|
||||||
|
(field) => !storeOrderEditNotAllowedFields.includes(field)
|
||||||
|
),
|
||||||
|
})
|
||||||
|
expect(orderEditServiceMock.computeLineItems).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns order", () => {
|
||||||
|
expect(subject.body.order_edit.id).toEqual(orderEditId)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { Request, Response } from "express"
|
||||||
|
import { OrderEditService } from "../../../../services"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @oas [get] /order-edits/{id}
|
||||||
|
* operationId: "GetOrderEditsOrderEdit"
|
||||||
|
* summary: "Retrieve an OrderEdit"
|
||||||
|
* description: "Retrieves a OrderEdit."
|
||||||
|
* parameters:
|
||||||
|
* - (path) id=* {string} The ID of the OrderEdit.
|
||||||
|
* x-codeSamples:
|
||||||
|
* - lang: JavaScript
|
||||||
|
* label: JS Client
|
||||||
|
* source: |
|
||||||
|
* import Medusa from "@medusajs/medusa-js"
|
||||||
|
* const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
|
||||||
|
* medusa.orderEdit.retrieve(orderEditId)
|
||||||
|
* .then(({ order_edit }) => {
|
||||||
|
* console.log(order_edit.id);
|
||||||
|
* });
|
||||||
|
* - lang: Shell
|
||||||
|
* label: cURL
|
||||||
|
* source: |
|
||||||
|
* curl --location --request GET 'https://medusa-url.com/store/order-edits/{id}'
|
||||||
|
* tags:
|
||||||
|
* - OrderEdit
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: OK
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* order_edit:
|
||||||
|
* $ref: "#/components/schemas/order_edit"
|
||||||
|
* "400":
|
||||||
|
* $ref: "#/components/responses/400_error"
|
||||||
|
* "401":
|
||||||
|
* $ref: "#/components/responses/unauthorized"
|
||||||
|
* "404":
|
||||||
|
* $ref: "#/components/responses/not_found_error"
|
||||||
|
* "409":
|
||||||
|
* $ref: "#/components/responses/invalid_state_error"
|
||||||
|
* "422":
|
||||||
|
* $ref: "#/components/responses/invalid_request_error"
|
||||||
|
* "500":
|
||||||
|
* $ref: "#/components/responses/500_error"
|
||||||
|
*/
|
||||||
|
export default async (req: Request, res: Response) => {
|
||||||
|
const orderEditService: OrderEditService =
|
||||||
|
req.scope.resolve("orderEditService")
|
||||||
|
|
||||||
|
const { id } = req.params
|
||||||
|
const retrieveConfig = req.retrieveConfig
|
||||||
|
|
||||||
|
const orderEdit = await orderEditService.retrieve(id, retrieveConfig)
|
||||||
|
const { items, removedItems } = await orderEditService.computeLineItems(id)
|
||||||
|
orderEdit.items = items
|
||||||
|
orderEdit.removed_items = removedItems
|
||||||
|
|
||||||
|
return res.json({ order_edit: orderEdit })
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { Router } from "express"
|
||||||
|
import middlewares, { transformQuery } from "../../../middlewares"
|
||||||
|
import { EmptyQueryParams } from "../../../../types/common"
|
||||||
|
import { isFeatureFlagEnabled } from "../../../middlewares/feature-flag-enabled"
|
||||||
|
import OrderEditingFeatureFlag from "../../../../loaders/feature-flags/order-editing"
|
||||||
|
import {
|
||||||
|
defaultOrderEditFields,
|
||||||
|
defaultOrderEditRelations,
|
||||||
|
} from "../../../../types/order-edit"
|
||||||
|
import { OrderEdit } from "../../../../models"
|
||||||
|
|
||||||
|
const route = Router()
|
||||||
|
|
||||||
|
export default (app) => {
|
||||||
|
app.use(
|
||||||
|
"/order-edits",
|
||||||
|
isFeatureFlagEnabled(OrderEditingFeatureFlag.key),
|
||||||
|
route
|
||||||
|
)
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
"/:id",
|
||||||
|
transformQuery(EmptyQueryParams, {
|
||||||
|
defaultRelations: defaultOrderEditRelations.filter(
|
||||||
|
(field) => !storeOrderEditNotAllowedFields.includes(field)
|
||||||
|
),
|
||||||
|
defaultFields: defaultOrderEditFields.filter(
|
||||||
|
(field) => !storeOrderEditNotAllowedFields.includes(field)
|
||||||
|
),
|
||||||
|
allowedFields: defaultOrderEditFields,
|
||||||
|
isList: false,
|
||||||
|
}),
|
||||||
|
middlewares.wrap(require("./get-order-edit").default)
|
||||||
|
)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
export type StoreOrderEditsRes = {
|
||||||
|
order_edit: Omit<
|
||||||
|
OrderEdit,
|
||||||
|
"internal_note" | "created_by" | "confirmed_by" | "canceled_by"
|
||||||
|
>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const storeOrderEditNotAllowedFields = [
|
||||||
|
"internal_note",
|
||||||
|
"created_by",
|
||||||
|
"confirmed_by",
|
||||||
|
"canceled_by",
|
||||||
|
]
|
||||||
@@ -35,6 +35,8 @@ export * from "./note"
|
|||||||
export * from "./notification"
|
export * from "./notification"
|
||||||
export * from "./oauth"
|
export * from "./oauth"
|
||||||
export * from "./order"
|
export * from "./order"
|
||||||
|
export * from "./order-edit"
|
||||||
|
export * from "./order-item-change"
|
||||||
export * from "./payment"
|
export * from "./payment"
|
||||||
export * from "./payment-provider"
|
export * from "./payment-provider"
|
||||||
export * from "./payment-session"
|
export * from "./payment-session"
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ export class OrderEdit extends SoftDeletableEntity {
|
|||||||
difference_due: number
|
difference_due: number
|
||||||
|
|
||||||
items: LineItem[]
|
items: LineItem[]
|
||||||
|
removed_items: LineItem[]
|
||||||
|
|
||||||
@BeforeInsert()
|
@BeforeInsert()
|
||||||
private beforeInsert(): void {
|
private beforeInsert(): void {
|
||||||
@@ -154,4 +155,9 @@ export class OrderEdit extends SoftDeletableEntity {
|
|||||||
* description: Computed line items from the changes.
|
* description: Computed line items from the changes.
|
||||||
* items:
|
* items:
|
||||||
* $ref: "#/components/schemas/line_item"
|
* $ref: "#/components/schemas/line_item"
|
||||||
|
* removed_items:
|
||||||
|
* type: array
|
||||||
|
* description: Computed line items from the changes that have been marked as deleted.
|
||||||
|
* removed_items:
|
||||||
|
* $ref: "#/components/schemas/line_item"
|
||||||
*/
|
*/
|
||||||
@@ -1,6 +1,68 @@
|
|||||||
import { EntityRepository, Repository } from "typeorm"
|
import { EntityRepository, FindManyOptions, Repository } from "typeorm"
|
||||||
|
|
||||||
import { OrderEdit } from "../models/order-edit"
|
import { OrderEdit } from "../models/order-edit"
|
||||||
|
import { flatten, groupBy, merge } from "lodash"
|
||||||
|
|
||||||
@EntityRepository(OrderEdit)
|
@EntityRepository(OrderEdit)
|
||||||
export class OrderEditRepository extends Repository<OrderEdit> {}
|
export class OrderEditRepository extends Repository<OrderEdit> {
|
||||||
|
public async findWithRelations(
|
||||||
|
relations: (keyof OrderEdit | string)[] = [],
|
||||||
|
idsOrOptionsWithoutRelations:
|
||||||
|
| Omit<FindManyOptions<OrderEdit>, "relations">
|
||||||
|
| string[] = {}
|
||||||
|
): Promise<[OrderEdit[], number]> {
|
||||||
|
let entities: OrderEdit[] = []
|
||||||
|
let count
|
||||||
|
if (Array.isArray(idsOrOptionsWithoutRelations)) {
|
||||||
|
entities = await this.findByIds(idsOrOptionsWithoutRelations)
|
||||||
|
count = idsOrOptionsWithoutRelations.length
|
||||||
|
} else {
|
||||||
|
const [results, resultCount] = await this.findAndCount(
|
||||||
|
idsOrOptionsWithoutRelations
|
||||||
|
)
|
||||||
|
entities = results
|
||||||
|
count = resultCount
|
||||||
|
}
|
||||||
|
const entitiesIds = entities.map(({ id }) => id)
|
||||||
|
|
||||||
|
const groupedRelations = {}
|
||||||
|
for (const rel of relations) {
|
||||||
|
const [topLevel] = rel.split(".")
|
||||||
|
if (groupedRelations[topLevel]) {
|
||||||
|
groupedRelations[topLevel].push(rel)
|
||||||
|
} else {
|
||||||
|
groupedRelations[topLevel] = [rel]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const entitiesIdsWithRelations = await Promise.all(
|
||||||
|
Object.entries(groupedRelations).map(async ([_, rels]) => {
|
||||||
|
return this.findByIds(entitiesIds, {
|
||||||
|
select: ["id"],
|
||||||
|
relations: rels as string[],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
).then(flatten)
|
||||||
|
const entitiesAndRelations = entitiesIdsWithRelations.concat(entities)
|
||||||
|
|
||||||
|
const entitiesAndRelationsById = groupBy(entitiesAndRelations, "id")
|
||||||
|
return [
|
||||||
|
Object.values(entitiesAndRelationsById).map((v) => merge({}, ...v)),
|
||||||
|
count,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
public async findOneWithRelations(
|
||||||
|
relations: Array<keyof OrderEdit> = [],
|
||||||
|
optionsWithoutRelations: Omit<FindManyOptions<OrderEdit>, "relations"> = {}
|
||||||
|
): Promise<OrderEdit> {
|
||||||
|
// Limit 1
|
||||||
|
optionsWithoutRelations.take = 1
|
||||||
|
|
||||||
|
const [result] = await this.findWithRelations(
|
||||||
|
relations,
|
||||||
|
optionsWithoutRelations
|
||||||
|
)
|
||||||
|
return result[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { IdMap } from "medusa-test-utils"
|
||||||
|
|
||||||
|
export const orderEdits = {
|
||||||
|
testCreatedOrder: {
|
||||||
|
id: IdMap.getId("testCreatedOrder"),
|
||||||
|
order_id: "empty-id",
|
||||||
|
internal_note: "internal note",
|
||||||
|
declined_reason: null,
|
||||||
|
declined_at: null,
|
||||||
|
declined_by: null,
|
||||||
|
canceled_at: null,
|
||||||
|
canceled_by: null,
|
||||||
|
requested_at: null,
|
||||||
|
requested_by: null,
|
||||||
|
created_at: new Date(),
|
||||||
|
created_by: "admin_user",
|
||||||
|
confirmed_at: null,
|
||||||
|
confirmed_by: null,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const orderEditServiceMock = {
|
||||||
|
withTransaction: function () {
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
retrieve: jest.fn().mockImplementation((orderId) => {
|
||||||
|
if (orderId === IdMap.getId("testCreatedOrder")) {
|
||||||
|
return Promise.resolve(orderEdits.testCreatedOrder)
|
||||||
|
}
|
||||||
|
return Promise.resolve(undefined)
|
||||||
|
}),
|
||||||
|
computeLineItems: jest.fn().mockImplementation((orderEdit) => {
|
||||||
|
return Promise.resolve(orderEdit)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
const mock = jest.fn().mockImplementation(() => {
|
||||||
|
return orderEditServiceMock
|
||||||
|
})
|
||||||
|
|
||||||
|
export default mock
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
import { IdMap, MockManager, MockRepository } from "medusa-test-utils"
|
||||||
|
import { OrderEditService, OrderService } from "../index"
|
||||||
|
import { OrderEditItemChangeType } from "../../models"
|
||||||
|
import { OrderServiceMock } from "../__mocks__/order"
|
||||||
|
|
||||||
|
const orderEditWithChanges = {
|
||||||
|
id: IdMap.getId("order-edit-with-changes"),
|
||||||
|
order: {
|
||||||
|
id: IdMap.getId("order-edit-with-changes-order"),
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: IdMap.getId("line-item-1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: IdMap.getId("line-item-2"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
type: OrderEditItemChangeType.ITEM_REMOVE,
|
||||||
|
id: "order-edit-with-changes-removed-change",
|
||||||
|
original_line_item_id: IdMap.getId("line-item-1"),
|
||||||
|
original_line_item: {
|
||||||
|
id: IdMap.getId("line-item-1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: OrderEditItemChangeType.ITEM_ADD,
|
||||||
|
id: IdMap.getId("order-edit-with-changes-added-change"),
|
||||||
|
line_item_id: IdMap.getId("line-item-3"),
|
||||||
|
line_item: {
|
||||||
|
id: IdMap.getId("line-item-3"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: OrderEditItemChangeType.ITEM_UPDATE,
|
||||||
|
id: IdMap.getId("order-edit-with-changes-updated-change"),
|
||||||
|
original_line_item_id: IdMap.getId("line-item-2"),
|
||||||
|
original_line_item: {
|
||||||
|
id: IdMap.getId("line-item-2"),
|
||||||
|
},
|
||||||
|
line_item_id: IdMap.getId("line-item-4"),
|
||||||
|
line_item: {
|
||||||
|
id: IdMap.getId("line-item-4"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("OrderEditService", () => {
|
||||||
|
const orderEditRepository = MockRepository({
|
||||||
|
findOneWithRelations: (relations, query) => {
|
||||||
|
if (query?.where?.id === IdMap.getId("order-edit-with-changes")) {
|
||||||
|
return orderEditWithChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const orderEditService = new OrderEditService({
|
||||||
|
manager: MockManager,
|
||||||
|
orderEditRepository,
|
||||||
|
orderService: OrderServiceMock as unknown as OrderService,
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should retrieve an order edit and call the repository with the right arguments", async () => {
|
||||||
|
await orderEditService.retrieve(IdMap.getId("order-edit-with-changes"))
|
||||||
|
expect(orderEditRepository.findOneWithRelations).toHaveBeenCalledTimes(1)
|
||||||
|
expect(orderEditRepository.findOneWithRelations).toHaveBeenCalledWith(
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
where: { id: IdMap.getId("order-edit-with-changes") },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should compute the items from the changes and attach them to the orderEdit", async () => {
|
||||||
|
const orderEdit = await orderEditService.retrieve(
|
||||||
|
IdMap.getId("order-edit-with-changes")
|
||||||
|
)
|
||||||
|
const { items, removedItems } = await orderEditService.computeLineItems(
|
||||||
|
orderEdit.id
|
||||||
|
)
|
||||||
|
expect(items.length).toBe(2)
|
||||||
|
expect(items).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: IdMap.getId("line-item-2"),
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: IdMap.getId("line-item-3"),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(removedItems.length).toBe(1)
|
||||||
|
expect(removedItems).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: IdMap.getId("line-item-1"),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -21,6 +21,7 @@ export { default as NoteService } from "./note"
|
|||||||
export { default as NotificationService } from "./notification"
|
export { default as NotificationService } from "./notification"
|
||||||
export { default as OauthService } from "./oauth"
|
export { default as OauthService } from "./oauth"
|
||||||
export { default as OrderService } from "./order"
|
export { default as OrderService } from "./order"
|
||||||
|
export { default as OrderEditService } from "./order-edit"
|
||||||
export { default as PaymentProviderService } from "./payment-provider"
|
export { default as PaymentProviderService } from "./payment-provider"
|
||||||
export { default as PricingService } from "./pricing"
|
export { default as PricingService } from "./pricing"
|
||||||
export { default as ProductCollectionService } from "./product-collection"
|
export { default as ProductCollectionService } from "./product-collection"
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
import { EntityManager } from "typeorm"
|
||||||
|
import { FindConfig } from "../types/common"
|
||||||
|
import { buildQuery } from "../utils"
|
||||||
|
import { MedusaError } from "medusa-core-utils"
|
||||||
|
import { OrderEditRepository } from "../repositories/order-edit"
|
||||||
|
import {
|
||||||
|
LineItem,
|
||||||
|
OrderEdit,
|
||||||
|
OrderEditItemChangeType,
|
||||||
|
OrderItemChange,
|
||||||
|
} from "../models"
|
||||||
|
import { TransactionBaseService } from "../interfaces"
|
||||||
|
import { OrderService } from "./index"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
manager: EntityManager
|
||||||
|
orderEditRepository: typeof OrderEditRepository
|
||||||
|
orderService: OrderService
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class OrderEditService extends TransactionBaseService {
|
||||||
|
protected transactionManager_: EntityManager | undefined
|
||||||
|
protected readonly manager_: EntityManager
|
||||||
|
protected readonly orderEditRepository_: typeof OrderEditRepository
|
||||||
|
protected readonly orderService_: OrderService
|
||||||
|
|
||||||
|
constructor({
|
||||||
|
manager,
|
||||||
|
orderEditRepository,
|
||||||
|
orderService,
|
||||||
|
}: InjectedDependencies) {
|
||||||
|
// eslint-disable-next-line prefer-rest-params
|
||||||
|
super(arguments[0])
|
||||||
|
|
||||||
|
this.manager_ = manager
|
||||||
|
this.orderEditRepository_ = orderEditRepository
|
||||||
|
this.orderService_ = orderService
|
||||||
|
}
|
||||||
|
|
||||||
|
async retrieve(
|
||||||
|
orderEditId: string,
|
||||||
|
config: FindConfig<OrderEdit> = {}
|
||||||
|
): Promise<OrderEdit | never> {
|
||||||
|
const orderEditRepository = this.manager_.getCustomRepository(
|
||||||
|
this.orderEditRepository_
|
||||||
|
)
|
||||||
|
const { relations, ...query } = buildQuery({ id: orderEditId }, config)
|
||||||
|
|
||||||
|
const orderEdit = await orderEditRepository.findOneWithRelations(
|
||||||
|
relations as (keyof OrderEdit)[],
|
||||||
|
query
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!orderEdit) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_FOUND,
|
||||||
|
`Order edit with id ${orderEditId} was not found`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return orderEdit
|
||||||
|
}
|
||||||
|
|
||||||
|
async computeLineItems(
|
||||||
|
orderEditId: string
|
||||||
|
): Promise<{ items: LineItem[]; removedItems: LineItem[] }> {
|
||||||
|
const orderEdit = await this.retrieve(orderEditId, {
|
||||||
|
select: ["id", "order_id", "changes", "order"],
|
||||||
|
relations: [
|
||||||
|
"changes",
|
||||||
|
"changes.line_item",
|
||||||
|
"changes.original_line_item",
|
||||||
|
"order",
|
||||||
|
"order.items",
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const originalItems = orderEdit.order.items
|
||||||
|
const removedItems: LineItem[] = []
|
||||||
|
const items: LineItem[] = []
|
||||||
|
|
||||||
|
const updatedItems = orderEdit.changes
|
||||||
|
.map((itemChange) => {
|
||||||
|
if (itemChange.type === OrderEditItemChangeType.ITEM_ADD) {
|
||||||
|
items.push(itemChange.line_item as LineItem)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemChange.type === OrderEditItemChangeType.ITEM_REMOVE) {
|
||||||
|
removedItems.push({
|
||||||
|
...itemChange.original_line_item,
|
||||||
|
id: itemChange.original_line_item_id,
|
||||||
|
} as LineItem)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return [itemChange.original_line_item_id as string, itemChange]
|
||||||
|
})
|
||||||
|
.filter((change) => !!change) as [string, OrderItemChange][]
|
||||||
|
|
||||||
|
const orderEditUpdatedChangesMap: Map<string, OrderItemChange> = new Map(
|
||||||
|
updatedItems
|
||||||
|
)
|
||||||
|
|
||||||
|
originalItems.map((item) => {
|
||||||
|
const itemChange = orderEditUpdatedChangesMap.get(item.id)
|
||||||
|
if (itemChange) {
|
||||||
|
items.push({
|
||||||
|
...itemChange.line_item,
|
||||||
|
id: itemChange.original_line_item_id,
|
||||||
|
} as LineItem)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return { items, removedItems }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { OrderEdit } from "../models"
|
||||||
|
|
||||||
|
export const defaultOrderEditRelations: string[] = [
|
||||||
|
"changes",
|
||||||
|
"changes.line_item",
|
||||||
|
"changes.original_line_item",
|
||||||
|
]
|
||||||
|
|
||||||
|
export const defaultOrderEditFields: (keyof OrderEdit)[] = [
|
||||||
|
"id",
|
||||||
|
"changes",
|
||||||
|
"order_id",
|
||||||
|
"created_by",
|
||||||
|
"requested_by",
|
||||||
|
"requested_at",
|
||||||
|
"confirmed_by",
|
||||||
|
"confirmed_at",
|
||||||
|
"declined_by",
|
||||||
|
"declined_reason",
|
||||||
|
"declined_at",
|
||||||
|
"canceled_by",
|
||||||
|
"canceled_at",
|
||||||
|
"internal_note",
|
||||||
|
]
|
||||||
@@ -145,6 +145,17 @@ export function prepareRetrieveQuery<
|
|||||||
expandFields = fields.split(",") as (keyof TEntity)[]
|
expandFields = fields.split(",") as (keyof TEntity)[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (queryConfig?.allowedFields?.length) {
|
||||||
|
expandFields?.forEach((field) => {
|
||||||
|
if (!queryConfig?.allowedFields?.includes(field as string)) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`Field ${field.toString()} is not valid`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return getRetrieveConfig<TEntity>(
|
return getRetrieveConfig<TEntity>(
|
||||||
queryConfig?.defaultFields as (keyof TEntity)[],
|
queryConfig?.defaultFields as (keyof TEntity)[],
|
||||||
(queryConfig?.defaultRelations ?? []) as string[],
|
(queryConfig?.defaultRelations ?? []) as string[],
|
||||||
|
|||||||
Reference in new issue
Block a user