feat: CartRegion link, definition + workflow (#6392)

This commit is contained in:
Oli Juhl
2024-02-16 14:06:26 +00:00
committed by GitHub
parent 7df4947ecf
commit 24fb102a56
17 changed files with 495 additions and 218 deletions
@@ -1,7 +1,3 @@
import {
createCart as createCartWorkflow,
Workflows,
} from "@medusajs/core-flows"
import {
IsArray,
IsInt,
@@ -10,7 +6,7 @@ import {
IsString,
ValidateNested,
} from "class-validator"
import { isDefined, MedusaError } from "medusa-core-utils"
import { MedusaError, isDefined } from "medusa-core-utils"
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
import {
CartService,
@@ -19,7 +15,6 @@ import {
RegionService,
} from "../../../../services"
import { MedusaContainer } from "@medusajs/modules-sdk"
import { FlagRouter } from "@medusajs/utils"
import { Type } from "class-transformer"
import reqIp from "request-ip"
@@ -122,130 +117,96 @@ export default async (req, res) => {
user_agent: req.get("user-agent"),
}
const isWorkflowEnabled = featureFlagRouter.isFeatureEnabled({
workflows: Workflows.CreateCart,
})
const lineItemService: LineItemService = req.scope.resolve("lineItemService")
const regionService: RegionService = req.scope.resolve("regionService")
let cart
if (isWorkflowEnabled) {
const cartWorkflow = createCartWorkflow(req.scope as MedusaContainer)
const input = {
...validated,
publishableApiKeyScopes: req.publishableApiKeyScopes,
context: {
...reqContext,
...validated.context,
},
}
const { result, errors } = await cartWorkflow.run({
input,
context: {
manager: entityManager,
},
throwOnError: false,
})
if (Array.isArray(errors)) {
if (isDefined(errors[0])) {
throw errors[0].error
}
}
cart = result
let regionId!: string
if (isDefined(validated.region_id)) {
regionId = validated.region_id as string
} else {
const lineItemService: LineItemService =
req.scope.resolve("lineItemService")
const regionService: RegionService = req.scope.resolve("regionService")
const regions = await regionService.list({})
let regionId!: string
if (isDefined(validated.region_id)) {
regionId = validated.region_id as string
} else {
const regions = await regionService.list({})
if (!regions?.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`A region is required to create a cart`
)
}
regionId = regions[0].id
if (!regions?.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`A region is required to create a cart`
)
}
const toCreate: Partial<CartCreateProps> = {
region_id: regionId,
sales_channel_id: validated.sales_channel_id,
context: {
...reqContext,
...validated.context,
},
}
if (req.user && req.user.customer_id) {
const customerService = req.scope.resolve("customerService")
const customer = await customerService.retrieve(req.user.customer_id)
toCreate["customer_id"] = customer.id
toCreate["email"] = customer.email
}
if (validated.country_code) {
toCreate["shipping_address"] = {
country_code: validated.country_code.toLowerCase(),
}
}
if (
!toCreate.sales_channel_id &&
req.publishableApiKeyScopes?.sales_channel_ids.length
) {
if (req.publishableApiKeyScopes.sales_channel_ids.length > 1) {
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
"The PublishableApiKey provided in the request header has multiple associated sales channels."
)
}
toCreate.sales_channel_id =
req.publishableApiKeyScopes.sales_channel_ids[0]
}
cart = await entityManager.transaction(async (manager) => {
const cartServiceTx = cartService.withTransaction(manager)
const lineItemServiceTx = lineItemService.withTransaction(manager)
const createdCart = await cartServiceTx.create(toCreate)
if (validated.items?.length) {
const generateInputData = validated.items.map((item) => {
return {
variantId: item.variant_id,
quantity: item.quantity,
}
})
const generatedLineItems: LineItem[] = await lineItemServiceTx.generate(
generateInputData,
{
region_id: regionId,
customer_id: req.user?.customer_id,
}
)
await cartServiceTx.addOrUpdateLineItems(
createdCart.id,
generatedLineItems,
{
validateSalesChannels:
featureFlagRouter.isFeatureEnabled("sales_channels"),
}
)
}
return createdCart
})
regionId = regions[0].id
}
const toCreate: Partial<CartCreateProps> = {
region_id: regionId,
sales_channel_id: validated.sales_channel_id,
context: {
...reqContext,
...validated.context,
},
}
if (req.user && req.user.customer_id) {
const customerService = req.scope.resolve("customerService")
const customer = await customerService.retrieve(req.user.customer_id)
toCreate["customer_id"] = customer.id
toCreate["email"] = customer.email
}
if (validated.country_code) {
toCreate["shipping_address"] = {
country_code: validated.country_code.toLowerCase(),
}
}
if (
!toCreate.sales_channel_id &&
req.publishableApiKeyScopes?.sales_channel_ids.length
) {
if (req.publishableApiKeyScopes.sales_channel_ids.length > 1) {
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
"The PublishableApiKey provided in the request header has multiple associated sales channels."
)
}
toCreate.sales_channel_id = req.publishableApiKeyScopes.sales_channel_ids[0]
}
let cart = await entityManager.transaction(async (manager) => {
const cartServiceTx = cartService.withTransaction(manager)
const lineItemServiceTx = lineItemService.withTransaction(manager)
const createdCart = await cartServiceTx.create(toCreate)
if (validated.items?.length) {
const generateInputData = validated.items.map((item) => {
return {
variantId: item.variant_id,
quantity: item.quantity,
}
})
const generatedLineItems: LineItem[] = await lineItemServiceTx.generate(
generateInputData,
{
region_id: regionId,
customer_id: req.user?.customer_id,
}
)
await cartServiceTx.addOrUpdateLineItems(
createdCart.id,
generatedLineItems,
{
validateSalesChannels:
featureFlagRouter.isFeatureEnabled("sales_channels"),
}
)
}
return createdCart
})
// }
cart = await cartService.retrieveWithTotals(cart!.id, {
select: defaultStoreCartFields,
relations: defaultStoreCartRelations,