add initital work on draft order
This commit is contained in:
@@ -0,0 +1,155 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
Generated,
|
||||||
|
BeforeInsert,
|
||||||
|
Index,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
PrimaryColumn,
|
||||||
|
OneToOne,
|
||||||
|
JoinColumn,
|
||||||
|
ManyToOne,
|
||||||
|
JoinTable,
|
||||||
|
ManyToMany,
|
||||||
|
OneToMany,
|
||||||
|
} from "typeorm"
|
||||||
|
import { ulid } from "ulid"
|
||||||
|
import { Address } from "./address"
|
||||||
|
|
||||||
|
import { Cart } from "./cart"
|
||||||
|
import { Customer } from "./customer"
|
||||||
|
import { Discount } from "./discount"
|
||||||
|
import { LineItem } from "./line-item"
|
||||||
|
import { Order } from "./order"
|
||||||
|
import { Payment } from "./payment"
|
||||||
|
import { Region } from "./region"
|
||||||
|
import { ShippingMethod } from "./shipping-method"
|
||||||
|
|
||||||
|
enum DraftOrderStatus {
|
||||||
|
OPEN = "open",
|
||||||
|
AWAITING = "awaiting",
|
||||||
|
COMPLETED = "completed",
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class DraftOrder {
|
||||||
|
@PrimaryColumn()
|
||||||
|
id: string
|
||||||
|
|
||||||
|
@Column({ type: "enum", enum: DraftOrderStatus, default: "open" })
|
||||||
|
status: DraftOrderStatus
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column()
|
||||||
|
@Generated("increment")
|
||||||
|
display_id: number
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({ nullable: true })
|
||||||
|
cart_id: string
|
||||||
|
|
||||||
|
@OneToOne(() => Cart)
|
||||||
|
@JoinColumn({ name: "cart_id" })
|
||||||
|
cart: Cart
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({ nullable: true })
|
||||||
|
order_id: string
|
||||||
|
|
||||||
|
@OneToOne(() => Order)
|
||||||
|
@JoinColumn({ name: "order_id" })
|
||||||
|
order: Order
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column()
|
||||||
|
customer_id: string
|
||||||
|
|
||||||
|
@ManyToOne(() => Customer, { cascade: ["insert"] })
|
||||||
|
@JoinColumn({ name: "customer_id" })
|
||||||
|
customer: Customer
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
() => LineItem,
|
||||||
|
lineItem => lineItem.draft_order,
|
||||||
|
{ cascade: ["insert", "remove"] }
|
||||||
|
)
|
||||||
|
items: LineItem[]
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
email: string
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({ nullable: true })
|
||||||
|
billing_address_id: string
|
||||||
|
|
||||||
|
@ManyToOne(() => Address, { cascade: ["insert"] })
|
||||||
|
@JoinColumn({ name: "billing_address_id" })
|
||||||
|
billing_address: Address
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({ nullable: true })
|
||||||
|
shipping_address_id: string
|
||||||
|
|
||||||
|
@ManyToOne(() => Address, { cascade: ["insert"] })
|
||||||
|
@JoinColumn({ name: "shipping_address_id" })
|
||||||
|
shipping_address: Address
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column()
|
||||||
|
region_id: string
|
||||||
|
|
||||||
|
@ManyToOne(() => Region)
|
||||||
|
@JoinColumn({ name: "region_id" })
|
||||||
|
region: Region
|
||||||
|
|
||||||
|
@ManyToMany(() => Discount, { cascade: ["insert"] })
|
||||||
|
@JoinTable({
|
||||||
|
name: "draft_order_discounts",
|
||||||
|
joinColumn: {
|
||||||
|
name: "draft_order_id",
|
||||||
|
referencedColumnName: "id",
|
||||||
|
},
|
||||||
|
inverseJoinColumn: {
|
||||||
|
name: "discount_id",
|
||||||
|
referencedColumnName: "id",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
discounts: Discount[]
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
() => ShippingMethod,
|
||||||
|
m => m.draft_order,
|
||||||
|
{ cascade: ["soft-remove", "remove"] }
|
||||||
|
)
|
||||||
|
shipping_methods: ShippingMethod[]
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
() => Payment,
|
||||||
|
p => p.draft_order,
|
||||||
|
{ cascade: ["insert"] }
|
||||||
|
)
|
||||||
|
payments: Payment[]
|
||||||
|
|
||||||
|
@Column({ nullable: true, type: "timestamptz" })
|
||||||
|
canceled_at: Date
|
||||||
|
|
||||||
|
@CreateDateColumn({ type: "timestamptz" })
|
||||||
|
created_at: Date
|
||||||
|
|
||||||
|
@UpdateDateColumn({ type: "timestamptz" })
|
||||||
|
updated_at: Date
|
||||||
|
|
||||||
|
@Column({ type: "jsonb", nullable: true })
|
||||||
|
metadata: any
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
idempotency_key: string
|
||||||
|
|
||||||
|
@BeforeInsert()
|
||||||
|
private beforeInsert() {
|
||||||
|
if (this.id) return
|
||||||
|
const id = ulid()
|
||||||
|
this.id = `dorder_${id}`
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ import { Cart } from "./cart"
|
|||||||
import { Order } from "./order"
|
import { Order } from "./order"
|
||||||
import { ClaimOrder } from "./claim-order"
|
import { ClaimOrder } from "./claim-order"
|
||||||
import { ProductVariant } from "./product-variant"
|
import { ProductVariant } from "./product-variant"
|
||||||
|
import { DraftOrder } from "./draft-order"
|
||||||
|
|
||||||
@Check(`"fulfilled_quantity" <= "quantity"`)
|
@Check(`"fulfilled_quantity" <= "quantity"`)
|
||||||
@Check(`"shipped_quantity" <= "fulfilled_quantity"`)
|
@Check(`"shipped_quantity" <= "fulfilled_quantity"`)
|
||||||
@@ -48,6 +49,17 @@ export class LineItem {
|
|||||||
)
|
)
|
||||||
@JoinColumn({ name: "order_id" })
|
@JoinColumn({ name: "order_id" })
|
||||||
order: Order
|
order: Order
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({ nullable: true })
|
||||||
|
draft_order_id: string
|
||||||
|
|
||||||
|
@ManyToOne(
|
||||||
|
() => DraftOrder,
|
||||||
|
dorder => dorder.items
|
||||||
|
)
|
||||||
|
@JoinColumn({ name: "draft_order_id" })
|
||||||
|
draft_order: DraftOrder
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import { Refund } from "./refund"
|
|||||||
import { Swap } from "./swap"
|
import { Swap } from "./swap"
|
||||||
import { ClaimOrder } from "./claim-order"
|
import { ClaimOrder } from "./claim-order"
|
||||||
import { ShippingMethod } from "./shipping-method"
|
import { ShippingMethod } from "./shipping-method"
|
||||||
|
import { DraftOrder } from "./draft-order"
|
||||||
|
|
||||||
export enum OrderStatus {
|
export enum OrderStatus {
|
||||||
PENDING = "pending",
|
PENDING = "pending",
|
||||||
@@ -212,6 +213,13 @@ export class Order {
|
|||||||
)
|
)
|
||||||
swaps: Swap[]
|
swaps: Swap[]
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
draft_order_id: string
|
||||||
|
|
||||||
|
@OneToOne(() => DraftOrder)
|
||||||
|
@JoinColumn({ name: "draft_order_id" })
|
||||||
|
draft_order: DraftOrder
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => LineItem,
|
() => LineItem,
|
||||||
lineItem => lineItem.order,
|
lineItem => lineItem.order,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { Swap } from "./swap"
|
|||||||
import { Currency } from "./currency"
|
import { Currency } from "./currency"
|
||||||
import { Cart } from "./cart"
|
import { Cart } from "./cart"
|
||||||
import { Order } from "./order"
|
import { Order } from "./order"
|
||||||
|
import { DraftOrder } from "./draft-order"
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Payment {
|
export class Payment {
|
||||||
@@ -49,6 +50,14 @@ export class Payment {
|
|||||||
@JoinColumn({ name: "order_id" })
|
@JoinColumn({ name: "order_id" })
|
||||||
order: Order
|
order: Order
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({ nullable: true })
|
||||||
|
draft_order_id: string
|
||||||
|
|
||||||
|
@OneToOne(() => DraftOrder)
|
||||||
|
@JoinColumn({ name: "draft_order_id" })
|
||||||
|
draft_order: DraftOrder
|
||||||
|
|
||||||
@Column({ type: "int" })
|
@Column({ type: "int" })
|
||||||
amount: number
|
amount: number
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { Cart } from "./cart"
|
|||||||
import { Swap } from "./swap"
|
import { Swap } from "./swap"
|
||||||
import { Return } from "./return"
|
import { Return } from "./return"
|
||||||
import { ShippingOption } from "./shipping-option"
|
import { ShippingOption } from "./shipping-option"
|
||||||
|
import { DraftOrder } from "./draft-order"
|
||||||
|
|
||||||
@Check(
|
@Check(
|
||||||
`"claim_order_id" IS NOT NULL OR "order_id" IS NOT NULL OR "cart_id" IS NOT NULL OR "swap_id" IS NOT NULL OR "return_id" IS NOT NULL`
|
`"claim_order_id" IS NOT NULL OR "order_id" IS NOT NULL OR "cart_id" IS NOT NULL OR "swap_id" IS NOT NULL OR "return_id" IS NOT NULL`
|
||||||
@@ -67,6 +68,14 @@ export class ShippingMethod {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
return_id: string
|
return_id: string
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({ nullable: true })
|
||||||
|
draft_order_id: string
|
||||||
|
|
||||||
|
@ManyToOne(() => DraftOrder)
|
||||||
|
@JoinColumn({ name: "draft_order_id" })
|
||||||
|
draft_order: DraftOrder
|
||||||
|
|
||||||
@OneToOne(
|
@OneToOne(
|
||||||
() => Return,
|
() => Return,
|
||||||
ret => ret.shipping_method
|
ret => ret.shipping_method
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { EntityRepository, Repository } from "typeorm"
|
||||||
|
import { DraftOrder } from "../models/draft-order"
|
||||||
|
|
||||||
|
@EntityRepository(DraftOrder)
|
||||||
|
export class DraftOrderRepository extends Repository<DraftOrder> {}
|
||||||
@@ -0,0 +1,361 @@
|
|||||||
|
import _ from "lodash"
|
||||||
|
import { BaseService } from "medusa-interfaces"
|
||||||
|
import { MedusaError } from "medusa-core-utils"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles swaps
|
||||||
|
* @implements BaseService
|
||||||
|
*/
|
||||||
|
class DraftOrderService extends BaseService {
|
||||||
|
static Events = {
|
||||||
|
CREATED: "draft_order.created",
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor({
|
||||||
|
manager,
|
||||||
|
draftOrderRepository,
|
||||||
|
eventBusService,
|
||||||
|
addressRepository,
|
||||||
|
cartService,
|
||||||
|
totalsService,
|
||||||
|
lineItemService,
|
||||||
|
productVariantService,
|
||||||
|
shippingOptionService,
|
||||||
|
regionService,
|
||||||
|
}) {
|
||||||
|
super()
|
||||||
|
|
||||||
|
/** @private @const {EntityManager} */
|
||||||
|
this.manager_ = manager
|
||||||
|
|
||||||
|
/** @private @const {SwapModel} */
|
||||||
|
this.draftOrderRepository_ = draftOrderRepository
|
||||||
|
|
||||||
|
/** @private @const {TotalsService} */
|
||||||
|
this.totalsService_ = totalsService
|
||||||
|
|
||||||
|
/** @private @const {AddressRepository} */
|
||||||
|
this.addressRepository_ = addressRepository
|
||||||
|
|
||||||
|
/** @private @const {LineItemService} */
|
||||||
|
this.lineItemService_ = lineItemService
|
||||||
|
|
||||||
|
/** @private @const {ReturnService} */
|
||||||
|
this.returnService_ = returnService
|
||||||
|
|
||||||
|
/** @private @const {CartService} */
|
||||||
|
this.cartService_ = cartService
|
||||||
|
|
||||||
|
/** @private @const {RegionService} */
|
||||||
|
this.regionService_ = regionService
|
||||||
|
|
||||||
|
/** @private @const {ProductVariantService} */
|
||||||
|
this.productVariantService_ = productVariantService
|
||||||
|
|
||||||
|
/** @private @const {ShippingOptionService} */
|
||||||
|
this.shippingOptionService_ = shippingOptionService
|
||||||
|
|
||||||
|
/** @private @const {EventBusService} */
|
||||||
|
this.eventBus_ = eventBusService
|
||||||
|
}
|
||||||
|
|
||||||
|
withTransaction(transactionManager) {
|
||||||
|
if (!transactionManager) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
const cloned = new DraftOrderService({
|
||||||
|
manager: transactionManager,
|
||||||
|
draftOrderRepository: this.draftOrderRepository_,
|
||||||
|
eventBusService: this.eventBus_,
|
||||||
|
cartService: this.cartService_,
|
||||||
|
totalsService: this.totalsService_,
|
||||||
|
productVariantService: this.productVariantService_,
|
||||||
|
lineItemService: this.lineItemService_,
|
||||||
|
})
|
||||||
|
|
||||||
|
cloned.transactionManager_ = transactionManager
|
||||||
|
|
||||||
|
return cloned
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a draft order with the given id.
|
||||||
|
* @param {string} id - id of the draft order to retrieve
|
||||||
|
* @return {Promise<DraftOrder>} the draft order
|
||||||
|
*/
|
||||||
|
async retrieve(id, config = {}) {
|
||||||
|
const draftOrderRepo = this.manager_.getCustomRepository(
|
||||||
|
this.draftOrderRepository_
|
||||||
|
)
|
||||||
|
|
||||||
|
const validatedId = this.validateId_(id)
|
||||||
|
|
||||||
|
const query = this.buildQuery_({ id: validatedId }, config)
|
||||||
|
|
||||||
|
const draftOrder = await draftOrderRepo.findOne(query)
|
||||||
|
|
||||||
|
if (!draftOrder) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_FOUND,
|
||||||
|
`Draft order with id: ${id} was not found`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return draftOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a draft order based on its associated cart id
|
||||||
|
* @param {string} cartId - cart id that the draft orders's cart has
|
||||||
|
* @return {Promise<DraftOrder>} the draft order
|
||||||
|
*/
|
||||||
|
async retrieveByCartId(cartId, relations = []) {
|
||||||
|
const draftOrderRepo = this.manager_.getCustomRepository(
|
||||||
|
this.draftOrderRepository_
|
||||||
|
)
|
||||||
|
|
||||||
|
const draftOrder = await draftOrderRepo.findOne({
|
||||||
|
where: {
|
||||||
|
cart_id: cartId,
|
||||||
|
},
|
||||||
|
relations,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!draftOrder) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_FOUND,
|
||||||
|
`Draft order was not found`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return draftOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists draft orders
|
||||||
|
* @param {Object} selector - query object for find
|
||||||
|
* @param {Object} config - configurable attributes for find
|
||||||
|
* @return {Promise<Array<DraftOrder>>} list of draft orders
|
||||||
|
*/
|
||||||
|
async list(
|
||||||
|
selector,
|
||||||
|
config = { skip: 0, take: 50, order: { created_at: "DESC" } }
|
||||||
|
) {
|
||||||
|
const draftOrderRepo = this.manager_.getCustomRepository(
|
||||||
|
this.draftOrderRepository_
|
||||||
|
)
|
||||||
|
|
||||||
|
const query = this.buildQuery_(selector, config)
|
||||||
|
|
||||||
|
return draftOrderRepo.find(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
async setAddress_(region, address) {
|
||||||
|
const addressRepo = this.manager_.getCustomRepository(
|
||||||
|
this.addressRepository_
|
||||||
|
)
|
||||||
|
|
||||||
|
const regCountries = region.countries.map(({ iso_2 }) => iso_2)
|
||||||
|
|
||||||
|
if (!address.country_code) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`Address is missing country code`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!regCountries.includes(address.country_code)) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`Country ${address.country_code} is not in region ${region.name}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const created = addressRepo.create(adress)
|
||||||
|
return created
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirms if the contents of a line item is covered by the inventory.
|
||||||
|
* To be covered a variant must either not have its inventory managed or it
|
||||||
|
* must allow backorders or it must have enough inventory to cover the request.
|
||||||
|
* If the content is made up of multiple variants it will return true if all
|
||||||
|
* variants can be covered. If the content consists of a single variant it will
|
||||||
|
* return true if the variant is covered.
|
||||||
|
* @param {(LineItemContent | LineItemContentArray)} - the content of the line
|
||||||
|
* item
|
||||||
|
* @param {number} - the quantity of the line item
|
||||||
|
* @return {boolean} true if the inventory covers the line item.
|
||||||
|
*/
|
||||||
|
async confirmInventory_(variantId, quantity) {
|
||||||
|
// If the line item is not stock tracked we don't have double check it
|
||||||
|
if (!variantId) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.productVariantService_.canCoverQuantity(variantId, quantity)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addLineItem(doId, lineItem) {
|
||||||
|
return this.atomicPhase_(async manager => {
|
||||||
|
const draftOrder = await this.retrieve(doId, {
|
||||||
|
relations: [
|
||||||
|
"shipping_methods",
|
||||||
|
"items",
|
||||||
|
"payment_sessions",
|
||||||
|
"items.variant",
|
||||||
|
"items.variant.product",
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
if (draftOrder.status !== "open") {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
|
"You are not allowed to add items to a draft order with status awaiting or completed"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentItem
|
||||||
|
if (lineItem.should_merge) {
|
||||||
|
currentItem = draftOrder.items.find(line => {
|
||||||
|
if (line.should_merge && line.variant_id === lineItem.variant_id) {
|
||||||
|
return _.isEqual(line.metadata, lineItem.metadata)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// If content matches one of the line items currently in the cart we can
|
||||||
|
// simply update the quantity of the existing line item
|
||||||
|
if (currentItem) {
|
||||||
|
const newQuantity = currentItem.quantity + lineItem.quantity
|
||||||
|
|
||||||
|
// Confirm inventory
|
||||||
|
const hasInventory = await this.confirmInventory_(
|
||||||
|
lineItem.variant_id,
|
||||||
|
newQuantity
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!hasInventory) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
|
"Inventory doesn't cover the desired quantity"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.lineItemService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.update(currentItem.id, {
|
||||||
|
quantity: newQuantity,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Confirm inventory
|
||||||
|
const hasInventory = await this.confirmInventory_(
|
||||||
|
lineItem.variant_id,
|
||||||
|
lineItem.quantity
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!hasInventory) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
|
"Inventory doesn't cover the desired quantity"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.lineItemService_.withTransaction(manager).create({
|
||||||
|
...lineItem,
|
||||||
|
has_shipping: false,
|
||||||
|
cart_id: cartId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a draft order.
|
||||||
|
* @param {Object} data - data to create draft order from
|
||||||
|
* @return {Promise<DraftOrder>} the created draft order
|
||||||
|
*/
|
||||||
|
async create(data) {
|
||||||
|
return this.atomicPhase_(async manager => {
|
||||||
|
const draftOrderRepo = manager.getCustomRepository(
|
||||||
|
this.draftOrderRepository_
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!data.region_id) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`region_id is required to create a draft order`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const region = await this.regionService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.retrieve(data.region_id, {
|
||||||
|
relations: ["countries"],
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!data.shipping_address && !data.shipping_address_id) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`Shipping addresss is required to create a draft order`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.shipping_address && !data.shipping_address_id) {
|
||||||
|
data.shipping_address = await this.setAddress_(
|
||||||
|
region,
|
||||||
|
data.shipping_address
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.billing_address && !data.billing_address_id) {
|
||||||
|
data.billing_address = await this.setAddress_(
|
||||||
|
region,
|
||||||
|
data.billing_address
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { items, shipping_methods, ...rest } = data
|
||||||
|
|
||||||
|
const draftOrder = draftOrderRepo.create(rest)
|
||||||
|
const result = await draftOrderRepo.save(draftOrder)
|
||||||
|
|
||||||
|
await this.eventBus_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.emit(DraftOrderService.Events.CREATED, {
|
||||||
|
id: result.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
let shippingMethods = []
|
||||||
|
for (const method of shipping_methods) {
|
||||||
|
const m = await this.shippingOptionService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.createShippingMethod(method.option_id, method.data, {
|
||||||
|
draft_order_id: draftOrder.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
shippingMethods.push(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of items) {
|
||||||
|
const line = await this.lineItemService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.generate(
|
||||||
|
item.variant_id,
|
||||||
|
cart.region_id,
|
||||||
|
item.quantity,
|
||||||
|
item.metadata
|
||||||
|
)
|
||||||
|
|
||||||
|
await this.lineItemService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.create({ draft_order_id: draftOrder.id, ...line })
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DraftOrderService
|
||||||
@@ -254,6 +254,10 @@ class ShippingOptionService extends BaseService {
|
|||||||
toCreate.claim_order_id = config.claim_order_id
|
toCreate.claim_order_id = config.claim_order_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.draft_order_id) {
|
||||||
|
toCreate.draft_order_id = config.draft_order_id
|
||||||
|
}
|
||||||
|
|
||||||
const method = await methodRepo.create(toCreate)
|
const method = await methodRepo.create(toCreate)
|
||||||
|
|
||||||
const created = await methodRepo.save(method)
|
const created = await methodRepo.save(method)
|
||||||
|
|||||||
Reference in New Issue
Block a user