feat(customers): add delete and update (#6148)

Depends on #6137 

**What**
- Add update and delete methods to the customer module
This commit is contained in:
Sebastian Rindom
2024-01-22 13:31:46 +01:00
committed by GitHub
parent da5cc4cf7f
commit 76291823f4
5 changed files with 245 additions and 25 deletions

View File

@@ -309,4 +309,104 @@ describe("Customer Module Service", () => {
}
})
})
describe("update", () => {
it("should update a single customer", async () => {
const [customer] = await service.create([
{ first_name: "John", last_name: "Doe", email: "john.doe@example.com" },
])
const updateData = { first_name: "Jonathan" }
const updatedCustomer = await service.update(customer.id, updateData)
expect(updatedCustomer).toEqual(
expect.objectContaining({ id: customer.id, first_name: "Jonathan" })
)
})
it("should update multiple customers by IDs", async () => {
const customers = await service.create([
{ first_name: "John", last_name: "Doe", email: "john.doe@example.com" },
{
first_name: "Jane",
last_name: "Smith",
email: "jane.smith@example.com",
},
])
const updateData = { last_name: "Updated" }
const customerIds = customers.map((customer) => customer.id)
const updatedCustomers = await service.update(customerIds, updateData)
updatedCustomers.forEach((updatedCustomer) => {
expect(updatedCustomer).toEqual(
expect.objectContaining({ last_name: "Updated" })
)
})
})
it("should update customers using a selector", async () => {
await service.create([
{ first_name: "John", last_name: "Doe", email: "john.doe@example.com" },
{ first_name: "Jane", last_name: "Doe", email: "jane.doe@example.com" },
])
const selector = { last_name: "Doe" }
const updateData = { last_name: "Updated" }
const updatedCustomers = await service.update(selector, updateData)
updatedCustomers.forEach((updatedCustomer) => {
expect(updatedCustomer).toEqual(
expect.objectContaining({ last_name: "Updated" })
)
})
})
})
describe("delete", () => {
it("should delete a single customer", async () => {
const [customer] = await service.create([
{ first_name: "John", last_name: "Doe", email: "john.doe@example.com" },
])
await service.delete(customer.id)
await expect(service.retrieve(customer.id)).rejects.toThrow(
`Customer with id: ${customer.id} was not found`
)
})
it("should delete multiple customers by IDs", async () => {
const customers = await service.create([
{ first_name: "John", last_name: "Doe", email: "john.doe@example.com" },
{
first_name: "Jane",
last_name: "Smith",
email: "jane.smith@example.com",
},
])
const customerIds = customers.map((customer) => customer.id)
await service.delete(customerIds)
for (const customer of customers) {
await expect(service.retrieve(customer.id)).rejects.toThrow(
`Customer with id: ${customer.id} was not found`
)
}
})
it("should delete customers using a selector", async () => {
await service.create([
{ first_name: "John", last_name: "Doe", email: "john.doe@example.com" },
{ first_name: "Jane", last_name: "Doe", email: "jane.doe@example.com" },
])
const selector = { last_name: "Doe" }
await service.delete(selector)
const remainingCustomers = await service.list({ last_name: "Doe" })
expect(remainingCustomers.length).toBe(0)
})
})
})

View File

