feat(medusa): ordem items endpoint (#9646)
This commit is contained in:
1 parent
0a37675f0e
commit
2a98be6b65
16 files changed
+202
-19
No files matched your search
@@ -1,3 +1,4 @@
|
|||||||
|
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
||||||
import {
|
import {
|
||||||
ClaimReason,
|
ClaimReason,
|
||||||
ClaimType,
|
ClaimType,
|
||||||
@@ -5,7 +6,6 @@ import {
|
|||||||
Modules,
|
Modules,
|
||||||
RuleOperator,
|
RuleOperator,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
|
||||||
import {
|
import {
|
||||||
adminHeaders,
|
adminHeaders,
|
||||||
createAdminUser,
|
createAdminUser,
|
||||||
@@ -1372,6 +1372,33 @@ medusaIntegrationTestRunner({
|
|||||||
)
|
)
|
||||||
// additional items is one of the props that should be undefined
|
// additional items is one of the props that should be undefined
|
||||||
expect(res.data.claim.additional_items).toBeUndefined()
|
expect(res.data.claim.additional_items).toBeUndefined()
|
||||||
|
|
||||||
|
const resLineItems = await api.get(
|
||||||
|
`/admin/orders/${order.id}/line-items`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(resLineItems.data).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
order_items: [
|
||||||
|
expect.objectContaining({
|
||||||
|
order_id: order.id,
|
||||||
|
item_id: item.id,
|
||||||
|
version: 3,
|
||||||
|
item: expect.objectContaining({
|
||||||
|
title: "Custom Item 2",
|
||||||
|
unit_price: 25,
|
||||||
|
}),
|
||||||
|
history: {
|
||||||
|
version: {
|
||||||
|
from: 1,
|
||||||
|
to: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export const getOrderDetailWorkflow = createWorkflow(
|
|||||||
input: WorkflowData<{
|
input: WorkflowData<{
|
||||||
fields: string[]
|
fields: string[]
|
||||||
order_id: string
|
order_id: string
|
||||||
|
version?: number
|
||||||
}>
|
}>
|
||||||
): WorkflowResponse<OrderDetailDTO> => {
|
): WorkflowResponse<OrderDetailDTO> => {
|
||||||
const fields = transform(input, ({ fields }) => {
|
const fields = transform(input, ({ fields }) => {
|
||||||
@@ -38,7 +39,10 @@ export const getOrderDetailWorkflow = createWorkflow(
|
|||||||
const order: OrderDTO = useRemoteQueryStep({
|
const order: OrderDTO = useRemoteQueryStep({
|
||||||
entry_point: "orders",
|
entry_point: "orders",
|
||||||
fields,
|
fields,
|
||||||
variables: { id: input.order_id },
|
variables: {
|
||||||
|
id: input.order_id,
|
||||||
|
version: input.version,
|
||||||
|
},
|
||||||
list: false,
|
list: false,
|
||||||
throw_if_key_not_found: true,
|
throw_if_key_not_found: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export interface MedusaRequest<Body = unknown>
|
|||||||
*/
|
*/
|
||||||
remoteQueryConfig: {
|
remoteQueryConfig: {
|
||||||
fields: string[]
|
fields: string[]
|
||||||
pagination: { order?: Record<string, string>; skip?: number; take?: number }
|
pagination: { order?: Record<string, string>; skip: number; take?: number }
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* An object containing the fields that are filterable e.g `{ id: Any<String> }`
|
* An object containing the fields that are filterable e.g `{ id: Any<String> }`
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { MedusaContainer } from "@medusajs/types"
|
import { MedusaContainer } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
isString,
|
|
||||||
ContainerRegistrationKeys,
|
ContainerRegistrationKeys,
|
||||||
|
isString,
|
||||||
remoteQueryObjectFromString,
|
remoteQueryObjectFromString,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import { MedusaRequest } from "../types"
|
import { MedusaRequest } from "../types"
|
||||||
@@ -11,7 +11,7 @@ export const refetchEntities = async (
|
|||||||
idOrFilter: string | object,
|
idOrFilter: string | object,
|
||||||
scope: MedusaContainer,
|
scope: MedusaContainer,
|
||||||
fields: string[],
|
fields: string[],
|
||||||
pagination: MedusaRequest["remoteQueryConfig"]["pagination"] = {}
|
pagination?: MedusaRequest["remoteQueryConfig"]["pagination"]
|
||||||
) => {
|
) => {
|
||||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||||
const filters = isString(idOrFilter) ? { id: idOrFilter } : idOrFilter
|
const filters = isString(idOrFilter) ? { id: idOrFilter } : idOrFilter
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { z } from "zod"
|
|
||||||
import { omit } from "lodash"
|
|
||||||
import { NextFunction } from "express"
|
|
||||||
import { MedusaError, removeUndefinedProperties } from "@medusajs/utils"
|
|
||||||
import { BaseEntity, QueryConfig, RequestQueryFields } from "@medusajs/types"
|
import { BaseEntity, QueryConfig, RequestQueryFields } from "@medusajs/types"
|
||||||
|
import { MedusaError, removeUndefinedProperties } from "@medusajs/utils"
|
||||||
|
import { NextFunction } from "express"
|
||||||
|
import { omit } from "lodash"
|
||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
import { zodValidator } from "../../zod/zod-helpers"
|
import { zodValidator } from "../../zod/zod-helpers"
|
||||||
import { MedusaRequest, MedusaResponse } from "../types"
|
import { MedusaRequest, MedusaResponse } from "../types"
|
||||||
@@ -79,7 +79,7 @@ export function validateAndTransformQuery<TEntity extends BaseEntity>(
|
|||||||
|
|
||||||
req.validatedQuery = validated
|
req.validatedQuery = validated
|
||||||
req.filterableFields = getFilterableFields(req.validatedQuery)
|
req.filterableFields = getFilterableFields(req.validatedQuery)
|
||||||
req.remoteQueryConfig = cnf.remoteQueryConfig
|
req.remoteQueryConfig = cnf.remoteQueryConfig as any
|
||||||
req.listConfig = (cnf as any).listConfig
|
req.listConfig = (cnf as any).listConfig
|
||||||
req.retrieveConfig = (cnf as any).retrieveConfig
|
req.retrieveConfig = (cnf as any).retrieveConfig
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,19 @@ export interface AdminOrderChangeAction
|
|||||||
|
|
||||||
export interface AdminOrderFulfillment extends BaseOrderFulfillment {}
|
export interface AdminOrderFulfillment extends BaseOrderFulfillment {}
|
||||||
|
|
||||||
|
export interface AdminOrderItem {
|
||||||
|
order_id: string
|
||||||
|
item_id: string
|
||||||
|
version: number
|
||||||
|
history: {
|
||||||
|
version: {
|
||||||
|
from: number
|
||||||
|
to: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item: AdminOrderLineItem
|
||||||
|
}
|
||||||
|
|
||||||
export interface AdminOrderLineItem
|
export interface AdminOrderLineItem
|
||||||
extends Omit<BaseOrderLineItem, "variant" | "product"> {
|
extends Omit<BaseOrderLineItem, "variant" | "product"> {
|
||||||
variant?: AdminProductVariant
|
variant?: AdminProductVariant
|
||||||
|
|||||||
@@ -15,3 +15,10 @@ export interface AdminOrderFilters extends FindParams, BaseOrderFilters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AdminOrderChangesFilters extends BaseOrderChangesFilters {}
|
export interface AdminOrderChangesFilters extends BaseOrderChangesFilters {}
|
||||||
|
|
||||||
|
export interface AdminOrderItemsFilters extends FindParams {
|
||||||
|
id?: string[] | string
|
||||||
|
item_id?: string[] | string
|
||||||
|
order_id?: string[] | string
|
||||||
|
version?: number[] | number
|
||||||
|
}
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
import { PaginatedResponse } from "../../common"
|
import { PaginatedResponse } from "../../common"
|
||||||
import { AdminOrder, AdminOrderChange, AdminOrderPreview } from "./entities"
|
import {
|
||||||
|
AdminOrder,
|
||||||
|
AdminOrderChange,
|
||||||
|
AdminOrderItem,
|
||||||
|
AdminOrderPreview,
|
||||||
|
} from "./entities"
|
||||||
|
|
||||||
export interface AdminOrderResponse {
|
export interface AdminOrderResponse {
|
||||||
order: AdminOrder
|
order: AdminOrder
|
||||||
@@ -13,6 +18,10 @@ export type AdminOrderListResponse = PaginatedResponse<{
|
|||||||
orders: AdminOrder[]
|
orders: AdminOrder[]
|
||||||
}>
|
}>
|
||||||
|
|
||||||
|
export type AdminOrderLineItemsListResponse = {
|
||||||
|
order_items: AdminOrderItem[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface AdminOrderPreviewResponse {
|
export interface AdminOrderPreviewResponse {
|
||||||
order: AdminOrderPreview
|
order: AdminOrderPreview
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import {
|
||||||
|
AuthenticatedMedusaRequest,
|
||||||
|
MedusaResponse,
|
||||||
|
} from "@medusajs/framework/http"
|
||||||
|
import { HttpTypes } from "@medusajs/framework/types"
|
||||||
|
import {
|
||||||
|
ContainerRegistrationKeys,
|
||||||
|
deduplicate,
|
||||||
|
} from "@medusajs/framework/utils"
|
||||||
|
|
||||||
|
export const GET = async (
|
||||||
|
req: AuthenticatedMedusaRequest<HttpTypes.AdminOrderItemsFilters>,
|
||||||
|
res: MedusaResponse<HttpTypes.AdminOrderLineItemsListResponse>
|
||||||
|
) => {
|
||||||
|
const { id } = req.params
|
||||||
|
|
||||||
|
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
|
||||||
|
|
||||||
|
const result = await query.graph({
|
||||||
|
entity: "order_items",
|
||||||
|
filters: {
|
||||||
|
...req.filterableFields,
|
||||||
|
order_id: id,
|
||||||
|
},
|
||||||
|
fields: deduplicate(
|
||||||
|
req.remoteQueryConfig.fields.concat(["item_id", "version"])
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = result.data
|
||||||
|
const deduplicatedItems = {}
|
||||||
|
|
||||||
|
for (const item of data) {
|
||||||
|
const itemId = item.item_id
|
||||||
|
const version = item.version
|
||||||
|
|
||||||
|
if (!deduplicatedItems[itemId]) {
|
||||||
|
deduplicatedItems[itemId] = {
|
||||||
|
...item,
|
||||||
|
history: {
|
||||||
|
version: {
|
||||||
|
from: version,
|
||||||
|
to: version,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
deduplicatedItems[itemId].history.version.to = Math.max(
|
||||||
|
version,
|
||||||
|
deduplicatedItems[itemId].history.version.to
|
||||||
|
)
|
||||||
|
|
||||||
|
deduplicatedItems[itemId].history.version.from = Math.min(
|
||||||
|
version,
|
||||||
|
deduplicatedItems[itemId].history.version.from
|
||||||
|
)
|
||||||
|
|
||||||
|
if (version > deduplicatedItems[itemId].version) {
|
||||||
|
deduplicatedItems[itemId] = {
|
||||||
|
...item,
|
||||||
|
history: deduplicatedItems[itemId].history,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
order_items: Object.values(deduplicatedItems),
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
import { getOrderDetailWorkflow } from "@medusajs/core-flows"
|
import { getOrderDetailWorkflow } from "@medusajs/core-flows"
|
||||||
import {
|
|
||||||
ContainerRegistrationKeys,
|
|
||||||
remoteQueryObjectFromString,
|
|
||||||
} from "@medusajs/framework/utils"
|
|
||||||
import {
|
import {
|
||||||
AuthenticatedMedusaRequest,
|
AuthenticatedMedusaRequest,
|
||||||
MedusaResponse,
|
MedusaResponse,
|
||||||
} from "@medusajs/framework/http"
|
} from "@medusajs/framework/http"
|
||||||
import { HttpTypes } from "@medusajs/framework/types"
|
import { HttpTypes } from "@medusajs/framework/types"
|
||||||
|
import {
|
||||||
|
ContainerRegistrationKeys,
|
||||||
|
remoteQueryObjectFromString,
|
||||||
|
} from "@medusajs/framework/utils"
|
||||||
|
import { AdminGetOrdersOrderParamsType } from "../validators"
|
||||||
|
|
||||||
export const GET = async (
|
export const GET = async (
|
||||||
req: AuthenticatedMedusaRequest,
|
req: AuthenticatedMedusaRequest<AdminGetOrdersOrderParamsType>,
|
||||||
res: MedusaResponse<HttpTypes.AdminOrderResponse>
|
res: MedusaResponse<HttpTypes.AdminOrderResponse>
|
||||||
) => {
|
) => {
|
||||||
const workflow = getOrderDetailWorkflow(req.scope)
|
const workflow = getOrderDetailWorkflow(req.scope)
|
||||||
@@ -18,6 +19,7 @@ export const GET = async (
|
|||||||
input: {
|
input: {
|
||||||
fields: req.remoteQueryConfig.fields,
|
fields: req.remoteQueryConfig.fields,
|
||||||
order_id: req.params.id,
|
order_id: req.params.id,
|
||||||
|
version: req.validatedQuery.version as number,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { MiddlewareRoute } from "@medusajs/framework/http"
|
|
||||||
import {
|
import {
|
||||||
validateAndTransformBody,
|
validateAndTransformBody,
|
||||||
validateAndTransformQuery,
|
validateAndTransformQuery,
|
||||||
} from "@medusajs/framework"
|
} from "@medusajs/framework"
|
||||||
|
import { MiddlewareRoute } from "@medusajs/framework/http"
|
||||||
import * as QueryConfig from "./query-config"
|
import * as QueryConfig from "./query-config"
|
||||||
import {
|
import {
|
||||||
AdminCompleteOrder,
|
AdminCompleteOrder,
|
||||||
|
AdminGetOrdersOrderItemsParams,
|
||||||
AdminGetOrdersOrderParams,
|
AdminGetOrdersOrderParams,
|
||||||
AdminGetOrdersParams,
|
AdminGetOrdersParams,
|
||||||
AdminMarkOrderFulfillmentDelivered,
|
AdminMarkOrderFulfillmentDelivered,
|
||||||
@@ -36,6 +37,16 @@ export const adminOrderRoutesMiddlewares: MiddlewareRoute[] = [
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
method: ["GET"],
|
||||||
|
matcher: "/admin/orders/:id/line-items",
|
||||||
|
middlewares: [
|
||||||
|
validateAndTransformQuery(
|
||||||
|
AdminGetOrdersOrderItemsParams,
|
||||||
|
QueryConfig.listOrderItemsQueryConfig
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
method: ["GET"],
|
method: ["GET"],
|
||||||
matcher: "/admin/orders/:id/changes",
|
matcher: "/admin/orders/:id/changes",
|
||||||
|
|||||||
@@ -81,6 +81,14 @@ export const defaultAdminRetrieveOrderChangesFields = [
|
|||||||
"updated_at",
|
"updated_at",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export const defaultAdminOrderItemsFields = [
|
||||||
|
"id",
|
||||||
|
"order_id",
|
||||||
|
"item_id",
|
||||||
|
"version",
|
||||||
|
"*item",
|
||||||
|
]
|
||||||
|
|
||||||
export const retrieveTransformQueryConfig = {
|
export const retrieveTransformQueryConfig = {
|
||||||
defaults: defaultAdminRetrieveOrderFields,
|
defaults: defaultAdminRetrieveOrderFields,
|
||||||
isList: false,
|
isList: false,
|
||||||
@@ -96,3 +104,9 @@ export const retrieveOrderChangesTransformQueryConfig = {
|
|||||||
defaults: defaultAdminRetrieveOrderChangesFields,
|
defaults: defaultAdminRetrieveOrderChangesFields,
|
||||||
isList: false,
|
isList: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const listOrderItemsQueryConfig = {
|
||||||
|
defaults: defaultAdminOrderItemsFields,
|
||||||
|
defaultLimit: 100,
|
||||||
|
isList: true,
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ export const AdminGetOrdersOrderParams = createSelectParams().merge(
|
|||||||
z.object({
|
z.object({
|
||||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
status: z.union([z.string(), z.array(z.string())]).optional(),
|
status: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
|
version: z.number().optional(),
|
||||||
created_at: createOperatorMap().optional(),
|
created_at: createOperatorMap().optional(),
|
||||||
updated_at: createOperatorMap().optional(),
|
updated_at: createOperatorMap().optional(),
|
||||||
deleted_at: createOperatorMap().optional(),
|
deleted_at: createOperatorMap().optional(),
|
||||||
@@ -20,6 +21,18 @@ export type AdminGetOrdersOrderParamsType = z.infer<
|
|||||||
typeof AdminGetOrdersOrderParams
|
typeof AdminGetOrdersOrderParams
|
||||||
>
|
>
|
||||||
|
|
||||||
|
export const AdminGetOrdersOrderItemsParams = createSelectParams().merge(
|
||||||
|
z.object({
|
||||||
|
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
|
item_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
|
version: z.number().optional(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
export type AdminGetOrdersOrderItemsParamsType = z.infer<
|
||||||
|
typeof AdminGetOrdersOrderParams
|
||||||
|
>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters used to filter and configure the pagination of the retrieved order.
|
* Parameters used to filter and configure the pagination of the retrieved order.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ declare global {
|
|||||||
fields: string[]
|
fields: string[]
|
||||||
pagination: {
|
pagination: {
|
||||||
order?: Record<string, string>
|
order?: Record<string, string>
|
||||||
skip?: number
|
skip: number
|
||||||
take?: number
|
take?: number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { IOrderModuleService } from "@medusajs/framework/types"
|
import { IOrderModuleService } from "@medusajs/framework/types"
|
||||||
import { Module, Modules } from "@medusajs/framework/utils"
|
import { Module, Modules } from "@medusajs/framework/utils"
|
||||||
import { OrderModuleService } from "@services"
|
|
||||||
import { moduleIntegrationTestRunner } from "@medusajs/test-utils"
|
import { moduleIntegrationTestRunner } from "@medusajs/test-utils"
|
||||||
|
import { OrderModuleService } from "@services"
|
||||||
|
|
||||||
moduleIntegrationTestRunner<IOrderModuleService>({
|
moduleIntegrationTestRunner<IOrderModuleService>({
|
||||||
moduleName: Modules.ORDER,
|
moduleName: Modules.ORDER,
|
||||||
@@ -18,6 +18,7 @@ moduleIntegrationTestRunner<IOrderModuleService>({
|
|||||||
"orderChange",
|
"orderChange",
|
||||||
"orderClaim",
|
"orderClaim",
|
||||||
"orderExchange",
|
"orderExchange",
|
||||||
|
"orderItem",
|
||||||
"orderLineItem",
|
"orderLineItem",
|
||||||
"orderShippingMethod",
|
"orderShippingMethod",
|
||||||
"orderTransaction",
|
"orderTransaction",
|
||||||
@@ -89,6 +90,15 @@ moduleIntegrationTestRunner<IOrderModuleService>({
|
|||||||
field: "orderExchange",
|
field: "orderExchange",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
orderItem: {
|
||||||
|
id: {
|
||||||
|
linkable: "order_item_id",
|
||||||
|
entity: "OrderItem",
|
||||||
|
primaryKey: "id",
|
||||||
|
serviceName: "order",
|
||||||
|
field: "orderItem",
|
||||||
|
},
|
||||||
|
},
|
||||||
orderLineItem: {
|
orderLineItem: {
|
||||||
id: {
|
id: {
|
||||||
linkable: "order_line_item_id",
|
linkable: "order_line_item_id",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
OrderChange,
|
OrderChange,
|
||||||
OrderClaim,
|
OrderClaim,
|
||||||
OrderExchange,
|
OrderExchange,
|
||||||
|
OrderItem,
|
||||||
OrderLineItem,
|
OrderLineItem,
|
||||||
OrderShippingMethod,
|
OrderShippingMethod,
|
||||||
OrderTransaction,
|
OrderTransaction,
|
||||||
@@ -25,6 +26,7 @@ export const joinerConfig = defineJoinerConfig(Modules.ORDER, {
|
|||||||
OrderChange,
|
OrderChange,
|
||||||
OrderClaim,
|
OrderClaim,
|
||||||
OrderExchange,
|
OrderExchange,
|
||||||
|
OrderItem,
|
||||||
OrderLineItem,
|
OrderLineItem,
|
||||||
OrderShippingMethod,
|
OrderShippingMethod,
|
||||||
OrderTransaction,
|
OrderTransaction,
|
||||||
|
|||||||
Reference in new issue
Block a user