fix(core-flows): keep same customer on cart update (#9977)
* fix(core-flows): keep same customer on cart update * update guest customer email * create guest customer for new emails * rm log
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@medusajs/core-flows": patch
|
||||
---
|
||||
|
||||
Keep customer when updating cart
|
||||
@@ -1882,6 +1882,192 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
})
|
||||
|
||||
it("should create another guest customer and update the cart email when an different email is provided", async () => {
|
||||
const cart = (
|
||||
await api.post(
|
||||
`/store/carts`,
|
||||
{
|
||||
currency_code: "usd",
|
||||
email: "tony@stark-industries.com",
|
||||
shipping_address: {
|
||||
address_1: "test address 1",
|
||||
address_2: "test address 2",
|
||||
city: "ny",
|
||||
country_code: "us",
|
||||
province: "ny",
|
||||
postal_code: "94016",
|
||||
},
|
||||
sales_channel_id: salesChannel.id,
|
||||
},
|
||||
storeHeaders
|
||||
)
|
||||
).data.cart
|
||||
|
||||
const originalCartCustomer = cart.customer
|
||||
|
||||
// update the cart without providing an email
|
||||
await api.post(
|
||||
`/store/carts/${cart.id}`,
|
||||
{
|
||||
metadata: {
|
||||
test: "test updated",
|
||||
},
|
||||
},
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
let currentCart = await api.get(
|
||||
`/store/carts/${cart.id}`,
|
||||
storeHeaders
|
||||
)
|
||||
let currentCartCustomer = currentCart.data.cart.customer
|
||||
|
||||
let customerData = (
|
||||
await api.get(
|
||||
`/admin/customers/${currentCart.data.cart.customer_id}`,
|
||||
adminHeaders
|
||||
)
|
||||
).data.customer
|
||||
|
||||
expect(currentCartCustomer).toEqual(originalCartCustomer)
|
||||
expect(customerData.email).toEqual(currentCart.data.cart.email)
|
||||
expect(currentCart.data.cart.email).toEqual(
|
||||
"tony@stark-industries.com"
|
||||
)
|
||||
expect(currentCart.data.cart.metadata).toEqual({
|
||||
test: "test updated",
|
||||
})
|
||||
|
||||
// update the cart providing an email
|
||||
await api.post(
|
||||
`/store/carts/${cart.id}`,
|
||||
{
|
||||
email: "foo@bar.com",
|
||||
metadata: {
|
||||
test: "test updated 2, new customer",
|
||||
},
|
||||
},
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
currentCart = await api.get(`/store/carts/${cart.id}`, storeHeaders)
|
||||
|
||||
customerData = (
|
||||
await api.get(
|
||||
`/admin/customers/${currentCart.data.cart.customer_id}`,
|
||||
adminHeaders
|
||||
)
|
||||
).data.customer
|
||||
|
||||
currentCartCustomer = currentCart.data.cart.customer
|
||||
|
||||
expect(currentCartCustomer).not.toEqual(originalCartCustomer)
|
||||
expect(currentCart.data.cart.customer_id).not.toEqual(
|
||||
originalCartCustomer.id
|
||||
)
|
||||
expect(customerData.email).toEqual(currentCart.data.cart.email)
|
||||
expect(currentCart.data.cart.email).toEqual("foo@bar.com")
|
||||
expect(currentCart.data.cart.metadata).toEqual({
|
||||
test: "test updated 2, new customer",
|
||||
})
|
||||
})
|
||||
|
||||
it("should keep the same customer when updating the customer cart and update Cart's email if provided", async () => {
|
||||
// create a customer
|
||||
const mainEmail = "jhon.doe@acme.com"
|
||||
await customerModule.createCustomers({
|
||||
email: mainEmail,
|
||||
has_account: true,
|
||||
})
|
||||
|
||||
const cart = (
|
||||
await api.post(
|
||||
`/store/carts`,
|
||||
{
|
||||
currency_code: "usd",
|
||||
email: mainEmail,
|
||||
shipping_address: {
|
||||
address_1: "test address 1",
|
||||
address_2: "test address 2",
|
||||
city: "ny",
|
||||
country_code: "us",
|
||||
province: "ny",
|
||||
postal_code: "94016",
|
||||
},
|
||||
sales_channel_id: salesChannel.id,
|
||||
},
|
||||
storeHeaders
|
||||
)
|
||||
).data.cart
|
||||
|
||||
const originalCartCustomer = cart.customer
|
||||
|
||||
// update the cart without providing an email
|
||||
await api.post(
|
||||
`/store/carts/${cart.id}`,
|
||||
{
|
||||
metadata: {
|
||||
test: "test updated",
|
||||
},
|
||||
},
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
let currentCart = await api.get(
|
||||
`/store/carts/${cart.id}`,
|
||||
storeHeaders
|
||||
)
|
||||
let currentCartCustomer = currentCart.data.cart.customer
|
||||
|
||||
let customerData = (
|
||||
await api.get(
|
||||
`/admin/customers/${currentCart.data.cart.customer_id}`,
|
||||
adminHeaders
|
||||
)
|
||||
).data.customer
|
||||
|
||||
expect(currentCartCustomer).toEqual(originalCartCustomer)
|
||||
expect(customerData.email).toEqual(currentCart.data.cart.email)
|
||||
expect(currentCart.data.cart.email).toEqual(mainEmail)
|
||||
expect(currentCart.data.cart.metadata).toEqual({
|
||||
test: "test updated",
|
||||
})
|
||||
|
||||
// update the cart providing an email
|
||||
await api.post(
|
||||
`/store/carts/${cart.id}`,
|
||||
{
|
||||
email: "foo@bar.com",
|
||||
metadata: {
|
||||
test: "test updated 2, new customer",
|
||||
},
|
||||
},
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
currentCart = await api.get(`/store/carts/${cart.id}`, storeHeaders)
|
||||
|
||||
customerData = (
|
||||
await api.get(
|
||||
`/admin/customers/${currentCart.data.cart.customer_id}`,
|
||||
adminHeaders
|
||||
)
|
||||
).data.customer
|
||||
|
||||
currentCartCustomer = currentCart.data.cart.customer
|
||||
|
||||
expect(currentCartCustomer).toEqual(originalCartCustomer)
|
||||
expect(currentCart.data.cart.customer_id).toEqual(
|
||||
originalCartCustomer.id
|
||||
)
|
||||
expect(customerData.email).not.toEqual(currentCart.data.cart.email)
|
||||
expect(customerData.email).toEqual(mainEmail)
|
||||
expect(currentCart.data.cart.email).toEqual("foo@bar.com")
|
||||
expect(currentCart.data.cart.metadata).toEqual({
|
||||
test: "test updated 2, new customer",
|
||||
})
|
||||
})
|
||||
|
||||
it("should return order when cart is already completed", async () => {
|
||||
const cart = (
|
||||
await api.post(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CustomerDTO, ICustomerModuleService } from "@medusajs/framework/types"
|
||||
import { Modules, validateEmail } from "@medusajs/framework/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
|
||||
import { isDefined, Modules, validateEmail } from "@medusajs/framework/utils"
|
||||
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export interface FindOrCreateCustomerStepInput {
|
||||
customerId?: string | null
|
||||
@@ -21,20 +21,20 @@ export const findOrCreateCustomerStepId = "find-or-create-customer"
|
||||
/**
|
||||
* This step either finds a customer matching the specified ID, or finds / create a customer
|
||||
* matching the specified email. If both ID and email are provided, ID takes precedence.
|
||||
* If the customer is a guest, the email is updated to the provided email.
|
||||
*/
|
||||
export const findOrCreateCustomerStep = createStep(
|
||||
findOrCreateCustomerStepId,
|
||||
async (data: FindOrCreateCustomerStepInput, { container }) => {
|
||||
if (
|
||||
typeof data.customerId === undefined &&
|
||||
typeof data.email === undefined
|
||||
) {
|
||||
if (!isDefined(data.customerId) && !isDefined(data.email)) {
|
||||
return new StepResponse(
|
||||
{
|
||||
customer: undefined,
|
||||
email: undefined,
|
||||
},
|
||||
{ customerWasCreated: false }
|
||||
{
|
||||
customerWasCreated: false,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -44,37 +44,50 @@ export const findOrCreateCustomerStep = createStep(
|
||||
customer: null,
|
||||
email: null,
|
||||
}
|
||||
let originalCustomer: CustomerDTO | null = null
|
||||
let customerWasCreated = false
|
||||
|
||||
if (data.customerId) {
|
||||
const customer = await service.retrieveCustomer(data.customerId)
|
||||
customerData.customer = customer
|
||||
customerData.email = customer.email
|
||||
|
||||
return new StepResponse(customerData, {
|
||||
customerWasCreated,
|
||||
})
|
||||
originalCustomer = await service.retrieveCustomer(data.customerId)
|
||||
customerData.customer = originalCustomer
|
||||
customerData.email = originalCustomer.email
|
||||
}
|
||||
|
||||
if (data.email) {
|
||||
const validatedEmail = validateEmail(data.email)
|
||||
const validatedEmail = (data.email && validateEmail(data.email)) as string
|
||||
|
||||
let [customer] = await service.listCustomers({
|
||||
email: validatedEmail,
|
||||
has_account: false,
|
||||
})
|
||||
let [customer] = originalCustomer
|
||||
? [originalCustomer]
|
||||
: await service.listCustomers({
|
||||
email: validatedEmail,
|
||||
})
|
||||
|
||||
if (!customer) {
|
||||
// if NOT a guest customer, return it
|
||||
if (customer?.has_account) {
|
||||
customerData.customer = customer
|
||||
customerData.email = customer.email
|
||||
|
||||
return new StepResponse(customerData, {
|
||||
customerWasCreated,
|
||||
})
|
||||
}
|
||||
|
||||
if (
|
||||
!customer ||
|
||||
(isDefined(data.email) && customer.email !== validatedEmail)
|
||||
) {
|
||||
customer = await service.createCustomers({ email: validatedEmail })
|
||||
customerWasCreated = true
|
||||
}
|
||||
|
||||
originalCustomer = customer
|
||||
|
||||
customerData.customer = customer
|
||||
customerData.email = customer.email
|
||||
}
|
||||
|
||||
return new StepResponse(customerData, {
|
||||
customer: customerData.customer,
|
||||
customer: originalCustomer,
|
||||
customerWasCreated,
|
||||
})
|
||||
},
|
||||
|
||||
@@ -34,18 +34,32 @@ export const updateCartWorkflow = createWorkflow(
|
||||
const cartToUpdate = useRemoteQueryStep({
|
||||
entry_point: "cart",
|
||||
variables: { id: input.id },
|
||||
fields: ["id", "shipping_address.*", "region.*", "region.countries.*"],
|
||||
fields: [
|
||||
"id",
|
||||
"email",
|
||||
"customer_id",
|
||||
"shipping_address.*",
|
||||
"region.*",
|
||||
"region.countries.*",
|
||||
],
|
||||
list: false,
|
||||
throw_if_key_not_found: true,
|
||||
}).config({ name: "get-cart" })
|
||||
|
||||
const [salesChannel, customerData] = parallelize(
|
||||
const customerDataInput = transform({ input, cartToUpdate }, (data) => {
|
||||
return {
|
||||
customer_id: data.cartToUpdate.customer_id,
|
||||
email: data.input.email ?? data.cartToUpdate.email,
|
||||
}
|
||||
})
|
||||
|
||||
const [salesChannel, customer] = parallelize(
|
||||
findSalesChannelStep({
|
||||
salesChannelId: input.sales_channel_id,
|
||||
}),
|
||||
findOrCreateCustomerStep({
|
||||
customerId: input.customer_id,
|
||||
email: input.email,
|
||||
customerId: customerDataInput.customer_id,
|
||||
email: customerDataInput.email,
|
||||
})
|
||||
)
|
||||
|
||||
@@ -66,7 +80,13 @@ export const updateCartWorkflow = createWorkflow(
|
||||
})
|
||||
|
||||
const cartInput = transform(
|
||||
{ input, region, customerData, salesChannel, cartToUpdate },
|
||||
{
|
||||
input,
|
||||
region,
|
||||
customer,
|
||||
salesChannel,
|
||||
cartToUpdate,
|
||||
},
|
||||
(data) => {
|
||||
const {
|
||||
promo_codes,
|
||||
@@ -116,13 +136,16 @@ export const updateCartWorkflow = createWorkflow(
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(updateCartData.customer_id) ||
|
||||
isDefined(updateCartData.email)
|
||||
) {
|
||||
data_.customer_id = data.customerData.customer?.id || null
|
||||
data_.email =
|
||||
data.input?.email ?? (data.customerData.customer?.email || null)
|
||||
if (isDefined(updateCartData.email) && data.customer?.customer) {
|
||||
const currentCustomer = data.customer.customer!
|
||||
data_.customer_id = currentCustomer.id
|
||||
|
||||
// registered customers can update the cart email
|
||||
if (currentCustomer.has_account) {
|
||||
data_.email = updateCartData.email
|
||||
} else {
|
||||
data_.email = data.customer.email
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(updateCartData.sales_channel_id)) {
|
||||
@@ -133,6 +156,7 @@ export const updateCartWorkflow = createWorkflow(
|
||||
}
|
||||
)
|
||||
|
||||
/*
|
||||
when({ cartInput }, ({ cartInput }) => {
|
||||
return isDefined(cartInput.customer_id) || isDefined(cartInput.email)
|
||||
}).then(() => {
|
||||
@@ -141,6 +165,7 @@ export const updateCartWorkflow = createWorkflow(
|
||||
data: { id: input.id },
|
||||
}).config({ name: "emit-customer-updated" })
|
||||
})
|
||||
*/
|
||||
|
||||
when({ input, cartToUpdate }, ({ input, cartToUpdate }) => {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user