Feat: draft order api (#6797)

This commit is contained in:
Carlos R. L. Rodrigues authored and GitHub committed 2024-04-06 16:35:10 +02:00
1 parent 883a75c4f3
commit df0751f122
63 files changed
+2179 -1424

No files matched your search

@@ -0,0 +1,21 @@
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
import { defaultAdminOrderFields } from "../query-config"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const variables = { id: req.params.id }
const queryObject = remoteQueryObjectFromString({
entryPoint: "order",
variables,
fields: defaultAdminOrderFields,
})
const [draft_order] = await remoteQuery(queryObject)
res.status(200).json({ draft_order })
}
@@ -0,0 +1,48 @@
import { transformBody, transformQuery } from "../../../api/middlewares"
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
import { authenticate } from "../../../utils/authenticate-middleware"
import * as QueryConfig from "./query-config"
import {
AdminGetOrdersOrderParams,
AdminGetOrdersParams,
AdminPostDraftOrdersReq,
} from "./validators"
export const adminDraftOrderRoutesMiddlewares: MiddlewareRoute[] = [
{
method: ["ALL"],
matcher: "/admin/draft-orders*",
middlewares: [authenticate("admin", ["bearer", "session", "api-key"])],
},
{
method: ["GET"],
matcher: "/admin/draft-orders",
middlewares: [
transformQuery(
AdminGetOrdersParams,
QueryConfig.listTransformQueryConfig
),
],
},
{
method: ["GET"],
matcher: "/admin/draft-orders/:id",
middlewares: [
transformQuery(
AdminGetOrdersOrderParams,
QueryConfig.retrieveTransformQueryConfig
),
],
},
{
method: ["POST"],
matcher: "/admin/draft-orders",
middlewares: [
transformBody(AdminPostDraftOrdersReq),
transformQuery(
AdminGetOrdersOrderParams,
QueryConfig.retrieveTransformQueryConfig
),
],
},
]
@@ -0,0 +1,57 @@
export const defaultAdminOrderRelations = [
"items",
"items.tax_lines",
"items.adjustments",
"items.detail",
"shipping_address",
"billing_address",
"shipping_methods",
"shipping_methods.tax_lines",
"shipping_methods.adjustments",
]
export const allowedAdminOrderRelations = []
export const defaultAdminListOrderFields = [
"id",
"status",
"version",
"*items",
"summary",
"metadata",
"created_at",
"updated_at",
]
export const defaultAdminOrderFields = [
"id",
"status",
"version",
"*items",
"*items.tax_lines",
"*items.adjustments",
"*items.detail",
"*items.tax_lines",
"*items.adjustments",
"*shipping_address",
"*billing_address",
"*shipping_methods",
"*shipping_methods.tax_lines",
"*shipping_methods.adjustments",
"summary",
"metadata",
"created_at",
"updated_at",
]
export const retrieveTransformQueryConfig = {
defaultFields: defaultAdminOrderFields,
defaultRelations: defaultAdminOrderRelations,
allowedRelations: allowedAdminOrderRelations,
isList: false,
}
export const listTransformQueryConfig = {
defaultFields: defaultAdminListOrderFields,
defaultLimit: 20,
isList: true,
}
@@ -0,0 +1,88 @@
import { createOrdersWorkflow } from "@medusajs/core-flows"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import {
ContainerRegistrationKeys,
OrderStatus,
remoteQueryObjectFromString,
} from "@medusajs/utils"
import {
AuthenticatedMedusaRequest,
MedusaRequest,
MedusaResponse,
} from "../../../types/routing"
import { AdminPostDraftOrdersReq } from "./validators"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "order",
variables: {
filters: {
...req.filterableFields,
is_draft_order: true,
},
...req.remoteQueryConfig.pagination,
},
fields: req.remoteQueryConfig.fields,
})
const { rows: draft_orders, metadata } = await remoteQuery(queryObject)
res.json({
draft_orders,
count: metadata.count,
offset: metadata.skip,
limit: metadata.take,
})
}
export const POST = async (
req: AuthenticatedMedusaRequest<AdminPostDraftOrdersReq>,
res: MedusaResponse
) => {
const input = req.validatedBody
const workflowInput = {
...input,
no_notification: !!input.no_notification_order,
status: OrderStatus.DRAFT,
is_draft_order: true,
}
if (!input.currency_code) {
const regionService = req.scope.resolve(ModuleRegistrationName.REGION)
const region = await regionService.retrieve(input.region_id)
input.currency_code = region.currency_code
}
if (!input.email) {
const customerService = req.scope.resolve(ModuleRegistrationName.CUSTOMER)
const customer = await customerService.retrieve(input.customer_id)
input.email = customer.email
}
const { result, errors } = await createOrdersWorkflow(req.scope).run({
input: workflowInput,
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "order",
variables: {
filters: {
id: result.id,
},
},
fields: req.remoteQueryConfig.fields,
})
const draftOrder = await remoteQuery(queryObject)
res.status(200).json({ draft_order: draftOrder[0] })
}
@@ -0,0 +1,174 @@
import { BigNumberInput } from "@medusajs/types"
import { Type } from "class-transformer"
import {
IsArray,
IsBoolean,
IsEmail,
IsEnum,
IsNotEmpty,
IsNumber,
IsObject,
IsOptional,
IsString,
ValidateIf,
ValidateNested,
} from "class-validator"
import {
AddressPayload,
FindParams,
extendedFindParamsMixin,
} from "../../../types/common"
import { IsType } from "../../../utils/validators/is-type"
export class AdminGetOrdersOrderParams extends FindParams {}
/**
* Parameters used to filter and configure the pagination of the retrieved api keys.
*/
export class AdminGetOrdersParams extends extendedFindParamsMixin({
limit: 50,
offset: 0,
}) {
/**
* Search parameter for api keys.
*/
@IsString({ each: true })
@IsOptional()
id?: string | string[]
/**
* Filter by title
*/
@IsString({ each: true })
@IsOptional()
name?: string | string[]
// Additional filters from BaseFilterable
@IsOptional()
@ValidateNested({ each: true })
@Type(() => AdminGetOrdersParams)
$and?: AdminGetOrdersParams[]
@IsOptional()
@ValidateNested({ each: true })
@Type(() => AdminGetOrdersParams)
$or?: AdminGetOrdersParams[]
}
enum Status {
completed = "completed",
}
export class AdminPostDraftOrdersReq {
@IsEnum(Status)
@IsOptional()
status?: string
@IsEmail()
@ValidateIf((o) => !o.customer_id)
email: string
@IsString()
@IsOptional()
sales_channel_id?: string
@IsOptional()
@IsType([AddressPayload, String])
billing_address?: AddressPayload
@IsOptional()
@IsType([AddressPayload, String])
shipping_address?: AddressPayload
@IsArray()
@Type(() => Item)
@IsNotEmpty()
@ValidateNested({ each: true })
@IsOptional()
items?: Item[]
@IsString()
region_id: string
@IsArray()
@IsOptional()
promo_codes?: string[]
@IsString()
@IsOptional()
currency_code?: string
@IsString()
@IsOptional()
@ValidateIf((o) => !o.email)
customer_id?: string
@IsBoolean()
@IsOptional()
no_notification_order?: boolean
@IsArray()
@Type(() => ShippingMethod)
@IsNotEmpty()
@ValidateNested({ each: true })
shipping_methods: ShippingMethod[]
@IsObject()
@IsOptional()
metadata?: Record<string, unknown> = {}
}
class ShippingMethod {
@IsString()
@IsOptional()
shipping_method_id: string
@IsString()
@IsOptional()
order_id: string
@IsString()
name: string
@IsString()
option_id: string
@IsObject()
@IsOptional()
data?: Record<string, unknown> = {}
@IsNumber()
amount: BigNumberInput
}
class Item {
@IsString()
@ValidateIf((o) => !o.variant_id)
title: string
@IsString()
@IsOptional()
@ValidateIf((o) => !o.variant_id)
sku: string
@IsString()
@IsOptional()
@ValidateIf((o) => !o.variant_id)
barcode: string
@IsNumber()
@IsOptional()
unit_price: BigNumberInput
@IsString()
@IsOptional()
variant_id?: string
@IsNumber()
quantity: number
@IsObject()
@IsOptional()
metadata?: Record<string, unknown> = {}
}
export class AdminDeleteOrdersOrderReq {}
@@ -1,12 +1,12 @@
import { deleteUsersWorkflow, updateUsersWorkflow } from "@medusajs/core-flows"
import { IUserModuleService, UpdateUserDTO } from "@medusajs/types"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../types/routing"
import { IUserModuleService, UpdateUserDTO } from "@medusajs/types"
import { deleteUsersWorkflow, updateUsersWorkflow } from "@medusajs/core-flows"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { AdminUpdateUserRequest } from "../validators"
import { ModuleRegistrationName } from "../../../../../../modules-sdk/dist"
// Get user
export const GET = async (
@@ -5,6 +5,7 @@ import { adminCollectionRoutesMiddlewares } from "./admin/collections/middleware
import { adminCurrencyRoutesMiddlewares } from "./admin/currencies/middlewares"
import { adminCustomerGroupRoutesMiddlewares } from "./admin/customer-groups/middlewares"
import { adminCustomerRoutesMiddlewares } from "./admin/customers/middlewares"
import { adminDraftOrderRoutesMiddlewares } from "./admin/draft-orders/middlewares"
import { adminFulfillmentRoutesMiddlewares } from "./admin/fulfillment/middlewares"
import { adminInventoryRoutesMiddlewares } from "./admin/inventory-items/middlewares"
import { adminInviteRoutesMiddlewares } from "./admin/invites/middlewares"
@@ -59,6 +60,7 @@ export const config: MiddlewaresConfig = {
...adminCollectionRoutesMiddlewares,
...adminPricingRoutesMiddlewares,
...adminFulfillmentRoutesMiddlewares,
...adminDraftOrderRoutesMiddlewares,
...adminSalesChannelRoutesMiddlewares,
...adminStockLocationRoutesMiddlewares,
...adminProductTypeRoutesMiddlewares,