chore(): Module Internal Events (#13296)
* 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>
This commit is contained in:
1 parent
afe21741c4
commit
e8822f3e69
55 files changed
+3451
-2190
No files matched your search
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/api-key": patch
|
||||||
|
"@medusajs/cart": patch
|
||||||
|
"@medusajs/customer": patch
|
||||||
|
"@medusajs/fulfillment": patch
|
||||||
|
"@medusajs/inventory": patch
|
||||||
|
"@medusajs/notification": patch
|
||||||
|
"@medusajs/order": patch
|
||||||
|
"@medusajs/payment": patch
|
||||||
|
"@medusajs/pricing": patch
|
||||||
|
"@medusajs/product": patch
|
||||||
|
"@medusajs/utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
chore(): Module Internal Events
|
||||||
@@ -9,12 +9,13 @@ import {
|
|||||||
import { composeMessage } from "./build-event-messages"
|
import { composeMessage } from "./build-event-messages"
|
||||||
|
|
||||||
export class MessageAggregator implements IMessageAggregator {
|
export class MessageAggregator implements IMessageAggregator {
|
||||||
private messages: Message[] = []
|
#messagesHash: Set<string> = new Set()
|
||||||
|
#messages: Message[] = []
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
count(): number {
|
count(): number {
|
||||||
return this.messages.length
|
return this.#messages.length
|
||||||
}
|
}
|
||||||
|
|
||||||
save(msg: Message | Message[]): void {
|
save(msg: Message | Message[]): void {
|
||||||
@@ -23,7 +24,19 @@ export class MessageAggregator implements IMessageAggregator {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.messages.push(...messages)
|
for (const message of messages) {
|
||||||
|
try {
|
||||||
|
const hash = JSON.stringify(message)
|
||||||
|
if (!this.#messagesHash.has(hash)) {
|
||||||
|
this.#messagesHash.add(hash)
|
||||||
|
this.#messages.push(message)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// noop: if the message is not serializable, we don't want to deduplicate it
|
||||||
|
// It should not happen, but we don't want to fail the whole process
|
||||||
|
this.#messages.push(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saveRawMessageData<T>(
|
saveRawMessageData<T>(
|
||||||
@@ -55,15 +68,15 @@ export class MessageAggregator implements IMessageAggregator {
|
|||||||
const { groupBy, sortBy } = format ?? {}
|
const { groupBy, sortBy } = format ?? {}
|
||||||
|
|
||||||
if (sortBy) {
|
if (sortBy) {
|
||||||
this.messages.sort((a, b) => this.compareMessages(a, b, sortBy))
|
this.#messages.sort((a, b) => this.compareMessages(a, b, sortBy))
|
||||||
}
|
}
|
||||||
|
|
||||||
let messages: { [group: string]: Message[] } = {
|
let messages: { [group: string]: Message[] } = {
|
||||||
default: [...this.messages],
|
default: [...this.#messages],
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupBy) {
|
if (groupBy) {
|
||||||
messages = this.messages.reduce<{
|
messages = this.#messages.reduce<{
|
||||||
[key: string]: Message[]
|
[key: string]: Message[]
|
||||||
}>((acc, msg) => {
|
}>((acc, msg) => {
|
||||||
const key = groupBy
|
const key = groupBy
|
||||||
@@ -91,7 +104,8 @@ export class MessageAggregator implements IMessageAggregator {
|
|||||||
|
|
||||||
clearMessages(): void {
|
clearMessages(): void {
|
||||||
// Ensure no references are left over in case something rely on messages
|
// Ensure no references are left over in case something rely on messages
|
||||||
this.messages.length = 0
|
this.#messages.length = 0
|
||||||
|
this.#messagesHash.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
private getValueFromPath(obj: any, path: string): any {
|
private getValueFromPath(obj: any, path: string): any {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ describe("Internal Module Service Factory", () => {
|
|||||||
findAndCount: jest.fn(),
|
findAndCount: jest.fn(),
|
||||||
create: jest.fn(),
|
create: jest.fn(),
|
||||||
update: jest.fn(),
|
update: jest.fn(),
|
||||||
delete: jest.fn(),
|
delete: jest.fn().mockImplementation((ids) => Promise.resolve(ids)),
|
||||||
softDelete: jest.fn(),
|
softDelete: jest.fn(),
|
||||||
restore: jest.fn(),
|
restore: jest.fn(),
|
||||||
upsert: jest.fn(),
|
upsert: jest.fn(),
|
||||||
@@ -32,7 +32,7 @@ describe("Internal Module Service Factory", () => {
|
|||||||
findAndCount: jest.fn(),
|
findAndCount: jest.fn(),
|
||||||
create: jest.fn(),
|
create: jest.fn(),
|
||||||
update: jest.fn(),
|
update: jest.fn(),
|
||||||
delete: jest.fn(),
|
delete: jest.fn().mockImplementation((ids) => Promise.resolve(ids)),
|
||||||
softDelete: jest.fn(),
|
softDelete: jest.fn(),
|
||||||
restore: jest.fn(),
|
restore: jest.fn(),
|
||||||
upsert: jest.fn(),
|
upsert: jest.fn(),
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { Context } from "@medusajs/types"
|
||||||
|
import { EventArgs, EventSubscriber } from "@mikro-orm/core"
|
||||||
|
type Service = {
|
||||||
|
interceptEntityMutationEvents: (
|
||||||
|
event: "afterCreate" | "afterUpdate" | "afterUpsert" | "afterDelete",
|
||||||
|
args: EventArgs<any>,
|
||||||
|
context: Context
|
||||||
|
) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MedusaMikroOrmEventSubscriber = {
|
||||||
|
new (context: Context): EventSubscriber
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a new mikro orm event subscriber for the given models
|
||||||
|
* @param models
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function createMedusaMikroOrmEventSubscriber(
|
||||||
|
keys: string[],
|
||||||
|
service: Service
|
||||||
|
): MedusaMikroOrmEventSubscriber {
|
||||||
|
const klass = class MikroOrmEventSubscriber implements EventSubscriber {
|
||||||
|
#context: Context
|
||||||
|
#service: Service = service
|
||||||
|
|
||||||
|
constructor(context: Context) {
|
||||||
|
this.#context = context
|
||||||
|
}
|
||||||
|
|
||||||
|
async afterCreate<T>(args: EventArgs<T>): Promise<void> {
|
||||||
|
this.#service.interceptEntityMutationEvents(
|
||||||
|
"afterCreate",
|
||||||
|
args,
|
||||||
|
this.#context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async afterUpdate<T>(args: EventArgs<T>): Promise<void> {
|
||||||
|
this.#service.interceptEntityMutationEvents(
|
||||||
|
"afterUpdate",
|
||||||
|
args,
|
||||||
|
this.#context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async afterUpsert<T>(args: EventArgs<T>): Promise<void> {
|
||||||
|
this.#service.interceptEntityMutationEvents(
|
||||||
|
"afterUpsert",
|
||||||
|
args,
|
||||||
|
this.#context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async afterDelete<T>(args: EventArgs<T>): Promise<void> {
|
||||||
|
this.#service.interceptEntityMutationEvents(
|
||||||
|
"afterDelete",
|
||||||
|
args,
|
||||||
|
this.#context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(klass, "name", {
|
||||||
|
value: keys.join(","),
|
||||||
|
writable: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
return klass
|
||||||
|
}
|
||||||
@@ -21,3 +21,4 @@ export * from "./types/links-config"
|
|||||||
export * from "./types/medusa-service"
|
export * from "./types/medusa-service"
|
||||||
export * from "./module-provider-registration-key"
|
export * from "./module-provider-registration-key"
|
||||||
export * from "./modules-to-container-types"
|
export * from "./modules-to-container-types"
|
||||||
|
export * from "./create-medusa-mikro-orm-event-subscriber"
|
||||||
@@ -9,7 +9,12 @@ import {
|
|||||||
PerformedActions,
|
PerformedActions,
|
||||||
UpsertWithReplaceConfig,
|
UpsertWithReplaceConfig,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import type { EntityClass, EntitySchema } from "@mikro-orm/core"
|
import {
|
||||||
|
EventType,
|
||||||
|
type EntityClass,
|
||||||
|
type EntityManager,
|
||||||
|
type EntitySchema,
|
||||||
|
} from "@mikro-orm/core"
|
||||||
import {
|
import {
|
||||||
isDefined,
|
isDefined,
|
||||||
isObject,
|
isObject,
|
||||||
@@ -27,23 +32,60 @@ import {
|
|||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
} from "./decorators"
|
} from "./decorators"
|
||||||
|
import { MedusaMikroOrmEventSubscriber } from "./create-medusa-mikro-orm-event-subscriber"
|
||||||
|
|
||||||
|
type InternalService = {
|
||||||
|
new <TContainer extends object = object, TEntity extends object = any>(
|
||||||
|
container: TContainer
|
||||||
|
): ModulesSdkTypes.IMedusaInternalService<TEntity, TContainer>
|
||||||
|
|
||||||
|
setEventSubscriber(subscriber: MedusaMikroOrmEventSubscriber): void
|
||||||
|
}
|
||||||
|
|
||||||
type SelectorAndData = {
|
type SelectorAndData = {
|
||||||
selector: FilterQuery<any> | BaseFilterable<FilterQuery<any>>
|
selector: FilterQuery<any> | BaseFilterable<FilterQuery<any>>
|
||||||
data: any
|
data: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function registerInternalServiceEventSubscriber(
|
||||||
|
context: Context,
|
||||||
|
subscriber?: MedusaMikroOrmEventSubscriber
|
||||||
|
) {
|
||||||
|
const manager = (context.transactionManager ??
|
||||||
|
context.manager) as EntityManager
|
||||||
|
if (manager && subscriber) {
|
||||||
|
const subscriberInstance = new subscriber(context)
|
||||||
|
// There is no public API to unregister subscribers or check if a subscriber is already
|
||||||
|
// registered. This means that we need to manually check if the subscriber is already
|
||||||
|
// registered, otherwise we will register the same subscriber twice.
|
||||||
|
const hasListeners = (manager.getEventManager() as any).subscribers.some(
|
||||||
|
(s) => s.constructor.name === subscriberInstance.constructor.name
|
||||||
|
)
|
||||||
|
if (!hasListeners) {
|
||||||
|
manager.getEventManager().registerSubscriber(subscriberInstance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MedusaInternalServiceSymbol = Symbol.for(
|
||||||
|
"MedusaInternalServiceSymbol"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a value is a Medusa internal service
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
export function isMedusaInternalService(value: any): value is InternalService {
|
||||||
|
return (
|
||||||
|
!!value?.[MedusaInternalServiceSymbol] ||
|
||||||
|
!!value?.prototype?.[MedusaInternalServiceSymbol]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function MedusaInternalService<
|
export function MedusaInternalService<
|
||||||
TContainer extends object = object,
|
TContainer extends object = object,
|
||||||
TEntity extends object = any
|
TEntity extends object = any
|
||||||
>(
|
>(rawModel: any): InternalService {
|
||||||
rawModel: any
|
|
||||||
): {
|
|
||||||
new (container: TContainer): ModulesSdkTypes.IMedusaInternalService<
|
|
||||||
TEntity,
|
|
||||||
TContainer
|
|
||||||
>
|
|
||||||
} {
|
|
||||||
const model = DmlEntity.isDmlEntity(rawModel)
|
const model = DmlEntity.isDmlEntity(rawModel)
|
||||||
? toMikroORMEntity(rawModel)
|
? toMikroORMEntity(rawModel)
|
||||||
: rawModel
|
: rawModel
|
||||||
@@ -54,6 +96,10 @@ export function MedusaInternalService<
|
|||||||
class AbstractService_
|
class AbstractService_
|
||||||
implements ModulesSdkTypes.IMedusaInternalService<TEntity, TContainer>
|
implements ModulesSdkTypes.IMedusaInternalService<TEntity, TContainer>
|
||||||
{
|
{
|
||||||
|
[MedusaInternalServiceSymbol] = true
|
||||||
|
|
||||||
|
#eventSubscriber?: MedusaMikroOrmEventSubscriber
|
||||||
|
|
||||||
readonly __container__: TContainer;
|
readonly __container__: TContainer;
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
|
|
||||||
@@ -62,6 +108,10 @@ export function MedusaInternalService<
|
|||||||
this[propertyRepositoryName] = container[injectedRepositoryName]
|
this[propertyRepositoryName] = container[injectedRepositoryName]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setEventSubscriber(subscriber: MedusaMikroOrmEventSubscriber) {
|
||||||
|
this.#eventSubscriber = subscriber
|
||||||
|
}
|
||||||
|
|
||||||
static applyFreeTextSearchFilter(
|
static applyFreeTextSearchFilter(
|
||||||
filters: FilterQuery & { q?: string },
|
filters: FilterQuery & { q?: string },
|
||||||
config: FindConfig<any>
|
config: FindConfig<any>
|
||||||
@@ -223,6 +273,11 @@ export function MedusaInternalService<
|
|||||||
| InferEntityType<TEntity>[]
|
| InferEntityType<TEntity>[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerInternalServiceEventSubscriber(
|
||||||
|
sharedContext,
|
||||||
|
this.#eventSubscriber
|
||||||
|
)
|
||||||
|
|
||||||
const data_ = Array.isArray(data) ? data : [data]
|
const data_ = Array.isArray(data) ? data : [data]
|
||||||
const entities = await this[propertyRepositoryName].create(
|
const entities = await this[propertyRepositoryName].create(
|
||||||
data_,
|
data_,
|
||||||
@@ -260,6 +315,11 @@ export function MedusaInternalService<
|
|||||||
| InferEntityType<TEntity>[]
|
| InferEntityType<TEntity>[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerInternalServiceEventSubscriber(
|
||||||
|
sharedContext,
|
||||||
|
this.#eventSubscriber
|
||||||
|
)
|
||||||
|
|
||||||
let shouldReturnArray = false
|
let shouldReturnArray = false
|
||||||
if (Array.isArray(input)) {
|
if (Array.isArray(input)) {
|
||||||
shouldReturnArray = true
|
shouldReturnArray = true
|
||||||
@@ -419,6 +479,11 @@ export function MedusaInternalService<
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerInternalServiceEventSubscriber(
|
||||||
|
sharedContext,
|
||||||
|
this.#eventSubscriber
|
||||||
|
)
|
||||||
|
|
||||||
const primaryKeys = AbstractService_.retrievePrimaryKeys(model)
|
const primaryKeys = AbstractService_.retrievePrimaryKeys(model)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -467,10 +532,29 @@ export function MedusaInternalService<
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
return await this[propertyRepositoryName].delete(
|
const deletedIds = await this[propertyRepositoryName].delete(
|
||||||
deleteCriteria,
|
deleteCriteria,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Delete are handled a bit differently since we are going to the DB directly, therefore
|
||||||
|
// just like upsert with replace, we need to dispatch the events manually.
|
||||||
|
if (deletedIds.length) {
|
||||||
|
const manager = (sharedContext.transactionManager ??
|
||||||
|
sharedContext.manager) as EntityManager
|
||||||
|
const eventManager = manager.getEventManager()
|
||||||
|
|
||||||
|
deletedIds.forEach((id) => {
|
||||||
|
eventManager.dispatchEvent(EventType.afterDelete, {
|
||||||
|
entity: { id },
|
||||||
|
meta: {
|
||||||
|
className: model.name,
|
||||||
|
} as Parameters<typeof eventManager.dispatchEvent>[2],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return deletedIds
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager(propertyRepositoryName)
|
@InjectTransactionManager(propertyRepositoryName)
|
||||||
@@ -489,6 +573,11 @@ export function MedusaInternalService<
|
|||||||
return [[], {}]
|
return [[], {}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerInternalServiceEventSubscriber(
|
||||||
|
sharedContext,
|
||||||
|
this.#eventSubscriber
|
||||||
|
)
|
||||||
|
|
||||||
return await this[propertyRepositoryName].softDelete(
|
return await this[propertyRepositoryName].softDelete(
|
||||||
idsOrFilter,
|
idsOrFilter,
|
||||||
sharedContext
|
sharedContext
|
||||||
@@ -520,6 +609,11 @@ export function MedusaInternalService<
|
|||||||
data: any | any[],
|
data: any | any[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<InferEntityType<TEntity> | InferEntityType<TEntity>[]> {
|
): Promise<InferEntityType<TEntity> | InferEntityType<TEntity>[]> {
|
||||||
|
registerInternalServiceEventSubscriber(
|
||||||
|
sharedContext,
|
||||||
|
this.#eventSubscriber
|
||||||
|
)
|
||||||
|
|
||||||
const data_ = Array.isArray(data) ? data : [data]
|
const data_ = Array.isArray(data) ? data : [data]
|
||||||
const entities = await this[propertyRepositoryName].upsert(
|
const entities = await this[propertyRepositoryName].upsert(
|
||||||
data_,
|
data_,
|
||||||
@@ -556,10 +650,74 @@ export function MedusaInternalService<
|
|||||||
entities: InferEntityType<TEntity> | InferEntityType<TEntity>[]
|
entities: InferEntityType<TEntity> | InferEntityType<TEntity>[]
|
||||||
performedActions: PerformedActions
|
performedActions: PerformedActions
|
||||||
}> {
|
}> {
|
||||||
|
registerInternalServiceEventSubscriber(
|
||||||
|
sharedContext,
|
||||||
|
this.#eventSubscriber
|
||||||
|
)
|
||||||
|
|
||||||
const data_ = Array.isArray(data) ? data : [data]
|
const data_ = Array.isArray(data) ? data : [data]
|
||||||
const { entities, performedActions } = await this[
|
const { entities, performedActions } = await this[
|
||||||
propertyRepositoryName
|
propertyRepositoryName
|
||||||
].upsertWithReplace(data_, config, sharedContext)
|
].upsertWithReplace(data_, config, sharedContext)
|
||||||
|
|
||||||
|
const manager = (sharedContext.transactionManager ??
|
||||||
|
sharedContext.manager) as EntityManager
|
||||||
|
const eventManager = manager.getEventManager()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since the upsertWithReplace method is not emitting events, we need to do it manually
|
||||||
|
* by dispatching the events manually.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const createdEntities = !!Object.keys(performedActions.created).length
|
||||||
|
const updatedEntities = !!Object.keys(performedActions.updated).length
|
||||||
|
const deletedEntities = !!Object.keys(performedActions.deleted).length
|
||||||
|
|
||||||
|
if (createdEntities) {
|
||||||
|
Object.entries(
|
||||||
|
performedActions.created as Record<string, any[]>
|
||||||
|
).forEach(([modelName, entities]) => {
|
||||||
|
entities.forEach((entity) => {
|
||||||
|
eventManager.dispatchEvent(EventType.afterCreate, {
|
||||||
|
entity,
|
||||||
|
meta: {
|
||||||
|
className: modelName,
|
||||||
|
} as Parameters<typeof eventManager.dispatchEvent>[2],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedEntities) {
|
||||||
|
Object.entries(
|
||||||
|
performedActions.updated as Record<string, any[]>
|
||||||
|
).forEach(([modelName, entities]) => {
|
||||||
|
entities.forEach((entity) => {
|
||||||
|
eventManager.dispatchEvent(EventType.afterUpdate, {
|
||||||
|
entity,
|
||||||
|
meta: {
|
||||||
|
className: modelName,
|
||||||
|
} as Parameters<typeof eventManager.dispatchEvent>[2],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deletedEntities) {
|
||||||
|
Object.entries(
|
||||||
|
performedActions.deleted as Record<string, any[]>
|
||||||
|
).forEach(([modelName, entities]) => {
|
||||||
|
entities.forEach((entity) => {
|
||||||
|
eventManager.dispatchEvent(EventType.afterDelete, {
|
||||||
|
entity,
|
||||||
|
meta: {
|
||||||
|
className: modelName,
|
||||||
|
} as Parameters<typeof eventManager.dispatchEvent>[2],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entities: Array.isArray(data) ? entities : entities[0],
|
entities: Array.isArray(data) ? entities : entities[0],
|
||||||
performedActions,
|
performedActions,
|
||||||
@@ -567,5 +725,7 @@ export function MedusaInternalService<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return AbstractService_ as any
|
// We hide away the setEventSubscriber method from the public interface
|
||||||
|
// as it is not meant to be used by the user.
|
||||||
|
return AbstractService_ as unknown as InternalService
|
||||||
}
|
}
|
||||||
@@ -10,9 +10,9 @@ import {
|
|||||||
RestoreReturn,
|
RestoreReturn,
|
||||||
SoftDeleteReturn,
|
SoftDeleteReturn,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
|
import { EventArgs } from "@mikro-orm/core"
|
||||||
import {
|
import {
|
||||||
camelToSnakeCase,
|
camelToSnakeCase,
|
||||||
isString,
|
|
||||||
lowerCaseFirst,
|
lowerCaseFirst,
|
||||||
mapObjectTo,
|
mapObjectTo,
|
||||||
MapToConfig,
|
MapToConfig,
|
||||||
@@ -21,10 +21,12 @@ import {
|
|||||||
} from "../common"
|
} from "../common"
|
||||||
import { DmlEntity } from "../dml"
|
import { DmlEntity } from "../dml"
|
||||||
import { CommonEvents } from "../event-bus"
|
import { CommonEvents } from "../event-bus"
|
||||||
|
import { createMedusaMikroOrmEventSubscriber } from "./create-medusa-mikro-orm-event-subscriber"
|
||||||
import { EmitEvents, InjectManager, MedusaContext } from "./decorators"
|
import { EmitEvents, InjectManager, MedusaContext } from "./decorators"
|
||||||
import { Modules } from "./definition"
|
import { Modules } from "./definition"
|
||||||
import { moduleEventBuilderFactory } from "./event-builder-factory"
|
import { moduleEventBuilderFactory } from "./event-builder-factory"
|
||||||
import { buildModelsNameToLinkableKeysMap } from "./joiner-config-builder"
|
import { buildModelsNameToLinkableKeysMap } from "./joiner-config-builder"
|
||||||
|
import { isMedusaInternalService } from "./medusa-internal-service"
|
||||||
import {
|
import {
|
||||||
BaseMethods,
|
BaseMethods,
|
||||||
ExtractKeysFromConfig,
|
ExtractKeysFromConfig,
|
||||||
@@ -137,37 +139,6 @@ export function MedusaService<
|
|||||||
? ModelConfigurationsToConfigTemplate<TModels>
|
? ModelConfigurationsToConfigTemplate<TModels>
|
||||||
: ModelsConfig
|
: ModelsConfig
|
||||||
> {
|
> {
|
||||||
function emitSoftDeleteRestoreEvents(
|
|
||||||
this: AbstractModuleService_,
|
|
||||||
klassPrototype: any,
|
|
||||||
cascadedModelsMap: Record<string, string[]>,
|
|
||||||
action: string,
|
|
||||||
sharedContext: Context
|
|
||||||
) {
|
|
||||||
const joinerConfig = (
|
|
||||||
typeof this.__joinerConfig === "function"
|
|
||||||
? this.__joinerConfig()
|
|
||||||
: this.__joinerConfig
|
|
||||||
) as ModuleJoinerConfig
|
|
||||||
|
|
||||||
const emittedEntities = new Set<string>()
|
|
||||||
|
|
||||||
Object.entries(cascadedModelsMap).forEach(([linkableKey, ids]) => {
|
|
||||||
const entity = joinerConfig.linkableKeys?.[linkableKey]!
|
|
||||||
if (entity && !emittedEntities.has(entity)) {
|
|
||||||
emittedEntities.add(entity)
|
|
||||||
const linkableKeyEntity = camelToSnakeCase(entity).toLowerCase()
|
|
||||||
|
|
||||||
klassPrototype.aggregatedEvents.bind(this)({
|
|
||||||
action: action,
|
|
||||||
object: linkableKeyEntity,
|
|
||||||
data: { id: ids },
|
|
||||||
context: sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildAndAssignMethodImpl = function (
|
const buildAndAssignMethodImpl = function (
|
||||||
klassPrototype: any,
|
klassPrototype: any,
|
||||||
method: string,
|
method: string,
|
||||||
@@ -220,16 +191,9 @@ export function MedusaService<
|
|||||||
sharedContext: Context = {}
|
sharedContext: Context = {}
|
||||||
): Promise<T | T[]> {
|
): Promise<T | T[]> {
|
||||||
const service = this.__container__[serviceRegistrationName]
|
const service = this.__container__[serviceRegistrationName]
|
||||||
const models = await service.create(data, sharedContext)
|
const models_ = await service.create(data, sharedContext)
|
||||||
|
|
||||||
klassPrototype.aggregatedEvents.bind(this)({
|
return await this.baseRepository_.serialize<T | T[]>(models_)
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: camelToSnakeCase(modelName).toLowerCase(),
|
|
||||||
data: models,
|
|
||||||
context: sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<T | T[]>(models)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyMethod(methodImplementation, 1)
|
applyMethod(methodImplementation, 1)
|
||||||
@@ -244,13 +208,6 @@ export function MedusaService<
|
|||||||
const service = this.__container__[serviceRegistrationName]
|
const service = this.__container__[serviceRegistrationName]
|
||||||
const response = await service.update(data, sharedContext)
|
const response = await service.update(data, sharedContext)
|
||||||
|
|
||||||
klassPrototype.aggregatedEvents.bind(this)({
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: camelToSnakeCase(modelName).toLowerCase(),
|
|
||||||
data: response,
|
|
||||||
context: sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<T | T[]>(response)
|
return await this.baseRepository_.serialize<T | T[]>(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,19 +257,10 @@ export function MedusaService<
|
|||||||
? primaryKeyValues
|
? primaryKeyValues
|
||||||
: [primaryKeyValues]
|
: [primaryKeyValues]
|
||||||
|
|
||||||
const ids = await this.__container__[serviceRegistrationName].delete(
|
await this.__container__[serviceRegistrationName].delete(
|
||||||
primaryKeyValues_,
|
primaryKeyValues_,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
ids.map((id) =>
|
|
||||||
klassPrototype.aggregatedEvents.bind(this)({
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: camelToSnakeCase(modelName).toLowerCase(),
|
|
||||||
data: isString(id) ? { id: id } : id,
|
|
||||||
context: sharedContext,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyMethod(methodImplementation, 1)
|
applyMethod(methodImplementation, 1)
|
||||||
@@ -343,15 +291,6 @@ export function MedusaService<
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (mappedCascadedModelsMap) {
|
|
||||||
emitSoftDeleteRestoreEvents.bind(this)(
|
|
||||||
klassPrototype,
|
|
||||||
mappedCascadedModelsMap,
|
|
||||||
CommonEvents.DELETED,
|
|
||||||
sharedContext
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mappedCascadedModelsMap ? mappedCascadedModelsMap : void 0
|
return mappedCascadedModelsMap ? mappedCascadedModelsMap : void 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,15 +323,6 @@ export function MedusaService<
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (mappedCascadedModelsMap) {
|
|
||||||
emitSoftDeleteRestoreEvents.bind(this)(
|
|
||||||
klassPrototype,
|
|
||||||
mappedCascadedModelsMap,
|
|
||||||
CommonEvents.CREATED,
|
|
||||||
sharedContext
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mappedCascadedModelsMap ? mappedCascadedModelsMap : void 0
|
return mappedCascadedModelsMap ? mappedCascadedModelsMap : void 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,6 +354,41 @@ export function MedusaService<
|
|||||||
this.__container__ = container
|
this.__container__ = container
|
||||||
this.baseRepository_ = container.baseRepository
|
this.baseRepository_ = container.baseRepository
|
||||||
|
|
||||||
|
const joinerConfig = this.__joinerConfig?.()
|
||||||
|
/**
|
||||||
|
* Create a global subscriber to listen to all the entities mutations
|
||||||
|
* and forward them to the module service interceptEntityMutationEvents
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* Assign the global subscriber to all internal services or class that extends it
|
||||||
|
* such that it can attach it accordingly and forward the events to the module service.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (joinerConfig?.serviceName !== "index") {
|
||||||
|
let globalSubscriber!: ReturnType<
|
||||||
|
typeof createMedusaMikroOrmEventSubscriber
|
||||||
|
>
|
||||||
|
|
||||||
|
Object.keys(container)
|
||||||
|
.filter((key) => {
|
||||||
|
return key.endsWith("Service")
|
||||||
|
})
|
||||||
|
.forEach((key: string) => {
|
||||||
|
globalSubscriber ??= createMedusaMikroOrmEventSubscriber(
|
||||||
|
["__medusa_entities_subscriber__"],
|
||||||
|
this
|
||||||
|
)
|
||||||
|
try {
|
||||||
|
const service = container[key]
|
||||||
|
if (isMedusaInternalService(service)) {
|
||||||
|
service.setEventSubscriber(globalSubscriber)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Prevent circular issue which in that case would represent ourselves so we can skip
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const hasEventBusModuleService = Object.keys(this.__container__).find(
|
const hasEventBusModuleService = Object.keys(this.__container__).find(
|
||||||
(key) => key === Modules.EVENT_BUS
|
(key) => key === Modules.EVENT_BUS
|
||||||
)
|
)
|
||||||
@@ -433,9 +398,72 @@ export function MedusaService<
|
|||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
this[MedusaServiceModelNameToLinkableKeysMapSymbol] =
|
this[MedusaServiceModelNameToLinkableKeysMapSymbol] =
|
||||||
buildModelsNameToLinkableKeysMap(
|
buildModelsNameToLinkableKeysMap(joinerConfig?.linkableKeys ?? {})
|
||||||
this.__joinerConfig?.()?.linkableKeys ?? {}
|
}
|
||||||
)
|
|
||||||
|
/**
|
||||||
|
* @internal this method is meant to react to any event the orm might emit
|
||||||
|
* when an entity is being mutated (created, updated, deleted).
|
||||||
|
* The default implementation will handle all event to be emitted as part
|
||||||
|
* of the message aggregator from the context.
|
||||||
|
*
|
||||||
|
* If you want to handle the event differently, you can override this method.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* class MyService extends ModulesSdkUtils.MedusaService(models) {
|
||||||
|
* interceptEntityMutationEvents(event: "afterCreate" | "afterUpdate" | "afterUpsert" | "afterDelete", args: EventArgs<any>, context: Context) {
|
||||||
|
* console.log("interceptEntityMutationEvents", event, args.entity)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @param event - The event type
|
||||||
|
* @param args - The event arguments
|
||||||
|
* @param context - The context
|
||||||
|
*/
|
||||||
|
interceptEntityMutationEvents(
|
||||||
|
event: "afterCreate" | "afterUpdate" | "afterUpsert" | "afterDelete",
|
||||||
|
args: EventArgs<any>,
|
||||||
|
context: Context
|
||||||
|
) {
|
||||||
|
let action = ""
|
||||||
|
switch (event) {
|
||||||
|
case "afterCreate":
|
||||||
|
action = CommonEvents.CREATED
|
||||||
|
break
|
||||||
|
case "afterUpdate":
|
||||||
|
const isSoftDeleted =
|
||||||
|
!!args.changeSet?.entity.deleted_at &&
|
||||||
|
!args.changeSet?.originalEntity?.deleted_at
|
||||||
|
|
||||||
|
const isRestored =
|
||||||
|
!!args.changeSet?.originalEntity?.deleted_at &&
|
||||||
|
!args.changeSet?.entity.deleted_at
|
||||||
|
|
||||||
|
action = CommonEvents.UPDATED
|
||||||
|
|
||||||
|
if (isSoftDeleted) {
|
||||||
|
action = CommonEvents.DELETED
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRestored) {
|
||||||
|
action = CommonEvents.RESTORED
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
case "afterDelete":
|
||||||
|
action = CommonEvents.DELETED
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
const object = camelToSnakeCase(args.meta.className).toLowerCase()
|
||||||
|
|
||||||
|
this.aggregatedEvents({
|
||||||
|
action,
|
||||||
|
object,
|
||||||
|
data: { id: args.entity.id },
|
||||||
|
context,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -463,6 +491,10 @@ export function MedusaService<
|
|||||||
data: { id: any } | { id: any }[]
|
data: { id: any } | { id: any }[]
|
||||||
context: Context
|
context: Context
|
||||||
}) {
|
}) {
|
||||||
|
if (!context.messageAggregator) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const __joinerConfig = (
|
const __joinerConfig = (
|
||||||
typeof this.__joinerConfig === "function"
|
typeof this.__joinerConfig === "function"
|
||||||
? this.__joinerConfig()
|
? this.__joinerConfig()
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ import {
|
|||||||
Context,
|
Context,
|
||||||
FindConfig,
|
FindConfig,
|
||||||
IDmlEntity,
|
IDmlEntity,
|
||||||
|
InferEntityForModuleService,
|
||||||
|
InferEntityType,
|
||||||
Pluralize,
|
Pluralize,
|
||||||
Prettify,
|
Prettify,
|
||||||
RestoreReturn,
|
RestoreReturn,
|
||||||
SoftDeleteReturn,
|
SoftDeleteReturn,
|
||||||
InferEntityType,
|
|
||||||
InferEntityForModuleService,
|
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
|
import { EventArgs } from "@mikro-orm/core"
|
||||||
import { DmlEntity } from "../../dml"
|
import { DmlEntity } from "../../dml"
|
||||||
|
|
||||||
export type BaseMethods =
|
export type BaseMethods =
|
||||||
@@ -318,4 +319,22 @@ export type MedusaServiceReturnType<ModelsConfig extends Record<string, any>> =
|
|||||||
data: { id: any } | { id: any }[]
|
data: { id: any } | { id: any }[]
|
||||||
context: Context
|
context: Context
|
||||||
}): void
|
}): void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this method is meant to react to any event the orm might emit
|
||||||
|
* when an entity is being mutated (created, updated, deleted).
|
||||||
|
* The default implementation will handle all event to be emitted as part
|
||||||
|
* of the message aggregator from the context.
|
||||||
|
*
|
||||||
|
* If you want to handle the event differently, you can override this method.
|
||||||
|
*
|
||||||
|
* @param event - The event type
|
||||||
|
* @param args - The event arguments
|
||||||
|
* @param context - The context
|
||||||
|
*/
|
||||||
|
interceptEntityMutationEvents(
|
||||||
|
event: "afterCreate" | "afterUpdate" | "afterUpsert" | "afterDelete",
|
||||||
|
args: EventArgs<any>,
|
||||||
|
context: Context
|
||||||
|
): void
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
ApiKeyType,
|
ApiKeyType,
|
||||||
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isObject,
|
isObject,
|
||||||
@@ -65,11 +66,20 @@ export class ApiKeyModuleService
|
|||||||
return joinerConfig
|
return joinerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async deleteApiKeys(
|
async deleteApiKeys(
|
||||||
ids: string | string[],
|
ids: string | string[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
) {
|
||||||
|
return await this.deleteApiKeys_(ids, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async deleteApiKeys_(
|
||||||
|
ids: string | string[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
) {
|
) {
|
||||||
const apiKeyIds = Array.isArray(ids) ? ids : [ids]
|
const apiKeyIds = Array.isArray(ids) ? ids : [ids]
|
||||||
|
|
||||||
@@ -111,6 +121,7 @@ export class ApiKeyModuleService
|
|||||||
): Promise<ApiKeyTypes.ApiKeyDTO>
|
): Promise<ApiKeyTypes.ApiKeyDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
//@ts-expect-error
|
//@ts-expect-error
|
||||||
async createApiKeys(
|
async createApiKeys(
|
||||||
data: ApiKeyTypes.CreateApiKeyDTO | ApiKeyTypes.CreateApiKeyDTO[],
|
data: ApiKeyTypes.CreateApiKeyDTO | ApiKeyTypes.CreateApiKeyDTO[],
|
||||||
@@ -183,9 +194,20 @@ export class ApiKeyModuleService
|
|||||||
): Promise<ApiKeyTypes.ApiKeyDTO>
|
): Promise<ApiKeyTypes.ApiKeyDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertApiKeys(
|
async upsertApiKeys(
|
||||||
data: ApiKeyTypes.UpsertApiKeyDTO | ApiKeyTypes.UpsertApiKeyDTO[],
|
data: ApiKeyTypes.UpsertApiKeyDTO | ApiKeyTypes.UpsertApiKeyDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<ApiKeyTypes.ApiKeyDTO | ApiKeyTypes.ApiKeyDTO[]> {
|
||||||
|
const result = await this.upsertApiKeys_(data, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<ApiKeyTypes.ApiKeyDTO[]>(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertApiKeys_(
|
||||||
|
data: ApiKeyTypes.UpsertApiKeyDTO | ApiKeyTypes.UpsertApiKeyDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<ApiKeyTypes.ApiKeyDTO | ApiKeyTypes.ApiKeyDTO[]> {
|
): Promise<ApiKeyTypes.ApiKeyDTO | ApiKeyTypes.ApiKeyDTO[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter(
|
const forUpdate = input.filter(
|
||||||
@@ -205,9 +227,7 @@ export class ApiKeyModuleService
|
|||||||
)
|
)
|
||||||
const serializedResponse = await this.baseRepository_.serialize<
|
const serializedResponse = await this.baseRepository_.serialize<
|
||||||
ApiKeyTypes.ApiKeyDTO[]
|
ApiKeyTypes.ApiKeyDTO[]
|
||||||
>(createdApiKeys, {
|
>(createdApiKeys)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return serializedResponse.map(
|
return serializedResponse.map(
|
||||||
(key) =>
|
(key) =>
|
||||||
@@ -226,10 +246,7 @@ export class ApiKeyModuleService
|
|||||||
|
|
||||||
if (forUpdate.length) {
|
if (forUpdate.length) {
|
||||||
const op = async () => {
|
const op = async () => {
|
||||||
const updateResp = await this.updateApiKeys_(forUpdate, sharedContext)
|
return await this.updateApiKeys_(forUpdate, sharedContext)
|
||||||
return await this.baseRepository_.serialize<ApiKeyTypes.ApiKeyDTO[]>(
|
|
||||||
updateResp
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operations.push(op())
|
operations.push(op())
|
||||||
@@ -253,6 +270,7 @@ export class ApiKeyModuleService
|
|||||||
): Promise<ApiKeyTypes.ApiKeyDTO[]>
|
): Promise<ApiKeyTypes.ApiKeyDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
//@ts-expect-error
|
//@ts-expect-error
|
||||||
async updateApiKeys(
|
async updateApiKeys(
|
||||||
idOrSelector: string | FilterableApiKeyProps,
|
idOrSelector: string | FilterableApiKeyProps,
|
||||||
@@ -368,7 +386,9 @@ export class ApiKeyModuleService
|
|||||||
data: ApiKeyTypes.RevokeApiKeyDTO,
|
data: ApiKeyTypes.RevokeApiKeyDTO,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<ApiKeyTypes.ApiKeyDTO[]>
|
): Promise<ApiKeyTypes.ApiKeyDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async revoke(
|
async revoke(
|
||||||
idOrSelector: string | FilterableApiKeyProps,
|
idOrSelector: string | FilterableApiKeyProps,
|
||||||
data: ApiKeyTypes.RevokeApiKeyDTO,
|
data: ApiKeyTypes.RevokeApiKeyDTO,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
createRawPropertiesFromBigNumber,
|
createRawPropertiesFromBigNumber,
|
||||||
decorateCartTotals,
|
decorateCartTotals,
|
||||||
deduplicate,
|
deduplicate,
|
||||||
|
EmitEvents,
|
||||||
generateEntityId,
|
generateEntityId,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
@@ -269,6 +270,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.CartDTO>
|
): Promise<CartTypes.CartDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createCarts(
|
async createCarts(
|
||||||
data: CartTypes.CreateCartDTO[] | CartTypes.CreateCartDTO,
|
data: CartTypes.CreateCartDTO[] | CartTypes.CreateCartDTO,
|
||||||
@@ -340,6 +342,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.CartDTO[]>
|
): Promise<CartTypes.CartDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateCarts(
|
async updateCarts(
|
||||||
dataOrIdOrSelector:
|
dataOrIdOrSelector:
|
||||||
@@ -425,6 +428,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.CartLineItemDTO[]>
|
): Promise<CartTypes.CartLineItemDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addLineItems(
|
async addLineItems(
|
||||||
cartIdOrData:
|
cartIdOrData:
|
||||||
| string
|
| string
|
||||||
@@ -504,6 +508,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.CartLineItemDTO>
|
): Promise<CartTypes.CartLineItemDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateLineItems(
|
async updateLineItems(
|
||||||
lineItemIdOrDataOrSelector:
|
lineItemIdOrDataOrSelector:
|
||||||
@@ -606,6 +611,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.CartAddressDTO[]>
|
): Promise<CartTypes.CartAddressDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createAddresses(
|
async createAddresses(
|
||||||
data: CartTypes.CreateAddressDTO[] | CartTypes.CreateAddressDTO,
|
data: CartTypes.CreateAddressDTO[] | CartTypes.CreateAddressDTO,
|
||||||
@@ -645,6 +651,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.CartAddressDTO[]>
|
): Promise<CartTypes.CartAddressDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateAddresses(
|
async updateAddresses(
|
||||||
data: CartTypes.UpdateAddressDTO[] | CartTypes.UpdateAddressDTO,
|
data: CartTypes.UpdateAddressDTO[] | CartTypes.UpdateAddressDTO,
|
||||||
@@ -685,6 +692,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.CartShippingMethodDTO[]>
|
): Promise<CartTypes.CartShippingMethodDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addShippingMethods(
|
async addShippingMethods(
|
||||||
cartIdOrData:
|
cartIdOrData:
|
||||||
| string
|
| string
|
||||||
@@ -763,6 +771,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.LineItemAdjustmentDTO[]>
|
): Promise<CartTypes.LineItemAdjustmentDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addLineItemAdjustments(
|
async addLineItemAdjustments(
|
||||||
cartIdOrData:
|
cartIdOrData:
|
||||||
| string
|
| string
|
||||||
@@ -827,6 +836,7 @@ export default class CartModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertLineItemTaxLines(
|
async upsertLineItemTaxLines(
|
||||||
taxLines: (
|
taxLines: (
|
||||||
| CartTypes.CreateLineItemTaxLineDTO
|
| CartTypes.CreateLineItemTaxLineDTO
|
||||||
@@ -861,6 +871,7 @@ export default class CartModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertLineItemAdjustments(
|
async upsertLineItemAdjustments(
|
||||||
adjustments: (
|
adjustments: (
|
||||||
| CartTypes.CreateLineItemAdjustmentDTO
|
| CartTypes.CreateLineItemAdjustmentDTO
|
||||||
@@ -895,6 +906,7 @@ export default class CartModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertShippingMethodTaxLines(
|
async upsertShippingMethodTaxLines(
|
||||||
taxLines: (
|
taxLines: (
|
||||||
| CartTypes.CreateShippingMethodTaxLineDTO
|
| CartTypes.CreateShippingMethodTaxLineDTO
|
||||||
@@ -929,6 +941,7 @@ export default class CartModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertShippingMethodAdjustments(
|
async upsertShippingMethodAdjustments(
|
||||||
adjustments: (
|
adjustments: (
|
||||||
| CartTypes.CreateShippingMethodAdjustmentDTO
|
| CartTypes.CreateShippingMethodAdjustmentDTO
|
||||||
@@ -963,6 +976,7 @@ export default class CartModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async setLineItemAdjustments(
|
async setLineItemAdjustments(
|
||||||
cartId: string,
|
cartId: string,
|
||||||
adjustments: (
|
adjustments: (
|
||||||
@@ -1036,6 +1050,7 @@ export default class CartModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async setShippingMethodAdjustments(
|
async setShippingMethodAdjustments(
|
||||||
cartId: string,
|
cartId: string,
|
||||||
adjustments: (
|
adjustments: (
|
||||||
@@ -1122,6 +1137,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.ShippingMethodAdjustmentDTO[]>
|
): Promise<CartTypes.ShippingMethodAdjustmentDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addShippingMethodAdjustments(
|
async addShippingMethodAdjustments(
|
||||||
cartIdOrData:
|
cartIdOrData:
|
||||||
| string
|
| string
|
||||||
@@ -1212,6 +1228,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.LineItemTaxLineDTO[]>
|
): Promise<CartTypes.LineItemTaxLineDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addLineItemTaxLines(
|
async addLineItemTaxLines(
|
||||||
cartIdOrData:
|
cartIdOrData:
|
||||||
| string
|
| string
|
||||||
@@ -1275,6 +1292,7 @@ export default class CartModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async setLineItemTaxLines(
|
async setLineItemTaxLines(
|
||||||
cartId: string,
|
cartId: string,
|
||||||
taxLines: (
|
taxLines: (
|
||||||
@@ -1357,6 +1375,7 @@ export default class CartModuleService
|
|||||||
): Promise<CartTypes.ShippingMethodTaxLineDTO[]>
|
): Promise<CartTypes.ShippingMethodTaxLineDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addShippingMethodTaxLines(
|
async addShippingMethodTaxLines(
|
||||||
cartIdOrData:
|
cartIdOrData:
|
||||||
| string
|
| string
|
||||||
@@ -1422,6 +1441,7 @@ export default class CartModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async setShippingMethodTaxLines(
|
async setShippingMethodTaxLines(
|
||||||
cartId: string,
|
cartId: string,
|
||||||
taxLines: (
|
taxLines: (
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ import {
|
|||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isString,
|
isString,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaService,
|
MedusaService,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { EntityManager } from "@mikro-orm/core"
|
|
||||||
import {
|
import {
|
||||||
Customer,
|
Customer,
|
||||||
CustomerAddress,
|
CustomerAddress,
|
||||||
@@ -101,6 +101,7 @@ export default class CustomerModuleService
|
|||||||
): Promise<CustomerTypes.CustomerDTO[]>
|
): Promise<CustomerTypes.CustomerDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async createCustomers(
|
async createCustomers(
|
||||||
dataOrArray:
|
dataOrArray:
|
||||||
| CustomerTypes.CreateCustomerDTO
|
| CustomerTypes.CreateCustomerDTO
|
||||||
@@ -124,7 +125,7 @@ export default class CustomerModuleService
|
|||||||
| CustomerTypes.CreateCustomerDTO
|
| CustomerTypes.CreateCustomerDTO
|
||||||
| CustomerTypes.CreateCustomerDTO[],
|
| CustomerTypes.CreateCustomerDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<CustomerTypes.CustomerDTO[]> {
|
): Promise<InferEntityType<typeof Customer>[]> {
|
||||||
const data = Array.isArray(dataOrArray) ? dataOrArray : [dataOrArray]
|
const data = Array.isArray(dataOrArray) ? dataOrArray : [dataOrArray]
|
||||||
const customerAttributes = data.map(({ addresses, ...rest }) => {
|
const customerAttributes = data.map(({ addresses, ...rest }) => {
|
||||||
return rest
|
return rest
|
||||||
@@ -153,7 +154,7 @@ export default class CustomerModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
return customers as unknown as CustomerTypes.CustomerDTO[]
|
return customers
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -175,13 +176,33 @@ export default class CustomerModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<CustomerTypes.CustomerDTO[]>
|
): Promise<CustomerTypes.CustomerDTO[]>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateCustomers(
|
async updateCustomers(
|
||||||
idsOrSelector: string | string[] | CustomerTypes.FilterableCustomerProps,
|
idsOrSelector: string | string[] | CustomerTypes.FilterableCustomerProps,
|
||||||
data: CustomerTypes.CustomerUpdatableFields,
|
data: CustomerTypes.CustomerUpdatableFields,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@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:
|
let updateData:
|
||||||
| CustomerTypes.UpdateCustomerDTO
|
| CustomerTypes.UpdateCustomerDTO
|
||||||
| CustomerTypes.UpdateCustomerDTO[]
|
| CustomerTypes.UpdateCustomerDTO[]
|
||||||
@@ -212,13 +233,7 @@ export default class CustomerModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
return customers
|
||||||
CustomerTypes.CustomerDTO | CustomerTypes.CustomerDTO[]
|
|
||||||
>(customers, {
|
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return serialized
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -233,24 +248,43 @@ export default class CustomerModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createCustomerGroups(
|
async createCustomerGroups(
|
||||||
dataOrArrayOfData:
|
dataOrArrayOfData:
|
||||||
| CustomerTypes.CreateCustomerGroupDTO
|
| CustomerTypes.CreateCustomerGroupDTO
|
||||||
| CustomerTypes.CreateCustomerGroupDTO[],
|
| CustomerTypes.CreateCustomerGroupDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
) {
|
): Promise<
|
||||||
const groups = await this.customerGroupService_.create(
|
CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
|
||||||
|
> {
|
||||||
|
const groups = await this.createCustomerGroups_(
|
||||||
dataOrArrayOfData,
|
dataOrArrayOfData,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
|
CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
|
||||||
>(groups, {
|
>(groups)
|
||||||
populate: true,
|
}
|
||||||
})
|
|
||||||
|
@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
|
// @ts-expect-error
|
||||||
@@ -272,7 +306,8 @@ export default class CustomerModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
): Promise<CustomerTypes.CustomerGroupDTO[]>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateCustomerGroups(
|
async updateCustomerGroups(
|
||||||
groupIdOrSelector:
|
groupIdOrSelector:
|
||||||
@@ -281,7 +316,32 @@ export default class CustomerModuleService
|
|||||||
| CustomerTypes.FilterableCustomerGroupProps,
|
| CustomerTypes.FilterableCustomerGroupProps,
|
||||||
data: CustomerTypes.CustomerGroupUpdatableFields,
|
data: CustomerTypes.CustomerGroupUpdatableFields,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@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:
|
let updateData:
|
||||||
| CustomerTypes.UpdateCustomerGroupDTO
|
| CustomerTypes.UpdateCustomerGroupDTO
|
||||||
| CustomerTypes.UpdateCustomerGroupDTO[]
|
| CustomerTypes.UpdateCustomerGroupDTO[]
|
||||||
@@ -311,15 +371,10 @@ export default class CustomerModuleService
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (isString(groupIdOrSelector)) {
|
if (isString(groupIdOrSelector)) {
|
||||||
return await this.baseRepository_.serialize<CustomerTypes.CustomerGroupDTO>(
|
return groups[0]
|
||||||
groups[0],
|
|
||||||
{ populate: true }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return groups
|
||||||
CustomerTypes.CustomerGroupDTO[]
|
|
||||||
>(groups, { populate: true })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async addCustomerToGroup(
|
async addCustomerToGroup(
|
||||||
@@ -332,10 +387,21 @@ export default class CustomerModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<{ id: string }[]>
|
): Promise<{ id: string }[]>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addCustomerToGroup(
|
async addCustomerToGroup(
|
||||||
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@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 }[]> {
|
): Promise<{ id: string } | { id: string }[]> {
|
||||||
const groupCustomers = await this.customerGroupCustomerService_.create(
|
const groupCustomers = await this.customerGroupCustomerService_.create(
|
||||||
data,
|
data,
|
||||||
@@ -365,6 +431,7 @@ export default class CustomerModuleService
|
|||||||
): Promise<CustomerTypes.CustomerAddressDTO>
|
): Promise<CustomerTypes.CustomerAddressDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createCustomerAddresses(
|
async createCustomerAddresses(
|
||||||
data:
|
data:
|
||||||
@@ -419,7 +486,8 @@ export default class CustomerModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<CustomerTypes.CustomerAddressDTO[]>
|
): Promise<CustomerTypes.CustomerAddressDTO[]>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateCustomerAddresses(
|
async updateCustomerAddresses(
|
||||||
addressIdOrSelector:
|
addressIdOrSelector:
|
||||||
@@ -428,7 +496,32 @@ export default class CustomerModuleService
|
|||||||
| CustomerTypes.FilterableCustomerAddressProps,
|
| CustomerTypes.FilterableCustomerAddressProps,
|
||||||
data: CustomerTypes.UpdateCustomerAddressDTO,
|
data: CustomerTypes.UpdateCustomerAddressDTO,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@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:
|
let updateData:
|
||||||
| CustomerTypes.UpdateCustomerAddressDTO[]
|
| CustomerTypes.UpdateCustomerAddressDTO[]
|
||||||
| {
|
| {
|
||||||
@@ -459,17 +552,11 @@ export default class CustomerModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
await this.flush(sharedContext)
|
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
|
||||||
CustomerTypes.CustomerAddressDTO[]
|
|
||||||
>(addresses, { populate: true })
|
|
||||||
|
|
||||||
if (isString(addressIdOrSelector)) {
|
if (isString(addressIdOrSelector)) {
|
||||||
return serialized[0]
|
return addresses[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
return serialized
|
return addresses
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeCustomerFromGroup(
|
async removeCustomerFromGroup(
|
||||||
@@ -481,10 +568,19 @@ export default class CustomerModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<void>
|
): Promise<void>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async removeCustomerFromGroup(
|
async removeCustomerFromGroup(
|
||||||
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
await this.removeCustomerFromGroup_(data, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async removeCustomerFromGroup_(
|
||||||
|
data: CustomerTypes.GroupCustomerPair | CustomerTypes.GroupCustomerPair[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const pairs = Array.isArray(data) ? data : [data]
|
const pairs = Array.isArray(data) ? data : [data]
|
||||||
const groupCustomers = await this.customerGroupCustomerService_.list({
|
const groupCustomers = await this.customerGroupCustomerService_.list({
|
||||||
@@ -495,9 +591,4 @@ export default class CustomerModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async flush(context: Context) {
|
|
||||||
const em = (context.manager ?? context.transactionManager) as EntityManager
|
|
||||||
await em.flush()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+20
-34
@@ -219,7 +219,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([fulfillmentSets[i].id]),
|
id: fulfillmentSets[i].id,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@@ -338,7 +338,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([fulfillmentSets[i].id]),
|
id: fulfillmentSets[i].id,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -346,9 +346,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: fulfillmentSets[i].service_zones[0].id,
|
||||||
fulfillmentSets[i].service_zones[0].id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@@ -514,7 +512,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([fulfillmentSets[i].id]),
|
id: fulfillmentSets[i].id,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -522,9 +520,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: fulfillmentSets[i].service_zones[0].id,
|
||||||
fulfillmentSets[i].service_zones[0].id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -532,9 +528,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: fulfillmentSets[i].service_zones[0].geo_zones[0].id,
|
||||||
fulfillmentSets[i].service_zones[0].geo_zones[0].id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@@ -724,7 +718,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(updatedFulfillmentSets).toHaveLength(2)
|
expect(updatedFulfillmentSets).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(1)
|
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(2)
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const currentFullfillmentSet = fullfillmentSets.find(
|
const currentFullfillmentSet = fullfillmentSets.find(
|
||||||
@@ -746,7 +740,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "updated",
|
action: "updated",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([currentFullfillmentSet.id]),
|
id: currentFullfillmentSet.id,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@@ -1075,7 +1069,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(updatedFulfillmentSets).toHaveLength(2)
|
expect(updatedFulfillmentSets).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(5)
|
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(10)
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
||||||
@@ -1116,7 +1110,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "updated",
|
action: "updated",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([expectedFulfillmentSet.id]),
|
id: expectedFulfillmentSet.id,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -1124,9 +1118,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: expectedFulfillmentSet.service_zones[0].id,
|
||||||
expectedFulfillmentSet.service_zones[0].id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -1134,9 +1126,8 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: expectedFulfillmentSet.service_zones[0].geo_zones[0]
|
||||||
expectedFulfillmentSet.service_zones[0].geo_zones[0].id,
|
.id,
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -1144,9 +1135,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "deleted",
|
action: "deleted",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: originalFulfillmentSet.service_zones[0].id,
|
||||||
originalFulfillmentSet.service_zones[0].id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -1154,9 +1143,8 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "deleted",
|
action: "deleted",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: originalFulfillmentSet.service_zones[0].geo_zones[0]
|
||||||
originalFulfillmentSet.service_zones[0].geo_zones[0].id,
|
.id,
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@@ -1245,7 +1233,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(updatedFulfillmentSets).toHaveLength(2)
|
expect(updatedFulfillmentSets).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(3)
|
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(6)
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
||||||
@@ -1290,7 +1278,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "updated",
|
action: "updated",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([expectedFulfillmentSet.id]),
|
id: expectedFulfillmentSet.id,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -1298,7 +1286,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([createdServiceZone.id]),
|
id: createdServiceZone.id,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -1306,9 +1294,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: createdServiceZone.geo_zones[0].id,
|
||||||
createdServiceZone.geo_zones[0].id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
|
|||||||
+21
-15
@@ -152,15 +152,21 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(5)
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||||
[
|
expect.arrayContaining([
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.FULFILLMENT_CREATED,
|
eventName: FulfillmentEvents.FULFILLMENT_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "fulfillment",
|
object: "fulfillment",
|
||||||
data: { id: fulfillment.id },
|
data: { id: fulfillment.id },
|
||||||
}),
|
}),
|
||||||
|
buildExpectedEventMessageShape({
|
||||||
|
eventName: FulfillmentEvents.FULFILLMENT_UPDATED,
|
||||||
|
action: "updated",
|
||||||
|
object: "fulfillment",
|
||||||
|
data: { id: fulfillment.id },
|
||||||
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.FULFILLMENT_ADDRESS_CREATED,
|
eventName: FulfillmentEvents.FULFILLMENT_ADDRESS_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
@@ -179,7 +185,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
object: "fulfillment_label",
|
object: "fulfillment_label",
|
||||||
data: { id: fulfillment.labels[0].id },
|
data: { id: fulfillment.labels[0].id },
|
||||||
}),
|
}),
|
||||||
],
|
]),
|
||||||
{
|
{
|
||||||
internal: true,
|
internal: true,
|
||||||
}
|
}
|
||||||
@@ -244,15 +250,21 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(5)
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||||
[
|
expect.arrayContaining([
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.FULFILLMENT_CREATED,
|
eventName: FulfillmentEvents.FULFILLMENT_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "fulfillment",
|
object: "fulfillment",
|
||||||
data: { id: fulfillment.id },
|
data: { id: fulfillment.id },
|
||||||
}),
|
}),
|
||||||
|
buildExpectedEventMessageShape({
|
||||||
|
eventName: FulfillmentEvents.FULFILLMENT_UPDATED,
|
||||||
|
action: "updated",
|
||||||
|
object: "fulfillment",
|
||||||
|
data: { id: fulfillment.id },
|
||||||
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.FULFILLMENT_ADDRESS_CREATED,
|
eventName: FulfillmentEvents.FULFILLMENT_ADDRESS_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
@@ -271,7 +283,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
object: "fulfillment_label",
|
object: "fulfillment_label",
|
||||||
data: { id: fulfillment.labels[0].id },
|
data: { id: fulfillment.labels[0].id },
|
||||||
}),
|
}),
|
||||||
],
|
]),
|
||||||
{
|
{
|
||||||
internal: true,
|
internal: true,
|
||||||
}
|
}
|
||||||
@@ -383,15 +395,9 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(3)
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||||
[
|
expect.arrayContaining([
|
||||||
buildExpectedEventMessageShape({
|
|
||||||
eventName: FulfillmentEvents.FULFILLMENT_UPDATED,
|
|
||||||
action: "updated",
|
|
||||||
object: "fulfillment",
|
|
||||||
data: { id: updatedFulfillment.id },
|
|
||||||
}),
|
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.FULFILLMENT_LABEL_DELETED,
|
eventName: FulfillmentEvents.FULFILLMENT_LABEL_DELETED,
|
||||||
action: "deleted",
|
action: "deleted",
|
||||||
@@ -410,7 +416,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
object: "fulfillment_label",
|
object: "fulfillment_label",
|
||||||
data: { id: label4.id },
|
data: { id: label4.id },
|
||||||
}),
|
}),
|
||||||
],
|
]),
|
||||||
{
|
{
|
||||||
internal: true,
|
internal: true,
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -154,7 +154,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
const geoZones = await service.createGeoZones(data)
|
const geoZones = await service.createGeoZones(data)
|
||||||
|
|
||||||
expect(geoZones).toHaveLength(2)
|
expect(geoZones).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
||||||
|
|
||||||
let i = 0
|
let i = 0
|
||||||
for (const data_ of data) {
|
for (const data_ of data) {
|
||||||
@@ -172,7 +172,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: { id: expect.arrayContaining([geoZones[i].id]) },
|
data: { id: geoZones[i].id },
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
@@ -331,7 +331,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
const updatedGeoZones = await service.updateGeoZones(updateData)
|
const updatedGeoZones = await service.updateGeoZones(updateData)
|
||||||
|
|
||||||
expect(updatedGeoZones).toHaveLength(2)
|
expect(updatedGeoZones).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const expectedGeoZone = updatedGeoZones.find(
|
const expectedGeoZone = updatedGeoZones.find(
|
||||||
@@ -352,7 +352,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.GEO_ZONE_UPDATED,
|
eventName: FulfillmentEvents.GEO_ZONE_UPDATED,
|
||||||
action: "updated",
|
action: "updated",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: { id: expect.arrayContaining([expectedGeoZone.id]) },
|
data: { id: expectedGeoZone.id },
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
|
|||||||
+3
-3
@@ -371,7 +371,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||||
[
|
expect.arrayContaining([
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.GEO_ZONE_DELETED,
|
eventName: FulfillmentEvents.GEO_ZONE_DELETED,
|
||||||
action: "deleted",
|
action: "deleted",
|
||||||
@@ -396,7 +396,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: { id: usGeoZone.id },
|
data: { id: usGeoZone.id },
|
||||||
}),
|
}),
|
||||||
],
|
]),
|
||||||
{
|
{
|
||||||
internal: true,
|
internal: true,
|
||||||
}
|
}
|
||||||
@@ -510,7 +510,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
|
|
||||||
expect(updatedServiceZones).toHaveLength(2)
|
expect(updatedServiceZones).toHaveLength(2)
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(3) // Since the update only calls create and update which are already tested, only check the length
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(6) // Since the update only calls create and update which are already tested, only check the length
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const expectedServiceZone = updatedServiceZones.find(
|
const expectedServiceZone = updatedServiceZones.find(
|
||||||
|
|||||||
+33
-33
@@ -522,7 +522,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(3)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(3)
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||||
[
|
expect.arrayContaining([
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.SHIPPING_OPTION_CREATED,
|
eventName: FulfillmentEvents.SHIPPING_OPTION_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
@@ -541,7 +541,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
object: "shipping_option_rule",
|
object: "shipping_option_rule",
|
||||||
data: { id: createdShippingOption.rules[0].id },
|
data: { id: createdShippingOption.rules[0].id },
|
||||||
}),
|
}),
|
||||||
],
|
]),
|
||||||
{
|
{
|
||||||
internal: true,
|
internal: true,
|
||||||
}
|
}
|
||||||
@@ -582,7 +582,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(createdShippingOptions).toHaveLength(2)
|
expect(createdShippingOptions).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(3)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(6)
|
||||||
|
|
||||||
let i = 0
|
let i = 0
|
||||||
for (const data_ of createData) {
|
for (const data_ of createData) {
|
||||||
@@ -620,9 +620,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "shipping_option",
|
object: "shipping_option",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: createdShippingOptions[i].id,
|
||||||
createdShippingOptions[i].id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -630,9 +628,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "shipping_option_type",
|
object: "shipping_option_type",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: createdShippingOptions[i].type.id,
|
||||||
createdShippingOptions[i].type.id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -640,9 +636,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "shipping_option_rule",
|
object: "shipping_option_rule",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: createdShippingOptions[i].rules[0].id,
|
||||||
createdShippingOptions[i].rules[0].id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@@ -823,7 +817,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(5)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
@@ -832,12 +826,6 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
object: "shipping_option",
|
object: "shipping_option",
|
||||||
data: { id: updatedShippingOption.id },
|
data: { id: updatedShippingOption.id },
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
|
||||||
eventName: FulfillmentEvents.SHIPPING_OPTION_TYPE_DELETED,
|
|
||||||
action: "deleted",
|
|
||||||
object: "shipping_option_type",
|
|
||||||
data: { id: shippingOption.type.id },
|
|
||||||
}),
|
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.SHIPPING_OPTION_TYPE_CREATED,
|
eventName: FulfillmentEvents.SHIPPING_OPTION_TYPE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
@@ -1374,14 +1362,16 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
])
|
])
|
||||||
|
|
||||||
// Test with full address including postal expression
|
// Test with full address including postal expression
|
||||||
const shippingOptions = await service.listShippingOptionsForContext({
|
const shippingOptions = await service.listShippingOptionsForContext(
|
||||||
|
{
|
||||||
address: {
|
address: {
|
||||||
country_code: "US",
|
country_code: "US",
|
||||||
province_code: "CA",
|
province_code: "CA",
|
||||||
city: "Los Angeles",
|
city: "Los Angeles",
|
||||||
postal_expression: "90210",
|
postal_expression: "90210",
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
expect(shippingOptions).toHaveLength(1)
|
expect(shippingOptions).toHaveLength(1)
|
||||||
})
|
})
|
||||||
@@ -1419,13 +1409,15 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
])
|
])
|
||||||
|
|
||||||
// Test with city but no postal expression
|
// Test with city but no postal expression
|
||||||
const shippingOptions = await service.listShippingOptionsForContext({
|
const shippingOptions = await service.listShippingOptionsForContext(
|
||||||
|
{
|
||||||
address: {
|
address: {
|
||||||
country_code: "US",
|
country_code: "US",
|
||||||
province_code: "CA",
|
province_code: "CA",
|
||||||
city: "San Francisco",
|
city: "San Francisco",
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
expect(shippingOptions).toHaveLength(1)
|
expect(shippingOptions).toHaveLength(1)
|
||||||
})
|
})
|
||||||
@@ -1462,12 +1454,14 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
])
|
])
|
||||||
|
|
||||||
// Test with province but no city
|
// Test with province but no city
|
||||||
const shippingOptions = await service.listShippingOptionsForContext({
|
const shippingOptions = await service.listShippingOptionsForContext(
|
||||||
|
{
|
||||||
address: {
|
address: {
|
||||||
country_code: "US",
|
country_code: "US",
|
||||||
province_code: "NY",
|
province_code: "NY",
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
expect(shippingOptions).toHaveLength(1)
|
expect(shippingOptions).toHaveLength(1)
|
||||||
})
|
})
|
||||||
@@ -1503,11 +1497,13 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
])
|
])
|
||||||
|
|
||||||
// Test with only country
|
// Test with only country
|
||||||
const shippingOptions = await service.listShippingOptionsForContext({
|
const shippingOptions = await service.listShippingOptionsForContext(
|
||||||
|
{
|
||||||
address: {
|
address: {
|
||||||
country_code: "CA",
|
country_code: "CA",
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
expect(shippingOptions).toHaveLength(1)
|
expect(shippingOptions).toHaveLength(1)
|
||||||
})
|
})
|
||||||
@@ -1758,14 +1754,16 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
])
|
])
|
||||||
|
|
||||||
// Address with undefined fields should still match if country matches
|
// Address with undefined fields should still match if country matches
|
||||||
const shippingOptions = await service.listShippingOptionsForContext({
|
const shippingOptions = await service.listShippingOptionsForContext(
|
||||||
|
{
|
||||||
address: {
|
address: {
|
||||||
country_code: "US",
|
country_code: "US",
|
||||||
province_code: undefined,
|
province_code: undefined,
|
||||||
city: undefined,
|
city: undefined,
|
||||||
postal_expression: undefined,
|
postal_expression: undefined,
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
)
|
||||||
expect(shippingOptions).toHaveLength(1)
|
expect(shippingOptions).toHaveLength(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1831,7 +1829,8 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Create shipping options for each zone
|
// Create shipping options for each zone
|
||||||
const [usOption, europeOption, canadaOption] = await service.createShippingOptions([
|
const [usOption, europeOption, canadaOption] =
|
||||||
|
await service.createShippingOptions([
|
||||||
generateCreateShippingOptionsData({
|
generateCreateShippingOptionsData({
|
||||||
name: "US Shipping",
|
name: "US Shipping",
|
||||||
service_zone_id: fulfillmentSet.service_zones[0].id,
|
service_zone_id: fulfillmentSet.service_zones[0].id,
|
||||||
@@ -1970,7 +1969,8 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Create shipping options with different prices for each zone
|
// Create shipping options with different prices for each zone
|
||||||
const [broadOption, californiaOption, laOption] = await service.createShippingOptions([
|
const [broadOption, californiaOption, laOption] =
|
||||||
|
await service.createShippingOptions([
|
||||||
generateCreateShippingOptionsData({
|
generateCreateShippingOptionsData({
|
||||||
name: "Standard US Shipping",
|
name: "Standard US Shipping",
|
||||||
service_zone_id: fulfillmentSet.service_zones[0].id,
|
service_zone_id: fulfillmentSet.service_zones[0].id,
|
||||||
@@ -2001,7 +2001,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(shippingOptions).toHaveLength(3)
|
expect(shippingOptions).toHaveLength(3)
|
||||||
const laIds = shippingOptions.map(opt => opt.id)
|
const laIds = shippingOptions.map((opt) => opt.id)
|
||||||
expect(laIds).toContain(broadOption.id)
|
expect(laIds).toContain(broadOption.id)
|
||||||
expect(laIds).toContain(californiaOption.id)
|
expect(laIds).toContain(californiaOption.id)
|
||||||
expect(laIds).toContain(laOption.id)
|
expect(laIds).toContain(laOption.id)
|
||||||
@@ -2015,7 +2015,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(shippingOptions).toHaveLength(2)
|
expect(shippingOptions).toHaveLength(2)
|
||||||
const caIds = shippingOptions.map(opt => opt.id)
|
const caIds = shippingOptions.map((opt) => opt.id)
|
||||||
expect(caIds).toContain(broadOption.id)
|
expect(caIds).toContain(broadOption.id)
|
||||||
expect(caIds).toContain(californiaOption.id)
|
expect(caIds).toContain(californiaOption.id)
|
||||||
expect(caIds).not.toContain(laOption.id)
|
expect(caIds).not.toContain(laOption.id)
|
||||||
|
|||||||
+2
-4
@@ -100,7 +100,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
await service.createShippingProfiles(createData)
|
await service.createShippingProfiles(createData)
|
||||||
|
|
||||||
expect(createdShippingProfiles).toHaveLength(2)
|
expect(createdShippingProfiles).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
||||||
|
|
||||||
let i = 0
|
let i = 0
|
||||||
for (const data_ of createData) {
|
for (const data_ of createData) {
|
||||||
@@ -118,9 +118,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
action: "created",
|
action: "created",
|
||||||
object: "shipping_profile",
|
object: "shipping_profile",
|
||||||
data: {
|
data: {
|
||||||
id: expect.arrayContaining([
|
id: createdShippingProfiles[i].id,
|
||||||
createdShippingProfiles[i].id,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
|
|||||||
@@ -47,18 +47,9 @@ import {
|
|||||||
ShippingOptionType,
|
ShippingOptionType,
|
||||||
ShippingProfile,
|
ShippingProfile,
|
||||||
} from "@models"
|
} from "@models"
|
||||||
import {
|
import { isContextValid, Rule, validateAndNormalizeRules } from "@utils"
|
||||||
buildCreatedFulfillmentEvents,
|
|
||||||
buildCreatedFulfillmentSetEvents,
|
|
||||||
buildCreatedServiceZoneEvents,
|
|
||||||
eventBuilders,
|
|
||||||
isContextValid,
|
|
||||||
Rule,
|
|
||||||
validateAndNormalizeRules,
|
|
||||||
} from "@utils"
|
|
||||||
import { joinerConfig } from "../joiner-config"
|
import { joinerConfig } from "../joiner-config"
|
||||||
import { UpdateShippingOptionsInput } from "../types/service"
|
import { UpdateShippingOptionsInput } from "../types/service"
|
||||||
import { buildCreatedShippingOptionEvents } from "../utils/events"
|
|
||||||
import FulfillmentProviderService from "./fulfillment-provider"
|
import FulfillmentProviderService from "./fulfillment-provider"
|
||||||
|
|
||||||
const generateMethodForModels = {
|
const generateMethodForModels = {
|
||||||
@@ -70,7 +61,7 @@ const generateMethodForModels = {
|
|||||||
ShippingOptionRule,
|
ShippingOptionRule,
|
||||||
ShippingOptionType,
|
ShippingOptionType,
|
||||||
FulfillmentProvider,
|
FulfillmentProvider,
|
||||||
// Not adding Fulfillment to not auto generate the methods under the hood and only provide the methods we want to expose8
|
// Not adding Fulfillment to not auto generate the methods under the hood and only provide the methods we want to expose
|
||||||
}
|
}
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
@@ -339,11 +330,6 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
buildCreatedFulfillmentSetEvents({
|
|
||||||
fulfillmentSets: createdFulfillmentSets,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return createdFulfillmentSets
|
return createdFulfillmentSets
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,11 +391,6 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
buildCreatedServiceZoneEvents({
|
|
||||||
serviceZones: createdServiceZones,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return createdServiceZones
|
return createdServiceZones
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,11 +449,6 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
buildCreatedShippingOptionEvents({
|
|
||||||
shippingOptions: createdSO,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return createdSO
|
return createdSO
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,7 +463,7 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<FulfillmentTypes.ShippingProfileDTO>
|
): Promise<FulfillmentTypes.ShippingProfileDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createShippingProfiles(
|
async createShippingProfiles(
|
||||||
@@ -503,11 +479,6 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
eventBuilders.createdShippingProfile({
|
|
||||||
data: createdShippingProfiles,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
| FulfillmentTypes.ShippingProfileDTO
|
| FulfillmentTypes.ShippingProfileDTO
|
||||||
| FulfillmentTypes.ShippingProfileDTO[]
|
| FulfillmentTypes.ShippingProfileDTO[]
|
||||||
@@ -561,11 +532,6 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
eventBuilders.createdGeoZone({
|
|
||||||
data: createdGeoZones,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<FulfillmentTypes.GeoZoneDTO[]>(
|
return await this.baseRepository_.serialize<FulfillmentTypes.GeoZoneDTO[]>(
|
||||||
Array.isArray(data) ? createdGeoZones : createdGeoZones[0]
|
Array.isArray(data) ? createdGeoZones : createdGeoZones[0]
|
||||||
)
|
)
|
||||||
@@ -629,11 +595,6 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
eventBuilders.createdShippingOptionRule({
|
|
||||||
data: createdSORules.map((sor) => ({ id: sor.id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return createdSORules
|
return createdSORules
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,11 +640,6 @@ export default class FulfillmentModuleService
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
buildCreatedFulfillmentEvents({
|
|
||||||
fulfillments: [fulfillment],
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||||
fulfillment
|
fulfillment
|
||||||
)
|
)
|
||||||
@@ -754,11 +710,6 @@ export default class FulfillmentModuleService
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
buildCreatedFulfillmentEvents({
|
|
||||||
fulfillments: [fulfillment],
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||||
fulfillment
|
fulfillment
|
||||||
)
|
)
|
||||||
@@ -943,15 +894,6 @@ export default class FulfillmentModuleService
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (serviceZoneIdsToDelete.length) {
|
if (serviceZoneIdsToDelete.length) {
|
||||||
eventBuilders.deletedServiceZone({
|
|
||||||
data: serviceZoneIdsToDelete.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.deletedGeoZone({
|
|
||||||
data: geoZoneIdsToDelete.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
await promiseAll([
|
await promiseAll([
|
||||||
this.geoZoneService_.delete(
|
this.geoZoneService_.delete(
|
||||||
{
|
{
|
||||||
@@ -973,32 +915,6 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
eventBuilders.updatedFulfillmentSet({
|
|
||||||
data: updatedFulfillmentSets,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
const createdServiceZoneIds: string[] = []
|
|
||||||
const createdGeoZoneIds = updatedFulfillmentSets
|
|
||||||
.flatMap((f) =>
|
|
||||||
[...f.service_zones].flatMap((serviceZone) => {
|
|
||||||
if (!existingServiceZoneIds.includes(serviceZone.id)) {
|
|
||||||
createdServiceZoneIds.push(serviceZone.id)
|
|
||||||
}
|
|
||||||
return serviceZone.geo_zones.map((g) => g.id)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.filter((id) => !existingGeoZoneIds.includes(id))
|
|
||||||
|
|
||||||
eventBuilders.createdServiceZone({
|
|
||||||
data: createdServiceZoneIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.createdGeoZone({
|
|
||||||
data: createdGeoZoneIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data)
|
return Array.isArray(data)
|
||||||
? updatedFulfillmentSets
|
? updatedFulfillmentSets
|
||||||
: updatedFulfillmentSets[0]
|
: updatedFulfillmentSets[0]
|
||||||
@@ -1187,11 +1103,6 @@ export default class FulfillmentModuleService
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (geoZoneIdsToDelete.length) {
|
if (geoZoneIdsToDelete.length) {
|
||||||
eventBuilders.deletedGeoZone({
|
|
||||||
data: geoZoneIdsToDelete.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.geoZoneService_.delete(
|
await this.geoZoneService_.delete(
|
||||||
{
|
{
|
||||||
id: geoZoneIdsToDelete,
|
id: geoZoneIdsToDelete,
|
||||||
@@ -1205,26 +1116,6 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
eventBuilders.updatedServiceZone({
|
|
||||||
data: updatedServiceZones,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
const createdGeoZoneIds = updatedServiceZones
|
|
||||||
.flatMap((serviceZone) => {
|
|
||||||
return serviceZone.geo_zones.map((g) => g.id)
|
|
||||||
})
|
|
||||||
.filter((id) => !existingGeoZoneIds.includes(id))
|
|
||||||
|
|
||||||
eventBuilders.createdGeoZone({
|
|
||||||
data: createdGeoZoneIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.updatedGeoZone({
|
|
||||||
data: updatedGeoZoneIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data) ? updatedServiceZones : updatedServiceZones[0]
|
return Array.isArray(data) ? updatedServiceZones : updatedServiceZones[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1485,11 +1376,6 @@ export default class FulfillmentModuleService
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (ruleIdsToDelete.length) {
|
if (ruleIdsToDelete.length) {
|
||||||
eventBuilders.deletedShippingOptionRule({
|
|
||||||
data: ruleIdsToDelete.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.shippingOptionRuleService_.delete(
|
await this.shippingOptionRuleService_.delete(
|
||||||
ruleIdsToDelete,
|
ruleIdsToDelete,
|
||||||
sharedContext
|
sharedContext
|
||||||
@@ -1501,71 +1387,11 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
this.handleShippingOptionUpdateEvents({
|
|
||||||
shippingOptionsData: dataArray,
|
|
||||||
updatedShippingOptions,
|
|
||||||
optionTypeDeletedIds,
|
|
||||||
updatedRuleIds,
|
|
||||||
existingRuleIds,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data)
|
return Array.isArray(data)
|
||||||
? updatedShippingOptions
|
? updatedShippingOptions
|
||||||
: updatedShippingOptions[0]
|
: updatedShippingOptions[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleShippingOptionUpdateEvents({
|
|
||||||
shippingOptionsData,
|
|
||||||
updatedShippingOptions,
|
|
||||||
optionTypeDeletedIds,
|
|
||||||
updatedRuleIds,
|
|
||||||
existingRuleIds,
|
|
||||||
sharedContext,
|
|
||||||
}) {
|
|
||||||
eventBuilders.updatedShippingOption({
|
|
||||||
data: updatedShippingOptions,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.deletedShippingOptionType({
|
|
||||||
data: optionTypeDeletedIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
const createdOptionTypeIds = updatedShippingOptions
|
|
||||||
.filter((so) => {
|
|
||||||
const updateData = shippingOptionsData.find((sod) => sod.id === so.id)
|
|
||||||
return isObject(updateData?.type) && !("id" in updateData.type)
|
|
||||||
})
|
|
||||||
.map((so) => so.type.id)
|
|
||||||
|
|
||||||
eventBuilders.createdShippingOptionType({
|
|
||||||
data: createdOptionTypeIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
const createdRuleIds = updatedShippingOptions
|
|
||||||
.flatMap((so) =>
|
|
||||||
[...so.rules].map((rule) => {
|
|
||||||
if (existingRuleIds.includes(rule.id)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return rule.id
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.filter((id): id is string => !!id)
|
|
||||||
|
|
||||||
eventBuilders.createdShippingOptionRule({
|
|
||||||
data: createdRuleIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.updatedShippingOptionRule({
|
|
||||||
data: updatedRuleIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async upsertShippingOptions(
|
async upsertShippingOptions(
|
||||||
data: FulfillmentTypes.UpsertShippingOptionDTO[],
|
data: FulfillmentTypes.UpsertShippingOptionDTO[],
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
@@ -1652,7 +1478,8 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<FulfillmentTypes.ShippingOptionTypeDTO>
|
): Promise<FulfillmentTypes.ShippingOptionTypeDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertShippingOptionTypes(
|
async upsertShippingOptionTypes(
|
||||||
data:
|
data:
|
||||||
| FulfillmentTypes.UpsertShippingOptionTypeDTO[]
|
| FulfillmentTypes.UpsertShippingOptionTypeDTO[]
|
||||||
@@ -1662,12 +1489,7 @@ export default class FulfillmentModuleService
|
|||||||
| FulfillmentTypes.ShippingOptionTypeDTO[]
|
| FulfillmentTypes.ShippingOptionTypeDTO[]
|
||||||
| FulfillmentTypes.ShippingOptionTypeDTO
|
| FulfillmentTypes.ShippingOptionTypeDTO
|
||||||
> {
|
> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const results = await this.updateShippingOptionTypes_(data, sharedContext)
|
||||||
|
|
||||||
const results = await this.shippingOptionTypeService_.upsert(
|
|
||||||
input,
|
|
||||||
sharedContext
|
|
||||||
)
|
|
||||||
|
|
||||||
const allTypes = await this.baseRepository_.serialize<
|
const allTypes = await this.baseRepository_.serialize<
|
||||||
| FulfillmentTypes.ShippingOptionTypeDTO[]
|
| FulfillmentTypes.ShippingOptionTypeDTO[]
|
||||||
@@ -1677,6 +1499,23 @@ export default class FulfillmentModuleService
|
|||||||
return Array.isArray(data) ? allTypes : allTypes[0]
|
return Array.isArray(data) ? allTypes : allTypes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async updateShippingOptionTypes_(
|
||||||
|
data:
|
||||||
|
| FulfillmentTypes.UpsertShippingOptionTypeDTO[]
|
||||||
|
| FulfillmentTypes.UpsertShippingOptionTypeDTO,
|
||||||
|
sharedContext: Context
|
||||||
|
): Promise<InferEntityType<typeof ShippingOptionType>[]> {
|
||||||
|
const input = Array.isArray(data) ? data : [data]
|
||||||
|
|
||||||
|
const results = await this.shippingOptionTypeService_.upsert(
|
||||||
|
input,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
updateShippingOptionTypes(
|
updateShippingOptionTypes(
|
||||||
id: string,
|
id: string,
|
||||||
@@ -1691,6 +1530,7 @@ export default class FulfillmentModuleService
|
|||||||
): Promise<FulfillmentTypes.ShippingOptionTypeDTO[]>
|
): Promise<FulfillmentTypes.ShippingOptionTypeDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateShippingOptionTypes(
|
async updateShippingOptionTypes(
|
||||||
idOrSelector: string | FulfillmentTypes.FilterableShippingOptionTypeProps,
|
idOrSelector: string | FulfillmentTypes.FilterableShippingOptionTypeProps,
|
||||||
@@ -1747,7 +1587,8 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<FulfillmentTypes.ShippingProfileDTO>
|
): Promise<FulfillmentTypes.ShippingProfileDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateShippingProfiles(
|
async updateShippingProfiles(
|
||||||
idOrSelector: string | FulfillmentTypes.FilterableShippingProfileProps,
|
idOrSelector: string | FulfillmentTypes.FilterableShippingProfileProps,
|
||||||
@@ -1756,6 +1597,25 @@ export default class FulfillmentModuleService
|
|||||||
): Promise<
|
): Promise<
|
||||||
FulfillmentTypes.ShippingProfileDTO | FulfillmentTypes.ShippingProfileDTO[]
|
FulfillmentTypes.ShippingProfileDTO | FulfillmentTypes.ShippingProfileDTO[]
|
||||||
> {
|
> {
|
||||||
|
const profiles = await this.updateShippingProfiles_(
|
||||||
|
idOrSelector,
|
||||||
|
data,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
const updatedProfiles = await this.baseRepository_.serialize<
|
||||||
|
FulfillmentTypes.ShippingProfileDTO[]
|
||||||
|
>(profiles)
|
||||||
|
|
||||||
|
return isString(idOrSelector) ? updatedProfiles[0] : updatedProfiles
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async updateShippingProfiles_(
|
||||||
|
idOrSelector: string | FulfillmentTypes.FilterableShippingProfileProps,
|
||||||
|
data: FulfillmentTypes.UpdateShippingProfileDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof ShippingProfile>[]> {
|
||||||
let normalizedInput: ({
|
let normalizedInput: ({
|
||||||
id: string
|
id: string
|
||||||
} & FulfillmentTypes.UpdateShippingProfileDTO)[] = []
|
} & FulfillmentTypes.UpdateShippingProfileDTO)[] = []
|
||||||
@@ -1784,11 +1644,7 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
const updatedProfiles = await this.baseRepository_.serialize<
|
return profiles
|
||||||
FulfillmentTypes.ShippingProfileDTO[]
|
|
||||||
>(profiles)
|
|
||||||
|
|
||||||
return isString(idOrSelector) ? updatedProfiles[0] : updatedProfiles
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async upsertShippingProfiles(
|
async upsertShippingProfiles(
|
||||||
@@ -1800,7 +1656,8 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<FulfillmentTypes.ShippingProfileDTO>
|
): Promise<FulfillmentTypes.ShippingProfileDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertShippingProfiles(
|
async upsertShippingProfiles(
|
||||||
data:
|
data:
|
||||||
| FulfillmentTypes.UpsertShippingProfileDTO[]
|
| FulfillmentTypes.UpsertShippingProfileDTO[]
|
||||||
@@ -1808,6 +1665,24 @@ export default class FulfillmentModuleService
|
|||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<
|
): Promise<
|
||||||
FulfillmentTypes.ShippingProfileDTO[] | FulfillmentTypes.ShippingProfileDTO
|
FulfillmentTypes.ShippingProfileDTO[] | FulfillmentTypes.ShippingProfileDTO
|
||||||
|
> {
|
||||||
|
const profiles = await this.upsertShippingProfiles_(data, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<
|
||||||
|
| FulfillmentTypes.ShippingProfileDTO[]
|
||||||
|
| FulfillmentTypes.ShippingProfileDTO
|
||||||
|
>(Array.isArray(data) ? profiles : profiles[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertShippingProfiles_(
|
||||||
|
data:
|
||||||
|
| FulfillmentTypes.UpsertShippingProfileDTO[]
|
||||||
|
| FulfillmentTypes.UpsertShippingProfileDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<
|
||||||
|
| InferEntityType<typeof ShippingProfile>[]
|
||||||
|
| InferEntityType<typeof ShippingProfile>
|
||||||
> {
|
> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter((prof) => !!prof.id)
|
const forUpdate = input.filter((prof) => !!prof.id)
|
||||||
@@ -1831,13 +1706,7 @@ export default class FulfillmentModuleService
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = [...created, ...updated]
|
return [...created, ...updated]
|
||||||
const allProfiles = await this.baseRepository_.serialize<
|
|
||||||
| FulfillmentTypes.ShippingProfileDTO[]
|
|
||||||
| FulfillmentTypes.ShippingProfileDTO
|
|
||||||
>(result)
|
|
||||||
|
|
||||||
return Array.isArray(data) ? allProfiles : allProfiles[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -1873,11 +1742,6 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
eventBuilders.updatedGeoZone({
|
|
||||||
data: updatedGeoZones,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.GeoZoneDTO[]
|
FulfillmentTypes.GeoZoneDTO[]
|
||||||
>(updatedGeoZones)
|
>(updatedGeoZones)
|
||||||
@@ -1940,11 +1804,6 @@ export default class FulfillmentModuleService
|
|||||||
const updatedShippingOptionRules =
|
const updatedShippingOptionRules =
|
||||||
await this.shippingOptionRuleService_.update(data_, sharedContext)
|
await this.shippingOptionRuleService_.update(data_, sharedContext)
|
||||||
|
|
||||||
eventBuilders.updatedShippingOptionRule({
|
|
||||||
data: updatedShippingOptionRules.map((rule) => ({ id: rule.id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data)
|
return Array.isArray(data)
|
||||||
? updatedShippingOptionRules
|
? updatedShippingOptionRules
|
||||||
: updatedShippingOptionRules[0]
|
: updatedShippingOptionRules[0]
|
||||||
@@ -1980,9 +1839,6 @@ export default class FulfillmentModuleService
|
|||||||
)
|
)
|
||||||
|
|
||||||
const updatedLabelIds: string[] = []
|
const updatedLabelIds: string[] = []
|
||||||
let deletedLabelIds: string[] = []
|
|
||||||
|
|
||||||
const existingLabelIds = existingFulfillment.labels.map((label) => label.id)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @note
|
* @note
|
||||||
@@ -1995,12 +1851,6 @@ export default class FulfillmentModuleService
|
|||||||
* and we also need to emit the events later on.
|
* and we also need to emit the events later on.
|
||||||
*/
|
*/
|
||||||
if (isDefined(data.labels) && isPresent(data.labels)) {
|
if (isDefined(data.labels) && isPresent(data.labels)) {
|
||||||
const dataLabelIds: string[] = data.labels
|
|
||||||
.filter((label): label is { id: string } => "id" in label)
|
|
||||||
.map((label) => label.id)
|
|
||||||
|
|
||||||
deletedLabelIds = arrayDifference(existingLabelIds, dataLabelIds)
|
|
||||||
|
|
||||||
for (let label of data.labels) {
|
for (let label of data.labels) {
|
||||||
if (!("id" in label)) {
|
if (!("id" in label)) {
|
||||||
continue
|
continue
|
||||||
@@ -2029,49 +1879,9 @@ export default class FulfillmentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
this.handleFulfillmentUpdateEvents(
|
|
||||||
fulfillment,
|
|
||||||
existingLabelIds,
|
|
||||||
updatedLabelIds,
|
|
||||||
deletedLabelIds,
|
|
||||||
sharedContext
|
|
||||||
)
|
|
||||||
|
|
||||||
return fulfillment
|
return fulfillment
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleFulfillmentUpdateEvents(
|
|
||||||
fulfillment: InferEntityType<typeof Fulfillment>,
|
|
||||||
existingLabelIds: string[],
|
|
||||||
updatedLabelIds: string[],
|
|
||||||
deletedLabelIds: string[],
|
|
||||||
sharedContext: Context
|
|
||||||
) {
|
|
||||||
eventBuilders.updatedFulfillment({
|
|
||||||
data: [{ id: fulfillment.id }],
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
eventBuilders.deletedFulfillmentLabel({
|
|
||||||
data: deletedLabelIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
eventBuilders.updatedFulfillmentLabel({
|
|
||||||
data: updatedLabelIds.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
const createdLabels = fulfillment.labels.filter((label) => {
|
|
||||||
return !existingLabelIds.includes(label.id)
|
|
||||||
})
|
|
||||||
|
|
||||||
eventBuilders.createdFulfillmentLabel({
|
|
||||||
data: createdLabels.map((label) => ({ id: label.id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
async cancelFulfillment(
|
async cancelFulfillment(
|
||||||
@@ -2106,11 +1916,6 @@ export default class FulfillmentModuleService
|
|||||||
},
|
},
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
eventBuilders.updatedFulfillment({
|
|
||||||
data: [{ id }],
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await this.baseRepository_.serialize<FulfillmentDTO>(
|
const result = await this.baseRepository_.serialize<FulfillmentDTO>(
|
||||||
@@ -2211,6 +2016,7 @@ export default class FulfillmentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async deleteShippingProfiles(
|
async deleteShippingProfiles(
|
||||||
ids: string | string[],
|
ids: string | string[],
|
||||||
@@ -2226,6 +2032,7 @@ export default class FulfillmentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async softDeleteShippingProfiles<
|
async softDeleteShippingProfiles<
|
||||||
TReturnableLinkableKeys extends string = string
|
TReturnableLinkableKeys extends string = string
|
||||||
|
|||||||
+33
-7
@@ -436,17 +436,32 @@ moduleIntegrationTestRunner<IInventoryService>({
|
|||||||
|
|
||||||
const updated = await service.updateReservationItems(update)
|
const updated = await service.updateReservationItems(update)
|
||||||
|
|
||||||
|
const inventoryLevel =
|
||||||
|
await service.retrieveInventoryLevelByItemAndLocation(
|
||||||
|
reservationItem.inventory_item_id,
|
||||||
|
"location-1"
|
||||||
|
)
|
||||||
|
|
||||||
expect(updated).toEqual(expect.objectContaining(update))
|
expect(updated).toEqual(expect.objectContaining(update))
|
||||||
|
|
||||||
|
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(eventBusSpy.mock.calls[0][0]).toHaveLength(2)
|
||||||
expect(eventBusSpy).toHaveBeenNthCalledWith(
|
expect(eventBusSpy).toHaveBeenNthCalledWith(
|
||||||
1,
|
1,
|
||||||
[
|
expect.arrayContaining([
|
||||||
composeMessage(InventoryEvents.RESERVATION_ITEM_UPDATED, {
|
composeMessage(InventoryEvents.RESERVATION_ITEM_UPDATED, {
|
||||||
data: { id: reservationItem.id },
|
data: { id: reservationItem.id },
|
||||||
object: "reservation-item",
|
object: "reservation_item",
|
||||||
source: Modules.INVENTORY,
|
source: Modules.INVENTORY,
|
||||||
action: CommonEvents.UPDATED,
|
action: CommonEvents.UPDATED,
|
||||||
}),
|
}),
|
||||||
],
|
composeMessage(InventoryEvents.INVENTORY_LEVEL_UPDATED, {
|
||||||
|
data: { id: inventoryLevel.id },
|
||||||
|
object: "inventory_level",
|
||||||
|
source: Modules.INVENTORY,
|
||||||
|
action: CommonEvents.UPDATED,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
{
|
{
|
||||||
internal: true,
|
internal: true,
|
||||||
}
|
}
|
||||||
@@ -457,19 +472,30 @@ moduleIntegrationTestRunner<IInventoryService>({
|
|||||||
quantity: 10,
|
quantity: 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eventBusSpy.mockClear()
|
||||||
|
|
||||||
const updated2 = await service.updateReservationItems(update2)
|
const updated2 = await service.updateReservationItems(update2)
|
||||||
|
|
||||||
expect(updated2).toEqual(expect.objectContaining(update2))
|
expect(updated2).toEqual(expect.objectContaining(update2))
|
||||||
|
|
||||||
|
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(eventBusSpy.mock.calls[0][0]).toHaveLength(2)
|
||||||
expect(eventBusSpy).toHaveBeenNthCalledWith(
|
expect(eventBusSpy).toHaveBeenNthCalledWith(
|
||||||
2,
|
1,
|
||||||
[
|
expect.arrayContaining([
|
||||||
composeMessage(InventoryEvents.RESERVATION_ITEM_UPDATED, {
|
composeMessage(InventoryEvents.RESERVATION_ITEM_UPDATED, {
|
||||||
data: { id: reservationItem.id },
|
data: { id: reservationItem.id },
|
||||||
object: "reservation-item",
|
object: "reservation_item",
|
||||||
source: Modules.INVENTORY,
|
source: Modules.INVENTORY,
|
||||||
action: CommonEvents.UPDATED,
|
action: CommonEvents.UPDATED,
|
||||||
}),
|
}),
|
||||||
],
|
composeMessage(InventoryEvents.INVENTORY_LEVEL_UPDATED, {
|
||||||
|
data: { id: inventoryLevel.id },
|
||||||
|
object: "inventory_level",
|
||||||
|
source: Modules.INVENTORY,
|
||||||
|
action: CommonEvents.UPDATED,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
{
|
{
|
||||||
internal: true,
|
internal: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,19 +15,15 @@ import {
|
|||||||
import {
|
import {
|
||||||
arrayDifference,
|
arrayDifference,
|
||||||
BigNumber,
|
BigNumber,
|
||||||
CommonEvents,
|
|
||||||
EmitEvents,
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
InventoryEvents,
|
|
||||||
isDefined,
|
isDefined,
|
||||||
isString,
|
isString,
|
||||||
MathBN,
|
MathBN,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
MedusaService,
|
MedusaService,
|
||||||
moduleEventBuilderFactory,
|
|
||||||
Modules,
|
|
||||||
partitionArray,
|
partitionArray,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { InventoryItem, InventoryLevel, ReservationItem } from "@models"
|
import { InventoryItem, InventoryLevel, ReservationItem } from "@models"
|
||||||
@@ -249,21 +245,9 @@ export default class InventoryModuleService
|
|||||||
const toCreate = Array.isArray(input) ? input : [input]
|
const toCreate = Array.isArray(input) ? input : [input]
|
||||||
const created = await this.createReservationItems_(toCreate, context)
|
const created = await this.createReservationItems_(toCreate, context)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "reservation-item",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_CREATED,
|
|
||||||
})({
|
|
||||||
data: created,
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
|
|
||||||
const serializedReservations = await this.baseRepository_.serialize<
|
const serializedReservations = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.ReservationItemDTO[] | InventoryTypes.ReservationItemDTO
|
InventoryTypes.ReservationItemDTO[] | InventoryTypes.ReservationItemDTO
|
||||||
>(created, {
|
>(created)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(input)
|
return Array.isArray(input)
|
||||||
? serializedReservations
|
? serializedReservations
|
||||||
@@ -350,21 +334,9 @@ export default class InventoryModuleService
|
|||||||
)
|
)
|
||||||
const result = await this.createInventoryItems_(toCreate, context)
|
const result = await this.createInventoryItems_(toCreate, context)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "inventory-item",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.INVENTORY_ITEM_CREATED,
|
|
||||||
})({
|
|
||||||
data: result,
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
|
|
||||||
const serializedItems = await this.baseRepository_.serialize<
|
const serializedItems = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.InventoryItemDTO | InventoryTypes.InventoryItemDTO[]
|
InventoryTypes.InventoryItemDTO | InventoryTypes.InventoryItemDTO[]
|
||||||
>(result, {
|
>(result)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(input) ? serializedItems : serializedItems[0]
|
return Array.isArray(input) ? serializedItems : serializedItems[0]
|
||||||
}
|
}
|
||||||
@@ -374,7 +346,7 @@ export default class InventoryModuleService
|
|||||||
input: InventoryTypes.CreateInventoryItemInput[],
|
input: InventoryTypes.CreateInventoryItemInput[],
|
||||||
@MedusaContext() context: Context = {}
|
@MedusaContext() context: Context = {}
|
||||||
): Promise<InventoryTypes.InventoryItemDTO[]> {
|
): Promise<InventoryTypes.InventoryItemDTO[]> {
|
||||||
return await this.inventoryItemService_.create(input)
|
return await this.inventoryItemService_.create(input, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -405,21 +377,9 @@ export default class InventoryModuleService
|
|||||||
|
|
||||||
const created = await this.createInventoryLevels_(toCreate, context)
|
const created = await this.createInventoryLevels_(toCreate, context)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "inventory-level",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_CREATED,
|
|
||||||
})({
|
|
||||||
data: created,
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.InventoryLevelDTO[] | InventoryTypes.InventoryLevelDTO
|
InventoryTypes.InventoryLevelDTO[] | InventoryTypes.InventoryLevelDTO
|
||||||
>(created, {
|
>(created)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(input) ? serialized : serialized[0]
|
return Array.isArray(input) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
@@ -460,21 +420,9 @@ export default class InventoryModuleService
|
|||||||
|
|
||||||
const result = await this.updateInventoryItems_(updates, context)
|
const result = await this.updateInventoryItems_(updates, context)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "inventory-item",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.INVENTORY_ITEM_UPDATED,
|
|
||||||
})({
|
|
||||||
data: result,
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
|
|
||||||
const serializedItems = await this.baseRepository_.serialize<
|
const serializedItems = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.InventoryItemDTO | InventoryTypes.InventoryItemDTO[]
|
InventoryTypes.InventoryItemDTO | InventoryTypes.InventoryItemDTO[]
|
||||||
>(result, {
|
>(result)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(input) ? serializedItems : serializedItems[0]
|
return Array.isArray(input) ? serializedItems : serializedItems[0]
|
||||||
}
|
}
|
||||||
@@ -489,7 +437,7 @@ export default class InventoryModuleService
|
|||||||
return await this.inventoryItemService_.update(input, context)
|
return await this.inventoryItemService_.update(input, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
async deleteInventoryItemLevelByLocationId(
|
async deleteInventoryItemLevelByLocationId(
|
||||||
locationId: string | string[],
|
locationId: string | string[],
|
||||||
@@ -500,16 +448,6 @@ export default class InventoryModuleService
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "inventory-level",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_DELETED,
|
|
||||||
})({
|
|
||||||
data: result[0],
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,16 +470,6 @@ export default class InventoryModuleService
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "inventory-level",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_DELETED,
|
|
||||||
})({
|
|
||||||
data: { id: inventoryLevel.id },
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!inventoryLevel) {
|
if (!inventoryLevel) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -577,21 +505,9 @@ export default class InventoryModuleService
|
|||||||
|
|
||||||
const levels = await this.updateInventoryLevels_(input, context)
|
const levels = await this.updateInventoryLevels_(input, context)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "inventory-level",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_UPDATED,
|
|
||||||
})({
|
|
||||||
data: levels,
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
|
|
||||||
const updatedLevels = await this.baseRepository_.serialize<
|
const updatedLevels = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.InventoryLevelDTO | InventoryTypes.InventoryLevelDTO[]
|
InventoryTypes.InventoryLevelDTO | InventoryTypes.InventoryLevelDTO[]
|
||||||
>(levels, {
|
>(levels)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(updates) ? updatedLevels : updatedLevels[0]
|
return Array.isArray(updates) ? updatedLevels : updatedLevels[0]
|
||||||
}
|
}
|
||||||
@@ -659,21 +575,9 @@ export default class InventoryModuleService
|
|||||||
const update = Array.isArray(input) ? input : [input]
|
const update = Array.isArray(input) ? input : [input]
|
||||||
const result = await this.updateReservationItems_(update, context)
|
const result = await this.updateReservationItems_(update, context)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "reservation-item",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_UPDATED,
|
|
||||||
})({
|
|
||||||
data: result,
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.ReservationItemDTO | InventoryTypes.ReservationItemDTO[]
|
InventoryTypes.ReservationItemDTO | InventoryTypes.ReservationItemDTO[]
|
||||||
>(result, {
|
>(result)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(input) ? serialized : serialized[0]
|
return Array.isArray(input) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
@@ -807,33 +711,47 @@ export default class InventoryModuleService
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async softDeleteReservationItems(
|
async softDeleteReservationItems(
|
||||||
ids: string | string[],
|
ids: string | string[],
|
||||||
config?: SoftDeleteReturn<string>,
|
config?: SoftDeleteReturn<string>,
|
||||||
@MedusaContext() context: Context = {}
|
@MedusaContext() context: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
return await this.softDeleteReservationItems_(ids, config, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async softDeleteReservationItems_(
|
||||||
|
ids: string | string[],
|
||||||
|
config?: SoftDeleteReturn<string>,
|
||||||
|
@MedusaContext() context: Context = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const reservations: InventoryTypes.ReservationItemDTO[] =
|
const reservations: InventoryTypes.ReservationItemDTO[] =
|
||||||
await super.listReservationItems({ id: ids }, {}, context)
|
await super.listReservationItems({ id: ids }, {}, context)
|
||||||
|
|
||||||
const result = await super.softDeleteReservationItems(
|
await super.softDeleteReservationItems({ id: ids }, config, context)
|
||||||
{ id: ids },
|
|
||||||
config,
|
|
||||||
context
|
|
||||||
)
|
|
||||||
|
|
||||||
await this.adjustInventoryLevelsForReservationsDeletion(
|
await this.adjustInventoryLevelsForReservationsDeletion(
|
||||||
reservations,
|
reservations,
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
result
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
|
// @ts-expect-error
|
||||||
|
async restoreReservationItems(
|
||||||
|
ids: string | string[],
|
||||||
|
config?: RestoreReturn<string>,
|
||||||
|
@MedusaContext() context: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
return await this.restoreReservationItems_(ids, config, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
// @ts-expect-error
|
protected async restoreReservationItems_(
|
||||||
async restoreReservationItems(
|
|
||||||
ids: string | string[],
|
ids: string | string[],
|
||||||
config?: RestoreReturn<string>,
|
config?: RestoreReturn<string>,
|
||||||
@MedusaContext() context: Context = {}
|
@MedusaContext() context: Context = {}
|
||||||
@@ -849,11 +767,19 @@ export default class InventoryModuleService
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
async deleteReservationItemByLocationId(
|
async deleteReservationItemByLocationId(
|
||||||
locationId: string | string[],
|
locationId: string | string[],
|
||||||
@MedusaContext() context: Context = {}
|
@MedusaContext() context: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
return await this.deleteReservationItemByLocationId_(locationId, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async deleteReservationItemByLocationId_(
|
||||||
|
locationId: string | string[],
|
||||||
|
@MedusaContext() context: Context = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const reservations: InventoryTypes.ReservationItemDTO[] =
|
const reservations: InventoryTypes.ReservationItemDTO[] =
|
||||||
await this.listReservationItems({ location_id: locationId }, {}, context)
|
await this.listReservationItems({ location_id: locationId }, {}, context)
|
||||||
@@ -863,16 +789,6 @@ export default class InventoryModuleService
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "reservation-item",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_DELETED,
|
|
||||||
})({
|
|
||||||
data: reservations,
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.adjustInventoryLevelsForReservationsDeletion(
|
await this.adjustInventoryLevelsForReservationsDeletion(
|
||||||
reservations,
|
reservations,
|
||||||
context
|
context
|
||||||
@@ -885,11 +801,19 @@ export default class InventoryModuleService
|
|||||||
* @param context
|
* @param context
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
async deleteReservationItemsByLineItem(
|
async deleteReservationItemsByLineItem(
|
||||||
lineItemId: string | string[],
|
lineItemId: string | string[],
|
||||||
@MedusaContext() context: Context = {}
|
@MedusaContext() context: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
return await this.deleteReservationItemsByLineItem_(lineItemId, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async deleteReservationItemsByLineItem_(
|
||||||
|
lineItemId: string | string[],
|
||||||
|
@MedusaContext() context: Context = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const reservations: InventoryTypes.ReservationItemDTO[] =
|
const reservations: InventoryTypes.ReservationItemDTO[] =
|
||||||
await this.listReservationItems({ line_item_id: lineItemId }, {}, context)
|
await this.listReservationItems({ line_item_id: lineItemId }, {}, context)
|
||||||
@@ -903,16 +827,6 @@ export default class InventoryModuleService
|
|||||||
reservations,
|
reservations,
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "reservation-item",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_DELETED,
|
|
||||||
})({
|
|
||||||
data: reservations,
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -921,11 +835,19 @@ export default class InventoryModuleService
|
|||||||
* @param context
|
* @param context
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
async restoreReservationItemsByLineItem(
|
async restoreReservationItemsByLineItem(
|
||||||
lineItemId: string | string[],
|
lineItemId: string | string[],
|
||||||
@MedusaContext() context: Context = {}
|
@MedusaContext() context: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
return await this.restoreReservationItemsByLineItem_(lineItemId, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async restoreReservationItemsByLineItem_(
|
||||||
|
lineItemId: string | string[],
|
||||||
|
@MedusaContext() context: Context = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const reservations: InventoryTypes.ReservationItemDTO[] =
|
const reservations: InventoryTypes.ReservationItemDTO[] =
|
||||||
await this.listReservationItems({ line_item_id: lineItemId }, {}, context)
|
await this.listReservationItems({ line_item_id: lineItemId }, {}, context)
|
||||||
@@ -939,16 +861,6 @@ export default class InventoryModuleService
|
|||||||
reservations,
|
reservations,
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "reservation-item",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_CREATED,
|
|
||||||
})({
|
|
||||||
data: reservations,
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1008,23 +920,10 @@ export default class InventoryModuleService
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
results.push(result)
|
results.push(result)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "inventory-level",
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_UPDATED,
|
|
||||||
})({
|
|
||||||
data: { id: result.id },
|
|
||||||
sharedContext: context,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<InventoryTypes.InventoryLevelDTO>(
|
return await this.baseRepository_.serialize<InventoryTypes.InventoryLevelDTO>(
|
||||||
Array.isArray(inventoryItemIdOrData) ? results : results[0],
|
Array.isArray(inventoryItemIdOrData) ? results : results[0]
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-4
@@ -43,6 +43,10 @@ moduleIntegrationTestRunner<INotificationModuleService>({
|
|||||||
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
eventBusEmitSpy.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
it(`should export the appropriate linkable configuration`, () => {
|
it(`should export the appropriate linkable configuration`, () => {
|
||||||
const linkable = Module(Modules.NOTIFICATION, {
|
const linkable = Module(Modules.NOTIFICATION, {
|
||||||
service: NotificationModuleService,
|
service: NotificationModuleService,
|
||||||
@@ -119,16 +123,24 @@ moduleIntegrationTestRunner<INotificationModuleService>({
|
|||||||
|
|
||||||
const result = await service.createNotifications(notification)
|
const result = await service.createNotifications(notification)
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
expect(eventBusEmitSpy).toHaveBeenCalledTimes(1)
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
||||||
[
|
expect(eventBusEmitSpy).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
expect.arrayContaining([
|
||||||
composeMessage(NotificationEvents.NOTIFICATION_CREATED, {
|
composeMessage(NotificationEvents.NOTIFICATION_CREATED, {
|
||||||
data: { id: result.id },
|
data: { id: result.id },
|
||||||
object: "notification",
|
object: "notification",
|
||||||
source: Modules.NOTIFICATION,
|
source: Modules.NOTIFICATION,
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
}),
|
}),
|
||||||
],
|
composeMessage(NotificationEvents.NOTIFICATION_UPDATED, {
|
||||||
|
data: { id: result.id },
|
||||||
|
object: "notification",
|
||||||
|
source: Modules.NOTIFICATION,
|
||||||
|
action: CommonEvents.UPDATED,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
{
|
{
|
||||||
internal: true,
|
internal: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import {
|
|||||||
promiseAll,
|
promiseAll,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { Notification } from "@models"
|
import { Notification } from "@models"
|
||||||
import { eventBuilders } from "@utils"
|
|
||||||
import NotificationProviderService from "./notification-provider"
|
import NotificationProviderService from "./notification-provider"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
@@ -91,11 +90,6 @@ export default class NotificationModuleService
|
|||||||
NotificationTypes.NotificationDTO[]
|
NotificationTypes.NotificationDTO[]
|
||||||
>(createdNotifications)
|
>(createdNotifications)
|
||||||
|
|
||||||
eventBuilders.createdNotification({
|
|
||||||
data: serialized,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data) ? serialized : serialized[0]
|
return Array.isArray(data) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import {
|
|
||||||
CommonEvents,
|
|
||||||
moduleEventBuilderFactory,
|
|
||||||
Modules,
|
|
||||||
NotificationEvents,
|
|
||||||
} from "@medusajs/framework/utils"
|
|
||||||
|
|
||||||
export const eventBuilders = {
|
|
||||||
createdNotification: moduleEventBuilderFactory({
|
|
||||||
source: Modules.NOTIFICATION,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "notification",
|
|
||||||
eventName: NotificationEvents.NOTIFICATION_CREATED,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * from "./events"
|
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -41,6 +41,7 @@ import {
|
|||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
BigNumber,
|
BigNumber,
|
||||||
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isPresent,
|
isPresent,
|
||||||
@@ -182,8 +183,9 @@ export default class PaymentModuleService
|
|||||||
data: CreatePaymentCollectionDTO[],
|
data: CreatePaymentCollectionDTO[],
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<PaymentCollectionDTO[]>
|
): Promise<PaymentCollectionDTO[]>
|
||||||
@InjectManager()
|
|
||||||
|
|
||||||
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createPaymentCollections(
|
async createPaymentCollections(
|
||||||
data: CreatePaymentCollectionDTO | CreatePaymentCollectionDTO[],
|
data: CreatePaymentCollectionDTO | CreatePaymentCollectionDTO[],
|
||||||
@@ -197,10 +199,7 @@ export default class PaymentModuleService
|
|||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<PaymentCollectionDTO[]>(
|
return await this.baseRepository_.serialize<PaymentCollectionDTO[]>(
|
||||||
Array.isArray(data) ? collections : collections[0],
|
Array.isArray(data) ? collections : collections[0]
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,6 +225,7 @@ export default class PaymentModuleService
|
|||||||
): Promise<PaymentCollectionDTO[]>
|
): Promise<PaymentCollectionDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updatePaymentCollections(
|
async updatePaymentCollections(
|
||||||
idOrSelector: string | FilterablePaymentCollectionProps,
|
idOrSelector: string | FilterablePaymentCollectionProps,
|
||||||
@@ -260,10 +260,7 @@ export default class PaymentModuleService
|
|||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<PaymentCollectionDTO[]>(
|
return await this.baseRepository_.serialize<PaymentCollectionDTO[]>(
|
||||||
Array.isArray(data) ? result : result[0],
|
Array.isArray(data) ? result : result[0]
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,10 +282,23 @@ export default class PaymentModuleService
|
|||||||
): Promise<PaymentCollectionDTO>
|
): Promise<PaymentCollectionDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertPaymentCollections(
|
async upsertPaymentCollections(
|
||||||
data: UpsertPaymentCollectionDTO | UpsertPaymentCollectionDTO[],
|
data: UpsertPaymentCollectionDTO | UpsertPaymentCollectionDTO[],
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
): Promise<PaymentCollectionDTO | PaymentCollectionDTO[]> {
|
): Promise<PaymentCollectionDTO | PaymentCollectionDTO[]> {
|
||||||
|
const result = await this.upsertPaymentCollections_(data, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<
|
||||||
|
PaymentCollectionDTO[] | PaymentCollectionDTO
|
||||||
|
>(Array.isArray(data) ? result : result[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertPaymentCollections_(
|
||||||
|
data: UpsertPaymentCollectionDTO | UpsertPaymentCollectionDTO[],
|
||||||
|
@MedusaContext() sharedContext?: Context
|
||||||
|
): Promise<InferEntityType<typeof PaymentCollection>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter(
|
const forUpdate = input.filter(
|
||||||
(collection): collection is UpdatePaymentCollectionDTO => !!collection.id
|
(collection): collection is UpdatePaymentCollectionDTO => !!collection.id
|
||||||
@@ -309,9 +319,7 @@ export default class PaymentModuleService
|
|||||||
|
|
||||||
const result = (await promiseAll(operations)).flat()
|
const result = (await promiseAll(operations)).flat()
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return result
|
||||||
PaymentCollectionDTO[] | PaymentCollectionDTO
|
|
||||||
>(Array.isArray(data) ? result : result[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
completePaymentCollections(
|
completePaymentCollections(
|
||||||
@@ -325,6 +333,7 @@ export default class PaymentModuleService
|
|||||||
|
|
||||||
// Should we remove this and use `updatePaymentCollections` instead?
|
// Should we remove this and use `updatePaymentCollections` instead?
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async completePaymentCollections(
|
async completePaymentCollections(
|
||||||
paymentCollectionId: string | string[],
|
paymentCollectionId: string | string[],
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
@@ -344,12 +353,12 @@ export default class PaymentModuleService
|
|||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize(
|
return await this.baseRepository_.serialize(
|
||||||
Array.isArray(paymentCollectionId) ? updated : updated[0],
|
Array.isArray(paymentCollectionId) ? updated : updated[0]
|
||||||
{ populate: true }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async createPaymentSession(
|
async createPaymentSession(
|
||||||
paymentCollectionId: string,
|
paymentCollectionId: string,
|
||||||
input: CreatePaymentSessionDTO,
|
input: CreatePaymentSessionDTO,
|
||||||
@@ -429,6 +438,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async updatePaymentSession(
|
async updatePaymentSession(
|
||||||
data: UpdatePaymentSessionDTO,
|
data: UpdatePaymentSessionDTO,
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
@@ -462,10 +472,11 @@ export default class PaymentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize(updated, { populate: true })
|
return await this.baseRepository_.serialize(updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async deletePaymentSession(
|
async deletePaymentSession(
|
||||||
id: string,
|
id: string,
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
@@ -484,6 +495,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async authorizePaymentSession(
|
async authorizePaymentSession(
|
||||||
id: string,
|
id: string,
|
||||||
context: Record<string, unknown>,
|
context: Record<string, unknown>,
|
||||||
@@ -509,9 +521,7 @@ export default class PaymentModuleService
|
|||||||
|
|
||||||
// this method needs to be idempotent
|
// this method needs to be idempotent
|
||||||
if (session.payment && session.authorized_at) {
|
if (session.payment && session.authorized_at) {
|
||||||
return await this.baseRepository_.serialize(session.payment, {
|
return await this.baseRepository_.serialize(session.payment)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let { data, status } = await this.paymentProviderService_.authorizePayment(
|
let { data, status } = await this.paymentProviderService_.authorizePayment(
|
||||||
@@ -565,13 +575,11 @@ export default class PaymentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize(payment, {
|
return await this.baseRepository_.serialize(payment)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
async authorizePaymentSession_(
|
protected async authorizePaymentSession_(
|
||||||
session: InferEntityType<typeof PaymentSession>,
|
session: InferEntityType<typeof PaymentSession>,
|
||||||
data: Record<string, unknown> | undefined,
|
data: Record<string, unknown> | undefined,
|
||||||
status: PaymentSessionStatus,
|
status: PaymentSessionStatus,
|
||||||
@@ -620,6 +628,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async updatePayment(
|
async updatePayment(
|
||||||
data: UpdatePaymentDTO,
|
data: UpdatePaymentDTO,
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
@@ -632,6 +641,7 @@ export default class PaymentModuleService
|
|||||||
|
|
||||||
// TODO: This method should return a capture, not a payment
|
// TODO: This method should return a capture, not a payment
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async capturePayment(
|
async capturePayment(
|
||||||
data: CreateCaptureDTO,
|
data: CreateCaptureDTO,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -680,13 +690,11 @@ export default class PaymentModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize(payment, {
|
return await this.baseRepository_.serialize(payment)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
private async capturePayment_(
|
protected async capturePayment_(
|
||||||
data: CreateCaptureDTO,
|
data: CreateCaptureDTO,
|
||||||
payment: InferEntityType<typeof Payment>,
|
payment: InferEntityType<typeof Payment>,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -750,8 +758,9 @@ export default class PaymentModuleService
|
|||||||
|
|
||||||
return { isFullyCaptured, capture }
|
return { isFullyCaptured, capture }
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
private async capturePaymentFromProvider_(
|
protected async capturePaymentFromProvider_(
|
||||||
payment: InferEntityType<typeof Payment>,
|
payment: InferEntityType<typeof Payment>,
|
||||||
capture: InferEntityType<typeof Capture> | undefined,
|
capture: InferEntityType<typeof Capture> | undefined,
|
||||||
isFullyCaptured: boolean,
|
isFullyCaptured: boolean,
|
||||||
@@ -780,6 +789,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async refundPayment(
|
async refundPayment(
|
||||||
data: CreateRefundDTO,
|
data: CreateRefundDTO,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -862,7 +872,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
private async refundPaymentFromProvider_(
|
protected async refundPaymentFromProvider_(
|
||||||
payment: InferEntityType<typeof Payment>,
|
payment: InferEntityType<typeof Payment>,
|
||||||
refund: InferEntityType<typeof Refund>,
|
refund: InferEntityType<typeof Refund>,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -887,6 +897,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async cancelPayment(
|
async cancelPayment(
|
||||||
paymentId: string,
|
paymentId: string,
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
@@ -913,7 +924,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
private async maybeUpdatePaymentCollection_(
|
protected async maybeUpdatePaymentCollection_(
|
||||||
paymentCollectionId: string,
|
paymentCollectionId: string,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
) {
|
) {
|
||||||
@@ -1050,6 +1061,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async createAccountHolder(
|
async createAccountHolder(
|
||||||
input: CreateAccountHolderDTO,
|
input: CreateAccountHolderDTO,
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
@@ -1089,6 +1101,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async updateAccountHolder(
|
async updateAccountHolder(
|
||||||
input: UpdateAccountHolderDTO,
|
input: UpdateAccountHolderDTO,
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
@@ -1128,6 +1141,7 @@ export default class PaymentModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async deleteAccountHolder(
|
async deleteAccountHolder(
|
||||||
id: string,
|
id: string,
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
@@ -1187,7 +1201,6 @@ export default class PaymentModuleService
|
|||||||
return [normalizedResponse, paymentMethods.length]
|
return [normalizedResponse, paymentMethods.length]
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
createPaymentMethods(
|
createPaymentMethods(
|
||||||
data: CreatePaymentMethodDTO,
|
data: CreatePaymentMethodDTO,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
@@ -1197,7 +1210,9 @@ export default class PaymentModuleService
|
|||||||
data: CreatePaymentMethodDTO[],
|
data: CreatePaymentMethodDTO[],
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<PaymentMethodDTO[]>
|
): Promise<PaymentMethodDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async createPaymentMethods(
|
async createPaymentMethods(
|
||||||
data: CreatePaymentMethodDTO | CreatePaymentMethodDTO[],
|
data: CreatePaymentMethodDTO | CreatePaymentMethodDTO[],
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
|
|||||||
+50
-33
@@ -461,35 +461,41 @@ moduleIntegrationTestRunner<IPricingModuleService>({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const events = eventBusEmitSpy.mock.calls[0][0]
|
const events = eventBusEmitSpy.mock.calls[0][0]
|
||||||
expect(events).toHaveLength(3)
|
|
||||||
expect(events[0]).toEqual(
|
// 4 events: 1 price list created, 2 price list rules created, 1 price created
|
||||||
|
expect(events).toHaveLength(4)
|
||||||
|
|
||||||
|
expect(events).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
composeMessage(PricingEvents.PRICE_LIST_CREATED, {
|
composeMessage(PricingEvents.PRICE_LIST_CREATED, {
|
||||||
source: Modules.PRICING,
|
source: Modules.PRICING,
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "price_list",
|
object: "price_list",
|
||||||
data: { id: priceList.id },
|
data: { id: priceList.id },
|
||||||
})
|
}),
|
||||||
)
|
|
||||||
expect(events[1]).toEqual(
|
|
||||||
composeMessage(PricingEvents.PRICE_LIST_RULE_CREATED, {
|
composeMessage(PricingEvents.PRICE_LIST_RULE_CREATED, {
|
||||||
source: Modules.PRICING,
|
source: Modules.PRICING,
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "price_list_rule",
|
object: "price_list_rule",
|
||||||
data: {
|
data: {
|
||||||
id: [
|
id: priceList.price_list_rules?.[1].id,
|
||||||
priceList.price_list_rules?.[0].id,
|
|
||||||
priceList.price_list_rules?.[1].id,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
)
|
composeMessage(PricingEvents.PRICE_LIST_RULE_CREATED, {
|
||||||
expect(events[2]).toEqual(
|
source: Modules.PRICING,
|
||||||
|
action: CommonEvents.CREATED,
|
||||||
|
object: "price_list_rule",
|
||||||
|
data: {
|
||||||
|
id: priceList.price_list_rules?.[0].id,
|
||||||
|
},
|
||||||
|
}),
|
||||||
composeMessage(PricingEvents.PRICE_CREATED, {
|
composeMessage(PricingEvents.PRICE_CREATED, {
|
||||||
source: Modules.PRICING,
|
source: Modules.PRICING,
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "price",
|
object: "price",
|
||||||
data: { id: priceList.prices![0].id },
|
data: { id: priceList.prices![0].id },
|
||||||
})
|
}),
|
||||||
|
])
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -789,7 +795,7 @@ moduleIntegrationTestRunner<IPricingModuleService>({
|
|||||||
it("should update a price to a priceList successfully", async () => {
|
it("should update a price to a priceList successfully", async () => {
|
||||||
const [priceSet] = await service.createPriceSets([{}])
|
const [priceSet] = await service.createPriceSets([{}])
|
||||||
|
|
||||||
await service.addPriceListPrices([
|
const [priceBeforeUpdate] = await service.addPriceListPrices([
|
||||||
{
|
{
|
||||||
price_list_id: "price-list-1",
|
price_list_id: "price-list-1",
|
||||||
prices: [
|
prices: [
|
||||||
@@ -806,7 +812,9 @@ moduleIntegrationTestRunner<IPricingModuleService>({
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
await service.updatePriceListPrices([
|
eventBusEmitSpy.mockClear()
|
||||||
|
|
||||||
|
const [price] = await service.updatePriceListPrices([
|
||||||
{
|
{
|
||||||
price_list_id: "price-list-1",
|
price_list_id: "price-list-1",
|
||||||
prices: [
|
prices: [
|
||||||
@@ -822,28 +830,37 @@ moduleIntegrationTestRunner<IPricingModuleService>({
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const events = eventBusEmitSpy.mock.calls[2][0]
|
const events = eventBusEmitSpy.mock.calls[0][0]
|
||||||
|
|
||||||
|
// 4 events: 2 price rules created, 1 price updated, 1 price rule updated, 1 price rule deleted
|
||||||
|
expect(events).toHaveLength(4)
|
||||||
expect(events).toEqual(
|
expect(events).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining(
|
||||||
name: "pricing.price-rule.created",
|
composeMessage(PricingEvents.PRICE_UPDATED, {
|
||||||
}),
|
source: Modules.PRICING,
|
||||||
expect.objectContaining({
|
action: CommonEvents.UPDATED,
|
||||||
name: "pricing.price-rule.created",
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
name: "pricing.price.updated",
|
|
||||||
metadata: {
|
|
||||||
source: "pricing",
|
|
||||||
object: "price",
|
object: "price",
|
||||||
action: "updated",
|
data: { id: price.id },
|
||||||
},
|
})
|
||||||
data: {
|
),
|
||||||
id: "test-price-id",
|
composeMessage(PricingEvents.PRICE_RULE_CREATED, {
|
||||||
},
|
source: Modules.PRICING,
|
||||||
|
action: CommonEvents.CREATED,
|
||||||
|
object: "price_rule",
|
||||||
|
data: { id: price.price_rules![0].id },
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
composeMessage(PricingEvents.PRICE_RULE_CREATED, {
|
||||||
name: "pricing.price-rule.deleted",
|
source: Modules.PRICING,
|
||||||
|
action: CommonEvents.CREATED,
|
||||||
|
object: "price_rule",
|
||||||
|
data: { id: price.price_rules![1].id },
|
||||||
|
}),
|
||||||
|
composeMessage(PricingEvents.PRICE_RULE_DELETED, {
|
||||||
|
source: Modules.PRICING,
|
||||||
|
action: CommonEvents.DELETED,
|
||||||
|
object: "price_rule",
|
||||||
|
data: { id: priceBeforeUpdate.price_rules![0].id },
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ import {
|
|||||||
promiseAll,
|
promiseAll,
|
||||||
removeNullish,
|
removeNullish,
|
||||||
simpleHash,
|
simpleHash,
|
||||||
upperCaseFirst,
|
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -55,7 +54,7 @@ import {
|
|||||||
|
|
||||||
import { Collection } from "@mikro-orm/core"
|
import { Collection } from "@mikro-orm/core"
|
||||||
import { ServiceTypes } from "@types"
|
import { ServiceTypes } from "@types"
|
||||||
import { eventBuilders, validatePriceListDates } from "@utils"
|
import { validatePriceListDates } from "@utils"
|
||||||
import { joinerConfig } from "../joiner-config"
|
import { joinerConfig } from "../joiner-config"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
@@ -169,6 +168,8 @@ export default class PricingModuleService
|
|||||||
return pricingContext
|
return pricingContext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createPriceRules(
|
async createPriceRules(
|
||||||
...args: Parameters<PricingTypes.IPricingModuleService["createPriceRules"]>
|
...args: Parameters<PricingTypes.IPricingModuleService["createPriceRules"]>
|
||||||
@@ -180,6 +181,8 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updatePriceRules(
|
async updatePriceRules(
|
||||||
...args: Parameters<PricingTypes.IPricingModuleService["updatePriceRules"]>
|
...args: Parameters<PricingTypes.IPricingModuleService["updatePriceRules"]>
|
||||||
@@ -191,6 +194,8 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createPriceListRules(
|
async createPriceListRules(
|
||||||
...args: any[]
|
...args: any[]
|
||||||
@@ -203,6 +208,8 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updatePriceListRules(
|
async updatePriceListRules(
|
||||||
...args: any[]
|
...args: any[]
|
||||||
@@ -269,7 +276,7 @@ export default class PricingModuleService
|
|||||||
priceSet.calculated_price = calculatedPrice ?? null
|
priceSet.calculated_price = calculatedPrice ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
return priceSets
|
return await this.baseRepository_.serialize<PriceSetDTO[]>(priceSets)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
@@ -291,7 +298,10 @@ export default class PricingModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
if (!pricingContext || !priceSets.length) {
|
if (!pricingContext || !priceSets.length) {
|
||||||
return [priceSets, count]
|
const serializedPriceSets = await this.baseRepository_.serialize<
|
||||||
|
PriceSetDTO[]
|
||||||
|
>(priceSets)
|
||||||
|
return [serializedPriceSets, count]
|
||||||
}
|
}
|
||||||
|
|
||||||
const calculatedPrices = await this.calculatePrices(
|
const calculatedPrices = await this.calculatePrices(
|
||||||
@@ -310,7 +320,11 @@ export default class PricingModuleService
|
|||||||
priceSet.calculated_price = calculatedPrice ?? null
|
priceSet.calculated_price = calculatedPrice ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
return [priceSets, count]
|
const serializedPriceSets = await this.baseRepository_.serialize<
|
||||||
|
PriceSetDTO[]
|
||||||
|
>(priceSets)
|
||||||
|
|
||||||
|
return [serializedPriceSets, count]
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
@@ -405,13 +419,14 @@ export default class PricingModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
const calculatedPrices: PricingTypes.CalculatedPriceSet[] =
|
const calculatedPrices: PricingTypes.CalculatedPriceSet[] = []
|
||||||
pricingFilters.id
|
|
||||||
.map((priceSetId: string): PricingTypes.CalculatedPriceSet | null => {
|
for (const priceSetId of pricingFilters.id) {
|
||||||
const prices = pricesSetPricesMap.get(priceSetId)
|
const prices = pricesSetPricesMap.get(priceSetId)
|
||||||
if (!prices) {
|
if (!prices) {
|
||||||
return null
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
calculatedPrice,
|
calculatedPrice,
|
||||||
originalPrice,
|
originalPrice,
|
||||||
@@ -420,7 +435,7 @@ export default class PricingModuleService
|
|||||||
originalPrice: PricingTypes.CalculatedPriceSetDTO | undefined
|
originalPrice: PricingTypes.CalculatedPriceSetDTO | undefined
|
||||||
} = prices
|
} = prices
|
||||||
|
|
||||||
return {
|
const calculatedPrice_: PricingTypes.CalculatedPriceSet = {
|
||||||
id: priceSetId,
|
id: priceSetId,
|
||||||
is_calculated_price_price_list: !!calculatedPrice?.price_list_id,
|
is_calculated_price_price_list: !!calculatedPrice?.price_list_id,
|
||||||
is_calculated_price_tax_inclusive: isTaxInclusive(
|
is_calculated_price_tax_inclusive: isTaxInclusive(
|
||||||
@@ -454,10 +469,8 @@ export default class PricingModuleService
|
|||||||
id: calculatedPrice?.id || null,
|
id: calculatedPrice?.id || null,
|
||||||
price_list_id: calculatedPrice?.price_list_id || null,
|
price_list_id: calculatedPrice?.price_list_id || null,
|
||||||
price_list_type: calculatedPrice?.price_list_type || null,
|
price_list_type: calculatedPrice?.price_list_type || null,
|
||||||
min_quantity:
|
min_quantity: parseInt(calculatedPrice?.min_quantity || "") || null,
|
||||||
parseInt(calculatedPrice?.min_quantity || "") || null,
|
max_quantity: parseInt(calculatedPrice?.max_quantity || "") || null,
|
||||||
max_quantity:
|
|
||||||
parseInt(calculatedPrice?.max_quantity || "") || null,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
original_price: {
|
original_price: {
|
||||||
@@ -468,10 +481,11 @@ export default class PricingModuleService
|
|||||||
max_quantity: parseInt(originalPrice?.max_quantity || "") || null,
|
max_quantity: parseInt(originalPrice?.max_quantity || "") || null,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.filter(Boolean) as PricingTypes.CalculatedPriceSet[]
|
|
||||||
|
|
||||||
return JSON.parse(JSON.stringify(calculatedPrices))
|
calculatedPrices.push(calculatedPrice_)
|
||||||
|
}
|
||||||
|
|
||||||
|
return calculatedPrices
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -534,6 +548,22 @@ export default class PricingModuleService
|
|||||||
data: UpsertPriceSetDTO | UpsertPriceSetDTO[],
|
data: UpsertPriceSetDTO | UpsertPriceSetDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<PriceSetDTO | PriceSetDTO[]> {
|
): Promise<PriceSetDTO | PriceSetDTO[]> {
|
||||||
|
const result = await this.upsertPriceSets_(data, sharedContext)
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await this.baseRepository_.serialize<PriceSetDTO[] | PriceSetDTO>(
|
||||||
|
Array.isArray(data) ? result : result[0]
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
this.pricingRepository_.clearAvailableAttributes?.()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertPriceSets_(
|
||||||
|
data: UpsertPriceSetDTO | UpsertPriceSetDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof PriceSet>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
|
|
||||||
const forUpdate = input.filter(
|
const forUpdate = input.filter(
|
||||||
@@ -554,13 +584,7 @@ export default class PricingModuleService
|
|||||||
|
|
||||||
const result = (await promiseAll(operations)).flat()
|
const result = (await promiseAll(operations)).flat()
|
||||||
|
|
||||||
try {
|
return result
|
||||||
return await this.baseRepository_.serialize<PriceSetDTO[] | PriceSetDTO>(
|
|
||||||
Array.isArray(data) ? result : result[0]
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
this.pricingRepository_.clearAvailableAttributes?.()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -606,12 +630,13 @@ export default class PricingModuleService
|
|||||||
normalizedInput,
|
normalizedInput,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
const priceSets = await this.baseRepository_.serialize<
|
|
||||||
|
const serializedUpdateResult = await this.baseRepository_.serialize<
|
||||||
PriceSetDTO[] | PriceSetDTO
|
PriceSetDTO[] | PriceSetDTO
|
||||||
>(updateResult)
|
>(isString(idOrSelector) ? updateResult[0] : updateResult)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return isString(idOrSelector) ? priceSets[0] : priceSets
|
return serializedUpdateResult
|
||||||
} finally {
|
} finally {
|
||||||
this.pricingRepository_.clearAvailableAttributes?.()
|
this.pricingRepository_.clearAvailableAttributes?.()
|
||||||
}
|
}
|
||||||
@@ -707,10 +732,6 @@ export default class PricingModuleService
|
|||||||
})),
|
})),
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
eventBuilders.createdPriceRule({
|
|
||||||
data: createdPriceRules.map((r) => ({ id: r.id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priceRulesToUpdate.length > 0) {
|
if (priceRulesToUpdate.length > 0) {
|
||||||
@@ -718,10 +739,6 @@ export default class PricingModuleService
|
|||||||
priceRulesToUpdate,
|
priceRulesToUpdate,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
eventBuilders.updatedPriceRule({
|
|
||||||
data: updatedPriceRules.map((r) => ({ id: r.id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priceRulesToDelete.length > 0) {
|
if (priceRulesToDelete.length > 0) {
|
||||||
@@ -729,10 +746,6 @@ export default class PricingModuleService
|
|||||||
priceRulesToDelete,
|
priceRulesToDelete,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
eventBuilders.deletedPriceRule({
|
|
||||||
data: priceRulesToDelete.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const upsertedPriceRules = [
|
const upsertedPriceRules = [
|
||||||
@@ -755,10 +768,6 @@ export default class PricingModuleService
|
|||||||
priceRuleToDelete,
|
priceRuleToDelete,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
eventBuilders.deletedPriceRule({
|
|
||||||
data: priceRuleToDelete.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
;(priceToUpdate as InferEntityType<typeof Price>).rules_count = 0
|
;(priceToUpdate as InferEntityType<typeof Price>).rules_count = 0
|
||||||
@@ -780,27 +789,6 @@ export default class PricingModuleService
|
|||||||
await this.priceService_.delete(pricesToDelete, sharedContext)
|
await this.priceService_.delete(pricesToDelete, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createdPrices.length > 0) {
|
|
||||||
eventBuilders.createdPrice({
|
|
||||||
data: createdPrices.map((p) => ({ id: p.id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updatedPrices.length > 0) {
|
|
||||||
eventBuilders.updatedPrice({
|
|
||||||
data: updatedPrices.map((p) => ({ id: p.id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pricesToDelete.length > 0) {
|
|
||||||
eventBuilders.deletedPrice({
|
|
||||||
data: pricesToDelete.map((id) => ({ id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const priceSets = await this.priceSetService_.list(
|
const priceSets = await this.priceSetService_.list(
|
||||||
{ id: normalizedData.map(({ id }) => id) },
|
{ id: normalizedData.map(({ id }) => id) },
|
||||||
{
|
{
|
||||||
@@ -825,11 +813,6 @@ export default class PricingModuleService
|
|||||||
ps.prices = upsertedPricesMap.get(ps.id) || []
|
ps.prices = upsertedPricesMap.get(ps.id) || []
|
||||||
})
|
})
|
||||||
|
|
||||||
eventBuilders.updatedPriceSet({
|
|
||||||
data: priceSets.map((ps) => ({ id: ps.id })),
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return priceSets
|
return priceSets
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -952,8 +935,12 @@ export default class PricingModuleService
|
|||||||
return dbPrices.find((p) => p.id === inputItem.priceSetId)!
|
return dbPrices.find((p) => p.id === inputItem.priceSetId)!
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const serializedOrderedPriceSets = await this.baseRepository_.serialize<
|
||||||
|
PricingTypes.PriceSetDTO[]
|
||||||
|
>(Array.isArray(data) ? orderedPriceSets : orderedPriceSets[0])
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return Array.isArray(data) ? orderedPriceSets : orderedPriceSets[0]
|
return serializedOrderedPriceSets
|
||||||
} finally {
|
} finally {
|
||||||
this.pricingRepository_.clearAvailableAttributes?.()
|
this.pricingRepository_.clearAvailableAttributes?.()
|
||||||
}
|
}
|
||||||
@@ -977,7 +964,7 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
async updatePriceLists(
|
async updatePriceLists(
|
||||||
@@ -1117,6 +1104,18 @@ export default class PricingModuleService
|
|||||||
data: UpsertPricePreferenceDTO | UpsertPricePreferenceDTO[],
|
data: UpsertPricePreferenceDTO | UpsertPricePreferenceDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<PricePreferenceDTO | PricePreferenceDTO[]> {
|
): Promise<PricePreferenceDTO | PricePreferenceDTO[]> {
|
||||||
|
const result = await this.upsertPricePreferences_(data, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<
|
||||||
|
PricePreferenceDTO[] | PricePreferenceDTO
|
||||||
|
>(Array.isArray(data) ? result : result[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertPricePreferences_(
|
||||||
|
data: UpsertPricePreferenceDTO | UpsertPricePreferenceDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof PricePreference>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter(
|
const forUpdate = input.filter(
|
||||||
(
|
(
|
||||||
@@ -1139,9 +1138,8 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = (await promiseAll(operations)).flat()
|
const result = (await promiseAll(operations)).flat()
|
||||||
return await this.baseRepository_.serialize<
|
|
||||||
PricePreferenceDTO[] | PricePreferenceDTO
|
return result
|
||||||
>(Array.isArray(data) ? result : result[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -1158,6 +1156,7 @@ export default class PricingModuleService
|
|||||||
): Promise<PricePreferenceDTO[]>
|
): Promise<PricePreferenceDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updatePricePreferences(
|
async updatePricePreferences(
|
||||||
idOrSelector: string | PricingTypes.FilterablePricePreferenceProps,
|
idOrSelector: string | PricingTypes.FilterablePricePreferenceProps,
|
||||||
@@ -1248,49 +1247,6 @@ export default class PricingModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
const eventsData = priceSets.reduce(
|
|
||||||
(eventsData, priceSet) => {
|
|
||||||
eventsData.priceSets.push({
|
|
||||||
id: priceSet.id,
|
|
||||||
})
|
|
||||||
|
|
||||||
priceSet.prices.map((price) => {
|
|
||||||
eventsData.prices.push({
|
|
||||||
id: price.id,
|
|
||||||
})
|
|
||||||
price.price_rules.map((priceRule) => {
|
|
||||||
eventsData.priceRules.push({
|
|
||||||
id: priceRule.id,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return eventsData
|
|
||||||
},
|
|
||||||
{
|
|
||||||
priceSets: [],
|
|
||||||
priceRules: [],
|
|
||||||
prices: [],
|
|
||||||
} as {
|
|
||||||
priceSets: { id: string }[]
|
|
||||||
priceRules: { id: string }[]
|
|
||||||
prices: { id: string }[]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
eventBuilders.createdPriceSet({
|
|
||||||
data: eventsData.priceSets,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.createdPrice({
|
|
||||||
data: eventsData.prices,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.createdPriceRule({
|
|
||||||
data: eventsData.priceRules,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return priceSets
|
return priceSets
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1336,19 +1292,12 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { entities, performedActions } =
|
const { entities } = await this.priceService_.upsertWithReplace(
|
||||||
await this.priceService_.upsertWithReplace(
|
|
||||||
pricesToUpsert,
|
pricesToUpsert,
|
||||||
{ relations: ["price_rules"] },
|
{ relations: ["price_rules"] },
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
composeAllEvents({
|
|
||||||
eventBuilders,
|
|
||||||
performedActions,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1401,67 +1350,6 @@ export default class PricingModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
* Preparing data for emitting events
|
|
||||||
*/
|
|
||||||
const eventsData = priceLists.reduce(
|
|
||||||
(eventsData, priceList) => {
|
|
||||||
eventsData.priceList.push({
|
|
||||||
id: priceList.id,
|
|
||||||
})
|
|
||||||
|
|
||||||
priceList.price_list_rules.map((listRule) => {
|
|
||||||
eventsData.priceListRules.push({
|
|
||||||
id: listRule.id,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
priceList.prices.map((price) => {
|
|
||||||
eventsData.prices.push({
|
|
||||||
id: price.id,
|
|
||||||
})
|
|
||||||
price.price_rules.map((priceRule) => {
|
|
||||||
eventsData.priceRules.push({
|
|
||||||
id: priceRule.id,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return eventsData
|
|
||||||
},
|
|
||||||
{
|
|
||||||
priceList: [],
|
|
||||||
priceListRules: [],
|
|
||||||
priceRules: [],
|
|
||||||
prices: [],
|
|
||||||
} as {
|
|
||||||
priceList: { id: string }[]
|
|
||||||
priceListRules: { id: string }[]
|
|
||||||
priceRules: { id: string }[]
|
|
||||||
prices: { id: string }[]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitting events for all created entities
|
|
||||||
*/
|
|
||||||
eventBuilders.createdPriceList({
|
|
||||||
data: eventsData.priceList,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.createdPriceListRule({
|
|
||||||
data: eventsData.priceListRules,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.createdPrice({
|
|
||||||
data: eventsData.prices,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.createdPriceRule({
|
|
||||||
data: eventsData.priceRules,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return priceLists
|
return priceLists
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1519,16 +1407,12 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const { entities, performedActions } =
|
const { entities } = await this.priceListService_.upsertWithReplace(
|
||||||
await this.priceListService_.upsertWithReplace(normalizedData, {
|
normalizedData,
|
||||||
|
{
|
||||||
relations: ["price_list_rules"],
|
relations: ["price_list_rules"],
|
||||||
})
|
}
|
||||||
|
)
|
||||||
composeAllEvents({
|
|
||||||
eventBuilders,
|
|
||||||
performedActions,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
}
|
}
|
||||||
@@ -1572,19 +1456,12 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { entities, performedActions } =
|
const { entities } = await this.priceService_.upsertWithReplace(
|
||||||
await this.priceService_.upsertWithReplace(
|
|
||||||
pricesToUpsert,
|
pricesToUpsert,
|
||||||
{ relations: ["price_rules"] },
|
{ relations: ["price_rules"] },
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
composeAllEvents({
|
|
||||||
eventBuilders,
|
|
||||||
performedActions,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1634,19 +1511,12 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { entities, performedActions } =
|
const { entities } = await this.priceService_.upsertWithReplace(
|
||||||
await this.priceService_.upsertWithReplace(
|
|
||||||
pricesToUpsert,
|
pricesToUpsert,
|
||||||
{ relations: ["price_rules"] },
|
{ relations: ["price_rules"] },
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
composeAllEvents({
|
|
||||||
eventBuilders,
|
|
||||||
performedActions,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1705,19 +1575,12 @@ export default class PricingModuleService
|
|||||||
})
|
})
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
|
|
||||||
const { entities, performedActions } =
|
const { entities } = await this.priceListService_.upsertWithReplace(
|
||||||
await this.priceListService_.upsertWithReplace(
|
|
||||||
priceListsUpsert,
|
priceListsUpsert,
|
||||||
{ relations: ["price_list_rules"] },
|
{ relations: ["price_list_rules"] },
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
composeAllEvents({
|
|
||||||
eventBuilders,
|
|
||||||
performedActions,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1779,19 +1642,12 @@ export default class PricingModuleService
|
|||||||
})
|
})
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
|
|
||||||
const { entities, performedActions } =
|
const { entities } = await this.priceListService_.upsertWithReplace(
|
||||||
await this.priceListService_.upsertWithReplace(
|
|
||||||
priceListsUpsert,
|
priceListsUpsert,
|
||||||
{ relations: ["price_list_rules"] },
|
{ relations: ["price_list_rules"] },
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
composeAllEvents({
|
|
||||||
eventBuilders,
|
|
||||||
performedActions,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1829,26 +1685,6 @@ export default class PricingModuleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const composeAllEvents = ({
|
|
||||||
eventBuilders,
|
|
||||||
performedActions,
|
|
||||||
sharedContext,
|
|
||||||
}) => {
|
|
||||||
for (const action of Object.keys(performedActions)) {
|
|
||||||
for (const entity of Object.keys(performedActions[action])) {
|
|
||||||
const eventName = action + upperCaseFirst(entity)
|
|
||||||
if (!eventBuilders[eventName]) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
eventBuilders[eventName]({
|
|
||||||
data: performedActions[action][entity] ?? [],
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const isTaxInclusive = (
|
const isTaxInclusive = (
|
||||||
priceRules: InferEntityType<typeof PriceRule>[],
|
priceRules: InferEntityType<typeof PriceRule>[],
|
||||||
preferences: InferEntityType<typeof PricePreference>[],
|
preferences: InferEntityType<typeof PricePreference>[],
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
import {
|
|
||||||
CommonEvents,
|
|
||||||
moduleEventBuilderFactory,
|
|
||||||
Modules,
|
|
||||||
PricingEvents,
|
|
||||||
} from "@medusajs/framework/utils"
|
|
||||||
|
|
||||||
export const eventBuilders = {
|
|
||||||
createdPriceSet: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "price_set",
|
|
||||||
eventName: PricingEvents.PRICE_SET_CREATED,
|
|
||||||
}),
|
|
||||||
createdPrice: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "price",
|
|
||||||
eventName: PricingEvents.PRICE_CREATED,
|
|
||||||
}),
|
|
||||||
createdPriceRule: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "price_rule",
|
|
||||||
eventName: PricingEvents.PRICE_RULE_CREATED,
|
|
||||||
}),
|
|
||||||
createdPriceList: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "price_list",
|
|
||||||
eventName: PricingEvents.PRICE_LIST_CREATED,
|
|
||||||
}),
|
|
||||||
createdPriceListRule: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "price_list_rule",
|
|
||||||
eventName: PricingEvents.PRICE_LIST_RULE_CREATED,
|
|
||||||
}),
|
|
||||||
updatedPriceSet: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "price_set",
|
|
||||||
eventName: PricingEvents.PRICE_SET_UPDATED,
|
|
||||||
}),
|
|
||||||
updatedPrice: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "price",
|
|
||||||
eventName: PricingEvents.PRICE_UPDATED,
|
|
||||||
}),
|
|
||||||
updatedPriceList: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "price_list",
|
|
||||||
eventName: PricingEvents.PRICE_LIST_UPDATED,
|
|
||||||
}),
|
|
||||||
updatedPriceListRule: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "price_list_rule",
|
|
||||||
eventName: PricingEvents.PRICE_LIST_RULE_UPDATED,
|
|
||||||
}),
|
|
||||||
updatedPriceRule: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "price_rule",
|
|
||||||
eventName: PricingEvents.PRICE_RULE_UPDATED,
|
|
||||||
}),
|
|
||||||
deletedPriceSet: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "price_set",
|
|
||||||
eventName: PricingEvents.PRICE_SET_DELETED,
|
|
||||||
}),
|
|
||||||
deletedPrice: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "price",
|
|
||||||
eventName: PricingEvents.PRICE_DELETED,
|
|
||||||
}),
|
|
||||||
deletedPriceList: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "price_list",
|
|
||||||
eventName: PricingEvents.PRICE_LIST_DELETED,
|
|
||||||
}),
|
|
||||||
deletedPriceListRule: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "price_list_rule",
|
|
||||||
eventName: PricingEvents.PRICE_LIST_RULE_DELETED,
|
|
||||||
}),
|
|
||||||
deletedPriceRule: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "price_rule",
|
|
||||||
eventName: PricingEvents.PRICE_RULE_DELETED,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
@@ -1,2 +1 @@
|
|||||||
export * from "./validate-price-list-dates"
|
export * from "./validate-price-list-dates"
|
||||||
export * from "./events"
|
|
||||||
+4
-1
@@ -79,7 +79,10 @@ export const buildProductAndRelationsData = ({
|
|||||||
title: faker.commerce.productName(),
|
title: faker.commerce.productName(),
|
||||||
sku: faker.commerce.productName(),
|
sku: faker.commerce.productName(),
|
||||||
options: options
|
options: options
|
||||||
? { [options[0].title]: options[0].values[0] }
|
? options.reduce((acc, option) => {
|
||||||
|
acc[option.title] = option.values[0]
|
||||||
|
return acc
|
||||||
|
}, {} as Record<string, string>)
|
||||||
: {
|
: {
|
||||||
[defaultOptionTitle]: defaultOptionValue,
|
[defaultOptionTitle]: defaultOptionValue,
|
||||||
},
|
},
|
||||||
|
|||||||
File renamed without changes.
+1150
File diff suppressed because it is too large.
Load diff
-77
@@ -1,15 +1,11 @@
|
|||||||
import { IProductModuleService } from "@medusajs/framework/types"
|
import { IProductModuleService } from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
CommonEvents,
|
|
||||||
composeMessage,
|
|
||||||
Modules,
|
Modules,
|
||||||
ProductEvents,
|
|
||||||
ProductStatus,
|
ProductStatus,
|
||||||
toMikroORMEntity,
|
toMikroORMEntity,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { Product, ProductCategory } from "@models"
|
import { Product, ProductCategory } from "@models"
|
||||||
import {
|
import {
|
||||||
MockEventBusService,
|
|
||||||
moduleIntegrationTestRunner,
|
moduleIntegrationTestRunner,
|
||||||
} from "@medusajs/test-utils"
|
} from "@medusajs/test-utils"
|
||||||
import { productCategoriesRankData } from "../../__fixtures__/product-category/data"
|
import { productCategoriesRankData } from "../../__fixtures__/product-category/data"
|
||||||
@@ -18,9 +14,6 @@ jest.setTimeout(30000)
|
|||||||
|
|
||||||
moduleIntegrationTestRunner<IProductModuleService>({
|
moduleIntegrationTestRunner<IProductModuleService>({
|
||||||
moduleName: Modules.PRODUCT,
|
moduleName: Modules.PRODUCT,
|
||||||
injectedDependencies: {
|
|
||||||
[Modules.EVENT_BUS]: new MockEventBusService(),
|
|
||||||
},
|
|
||||||
testSuite: ({ MikroOrmWrapper, service }) => {
|
testSuite: ({ MikroOrmWrapper, service }) => {
|
||||||
describe("ProductModuleService product categories", () => {
|
describe("ProductModuleService product categories", () => {
|
||||||
let productOne: Product
|
let productOne: Product
|
||||||
@@ -404,29 +397,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
|
|
||||||
const category = await service.createProductCategories({
|
|
||||||
name: "New Category",
|
|
||||||
parent_category_id: productCategoryOne.id,
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(eventBusSpy.mock.calls[0][0]).toHaveLength(1)
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_CATEGORY_CREATED, {
|
|
||||||
data: { id: category.id },
|
|
||||||
object: "product_category",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should append rank from an existing category depending on parent", async () => {
|
it("should append rank from an existing category depending on parent", async () => {
|
||||||
await service.createProductCategories({
|
await service.createProductCategories({
|
||||||
@@ -504,29 +474,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
productCategoryZeroTwo = categories[5]
|
productCategoryZeroTwo = categories[5]
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
eventBusSpy.mockClear()
|
|
||||||
|
|
||||||
await service.updateProductCategories(productCategoryZero.id, {
|
|
||||||
name: "New Category",
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(eventBusSpy.mock.calls[0][0]).toHaveLength(1)
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_CATEGORY_UPDATED, {
|
|
||||||
data: { id: productCategoryZero.id },
|
|
||||||
object: "product_category",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should update the name of the category successfully", async () => {
|
it("should update the name of the category successfully", async () => {
|
||||||
await service.updateProductCategories(productCategoryZero.id, {
|
await service.updateProductCategories(productCategoryZero.id, {
|
||||||
@@ -683,30 +630,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
productCategoryTwo = categories[2]
|
productCategoryTwo = categories[2]
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
eventBusSpy.mockClear()
|
|
||||||
|
|
||||||
await service.deleteProductCategories([productCategoryOne.id])
|
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
expect.objectContaining({
|
|
||||||
data: { id: productCategoryOne.id },
|
|
||||||
name: "product.product-category.deleted",
|
|
||||||
metadata: {
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "product_category",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should throw an error when an id does not exist", async () => {
|
it("should throw an error when an id does not exist", async () => {
|
||||||
let error
|
let error
|
||||||
|
|||||||
-77
@@ -1,14 +1,10 @@
|
|||||||
import { IProductModuleService } from "@medusajs/framework/types"
|
import { IProductModuleService } from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
CommonEvents,
|
|
||||||
composeMessage,
|
|
||||||
Modules,
|
Modules,
|
||||||
ProductEvents,
|
|
||||||
ProductStatus,
|
ProductStatus,
|
||||||
toMikroORMEntity,
|
toMikroORMEntity,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import {
|
import {
|
||||||
MockEventBusService,
|
|
||||||
moduleIntegrationTestRunner,
|
moduleIntegrationTestRunner,
|
||||||
} from "@medusajs/test-utils"
|
} from "@medusajs/test-utils"
|
||||||
import { Product, ProductCollection } from "@models"
|
import { Product, ProductCollection } from "@models"
|
||||||
@@ -18,9 +14,6 @@ jest.setTimeout(30000)
|
|||||||
|
|
||||||
moduleIntegrationTestRunner<IProductModuleService>({
|
moduleIntegrationTestRunner<IProductModuleService>({
|
||||||
moduleName: Modules.PRODUCT,
|
moduleName: Modules.PRODUCT,
|
||||||
injectedDependencies: {
|
|
||||||
[Modules.EVENT_BUS]: new MockEventBusService(),
|
|
||||||
},
|
|
||||||
testSuite: ({ MikroOrmWrapper, service }) => {
|
testSuite: ({ MikroOrmWrapper, service }) => {
|
||||||
describe("ProductModuleService product collections", () => {
|
describe("ProductModuleService product collections", () => {
|
||||||
let productOne: Product
|
let productOne: Product
|
||||||
@@ -284,59 +277,11 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
expect(collections).toHaveLength(0)
|
expect(collections).toHaveLength(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
await service.deleteProductCollections([collectionId])
|
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
name: "product.product-collection.deleted",
|
|
||||||
data: { id: collectionId },
|
|
||||||
metadata: {
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "product_collection",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("updateCollections", () => {
|
describe("updateCollections", () => {
|
||||||
const collectionId = "test-1"
|
const collectionId = "test-1"
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
|
|
||||||
await service.upsertProductCollections([
|
|
||||||
{
|
|
||||||
id: collectionId,
|
|
||||||
title: "New Collection",
|
|
||||||
product_ids: ["product_id"],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_COLLECTION_UPDATED, {
|
|
||||||
data: { id: collectionId },
|
|
||||||
object: "product_collection",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should update the value of the collection successfully", async () => {
|
it("should update the value of the collection successfully", async () => {
|
||||||
await service.upsertProductCollections([
|
await service.upsertProductCollections([
|
||||||
@@ -534,28 +479,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
|
|
||||||
const collections = await service.createProductCollections([
|
|
||||||
{ title: "New Collection" },
|
|
||||||
])
|
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_COLLECTION_CREATED, {
|
|
||||||
data: { id: collections[0].id },
|
|
||||||
object: "product_collection",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
-61
@@ -1,15 +1,11 @@
|
|||||||
import { IProductModuleService } from "@medusajs/framework/types"
|
import { IProductModuleService } from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
CommonEvents,
|
|
||||||
composeMessage,
|
|
||||||
Modules,
|
Modules,
|
||||||
ProductEvents,
|
|
||||||
ProductStatus,
|
ProductStatus,
|
||||||
toMikroORMEntity,
|
toMikroORMEntity,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { Product, ProductTag } from "@models"
|
import { Product, ProductTag } from "@models"
|
||||||
import {
|
import {
|
||||||
MockEventBusService,
|
|
||||||
moduleIntegrationTestRunner,
|
moduleIntegrationTestRunner,
|
||||||
} from "@medusajs/test-utils"
|
} from "@medusajs/test-utils"
|
||||||
|
|
||||||
@@ -18,15 +14,6 @@ jest.setTimeout(30000)
|
|||||||
moduleIntegrationTestRunner<IProductModuleService>({
|
moduleIntegrationTestRunner<IProductModuleService>({
|
||||||
moduleName: Modules.PRODUCT,
|
moduleName: Modules.PRODUCT,
|
||||||
testSuite: ({ MikroOrmWrapper, service }) => {
|
testSuite: ({ MikroOrmWrapper, service }) => {
|
||||||
let eventBusEmitSpy
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("ProductModuleService product tags", () => {
|
describe("ProductModuleService product tags", () => {
|
||||||
let tagOne: ProductTag
|
let tagOne: ProductTag
|
||||||
@@ -303,20 +290,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
|
|
||||||
expect(productTag.value).toEqual("UK")
|
expect(productTag.value).toEqual("UK")
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_TAG_UPDATED, {
|
|
||||||
data: { id: productTag.id },
|
|
||||||
object: "product_tag",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should throw an error when an id does not exist", async () => {
|
it("should throw an error when an id does not exist", async () => {
|
||||||
@@ -350,20 +323,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
|
|
||||||
expect(productTag[0]?.value).toEqual("UK")
|
expect(productTag[0]?.value).toEqual("UK")
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_TAG_CREATED, {
|
|
||||||
data: { id: productTag[0].id },
|
|
||||||
object: "product_tag",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -409,26 +368,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
const newTag = productTags.find((t) => t.value === "new")!
|
const newTag = productTags.find((t) => t.value === "new")!
|
||||||
const updatedTag = productTags.find((t) => t.value === "updated")!
|
const updatedTag = productTags.find((t) => t.value === "updated")!
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_TAG_CREATED, {
|
|
||||||
data: { id: newTag.id },
|
|
||||||
object: "product_tag",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
}),
|
|
||||||
composeMessage(ProductEvents.PRODUCT_TAG_UPDATED, {
|
|
||||||
data: { id: updatedTag.id },
|
|
||||||
object: "product_tag",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
-41
@@ -7,15 +7,11 @@ import {
|
|||||||
UpdateProductVariantDTO,
|
UpdateProductVariantDTO,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
CommonEvents,
|
|
||||||
composeMessage,
|
|
||||||
Modules,
|
Modules,
|
||||||
ProductEvents,
|
|
||||||
ProductStatus,
|
ProductStatus,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MockEventBusService,
|
|
||||||
moduleIntegrationTestRunner,
|
moduleIntegrationTestRunner,
|
||||||
} from "@medusajs/test-utils"
|
} from "@medusajs/test-utils"
|
||||||
|
|
||||||
@@ -24,15 +20,6 @@ jest.setTimeout(30000)
|
|||||||
moduleIntegrationTestRunner<IProductModuleService>({
|
moduleIntegrationTestRunner<IProductModuleService>({
|
||||||
moduleName: Modules.PRODUCT,
|
moduleName: Modules.PRODUCT,
|
||||||
testSuite: ({ service }) => {
|
testSuite: ({ service }) => {
|
||||||
let eventBusEmitSpy
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("ProductModuleService product variants", () => {
|
describe("ProductModuleService product variants", () => {
|
||||||
let variantOne: ProductVariantDTO
|
let variantOne: ProductVariantDTO
|
||||||
@@ -212,20 +199,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
)
|
)
|
||||||
expect(productVariant.title).toEqual("new test")
|
expect(productVariant.title).toEqual("new test")
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_VARIANT_UPDATED, {
|
|
||||||
data: { id: variantOne.id },
|
|
||||||
object: "product_variant",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should do a partial update on the options of a variant successfully", async () => {
|
it("should do a partial update on the options of a variant successfully", async () => {
|
||||||
@@ -294,20 +267,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
|
||||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_VARIANT_CREATED, {
|
|
||||||
data: { id: variant.id },
|
|
||||||
object: "product_variant",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should correctly associate variants with own product options", async () => {
|
it("should correctly associate variants with own product options", async () => {
|
||||||
|
|||||||
-130
@@ -4,11 +4,8 @@ import {
|
|||||||
ProductTagDTO,
|
ProductTagDTO,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
CommonEvents,
|
|
||||||
composeMessage,
|
|
||||||
kebabCase,
|
kebabCase,
|
||||||
Modules,
|
Modules,
|
||||||
ProductEvents,
|
|
||||||
ProductStatus,
|
ProductStatus,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import {
|
import {
|
||||||
@@ -20,7 +17,6 @@ import {
|
|||||||
} from "@models"
|
} from "@models"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MockEventBusService,
|
|
||||||
moduleIntegrationTestRunner,
|
moduleIntegrationTestRunner,
|
||||||
} from "@medusajs/test-utils"
|
} from "@medusajs/test-utils"
|
||||||
import { UpdateProductInput } from "@types"
|
import { UpdateProductInput } from "@types"
|
||||||
@@ -34,9 +30,6 @@ jest.setTimeout(300000)
|
|||||||
|
|
||||||
moduleIntegrationTestRunner<IProductModuleService>({
|
moduleIntegrationTestRunner<IProductModuleService>({
|
||||||
moduleName: Modules.PRODUCT,
|
moduleName: Modules.PRODUCT,
|
||||||
injectedDependencies: {
|
|
||||||
[Modules.EVENT_BUS]: new MockEventBusService(),
|
|
||||||
},
|
|
||||||
testSuite: ({ MikroOrmWrapper, service }) => {
|
testSuite: ({ MikroOrmWrapper, service }) => {
|
||||||
describe("ProductModuleService products", function () {
|
describe("ProductModuleService products", function () {
|
||||||
let productCollectionOne: ProductCollection
|
let productCollectionOne: ProductCollection
|
||||||
@@ -573,37 +566,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through event bus", async () => {
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
const data = buildProductAndRelationsData({
|
|
||||||
images,
|
|
||||||
thumbnail: images[0].url,
|
|
||||||
})
|
|
||||||
|
|
||||||
const updateData = {
|
|
||||||
...data,
|
|
||||||
options: data.options,
|
|
||||||
id: productOne.id,
|
|
||||||
title: "updated title",
|
|
||||||
}
|
|
||||||
|
|
||||||
await service.upsertProducts([updateData])
|
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_UPDATED, {
|
|
||||||
data: { id: productOne.id },
|
|
||||||
object: "product",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should add relationships to a product", async () => {
|
it("should add relationships to a product", async () => {
|
||||||
const updateData = {
|
const updateData = {
|
||||||
@@ -1086,29 +1048,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through eventBus", async () => {
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
const data = buildProductAndRelationsData({
|
|
||||||
images,
|
|
||||||
thumbnail: images[0].url,
|
|
||||||
})
|
|
||||||
|
|
||||||
const products = await service.createProducts([data])
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_CREATED, {
|
|
||||||
data: { id: products[0].id },
|
|
||||||
object: "product",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should throw because variant doesn't have all options set", async () => {
|
it("should throw because variant doesn't have all options set", async () => {
|
||||||
const error = await service
|
const error = await service
|
||||||
@@ -1289,75 +1228,6 @@ moduleIntegrationTestRunner<IProductModuleService>({
|
|||||||
expect(softDeleted).toHaveLength(1)
|
expect(softDeleted).toHaveLength(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should emit events through eventBus", async () => {
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
|
||||||
const data = buildProductAndRelationsData({
|
|
||||||
images,
|
|
||||||
thumbnail: images[0].url,
|
|
||||||
})
|
|
||||||
|
|
||||||
const products = await service.createProducts([data])
|
|
||||||
|
|
||||||
await service.softDeleteProducts([products[0].id])
|
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenNthCalledWith(
|
|
||||||
1,
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_CREATED, {
|
|
||||||
data: { id: products[0].id },
|
|
||||||
object: "product",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenNthCalledWith(
|
|
||||||
2,
|
|
||||||
[
|
|
||||||
composeMessage(ProductEvents.PRODUCT_DELETED, {
|
|
||||||
data: { id: [products[0].id] },
|
|
||||||
object: "product",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
}),
|
|
||||||
composeMessage(ProductEvents.PRODUCT_VARIANT_DELETED, {
|
|
||||||
data: { id: [products[0].variants[0].id] },
|
|
||||||
object: "product_variant",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
}),
|
|
||||||
composeMessage(ProductEvents.PRODUCT_OPTION_DELETED, {
|
|
||||||
data: { id: [products[0].options[0].id] },
|
|
||||||
object: "product_option",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
}),
|
|
||||||
composeMessage(ProductEvents.PRODUCT_IMAGE_DELETED, {
|
|
||||||
data: {
|
|
||||||
id: [products[0].images[0].id],
|
|
||||||
},
|
|
||||||
object: "product_image",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
}),
|
|
||||||
composeMessage(ProductEvents.PRODUCT_OPTION_VALUE_DELETED, {
|
|
||||||
data: {
|
|
||||||
id: [products[0].options[0].values[0].id],
|
|
||||||
},
|
|
||||||
object: "product_option_value",
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("restore", function () {
|
describe("restore", function () {
|
||||||
|
|||||||
File renamed without changes.
@@ -29,7 +29,7 @@
|
|||||||
"resolve:aliases": "tsc --showConfig -p tsconfig.json > tsconfig.resolved.json && tsc-alias -p tsconfig.resolved.json && rimraf tsconfig.resolved.json",
|
"resolve:aliases": "tsc --showConfig -p tsconfig.json > tsconfig.resolved.json && tsc-alias -p tsconfig.resolved.json && rimraf tsconfig.resolved.json",
|
||||||
"build": "rimraf dist && tsc --build && npm run resolve:aliases",
|
"build": "rimraf dist && tsc --build && npm run resolve:aliases",
|
||||||
"test": "jest --runInBand --bail --forceExit -- src/**/__tests__/**/*.ts",
|
"test": "jest --runInBand --bail --forceExit -- src/**/__tests__/**/*.ts",
|
||||||
"test:integration": "jest --bail --forceExit -- integration-tests/__tests__/**/*.ts",
|
"test:integration": "jest --bail --forceExit -- integration-tests/__tests__/**/*.spec.ts",
|
||||||
"migration:initial": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts medusa-mikro-orm migration:create --initial",
|
"migration:initial": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts medusa-mikro-orm migration:create --initial",
|
||||||
"migration:create": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts medusa-mikro-orm migration:create",
|
"migration:create": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts medusa-mikro-orm migration:create",
|
||||||
"migration:up": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts medusa-mikro-orm migration:up",
|
"migration:up": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts medusa-mikro-orm migration:up",
|
||||||
|
|||||||
@@ -452,9 +452,7 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
|
|||||||
}
|
}
|
||||||
let productCategory = await manager.findOne<
|
let productCategory = await manager.findOne<
|
||||||
InferEntityType<typeof ProductCategory>
|
InferEntityType<typeof ProductCategory>
|
||||||
>(ProductCategory.name, {
|
>(ProductCategory.name, categoryData.id!)
|
||||||
id: categoryData.id,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!productCategory) {
|
if (!productCategory) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
isPresent,
|
isPresent,
|
||||||
mergeMetadata,
|
mergeMetadata,
|
||||||
isDefined,
|
isDefined,
|
||||||
|
deepCopy,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { SqlEntityManager, wrap } from "@mikro-orm/postgresql"
|
import { SqlEntityManager, wrap } from "@mikro-orm/postgresql"
|
||||||
|
|
||||||
@@ -80,21 +81,22 @@ export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
|
|||||||
) => void,
|
) => void,
|
||||||
context: Context = {}
|
context: Context = {}
|
||||||
): Promise<InferEntityType<typeof Product>[]> {
|
): Promise<InferEntityType<typeof Product>[]> {
|
||||||
|
const productsToUpdate_ = deepCopy(productsToUpdate)
|
||||||
const productIdsToUpdate: string[] = []
|
const productIdsToUpdate: string[] = []
|
||||||
|
|
||||||
productsToUpdate.forEach((productToUpdate) => {
|
productsToUpdate_.forEach((productToUpdate) => {
|
||||||
ProductRepository.#correctUpdateDTOTypes(productToUpdate)
|
ProductRepository.#correctUpdateDTOTypes(productToUpdate)
|
||||||
productIdsToUpdate.push(productToUpdate.id)
|
productIdsToUpdate.push(productToUpdate.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
const relationsToLoad =
|
const relationsToLoad =
|
||||||
ProductRepository.#getProductDeepUpdateRelationsToLoad(productsToUpdate)
|
ProductRepository.#getProductDeepUpdateRelationsToLoad(productsToUpdate_)
|
||||||
|
|
||||||
const findOptions = buildQuery(
|
const findOptions = buildQuery(
|
||||||
{ id: productIdsToUpdate },
|
{ id: productIdsToUpdate },
|
||||||
{
|
{
|
||||||
relations: relationsToLoad,
|
relations: relationsToLoad,
|
||||||
take: productsToUpdate.length,
|
take: productsToUpdate_.length,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -111,7 +113,7 @@ export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const productToUpdate of productsToUpdate) {
|
for (const productToUpdate of productsToUpdate_) {
|
||||||
const product = productsMap.get(productToUpdate.id)!
|
const product = productsMap.get(productToUpdate.id)!
|
||||||
const wrappedProduct = wrap(product)
|
const wrappedProduct = wrap(product)
|
||||||
|
|
||||||
@@ -173,7 +175,7 @@ export class ProductRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
|
|||||||
// Doing this to ensure updates are returned in the same order they were provided,
|
// Doing this to ensure updates are returned in the same order they were provided,
|
||||||
// since some core flows rely on this.
|
// since some core flows rely on this.
|
||||||
// This is a high level of coupling though.
|
// This is a high level of coupling though.
|
||||||
return productsToUpdate.map(
|
return productsToUpdate_.map(
|
||||||
(productToUpdate) => productsMap.get(productToUpdate.id)!
|
(productToUpdate) => productsMap.get(productToUpdate.id)!
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,30 +6,45 @@ import {
|
|||||||
ProductTypes,
|
ProductTypes,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
|
createMedusaMikroOrmEventSubscriber,
|
||||||
FreeTextSearchFilterKeyPrefix,
|
FreeTextSearchFilterKeyPrefix,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isDefined,
|
isDefined,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
|
MedusaInternalService,
|
||||||
|
MedusaService,
|
||||||
ModulesSdkUtils,
|
ModulesSdkUtils,
|
||||||
|
registerInternalServiceEventSubscriber,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
|
import { EntityManager, EventType } from "@mikro-orm/core"
|
||||||
import { ProductCategory } from "@models"
|
import { ProductCategory } from "@models"
|
||||||
import { ProductCategoryRepository } from "@repositories"
|
import { ProductCategoryRepository } from "@repositories"
|
||||||
import { UpdateCategoryInput } from "@types"
|
import { UpdateCategoryInput } from "@types"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
productCategoryRepository: DAL.TreeRepositoryService
|
productCategoryRepository: DAL.TreeRepositoryService
|
||||||
|
productModuleService: ReturnType<typeof MedusaService>
|
||||||
}
|
}
|
||||||
export default class ProductCategoryService {
|
|
||||||
protected readonly productCategoryRepository_: DAL.TreeRepositoryService
|
|
||||||
|
|
||||||
constructor({ productCategoryRepository }: InjectedDependencies) {
|
export default class ProductCategoryService extends MedusaInternalService<
|
||||||
this.productCategoryRepository_ = productCategoryRepository
|
InjectedDependencies,
|
||||||
|
typeof ProductCategory
|
||||||
|
>(ProductCategory) {
|
||||||
|
protected readonly productCategoryRepository_: DAL.TreeRepositoryService
|
||||||
|
protected readonly container: InjectedDependencies
|
||||||
|
|
||||||
|
constructor(container: InjectedDependencies) {
|
||||||
|
// @ts-expect-error
|
||||||
|
super(...arguments)
|
||||||
|
this.container = container
|
||||||
|
this.productCategoryRepository_ = container.productCategoryRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add support for object filter
|
// TODO: Add support for object filter
|
||||||
@InjectManager("productCategoryRepository_")
|
@InjectManager("productCategoryRepository_")
|
||||||
|
// @ts-expect-error
|
||||||
async retrieve(
|
async retrieve(
|
||||||
productCategoryId: string,
|
productCategoryId: string,
|
||||||
config: FindConfig<ProductTypes.ProductCategoryDTO> = {},
|
config: FindConfig<ProductTypes.ProductCategoryDTO> = {},
|
||||||
@@ -150,6 +165,7 @@ export default class ProductCategoryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("productCategoryRepository_")
|
@InjectTransactionManager("productCategoryRepository_")
|
||||||
|
// @ts-expect-error
|
||||||
async update(
|
async update(
|
||||||
data: UpdateCategoryInput[],
|
data: UpdateCategoryInput[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -160,14 +176,45 @@ export default class ProductCategoryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("productCategoryRepository_")
|
@InjectTransactionManager("productCategoryRepository_")
|
||||||
|
// @ts-expect-error
|
||||||
async delete(
|
async delete(
|
||||||
ids: string[],
|
ids: string[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
return await this.productCategoryRepository_.delete(ids, sharedContext)
|
const subscriber = createMedusaMikroOrmEventSubscriber(
|
||||||
|
[ProductCategory.name],
|
||||||
|
this.container["productModuleService"]
|
||||||
|
)
|
||||||
|
|
||||||
|
registerInternalServiceEventSubscriber(sharedContext, subscriber)
|
||||||
|
|
||||||
|
const deletedIds = await this.productCategoryRepository_.delete(
|
||||||
|
ids,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
// Delete are handled a bit differently since we are going to the DB directly, therefore
|
||||||
|
// just like upsert with replace, we need to dispatch the events manually.
|
||||||
|
if (deletedIds.length) {
|
||||||
|
const manager = (sharedContext.transactionManager ??
|
||||||
|
sharedContext.manager) as EntityManager
|
||||||
|
const eventManager = manager.getEventManager()
|
||||||
|
|
||||||
|
deletedIds.forEach((id) => {
|
||||||
|
eventManager.dispatchEvent(EventType.afterDelete, {
|
||||||
|
entity: { id },
|
||||||
|
meta: {
|
||||||
|
className: ProductCategory.name,
|
||||||
|
} as Parameters<typeof eventManager.dispatchEvent>[2],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return deletedIds
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("productCategoryRepository_")
|
@InjectTransactionManager("productCategoryRepository_")
|
||||||
|
// @ts-expect-error
|
||||||
async softDelete(
|
async softDelete(
|
||||||
ids: string[],
|
ids: string[],
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
@@ -178,6 +225,7 @@ export default class ProductCategoryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("productCategoryRepository_")
|
@InjectTransactionManager("productCategoryRepository_")
|
||||||
|
// @ts-expect-error
|
||||||
async restore(
|
async restore(
|
||||||
ids: string[],
|
ids: string[],
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { ProductCategoryService } from "@services"
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
arrayDifference,
|
arrayDifference,
|
||||||
|
createMedusaMikroOrmEventSubscriber,
|
||||||
EmitEvents,
|
EmitEvents,
|
||||||
generateEntityId,
|
generateEntityId,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
@@ -37,11 +38,13 @@ import {
|
|||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
MedusaService,
|
MedusaService,
|
||||||
|
MessageAggregator,
|
||||||
Modules,
|
Modules,
|
||||||
ProductStatus,
|
ProductStatus,
|
||||||
removeUndefined,
|
removeUndefined,
|
||||||
toHandle,
|
toHandle,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
|
import { EntityManager } from "@mikro-orm/core"
|
||||||
import { ProductRepository } from "../repositories"
|
import { ProductRepository } from "../repositories"
|
||||||
import {
|
import {
|
||||||
UpdateCategoryInput,
|
UpdateCategoryInput,
|
||||||
@@ -52,8 +55,8 @@ import {
|
|||||||
UpdateTagInput,
|
UpdateTagInput,
|
||||||
UpdateTypeInput,
|
UpdateTypeInput,
|
||||||
} from "../types"
|
} from "../types"
|
||||||
import { eventBuilders } from "../utils"
|
|
||||||
import { joinerConfig } from "./../joiner-config"
|
import { joinerConfig } from "./../joiner-config"
|
||||||
|
import { eventBuilders } from "../utils/events"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
baseRepository: DAL.RepositoryService
|
baseRepository: DAL.RepositoryService
|
||||||
@@ -331,11 +334,6 @@ export default class ProductModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
eventBuilders.createdProductVariant({
|
|
||||||
data: createdVariants,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return createdVariants
|
return createdVariants
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,11 +364,11 @@ export default class ProductModuleService
|
|||||||
(variant): variant is ProductTypes.CreateProductVariantDTO => !variant.id
|
(variant): variant is ProductTypes.CreateProductVariantDTO => !variant.id
|
||||||
)
|
)
|
||||||
|
|
||||||
let created: InferEntityType<typeof ProductVariant>[] = []
|
let created: ProductTypes.ProductVariantDTO[] = []
|
||||||
let updated: InferEntityType<typeof ProductVariant>[] = []
|
let updated: InferEntityType<typeof ProductVariant>[] = []
|
||||||
|
|
||||||
if (forCreate.length) {
|
if (forCreate.length) {
|
||||||
created = await this.createVariants_(forCreate, sharedContext)
|
created = await this.createProductVariants(forCreate, sharedContext)
|
||||||
}
|
}
|
||||||
if (forUpdate.length) {
|
if (forUpdate.length) {
|
||||||
updated = await this.updateVariants_(forUpdate, sharedContext)
|
updated = await this.updateVariants_(forUpdate, sharedContext)
|
||||||
@@ -493,7 +491,7 @@ export default class ProductModuleService
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { entities: productVariants, performedActions } =
|
const { entities: productVariants } =
|
||||||
await this.productVariantService_.upsertWithReplace(
|
await this.productVariantService_.upsertWithReplace(
|
||||||
productVariantsWithOptions,
|
productVariantsWithOptions,
|
||||||
{
|
{
|
||||||
@@ -502,19 +500,6 @@ export default class ProductModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
eventBuilders.createdProductVariant({
|
|
||||||
data: performedActions.created[ProductVariant.name] ?? [],
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.updatedProductVariant({
|
|
||||||
data: performedActions.updated[ProductVariant.name] ?? [],
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
eventBuilders.deletedProductVariant({
|
|
||||||
data: performedActions.deleted[ProductVariant.name] ?? [],
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return productVariants
|
return productVariants
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,11 +529,6 @@ export default class ProductModuleService
|
|||||||
ProductTypes.ProductTagDTO[]
|
ProductTypes.ProductTagDTO[]
|
||||||
>(tags)
|
>(tags)
|
||||||
|
|
||||||
eventBuilders.createdProductTag({
|
|
||||||
data: createdTags,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data) ? createdTags : createdTags[0]
|
return Array.isArray(data) ? createdTags : createdTags[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,12 +541,26 @@ export default class ProductModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<ProductTypes.ProductTagDTO>
|
): Promise<ProductTypes.ProductTagDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
async upsertProductTags(
|
async upsertProductTags(
|
||||||
data: ProductTypes.UpsertProductTagDTO[] | ProductTypes.UpsertProductTagDTO,
|
data: ProductTypes.UpsertProductTagDTO[] | ProductTypes.UpsertProductTagDTO,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<ProductTypes.ProductTagDTO[] | ProductTypes.ProductTagDTO> {
|
): Promise<ProductTypes.ProductTagDTO[] | ProductTypes.ProductTagDTO> {
|
||||||
|
const tags = await this.upsertProductTags_(data, sharedContext)
|
||||||
|
|
||||||
|
const allTags = await this.baseRepository_.serialize<
|
||||||
|
ProductTypes.ProductTagDTO[] | ProductTypes.ProductTagDTO
|
||||||
|
>(Array.isArray(data) ? tags : tags[0])
|
||||||
|
|
||||||
|
return allTags
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertProductTags_(
|
||||||
|
data: ProductTypes.UpsertProductTagDTO[] | ProductTypes.UpsertProductTagDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof ProductTag>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter((tag): tag is UpdateTagInput => !!tag.id)
|
const forUpdate = input.filter((tag): tag is UpdateTagInput => !!tag.id)
|
||||||
const forCreate = input.filter(
|
const forCreate = input.filter(
|
||||||
@@ -578,25 +572,12 @@ export default class ProductModuleService
|
|||||||
|
|
||||||
if (forCreate.length) {
|
if (forCreate.length) {
|
||||||
created = await this.productTagService_.create(forCreate, sharedContext)
|
created = await this.productTagService_.create(forCreate, sharedContext)
|
||||||
eventBuilders.createdProductTag({
|
|
||||||
data: created,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (forUpdate.length) {
|
if (forUpdate.length) {
|
||||||
updated = await this.productTagService_.update(forUpdate, sharedContext)
|
updated = await this.productTagService_.update(forUpdate, sharedContext)
|
||||||
eventBuilders.updatedProductTag({
|
|
||||||
data: updated,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = [...created, ...updated]
|
return [...created, ...updated]
|
||||||
const allTags = await this.baseRepository_.serialize<
|
|
||||||
ProductTypes.ProductTagDTO[] | ProductTypes.ProductTagDTO
|
|
||||||
>(result)
|
|
||||||
|
|
||||||
return Array.isArray(data) ? allTags : allTags[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -647,11 +628,6 @@ export default class ProductModuleService
|
|||||||
ProductTypes.ProductTagDTO[]
|
ProductTypes.ProductTagDTO[]
|
||||||
>(tags)
|
>(tags)
|
||||||
|
|
||||||
eventBuilders.updatedProductTag({
|
|
||||||
data: updatedTags,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return isString(idOrSelector) ? updatedTags[0] : updatedTags
|
return isString(idOrSelector) ? updatedTags[0] : updatedTags
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,6 +643,7 @@ export default class ProductModuleService
|
|||||||
): Promise<ProductTypes.ProductTypeDTO>
|
): Promise<ProductTypes.ProductTypeDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createProductTypes(
|
async createProductTypes(
|
||||||
data:
|
data:
|
||||||
@@ -694,13 +671,30 @@ export default class ProductModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<ProductTypes.ProductTypeDTO>
|
): Promise<ProductTypes.ProductTypeDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertProductTypes(
|
async upsertProductTypes(
|
||||||
data:
|
data:
|
||||||
| ProductTypes.UpsertProductTypeDTO[]
|
| ProductTypes.UpsertProductTypeDTO[]
|
||||||
| ProductTypes.UpsertProductTypeDTO,
|
| ProductTypes.UpsertProductTypeDTO,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<ProductTypes.ProductTypeDTO[] | ProductTypes.ProductTypeDTO> {
|
): Promise<ProductTypes.ProductTypeDTO[] | ProductTypes.ProductTypeDTO> {
|
||||||
|
const types = await this.upsertProductTypes_(data, sharedContext)
|
||||||
|
|
||||||
|
const result = await this.baseRepository_.serialize<
|
||||||
|
ProductTypes.ProductTypeDTO[] | ProductTypes.ProductTypeDTO
|
||||||
|
>(types)
|
||||||
|
|
||||||
|
return Array.isArray(data) ? result : result[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertProductTypes_(
|
||||||
|
data:
|
||||||
|
| ProductTypes.UpsertProductTypeDTO
|
||||||
|
| ProductTypes.UpsertProductTypeDTO[],
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<InferEntityType<typeof ProductType>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter((type): type is UpdateTypeInput => !!type.id)
|
const forUpdate = input.filter((type): type is UpdateTypeInput => !!type.id)
|
||||||
const forCreate = input.filter(
|
const forCreate = input.filter(
|
||||||
@@ -717,12 +711,7 @@ export default class ProductModuleService
|
|||||||
updated = await this.productTypeService_.update(forUpdate, sharedContext)
|
updated = await this.productTypeService_.update(forUpdate, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = [...created, ...updated]
|
return [...created, ...updated]
|
||||||
const allTypes = await this.baseRepository_.serialize<
|
|
||||||
ProductTypes.ProductTypeDTO[] | ProductTypes.ProductTypeDTO
|
|
||||||
>(result)
|
|
||||||
|
|
||||||
return Array.isArray(data) ? allTypes : allTypes[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -739,6 +728,7 @@ export default class ProductModuleService
|
|||||||
): Promise<ProductTypes.ProductTypeDTO[]>
|
): Promise<ProductTypes.ProductTypeDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateProductTypes(
|
async updateProductTypes(
|
||||||
idOrSelector: string | ProductTypes.FilterableProductTypeProps,
|
idOrSelector: string | ProductTypes.FilterableProductTypeProps,
|
||||||
@@ -787,6 +777,7 @@ export default class ProductModuleService
|
|||||||
): Promise<ProductTypes.ProductOptionDTO>
|
): Promise<ProductTypes.ProductOptionDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createProductOptions(
|
async createProductOptions(
|
||||||
data:
|
data:
|
||||||
@@ -842,6 +833,7 @@ export default class ProductModuleService
|
|||||||
): Promise<ProductTypes.ProductOptionDTO>
|
): Promise<ProductTypes.ProductOptionDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertProductOptions(
|
async upsertProductOptions(
|
||||||
data:
|
data:
|
||||||
| ProductTypes.UpsertProductOptionDTO[]
|
| ProductTypes.UpsertProductOptionDTO[]
|
||||||
@@ -888,6 +880,7 @@ export default class ProductModuleService
|
|||||||
): Promise<ProductTypes.ProductOptionDTO[]>
|
): Promise<ProductTypes.ProductOptionDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateProductOptions(
|
async updateProductOptions(
|
||||||
idOrSelector: string | ProductTypes.FilterableProductOptionProps,
|
idOrSelector: string | ProductTypes.FilterableProductOptionProps,
|
||||||
@@ -1023,11 +1016,6 @@ export default class ProductModuleService
|
|||||||
ProductTypes.ProductCollectionDTO[]
|
ProductTypes.ProductCollectionDTO[]
|
||||||
>(collections)
|
>(collections)
|
||||||
|
|
||||||
eventBuilders.createdProductCollection({
|
|
||||||
data: collections,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data) ? createdCollections : createdCollections[0]
|
return Array.isArray(data) ? createdCollections : createdCollections[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1061,7 +1049,7 @@ export default class ProductModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<ProductTypes.ProductCollectionDTO>
|
): Promise<ProductTypes.ProductCollectionDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
async upsertProductCollections(
|
async upsertProductCollections(
|
||||||
data:
|
data:
|
||||||
@@ -1071,6 +1059,24 @@ export default class ProductModuleService
|
|||||||
): Promise<
|
): Promise<
|
||||||
ProductTypes.ProductCollectionDTO[] | ProductTypes.ProductCollectionDTO
|
ProductTypes.ProductCollectionDTO[] | ProductTypes.ProductCollectionDTO
|
||||||
> {
|
> {
|
||||||
|
const collections = await this.upsertCollections_(data, sharedContext)
|
||||||
|
|
||||||
|
const serializedCollections = await this.baseRepository_.serialize<
|
||||||
|
ProductTypes.ProductCollectionDTO[]
|
||||||
|
>(collections)
|
||||||
|
|
||||||
|
return Array.isArray(data)
|
||||||
|
? serializedCollections
|
||||||
|
: serializedCollections[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertCollections_(
|
||||||
|
data:
|
||||||
|
| ProductTypes.UpsertProductCollectionDTO[]
|
||||||
|
| ProductTypes.UpsertProductCollectionDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof ProductCollection>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter(
|
const forUpdate = input.filter(
|
||||||
(collection): collection is UpdateCollectionInput => !!collection.id
|
(collection): collection is UpdateCollectionInput => !!collection.id
|
||||||
@@ -1091,26 +1097,7 @@ export default class ProductModuleService
|
|||||||
updated = await this.updateCollections_(forUpdate, sharedContext)
|
updated = await this.updateCollections_(forUpdate, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = [...created, ...updated]
|
return [...created, ...updated]
|
||||||
const allCollections = await this.baseRepository_.serialize<
|
|
||||||
ProductTypes.ProductCollectionDTO[] | ProductTypes.ProductCollectionDTO
|
|
||||||
>(result)
|
|
||||||
|
|
||||||
if (created.length) {
|
|
||||||
eventBuilders.createdProductCollection({
|
|
||||||
data: created,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updated.length) {
|
|
||||||
eventBuilders.updatedProductCollection({
|
|
||||||
data: updated,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.isArray(data) ? allCollections : allCollections[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -1166,11 +1153,6 @@ export default class ProductModuleService
|
|||||||
ProductTypes.ProductCollectionDTO[]
|
ProductTypes.ProductCollectionDTO[]
|
||||||
>(collections)
|
>(collections)
|
||||||
|
|
||||||
eventBuilders.updatedProductCollection({
|
|
||||||
data: updatedCollections,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return isString(idOrSelector) ? updatedCollections[0] : updatedCollections
|
return isString(idOrSelector) ? updatedCollections[0] : updatedCollections
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1283,6 +1265,7 @@ export default class ProductModuleService
|
|||||||
ProductTypes.ProductCategoryDTO[]
|
ProductTypes.ProductCategoryDTO[]
|
||||||
>(categories)
|
>(categories)
|
||||||
|
|
||||||
|
// TODO: Same as the update categories, for some reason I cant get the tree repository update
|
||||||
eventBuilders.createdProductCategory({
|
eventBuilders.createdProductCategory({
|
||||||
data: createdCategories,
|
data: createdCategories,
|
||||||
sharedContext,
|
sharedContext,
|
||||||
@@ -1300,7 +1283,7 @@ export default class ProductModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<ProductTypes.ProductCategoryDTO>
|
): Promise<ProductTypes.ProductCategoryDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
@EmitEvents()
|
@EmitEvents()
|
||||||
async upsertProductCategories(
|
async upsertProductCategories(
|
||||||
data:
|
data:
|
||||||
@@ -1310,11 +1293,27 @@ export default class ProductModuleService
|
|||||||
): Promise<
|
): Promise<
|
||||||
ProductTypes.ProductCategoryDTO[] | ProductTypes.ProductCategoryDTO
|
ProductTypes.ProductCategoryDTO[] | ProductTypes.ProductCategoryDTO
|
||||||
> {
|
> {
|
||||||
|
const categories = await this.upsertProductCategories_(data, sharedContext)
|
||||||
|
|
||||||
|
const serializedCategories = await this.baseRepository_.serialize<
|
||||||
|
ProductTypes.ProductCategoryDTO[]
|
||||||
|
>(categories)
|
||||||
|
|
||||||
|
return Array.isArray(data) ? serializedCategories : serializedCategories[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertProductCategories_(
|
||||||
|
data:
|
||||||
|
| ProductTypes.UpsertProductCategoryDTO[]
|
||||||
|
| ProductTypes.UpsertProductCategoryDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof ProductCategory>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter(
|
const forUpdate = input.filter(
|
||||||
(category): category is UpdateCategoryInput => !!category.id
|
(category): category is UpdateCategoryInput => !!category.id
|
||||||
)
|
)
|
||||||
const forCreate = input.filter(
|
let forCreate = input.filter(
|
||||||
(category): category is ProductTypes.CreateProductCategoryDTO =>
|
(category): category is ProductTypes.CreateProductCategoryDTO =>
|
||||||
!category.id
|
!category.id
|
||||||
)
|
)
|
||||||
@@ -1323,6 +1322,11 @@ export default class ProductModuleService
|
|||||||
let updated: InferEntityType<typeof ProductCategory>[] = []
|
let updated: InferEntityType<typeof ProductCategory>[] = []
|
||||||
|
|
||||||
if (forCreate.length) {
|
if (forCreate.length) {
|
||||||
|
forCreate = forCreate.map((productCategory) => {
|
||||||
|
productCategory.handle ??= kebabCase(productCategory.name)
|
||||||
|
return productCategory
|
||||||
|
})
|
||||||
|
|
||||||
created = await this.productCategoryService_.create(
|
created = await this.productCategoryService_.create(
|
||||||
forCreate,
|
forCreate,
|
||||||
sharedContext
|
sharedContext
|
||||||
@@ -1335,25 +1339,22 @@ export default class ProductModuleService
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const createdCategories = await this.baseRepository_.serialize<
|
// TODO: Same as the update categories, for some reason I cant get the tree repository update
|
||||||
ProductTypes.ProductCategoryDTO[]
|
// event. I ll need to investigate this
|
||||||
>(created)
|
if (created.length) {
|
||||||
const updatedCategories = await this.baseRepository_.serialize<
|
|
||||||
ProductTypes.ProductCategoryDTO[]
|
|
||||||
>(updated)
|
|
||||||
|
|
||||||
eventBuilders.createdProductCategory({
|
eventBuilders.createdProductCategory({
|
||||||
data: createdCategories,
|
data: created,
|
||||||
sharedContext,
|
sharedContext,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
if (updated.length) {
|
||||||
eventBuilders.updatedProductCategory({
|
eventBuilders.updatedProductCategory({
|
||||||
data: updatedCategories,
|
data: updated,
|
||||||
sharedContext,
|
sharedContext,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const result = [...createdCategories, ...updatedCategories]
|
return [...created, ...updated]
|
||||||
return Array.isArray(data) ? result : result[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -1377,8 +1378,36 @@ export default class ProductModuleService
|
|||||||
data: ProductTypes.UpdateProductCategoryDTO,
|
data: ProductTypes.UpdateProductCategoryDTO,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<
|
): Promise<
|
||||||
ProductTypes.ProductCategoryDTO[] | ProductTypes.ProductCategoryDTO
|
ProductTypes.ProductCategoryDTO | ProductTypes.ProductCategoryDTO[]
|
||||||
> {
|
> {
|
||||||
|
const categories = await this.updateProductCategories_(
|
||||||
|
idOrSelector,
|
||||||
|
data,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
const serializedCategories = await this.baseRepository_.serialize<
|
||||||
|
ProductTypes.ProductCategoryDTO[]
|
||||||
|
>(categories)
|
||||||
|
|
||||||
|
// TODO: for some reason I cant get the tree repository update
|
||||||
|
// event. I ll need to investigate this
|
||||||
|
eventBuilders.updatedProductCategory({
|
||||||
|
data: serializedCategories,
|
||||||
|
sharedContext,
|
||||||
|
})
|
||||||
|
|
||||||
|
return isString(idOrSelector)
|
||||||
|
? serializedCategories[0]
|
||||||
|
: serializedCategories
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async updateProductCategories_(
|
||||||
|
idOrSelector: string | ProductTypes.FilterableProductTypeProps,
|
||||||
|
data: ProductTypes.UpdateProductCategoryDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof ProductCategory>[]> {
|
||||||
let normalizedInput: UpdateCategoryInput[] = []
|
let normalizedInput: UpdateCategoryInput[] = []
|
||||||
if (isString(idOrSelector)) {
|
if (isString(idOrSelector)) {
|
||||||
// Check if the type exists in the first place
|
// Check if the type exists in the first place
|
||||||
@@ -1406,16 +1435,7 @@ export default class ProductModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
const updatedCategories = await this.baseRepository_.serialize<
|
return categories
|
||||||
ProductTypes.ProductCategoryDTO[]
|
|
||||||
>(categories)
|
|
||||||
|
|
||||||
eventBuilders.updatedProductCategory({
|
|
||||||
data: updatedCategories,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return isString(idOrSelector) ? updatedCategories[0] : updatedCategories
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//@ts-expect-error
|
//@ts-expect-error
|
||||||
@@ -1443,11 +1463,6 @@ export default class ProductModuleService
|
|||||||
ProductTypes.ProductDTO[]
|
ProductTypes.ProductDTO[]
|
||||||
>(products)
|
>(products)
|
||||||
|
|
||||||
eventBuilders.createdProduct({
|
|
||||||
data: createdProducts,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data) ? createdProducts : createdProducts[0]
|
return Array.isArray(data) ? createdProducts : createdProducts[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1474,11 +1489,11 @@ export default class ProductModuleService
|
|||||||
(product): product is ProductTypes.CreateProductDTO => !product.id
|
(product): product is ProductTypes.CreateProductDTO => !product.id
|
||||||
)
|
)
|
||||||
|
|
||||||
let created: InferEntityType<typeof Product>[] = []
|
let created: ProductTypes.ProductDTO[] = []
|
||||||
let updated: InferEntityType<typeof Product>[] = []
|
let updated: InferEntityType<typeof Product>[] = []
|
||||||
|
|
||||||
if (forCreate.length) {
|
if (forCreate.length) {
|
||||||
created = await this.createProducts_(forCreate, sharedContext)
|
created = await this.createProducts(forCreate, sharedContext)
|
||||||
}
|
}
|
||||||
if (forUpdate.length) {
|
if (forUpdate.length) {
|
||||||
updated = await this.updateProducts_(forUpdate, sharedContext)
|
updated = await this.updateProducts_(forUpdate, sharedContext)
|
||||||
@@ -1489,20 +1504,6 @@ export default class ProductModuleService
|
|||||||
ProductTypes.ProductDTO[] | ProductTypes.ProductDTO
|
ProductTypes.ProductDTO[] | ProductTypes.ProductDTO
|
||||||
>(result)
|
>(result)
|
||||||
|
|
||||||
if (created.length) {
|
|
||||||
eventBuilders.createdProduct({
|
|
||||||
data: created,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updated.length) {
|
|
||||||
eventBuilders.updatedProduct({
|
|
||||||
data: updated,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.isArray(data) ? allProducts : allProducts[0]
|
return Array.isArray(data) ? allProducts : allProducts[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1552,11 +1553,6 @@ export default class ProductModuleService
|
|||||||
ProductTypes.ProductDTO[]
|
ProductTypes.ProductDTO[]
|
||||||
>(products)
|
>(products)
|
||||||
|
|
||||||
eventBuilders.updatedProduct({
|
|
||||||
data: updatedProducts,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return isString(idOrSelector) ? updatedProducts[0] : updatedProducts
|
return isString(idOrSelector) ? updatedProducts[0] : updatedProducts
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1657,20 +1653,47 @@ export default class ProductModuleService
|
|||||||
data: UpdateProductInput[],
|
data: UpdateProductInput[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<InferEntityType<typeof Product>[]> {
|
): Promise<InferEntityType<typeof Product>[]> {
|
||||||
|
// We have to do that manually because this method is bypassing the product service and goes
|
||||||
|
// directly to the custom product repository
|
||||||
|
const manager = (sharedContext.transactionManager ??
|
||||||
|
sharedContext.manager) as EntityManager
|
||||||
|
const subscriber = createMedusaMikroOrmEventSubscriber(
|
||||||
|
["updateProducts_"],
|
||||||
|
this as unknown as ReturnType<typeof MedusaService<any>>
|
||||||
|
)
|
||||||
|
|
||||||
|
if (manager && subscriber) {
|
||||||
|
manager
|
||||||
|
.getEventManager()
|
||||||
|
.registerSubscriber(new subscriber(sharedContext))
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalProducts = await this.productService_.list(
|
||||||
|
{
|
||||||
|
id: data.map((d) => d.id),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relations: ["options", "options.values", "variants", "images", "tags"],
|
||||||
|
},
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
const normalizedProducts = await this.normalizeUpdateProductInput(
|
const normalizedProducts = await this.normalizeUpdateProductInput(
|
||||||
data,
|
data,
|
||||||
sharedContext
|
originalProducts
|
||||||
)
|
)
|
||||||
|
|
||||||
for (const product of normalizedProducts) {
|
for (const product of normalizedProducts) {
|
||||||
this.validateProductUpdatePayload(product)
|
this.validateProductUpdatePayload(product)
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.productRepository_.deepUpdate(
|
const updatedProducts = await this.productRepository_.deepUpdate(
|
||||||
normalizedProducts,
|
normalizedProducts,
|
||||||
ProductModuleService.validateVariantOptions,
|
ProductModuleService.validateVariantOptions,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return updatedProducts
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -1685,6 +1708,7 @@ export default class ProductModuleService
|
|||||||
data: ProductTypes.UpdateProductOptionValueDTO,
|
data: ProductTypes.UpdateProductOptionValueDTO,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<ProductTypes.ProductOptionValueDTO[]>
|
): Promise<ProductTypes.ProductOptionValueDTO[]>
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateProductOptionValues(
|
async updateProductOptionValues(
|
||||||
idOrSelector: string | FilterableProductOptionValueProps,
|
idOrSelector: string | FilterableProductOptionValueProps,
|
||||||
@@ -1693,6 +1717,11 @@ export default class ProductModuleService
|
|||||||
): Promise<
|
): Promise<
|
||||||
ProductTypes.ProductOptionValueDTO | ProductTypes.ProductOptionValueDTO[]
|
ProductTypes.ProductOptionValueDTO | ProductTypes.ProductOptionValueDTO[]
|
||||||
> {
|
> {
|
||||||
|
// TODO: There is a missmatch in the API which lead to function with different number of
|
||||||
|
// arguments. Therefore, applying the MedusaContext() decorator to the function will not work
|
||||||
|
// because the context arg index will differ from method to method.
|
||||||
|
sharedContext.messageAggregator ??= new MessageAggregator()
|
||||||
|
|
||||||
let normalizedInput: ({
|
let normalizedInput: ({
|
||||||
id: string
|
id: string
|
||||||
} & ProductTypes.UpdateProductOptionValueDTO)[] = []
|
} & ProductTypes.UpdateProductOptionValueDTO)[] = []
|
||||||
@@ -1718,7 +1747,7 @@ export default class ProductModuleService
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
const productOptionValues = await super.updateProductOptionValues(
|
const productOptionValues = await this.updateProductOptionValues_(
|
||||||
normalizedInput,
|
normalizedInput,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
@@ -1727,16 +1756,45 @@ export default class ProductModuleService
|
|||||||
ProductTypes.ProductOptionValueDTO[]
|
ProductTypes.ProductOptionValueDTO[]
|
||||||
>(productOptionValues)
|
>(productOptionValues)
|
||||||
|
|
||||||
eventBuilders.updatedProductOptionValue({
|
// TODO: Because of the wrong method override, we have to compensate to prevent breaking
|
||||||
data: updatedProductOptionValues,
|
// changes right now
|
||||||
sharedContext: sharedContext,
|
const groupedEvents = sharedContext.messageAggregator!.getMessages()
|
||||||
|
if (
|
||||||
|
Object.values(groupedEvents).flat().length > 0 &&
|
||||||
|
this.eventBusModuleService_
|
||||||
|
) {
|
||||||
|
const promises: Promise<void>[] = []
|
||||||
|
for (const group of Object.keys(groupedEvents)) {
|
||||||
|
promises.push(
|
||||||
|
this.eventBusModuleService_!.emit(groupedEvents[group], {
|
||||||
|
internal: true,
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises)
|
||||||
|
|
||||||
|
sharedContext.messageAggregator.clearMessages()
|
||||||
|
}
|
||||||
|
|
||||||
return isString(idOrSelector)
|
return isString(idOrSelector)
|
||||||
? updatedProductOptionValues[0]
|
? updatedProductOptionValues[0]
|
||||||
: updatedProductOptionValues
|
: updatedProductOptionValues
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async updateProductOptionValues_(
|
||||||
|
normalizedInput: ({
|
||||||
|
id: string
|
||||||
|
} & ProductTypes.UpdateProductOptionValueDTO)[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof ProductOptionValue>[]> {
|
||||||
|
return await this.productOptionValueService_.update(
|
||||||
|
normalizedInput,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the manually provided handle value of the product
|
* Validates the manually provided handle value of the product
|
||||||
* to be URL-safe
|
* to be URL-safe
|
||||||
@@ -1805,8 +1863,7 @@ export default class ProductModuleService
|
|||||||
const products_ = Array.isArray(products) ? products : [products]
|
const products_ = Array.isArray(products) ? products : [products]
|
||||||
|
|
||||||
const normalizedProducts = (await this.normalizeUpdateProductInput(
|
const normalizedProducts = (await this.normalizeUpdateProductInput(
|
||||||
products_ as UpdateProductInput[],
|
products_ as UpdateProductInput[]
|
||||||
sharedContext
|
|
||||||
)) as ProductTypes.CreateProductDTO[]
|
)) as ProductTypes.CreateProductDTO[]
|
||||||
|
|
||||||
for (const productData of normalizedProducts) {
|
for (const productData of normalizedProducts) {
|
||||||
@@ -1839,6 +1896,12 @@ export default class ProductModuleService
|
|||||||
) as TOutput
|
) as TOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes the input for the update product input
|
||||||
|
* @param products - The products to normalize
|
||||||
|
* @param originalProducts - The original products to use for the normalization (must include options and option values relations)
|
||||||
|
* @returns The normalized products
|
||||||
|
*/
|
||||||
protected async normalizeUpdateProductInput<
|
protected async normalizeUpdateProductInput<
|
||||||
T extends UpdateProductInput | UpdateProductInput[],
|
T extends UpdateProductInput | UpdateProductInput[],
|
||||||
TOutput = T extends UpdateProductInput[]
|
TOutput = T extends UpdateProductInput[]
|
||||||
@@ -1846,7 +1909,7 @@ export default class ProductModuleService
|
|||||||
: UpdateProductInput
|
: UpdateProductInput
|
||||||
>(
|
>(
|
||||||
products: T,
|
products: T,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
originalProducts?: InferEntityType<typeof Product>[]
|
||||||
): Promise<TOutput> {
|
): Promise<TOutput> {
|
||||||
const products_ = Array.isArray(products) ? products : [products]
|
const products_ = Array.isArray(products) ? products : [products]
|
||||||
const productsIds = products_.map((p) => p.id).filter(Boolean)
|
const productsIds = products_.map((p) => p.id).filter(Boolean)
|
||||||
@@ -1854,11 +1917,14 @@ export default class ProductModuleService
|
|||||||
let dbOptions: InferEntityType<typeof ProductOption>[] = []
|
let dbOptions: InferEntityType<typeof ProductOption>[] = []
|
||||||
|
|
||||||
if (productsIds.length) {
|
if (productsIds.length) {
|
||||||
dbOptions = await this.productOptionService_.list(
|
// Re map options to handle non serialized data as well
|
||||||
{ product_id: productsIds },
|
dbOptions =
|
||||||
{ relations: ["values"] },
|
originalProducts
|
||||||
sharedContext
|
?.map((originalProduct) =>
|
||||||
|
originalProduct.options.map((option) => option)
|
||||||
)
|
)
|
||||||
|
.flat()
|
||||||
|
.filter(Boolean) ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalizedProducts: UpdateProductInput[] = []
|
const normalizedProducts: UpdateProductInput[] = []
|
||||||
@@ -1872,7 +1938,9 @@ export default class ProductModuleService
|
|||||||
if (productData.options?.length) {
|
if (productData.options?.length) {
|
||||||
;(productData as any).options = productData.options?.map((option) => {
|
;(productData as any).options = productData.options?.map((option) => {
|
||||||
const dbOption = dbOptions.find(
|
const dbOption = dbOptions.find(
|
||||||
(o) => o.title === option.title && o.product_id === productData.id
|
(o) =>
|
||||||
|
(o.title === option.title || o.id === option.id) &&
|
||||||
|
o.product_id === productData.id
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
title: option.title,
|
title: option.title,
|
||||||
|
|||||||
@@ -6,96 +6,6 @@ import {
|
|||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
|
|
||||||
export const eventBuilders = {
|
export const eventBuilders = {
|
||||||
createdProduct: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "product",
|
|
||||||
eventName: ProductEvents.PRODUCT_CREATED,
|
|
||||||
}),
|
|
||||||
updatedProduct: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "product",
|
|
||||||
eventName: ProductEvents.PRODUCT_UPDATED,
|
|
||||||
}),
|
|
||||||
deletedProduct: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "product",
|
|
||||||
eventName: ProductEvents.PRODUCT_DELETED,
|
|
||||||
}),
|
|
||||||
createdProductVariant: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "product_variant",
|
|
||||||
eventName: ProductEvents.PRODUCT_VARIANT_CREATED,
|
|
||||||
}),
|
|
||||||
updatedProductVariant: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "product_variant",
|
|
||||||
eventName: ProductEvents.PRODUCT_VARIANT_UPDATED,
|
|
||||||
}),
|
|
||||||
deletedProductVariant: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "product_variant",
|
|
||||||
eventName: ProductEvents.PRODUCT_VARIANT_DELETED,
|
|
||||||
}),
|
|
||||||
createdProductOption: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "product_option",
|
|
||||||
eventName: ProductEvents.PRODUCT_OPTION_CREATED,
|
|
||||||
}),
|
|
||||||
updatedProductOption: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "product_option",
|
|
||||||
eventName: ProductEvents.PRODUCT_OPTION_UPDATED,
|
|
||||||
}),
|
|
||||||
deletedProductOption: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "product_option",
|
|
||||||
eventName: ProductEvents.PRODUCT_OPTION_DELETED,
|
|
||||||
}),
|
|
||||||
createdProductType: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "product_type",
|
|
||||||
eventName: ProductEvents.PRODUCT_TYPE_CREATED,
|
|
||||||
}),
|
|
||||||
updatedProductType: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "product_type",
|
|
||||||
eventName: ProductEvents.PRODUCT_TYPE_UPDATED,
|
|
||||||
}),
|
|
||||||
deletedProductType: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "product_type",
|
|
||||||
eventName: ProductEvents.PRODUCT_TYPE_DELETED,
|
|
||||||
}),
|
|
||||||
createdProductTag: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "product_tag",
|
|
||||||
eventName: ProductEvents.PRODUCT_TAG_CREATED,
|
|
||||||
}),
|
|
||||||
updatedProductTag: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "product_tag",
|
|
||||||
eventName: ProductEvents.PRODUCT_TAG_UPDATED,
|
|
||||||
}),
|
|
||||||
deletedProductTag: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "product_tag",
|
|
||||||
eventName: ProductEvents.PRODUCT_TAG_DELETED,
|
|
||||||
}),
|
|
||||||
createdProductCategory: moduleEventBuilderFactory({
|
createdProductCategory: moduleEventBuilderFactory({
|
||||||
source: Modules.PRODUCT,
|
source: Modules.PRODUCT,
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
@@ -114,40 +24,4 @@ export const eventBuilders = {
|
|||||||
object: "product_category",
|
object: "product_category",
|
||||||
eventName: ProductEvents.PRODUCT_CATEGORY_DELETED,
|
eventName: ProductEvents.PRODUCT_CATEGORY_DELETED,
|
||||||
}),
|
}),
|
||||||
createdProductCollection: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "product_collection",
|
|
||||||
eventName: ProductEvents.PRODUCT_COLLECTION_CREATED,
|
|
||||||
}),
|
|
||||||
updatedProductCollection: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "product_collection",
|
|
||||||
eventName: ProductEvents.PRODUCT_COLLECTION_UPDATED,
|
|
||||||
}),
|
|
||||||
deletedProductCollection: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "product_collection",
|
|
||||||
eventName: ProductEvents.PRODUCT_COLLECTION_DELETED,
|
|
||||||
}),
|
|
||||||
createdProductOptionValue: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "product_option_value",
|
|
||||||
eventName: ProductEvents.PRODUCT_OPTION_VALUE_CREATED,
|
|
||||||
}),
|
|
||||||
updatedProductOptionValue: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "product_option_value",
|
|
||||||
eventName: ProductEvents.PRODUCT_OPTION_VALUE_UPDATED,
|
|
||||||
}),
|
|
||||||
deletedProductOptionValue: moduleEventBuilderFactory({
|
|
||||||
source: Modules.PRODUCT,
|
|
||||||
action: CommonEvents.DELETED,
|
|
||||||
object: "product_option_value",
|
|
||||||
eventName: ProductEvents.PRODUCT_OPTION_VALUE_DELETED,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
CampaignBudgetType,
|
CampaignBudgetType,
|
||||||
ComputedActions,
|
ComputedActions,
|
||||||
deduplicate,
|
deduplicate,
|
||||||
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isDefined,
|
isDefined,
|
||||||
@@ -193,6 +194,7 @@ export default class PromotionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
async registerUsage(
|
async registerUsage(
|
||||||
computedActions: PromotionTypes.UsageComputedActions[],
|
computedActions: PromotionTypes.UsageComputedActions[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -306,6 +308,7 @@ export default class PromotionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
async revertUsage(
|
async revertUsage(
|
||||||
computedActions: PromotionTypes.UsageComputedActions[],
|
computedActions: PromotionTypes.UsageComputedActions[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -625,6 +628,7 @@ export default class PromotionModuleService
|
|||||||
): Promise<PromotionTypes.PromotionDTO[]>
|
): Promise<PromotionTypes.PromotionDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createPromotions(
|
async createPromotions(
|
||||||
data:
|
data:
|
||||||
@@ -1041,6 +1045,7 @@ export default class PromotionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
async updatePromotionRules(
|
async updatePromotionRules(
|
||||||
data: PromotionTypes.UpdatePromotionRuleDTO[],
|
data: PromotionTypes.UpdatePromotionRuleDTO[],
|
||||||
@@ -1149,6 +1154,7 @@ export default class PromotionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addPromotionTargetRules(
|
async addPromotionTargetRules(
|
||||||
promotionId: string,
|
promotionId: string,
|
||||||
rulesData: PromotionTypes.CreatePromotionRuleDTO[],
|
rulesData: PromotionTypes.CreatePromotionRuleDTO[],
|
||||||
@@ -1182,6 +1188,7 @@ export default class PromotionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addPromotionBuyRules(
|
async addPromotionBuyRules(
|
||||||
promotionId: string,
|
promotionId: string,
|
||||||
rulesData: PromotionTypes.CreatePromotionRuleDTO[],
|
rulesData: PromotionTypes.CreatePromotionRuleDTO[],
|
||||||
@@ -1278,6 +1285,7 @@ export default class PromotionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async removePromotionRules(
|
async removePromotionRules(
|
||||||
promotionId: string,
|
promotionId: string,
|
||||||
ruleIds: string[],
|
ruleIds: string[],
|
||||||
@@ -1305,6 +1313,7 @@ export default class PromotionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async removePromotionTargetRules(
|
async removePromotionTargetRules(
|
||||||
promotionId: string,
|
promotionId: string,
|
||||||
ruleIds: string[],
|
ruleIds: string[],
|
||||||
@@ -1379,6 +1388,7 @@ export default class PromotionModuleService
|
|||||||
): Promise<PromotionTypes.CampaignDTO[]>
|
): Promise<PromotionTypes.CampaignDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createCampaigns(
|
async createCampaigns(
|
||||||
data: PromotionTypes.CreateCampaignDTO | PromotionTypes.CreateCampaignDTO[],
|
data: PromotionTypes.CreateCampaignDTO | PromotionTypes.CreateCampaignDTO[],
|
||||||
@@ -1490,6 +1500,7 @@ export default class PromotionModuleService
|
|||||||
): Promise<PromotionTypes.CampaignDTO[]>
|
): Promise<PromotionTypes.CampaignDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateCampaigns(
|
async updateCampaigns(
|
||||||
data: PromotionTypes.UpdateCampaignDTO | PromotionTypes.UpdateCampaignDTO[],
|
data: PromotionTypes.UpdateCampaignDTO | PromotionTypes.UpdateCampaignDTO[],
|
||||||
@@ -1583,9 +1594,10 @@ export default class PromotionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async addPromotionsToCampaign(
|
async addPromotionsToCampaign(
|
||||||
data: PromotionTypes.AddPromotionsToCampaignDTO,
|
data: PromotionTypes.AddPromotionsToCampaignDTO,
|
||||||
sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
): Promise<{ ids: string[] }> {
|
): Promise<{ ids: string[] }> {
|
||||||
const ids = await this.addPromotionsToCampaign_(data, sharedContext)
|
const ids = await this.addPromotionsToCampaign_(data, sharedContext)
|
||||||
|
|
||||||
@@ -1650,9 +1662,10 @@ export default class PromotionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async removePromotionsFromCampaign(
|
async removePromotionsFromCampaign(
|
||||||
data: PromotionTypes.AddPromotionsToCampaignDTO,
|
data: PromotionTypes.AddPromotionsToCampaignDTO,
|
||||||
sharedContext?: Context
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<{ ids: string[] }> {
|
): Promise<{ ids: string[] }> {
|
||||||
const ids = await this.removePromotionsFromCampaign_(data, sharedContext)
|
const ids = await this.removePromotionsFromCampaign_(data, sharedContext)
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
arrayDifference,
|
arrayDifference,
|
||||||
|
EmitEvents,
|
||||||
getDuplicates,
|
getDuplicates,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
@@ -78,6 +79,7 @@ export default class RegionModuleService
|
|||||||
): Promise<RegionDTO>
|
): Promise<RegionDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createRegions(
|
async createRegions(
|
||||||
data: CreateRegionDTO | CreateRegionDTO[],
|
data: CreateRegionDTO | CreateRegionDTO[],
|
||||||
@@ -132,6 +134,7 @@ export default class RegionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async softDeleteRegions(
|
async softDeleteRegions(
|
||||||
ids: string | object | string[] | object[],
|
ids: string | object | string[] | object[],
|
||||||
@@ -160,11 +163,24 @@ export default class RegionModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<RegionDTO>
|
): Promise<RegionDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertRegions(
|
async upsertRegions(
|
||||||
data: UpsertRegionDTO | UpsertRegionDTO[],
|
data: UpsertRegionDTO | UpsertRegionDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<RegionDTO | RegionDTO[]> {
|
): Promise<RegionDTO | RegionDTO[]> {
|
||||||
|
const result = await this.upsertRegions_(data, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<RegionDTO[] | RegionDTO>(
|
||||||
|
Array.isArray(data) ? result : result[0]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertRegions_(
|
||||||
|
data: UpsertRegionDTO | UpsertRegionDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof Region>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter(
|
const forUpdate = input.filter(
|
||||||
(region): region is UpdateRegionInput => !!region.id
|
(region): region is UpdateRegionInput => !!region.id
|
||||||
@@ -183,9 +199,8 @@ export default class RegionModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = (await promiseAll(operations)).flat()
|
const result = (await promiseAll(operations)).flat()
|
||||||
return await this.baseRepository_.serialize<RegionDTO[] | RegionDTO>(
|
|
||||||
Array.isArray(data) ? result : result[0]
|
return result
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -202,6 +217,7 @@ export default class RegionModuleService
|
|||||||
): Promise<RegionDTO[]>
|
): Promise<RegionDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateRegions(
|
async updateRegions(
|
||||||
idOrSelector: string | FilterableRegionProps,
|
idOrSelector: string | FilterableRegionProps,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
UpsertSalesChannelDTO,
|
UpsertSalesChannelDTO,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isString,
|
isString,
|
||||||
@@ -67,6 +68,7 @@ export default class SalesChannelModuleService
|
|||||||
): Promise<SalesChannelDTO>
|
): Promise<SalesChannelDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createSalesChannels(
|
async createSalesChannels(
|
||||||
data: CreateSalesChannelDTO | CreateSalesChannelDTO[],
|
data: CreateSalesChannelDTO | CreateSalesChannelDTO[],
|
||||||
@@ -77,10 +79,7 @@ export default class SalesChannelModuleService
|
|||||||
const result = await this.createSalesChannels_(input, sharedContext)
|
const result = await this.createSalesChannels_(input, sharedContext)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<SalesChannelDTO[]>(
|
return await this.baseRepository_.serialize<SalesChannelDTO[]>(
|
||||||
Array.isArray(data) ? result : result[0],
|
Array.isArray(data) ? result : result[0]
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +105,7 @@ export default class SalesChannelModuleService
|
|||||||
): Promise<SalesChannelDTO[]>
|
): Promise<SalesChannelDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateSalesChannels(
|
async updateSalesChannels(
|
||||||
idOrSelector: string | FilterableSalesChannelProps,
|
idOrSelector: string | FilterableSalesChannelProps,
|
||||||
@@ -134,10 +134,7 @@ export default class SalesChannelModuleService
|
|||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<SalesChannelDTO[]>(
|
return await this.baseRepository_.serialize<SalesChannelDTO[]>(
|
||||||
Array.isArray(data) ? result : result[0],
|
Array.isArray(data) ? result : result[0]
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,11 +154,25 @@ export default class SalesChannelModuleService
|
|||||||
data: UpsertSalesChannelDTO,
|
data: UpsertSalesChannelDTO,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<SalesChannelDTO>
|
): Promise<SalesChannelDTO>
|
||||||
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
async upsertSalesChannels(
|
async upsertSalesChannels(
|
||||||
data: UpsertSalesChannelDTO | UpsertSalesChannelDTO[],
|
data: UpsertSalesChannelDTO | UpsertSalesChannelDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<SalesChannelDTO | SalesChannelDTO[]> {
|
): Promise<SalesChannelDTO | SalesChannelDTO[]> {
|
||||||
|
const result = await this.upsertSalesChannels_(data, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<
|
||||||
|
SalesChannelDTO[] | SalesChannelDTO
|
||||||
|
>(Array.isArray(data) ? result : result[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertSalesChannels_(
|
||||||
|
data: UpsertSalesChannelDTO | UpsertSalesChannelDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof SalesChannel>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter(
|
const forUpdate = input.filter(
|
||||||
(channel): channel is UpdateSalesChannelDTO => !!channel.id
|
(channel): channel is UpdateSalesChannelDTO => !!channel.id
|
||||||
@@ -180,8 +191,7 @@ export default class SalesChannelModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = (await promiseAll(operations)).flat()
|
const result = (await promiseAll(operations)).flat()
|
||||||
return await this.baseRepository_.serialize<
|
|
||||||
SalesChannelDTO[] | SalesChannelDTO
|
return result
|
||||||
>(Array.isArray(data) ? result : result[0])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
SettingsTypes,
|
SettingsTypes,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
@@ -50,7 +51,8 @@ export default class SettingsModuleService
|
|||||||
this.userPreferenceService_ = userPreferenceService
|
this.userPreferenceService_ = userPreferenceService
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createViewConfigurations(
|
async createViewConfigurations(
|
||||||
data:
|
data:
|
||||||
@@ -97,10 +99,14 @@ export default class SettingsModuleService
|
|||||||
dataArray,
|
dataArray,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
return isArrayInput ? result : result[0]
|
|
||||||
|
return await this.baseRepository_.serialize<
|
||||||
|
SettingsTypes.ViewConfigurationDTO[] | SettingsTypes.ViewConfigurationDTO
|
||||||
|
>(isArrayInput ? result : result[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateViewConfigurations(
|
async updateViewConfigurations(
|
||||||
idOrSelector: string | SettingsTypes.FilterableViewConfigurationProps,
|
idOrSelector: string | SettingsTypes.FilterableViewConfigurationProps,
|
||||||
@@ -109,6 +115,25 @@ export default class SettingsModuleService
|
|||||||
): Promise<
|
): Promise<
|
||||||
SettingsTypes.ViewConfigurationDTO | SettingsTypes.ViewConfigurationDTO[]
|
SettingsTypes.ViewConfigurationDTO | SettingsTypes.ViewConfigurationDTO[]
|
||||||
> {
|
> {
|
||||||
|
const updated = await this.updateViewConfigurations_(
|
||||||
|
idOrSelector,
|
||||||
|
data,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
const serialized = await this.baseRepository_.serialize<
|
||||||
|
SettingsTypes.ViewConfigurationDTO[] | SettingsTypes.ViewConfigurationDTO
|
||||||
|
>(updated)
|
||||||
|
|
||||||
|
return typeof idOrSelector === "string" ? serialized[0] : serialized
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async updateViewConfigurations_(
|
||||||
|
idOrSelector: string | SettingsTypes.FilterableViewConfigurationProps,
|
||||||
|
data: SettingsTypes.UpdateViewConfigurationDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof ViewConfiguration>[]> {
|
||||||
let selector: SettingsTypes.FilterableViewConfigurationProps = {}
|
let selector: SettingsTypes.FilterableViewConfigurationProps = {}
|
||||||
|
|
||||||
if (typeof idOrSelector === "string") {
|
if (typeof idOrSelector === "string") {
|
||||||
@@ -164,11 +189,7 @@ export default class SettingsModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
return updatedEntities
|
||||||
SettingsTypes.ViewConfigurationDTO[]
|
|
||||||
>(updatedEntities, { populate: true })
|
|
||||||
|
|
||||||
return typeof idOrSelector === "string" ? serialized[0] : serialized
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For non-configuration updates, use the standard update method
|
// For non-configuration updates, use the standard update method
|
||||||
@@ -177,11 +198,7 @@ export default class SettingsModuleService
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
return updated as unknown as InferEntityType<typeof ViewConfiguration>[]
|
||||||
SettingsTypes.ViewConfigurationDTO[]
|
|
||||||
>(updated, { populate: true })
|
|
||||||
|
|
||||||
return typeof idOrSelector === "string" ? serialized[0] : serialized
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
@@ -201,12 +218,12 @@ export default class SettingsModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<SettingsTypes.UserPreferenceDTO>(
|
return await this.baseRepository_.serialize<SettingsTypes.UserPreferenceDTO>(
|
||||||
prefs[0],
|
prefs[0]
|
||||||
{ populate: true }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async setUserPreference(
|
async setUserPreference(
|
||||||
userId: string,
|
userId: string,
|
||||||
key: string,
|
key: string,
|
||||||
@@ -236,8 +253,7 @@ export default class SettingsModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<SettingsTypes.UserPreferenceDTO>(
|
return await this.baseRepository_.serialize<SettingsTypes.UserPreferenceDTO>(
|
||||||
result,
|
result
|
||||||
{ populate: true }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +313,8 @@ export default class SettingsModuleService
|
|||||||
return systemDefaults.length > 0 ? systemDefaults[0] : null
|
return systemDefaults.length > 0 ? systemDefaults[0] : null
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async setActiveViewConfiguration(
|
async setActiveViewConfiguration(
|
||||||
entity: string,
|
entity: string,
|
||||||
userId: string,
|
userId: string,
|
||||||
@@ -347,7 +364,8 @@ export default class SettingsModuleService
|
|||||||
return systemDefaults.length > 0 ? systemDefaults[0] : null
|
return systemDefaults.length > 0 ? systemDefaults[0] : null
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async clearActiveViewConfiguration(
|
async clearActiveViewConfiguration(
|
||||||
entity: string,
|
entity: string,
|
||||||
userId: string,
|
userId: string,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
UpsertStockLocationInput,
|
UpsertStockLocationInput,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isString,
|
isString,
|
||||||
@@ -86,7 +87,9 @@ export default class StockLocationModuleService
|
|||||||
data: CreateStockLocationInput[],
|
data: CreateStockLocationInput[],
|
||||||
context: Context
|
context: Context
|
||||||
): Promise<StockLocationTypes.StockLocationDTO[]>
|
): Promise<StockLocationTypes.StockLocationDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createStockLocations(
|
async createStockLocations(
|
||||||
data: CreateStockLocationInput | CreateStockLocationInput[],
|
data: CreateStockLocationInput | CreateStockLocationInput[],
|
||||||
@@ -101,7 +104,7 @@ export default class StockLocationModuleService
|
|||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
| StockLocationTypes.StockLocationDTO
|
| StockLocationTypes.StockLocationDTO
|
||||||
| StockLocationTypes.StockLocationDTO[]
|
| StockLocationTypes.StockLocationDTO[]
|
||||||
>(created, { populate: true })
|
>(created)
|
||||||
|
|
||||||
return Array.isArray(data) ? serialized : serialized[0]
|
return Array.isArray(data) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
@@ -124,6 +127,7 @@ export default class StockLocationModuleService
|
|||||||
): Promise<StockLocationTypes.StockLocationDTO[]>
|
): Promise<StockLocationTypes.StockLocationDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertStockLocations(
|
async upsertStockLocations(
|
||||||
data: UpsertStockLocationInput | UpsertStockLocationInput[],
|
data: UpsertStockLocationInput | UpsertStockLocationInput[],
|
||||||
@MedusaContext() context: Context = {}
|
@MedusaContext() context: Context = {}
|
||||||
@@ -179,6 +183,7 @@ export default class StockLocationModuleService
|
|||||||
input: UpdateStockLocationInput,
|
input: UpdateStockLocationInput,
|
||||||
context?: Context
|
context?: Context
|
||||||
): Promise<StockLocationTypes.StockLocationDTO[]>
|
): Promise<StockLocationTypes.StockLocationDTO[]>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates an existing stock location.
|
* Updates an existing stock location.
|
||||||
* @param stockLocationId - The ID of the stock location to update.
|
* @param stockLocationId - The ID of the stock location to update.
|
||||||
@@ -187,6 +192,7 @@ export default class StockLocationModuleService
|
|||||||
* @returns The updated stock location.
|
* @returns The updated stock location.
|
||||||
*/
|
*/
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateStockLocations(
|
async updateStockLocations(
|
||||||
idOrSelector: string | FilterableStockLocationProps,
|
idOrSelector: string | FilterableStockLocationProps,
|
||||||
@@ -208,7 +214,7 @@ export default class StockLocationModuleService
|
|||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
| StockLocationTypes.StockLocationDTO
|
| StockLocationTypes.StockLocationDTO
|
||||||
| StockLocationTypes.StockLocationDTO[]
|
| StockLocationTypes.StockLocationDTO[]
|
||||||
>(updated, { populate: true })
|
>(updated)
|
||||||
|
|
||||||
return Array.isArray(data) ? serialized : serialized[0]
|
return Array.isArray(data) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
@@ -239,6 +245,7 @@ export default class StockLocationModuleService
|
|||||||
): Promise<StockLocationTypes.StockLocationAddressDTO[]>
|
): Promise<StockLocationTypes.StockLocationAddressDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateStockLocationAddresses(
|
async updateStockLocationAddresses(
|
||||||
data:
|
data:
|
||||||
@@ -253,7 +260,7 @@ export default class StockLocationModuleService
|
|||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
| StockLocationTypes.StockLocationAddressDTO
|
| StockLocationTypes.StockLocationAddressDTO
|
||||||
| StockLocationTypes.StockLocationAddressDTO[]
|
| StockLocationTypes.StockLocationAddressDTO[]
|
||||||
>(updated, { populate: true })
|
>(updated)
|
||||||
|
|
||||||
return Array.isArray(data) ? serialized : serialized[0]
|
return Array.isArray(data) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
@@ -276,6 +283,7 @@ export default class StockLocationModuleService
|
|||||||
): Promise<StockLocationTypes.StockLocationAddressDTO[]>
|
): Promise<StockLocationTypes.StockLocationAddressDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertStockLocationAddresses(
|
async upsertStockLocationAddresses(
|
||||||
data: UpsertStockLocationAddressInput | UpsertStockLocationAddressInput[],
|
data: UpsertStockLocationAddressInput | UpsertStockLocationAddressInput[],
|
||||||
@MedusaContext() context: Context = {}
|
@MedusaContext() context: Context = {}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
StoreTypes,
|
StoreTypes,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
|
EmitEvents,
|
||||||
getDuplicates,
|
getDuplicates,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
@@ -59,7 +60,9 @@ export default class StoreModuleService
|
|||||||
data: StoreTypes.CreateStoreDTO,
|
data: StoreTypes.CreateStoreDTO,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<StoreTypes.StoreDTO>
|
): Promise<StoreTypes.StoreDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createStores(
|
async createStores(
|
||||||
data: StoreTypes.CreateStoreDTO | StoreTypes.CreateStoreDTO[],
|
data: StoreTypes.CreateStoreDTO | StoreTypes.CreateStoreDTO[],
|
||||||
@@ -99,11 +102,25 @@ export default class StoreModuleService
|
|||||||
data: StoreTypes.UpsertStoreDTO,
|
data: StoreTypes.UpsertStoreDTO,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<StoreTypes.StoreDTO>
|
): Promise<StoreTypes.StoreDTO>
|
||||||
@InjectTransactionManager()
|
|
||||||
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertStores(
|
async upsertStores(
|
||||||
data: StoreTypes.UpsertStoreDTO | StoreTypes.UpsertStoreDTO[],
|
data: StoreTypes.UpsertStoreDTO | StoreTypes.UpsertStoreDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<StoreTypes.StoreDTO | StoreTypes.StoreDTO[]> {
|
): Promise<StoreTypes.StoreDTO | StoreTypes.StoreDTO[]> {
|
||||||
|
const result = await this.upsertStores_(data, sharedContext)
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<
|
||||||
|
StoreTypes.StoreDTO[] | StoreTypes.StoreDTO
|
||||||
|
>(Array.isArray(data) ? result : result[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
protected async upsertStores_(
|
||||||
|
data: StoreTypes.UpsertStoreDTO | StoreTypes.UpsertStoreDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<InferEntityType<typeof Store>[]> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const forUpdate = input.filter(
|
const forUpdate = input.filter(
|
||||||
(store): store is UpdateStoreInput => !!store.id
|
(store): store is UpdateStoreInput => !!store.id
|
||||||
@@ -122,9 +139,8 @@ export default class StoreModuleService
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = (await promiseAll(operations)).flat()
|
const result = (await promiseAll(operations)).flat()
|
||||||
return await this.baseRepository_.serialize<
|
|
||||||
StoreTypes.StoreDTO[] | StoreTypes.StoreDTO
|
return result
|
||||||
>(Array.isArray(data) ? result : result[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -139,7 +155,9 @@ export default class StoreModuleService
|
|||||||
data: StoreTypes.UpdateStoreDTO,
|
data: StoreTypes.UpdateStoreDTO,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<StoreTypes.StoreDTO[]>
|
): Promise<StoreTypes.StoreDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateStores(
|
async updateStores(
|
||||||
idOrSelector: string | StoreTypes.FilterableStoreProps,
|
idOrSelector: string | StoreTypes.FilterableStoreProps,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
TaxTypes,
|
TaxTypes,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isDefined,
|
isDefined,
|
||||||
@@ -17,7 +18,6 @@ import {
|
|||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
ModulesSdkUtils,
|
ModulesSdkUtils,
|
||||||
promiseAll,
|
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { TaxProvider, TaxRate, TaxRateRule, TaxRegion } from "@models"
|
import { TaxProvider, TaxRate, TaxRateRule, TaxRegion } from "@models"
|
||||||
import { TaxProviderService } from "@services"
|
import { TaxProviderService } from "@services"
|
||||||
@@ -94,6 +94,7 @@ export default class TaxModuleService
|
|||||||
): Promise<TaxTypes.TaxRateDTO>
|
): Promise<TaxTypes.TaxRateDTO>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createTaxRates(
|
async createTaxRates(
|
||||||
data: TaxTypes.CreateTaxRateDTO[] | TaxTypes.CreateTaxRateDTO,
|
data: TaxTypes.CreateTaxRateDTO[] | TaxTypes.CreateTaxRateDTO,
|
||||||
@@ -101,7 +102,12 @@ export default class TaxModuleService
|
|||||||
): Promise<TaxTypes.TaxRateDTO[] | TaxTypes.TaxRateDTO> {
|
): Promise<TaxTypes.TaxRateDTO[] | TaxTypes.TaxRateDTO> {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const rates = await this.createTaxRates_(input, sharedContext)
|
const rates = await this.createTaxRates_(input, sharedContext)
|
||||||
return Array.isArray(data) ? rates : rates[0]
|
|
||||||
|
const serialized = await this.baseRepository_.serialize<
|
||||||
|
TaxTypes.TaxRateDTO[] | TaxTypes.TaxRateDTO
|
||||||
|
>(rates)
|
||||||
|
|
||||||
|
return Array.isArray(data) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
@@ -145,9 +151,7 @@ export default class TaxModuleService
|
|||||||
await this.taxRateRuleService_.create(rulesToCreate, sharedContext)
|
await this.taxRateRuleService_.create(rulesToCreate, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<TaxTypes.TaxRateDTO[]>(rates, {
|
return rates
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -170,6 +174,7 @@ export default class TaxModuleService
|
|||||||
): Promise<TaxTypes.TaxRateDTO[]>
|
): Promise<TaxTypes.TaxRateDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async updateTaxRates(
|
async updateTaxRates(
|
||||||
selector: string | string[] | TaxTypes.FilterableTaxRateProps,
|
selector: string | string[] | TaxTypes.FilterableTaxRateProps,
|
||||||
@@ -177,9 +182,11 @@ export default class TaxModuleService
|
|||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<TaxTypes.TaxRateDTO | TaxTypes.TaxRateDTO[]> {
|
): Promise<TaxTypes.TaxRateDTO | TaxTypes.TaxRateDTO[]> {
|
||||||
const rates = await this.updateTaxRates_(selector, data, sharedContext)
|
const rates = await this.updateTaxRates_(selector, data, sharedContext)
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
TaxTypes.TaxRateDTO[]
|
TaxTypes.TaxRateDTO[]
|
||||||
>(rates, { populate: true })
|
>(rates)
|
||||||
|
|
||||||
return isString(selector) ? serialized[0] : serialized
|
return isString(selector) ? serialized[0] : serialized
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,15 +289,18 @@ export default class TaxModuleService
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<TaxTypes.TaxRateDTO>
|
): Promise<TaxTypes.TaxRateDTO>
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
async upsertTaxRates(
|
async upsertTaxRates(
|
||||||
data: TaxTypes.UpsertTaxRateDTO | TaxTypes.UpsertTaxRateDTO[],
|
data: TaxTypes.UpsertTaxRateDTO | TaxTypes.UpsertTaxRateDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<TaxTypes.TaxRateDTO | TaxTypes.TaxRateDTO[]> {
|
): Promise<TaxTypes.TaxRateDTO | TaxTypes.TaxRateDTO[]> {
|
||||||
const result = await this.taxRateService_.upsert(data, sharedContext)
|
const result = await this.taxRateService_.upsert(data, sharedContext)
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
TaxTypes.TaxRateDTO[]
|
TaxTypes.TaxRateDTO[]
|
||||||
>(result, { populate: true })
|
>(result)
|
||||||
|
|
||||||
return Array.isArray(data) ? serialized : serialized[0]
|
return Array.isArray(data) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,6 +317,7 @@ export default class TaxModuleService
|
|||||||
): Promise<TaxRegionDTO[]>
|
): Promise<TaxRegionDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createTaxRegions(
|
async createTaxRegions(
|
||||||
data: TaxTypes.CreateTaxRegionDTO | TaxTypes.CreateTaxRegionDTO[],
|
data: TaxTypes.CreateTaxRegionDTO | TaxTypes.CreateTaxRegionDTO[],
|
||||||
@@ -314,9 +325,15 @@ export default class TaxModuleService
|
|||||||
) {
|
) {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const result = await this.createTaxRegions_(input, sharedContext)
|
const result = await this.createTaxRegions_(input, sharedContext)
|
||||||
return Array.isArray(data) ? result : result[0]
|
|
||||||
|
const serialized = await this.baseRepository_.serialize<
|
||||||
|
TaxTypes.TaxRegionDTO[] | TaxTypes.TaxRegionDTO
|
||||||
|
>(result)
|
||||||
|
|
||||||
|
return Array.isArray(data) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
async createTaxRegions_(
|
async createTaxRegions_(
|
||||||
data: TaxTypes.CreateTaxRegionDTO[],
|
data: TaxTypes.CreateTaxRegionDTO[],
|
||||||
sharedContext: Context = {}
|
sharedContext: Context = {}
|
||||||
@@ -347,10 +364,7 @@ export default class TaxModuleService
|
|||||||
await this.createTaxRates(rates, sharedContext)
|
await this.createTaxRates(rates, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<TaxTypes.TaxRegionDTO[]>(
|
return regions
|
||||||
regions,
|
|
||||||
{ populate: true }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -365,6 +379,7 @@ export default class TaxModuleService
|
|||||||
): Promise<TaxTypes.TaxRateRuleDTO[]>
|
): Promise<TaxTypes.TaxRateRuleDTO[]>
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
|
@EmitEvents()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async createTaxRateRules(
|
async createTaxRateRules(
|
||||||
data: TaxTypes.CreateTaxRateRuleDTO | TaxTypes.CreateTaxRateRuleDTO[],
|
data: TaxTypes.CreateTaxRateRuleDTO | TaxTypes.CreateTaxRateRuleDTO[],
|
||||||
@@ -372,7 +387,12 @@ export default class TaxModuleService
|
|||||||
) {
|
) {
|
||||||
const input = Array.isArray(data) ? data : [data]
|
const input = Array.isArray(data) ? data : [data]
|
||||||
const result = await this.createTaxRateRules_(input, sharedContext)
|
const result = await this.createTaxRateRules_(input, sharedContext)
|
||||||
return Array.isArray(data) ? result : result[0]
|
|
||||||
|
const serialized = await this.baseRepository_.serialize<
|
||||||
|
TaxTypes.TaxRateRuleDTO[] | TaxTypes.TaxRateRuleDTO
|
||||||
|
>(result)
|
||||||
|
|
||||||
|
return Array.isArray(data) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
@@ -381,12 +401,7 @@ export default class TaxModuleService
|
|||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
) {
|
) {
|
||||||
const rules = await this.taxRateRuleService_.create(data, sharedContext)
|
const rules = await this.taxRateRuleService_.create(data, sharedContext)
|
||||||
return await this.baseRepository_.serialize<TaxTypes.TaxRateRuleDTO[]>(
|
return rules
|
||||||
rules,
|
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
@@ -419,29 +434,70 @@ export default class TaxModuleService
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const toReturn = await promiseAll(
|
|
||||||
items.map(async (item) => {
|
|
||||||
const regionIds = regions.map((r) => r.id)
|
const regionIds = regions.map((r) => r.id)
|
||||||
const rateQuery = this.getTaxRateQueryForItem(item, regionIds)
|
|
||||||
const candidateRates = await this.taxRateService_.list(
|
// Collect all unique reference IDs for batch query
|
||||||
rateQuery,
|
const productIds = new Set<string>()
|
||||||
|
const productTypeIds = new Set<string>()
|
||||||
|
const shippingOptionIds = new Set<string>()
|
||||||
|
|
||||||
|
items.forEach((item) => {
|
||||||
|
if ("shipping_option_id" in item) {
|
||||||
|
shippingOptionIds.add(item.shipping_option_id)
|
||||||
|
} else {
|
||||||
|
productIds.add(item.product_id)
|
||||||
|
if (item.product_type_id) {
|
||||||
|
productTypeIds.add(item.product_type_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Build comprehensive query for all items
|
||||||
|
const ruleQueries = [
|
||||||
|
...Array.from(productIds).map((id) => ({
|
||||||
|
reference: "product",
|
||||||
|
reference_id: id,
|
||||||
|
})),
|
||||||
|
...Array.from(productTypeIds).map((id) => ({
|
||||||
|
reference: "product_type",
|
||||||
|
reference_id: id,
|
||||||
|
})),
|
||||||
|
...Array.from(shippingOptionIds).map((id) => ({
|
||||||
|
reference: "shipping_option",
|
||||||
|
reference_id: id,
|
||||||
|
})),
|
||||||
|
]
|
||||||
|
|
||||||
|
const allCandidateRates = await this.taxRateService_.list(
|
||||||
|
{
|
||||||
|
$and: [
|
||||||
|
{ tax_region_id: regionIds },
|
||||||
|
{
|
||||||
|
$or: [
|
||||||
|
{ is_default: true },
|
||||||
|
...(ruleQueries.length ? [{ rules: { $or: ruleQueries } }] : []),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
relations: ["tax_region", "rules"],
|
relations: ["tax_region", "rules"],
|
||||||
},
|
},
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
const applicableRates = await this.getTaxRatesForItem(
|
const toReturn = items.map((item) => {
|
||||||
item,
|
const rateQuery = this.getTaxRateQueryForItem(item, regionIds)
|
||||||
candidateRates
|
const candidateRates = allCandidateRates.filter((rate) =>
|
||||||
|
this.rateMatchesQuery(rate, rateQuery)
|
||||||
)
|
)
|
||||||
|
const applicableRates = this.getTaxRatesForItem(item, candidateRates)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rates: applicableRates,
|
rates: applicableRates,
|
||||||
item,
|
item,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
|
||||||
|
|
||||||
const taxLines = await this.getTaxLinesFromProvider(
|
const taxLines = await this.getTaxLinesFromProvider(
|
||||||
parentRegion.provider_id as string,
|
parentRegion.provider_id as string,
|
||||||
@@ -574,10 +630,10 @@ export default class TaxModuleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getTaxRatesForItem(
|
private getTaxRatesForItem(
|
||||||
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO,
|
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO,
|
||||||
rates: InferEntityType<typeof TaxRate>[]
|
rates: InferEntityType<typeof TaxRate>[]
|
||||||
): Promise<InferEntityType<typeof TaxRate>[]> {
|
): InferEntityType<typeof TaxRate>[] {
|
||||||
if (!rates.length) {
|
if (!rates.length) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@@ -609,7 +665,17 @@ export default class TaxModuleService
|
|||||||
private getTaxRateQueryForItem(
|
private getTaxRateQueryForItem(
|
||||||
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO,
|
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO,
|
||||||
regionIds: string[]
|
regionIds: string[]
|
||||||
) {
|
): {
|
||||||
|
$and: {
|
||||||
|
tax_region_id?: string[]
|
||||||
|
$or?: {
|
||||||
|
is_default?: boolean
|
||||||
|
rules?: {
|
||||||
|
$or: { reference: string; reference_id: string | undefined }[]
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
} {
|
||||||
const isShipping = "shipping_option_id" in item
|
const isShipping = "shipping_option_id" in item
|
||||||
let ruleQuery = isShipping
|
let ruleQuery = isShipping
|
||||||
? [
|
? [
|
||||||
@@ -637,6 +703,58 @@ export default class TaxModuleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private rateMatchesQuery(
|
||||||
|
rate: InferEntityType<typeof TaxRate>,
|
||||||
|
query: {
|
||||||
|
$and: {
|
||||||
|
tax_region_id?: string[]
|
||||||
|
$or?: {
|
||||||
|
is_default?: boolean
|
||||||
|
rules?: {
|
||||||
|
$or: { reference: string; reference_id: string | undefined }[]
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
): boolean {
|
||||||
|
const { $and } = query
|
||||||
|
const [regionCheck, ruleCheck] = $and
|
||||||
|
|
||||||
|
// Check region match
|
||||||
|
if (!regionCheck.tax_region_id?.includes(rate.tax_region_id)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check rule match
|
||||||
|
const { $or } = ruleCheck
|
||||||
|
if (rate.is_default) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if any rule matches
|
||||||
|
for (const ruleCondition of $or ?? []) {
|
||||||
|
if (ruleCondition.is_default && rate.is_default) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (ruleCondition.rules) {
|
||||||
|
const { $or: ruleQueries } = ruleCondition.rules
|
||||||
|
for (const ruleQuery of ruleQueries) {
|
||||||
|
if (
|
||||||
|
[...(rate.rules ?? [])]?.some(
|
||||||
|
(rule: InferEntityType<typeof TaxRateRule>) =>
|
||||||
|
rule.reference === ruleQuery.reference &&
|
||||||
|
rule.reference_id === ruleQuery.reference_id
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private checkRuleMatches(
|
private checkRuleMatches(
|
||||||
rate: InferEntityType<typeof TaxRate>,
|
rate: InferEntityType<typeof TaxRate>,
|
||||||
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO
|
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO
|
||||||
|
|||||||
@@ -172,17 +172,20 @@ moduleIntegrationTestRunner<IUserModuleService>({
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
// 2 events: 1 invite updated, 1 invite token generated
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
const events = eventBusSpy.mock.calls[0][0]
|
||||||
[
|
expect(events).toHaveLength(2)
|
||||||
|
expect(events).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: { id: "1" },
|
data: { id: "1" },
|
||||||
name: UserEvents.INVITE_UPDATED,
|
name: UserEvents.INVITE_UPDATED,
|
||||||
}),
|
}),
|
||||||
],
|
expect.objectContaining({
|
||||||
{
|
data: { id: "1" },
|
||||||
internal: true,
|
name: UserEvents.INVITE_TOKEN_GENERATED,
|
||||||
}
|
}),
|
||||||
|
])
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -190,21 +193,25 @@ moduleIntegrationTestRunner<IUserModuleService>({
|
|||||||
describe("resendInvite", () => {
|
describe("resendInvite", () => {
|
||||||
it("should emit token generated event for invites", async () => {
|
it("should emit token generated event for invites", async () => {
|
||||||
await service.createInvites(defaultInviteData)
|
await service.createInvites(defaultInviteData)
|
||||||
|
|
||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
||||||
|
eventBusSpy.mockClear()
|
||||||
|
|
||||||
await service.refreshInviteTokens(["1"])
|
await service.refreshInviteTokens(["1"])
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(2)
|
const events = eventBusSpy.mock.calls[0][0]
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
expect(events).toHaveLength(2)
|
||||||
[
|
expect(events).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
name: UserEvents.INVITE_UPDATED,
|
||||||
data: { id: "1" },
|
data: { id: "1" },
|
||||||
name: UserEvents.INVITE_TOKEN_GENERATED,
|
|
||||||
}),
|
}),
|
||||||
],
|
expect.objectContaining({
|
||||||
{
|
name: UserEvents.INVITE_TOKEN_GENERATED,
|
||||||
internal: true,
|
data: { id: "1" },
|
||||||
}
|
}),
|
||||||
|
])
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -251,21 +258,25 @@ moduleIntegrationTestRunner<IUserModuleService>({
|
|||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
||||||
await service.createInvites(defaultInviteData)
|
await service.createInvites(defaultInviteData)
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
// 4 events: 2 invites created, 2 invite token generated
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
const events = eventBusSpy.mock.calls[0][0]
|
||||||
[
|
expect(events).toHaveLength(3)
|
||||||
|
|
||||||
|
expect(events).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: { id: ["1", "2"] },
|
data: { id: "1" },
|
||||||
|
name: UserEvents.INVITE_CREATED,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
data: { id: "2" },
|
||||||
name: UserEvents.INVITE_CREATED,
|
name: UserEvents.INVITE_CREATED,
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: { id: ["1", "2"] },
|
data: { id: ["1", "2"] },
|
||||||
name: UserEvents.INVITE_TOKEN_GENERATED,
|
name: UserEvents.INVITE_TOKEN_GENERATED,
|
||||||
}),
|
}),
|
||||||
],
|
])
|
||||||
{
|
|
||||||
internal: true,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -253,17 +253,22 @@ moduleIntegrationTestRunner<IUserModuleService>({
|
|||||||
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
const eventBusSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
||||||
await service.createUsers(defaultUserData)
|
await service.createUsers(defaultUserData)
|
||||||
|
|
||||||
expect(eventBusSpy).toHaveBeenCalledTimes(1)
|
// 2 events: 2 user created
|
||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
expect(eventBusSpy.mock.calls[0][0]).toHaveLength(2)
|
||||||
[
|
|
||||||
|
const events = eventBusSpy.mock.calls[0][0]
|
||||||
|
expect(events).toHaveLength(2)
|
||||||
|
expect(events).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: { id: ["1", "2"] },
|
data: { id: "1" },
|
||||||
name: UserEvents.USER_CREATED,
|
name: UserEvents.USER_CREATED,
|
||||||
}),
|
}),
|
||||||
],
|
expect.objectContaining({
|
||||||
{
|
data: { id: "2" },
|
||||||
internal: true,
|
name: UserEvents.USER_CREATED,
|
||||||
}
|
}),
|
||||||
|
])
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ export default class UserModuleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectManager()
|
||||||
async validateInviteToken(
|
async validateInviteToken(
|
||||||
token: string,
|
token: string,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -129,9 +129,7 @@ export default class UserModuleService
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<UserTypes.InviteDTO>(invite, {
|
return await this.baseRepository_.serialize<UserTypes.InviteDTO>(invite)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
@@ -142,22 +140,21 @@ export default class UserModuleService
|
|||||||
): Promise<UserTypes.InviteDTO[]> {
|
): Promise<UserTypes.InviteDTO[]> {
|
||||||
const invites = await this.refreshInviteTokens_(inviteIds, sharedContext)
|
const invites = await this.refreshInviteTokens_(inviteIds, sharedContext)
|
||||||
|
|
||||||
|
const serializedInvites = await this.baseRepository_.serialize<
|
||||||
|
UserTypes.InviteDTO[]
|
||||||
|
>(invites)
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
moduleEventBuilderFactory({
|
||||||
eventName: UserEvents.INVITE_TOKEN_GENERATED,
|
eventName: UserEvents.INVITE_TOKEN_GENERATED,
|
||||||
source: Modules.USER,
|
source: Modules.USER,
|
||||||
action: "token_generated",
|
action: CommonEvents.CREATED,
|
||||||
object: "invite",
|
object: "invite",
|
||||||
})({
|
})({
|
||||||
data: invites,
|
data: serializedInvites,
|
||||||
sharedContext,
|
sharedContext,
|
||||||
})
|
})
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<UserTypes.InviteDTO[]>(
|
return serializedInvites
|
||||||
invites,
|
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
@@ -221,19 +218,7 @@ export default class UserModuleService
|
|||||||
|
|
||||||
const serializedUsers = await this.baseRepository_.serialize<
|
const serializedUsers = await this.baseRepository_.serialize<
|
||||||
UserTypes.UserDTO[] | UserTypes.UserDTO
|
UserTypes.UserDTO[] | UserTypes.UserDTO
|
||||||
>(users, {
|
>(users)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
eventName: UserEvents.USER_CREATED,
|
|
||||||
source: Modules.USER,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "user",
|
|
||||||
})({
|
|
||||||
data: serializedUsers,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
|
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
|
||||||
}
|
}
|
||||||
@@ -262,19 +247,7 @@ export default class UserModuleService
|
|||||||
|
|
||||||
const serializedUsers = await this.baseRepository_.serialize<
|
const serializedUsers = await this.baseRepository_.serialize<
|
||||||
UserTypes.UserDTO[]
|
UserTypes.UserDTO[]
|
||||||
>(updatedUsers, {
|
>(updatedUsers)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
eventName: UserEvents.USER_UPDATED,
|
|
||||||
source: Modules.USER,
|
|
||||||
action: CommonEvents.UPDATED,
|
|
||||||
object: "user",
|
|
||||||
})({
|
|
||||||
data: serializedUsers,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
|
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
|
||||||
}
|
}
|
||||||
@@ -303,19 +276,7 @@ export default class UserModuleService
|
|||||||
|
|
||||||
const serializedInvites = await this.baseRepository_.serialize<
|
const serializedInvites = await this.baseRepository_.serialize<
|
||||||
UserTypes.InviteDTO[] | UserTypes.InviteDTO
|
UserTypes.InviteDTO[] | UserTypes.InviteDTO
|
||||||
>(invites, {
|
>(invites)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
|
||||||
eventName: UserEvents.INVITE_CREATED,
|
|
||||||
source: Modules.USER,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "invite",
|
|
||||||
})({
|
|
||||||
data: serializedInvites,
|
|
||||||
sharedContext,
|
|
||||||
})
|
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
moduleEventBuilderFactory({
|
||||||
eventName: UserEvents.INVITE_TOKEN_GENERATED,
|
eventName: UserEvents.INVITE_TOKEN_GENERATED,
|
||||||
@@ -390,14 +351,12 @@ export default class UserModuleService
|
|||||||
|
|
||||||
const serializedInvites = await this.baseRepository_.serialize<
|
const serializedInvites = await this.baseRepository_.serialize<
|
||||||
UserTypes.InviteDTO[]
|
UserTypes.InviteDTO[]
|
||||||
>(updatedInvites, {
|
>(updatedInvites)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
moduleEventBuilderFactory({
|
moduleEventBuilderFactory({
|
||||||
eventName: UserEvents.INVITE_UPDATED,
|
eventName: UserEvents.INVITE_TOKEN_GENERATED,
|
||||||
source: Modules.USER,
|
source: Modules.USER,
|
||||||
action: CommonEvents.UPDATED,
|
action: "token_generated",
|
||||||
object: "invite",
|
object: "invite",
|
||||||
})({
|
})({
|
||||||
data: serializedInvites,
|
data: serializedInvites,
|
||||||
|
|||||||
Reference in new issue
Block a user