Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(customer): manage default address selection #6295

Merged
merged 4 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,76 @@ describe("POST /admin/customers/:id/addresses", () => {

expect(customerWithAddresses.addresses?.length).toEqual(1)
})

it("sets new shipping address as default and unsets the old one", async () => {
const customer = await customerModuleService.create({
first_name: "John",
last_name: "Doe",
addresses: [
{
first_name: "John",
last_name: "Doe",
address_1: "Test street 1",
is_default_shipping: true,
},
],
})

const api = useApi() as any
const response = await api.post(
`/admin/customers/${customer.id}/addresses`,
{
first_name: "John",
last_name: "Doe",
address_1: "Test street 2",
is_default_shipping: true,
},
adminHeaders
)

expect(response.status).toEqual(200)

const [address] = await customerModuleService.listAddresses({
customer_id: customer.id,
is_default_shipping: true,
})

expect(address.address_1).toEqual("Test street 2")
})

it("sets new billing address as default and unsets the old one", async () => {
const customer = await customerModuleService.create({
first_name: "John",
last_name: "Doe",
addresses: [
{
first_name: "John",
last_name: "Doe",
address_1: "Test street 1",
is_default_billing: true,
},
],
})

const api = useApi() as any
const response = await api.post(
`/admin/customers/${customer.id}/addresses`,
{
first_name: "John",
last_name: "Doe",
address_1: "Test street 2",
is_default_billing: true,
},
adminHeaders
)

expect(response.status).toEqual(200)

const [address] = await customerModuleService.listAddresses({
customer_id: customer.id,
is_default_billing: true,
})

expect(address.address_1).toEqual("Test street 2")
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,89 @@ describe("POST /admin/customers/:id/addresses/:address_id", () => {
})
)
})

it("updates a new address to be default and unsets old one", async () => {
const customer = await customerModuleService.create({
first_name: "John",
last_name: "Doe",
})
const [, address] = await customerModuleService.addAddresses([
{
customer_id: customer.id,
first_name: "John",
last_name: "Doe",
address_1: "Test street 1",
is_default_shipping: true,
},
{
customer_id: customer.id,
first_name: "John",
last_name: "Doe",
address_1: "Test street 2",
},
])

const api = useApi() as any
const response = await api.post(
`/admin/customers/${customer.id}/addresses/${address.id}`,
{
first_name: "jane",
is_default_shipping: true,
},
adminHeaders
)

expect(response.status).toEqual(200)

const [defaultAddress] = await customerModuleService.listAddresses({
customer_id: customer.id,
is_default_shipping: true,
})

expect(defaultAddress.first_name).toEqual("jane")
expect(defaultAddress.address_1).toEqual("Test street 2")
})

// do the same as above but for billing address
it("updates a new address to be default and unsets old one", async () => {
const customer = await customerModuleService.create({
first_name: "John",
last_name: "Doe",
})
const [, address] = await customerModuleService.addAddresses([
{
customer_id: customer.id,
first_name: "John",
last_name: "Doe",
address_1: "Test street 1",
is_default_billing: true,
},
{
customer_id: customer.id,
first_name: "John",
last_name: "Doe",
address_1: "Test street 2",
},
])

const api = useApi() as any
const response = await api.post(
`/admin/customers/${customer.id}/addresses/${address.id}`,
{
first_name: "jane",
is_default_billing: true,
},
adminHeaders
)

expect(response.status).toEqual(200)

const [defaultAddress] = await customerModuleService.listAddresses({
customer_id: customer.id,
is_default_billing: true,
})

expect(defaultAddress.first_name).toEqual("jane")
expect(defaultAddress.address_1).toEqual("Test street 2")
})
})
2 changes: 2 additions & 0 deletions packages/core-flows/src/customer/steps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export * from "./delete-customers"
export * from "./create-addresses"
export * from "./update-addresses"
export * from "./delete-addresses"
export * from "./maybe-unset-default-billing-addresses"
export * from "./maybe-unset-default-shipping-addresses"
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {
ICustomerModuleService,
CreateCustomerAddressDTO,
FilterableCustomerAddressProps,
CustomerAddressDTO,
} from "@medusajs/types"
import { createStep } from "@medusajs/workflows-sdk"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { unsetForUpdate, unsetForCreate } from "./utils"
import { isDefined } from "@medusajs/utils"

type StepInput = {
create?: CreateCustomerAddressDTO[]
update?: {
selector: FilterableCustomerAddressProps
update: Partial<CustomerAddressDTO>
}
}

