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:
1 parent
6e775a2e04
commit
1bae311a29
4 files changed
+262
-33
No files matched your search
@@ -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 () => {
|
it("should return order when cart is already completed", async () => {
|
||||||
const cart = (
|
const cart = (
|
||||||
await api.post(
|
await api.post(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { CustomerDTO, ICustomerModuleService } from "@medusajs/framework/types"
|
import { CustomerDTO, ICustomerModuleService } from "@medusajs/framework/types"
|
||||||
import { Modules, validateEmail } from "@medusajs/framework/utils"
|
import { isDefined, Modules, validateEmail } from "@medusajs/framework/utils"
|
||||||
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
|
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
|
||||||
|
|
||||||
export interface FindOrCreateCustomerStepInput {
|
export interface FindOrCreateCustomerStepInput {
|
||||||
customerId?: string | null
|
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
|
* 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.
|
* 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(
|
export const findOrCreateCustomerStep = createStep(
|
||||||
findOrCreateCustomerStepId,
|
findOrCreateCustomerStepId,
|
||||||
async (data: FindOrCreateCustomerStepInput, { container }) => {
|
async (data: FindOrCreateCustomerStepInput, { container }) => {
|
||||||
if (
|
if (!isDefined(data.customerId) && !isDefined(data.email)) {
|
||||||
typeof data.customerId === undefined &&
|
|
||||||
typeof data.email === undefined
|
|
||||||
) {
|
|
||||||
return new StepResponse(
|
return new StepResponse(
|
||||||
{
|
{
|
||||||
customer: undefined,
|
customer: undefined,
|
||||||
email: undefined,
|
email: undefined,
|
||||||
},
|
},
|
||||||
{ customerWasCreated: false }
|
{
|
||||||
|
customerWasCreated: false,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,37 +44,50 @@ export const findOrCreateCustomerStep = createStep(
|
|||||||
customer: null,
|
customer: null,
|
||||||
email: null,
|
email: null,
|
||||||
}
|
}
|
||||||
|
let originalCustomer: CustomerDTO | null = null
|
||||||
let customerWasCreated = false
|
let customerWasCreated = false
|
||||||
|
|
||||||
if (data.customerId) {
|
if (data.customerId) {
|
||||||
const customer = await service.retrieveCustomer(data.customerId)
|
originalCustomer = await service.retrieveCustomer(data.customerId)
|
||||||
customerData.customer = customer
|
customerData.customer = originalCustomer
|
||||||
customerData.email = customer.email
|
customerData.email = originalCustomer.email
|
||||||
|
|
||||||
return new StepResponse(customerData, {
|
|
||||||
customerWasCreated,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.email) {
|
if (data.email) {
|
||||||
const validatedEmail = validateEmail(data.email)
|
const validatedEmail = (data.email && validateEmail(data.email)) as string
|
||||||
|
|
||||||
let [customer] = await service.listCustomers({
|
let [customer] = originalCustomer
|
||||||
email: validatedEmail,
|
? [originalCustomer]
|
||||||
has_account: false,
|
: 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 })
|
customer = await service.createCustomers({ email: validatedEmail })
|
||||||
customerWasCreated = true
|
customerWasCreated = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
originalCustomer = customer
|
||||||
|
|
||||||
customerData.customer = customer
|
customerData.customer = customer
|
||||||
customerData.email = customer.email
|
customerData.email = customer.email
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StepResponse(customerData, {
|
return new StepResponse(customerData, {
|
||||||
customer: customerData.customer,
|
customer: originalCustomer,
|
||||||
customerWasCreated,
|
customerWasCreated,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -34,18 +34,32 @@ export const updateCartWorkflow = createWorkflow(
|
|||||||
const cartToUpdate = useRemoteQueryStep({
|
const cartToUpdate = useRemoteQueryStep({
|
||||||
entry_point: "cart",
|
entry_point: "cart",
|
||||||
variables: { id: input.id },
|
variables: { id: input.id },
|
||||||
fields: ["id", "shipping_address.*", "region.*", "region.countries.*"],
|
fields: [
|
||||||
|
"id",
|
||||||
|
"email",
|
||||||
|
"customer_id",
|
||||||
|
"shipping_address.*",
|
||||||
|
"region.*",
|
||||||
|
"region.countries.*",
|
||||||
|
],
|
||||||
list: false,
|
list: false,
|
||||||
throw_if_key_not_found: true,
|
throw_if_key_not_found: true,
|
||||||
}).config({ name: "get-cart" })
|
}).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({
|
findSalesChannelStep({
|
||||||
salesChannelId: input.sales_channel_id,
|
salesChannelId: input.sales_channel_id,
|
||||||
}),
|
}),
|
||||||
findOrCreateCustomerStep({
|
findOrCreateCustomerStep({
|
||||||
customerId: input.customer_id,
|
customerId: customerDataInput.customer_id,
|
||||||
email: input.email,
|
email: customerDataInput.email,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -66,7 +80,13 @@ export const updateCartWorkflow = createWorkflow(
|
|||||||
})
|
})
|
||||||
|
|
||||||
const cartInput = transform(
|
const cartInput = transform(
|
||||||
{ input, region, customerData, salesChannel, cartToUpdate },
|
{
|
||||||
|
input,
|
||||||
|
region,
|
||||||
|
customer,
|
||||||
|
salesChannel,
|
||||||
|
cartToUpdate,
|
||||||
|
},
|
||||||
(data) => {
|
(data) => {
|
||||||
const {
|
const {
|
||||||
promo_codes,
|
promo_codes,
|
||||||
@@ -116,13 +136,16 @@ export const updateCartWorkflow = createWorkflow(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (isDefined(updateCartData.email) && data.customer?.customer) {
|
||||||
isDefined(updateCartData.customer_id) ||
|
const currentCustomer = data.customer.customer!
|
||||||
isDefined(updateCartData.email)
|
data_.customer_id = currentCustomer.id
|
||||||
) {
|
|
||||||
data_.customer_id = data.customerData.customer?.id || null
|
// registered customers can update the cart email
|
||||||
data_.email =
|
if (currentCustomer.has_account) {
|
||||||
data.input?.email ?? (data.customerData.customer?.email || null)
|
data_.email = updateCartData.email
|
||||||
|
} else {
|
||||||
|
data_.email = data.customer.email
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDefined(updateCartData.sales_channel_id)) {
|
if (isDefined(updateCartData.sales_channel_id)) {
|
||||||
@@ -133,6 +156,7 @@ export const updateCartWorkflow = createWorkflow(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
when({ cartInput }, ({ cartInput }) => {
|
when({ cartInput }, ({ cartInput }) => {
|
||||||
return isDefined(cartInput.customer_id) || isDefined(cartInput.email)
|
return isDefined(cartInput.customer_id) || isDefined(cartInput.email)
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@@ -141,6 +165,7 @@ export const updateCartWorkflow = createWorkflow(
|
|||||||
data: { id: input.id },
|
data: { id: input.id },
|
||||||
}).config({ name: "emit-customer-updated" })
|
}).config({ name: "emit-customer-updated" })
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
when({ input, cartToUpdate }, ({ input, cartToUpdate }) => {
|
when({ input, cartToUpdate }, ({ input, cartToUpdate }) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in new issue
Block a user