feat(customer): Introduce customer group (#6137)
**What** Methods for: - Bulk create customers - Bulk and single create of customer groups - Assigning customer <> group relationships - listing of customers and customer groups ++ Uses new repository loading mechanism
This commit is contained in:
+275
-4
@@ -23,19 +23,290 @@ describe("Customer Module Service", () => {
|
||||
})
|
||||
|
||||
describe("create", () => {
|
||||
it("should create a customer", async () => {
|
||||
const customerPromise = service.create({
|
||||
it("should create a single customer", async () => {
|
||||
const customerData = {
|
||||
company_name: "Acme Corp",
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
})
|
||||
email: "john.doe@acmecorp.com",
|
||||
phone: "123456789",
|
||||
created_by: "admin",
|
||||
metadata: { membership: "gold" },
|
||||
}
|
||||
const customer = await service.create(customerData)
|
||||
|
||||
await expect(customerPromise).resolves.toEqual(
|
||||
expect(customer).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
company_name: "Acme Corp",
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john.doe@acmecorp.com",
|
||||
phone: "123456789",
|
||||
created_by: "admin",
|
||||
metadata: expect.objectContaining({ membership: "gold" }),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create multiple customers", async () => {
|
||||
const customersData = [
|
||||
{
|
||||
company_name: "Acme Corp",
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john.doe@acmecorp.com",
|
||||
phone: "123456789",
|
||||
created_by: "admin",
|
||||
metadata: { membership: "gold" },
|
||||
},
|
||||
{
|
||||
first_name: "Jane",
|
||||
last_name: "Smith",
|
||||
email: "jane.smith@example.com",
|
||||
phone: "987654321",
|
||||
metadata: { membership: "silver" },
|
||||
},
|
||||
]
|
||||
const customer = await service.create(customersData)
|
||||
|
||||
expect(customer).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
company_name: "Acme Corp",
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john.doe@acmecorp.com",
|
||||
phone: "123456789",
|
||||
created_by: "admin",
|
||||
metadata: expect.objectContaining({ membership: "gold" }),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
first_name: "Jane",
|
||||
last_name: "Smith",
|
||||
email: "jane.smith@example.com",
|
||||
phone: "987654321",
|
||||
metadata: expect.objectContaining({ membership: "silver" }),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("createCustomerGroup", () => {
|
||||
it("should create a single customer group", async () => {
|
||||
const group = await service.createCustomerGroup({
|
||||
name: "VIP Customers",
|
||||
metadata: { priority: "high" },
|
||||
created_by: "admin",
|
||||
})
|
||||
|
||||
expect(group).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "VIP Customers",
|
||||
metadata: expect.objectContaining({ priority: "high" }),
|
||||
created_by: "admin",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should create multiple customer groups", async () => {
|
||||
const groups = await service.createCustomerGroup([
|
||||
{
|
||||
name: "VIP Customers",
|
||||
metadata: { priority: "high" },
|
||||
created_by: "admin",
|
||||
},
|
||||
{
|
||||
name: "Regular Customers",
|
||||
metadata: { discount: "10%" },
|
||||
created_by: "staff",
|
||||
},
|
||||
])
|
||||
|
||||
expect(groups).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "VIP Customers",
|
||||
metadata: expect.objectContaining({ priority: "high" }),
|
||||
created_by: "admin",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
name: "Regular Customers",
|
||||
metadata: expect.objectContaining({ discount: "10%" }),
|
||||
created_by: "staff",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("list", () => {
|
||||
it("should list all customers when no filters are applied", async () => {
|
||||
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 customers = await service.list()
|
||||
|
||||
expect(customers.length).toBeGreaterThanOrEqual(2)
|
||||
expect(customers).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john.doe@example.com",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
first_name: "Jane",
|
||||
last_name: "Smith",
|
||||
email: "jane.smith@example.com",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should list customers filtered by a specific email", async () => {
|
||||
await service.create([
|
||||
{
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "unique.email@example.com",
|
||||
},
|
||||
{
|
||||
first_name: "Jane",
|
||||
last_name: "Smith",
|
||||
email: "jane.smith@example.com",
|
||||
},
|
||||
])
|
||||
|
||||
const filter = { email: "unique.email@example.com" }
|
||||
const customers = await service.list(filter)
|
||||
|
||||
expect(customers.length).toBe(1)
|
||||
expect(customers[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "unique.email@example.com",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should list customers by a specific customer group", async () => {
|
||||
const vipGroup = await service.createCustomerGroup({ name: "VIP" })
|
||||
|
||||
const [john] = 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",
|
||||
},
|
||||
])
|
||||
|
||||
await service.addCustomerToGroup({
|
||||
customer_id: john.id,
|
||||
customer_group_id: vipGroup.id,
|
||||
})
|
||||
|
||||
const filter = { groups: vipGroup.id }
|
||||
const customers = await service.list(filter)
|
||||
|
||||
expect(customers).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john.doe@example.com",
|
||||
}),
|
||||
])
|
||||
)
|
||||
expect(customers).not.toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
first_name: "Jane",
|
||||
last_name: "Smith",
|
||||
email: "jane.smith@example.com",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("addCustomerToGroup", () => {
|
||||
it("should add a single customer to a customer group", async () => {
|
||||
const [customer] = await service.create([
|
||||
{ first_name: "John", last_name: "Doe", email: "john.doe@example.com" },
|
||||
])
|
||||
const [group] = await service.createCustomerGroup([{ name: "VIP" }])
|
||||
|
||||
const result = await service.addCustomerToGroup({
|
||||
customer_id: customer.id,
|
||||
customer_group_id: group.id,
|
||||
})
|
||||
|
||||
expect(result).toEqual(
|
||||
expect.objectContaining({ id: expect.any(String) })
|
||||
)
|
||||
|
||||
// Additional validation (optional): retrieve the customer and check if the group is assigned
|
||||
const updatedCustomer = await service.retrieve(customer.id, {
|
||||
relations: ["groups"],
|
||||
})
|
||||
expect(updatedCustomer.groups).toContainEqual(
|
||||
expect.objectContaining({ id: group.id })
|
||||
)
|
||||
})
|
||||
|
||||
it("should add multiple customers to customer groups", 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 groups = await service.createCustomerGroup([
|
||||
{ name: "VIP" },
|
||||
{ name: "Regular" },
|
||||
])
|
||||
|
||||
const pairs = customers.map((customer, index) => ({
|
||||
customer_id: customer.id,
|
||||
customer_group_id: groups[index % groups.length].id,
|
||||
}))
|
||||
|
||||
const results = await service.addCustomerToGroup(pairs)
|
||||
|
||||
expect(results).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ id: expect.any(String) }),
|
||||
expect.objectContaining({ id: expect.any(String) }),
|
||||
])
|
||||
)
|
||||
|
||||
for (const customer of customers) {
|
||||
const updatedCustomer = await service.retrieve(customer.id, {
|
||||
relations: ["groups"],
|
||||
})
|
||||
expect(updatedCustomer.groups).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: groups[customers.indexOf(customer) % groups.length].id,
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,52 +1,9 @@
|
||||
import * as defaultRepositories from "@repositories"
|
||||
import { MikroOrmBaseRepository, ModulesSdkUtils } from "@medusajs/utils"
|
||||
import * as ModuleModels from "@models"
|
||||
import * as ModuleServices from "@services"
|
||||
|
||||
import { LoaderOptions } from "@medusajs/modules-sdk"
|
||||
import { ModulesSdkTypes } from "@medusajs/types"
|
||||
import { loadCustomRepositories } from "@medusajs/utils"
|
||||
import * as defaultServices from "@services"
|
||||
import { asClass } from "awilix"
|
||||
|
||||
export default async ({
|
||||
container,
|
||||
options,
|
||||
}: LoaderOptions<
|
||||
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||
>): Promise<void> => {
|
||||
const customRepositories = (
|
||||
options as ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||
)?.repositories
|
||||
|
||||
container.register({
|
||||
customerService: asClass(defaultServices.CustomerService).singleton(),
|
||||
addressService: asClass(defaultServices.AddressService).singleton(),
|
||||
customerGroupService: asClass(
|
||||
defaultServices.CustomerGroupService
|
||||
).singleton(),
|
||||
})
|
||||
|
||||
if (customRepositories) {
|
||||
loadCustomRepositories({
|
||||
defaultRepositories,
|
||||
customRepositories,
|
||||
container,
|
||||
})
|
||||
} else {
|
||||
loadDefaultRepositories({ container })
|
||||
}
|
||||
}
|
||||
|
||||
function loadDefaultRepositories({ container }) {
|
||||
container.register({
|
||||
baseRepository: asClass(defaultRepositories.BaseRepository).singleton(),
|
||||
customerRepository: asClass(
|
||||
defaultRepositories.CustomerRepository
|
||||
).singleton(),
|
||||
addressRepository: asClass(
|
||||
defaultRepositories.AddressRepository
|
||||
).singleton(),
|
||||
customerGroupRepository: asClass(
|
||||
defaultRepositories.CustomerGroupRepository
|
||||
).singleton(),
|
||||
})
|
||||
}
|
||||
export default ModulesSdkUtils.moduleContainerLoaderFactory({
|
||||
moduleModels: ModuleModels,
|
||||
moduleServices: ModuleServices,
|
||||
moduleRepositories: { BaseRepository: MikroOrmBaseRepository },
|
||||
})
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import Customer from "./customer"
|
||||
import CustomerGroup from "./customer-group"
|
||||
|
||||
type OptionalGroupProps = DAL.EntityDateColumns // TODO: To be revisited when more clear
|
||||
type OptionalGroupProps = "customer_group" | "customer" | DAL.EntityDateColumns // TODO: To be revisited when more clear
|
||||
|
||||
@Entity({ tableName: "customer_group_customer" })
|
||||
export default class CustomerGroupCustomer {
|
||||
@@ -21,19 +21,27 @@ export default class CustomerGroupCustomer {
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
customer_id: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
customer_group_id: string
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => Customer,
|
||||
fieldName: "customer__id",
|
||||
fieldName: "customer_id",
|
||||
index: "IDX_customer_group_customer_customer_id",
|
||||
nullable: true,
|
||||
})
|
||||
customer: Customer
|
||||
customer: Customer | null
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => CustomerGroup,
|
||||
fieldName: "customer_group_id",
|
||||
index: "IDX_customer_group_customer_group_id",
|
||||
nullable: true,
|
||||
})
|
||||
customer_group: CustomerGroup
|
||||
customer_group: CustomerGroup | null
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
@@ -53,6 +61,9 @@ export default class CustomerGroupCustomer {
|
||||
})
|
||||
updated_at: Date
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
created_by: string | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "cusgc")
|
||||
|
||||
@@ -34,6 +34,9 @@ export default class CustomerGroup {
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
created_by: string | null = null
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
|
||||
@@ -71,7 +71,7 @@ export default class Customer {
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@ManyToMany({
|
||||
inversedBy: (group) => group.customers,
|
||||
mappedBy: "customers",
|
||||
entity: () => CustomerGroup,
|
||||
pivotEntity: () => CustomerGroupCustomer,
|
||||
})
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { DALUtils } from "@medusajs/utils"
|
||||
import { Address } from "@models"
|
||||
import { CreateAddressDTO, UpdateAddressDTO } from "@types"
|
||||
|
||||
export class AddressRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
|
||||
Address,
|
||||
{
|
||||
create: CreateAddressDTO
|
||||
update: UpdateAddressDTO
|
||||
}
|
||||
>(Address) {}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { DALUtils } from "@medusajs/utils"
|
||||
import { CustomerGroup } from "@models"
|
||||
import { CreateCustomerGroupDTO, UpdateCustomerGroupDTO } from "@types"
|
||||
|
||||
export class CustomerGroupRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
|
||||
CustomerGroup,
|
||||
{
|
||||
create: CreateCustomerGroupDTO
|
||||
update: UpdateCustomerGroupDTO
|
||||
}
|
||||
>(CustomerGroup) {}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { DALUtils } from "@medusajs/utils"
|
||||
import { Customer } from "@models"
|
||||
import { CreateCustomerDTO, UpdateCustomerDTO } from "@medusajs/types"
|
||||
|
||||
export class CustomerRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
|
||||
Customer,
|
||||
{
|
||||
create: CreateCustomerDTO
|
||||
update: UpdateCustomerDTO
|
||||
}
|
||||
>(Customer) {}
|
||||
@@ -1,4 +0,0 @@
|
||||
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
|
||||
export * from "./address"
|
||||
export * from "./customer"
|
||||
export * from "./customer-group"
|
||||
@@ -0,0 +1,25 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import { CustomerGroupCustomer } from "@models"
|
||||
|
||||
type CreateCustomerGroupCustomerDTO = {
|
||||
customer_id: string
|
||||
customer_group_id: string
|
||||
created_by?: string
|
||||
}
|
||||
|
||||
type InjectedDependencies = {
|
||||
customerGroupRepository: DAL.RepositoryService
|
||||
}
|
||||
|
||||
export default class CustomerGroupCustomerService<
|
||||
TEntity extends CustomerGroupCustomer = CustomerGroupCustomer
|
||||
> extends ModulesSdkUtils.abstractServiceFactory<
|
||||
InjectedDependencies,
|
||||
{ create: CreateCustomerGroupCustomerDTO }
|
||||
>(CustomerGroupCustomer)<TEntity> {
|
||||
constructor(container: InjectedDependencies) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import { CustomerGroup } from "@models"
|
||||
import { CreateCustomerGroupDTO, UpdateCustomerGroupDTO } from "@types"
|
||||
import { CreateCustomerGroupDTO, UpdateCustomerGroupDTO } from "@medusajs/types"
|
||||
|
||||
type InjectedDependencies = {
|
||||
customerGroupRepository: DAL.RepositoryService
|
||||
|
||||
@@ -8,7 +8,11 @@ import {
|
||||
CustomerTypes,
|
||||
} from "@medusajs/types"
|
||||
|
||||
import { InjectManager, MedusaContext } from "@medusajs/utils"
|
||||
import {
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
MedusaContext,
|
||||
} from "@medusajs/utils"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import * as services from "../services"
|
||||
|
||||
@@ -17,6 +21,7 @@ type InjectedDependencies = {
|
||||
customerService: services.CustomerService
|
||||
addressService: services.AddressService
|
||||
customerGroupService: services.CustomerGroupService
|
||||
customerGroupCustomerService: services.CustomerGroupCustomerService
|
||||
}
|
||||
|
||||
export default class CustomerModuleService implements ICustomerModuleService {
|
||||
@@ -24,6 +29,7 @@ export default class CustomerModuleService implements ICustomerModuleService {
|
||||
protected customerService_: services.CustomerService
|
||||
protected addressService_: services.AddressService
|
||||
protected customerGroupService_: services.CustomerGroupService
|
||||
protected customerGroupCustomerService_: services.CustomerGroupCustomerService
|
||||
|
||||
constructor(
|
||||
{
|
||||
@@ -31,6 +37,7 @@ export default class CustomerModuleService implements ICustomerModuleService {
|
||||
customerService,
|
||||
addressService,
|
||||
customerGroupService,
|
||||
customerGroupCustomerService,
|
||||
}: InjectedDependencies,
|
||||
protected readonly moduleDeclaration: InternalModuleDeclaration
|
||||
) {
|
||||
@@ -38,6 +45,7 @@ export default class CustomerModuleService implements ICustomerModuleService {
|
||||
this.customerService_ = customerService
|
||||
this.addressService_ = addressService
|
||||
this.customerGroupService_ = customerGroupService
|
||||
this.customerGroupCustomerService_ = customerGroupCustomerService
|
||||
}
|
||||
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
@@ -64,18 +72,189 @@ export default class CustomerModuleService implements ICustomerModuleService {
|
||||
)
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async create(
|
||||
data: CustomerTypes.CreateCustomerDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerDTO>
|
||||
|
||||
async create(
|
||||
data: CustomerTypes.CreateCustomerDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerDTO[]>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async create(
|
||||
dataOrArray:
|
||||
| CustomerTypes.CreateCustomerDTO
|
||||
| CustomerTypes.CreateCustomerDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<CustomerTypes.CustomerDTO> {
|
||||
const [customer] = await this.customerService_.create([data], sharedContext)
|
||||
) {
|
||||
const data = Array.isArray(dataOrArray) ? dataOrArray : [dataOrArray]
|
||||
const customer = await this.customerService_.create(data, sharedContext)
|
||||
|
||||
if (Array.isArray(dataOrArray)) {
|
||||
return await this.baseRepository_.serialize<CustomerTypes.CustomerDTO[]>(
|
||||
customer,
|
||||
{
|
||||
populate: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return await this.baseRepository_.serialize<CustomerTypes.CustomerDTO>(
|
||||
customer,
|
||||
customer[0],
|
||||
{
|
||||
populate: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async list(
|
||||
filters: CustomerTypes.FilterableCustomerProps = {},
|
||||
config: FindConfig<CustomerTypes.CustomerDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
) {
|
||||
const customers = await this.customerService_.list(
|
||||
filters,
|
||||
config,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize<CustomerTypes.CustomerDTO[]>(
|
||||
customers,
|
||||
{
|
||||
populate: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async listAndCount(
|
||||
filters: CustomerTypes.FilterableCustomerProps = {},
|
||||
config: FindConfig<CustomerTypes.CustomerDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<[CustomerTypes.CustomerDTO[], number]> {
|
||||
const [customers, count] = await this.customerService_.listAndCount(
|
||||
filters,
|
||||
config,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return [
|
||||
await this.baseRepository_.serialize<CustomerTypes.CustomerDTO[]>(
|
||||
customers,
|
||||
{
|
||||
populate: true,
|
||||
}
|
||||
),
|
||||
count,
|
||||
]
|
||||
}
|
||||
|
||||
async createCustomerGroup(
|
||||
dataOrArrayOfData: CustomerTypes.CreateCustomerGroupDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerGroupDTO>
|
||||
|
||||
async createCustomerGroup(
|
||||
dataOrArrayOfData: CustomerTypes.CreateCustomerGroupDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async createCustomerGroup(
|
||||
dataOrArrayOfData:
|
||||
| CustomerTypes.CreateCustomerGroupDTO
|
||||
| CustomerTypes.CreateCustomerGroupDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
) {
|
||||
const data = Array.isArray(dataOrArrayOfData)
|
||||
? dataOrArrayOfData
|
||||
: [dataOrArrayOfData]
|
||||
|
||||
const groups = await this.customerGroupService_.create(data, sharedContext)
|
||||
|
||||
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 }
|
||||
)
|
||||
}
|
||||
|
||||
async addCustomerToGroup(
|
||||
groupCustomerPair: CustomerTypes.GroupCustomerPair,
|
||||
sharedContext?: Context
|
||||
): Promise<{ id: string }>
|
||||
|
||||
async addCustomerToGroup(
|
||||
groupCustomerPairs: CustomerTypes.GroupCustomerPair[],
|
||||
sharedContext?: Context
|
||||
): Promise<{ id: string }[]>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async addCustomerToGroup(
|
||||
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<{ id: string } | { id: string }[]> {
|
||||
const groupCustomers = await this.customerGroupCustomerService_.create(
|
||||
Array.isArray(data) ? data : [data],
|
||||
sharedContext
|
||||
)
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
return groupCustomers.map((gc) => ({ id: gc.id }))
|
||||
}
|
||||
|
||||
return { id: groupCustomers[0].id }
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async listCustomerGroups(
|
||||
filters: CustomerTypes.FilterableCustomerGroupProps = {},
|
||||
config: FindConfig<CustomerTypes.CustomerGroupDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
) {
|
||||
const groups = await this.customerGroupService_.list(
|
||||
filters,
|
||||
config,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
CustomerTypes.CustomerGroupDTO[]
|
||||
>(groups, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async listAndCountCustomerGroups(
|
||||
filters: CustomerTypes.FilterableCustomerGroupProps = {},
|
||||
config: FindConfig<CustomerTypes.CustomerGroupDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<[CustomerTypes.CustomerGroupDTO[], number]> {
|
||||
const [groups, count] = await this.customerGroupService_.listAndCount(
|
||||
filters,
|
||||
config,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return [
|
||||
await this.baseRepository_.serialize<CustomerTypes.CustomerGroupDTO[]>(
|
||||
groups,
|
||||
{
|
||||
populate: true,
|
||||
}
|
||||
),
|
||||
count,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@ export { default as AddressService } from "./address"
|
||||
export { default as CustomerGroupService } from "./customer-group"
|
||||
export { default as CustomerService } from "./customer"
|
||||
export { default as CustomerModuleService } from "./customer-module"
|
||||
export { default as CustomerGroupCustomerService } from "./customer-group-customer"
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
export type CreateCustomerGroupDTO = {
|
||||
name: string
|
||||
customer_ids?: string[]
|
||||
metadata?: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
export type UpdateCustomerGroupDTO = {
|
||||
name?: string
|
||||
customer_ids?: string[]
|
||||
metadata?: Record<string, unknown> | null
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import { Logger } from "@medusajs/types"
|
||||
export * from "./address"
|
||||
export * from "./customer-group"
|
||||
|
||||
export type InitializeModuleInjectableDependencies = {
|
||||
logger?: Logger
|
||||
}
|
||||
|
||||
@@ -1,5 +1,43 @@
|
||||
import { BaseFilterable } from "../dal"
|
||||
import { OperatorMap } from "../dal/utils"
|
||||
import { AddressDTO } from "../address"
|
||||
|
||||
export interface CustomerGroupDTO {
|
||||
id: string
|
||||
name: string
|
||||
customers?: Partial<CustomerDTO>[]
|
||||
metadata?: Record<string, unknown>
|
||||
created_by?: string | null
|
||||
deleted_at?: Date | string | null
|
||||
created_at?: Date | string
|
||||
updated_at?: Date | string
|
||||
}
|
||||
|
||||
export interface FilterableCustomerGroupProps
|
||||
extends BaseFilterable<FilterableCustomerGroupProps> {
|
||||
id?: string | string[]
|
||||
name?: OperatorMap<string>
|
||||
customers?: FilterableCustomerProps | string | string[]
|
||||
created_by?: string | string[] | null
|
||||
created_at?: OperatorMap<string>
|
||||
updated_at?: OperatorMap<string>
|
||||
}
|
||||
|
||||
export interface FilterableCustomerProps
|
||||
extends BaseFilterable<FilterableCustomerProps> {
|
||||
id?: string | string[]
|
||||
email?: string | string[] | OperatorMap<string>
|
||||
groups?: FilterableCustomerGroupProps | string | string[]
|
||||
default_billing_address_id?: string | string[] | null
|
||||
default_shipping_address_id?: string | string[] | null
|
||||
company_name?: string | string[] | OperatorMap<string> | null
|
||||
first_name?: string | string[] | OperatorMap<string> | null
|
||||
last_name?: string | string[] | OperatorMap<string> | null
|
||||
created_by?: string | string[] | null
|
||||
created_at?: OperatorMap<string>
|
||||
updated_at?: OperatorMap<string>
|
||||
}
|
||||
|
||||
export interface CustomerDTO {
|
||||
id: string
|
||||
email: string
|
||||
@@ -14,11 +52,16 @@ export interface CustomerDTO {
|
||||
phone?: string | null
|
||||
groups?: { id: string }[]
|
||||
metadata?: Record<string, unknown>
|
||||
deleted_at?: Date | string
|
||||
deleted_at?: Date | string | null
|
||||
created_at?: Date | string
|
||||
updated_at?: Date | string
|
||||
}
|
||||
|
||||
export type GroupCustomerPair = {
|
||||
customer_id: string
|
||||
customer_group_id: string
|
||||
}
|
||||
|
||||
export type legacy_CustomerDTO = {
|
||||
id: string
|
||||
email: string
|
||||
|
||||
@@ -4,6 +4,7 @@ export interface CreateCustomerDTO {
|
||||
last_name?: string
|
||||
email?: string
|
||||
phone?: string
|
||||
created_by?: string
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
|
||||
@@ -15,3 +16,20 @@ export interface UpdateCustomerDTO {
|
||||
phone?: string
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
|
||||
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
|
||||
metadata?: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import { FindConfig } from "../common"
|
||||
import { IModuleService } from "../modules-sdk"
|
||||
import { Context } from "../shared-context"
|
||||
import { CustomerDTO } from "./common"
|
||||
import { CreateCustomerDTO } from "./mutations"
|
||||
import {
|
||||
CustomerDTO,
|
||||
CustomerGroupDTO,
|
||||
FilterableCustomerProps,
|
||||
FilterableCustomerGroupProps,
|
||||
GroupCustomerPair,
|
||||
} from "./common"
|
||||
import { CreateCustomerDTO, CreateCustomerGroupDTO } from "./mutations"
|
||||
|
||||
export interface ICustomerModuleService extends IModuleService {
|
||||
retrieve(
|
||||
@@ -11,5 +17,54 @@ export interface ICustomerModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerDTO>
|
||||
|
||||
create(
|
||||
data: CreateCustomerDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerDTO[]>
|
||||
|
||||
create(data: CreateCustomerDTO, sharedContext?: Context): Promise<CustomerDTO>
|
||||
|
||||
createCustomerGroup(
|
||||
data: CreateCustomerGroupDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerGroupDTO[]>
|
||||
|
||||
createCustomerGroup(
|
||||
data: CreateCustomerGroupDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerGroupDTO>
|
||||
|
||||
addCustomerToGroup(
|
||||
groupCustomerPair: GroupCustomerPair,
|
||||
sharedContext?: Context
|
||||
): Promise<{ id: string }>
|
||||
|
||||
addCustomerToGroup(
|
||||
groupCustomerPairs: GroupCustomerPair[],
|
||||
sharedContext?: Context
|
||||
): Promise<{ id: string }[]>
|
||||
|
||||
list(
|
||||
filters?: FilterableCustomerProps,
|
||||
config?: FindConfig<CustomerDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerDTO[]>
|
||||
|
||||
listAndCount(
|
||||
filters?: FilterableCustomerProps,
|
||||
config?: FindConfig<CustomerDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<[CustomerDTO[], number]>
|
||||
|
||||
listCustomerGroups(
|
||||
filters?: FilterableCustomerGroupProps,
|
||||
config?: FindConfig<CustomerGroupDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<CustomerGroupDTO[]>
|
||||
|
||||
listAndCountCustomerGroups(
|
||||
filters?: FilterableCustomerGroupProps,
|
||||
config?: FindConfig<CustomerGroupDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<[CustomerGroupDTO[], number]>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user