@@ -12,6 +12,8 @@ import {
InjectManager,
InjectTransactionManager,
MedusaContext,
isString,
isObject,
} from "@medusajs/utils"
import { joinerConfig } from "../joiner-config"
import * as services from "../services"
@@ -91,22 +93,101 @@ export default class CustomerModuleService implements ICustomerModuleService {
) {
const data = Array.isArray(dataOrArray) ? dataOrArray : [dataOrArray]
const customer = await this.customerService_.create(data, sharedContext)
const serialized = await this.baseRepository_.serialize<
CustomerTypes.CustomerDTO[]
>(customer, {
populate: true,
})
return Array.isArray(dataOrArray) ? serialized : serialized[0]
}
if (Array.isArray(dataOrArray)) {
return await this.baseRepository_.serialize<CustomerTypes.CustomerDTO[]>(
customer,
update(
customerId: string,
data: Partial<CustomerTypes.CreateCustomerDTO>,
sharedContext?: Context
): Promise<CustomerTypes.CustomerDTO>
update(
customerIds: string[],
data: Partial<CustomerTypes.CreateCustomerDTO>,
sharedContext?: Context
): Promise<CustomerTypes.CustomerDTO[]>
update(
selector: CustomerTypes.FilterableCustomerProps,
data: Partial<CustomerTypes.CreateCustomerDTO>,
sharedContext?: Context
): Promise<CustomerTypes.CustomerDTO[]>
@InjectTransactionManager("baseRepository_")
async update(
idsOrSelector: string | string[] | CustomerTypes.FilterableCustomerProps,
data: Partial<CustomerTypes.CreateCustomerDTO>,
@MedusaContext() sharedContext: Context = {}
) {
let updateData: CustomerTypes.UpdateCustomerDTO[] = []
if (typeof idsOrSelector === "string") {
updateData = [
{
populate: true,
}
id: idsOrSelector,
...data,
},
]
} else if (Array.isArray(idsOrSelector)) {
updateData = idsOrSelector.map((id) => ({
id,
...data,
}))
} else {
const ids = await this.customerService_.list(
idsOrSelector,
{ select: ["id"] },
sharedContext
)
updateData = ids.map(({ id }) => ({
id,
...data,
}))
}
return await this.baseRepository_.serialize<CustomerTypes.CustomerDTO>(
customer[0],
{
populate: true,
}
const customers = await this.customerService_.update(
updateData,
sharedContext
)
const serialized = await this.baseRepository_.serialize<
CustomerTypes.CustomerDTO[]
>(customers, {
populate: true,
})
return isString(idsOrSelector) ? serialized[0] : serialized
}
delete(customerId: string, sharedContext?: Context): Promise<void>
delete(customerIds: string[], sharedContext?: Context): Promise<void>
delete(
selector: CustomerTypes.FilterableCustomerProps,
sharedContext?: Context
): Promise<void>
@InjectTransactionManager("baseRepository_")
async delete(
idsOrSelector: string | string[] | CustomerTypes.FilterableCustomerProps,
@MedusaContext() sharedContext: Context = {}
) {
let toDelete = Array.isArray(idsOrSelector)
? idsOrSelector
: [idsOrSelector as string]
if (isObject(idsOrSelector)) {
const ids = await this.customerService_.list(
idsOrSelector,
{
select: ["id"],
},
sharedContext
)
toDelete = ids.map(({ id }) => id)
}
return await this.customerService_.delete(toDelete, sharedContext)
}
@InjectManager("baseRepository_")
@@ -174,19 +255,13 @@ export default class CustomerModuleService implements ICustomerModuleService {
: [dataOrArrayOfData]
const groups = await this.customerGroupService_.create(data, sharedContext)
const serialized = await this.baseRepository_.serialize<
CustomerTypes.CustomerGroupDTO[]
>(groups, {
populate: true,
})
if (Array.isArray(dataOrArrayOfData)) {
return await this.baseRepository_.serialize<
CustomerTypes.CustomerGroupDTO[]
>(groups, {
populate: true,
})
}
return await this.baseRepository_.serialize<CustomerTypes.CustomerGroupDTO>(
groups[0],
{ populate: true }
)
return Array.isArray(dataOrArrayOfData) ? serialized : serialized[0]
}
async addCustomerToGroup(

View File

@@ -1,16 +1,19 @@
import { CreateCustomerDTO, DAL } from "@medusajs/types"
import { CustomerTypes, DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { Customer } from "@models"
type InjectedDependencies = {
cartRepository: DAL.RepositoryService
customerRepository: DAL.RepositoryService
}
export default class CustomerService<
TEntity extends Customer = Customer
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{ create: CreateCustomerDTO }
{
create: CustomerTypes.CreateCustomerDTO
update: CustomerTypes.UpdateCustomerDTO
}
>(Customer)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore

View File

@@ -9,6 +9,7 @@ export interface CreateCustomerDTO {
}
export interface UpdateCustomerDTO {
id: string
company_name?: string
first_name?: string
last_name?: string
@@ -28,6 +29,24 @@ export interface CustomerGroupUpdatableFileds {
metadata?: Record<string, unknown> | null
}
export interface UpdateCustomerGroupDTO {
id?: string
name?: string
customer_ids?: string[]
metadata?: Record<string, unknown> | null
}
export interface CreateCustomerGroupDTO {
name: string
metadata?: Record<string, unknown> | null
created_by?: string
}
export interface CustomerGroupUpdatableFileds {
name?: string
metadata?: Record<string, unknown> | null
}
export interface UpdateCustomerGroupDTO {
id?: string
name?: string

View File

@@ -24,6 +24,29 @@ export interface ICustomerModuleService extends IModuleService {
create(data: CreateCustomerDTO, sharedContext?: Context): Promise<CustomerDTO>
update(
customerId: string,
data: Partial<CreateCustomerDTO>,
sharedContext?: Context
): Promise<CustomerDTO>
update(
customerIds: string[],
data: Partial<CreateCustomerDTO>,
sharedContext?: Context
): Promise<CustomerDTO[]>
update(
selector: FilterableCustomerProps,
data: Partial<CreateCustomerDTO>,
sharedContext?: Context
): Promise<CustomerDTO[]>
delete(customerId: string, sharedContext?: Context): Promise<void>
delete(customerIds: string[], sharedContext?: Context): Promise<void>
delete(
selector: FilterableCustomerProps,
sharedContext?: Context
): Promise<void>
createCustomerGroup(
data: CreateCustomerGroupDTO[],
sharedContext?: Context