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:
Oliver Windall Juhl
2021-11-18 15:19:17 +01:00
committed by GitHub
co-authored by Philip Korsholm Zakaria El Asri Kasper Fabricius Kristensen Philip Korsholm Sebastian Rindom
parent 55e200bf68
commit 373532ecbc
413 changed files with 20957 additions and 10349 deletions
@@ -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 = {}
}
@@ -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 = {}
}
@@ -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({
@@ -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 })
}
@@ -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
}
@@ -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) => {
@@ -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
}
@@ -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 = {}
}