feat(medusa, core-workflows, product): slightly improve create cart workflow (#5725)
This commit is contained in:
committed by
GitHub
parent
946db51a9b
commit
85cda7ce37
6
.changeset/unlucky-snails-drive.md
Normal file
6
.changeset/unlucky-snails-drive.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@medusajs/medusa": patch
|
||||
"@medusajs/core-flows": patch
|
||||
---
|
||||
|
||||
slightly improve create cart workflow
|
||||
@@ -5,7 +5,9 @@ import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
type AddressesDTO = {
|
||||
shipping_address_id?: string
|
||||
shipping_address?: AddressDTO
|
||||
billing_address_id?: string
|
||||
billing_address?: AddressDTO
|
||||
}
|
||||
|
||||
type HandlerInputData = {
|
||||
@@ -48,6 +50,7 @@ export async function findOrCreateAddresses({
|
||||
country_code: regionCountries[0],
|
||||
})
|
||||
|
||||
addressesDTO.shipping_address = shippingAddress
|
||||
addressesDTO.shipping_address_id = shippingAddress?.id
|
||||
}
|
||||
} else {
|
||||
@@ -75,6 +78,7 @@ export async function findOrCreateAddresses({
|
||||
)
|
||||
}
|
||||
|
||||
addressesDTO.shipping_address = address
|
||||
addressesDTO.shipping_address_id = address.id
|
||||
}
|
||||
}
|
||||
@@ -103,6 +107,7 @@ export async function findOrCreateAddresses({
|
||||
)
|
||||
}
|
||||
|
||||
addressesDTO.billing_address = address
|
||||
addressesDTO.billing_address_id = billingAddressId
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CartDTO } from "@medusajs/types"
|
||||
import { AddressDTO, CartDTO, CustomerDTO, RegionDTO } from "@medusajs/types"
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
enum Aliases {
|
||||
@@ -14,14 +14,18 @@ type HandlerInputData = {
|
||||
sales_channel_id?: string
|
||||
}
|
||||
addresses: {
|
||||
shipping_address?: AddressDTO
|
||||
shipping_address_id: string
|
||||
billing_address?: AddressDTO
|
||||
billing_address_id: string
|
||||
}
|
||||
customer: {
|
||||
customer?: CustomerDTO
|
||||
customer_id?: string
|
||||
email?: string
|
||||
}
|
||||
region: {
|
||||
region?: RegionDTO
|
||||
region_id: string
|
||||
}
|
||||
context: {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { validateEmail } from "@medusajs/utils"
|
||||
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
import { CustomerTypes } from "@medusajs/types"
|
||||
|
||||
type CustomerDTO = {
|
||||
type CustomerResultDTO = {
|
||||
customer?: CustomerTypes.CustomerDTO
|
||||
customer_id?: string
|
||||
email?: string
|
||||
}
|
||||
@@ -22,12 +24,12 @@ export async function findOrCreateCustomer({
|
||||
container,
|
||||
context,
|
||||
data,
|
||||
}: WorkflowArguments<HandlerInputData>): Promise<CustomerDTO> {
|
||||
}: WorkflowArguments<HandlerInputData>): Promise<CustomerResultDTO> {
|
||||
const { manager } = context
|
||||
|
||||
const customerService = container.resolve("customerService")
|
||||
|
||||
const customerDTO: CustomerDTO = {}
|
||||
const customerDataDTO: CustomerResultDTO = {}
|
||||
const customerId = data[Aliases.Customer].customer_id
|
||||
const customerServiceTx = customerService.withTransaction(manager)
|
||||
|
||||
@@ -36,8 +38,9 @@ export async function findOrCreateCustomer({
|
||||
.retrieve(customerId)
|
||||
.catch(() => undefined)
|
||||
|
||||
customerDTO.customer_id = customer?.id
|
||||
customerDTO.email = customer?.email
|
||||
customerDataDTO.customer = customer
|
||||
customerDataDTO.customer_id = customer?.id
|
||||
customerDataDTO.email = customer?.email
|
||||
}
|
||||
|
||||
const customerEmail = data[Aliases.Customer].email
|
||||
@@ -53,11 +56,12 @@ export async function findOrCreateCustomer({
|
||||
customer = await customerServiceTx.create({ email: validatedEmail })
|
||||
}
|
||||
|
||||
customerDTO.customer_id = customer.id
|
||||
customerDTO.email = customer.email
|
||||
customerDataDTO.customer = customer
|
||||
customerDataDTO.customer_id = customer.id
|
||||
customerDataDTO.email = customer.email
|
||||
}
|
||||
|
||||
return customerDTO
|
||||
return customerDataDTO
|
||||
}
|
||||
|
||||
findOrCreateCustomer.aliases = Aliases
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { MedusaError } from "@medusajs/utils"
|
||||
import { RegionTypes } from "@medusajs/types"
|
||||
import { isDefined } from "medusa-core-utils"
|
||||
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
type RegionDTO = {
|
||||
type RegionResultDTO = {
|
||||
region_id?: string
|
||||
region?: RegionTypes.RegionDTO
|
||||
}
|
||||
|
||||
type HandlerInputData = {
|
||||
@@ -20,16 +22,24 @@ enum Aliases {
|
||||
export async function findRegion({
|
||||
container,
|
||||
data,
|
||||
}: WorkflowArguments<HandlerInputData>): Promise<RegionDTO> {
|
||||
}: WorkflowArguments<HandlerInputData>): Promise<RegionResultDTO> {
|
||||
const regionService = container.resolve("regionService")
|
||||
|
||||
let regionId: string
|
||||
const regionDTO: RegionDTO = {}
|
||||
const regionDTO: RegionResultDTO = {}
|
||||
|
||||
if (isDefined(data[Aliases.Region].region_id)) {
|
||||
regionId = data[Aliases.Region].region_id
|
||||
regionDTO.region_id = data[Aliases.Region].region_id
|
||||
regionDTO.region = await regionService.retrieve(regionDTO.region_id, {
|
||||
relations: ["countries"],
|
||||
})
|
||||
} else {
|
||||
const regions = await regionService.list({}, {})
|
||||
const regions = await regionService.list(
|
||||
{},
|
||||
{
|
||||
relations: ["countries"],
|
||||
}
|
||||
)
|
||||
|
||||
if (!regions?.length) {
|
||||
throw new MedusaError(
|
||||
@@ -38,11 +48,10 @@ export async function findRegion({
|
||||
)
|
||||
}
|
||||
|
||||
regionId = regions[0].id
|
||||
regionDTO.region_id = regions[0].id
|
||||
regionDTO.region = regions[0]
|
||||
}
|
||||
|
||||
regionDTO.region_id = regionId
|
||||
|
||||
return regionDTO
|
||||
}
|
||||
|
||||
|
||||
@@ -364,11 +364,15 @@ class CartService extends TransactionBaseService {
|
||||
).id
|
||||
}
|
||||
|
||||
if (data.customer_id) {
|
||||
const customer = await this.customerService_
|
||||
.withTransaction(transactionManager)
|
||||
.retrieve(data.customer_id)
|
||||
.catch(() => undefined)
|
||||
if (data.customer_id || data.customer) {
|
||||
const customer =
|
||||
(data.customer ??
|
||||
(data.customer_id &&
|
||||
(await this.customerService_
|
||||
.withTransaction(transactionManager)
|
||||
.retrieve(data.customer_id)
|
||||
.catch(() => undefined)))) as Customer
|
||||
|
||||
rawCart.customer = customer
|
||||
rawCart.customer_id = customer?.id
|
||||
rawCart.email = customer?.email
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Cart, CartType } from "../models/cart"
|
||||
import { IsType } from "../utils/validators/is-type"
|
||||
import { Region } from "../models"
|
||||
import { ValidateNested } from "class-validator"
|
||||
import { CustomerTypes } from "@medusajs/types"
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function isCart(object: any): object is Cart {
|
||||
@@ -60,6 +61,7 @@ export type CartCreateProps = {
|
||||
shipping_address?: Partial<AddressPayload>
|
||||
gift_cards?: GiftCard[]
|
||||
discounts?: Discount[]
|
||||
customer?: CustomerTypes.CustomerDTO
|
||||
customer_id?: string
|
||||
type?: CartType
|
||||
context?: object
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { MedusaModule } from "@medusajs/modules-sdk"
|
||||
import { IProductModuleService, ProductTypes } from "@medusajs/types"
|
||||
import {
|
||||
IProductModuleService,
|
||||
ProductTypes,
|
||||
UpdateProductDTO,
|
||||
} from "@medusajs/types"
|
||||
import { kebabCase } from "@medusajs/utils"
|
||||
import {
|
||||
Product,
|
||||
@@ -172,16 +176,30 @@ describe("ProductModuleService products", function () {
|
||||
|
||||
const variantTitle = data.variants[0].title
|
||||
|
||||
const updateData = {
|
||||
...data,
|
||||
id: productOne.id,
|
||||
title: "updated title",
|
||||
}
|
||||
const productBefore = (await module.retrieve(productOne.id, {
|
||||
relations: [
|
||||
"images",
|
||||
"variants",
|
||||
"options",
|
||||
"options.values",
|
||||
"variants.options",
|
||||
"tags",
|
||||
"type",
|
||||
],
|
||||
})) as unknown as UpdateProductDTO
|
||||
|
||||
const updatedProducts = await module.update([updateData])
|
||||
productBefore.title = "updated title"
|
||||
productBefore.variants = [...productBefore.variants!, ...data.variants]
|
||||
productBefore.type = { value: "new-type" }
|
||||
productBefore.options = data.options
|
||||
productBefore.images = data.images
|
||||
productBefore.thumbnail = data.thumbnail
|
||||
productBefore.tags = data.tags
|
||||
|
||||
const updatedProducts = await module.update([productBefore])
|
||||
expect(updatedProducts).toHaveLength(1)
|
||||
|
||||
const product = await module.retrieve(updateData.id, {
|
||||
const product = await module.retrieve(productBefore.id, {
|
||||
relations: [
|
||||
"images",
|
||||
"variants",
|
||||
@@ -195,7 +213,7 @@ describe("ProductModuleService products", function () {
|
||||
|
||||
const createdVariant = product.variants.find(
|
||||
(v) => v.title === variantTitle
|
||||
)
|
||||
)!
|
||||
|
||||
expect(product.images).toHaveLength(1)
|
||||
expect(createdVariant?.options).toHaveLength(1)
|
||||
@@ -206,12 +224,12 @@ describe("ProductModuleService products", function () {
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: "updated title",
|
||||
description: updateData.description,
|
||||
subtitle: updateData.subtitle,
|
||||
is_giftcard: updateData.is_giftcard,
|
||||
discountable: updateData.discountable,
|
||||
description: productBefore.description,
|
||||
subtitle: productBefore.subtitle,
|
||||
is_giftcard: productBefore.is_giftcard,
|
||||
discountable: productBefore.discountable,
|
||||
thumbnail: images[0],
|
||||
status: updateData.status,
|
||||
status: productBefore.status,
|
||||
images: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
@@ -221,11 +239,11 @@ describe("ProductModuleService products", function () {
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: updateData.options[0].title,
|
||||
title: productBefore.options?.[0].title,
|
||||
values: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
value: updateData.variants[0].options?.[0].value,
|
||||
value: createdVariant.options?.[0].value,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
@@ -233,18 +251,18 @@ describe("ProductModuleService products", function () {
|
||||
tags: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
value: updateData.tags[0].value,
|
||||
value: productBefore.tags?.[0].value,
|
||||
}),
|
||||
]),
|
||||
type: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
value: updateData.type.value,
|
||||
value: productBefore.type!.value,
|
||||
}),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: updateData.variants[0].title,
|
||||
sku: updateData.variants[0].sku,
|
||||
title: createdVariant.title,
|
||||
sku: createdVariant.sku,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
inventory_quantity: "100",
|
||||
@@ -252,7 +270,7 @@ describe("ProductModuleService products", function () {
|
||||
options: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
value: updateData.variants[0].options?.[0].value,
|
||||
value: createdVariant.options?.[0].value,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * as CacheTypes from "./cache"
|
||||
export * as CommonTypes from "./common"
|
||||
export * as CustomerTypes from "./customer"
|
||||
export * as DAL from "./dal"
|
||||
export * as EventBusTypes from "./event-bus"
|
||||
export * as FeatureFlagTypes from "./feature-flag"
|
||||
@@ -8,6 +9,7 @@ export * as LoggerTypes from "./logger"
|
||||
export * as ModulesSdkTypes from "./modules-sdk"
|
||||
export * as PricingTypes from "./pricing"
|
||||
export * as ProductTypes from "./product"
|
||||
export * as RegionTypes from "./region"
|
||||
export * as SalesChannelTypes from "./sales-channel"
|
||||
export * as SearchTypes from "./search"
|
||||
export * as StockLocationTypes from "./stock-location"
|
||||
|
||||
24
packages/types/src/customer/common.ts
Normal file
24
packages/types/src/customer/common.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { AddressDTO } from "../address"
|
||||
|
||||
export interface CustomerDTO {
|
||||
id: string
|
||||
email: string
|
||||
billing_address_id?: string | null
|
||||
shipping_address_id?: string | null
|
||||
first_name?: string | null
|
||||
last_name?: string | null
|
||||
billing_address?: AddressDTO
|
||||
shipping_address?: AddressDTO
|
||||
phone?: string | null
|
||||
has_account: boolean
|
||||
groups?: {
|
||||
id: string
|
||||
}[]
|
||||
orders: {
|
||||
id: string
|
||||
}[]
|
||||
metadata?: Record<string, unknown>
|
||||
deleted_at?: Date | string
|
||||
created_at?: Date | string
|
||||
updated_at?: Date | string
|
||||
}
|
||||
1
packages/types/src/customer/index.ts
Normal file
1
packages/types/src/customer/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./common"
|
||||
@@ -3,6 +3,7 @@ export * from "./bundles"
|
||||
export * from "./cache"
|
||||
export * from "./cart"
|
||||
export * from "./common"
|
||||
export * from "./customer"
|
||||
export * from "./dal"
|
||||
export * from "./event-bus"
|
||||
export * from "./feature-flag"
|
||||
@@ -15,6 +16,7 @@ export * from "./modules-sdk"
|
||||
export * from "./pricing"
|
||||
export * from "./product"
|
||||
export * from "./product-category"
|
||||
export * from "./region"
|
||||
export * from "./sales-channel"
|
||||
export * from "./search"
|
||||
export * from "./shared-context"
|
||||
|
||||
11
packages/types/src/region/common.ts
Normal file
11
packages/types/src/region/common.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export type RegionDTO = {
|
||||
name: string
|
||||
currency_code: string
|
||||
tax_rate?: number
|
||||
tax_code?: string | null
|
||||
gift_cards_taxable?: boolean
|
||||
automatic_taxes?: boolean
|
||||
tax_provider_id?: string | null
|
||||
metadata?: Record<string, unknown>
|
||||
includes_tax?: boolean
|
||||
}
|
||||
1
packages/types/src/region/index.ts
Normal file
1
packages/types/src/region/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./common"
|
||||
Reference in New Issue
Block a user