feat: Typescript for API layer (#817)
Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com> Co-authored-by: Zakaria El Asri <33696020+zakariaelas@users.noreply.github.com> Co-authored-by: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Co-authored-by: Philip Korsholm <philip.korsholm@hotmail.com> Co-authored-by: Sebastian Rindom <seb@medusa-commerce.com>
This commit is contained in:
co-authored by
Philip Korsholm
Zakaria El Asri
Kasper Fabricius Kristensen
Philip Korsholm
Sebastian Rindom
parent
55e200bf68
commit
373532ecbc
+131
-47
@@ -1,19 +1,40 @@
|
||||
import { Type } from "class-transformer"
|
||||
import {
|
||||
MedusaError,
|
||||
Validator,
|
||||
transformIdableFields,
|
||||
} from "medusa-core-utils"
|
||||
import { defaultFields, defaultRelations } from "."
|
||||
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsEmail,
|
||||
IsEnum,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsObject,
|
||||
IsOptional,
|
||||
IsString,
|
||||
ValidateNested,
|
||||
} from "class-validator"
|
||||
import { transformIdableFields } from "medusa-core-utils"
|
||||
import {
|
||||
defaultAdminDraftOrdersFields,
|
||||
defaultAdminDraftOrdersRelations,
|
||||
} from "."
|
||||
import { DraftOrder } from "../../../.."
|
||||
import { DraftOrderService } from "../../../../services"
|
||||
import { AddressPayload } from "../../../../types/common"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
/**
|
||||
* @oas [post] /draft-orders
|
||||
* operationId: "PostDraftOrders"
|
||||
* summary: "Create a Draft Order"
|
||||
* description: "Creates a Draft Order"
|
||||
* x-authenticated: true
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* required:
|
||||
* - email
|
||||
* - items
|
||||
* - region_id
|
||||
* - shipping_methods
|
||||
* properties:
|
||||
* status:
|
||||
* description: "The status of the draft order"
|
||||
@@ -97,52 +118,115 @@ import { defaultFields, defaultRelations } from "."
|
||||
*/
|
||||
|
||||
export default async (req, res) => {
|
||||
const schema = Validator.object().keys({
|
||||
status: Validator.string().valid("open", "completed").optional(),
|
||||
email: Validator.string().email().required(),
|
||||
billing_address: Validator.address().optional(),
|
||||
shipping_address: Validator.address().optional(),
|
||||
items: Validator.array()
|
||||
.items({
|
||||
variant_id: Validator.string().optional().allow(""),
|
||||
unit_price: Validator.number().optional(),
|
||||
title: Validator.string().optional().allow(""),
|
||||
quantity: Validator.number().required(),
|
||||
metadata: Validator.object().default({}),
|
||||
})
|
||||
.required(),
|
||||
region_id: Validator.string().required(),
|
||||
discounts: Validator.array()
|
||||
.items({
|
||||
code: Validator.string().required(),
|
||||
})
|
||||
.optional(),
|
||||
customer_id: Validator.string().optional(),
|
||||
no_notification_order: Validator.boolean().optional(),
|
||||
shipping_methods: Validator.array()
|
||||
.items({
|
||||
option_id: Validator.string().required(),
|
||||
data: Validator.object().optional(),
|
||||
price: Validator.number().integer().integer().allow(0).optional(),
|
||||
})
|
||||
.required(),
|
||||
metadata: Validator.object().optional(),
|
||||
})
|
||||
const validated = await validator(AdminPostDraftOrdersReq, req.body)
|
||||
|
||||
let { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
const value = transformIdableFields(validated, [
|
||||
"shipping_address",
|
||||
"billing_address",
|
||||
])
|
||||
|
||||
value = transformIdableFields(value, ["shipping_address", "billing_address"])
|
||||
|
||||
const draftOrderService = req.scope.resolve("draftOrderService")
|
||||
let draftOrder = await draftOrderService.create(value)
|
||||
const draftOrderService: DraftOrderService =
|
||||
req.scope.resolve("draftOrderService")
|
||||
let draftOrder: DraftOrder = await draftOrderService.create(value)
|
||||
|
||||
draftOrder = await draftOrderService.retrieve(draftOrder.id, {
|
||||
relations: defaultRelations,
|
||||
select: defaultFields,
|
||||
relations: defaultAdminDraftOrdersRelations,
|
||||
select: defaultAdminDraftOrdersFields,
|
||||
})
|
||||
|
||||
res.status(200).json({ draft_order: draftOrder })
|
||||
}
|
||||
|
||||
enum Status {
|
||||
open = "open",
|
||||
completed = "completed",
|
||||
}
|
||||
|
||||
export class AdminPostDraftOrdersReq {
|
||||
@IsEnum(Status)
|
||||
@IsOptional()
|
||||
status?: string
|
||||
|
||||
@IsEmail()
|
||||
email: string
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => AddressPayload)
|
||||
billing_address?: AddressPayload
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => AddressPayload)
|
||||
shipping_address?: AddressPayload
|
||||
|
||||
@IsArray()
|
||||
@Type(() => Item)
|
||||
@IsNotEmpty()
|
||||
@ValidateNested({ each: true })
|
||||
items: Item[]
|
||||
|
||||
@IsString()
|
||||
region_id: string
|
||||
|
||||
@IsArray()
|
||||
@IsOptional()
|
||||
@Type(() => Discount)
|
||||
@ValidateNested({ each: true })
|
||||
discounts?: Discount[]
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
customer_id?: string
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
no_notification_order?: boolean
|
||||
|
||||
@IsArray()
|
||||
@Type(() => ShippingMethod)
|
||||
@IsNotEmpty()
|
||||
@ValidateNested({ each: true })
|
||||
shipping_methods: ShippingMethod[]
|
||||
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
metadata?: object = {}
|
||||
}
|
||||
|
||||
class ShippingMethod {
|
||||
@IsString()
|
||||
option_id: string
|
||||
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
data?: object = {}
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
price?: number
|
||||
}
|
||||
|
||||
class Discount {
|
||||
@IsString()
|
||||
code: string
|
||||
}
|
||||
|
||||
class Item {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
title?: string
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
unit_price?: number
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
variant_id?: string
|
||||
|
||||
@IsNumber()
|
||||
quantity: number
|
||||
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
metadata?: object = {}
|
||||
}
|
||||
+60
-29
@@ -1,14 +1,28 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
import { defaultCartFields, defaultCartRelations, defaultFields } from "."
|
||||
|
||||
import { IsInt, IsObject, IsOptional, IsString } from "class-validator"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { EntityManager } from "typeorm"
|
||||
import {
|
||||
defaultAdminDraftOrdersCartFields,
|
||||
defaultAdminDraftOrdersCartRelations,
|
||||
defaultAdminDraftOrdersFields,
|
||||
} from "."
|
||||
import {
|
||||
CartService,
|
||||
DraftOrderService,
|
||||
LineItemService,
|
||||
} from "../../../../services"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
/**
|
||||
* @oas [post] /draft-orders/{id}/line-items
|
||||
* operationId: "PostDraftOrdersDraftOrderLineItems"
|
||||
* summary: "Create a Line Item for Draft Order"
|
||||
* description: "Creates a Line Item for the Draft Order"
|
||||
* x-authenticated: true
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
* required:
|
||||
* - quantity
|
||||
* schema:
|
||||
* properties:
|
||||
* variant_id:
|
||||
@@ -42,28 +56,24 @@ import { defaultCartFields, defaultCartRelations, defaultFields } from "."
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
title: Validator.string().optional(),
|
||||
unit_price: Validator.number().optional(),
|
||||
variant_id: Validator.string().optional(),
|
||||
quantity: Validator.number().required(),
|
||||
metadata: Validator.object().optional(),
|
||||
})
|
||||
const validated = await validator(
|
||||
AdminPostDraftOrdersDraftOrderLineItemsReq,
|
||||
req.body
|
||||
)
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
const draftOrderService = req.scope.resolve("draftOrderService")
|
||||
const cartService = req.scope.resolve("cartService")
|
||||
const lineItemService = req.scope.resolve("lineItemService")
|
||||
const entityManager = req.scope.resolve("manager")
|
||||
const draftOrderService: DraftOrderService =
|
||||
req.scope.resolve("draftOrderService")
|
||||
const cartService: CartService = req.scope.resolve("cartService")
|
||||
const lineItemService: LineItemService = req.scope.resolve("lineItemService")
|
||||
const entityManager: EntityManager = req.scope.resolve("manager")
|
||||
|
||||
await entityManager.transaction(async (manager) => {
|
||||
const draftOrder = await draftOrderService
|
||||
.withTransaction(manager)
|
||||
.retrieve(id, { select: defaultFields, relations: ["cart"] })
|
||||
.retrieve(id, {
|
||||
select: defaultAdminDraftOrdersFields,
|
||||
relations: ["cart"],
|
||||
})
|
||||
|
||||
if (draftOrder.status === "completed") {
|
||||
throw new MedusaError(
|
||||
@@ -72,12 +82,12 @@ export default async (req, res) => {
|
||||
)
|
||||
}
|
||||
|
||||
if (value.variant_id) {
|
||||
if (validated.variant_id) {
|
||||
const line = await lineItemService.generate(
|
||||
value.variant_id,
|
||||
validated.variant_id,
|
||||
draftOrder.cart.region_id,
|
||||
value.quantity,
|
||||
{ metadata: value.metadata, unit_price: value.unit_price }
|
||||
validated.quantity,
|
||||
{ metadata: validated.metadata, unit_price: validated.unit_price }
|
||||
)
|
||||
|
||||
await cartService
|
||||
@@ -88,20 +98,41 @@ export default async (req, res) => {
|
||||
await lineItemService.withTransaction(manager).create({
|
||||
cart_id: draftOrder.cart_id,
|
||||
has_shipping: true,
|
||||
title: value.title || "Custom item",
|
||||
title: validated.title,
|
||||
allow_discounts: false,
|
||||
unit_price: value.unit_price || 0,
|
||||
quantity: value.quantity,
|
||||
unit_price: validated.unit_price || 0,
|
||||
quantity: validated.quantity,
|
||||
})
|
||||
}
|
||||
|
||||
draftOrder.cart = await cartService
|
||||
.withTransaction(manager)
|
||||
.retrieve(draftOrder.cart_id, {
|
||||
relations: defaultCartRelations,
|
||||
select: defaultCartFields,
|
||||
relations: defaultAdminDraftOrdersCartRelations,
|
||||
select: defaultAdminDraftOrdersCartFields,
|
||||
})
|
||||
|
||||
res.status(200).json({ draft_order: draftOrder })
|
||||
})
|
||||
}
|
||||
|
||||
export class AdminPostDraftOrdersDraftOrderLineItemsReq {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
title?: string = "Custom item"
|
||||
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
unit_price?: number
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
variant_id?: string
|
||||
|
||||
@IsInt()
|
||||
quantity: number
|
||||
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
metadata?: object = {}
|
||||
}
|
||||
+4
-2
@@ -1,8 +1,10 @@
|
||||
import { DraftOrderService } from "../../../../services"
|
||||
/**
|
||||
* @oas [delete] /draft-orders/{id}
|
||||
* operationId: DeleteDraftOrdersDraftOrder
|
||||
* summary: Delete a Draft Order
|
||||
* description: "Deletes a Draft Order"
|
||||
* x-authenticated: true
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Draft Order.
|
||||
* tags:
|
||||
@@ -23,11 +25,11 @@
|
||||
* deleted:
|
||||
* type: boolean
|
||||
*/
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const draftOrderService = req.scope.resolve("draftOrderService")
|
||||
const draftOrderService: DraftOrderService =
|
||||
req.scope.resolve("draftOrderService")
|
||||
await draftOrderService.delete(id)
|
||||
|
||||
res.json({
|
||||
+17
-9
@@ -1,11 +1,18 @@
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { defaultCartFields, defaultCartRelations, defaultFields } from "."
|
||||
|
||||
import { EntityManager } from "typeorm"
|
||||
import {
|
||||
defaultAdminDraftOrdersCartFields,
|
||||
defaultAdminDraftOrdersCartRelations,
|
||||
defaultAdminDraftOrdersFields,
|
||||
} from "."
|
||||
import { DraftOrder } from "../../../.."
|
||||
import { CartService, DraftOrderService } from "../../../../services"
|
||||
/**
|
||||
* @oas [delete] /draft-orders/{id}/line-items/{line_id}
|
||||
* operationId: DeleteDraftOrdersDraftOrderLineItemsItem
|
||||
* summary: Delete a Line Item
|
||||
* description: "Removes a Line Item from a Draft Order."
|
||||
* x-authenticated: true
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Draft Order.
|
||||
* - (path) line_id=* {string} The id of the Draft Order.
|
||||
@@ -25,14 +32,15 @@ import { defaultCartFields, defaultCartRelations, defaultFields } from "."
|
||||
export default async (req, res) => {
|
||||
const { id, line_id } = req.params
|
||||
|
||||
const draftOrderService = req.scope.resolve("draftOrderService")
|
||||
const cartService = req.scope.resolve("cartService")
|
||||
const entityManager = req.scope.resolve("manager")
|
||||
const draftOrderService: DraftOrderService =
|
||||
req.scope.resolve("draftOrderService")
|
||||
const cartService: CartService = req.scope.resolve("cartService")
|
||||
const entityManager: EntityManager = req.scope.resolve("manager")
|
||||
|
||||
await entityManager.transaction(async (manager) => {
|
||||
const draftOrder = await draftOrderService
|
||||
const draftOrder: DraftOrder = await draftOrderService
|
||||
.withTransaction(manager)
|
||||
.retrieve(id, { select: defaultFields })
|
||||
.retrieve(id, { select: defaultAdminDraftOrdersFields })
|
||||
|
||||
if (draftOrder.status === "completed") {
|
||||
throw new MedusaError(
|
||||
@@ -48,8 +56,8 @@ export default async (req, res) => {
|
||||
draftOrder.cart = await cartService
|
||||
.withTransaction(manager)
|
||||
.retrieve(draftOrder.cart_id, {
|
||||
relations: defaultCartRelations,
|
||||
select: defaultCartFields,
|
||||
relations: defaultAdminDraftOrdersCartRelations,
|
||||
select: defaultAdminDraftOrdersCartFields,
|
||||
})
|
||||
|
||||
res.status(200).json({ draft_order: draftOrder })
|
||||
@@ -1,45 +0,0 @@
|
||||
import {
|
||||
defaultRelations,
|
||||
defaultFields,
|
||||
defaultCartRelations,
|
||||
defaultCartFields,
|
||||
} from "."
|
||||
|
||||
/**
|
||||
* @oas [get] /draft-orders/{id}
|
||||
* operationId: "GetDraftOrdersDraftOrder"
|
||||
* summary: "Retrieve a Draft Order"
|
||||
* description: "Retrieves a Draft Order."
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Draft Order.
|
||||
* tags:
|
||||
* - Draft Order
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* draft_order:
|
||||
* $ref: "#/components/schemas/draft-order"
|
||||
*/
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const draftOrderService = req.scope.resolve("draftOrderService")
|
||||
const cartService = req.scope.resolve("cartService")
|
||||
|
||||
const draftOrder = await draftOrderService.retrieve(id, {
|
||||
select: defaultFields,
|
||||
relations: defaultRelations,
|
||||
})
|
||||
|
||||
draftOrder.cart = await cartService.retrieve(draftOrder.cart_id, {
|
||||
relations: defaultCartRelations,
|
||||
select: defaultCartFields,
|
||||
})
|
||||
|
||||
res.json({ draft_order: draftOrder })
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
defaultAdminDraftOrdersRelations,
|
||||
defaultAdminDraftOrdersFields,
|
||||
defaultAdminDraftOrdersCartRelations,
|
||||
defaultAdminDraftOrdersCartFields,
|
||||
} from "."
|
||||
import { DraftOrder } from "../../../.."
|
||||
import { CartService, DraftOrderService } from "../../../../services"
|
||||
|
||||
/**
|
||||
* @oas [get] /draft-orders/{id}
|
||||
* operationId: "GetDraftOrdersDraftOrder"
|
||||
* summary: "Retrieve a Draft Order"
|
||||
* description: "Retrieves a Draft Order."
|
||||
* x-authenticated: true
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Draft Order.
|
||||
* tags:
|
||||
* - Draft Order
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* draft_order:
|
||||
* $ref: "#/components/schemas/draft-order"
|
||||
*/
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const draftOrderService: DraftOrderService =
|
||||
req.scope.resolve("draftOrderService")
|
||||
const cartService: CartService = req.scope.resolve("cartService")
|
||||
|
||||
const draftOrder: DraftOrder = await draftOrderService.retrieve(id, {
|
||||
select: defaultAdminDraftOrdersFields,
|
||||
relations: defaultAdminDraftOrdersRelations,
|
||||
})
|
||||
|
||||
draftOrder.cart = await cartService.retrieve(draftOrder.cart_id, {
|
||||
relations: defaultAdminDraftOrdersCartRelations,
|
||||
select: defaultAdminDraftOrdersCartFields,
|
||||
})
|
||||
|
||||
res.json({ draft_order: draftOrder })
|
||||
}
|
||||
+32
-6
@@ -1,5 +1,7 @@
|
||||
import { Router } from "express"
|
||||
import { DraftOrder, Order } from "../../../.."
|
||||
import middlewares from "../../../middlewares"
|
||||
import { DeleteResponse, PaginatedResponse } from "../../../../types/common"
|
||||
|
||||
const route = Router()
|
||||
|
||||
@@ -44,9 +46,9 @@ export default (app) => {
|
||||
return app
|
||||
}
|
||||
|
||||
export const defaultRelations = ["order", "cart"]
|
||||
export const defaultAdminDraftOrdersRelations = ["order", "cart"]
|
||||
|
||||
export const defaultCartRelations = [
|
||||
export const defaultAdminDraftOrdersCartRelations = [
|
||||
"region",
|
||||
"items",
|
||||
"payment",
|
||||
@@ -60,7 +62,7 @@ export const defaultCartRelations = [
|
||||
"discounts.rule",
|
||||
]
|
||||
|
||||
export const defaultCartFields = [
|
||||
export const defaultAdminDraftOrdersCartFields = [
|
||||
"subtotal",
|
||||
"tax_total",
|
||||
"shipping_total",
|
||||
@@ -69,7 +71,7 @@ export const defaultCartFields = [
|
||||
"total",
|
||||
]
|
||||
|
||||
export const defaultFields = [
|
||||
export const defaultAdminDraftOrdersFields = [
|
||||
"id",
|
||||
"status",
|
||||
"display_id",
|
||||
@@ -82,7 +84,7 @@ export const defaultFields = [
|
||||
"no_notification_order",
|
||||
]
|
||||
|
||||
export const allowedFields = [
|
||||
export const allowedAdminDraftOrdersFields = [
|
||||
"id",
|
||||
"status",
|
||||
"display_id",
|
||||
@@ -94,4 +96,28 @@ export const allowedFields = [
|
||||
"no_notification_order",
|
||||
]
|
||||
|
||||
export const allowedRelations = ["cart"]
|
||||
export const allowedAdminDraftOrdersRelations = ["cart"]
|
||||
|
||||
export type AdminPostDraftOrdersDraftOrderRegisterPaymentRes = {
|
||||
order: Order
|
||||
}
|
||||
|
||||
export type AdminDraftOrdersRes = {
|
||||
draft_order: DraftOrder
|
||||
}
|
||||
|
||||
export type AdminDraftOrdersDeleteRes = DeleteResponse
|
||||
|
||||
export type AdminDraftOrdersListRes = PaginatedResponse & {
|
||||
draft_orders: DraftOrder[]
|
||||
}
|
||||
|
||||
export * from "./create-draft-order"
|
||||
export * from "./create-line-item"
|
||||
export * from "./delete-draft-order"
|
||||
export * from "./delete-line-item"
|
||||
export * from "./get-draft-order"
|
||||
export * from "./list-draft-orders"
|
||||
export * from "./register-payment"
|
||||
export * from "./update-draft-order"
|
||||
export * from "./update-line-item"
|
||||
@@ -1,47 +0,0 @@
|
||||
import { defaultFields, defaultRelations } from "./"
|
||||
|
||||
/**
|
||||
* @oas [get] /draft-orders
|
||||
* operationId: "GetDraftOrders"
|
||||
* summary: "List Draft Orders"
|
||||
* description: "Retrieves an list of Draft Orders"
|
||||
* tags:
|
||||
* - Draft Order
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* draft_order:
|
||||
* $ref: "#/components/schemas/draft-order"
|
||||
*/
|
||||
|
||||
export default async (req, res) => {
|
||||
const draftOrderService = req.scope.resolve("draftOrderService")
|
||||
|
||||
const limit = parseInt(req.query.limit) || 50
|
||||
const offset = parseInt(req.query.offset) || 0
|
||||
|
||||
const selector = {}
|
||||
|
||||
if ("q" in req.query) {
|
||||
selector.q = req.query.q
|
||||
}
|
||||
|
||||
const listConfig = {
|
||||
select: defaultFields,
|
||||
relations: defaultRelations,
|
||||
skip: offset,
|
||||
take: limit,
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
|
||||
const [draftOrders, count] = await draftOrderService.listAndCount(
|
||||
selector,
|
||||
listConfig
|
||||
)
|
||||
|
||||
res.json({ draft_orders: draftOrders, count, offset, limit })
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
defaultAdminDraftOrdersFields,
|
||||
defaultAdminDraftOrdersRelations,
|
||||
} from "."
|
||||
import { DraftOrderService } from "../../../../services"
|
||||
import { IsNumber, IsOptional, IsString } from "class-validator"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
import { Type } from "class-transformer"
|
||||
import { DraftOrderListSelector } from "../../../../types/draft-orders"
|
||||
/**
|
||||
* @oas [get] /draft-orders
|
||||
* operationId: "GetDraftOrders"
|
||||
* summary: "List Draft Orders"
|
||||
* description: "Retrieves an list of Draft Orders"
|
||||
* x-authenticated: true
|
||||
* tags:
|
||||
* - Draft Order
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* draft_order:
|
||||
* $ref: "#/components/schemas/draft-order"
|
||||
*/
|
||||
|
||||
export default async (req, res) => {
|
||||
const draftOrderService: DraftOrderService =
|
||||
req.scope.resolve("draftOrderService")
|
||||
|
||||
const validated = await validator(AdminGetDraftOrdersParams, req.query)
|
||||
|
||||
const selector: DraftOrderListSelector = {}
|
||||
|
||||
if (validated.q) {
|
||||
selector.q = validated.q
|
||||
}
|
||||
|
||||
const listConfig = {
|
||||
select: defaultAdminDraftOrdersFields,
|
||||
relations: defaultAdminDraftOrdersRelations,
|
||||
skip: validated.offset,
|
||||
take: validated.limit,
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
|
||||
const [draftOrders, count] = await draftOrderService.listAndCount(
|
||||
selector,
|
||||
listConfig
|
||||
)
|
||||
|
||||
res.json({
|
||||
draft_orders: draftOrders,
|
||||
count,
|
||||
offset: validated.offset,
|
||||
limit: validated.limit,
|
||||
})
|
||||
}
|
||||
|
||||
export class AdminGetDraftOrdersParams {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
q?: string
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
limit?: number = 50
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
offset?: number = 0
|
||||
}
|
||||
+18
-7
@@ -1,6 +1,13 @@
|
||||
import { EntityManager } from "typeorm"
|
||||
import {
|
||||
defaultFields as defaultOrderFields,
|
||||
defaultRelations as defaultOrderRelations,
|
||||
CartService,
|
||||
DraftOrderService,
|
||||
OrderService,
|
||||
PaymentProviderService,
|
||||
} from "../../../../services"
|
||||
import {
|
||||
defaultAdminOrdersFields as defaultOrderFields,
|
||||
defaultAdminOrdersRelations as defaultOrderRelations,
|
||||
} from "../orders/index"
|
||||
|
||||
/**
|
||||
@@ -8,6 +15,7 @@ import {
|
||||
* summary: "Registers a payment for a Draft Order"
|
||||
* operationId: "PostDraftOrdersDraftOrderRegisterPayment"
|
||||
* description: "Registers a payment for a Draft Order."
|
||||
* x-authenticated: true
|
||||
* parameters:
|
||||
* - (path) id=* {String} The Draft Order id.
|
||||
* tags:
|
||||
@@ -26,11 +34,14 @@ import {
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const draftOrderService = req.scope.resolve("draftOrderService")
|
||||
const paymentProviderService = req.scope.resolve("paymentProviderService")
|
||||
const orderService = req.scope.resolve("orderService")
|
||||
const cartService = req.scope.resolve("cartService")
|
||||
const entityManager = req.scope.resolve("manager")
|
||||
const draftOrderService: DraftOrderService =
|
||||
req.scope.resolve("draftOrderService")
|
||||
const paymentProviderService: PaymentProviderService = req.scope.resolve(
|
||||
"paymentProviderService"
|
||||
)
|
||||
const orderService: OrderService = req.scope.resolve("orderService")
|
||||
const cartService: CartService = req.scope.resolve("cartService")
|
||||
const entityManager: EntityManager = req.scope.resolve("manager")
|
||||
|
||||
let result
|
||||
await entityManager.transaction(async (manager) => {
|
||||
+69
-30
@@ -1,11 +1,26 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
import { defaultCartFields, defaultCartRelations } from "."
|
||||
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import {
|
||||
defaultAdminDraftOrdersCartFields,
|
||||
defaultAdminDraftOrdersCartRelations,
|
||||
} from "."
|
||||
import {
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsEmail,
|
||||
IsOptional,
|
||||
IsString,
|
||||
ValidateNested,
|
||||
} from "class-validator"
|
||||
import { CartService, DraftOrderService } from "../../../../services"
|
||||
import { Type } from "class-transformer"
|
||||
import { AddressPayload } from "../../../../types/common"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
/**
|
||||
* @oas [post] /admin/draft-orders/{id}
|
||||
* operationId: PostDraftOrdersDraftOrder
|
||||
* summary: Update a Draft Order"
|
||||
* description: "Updates a Draft Order."
|
||||
* x-authenticated: true
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Draft Order.
|
||||
* requestBody:
|
||||
@@ -57,28 +72,11 @@ import { defaultCartFields, defaultCartRelations } from "."
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
region_id: Validator.string().optional(),
|
||||
country_code: Validator.string().optional(),
|
||||
email: Validator.string().email().optional(),
|
||||
billing_address: Validator.object().optional(),
|
||||
shipping_address: Validator.object().optional(),
|
||||
discounts: Validator.array()
|
||||
.items({
|
||||
code: Validator.string(),
|
||||
})
|
||||
.optional(),
|
||||
customer_id: Validator.string().optional(),
|
||||
no_notification_order: Validator.boolean().optional(),
|
||||
})
|
||||
const validated = await validator(AdminPostDraftOrdersDraftOrderReq, req.body)
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
const draftOrderService = req.scope.resolve("draftOrderService")
|
||||
const cartService = req.scope.resolve("cartService")
|
||||
const draftOrderService: DraftOrderService =
|
||||
req.scope.resolve("draftOrderService")
|
||||
const cartService: CartService = req.scope.resolve("cartService")
|
||||
|
||||
const draftOrder = await draftOrderService.retrieve(id)
|
||||
|
||||
@@ -89,19 +87,60 @@ export default async (req, res) => {
|
||||
)
|
||||
}
|
||||
|
||||
if ("no_notification_order" in value) {
|
||||
if (validated.no_notification_order !== undefined) {
|
||||
await draftOrderService.update(draftOrder.id, {
|
||||
no_notification_order: value.no_notification_order,
|
||||
no_notification_order: validated.no_notification_order,
|
||||
})
|
||||
delete value.no_notification_order
|
||||
delete validated.no_notification_order
|
||||
}
|
||||
|
||||
await cartService.update(draftOrder.cart_id, value)
|
||||
await cartService.update(draftOrder.cart_id, validated)
|
||||
|
||||
draftOrder.cart = await cartService.retrieve(draftOrder.cart_id, {
|
||||
relations: defaultCartRelations,
|
||||
select: defaultCartFields,
|
||||
relations: defaultAdminDraftOrdersCartRelations,
|
||||
select: defaultAdminDraftOrdersCartFields,
|
||||
})
|
||||
|
||||
res.status(200).json({ draft_order: draftOrder })
|
||||
}
|
||||
|
||||
export class AdminPostDraftOrdersDraftOrderReq {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
region_id?: string
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
country_code?: string
|
||||
|
||||
@IsEmail()
|
||||
@IsOptional()
|
||||
email?: string
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => AddressPayload)
|
||||
billing_address?: AddressPayload
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => AddressPayload)
|
||||
shipping_address?: AddressPayload
|
||||
|
||||
@IsArray()
|
||||
@IsOptional()
|
||||
@Type(() => Discount)
|
||||
@ValidateNested({ each: true })
|
||||
discounts?: Discount[]
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
customer_id?: string
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
no_notification_order?: boolean
|
||||
}
|
||||
|
||||
class Discount {
|
||||
@IsString()
|
||||
code: string
|
||||
}
|
||||
+54
-24
@@ -1,11 +1,20 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
import { defaultCartFields, defaultCartRelations, defaultFields } from "."
|
||||
|
||||
import { IsInt, IsObject, IsOptional, IsString } from "class-validator"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { EntityManager } from "typeorm"
|
||||
import {
|
||||
defaultAdminDraftOrdersCartFields,
|
||||
defaultAdminDraftOrdersCartRelations,
|
||||
defaultAdminDraftOrdersFields,
|
||||
} from "."
|
||||
import { DraftOrder } from "../../../.."
|
||||
import { CartService, DraftOrderService } from "../../../../services"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
/**
|
||||
* @oas [post] /draft-orders/{id}/line-items/{line_id}
|
||||
* operationId: "PostDraftOrdersDraftOrderLineItemsItem"
|
||||
* summary: "Update a Line Item for a Draft Order"
|
||||
* description: "Updates a Line Item for a Draft Order"
|
||||
* x-authenticated: true
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
@@ -39,27 +48,21 @@ import { defaultCartFields, defaultCartRelations, defaultFields } from "."
|
||||
export default async (req, res) => {
|
||||
const { id, line_id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
title: Validator.string().optional(),
|
||||
unit_price: Validator.number().optional(),
|
||||
quantity: Validator.number().optional(),
|
||||
metadata: Validator.object().optional(),
|
||||
})
|
||||
const validated = await validator(
|
||||
AdminPostDraftOrdersDraftOrderLineItemsItemReq,
|
||||
req.body
|
||||
)
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
const draftOrderService = req.scope.resolve("draftOrderService")
|
||||
const cartService = req.scope.resolve("cartService")
|
||||
const entityManager = req.scope.resolve("manager")
|
||||
const draftOrderService: DraftOrderService =
|
||||
req.scope.resolve("draftOrderService")
|
||||
const cartService: CartService = req.scope.resolve("cartService")
|
||||
const entityManager: EntityManager = req.scope.resolve("manager")
|
||||
|
||||
await entityManager.transaction(async (manager) => {
|
||||
const draftOrder = await draftOrderService
|
||||
const draftOrder: DraftOrder = await draftOrderService
|
||||
.withTransaction(manager)
|
||||
.retrieve(id, {
|
||||
select: defaultFields,
|
||||
select: defaultAdminDraftOrdersFields,
|
||||
relations: ["cart", "cart.items"],
|
||||
})
|
||||
|
||||
@@ -70,7 +73,7 @@ export default async (req, res) => {
|
||||
)
|
||||
}
|
||||
|
||||
if (value.quantity === 0) {
|
||||
if (validated.quantity === 0) {
|
||||
await cartService
|
||||
.withTransaction(manager)
|
||||
.removeLineItem(draftOrder.cart.id, line_id)
|
||||
@@ -84,8 +87,8 @@ export default async (req, res) => {
|
||||
)
|
||||
}
|
||||
|
||||
const lineItemUpdate = {
|
||||
...value,
|
||||
const lineItemUpdate: LineItemUpdate = {
|
||||
...validated,
|
||||
region_id: draftOrder.cart.region_id,
|
||||
}
|
||||
|
||||
@@ -101,10 +104,37 @@ export default async (req, res) => {
|
||||
draftOrder.cart = await cartService
|
||||
.withTransaction(manager)
|
||||
.retrieve(draftOrder.cart_id, {
|
||||
relations: defaultCartRelations,
|
||||
select: defaultCartFields,
|
||||
relations: defaultAdminDraftOrdersCartRelations,
|
||||
select: defaultAdminDraftOrdersCartFields,
|
||||
})
|
||||
|
||||
res.status(200).json({ draft_order: draftOrder })
|
||||
})
|
||||
}
|
||||
|
||||
class LineItemUpdate {
|
||||
title?: string
|
||||
unit_price?: number
|
||||
quantity?: number
|
||||
metadata?: object = {}
|
||||
region_id?: string
|
||||
variant_id?: string
|
||||
}
|
||||
|
||||
export class AdminPostDraftOrdersDraftOrderLineItemsItemReq {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
title?: string
|
||||
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
unit_price?: number
|
||||
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
quantity?: number
|
||||
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
metadata?: object = {}
|
||||
}
|
||||
Reference in New Issue
Block a user