export const maybeUnsetDefaultBillingAddressesStepId =
"maybe-unset-default-billing-customer-addresses"
export const maybeUnsetDefaultBillingAddressesStep = createStep(
maybeUnsetDefaultBillingAddressesStepId,
async (data: StepInput, { container }) => {
const customerModuleService = container.resolve<ICustomerModuleService>(
ModuleRegistrationName.CUSTOMER
)

if (isDefined(data.create)) {
return unsetForCreate(
data.create,
customerModuleService,
"is_default_billing"
)
}

if (isDefined(data.update)) {
return unsetForUpdate(
data.update,
customerModuleService,
"is_default_billing"
)
}

throw new Error("Invalid step input")
},
async (addressesToSet, { container }) => {
if (!addressesToSet?.length) {
return
}

const customerModuleService = container.resolve<ICustomerModuleService>(
ModuleRegistrationName.CUSTOMER
)

await customerModuleService.updateAddress(
{ id: addressesToSet },
{ is_default_billing: true }
)
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {
ICustomerModuleService,
CreateCustomerAddressDTO,
FilterableCustomerAddressProps,
CustomerAddressDTO,
} from "@medusajs/types"
import { createStep } from "@medusajs/workflows-sdk"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { unsetForUpdate, unsetForCreate } from "./utils"
import { isDefined } from "@medusajs/utils"

type StepInput = {
create?: CreateCustomerAddressDTO[]
update?: {
selector: FilterableCustomerAddressProps
update: Partial<CustomerAddressDTO>
}
}

export const maybeUnsetDefaultShippingAddressesStepId =
"maybe-unset-default-shipping-customer-addresses"
export const maybeUnsetDefaultShippingAddressesStep = createStep(
maybeUnsetDefaultShippingAddressesStepId,
async (data: StepInput, { container }) => {
const customerModuleService = container.resolve<ICustomerModuleService>(
ModuleRegistrationName.CUSTOMER
)
if (isDefined(data.create)) {
return unsetForCreate(
data.create,
customerModuleService,
"is_default_shipping"
)
}

if (isDefined(data.update)) {
return unsetForUpdate(
data.update,
customerModuleService,
"is_default_shipping"
)
}

throw new Error("Invalid step input")
},
async (addressesToSet, { container }) => {
if (!addressesToSet?.length) {
return
}

const customerModuleService = container.resolve<ICustomerModuleService>(
ModuleRegistrationName.CUSTOMER
)

await customerModuleService.updateAddress(
{ id: addressesToSet },
{ is_default_shipping: true }
)
}
)
2 changes: 2 additions & 0 deletions packages/core-flows/src/customer/steps/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./unset-address-for-create"
export * from "./unset-address-for-update"
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
CreateCustomerAddressDTO,
ICustomerModuleService,
} from "@medusajs/types"
import { StepResponse } from "@medusajs/workflows-sdk"

export const unsetForCreate = async (
data: CreateCustomerAddressDTO[],
customerService: ICustomerModuleService,
field: "is_default_billing" | "is_default_shipping"
) => {
const customerIds = data.reduce<string[]>((acc, curr) => {
if (curr[field]) {
acc.push(curr.customer_id)
}
return acc
}, [])

const customerDefaultAddresses = await customerService.listAddresses({
customer_id: customerIds,
[field]: true,
})

await customerService.updateAddress(
{ customer_id: customerIds, [field]: true },
{ [field]: false }
)

return new StepResponse(
void 0,
customerDefaultAddresses.map((address) => address.id)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
CustomerAddressDTO,
FilterableCustomerAddressProps,
ICustomerModuleService,
} from "@medusajs/types"
import { StepResponse } from "@medusajs/workflows-sdk"

export const unsetForUpdate = async (
data: {
selector: FilterableCustomerAddressProps
update: Partial<CustomerAddressDTO>
},
customerService: ICustomerModuleService,
field: "is_default_billing" | "is_default_shipping"
) => {
if (!data.update[field]) {
return new StepResponse(void 0)
}

const affectedCustomers = await customerService.listAddresses(data.selector, {
select: ["id", "customer_id"],
})

const customerIds = affectedCustomers.map((address) => address.customer_id)

const customerDefaultAddresses = await customerService.listAddresses({
customer_id: customerIds,
[field]: true,
})

await customerService.updateAddress(
{ customer_id: customerIds, [field]: true },
{ [field]: false }
)

return new StepResponse(
void 0,
customerDefaultAddresses.map((address) => address.id)
)
}
Loading
Loading