* chore(): Ensure the product module emits all necessary events * chore(): Ensure the product module emits all necessary events * Update events tests * more events and fixes * more tests and category fixes * more tests and category fixes * Add todo * update updateProduct_ event emitting and adjust test * Adjust update products implementation to rely on already computed events * rm unnecessary update variants events * Fix formatting in changeset for product events * refactor: Manage event emitting automatically (WIP) * refactor: Manage event emitting automatically (WIP) * chore(api-key): Add missing emit events and refactoring * chore(cart): Add missing emit events and refactoring * chore(customer): Add missing emit events and refactoring * chore(fufillment, utils): Add missing emit events and refactoring * chore(fufillment, utils): Add missing emit events and refactoring * chore(inventory): Add missing emit events and refactoring * chore(notification): Add missing emit events and refactoring * chore(utils): Remove medusa service event handling legacy * chore(product): Add missing emit events and refactoring * chore(order): Add missing emit events and refactoring * chore(payment): Add missing emit events and refactoring * chore(pricing, util): Add missing emit events and refactoring, fix internal service upsertWithReplace event dispatching * chore(promotions): Add missing emit events and refactoring * chore(region): Add missing emit events and refactoring * chore(sales-channel): Add missing emit events and refactoring * chore(settings): Add missing emit events and refactoring * chore(stock-location): Add missing emit events and refactoring * chore(store): Add missing emit events and refactoring * chore(taxes): Add missing emit events and refactoring * chore(user): Add missing emit events and refactoring * fix unit tests * rm changeset for regeneration * Create changeset for Medusa.js patch updates Add a changeset for patch updates to multiple Medusa.js modules. * rm unused product event builders * address feedback * remove old changeset * fix event action for token generated * fix user module events * fix import * fix promotion events * add new module integration tests shard * fix medusa service * revert shard * fix event action * fix pipeline * fix pipeline --------- Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
595 lines
16 KiB
TypeScript
595 lines
16 KiB
TypeScript
import {
|
|
Context,
|
|
CustomerAddressDTO,
|
|
CustomerDTO,
|
|
CustomerGroupCustomerDTO,
|
|
CustomerGroupDTO,
|
|
CustomerTypes,
|
|
DAL,
|
|
ICustomerModuleService,
|
|
InferEntityType,
|
|
InternalModuleDeclaration,
|
|
ModuleJoinerConfig,
|
|
ModulesSdkTypes,
|
|
} from "@medusajs/framework/types"
|
|
|
|
import {
|
|
EmitEvents,
|
|
InjectManager,
|
|
InjectTransactionManager,
|
|
isString,
|
|
MedusaContext,
|
|
MedusaService,
|
|
} from "@medusajs/framework/utils"
|
|
import {
|
|
Customer,
|
|
CustomerAddress,
|
|
CustomerGroup,
|
|
CustomerGroupCustomer,
|
|
} from "@models"
|
|
import { joinerConfig } from "../joiner-config"
|
|
|
|
type InjectedDependencies = {
|
|
baseRepository: DAL.RepositoryService
|
|
customerService: ModulesSdkTypes.IMedusaInternalService<any>
|
|
customerAddressService: ModulesSdkTypes.IMedusaInternalService<any>
|
|
customerGroupService: ModulesSdkTypes.IMedusaInternalService<any>
|
|
customerGroupCustomerService: ModulesSdkTypes.IMedusaInternalService<any>
|
|
}
|
|
|
|
export default class CustomerModuleService
|
|
extends MedusaService<{
|
|
CustomerAddress: { dto: CustomerAddressDTO }
|
|
Customer: { dto: CustomerDTO }
|
|
CustomerGroup: { dto: CustomerGroupDTO }
|
|
CustomerGroupCustomer: { dto: CustomerGroupCustomerDTO }
|
|
}>({
|
|
CustomerAddress,
|
|
Customer,
|
|
CustomerGroup,
|
|
CustomerGroupCustomer,
|
|
})
|
|
implements ICustomerModuleService
|
|
{
|
|
protected baseRepository_: DAL.RepositoryService
|
|
protected customerService_: ModulesSdkTypes.IMedusaInternalService<
|
|
InferEntityType<typeof Customer>
|
|
>
|
|
protected customerAddressService_: ModulesSdkTypes.IMedusaInternalService<
|
|
InferEntityType<typeof CustomerAddress>
|
|
>
|
|
protected customerGroupService_: ModulesSdkTypes.IMedusaInternalService<
|
|
InferEntityType<typeof CustomerGroup>
|
|
>
|
|
protected customerGroupCustomerService_: ModulesSdkTypes.IMedusaInternalService<
|
|
InferEntityType<typeof CustomerGroupCustomer>
|
|
>
|
|
|
|
constructor(
|
|
{
|
|
baseRepository,
|
|
customerService,
|
|
customerAddressService,
|
|
customerGroupService,
|
|
customerGroupCustomerService,
|
|
}: InjectedDependencies,
|
|
protected readonly moduleDeclaration: InternalModuleDeclaration
|
|
) {
|
|
// @ts-ignore
|
|
super(...arguments)
|
|
|
|
this.baseRepository_ = baseRepository
|
|
this.customerService_ = customerService
|
|
this.customerAddressService_ = customerAddressService
|
|
this.customerGroupService_ = customerGroupService
|
|
this.customerGroupCustomerService_ = customerGroupCustomerService
|
|
}
|
|
|
|
__joinerConfig(): ModuleJoinerConfig {
|
|
return joinerConfig
|
|
}
|
|
|
|
// @ts-expect-error
|
|
async createCustomers(
|
|
data: CustomerTypes.CreateCustomerDTO,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerDTO>
|
|
|
|
async createCustomers(
|
|
data: CustomerTypes.CreateCustomerDTO[],
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerDTO[]>
|
|
|
|
@InjectManager()
|
|
@EmitEvents()
|
|
async createCustomers(
|
|
dataOrArray:
|
|
| CustomerTypes.CreateCustomerDTO
|
|
| CustomerTypes.CreateCustomerDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<CustomerTypes.CustomerDTO | CustomerTypes.CustomerDTO[]> {
|
|
const customers = await this.createCustomers_(dataOrArray, sharedContext)
|
|
|
|
const serialized = await this.baseRepository_.serialize<
|
|
CustomerTypes.CustomerDTO[]
|
|
>(customers, {
|
|
populate: true,
|
|
})
|
|
|
|
return Array.isArray(dataOrArray) ? serialized : serialized[0]
|
|
}
|
|
|
|
@InjectTransactionManager()
|
|
async createCustomers_(
|
|
dataOrArray:
|
|
| CustomerTypes.CreateCustomerDTO
|
|
| CustomerTypes.CreateCustomerDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<InferEntityType<typeof Customer>[]> {
|
|
const data = Array.isArray(dataOrArray) ? dataOrArray : [dataOrArray]
|
|
const customerAttributes = data.map(({ addresses, ...rest }) => {
|
|
return rest
|
|
})
|
|
|
|
const customers = await this.customerService_.create(
|
|
customerAttributes,
|
|
sharedContext
|
|
)
|
|
|
|
const addressDataWithCustomerIds = data
|
|
.map(({ addresses }, i) => {
|
|
if (!addresses) {
|
|
return []
|
|
}
|
|
|
|
return addresses.map((address) => ({
|
|
...address,
|
|
customer_id: customers[i].id,
|
|
}))
|
|
})
|
|
.flat()
|
|
|
|
await this.createCustomerAddresses(
|
|
addressDataWithCustomerIds,
|
|
sharedContext
|
|
)
|
|
|
|
return customers
|
|
}
|
|
|
|
// @ts-expect-error
|
|
updateCustomers(
|
|
customerId: string,
|
|
data: CustomerTypes.CustomerUpdatableFields,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerDTO>
|
|
// @ts-expect-error
|
|
updateCustomers(
|
|
customerIds: string[],
|
|
data: CustomerTypes.CustomerUpdatableFields,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerDTO[]>
|
|
// @ts-expect-error
|
|
updateCustomers(
|
|
selector: CustomerTypes.FilterableCustomerProps,
|
|
data: CustomerTypes.CustomerUpdatableFields,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerDTO[]>
|
|
|
|
@InjectManager()
|
|
@EmitEvents()
|
|
// @ts-expect-error
|
|
async updateCustomers(
|
|
idsOrSelector: string | string[] | CustomerTypes.FilterableCustomerProps,
|
|
data: CustomerTypes.CustomerUpdatableFields,
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<CustomerTypes.CustomerDTO | CustomerTypes.CustomerDTO[]> {
|
|
const customers = await this.updateCustomers_(
|
|
idsOrSelector,
|
|
data,
|
|
sharedContext
|
|
)
|
|
|
|
return await this.baseRepository_.serialize<
|
|
CustomerTypes.CustomerDTO | CustomerTypes.CustomerDTO[]
|
|
>(customers)
|
|
}
|
|
|
|
@InjectTransactionManager()
|
|
protected async updateCustomers_(
|
|
idsOrSelector: string | string[] | CustomerTypes.FilterableCustomerProps,
|
|
data: CustomerTypes.CustomerUpdatableFields,
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<
|
|
InferEntityType<typeof Customer>[] | InferEntityType<typeof Customer>
|
|
> {
|
|
let updateData:
|
|
| CustomerTypes.UpdateCustomerDTO
|
|
| CustomerTypes.UpdateCustomerDTO[]
|
|
| {
|
|
selector: CustomerTypes.FilterableCustomerProps
|
|
data: CustomerTypes.CustomerUpdatableFields
|
|
}
|
|
|
|
if (isString(idsOrSelector)) {
|
|
updateData = {
|
|
id: idsOrSelector,
|
|
...data,
|
|
}
|
|
} else if (Array.isArray(idsOrSelector)) {
|
|
updateData = idsOrSelector.map((id) => ({
|
|
id,
|
|
...data,
|
|
}))
|
|
} else {
|
|
updateData = {
|
|
selector: idsOrSelector,
|
|
data: data,
|
|
}
|
|
}
|
|
|
|
const customers = await this.customerService_.update(
|
|
updateData,
|
|
sharedContext
|
|
)
|
|
|
|
return customers
|
|
}
|
|
|
|
// @ts-expect-error
|
|
async createCustomerGroups(
|
|
dataOrArrayOfData: CustomerTypes.CreateCustomerGroupDTO,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerGroupDTO>
|
|
|
|
// @ts-expect-error
|
|
async createCustomerGroups(
|
|
dataOrArrayOfData: CustomerTypes.CreateCustomerGroupDTO[],
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
|
|
|
@InjectManager()
|
|
@EmitEvents()
|
|
// @ts-expect-error
|
|
async createCustomerGroups(
|
|
dataOrArrayOfData:
|
|
| CustomerTypes.CreateCustomerGroupDTO
|
|
| CustomerTypes.CreateCustomerGroupDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<
|
|
CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
|
|
> {
|
|
const groups = await this.createCustomerGroups_(
|
|
dataOrArrayOfData,
|
|
sharedContext
|
|
)
|
|
|
|
return await this.baseRepository_.serialize<
|
|
CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
|
|
>(groups)
|
|
}
|
|
|
|
@InjectTransactionManager()
|
|
protected async createCustomerGroups_(
|
|
dataOrArrayOfData:
|
|
| CustomerTypes.CreateCustomerGroupDTO
|
|
| CustomerTypes.CreateCustomerGroupDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<
|
|
| InferEntityType<typeof CustomerGroup>[]
|
|
| InferEntityType<typeof CustomerGroup>
|
|
> {
|
|
const groups = await this.customerGroupService_.create(
|
|
dataOrArrayOfData,
|
|
sharedContext
|
|
)
|
|
|
|
return groups
|
|
}
|
|
|
|
// @ts-expect-error
|
|
async updateCustomerGroups(
|
|
groupId: string,
|
|
data: CustomerTypes.CustomerGroupUpdatableFields,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerGroupDTO>
|
|
// @ts-expect-error
|
|
async updateCustomerGroups(
|
|
groupIds: string[],
|
|
data: CustomerTypes.CustomerGroupUpdatableFields,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
|
// @ts-expect-error
|
|
async updateCustomerGroups(
|
|
selector: CustomerTypes.FilterableCustomerGroupProps,
|
|
data: CustomerTypes.CustomerGroupUpdatableFields,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
|
|
|
@InjectManager()
|
|
@EmitEvents()
|
|
// @ts-expect-error
|
|
async updateCustomerGroups(
|
|
groupIdOrSelector:
|
|
| string
|
|
| string[]
|
|
| CustomerTypes.FilterableCustomerGroupProps,
|
|
data: CustomerTypes.CustomerGroupUpdatableFields,
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<
|
|
CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
|
|
> {
|
|
const groups = await this.updateCustomerGroups_(
|
|
groupIdOrSelector,
|
|
data,
|
|
sharedContext
|
|
)
|
|
|
|
return await this.baseRepository_.serialize<
|
|
CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
|
|
>(groups)
|
|
}
|
|
|
|
@InjectTransactionManager()
|
|
protected async updateCustomerGroups_(
|
|
groupIdOrSelector:
|
|
| string
|
|
| string[]
|
|
| CustomerTypes.FilterableCustomerGroupProps,
|
|
data: CustomerTypes.CustomerGroupUpdatableFields,
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<
|
|
| InferEntityType<typeof CustomerGroup>[]
|
|
| InferEntityType<typeof CustomerGroup>
|
|
> {
|
|
let updateData:
|
|
| CustomerTypes.UpdateCustomerGroupDTO
|
|
| CustomerTypes.UpdateCustomerGroupDTO[]
|
|
| {
|
|
selector: CustomerTypes.FilterableCustomerGroupProps
|
|
data: CustomerTypes.CustomerGroupUpdatableFields
|
|
}
|
|
|
|
if (isString(groupIdOrSelector) || Array.isArray(groupIdOrSelector)) {
|
|
const groupIdOrSelectorArray = Array.isArray(groupIdOrSelector)
|
|
? groupIdOrSelector
|
|
: [groupIdOrSelector]
|
|
updateData = groupIdOrSelectorArray.map((id) => ({
|
|
id,
|
|
...data,
|
|
}))
|
|
} else {
|
|
updateData = {
|
|
selector: groupIdOrSelector,
|
|
data: data,
|
|
}
|
|
}
|
|
|
|
const groups = await this.customerGroupService_.update(
|
|
updateData,
|
|
sharedContext
|
|
)
|
|
|
|
if (isString(groupIdOrSelector)) {
|
|
return groups[0]
|
|
}
|
|
|
|
return groups
|
|
}
|
|
|
|
async addCustomerToGroup(
|
|
groupCustomerPair: CustomerTypes.GroupCustomerPair,
|
|
sharedContext?: Context
|
|
): Promise<{ id: string }>
|
|
|
|
async addCustomerToGroup(
|
|
groupCustomerPairs: CustomerTypes.GroupCustomerPair[],
|
|
sharedContext?: Context
|
|
): Promise<{ id: string }[]>
|
|
|
|
@InjectManager()
|
|
@EmitEvents()
|
|
async addCustomerToGroup(
|
|
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<{ id: string } | { id: string }[]> {
|
|
const groupCustomers = await this.addCustomerToGroup_(data, sharedContext)
|
|
|
|
return groupCustomers
|
|
}
|
|
|
|
@InjectTransactionManager()
|
|
protected async addCustomerToGroup_(
|
|
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<{ id: string } | { id: string }[]> {
|
|
const groupCustomers = await this.customerGroupCustomerService_.create(
|
|
data,
|
|
sharedContext
|
|
)
|
|
|
|
if (Array.isArray(data)) {
|
|
return (
|
|
groupCustomers as unknown as InferEntityType<
|
|
typeof CustomerGroupCustomer
|
|
>[]
|
|
).map((gc) => ({ id: gc.id }))
|
|
}
|
|
|
|
return { id: groupCustomers.id }
|
|
}
|
|
|
|
// @ts-expect-error
|
|
async createCustomerAddresses(
|
|
addresses: CustomerTypes.CreateCustomerAddressDTO[],
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerAddressDTO[]>
|
|
// @ts-expect-error
|
|
async createCustomerAddresses(
|
|
address: CustomerTypes.CreateCustomerAddressDTO,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerAddressDTO>
|
|
|
|
@InjectManager()
|
|
@EmitEvents()
|
|
// @ts-expect-error
|
|
async createCustomerAddresses(
|
|
data:
|
|
| CustomerTypes.CreateCustomerAddressDTO
|
|
| CustomerTypes.CreateCustomerAddressDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<
|
|
CustomerTypes.CustomerAddressDTO | CustomerTypes.CustomerAddressDTO[]
|
|
> {
|
|
const addresses = await this.createCustomerAddresses_(data, sharedContext)
|
|
|
|
const serialized = await this.baseRepository_.serialize<
|
|
CustomerTypes.CustomerAddressDTO[]
|
|
>(addresses, { populate: true })
|
|
|
|
if (Array.isArray(data)) {
|
|
return serialized
|
|
}
|
|
|
|
return serialized[0]
|
|
}
|
|
|
|
@InjectTransactionManager()
|
|
private async createCustomerAddresses_(
|
|
data:
|
|
| CustomerTypes.CreateCustomerAddressDTO
|
|
| CustomerTypes.CreateCustomerAddressDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
) {
|
|
return await this.customerAddressService_.create(
|
|
Array.isArray(data) ? data : [data],
|
|
sharedContext
|
|
)
|
|
}
|
|
|
|
// @ts-expect-error
|
|
async updateCustomerAddresses(
|
|
addressId: string,
|
|
data: CustomerTypes.UpdateCustomerAddressDTO,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerAddressDTO>
|
|
// @ts-expect-error
|
|
async updateCustomerAddresses(
|
|
addressIds: string[],
|
|
data: CustomerTypes.UpdateCustomerAddressDTO,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerAddressDTO[]>
|
|
// @ts-expect-error
|
|
async updateCustomerAddresses(
|
|
selector: CustomerTypes.FilterableCustomerAddressProps,
|
|
data: CustomerTypes.UpdateCustomerAddressDTO,
|
|
sharedContext?: Context
|
|
): Promise<CustomerTypes.CustomerAddressDTO[]>
|
|
|
|
@InjectManager()
|
|
@EmitEvents()
|
|
// @ts-expect-error
|
|
async updateCustomerAddresses(
|
|
addressIdOrSelector:
|
|
| string
|
|
| string[]
|
|
| CustomerTypes.FilterableCustomerAddressProps,
|
|
data: CustomerTypes.UpdateCustomerAddressDTO,
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<
|
|
CustomerTypes.CustomerAddressDTO | CustomerTypes.CustomerAddressDTO[]
|
|
> {
|
|
const addresses = await this.updateCustomerAddresses_(
|
|
addressIdOrSelector,
|
|
data,
|
|
sharedContext
|
|
)
|
|
|
|
return await this.baseRepository_.serialize<
|
|
CustomerTypes.CustomerAddressDTO | CustomerTypes.CustomerAddressDTO[]
|
|
>(addresses)
|
|
}
|
|
|
|
@InjectTransactionManager()
|
|
protected async updateCustomerAddresses_(
|
|
addressIdOrSelector:
|
|
| string
|
|
| string[]
|
|
| CustomerTypes.FilterableCustomerAddressProps,
|
|
data: CustomerTypes.UpdateCustomerAddressDTO,
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<
|
|
| InferEntityType<typeof CustomerAddress>[]
|
|
| InferEntityType<typeof CustomerAddress>
|
|
> {
|
|
let updateData:
|
|
| CustomerTypes.UpdateCustomerAddressDTO[]
|
|
| {
|
|
selector: CustomerTypes.FilterableCustomerAddressProps
|
|
data: CustomerTypes.UpdateCustomerAddressDTO
|
|
}
|
|
if (isString(addressIdOrSelector)) {
|
|
updateData = [
|
|
{
|
|
id: addressIdOrSelector,
|
|
...data,
|
|
},
|
|
]
|
|
} else if (Array.isArray(addressIdOrSelector)) {
|
|
updateData = addressIdOrSelector.map((id) => ({
|
|
id,
|
|
...data,
|
|
}))
|
|
} else {
|
|
updateData = {
|
|
selector: addressIdOrSelector,
|
|
data,
|
|
}
|
|
}
|
|
|
|
const addresses = await this.customerAddressService_.update(
|
|
updateData,
|
|
sharedContext
|
|
)
|
|
|
|
if (isString(addressIdOrSelector)) {
|
|
return addresses[0]
|
|
}
|
|
|
|
return addresses
|
|
}
|
|
|
|
async removeCustomerFromGroup(
|
|
groupCustomerPair: CustomerTypes.GroupCustomerPair,
|
|
sharedContext?: Context
|
|
): Promise<void>
|
|
async removeCustomerFromGroup(
|
|
groupCustomerPairs: CustomerTypes.GroupCustomerPair[],
|
|
sharedContext?: Context
|
|
): Promise<void>
|
|
|
|
@InjectManager()
|
|
@EmitEvents()
|
|
async removeCustomerFromGroup(
|
|
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<void> {
|
|
await this.removeCustomerFromGroup_(data, sharedContext)
|
|
}
|
|
|
|
@InjectTransactionManager()
|
|
protected async removeCustomerFromGroup_(
|
|
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<void> {
|
|
const pairs = Array.isArray(data) ? data : [data]
|
|
const groupCustomers = await this.customerGroupCustomerService_.list({
|
|
$or: pairs,
|
|
})
|
|
await this.customerGroupCustomerService_.delete(
|
|
groupCustomers.map((gc) => gc.id),
|
|
sharedContext
|
|
)
|
|
}
|
|
}
|