chores(medusa): Improve draft order creation perf flow (#3431)
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
chores(medusa): Improve draft order creation perf flow
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import CustomShippingOptionService from "../custom-shipping-option"
|
import CustomShippingOptionService from "../custom-shipping-option"
|
||||||
import { MockManager, MockRepository, IdMap } from "medusa-test-utils"
|
|
||||||
|
import { MockManager, MockRepository } from "medusa-test-utils"
|
||||||
|
|
||||||
describe("CustomShippingOptionService", () => {
|
describe("CustomShippingOptionService", () => {
|
||||||
describe("list", () => {
|
describe("list", () => {
|
||||||
@@ -108,20 +109,22 @@ describe("CustomShippingOptionService", () => {
|
|||||||
await customShippingOptionService.create(customShippingOption)
|
await customShippingOptionService.create(customShippingOption)
|
||||||
|
|
||||||
expect(customShippingOptionRepository.create).toHaveBeenCalledTimes(1)
|
expect(customShippingOptionRepository.create).toHaveBeenCalledTimes(1)
|
||||||
expect(customShippingOptionRepository.create).toHaveBeenCalledWith({
|
expect(customShippingOptionRepository.create).toHaveBeenCalledWith([
|
||||||
cart_id: "test-cso-cart",
|
{
|
||||||
shipping_option_id: "test-so",
|
cart_id: "test-cso-cart",
|
||||||
price: 30,
|
shipping_option_id: "test-so",
|
||||||
metadata: undefined,
|
price: 30,
|
||||||
})
|
},
|
||||||
|
])
|
||||||
|
|
||||||
expect(customShippingOptionRepository.save).toHaveBeenCalledTimes(1)
|
expect(customShippingOptionRepository.save).toHaveBeenCalledTimes(1)
|
||||||
expect(customShippingOptionRepository.save).toHaveBeenCalledWith({
|
expect(customShippingOptionRepository.save).toHaveBeenCalledWith({
|
||||||
|
0: {
|
||||||
|
cart_id: "test-cso-cart",
|
||||||
|
shipping_option_id: "test-so",
|
||||||
|
price: 30,
|
||||||
|
},
|
||||||
id: "test-cso",
|
id: "test-cso",
|
||||||
cart_id: "test-cso-cart",
|
|
||||||
shipping_option_id: "test-so",
|
|
||||||
price: 30,
|
|
||||||
metadata: undefined,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -35,10 +35,12 @@ describe("DraftOrderService", () => {
|
|||||||
|
|
||||||
const lineItemService = {
|
const lineItemService = {
|
||||||
generate: jest.fn().mockImplementation(() =>
|
generate: jest.fn().mockImplementation(() =>
|
||||||
Promise.resolve({
|
Promise.resolve([
|
||||||
title: "test-item",
|
{
|
||||||
variant_id: "test-variant",
|
title: "test-item",
|
||||||
})
|
variant_id: "test-variant",
|
||||||
|
},
|
||||||
|
])
|
||||||
),
|
),
|
||||||
create: jest.fn().mockImplementation((data) => data),
|
create: jest.fn().mockImplementation((data) => data),
|
||||||
withTransaction: function () {
|
withTransaction: function () {
|
||||||
@@ -88,6 +90,12 @@ describe("DraftOrderService", () => {
|
|||||||
...testOrder,
|
...testOrder,
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
retrieveWithTotals: jest.fn().mockReturnValue(
|
||||||
|
Promise.resolve({
|
||||||
|
id: "test-cart",
|
||||||
|
...testOrder,
|
||||||
|
})
|
||||||
|
),
|
||||||
update: jest.fn(),
|
update: jest.fn(),
|
||||||
applyDiscount: jest.fn(),
|
applyDiscount: jest.fn(),
|
||||||
addShippingMethod: jest.fn(),
|
addShippingMethod: jest.fn(),
|
||||||
@@ -151,28 +159,37 @@ describe("DraftOrderService", () => {
|
|||||||
|
|
||||||
expect(cartService.addShippingMethod).toHaveBeenCalledTimes(1)
|
expect(cartService.addShippingMethod).toHaveBeenCalledTimes(1)
|
||||||
expect(cartService.addShippingMethod).toHaveBeenCalledWith(
|
expect(cartService.addShippingMethod).toHaveBeenCalledWith(
|
||||||
"test-cart",
|
{
|
||||||
|
id: "test-cart",
|
||||||
|
...testOrder,
|
||||||
|
},
|
||||||
"test-option",
|
"test-option",
|
||||||
{}
|
{}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(lineItemService.generate).toHaveBeenCalledTimes(1)
|
expect(lineItemService.generate).toHaveBeenCalledTimes(1)
|
||||||
expect(lineItemService.generate).toHaveBeenCalledWith(
|
expect(lineItemService.generate).toHaveBeenCalledWith(
|
||||||
"test-variant",
|
[
|
||||||
"test-region",
|
{
|
||||||
2,
|
variantId: "test-variant",
|
||||||
|
quantity: 2,
|
||||||
|
metadata: {},
|
||||||
|
unit_price: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
{
|
{
|
||||||
metadata: {},
|
region_id: "test-region",
|
||||||
unit_price: undefined,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(lineItemService.create).toHaveBeenCalledTimes(1)
|
expect(lineItemService.create).toHaveBeenCalledTimes(1)
|
||||||
expect(lineItemService.create).toHaveBeenCalledWith({
|
expect(lineItemService.create).toHaveBeenCalledWith([
|
||||||
cart_id: cartId,
|
{
|
||||||
title,
|
cart_id: cartId,
|
||||||
variant_id: "test-variant",
|
title,
|
||||||
})
|
variant_id: "test-variant",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
expect(cartService.applyDiscount).toHaveBeenCalledTimes(0)
|
expect(cartService.applyDiscount).toHaveBeenCalledTimes(0)
|
||||||
})
|
})
|
||||||
@@ -181,6 +198,8 @@ describe("DraftOrderService", () => {
|
|||||||
const cartId = "test-cart"
|
const cartId = "test-cart"
|
||||||
const title = "test-item"
|
const title = "test-item"
|
||||||
|
|
||||||
|
const originalTestOrder = { ...testOrder }
|
||||||
|
|
||||||
testOrder["discounts"] = [{ code: "TEST" }]
|
testOrder["discounts"] = [{ code: "TEST" }]
|
||||||
await draftOrderService.create(testOrder)
|
await draftOrderService.create(testOrder)
|
||||||
|
|
||||||
@@ -200,28 +219,37 @@ describe("DraftOrderService", () => {
|
|||||||
|
|
||||||
expect(cartService.addShippingMethod).toHaveBeenCalledTimes(1)
|
expect(cartService.addShippingMethod).toHaveBeenCalledTimes(1)
|
||||||
expect(cartService.addShippingMethod).toHaveBeenCalledWith(
|
expect(cartService.addShippingMethod).toHaveBeenCalledWith(
|
||||||
"test-cart",
|
{
|
||||||
|
id: "test-cart",
|
||||||
|
...originalTestOrder,
|
||||||
|
},
|
||||||
"test-option",
|
"test-option",
|
||||||
{}
|
{}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(lineItemService.generate).toHaveBeenCalledTimes(1)
|
expect(lineItemService.generate).toHaveBeenCalledTimes(1)
|
||||||
expect(lineItemService.generate).toHaveBeenCalledWith(
|
expect(lineItemService.generate).toHaveBeenCalledWith(
|
||||||
"test-variant",
|
[
|
||||||
"test-region",
|
{
|
||||||
2,
|
variantId: "test-variant",
|
||||||
|
quantity: 2,
|
||||||
|
metadata: {},
|
||||||
|
unit_price: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
{
|
{
|
||||||
metadata: {},
|
region_id: "test-region",
|
||||||
unit_price: undefined,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(lineItemService.create).toHaveBeenCalledTimes(1)
|
expect(lineItemService.create).toHaveBeenCalledTimes(1)
|
||||||
expect(lineItemService.create).toHaveBeenCalledWith({
|
expect(lineItemService.create).toHaveBeenCalledWith([
|
||||||
cart_id: cartId,
|
{
|
||||||
title,
|
cart_id: cartId,
|
||||||
variant_id: "test-variant",
|
title,
|
||||||
})
|
variant_id: "test-variant",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
expect(cartService.update).toHaveBeenCalledTimes(1)
|
expect(cartService.update).toHaveBeenCalledTimes(1)
|
||||||
expect(cartService.update).toHaveBeenCalledWith(cartId, {
|
expect(cartService.update).toHaveBeenCalledWith(cartId, {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import {
|
|||||||
TotalField,
|
TotalField,
|
||||||
WithRequiredProperty,
|
WithRequiredProperty,
|
||||||
} from "../types/common"
|
} from "../types/common"
|
||||||
import { buildQuery, setMetadata } from "../utils"
|
import { buildQuery, isString, setMetadata } from "../utils"
|
||||||
import { FlagRouter } from "../utils/flag-router"
|
import { FlagRouter } from "../utils/flag-router"
|
||||||
import { validateEmail } from "../utils/is-email"
|
import { validateEmail } from "../utils/is-email"
|
||||||
import { PaymentSessionInput } from "../types/payment"
|
import { PaymentSessionInput } from "../types/payment"
|
||||||
@@ -2060,27 +2060,30 @@ class CartService extends TransactionBaseService {
|
|||||||
* Shipping Option is a possible way to ship an order. Shipping Methods may
|
* Shipping Option is a possible way to ship an order. Shipping Methods may
|
||||||
* also have additional details in the data field such as an id for a package
|
* also have additional details in the data field such as an id for a package
|
||||||
* shop.
|
* shop.
|
||||||
* @param cartId - the id of the cart to add shipping method to
|
* @param cartOrId - the id or the cart to add shipping method to
|
||||||
* @param optionId - id of shipping option to add as valid method
|
* @param optionId - id of shipping option to add as valid method
|
||||||
* @param data - the fulmillment data for the method
|
* @param data - the fulmillment data for the method
|
||||||
* @return the result of the update operation
|
* @return the result of the update operation
|
||||||
*/
|
*/
|
||||||
async addShippingMethod(
|
async addShippingMethod(
|
||||||
cartId: string,
|
cartOrId: string | Cart,
|
||||||
optionId: string,
|
optionId: string,
|
||||||
data: Record<string, unknown> = {}
|
data: Record<string, unknown> = {}
|
||||||
): Promise<Cart> {
|
): Promise<Cart> {
|
||||||
return await this.atomicPhase_(
|
return await this.atomicPhase_(
|
||||||
async (transactionManager: EntityManager) => {
|
async (transactionManager: EntityManager) => {
|
||||||
const cart = await this.retrieveWithTotals(cartId, {
|
const cart = !isString(cartOrId)
|
||||||
relations: [
|
? cartOrId
|
||||||
"shipping_methods",
|
: await this.retrieveWithTotals(cartOrId, {
|
||||||
"shipping_methods.shipping_option",
|
relations: [
|
||||||
"items",
|
"shipping_methods",
|
||||||
"items.variant",
|
"shipping_methods.shipping_option",
|
||||||
"items.variant.product",
|
"items",
|
||||||
],
|
"items.variant",
|
||||||
})
|
"items.variant.product",
|
||||||
|
"payment_sessions",
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
const cartCustomShippingOptions =
|
const cartCustomShippingOptions =
|
||||||
await this.customShippingOptionService_
|
await this.customShippingOptionService_
|
||||||
@@ -2140,7 +2143,7 @@ class CartService extends TransactionBaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedCart = await this.retrieve(cartId, {
|
const updatedCart = await this.retrieve(cart.id, {
|
||||||
relations: ["discounts", "discounts.rule", "shipping_methods"],
|
relations: ["discounts", "discounts.rule", "shipping_methods"],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { MedusaError } from "medusa-core-utils"
|
import { MedusaError } from "medusa-core-utils"
|
||||||
import { EntityManager } from "typeorm"
|
import { DeepPartial, EntityManager } from "typeorm"
|
||||||
import { TransactionBaseService } from "../interfaces"
|
import { TransactionBaseService } from "../interfaces"
|
||||||
import { CustomShippingOption } from "../models"
|
import { CustomShippingOption } from "../models"
|
||||||
import { CustomShippingOptionRepository } from "../repositories/custom-shipping-option"
|
import { CustomShippingOptionRepository } from "../repositories/custom-shipping-option"
|
||||||
@@ -86,23 +86,28 @@ class CustomShippingOptionService extends TransactionBaseService {
|
|||||||
* @param config - any configurations if needed, including meta data
|
* @param config - any configurations if needed, including meta data
|
||||||
* @return resolves to the creation result
|
* @return resolves to the creation result
|
||||||
*/
|
*/
|
||||||
async create(
|
async create<
|
||||||
data: CreateCustomShippingOptionInput
|
T = CreateCustomShippingOptionInput | CreateCustomShippingOptionInput[],
|
||||||
): Promise<CustomShippingOption> {
|
TResult = T extends CreateCustomShippingOptionInput[]
|
||||||
const { cart_id, shipping_option_id, price, metadata } = data
|
? CustomShippingOption[]
|
||||||
|
: CustomShippingOption
|
||||||
const manager = this.manager_
|
>(data: T): Promise<TResult> {
|
||||||
|
const manager = this.transactionManager_ ?? this.manager_
|
||||||
const customShippingOptionRepo = manager.getCustomRepository(
|
const customShippingOptionRepo = manager.getCustomRepository(
|
||||||
this.customShippingOptionRepository_
|
this.customShippingOptionRepository_
|
||||||
)
|
)
|
||||||
|
const data_ = (
|
||||||
|
Array.isArray(data) ? data : [data]
|
||||||
|
) as DeepPartial<CustomShippingOption>[]
|
||||||
|
|
||||||
const customShippingOption = customShippingOptionRepo.create({
|
const customShippingOptions = customShippingOptionRepo.create(data_)
|
||||||
cart_id,
|
const shippingOptions = await customShippingOptionRepo.save(
|
||||||
shipping_option_id,
|
customShippingOptions
|
||||||
price,
|
)
|
||||||
metadata,
|
|
||||||
})
|
return (Array.isArray(data)
|
||||||
return await customShippingOptionRepo.save(customShippingOption)
|
? shippingOptions
|
||||||
|
: shippingOptions[0]) as unknown as TResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||||
import { Brackets, EntityManager, FindManyOptions, UpdateResult } from "typeorm"
|
import { Brackets, EntityManager, FindManyOptions, UpdateResult } from "typeorm"
|
||||||
import { TransactionBaseService } from "../interfaces"
|
import { TransactionBaseService } from "../interfaces"
|
||||||
import { CartType, DraftOrder, DraftOrderStatus } from "../models"
|
import {
|
||||||
|
CartType,
|
||||||
|
DraftOrder,
|
||||||
|
DraftOrderStatus,
|
||||||
|
LineItem,
|
||||||
|
ShippingMethod,
|
||||||
|
} from "../models"
|
||||||
import { DraftOrderRepository } from "../repositories/draft-order"
|
import { DraftOrderRepository } from "../repositories/draft-order"
|
||||||
import { OrderRepository } from "../repositories/order"
|
import { OrderRepository } from "../repositories/order"
|
||||||
import { PaymentRepository } from "../repositories/payment"
|
import { PaymentRepository } from "../repositories/payment"
|
||||||
@@ -14,6 +20,7 @@ import EventBusService from "./event-bus"
|
|||||||
import LineItemService from "./line-item"
|
import LineItemService from "./line-item"
|
||||||
import ProductVariantService from "./product-variant"
|
import ProductVariantService from "./product-variant"
|
||||||
import ShippingOptionService from "./shipping-option"
|
import ShippingOptionService from "./shipping-option"
|
||||||
|
import { GenerateInputData } from "../types/line-item"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
manager: EntityManager
|
manager: EntityManager
|
||||||
@@ -271,7 +278,7 @@ class DraftOrderService extends TransactionBaseService {
|
|||||||
const cartServiceTx =
|
const cartServiceTx =
|
||||||
this.cartService_.withTransaction(transactionManager)
|
this.cartService_.withTransaction(transactionManager)
|
||||||
|
|
||||||
const createdCart = await cartServiceTx.create({
|
let createdCart = await cartServiceTx.create({
|
||||||
type: CartType.DRAFT_ORDER,
|
type: CartType.DRAFT_ORDER,
|
||||||
...rawCart,
|
...rawCart,
|
||||||
})
|
})
|
||||||
@@ -293,64 +300,108 @@ class DraftOrderService extends TransactionBaseService {
|
|||||||
const lineItemServiceTx =
|
const lineItemServiceTx =
|
||||||
this.lineItemService_.withTransaction(transactionManager)
|
this.lineItemService_.withTransaction(transactionManager)
|
||||||
|
|
||||||
for (const item of items || []) {
|
const itemsToGenerate: GenerateInputData[] = []
|
||||||
|
const itemsToCreate: Partial<LineItem>[] = []
|
||||||
|
|
||||||
|
// prepare that for next steps
|
||||||
|
;(items ?? []).forEach((item) => {
|
||||||
if (item.variant_id) {
|
if (item.variant_id) {
|
||||||
const line = await lineItemServiceTx.generate(
|
itemsToGenerate.push({
|
||||||
item.variant_id,
|
variantId: item.variant_id,
|
||||||
data.region_id,
|
|
||||||
item.quantity,
|
|
||||||
{
|
|
||||||
metadata: item?.metadata || {},
|
|
||||||
unit_price: item.unit_price,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
await lineItemServiceTx.create({
|
|
||||||
...line,
|
|
||||||
cart_id: createdCart.id,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
let price
|
|
||||||
if (typeof item.unit_price === `undefined` || item.unit_price < 0) {
|
|
||||||
price = 0
|
|
||||||
} else {
|
|
||||||
price = item.unit_price
|
|
||||||
}
|
|
||||||
|
|
||||||
// custom line items can be added to a draft order
|
|
||||||
await lineItemServiceTx.create({
|
|
||||||
cart_id: createdCart.id,
|
|
||||||
has_shipping: true,
|
|
||||||
title: item.title || "Custom item",
|
|
||||||
allow_discounts: false,
|
|
||||||
unit_price: price,
|
|
||||||
quantity: item.quantity,
|
quantity: item.quantity,
|
||||||
|
metadata: item.metadata,
|
||||||
|
unit_price: item.unit_price,
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let price
|
||||||
|
if (!isDefined(item.unit_price) || item.unit_price < 0) {
|
||||||
|
price = 0
|
||||||
|
} else {
|
||||||
|
price = item.unit_price
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsToCreate.push({
|
||||||
|
cart_id: createdCart.id,
|
||||||
|
has_shipping: true,
|
||||||
|
title: item.title || "Custom item",
|
||||||
|
allow_discounts: false,
|
||||||
|
unit_price: price,
|
||||||
|
quantity: item.quantity,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const promises: Promise<any>[] = []
|
||||||
|
|
||||||
|
// generate line item link to a variant
|
||||||
|
if (itemsToGenerate.length) {
|
||||||
|
const generatedLines = await lineItemServiceTx.generate(
|
||||||
|
itemsToGenerate,
|
||||||
|
{
|
||||||
|
region_id: data.region_id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const toCreate = generatedLines.map((line) => ({
|
||||||
|
...line,
|
||||||
|
cart_id: createdCart.id,
|
||||||
|
}))
|
||||||
|
|
||||||
|
promises.push(lineItemServiceTx.create(toCreate))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// custom line items can be added to a draft order
|
||||||
|
if (itemsToCreate.length) {
|
||||||
|
promises.push(lineItemServiceTx.create(itemsToCreate))
|
||||||
|
}
|
||||||
|
|
||||||
|
const shippingMethodToCreate: Partial<ShippingMethod>[] = []
|
||||||
|
|
||||||
|
shipping_methods.forEach((method) => {
|
||||||
|
if (isDefined(method.price)) {
|
||||||
|
shippingMethodToCreate.push({
|
||||||
|
shipping_option_id: method.option_id,
|
||||||
|
cart_id: createdCart.id,
|
||||||
|
price: method.price,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (shippingMethodToCreate.length) {
|
||||||
|
await this.customShippingOptionService_
|
||||||
|
.withTransaction(transactionManager)
|
||||||
|
.create(shippingMethodToCreate)
|
||||||
|
}
|
||||||
|
|
||||||
|
createdCart = await cartServiceTx.retrieveWithTotals(createdCart.id, {
|
||||||
|
relations: [
|
||||||
|
"shipping_methods",
|
||||||
|
"shipping_methods.shipping_option",
|
||||||
|
"items",
|
||||||
|
"items.variant",
|
||||||
|
"items.variant.product",
|
||||||
|
"payment_sessions",
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
shipping_methods.forEach((method) => {
|
||||||
|
promises.push(
|
||||||
|
cartServiceTx.addShippingMethod(
|
||||||
|
createdCart,
|
||||||
|
method.option_id,
|
||||||
|
method.data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all(promises)
|
||||||
|
|
||||||
if (discounts?.length) {
|
if (discounts?.length) {
|
||||||
await cartServiceTx.update(createdCart.id, { discounts })
|
await cartServiceTx.update(createdCart.id, { discounts })
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const method of shipping_methods) {
|
|
||||||
if (typeof method.price !== "undefined") {
|
|
||||||
await this.customShippingOptionService_
|
|
||||||
.withTransaction(transactionManager)
|
|
||||||
.create({
|
|
||||||
shipping_option_id: method.option_id,
|
|
||||||
cart_id: createdCart.id,
|
|
||||||
price: method.price,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
await cartServiceTx.addShippingMethod(
|
|
||||||
createdCart.id,
|
|
||||||
method.option_id,
|
|
||||||
method.data
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -220,9 +220,11 @@ class LineItemService extends TransactionBaseService {
|
|||||||
quantity: quantity as number,
|
quantity: quantity as number,
|
||||||
}
|
}
|
||||||
: variantIdOrData
|
: variantIdOrData
|
||||||
|
|
||||||
const resolvedContext = isString(variantIdOrData)
|
const resolvedContext = isString(variantIdOrData)
|
||||||
? context
|
? context
|
||||||
: (regionIdOrContext as GenerateLineItemContext)
|
: (regionIdOrContext as GenerateLineItemContext)
|
||||||
|
|
||||||
const regionId = (
|
const regionId = (
|
||||||
isString(variantIdOrData)
|
isString(variantIdOrData)
|
||||||
? regionIdOrContext
|
? regionIdOrContext
|
||||||
@@ -233,6 +235,10 @@ class LineItemService extends TransactionBaseService {
|
|||||||
Array.isArray(data) ? data : [data]
|
Array.isArray(data) ? data : [data]
|
||||||
) as GenerateInputData[]
|
) as GenerateInputData[]
|
||||||
|
|
||||||
|
const resolvedDataMap = new Map(
|
||||||
|
resolvedData.map((d) => [d.variantId, d])
|
||||||
|
)
|
||||||
|
|
||||||
const variants = await this.productVariantService_.list(
|
const variants = await this.productVariantService_.list(
|
||||||
{
|
{
|
||||||
id: resolvedData.map((d) => d.variantId),
|
id: resolvedData.map((d) => d.variantId),
|
||||||
@@ -247,7 +253,11 @@ class LineItemService extends TransactionBaseService {
|
|||||||
|
|
||||||
for (const variant of variants) {
|
for (const variant of variants) {
|
||||||
variantsMap.set(variant.id, variant)
|
variantsMap.set(variant.id, variant)
|
||||||
if (resolvedContext.unit_price == null) {
|
const variantResolvedData = resolvedDataMap.get(variant.id)
|
||||||
|
if (
|
||||||
|
resolvedContext.unit_price == null &&
|
||||||
|
variantResolvedData?.unit_price == null
|
||||||
|
) {
|
||||||
variantIdsToCalculatePricingFor.push(variant.id)
|
variantIdsToCalculatePricingFor.push(variant.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,6 +284,8 @@ class LineItemService extends TransactionBaseService {
|
|||||||
variantData.quantity,
|
variantData.quantity,
|
||||||
{
|
{
|
||||||
...resolvedContext,
|
...resolvedContext,
|
||||||
|
unit_price: variantData.unit_price ?? resolvedContext.unit_price,
|
||||||
|
metadata: variantData.metadata ?? resolvedContext.metadata,
|
||||||
variantPricing,
|
variantPricing,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -313,8 +325,6 @@ class LineItemService extends TransactionBaseService {
|
|||||||
variantPricing: ProductVariantPricing
|
variantPricing: ProductVariantPricing
|
||||||
}
|
}
|
||||||
): Promise<LineItem> {
|
): Promise<LineItem> {
|
||||||
const transactionManager = this.transactionManager_ ?? this.manager_
|
|
||||||
|
|
||||||
let unit_price = Number(context.unit_price) < 0 ? 0 : context.unit_price
|
let unit_price = Number(context.unit_price) < 0 ? 0 : context.unit_price
|
||||||
let unitPriceIncludesTax = false
|
let unitPriceIncludesTax = false
|
||||||
let shouldMerge = false
|
let shouldMerge = false
|
||||||
@@ -350,9 +360,8 @@ class LineItemService extends TransactionBaseService {
|
|||||||
|
|
||||||
rawLineItem.order_edit_id = context.order_edit_id || null
|
rawLineItem.order_edit_id = context.order_edit_id || null
|
||||||
|
|
||||||
const lineItemRepo = transactionManager.getCustomRepository(
|
const manager = this.transactionManager_ ?? this.manager_
|
||||||
this.lineItemRepository_
|
const lineItemRepo = manager.getCustomRepository(this.lineItemRepository_)
|
||||||
)
|
|
||||||
|
|
||||||
const lineItem = lineItemRepo.create(rawLineItem)
|
const lineItem = lineItemRepo.create(rawLineItem)
|
||||||
lineItem.variant = variant as ProductVariant
|
lineItem.variant = variant as ProductVariant
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { CalculationContextData } from "./totals"
|
|||||||
export type GenerateInputData = {
|
export type GenerateInputData = {
|
||||||
variantId: string
|
variantId: string
|
||||||
quantity: number
|
quantity: number
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
unit_price?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GenerateLineItemContext = {
|
export type GenerateLineItemContext = {
|
||||||
|
|||||||
Reference in New Issue
Block a user