feat: Event emitting part 1/N (Fulfillment) (#7391)
**What** Add support for event emitting in the fulfillment module **NOTE** It does not include the review of the events for the abstract module factory if the method is not implemented in the module itself and rely on the default implementation
This commit is contained in:
committed by
GitHub
parent
28d2a5347a
commit
9608bf06ef
@@ -60,11 +60,29 @@ export type UpdateStockLocationSalesChannelsReq = {
|
||||
}
|
||||
export type CreateFulfillmentSetReq = CreateFulfillmentSetDTO
|
||||
export type CreateServiceZoneReq = CreateServiceZoneDTO
|
||||
export type UpdateServiceZoneReq = UpdateServiceZoneDTO
|
||||
export type UpdateServiceZoneReq =
|
||||
| UpdateServiceZoneDTO
|
||||
|
||||
// Shipping Options
|
||||
export type CreateShippingOptionReq = CreateShippingOptionDTO
|
||||
export type UpdateShippingOptionReq = UpdateShippingOptionDTO
|
||||
// Shipping Options
|
||||
| { region_id: string; amount: number }
|
||||
export type CreateShippingOptionReq = CreateShippingOptionDTO & {
|
||||
/**
|
||||
* The shipping option pricing
|
||||
*/
|
||||
prices: (
|
||||
| { currency_code: string; amount: number }
|
||||
| { region_id: string; amount: number }
|
||||
)[]
|
||||
}
|
||||
export type UpdateShippingOptionReq = UpdateShippingOptionDTO & {
|
||||
/**
|
||||
* The shipping option pricing
|
||||
*/
|
||||
prices: (
|
||||
| { currency_code: string; amount: number; id?: string }
|
||||
| { region_id: string; amount: number; id?: string }
|
||||
)[]
|
||||
}
|
||||
|
||||
// Shipping Profile
|
||||
export type CreateShippingProfileReq = CreateShippingProfileDTO
|
||||
|
||||
@@ -14,7 +14,7 @@ export interface SuiteOptions<TService = unknown> {
|
||||
}
|
||||
}
|
||||
|
||||
export function moduleIntegrationTestRunner({
|
||||
export function moduleIntegrationTestRunner<TService = any>({
|
||||
moduleName,
|
||||
moduleModels,
|
||||
moduleOptions = {},
|
||||
@@ -34,7 +34,7 @@ export function moduleIntegrationTestRunner({
|
||||
injectedDependencies?: Record<string, any>
|
||||
resolve?: string
|
||||
debug?: boolean
|
||||
testSuite: <TService = unknown>(options: SuiteOptions<TService>) => void
|
||||
testSuite: (options: SuiteOptions<TService>) => void
|
||||
}) {
|
||||
const moduleSdkImports = require("@medusajs/modules-sdk")
|
||||
|
||||
@@ -111,7 +111,7 @@ export function moduleIntegrationTestRunner({
|
||||
schema,
|
||||
clientUrl: dbConfig.clientUrl,
|
||||
},
|
||||
} as SuiteOptions
|
||||
} as SuiteOptions<TService>
|
||||
|
||||
const beforeEach_ = async () => {
|
||||
await MikroOrmWrapper.setupDatabase()
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { Context } from "../shared-context"
|
||||
|
||||
export type Subscriber<T = unknown> = (
|
||||
data: T,
|
||||
eventName: string
|
||||
@@ -39,13 +41,12 @@ export type Message<T = unknown> = {
|
||||
options?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export type MessageFormat<T = unknown> = {
|
||||
export type RawMessageFormat<T = any> = {
|
||||
eventName: string
|
||||
metadata: {
|
||||
service: string
|
||||
action: string
|
||||
object: string
|
||||
eventGroupId?: string
|
||||
}
|
||||
data: T | T[]
|
||||
data: T
|
||||
service: string
|
||||
object: string
|
||||
action?: string
|
||||
context?: Pick<Context, "eventGroupId">
|
||||
options?: Record<string, any>
|
||||
}
|
||||
|
||||
@@ -110,5 +110,8 @@ export interface UpdateFulfillmentDTO {
|
||||
/**
|
||||
* The labels associated with the fulfillment.
|
||||
*/
|
||||
labels?: Omit<CreateFulfillmentLabelDTO, "fulfillment_id">[]
|
||||
labels?: (
|
||||
| Omit<CreateFulfillmentLabelDTO, "fulfillment_id">
|
||||
| { id: string }
|
||||
)[]
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@ import {
|
||||
CreateCountryGeoZoneDTO,
|
||||
CreateProvinceGeoZoneDTO,
|
||||
CreateZipGeoZoneDTO,
|
||||
UpdateCityGeoZoneDTO,
|
||||
UpdateCountryGeoZoneDTO,
|
||||
UpdateProvinceGeoZoneDTO,
|
||||
UpdateZipGeoZoneDTO,
|
||||
} from "./geo-zone"
|
||||
|
||||
/**
|
||||
@@ -52,6 +56,10 @@ export interface UpdateServiceZoneDTO {
|
||||
| Omit<CreateProvinceGeoZoneDTO, "service_zone_id">
|
||||
| Omit<CreateCityGeoZoneDTO, "service_zone_id">
|
||||
| Omit<CreateZipGeoZoneDTO, "service_zone_id">
|
||||
| UpdateCountryGeoZoneDTO
|
||||
| UpdateProvinceGeoZoneDTO
|
||||
| UpdateCityGeoZoneDTO
|
||||
| UpdateZipGeoZoneDTO
|
||||
| {
|
||||
/**
|
||||
* The ID of the geo zone.
|
||||
|
||||
@@ -46,14 +46,6 @@ export interface CreateShippingOptionDTO {
|
||||
* The shipping option rules associated with the shipping option.
|
||||
*/
|
||||
rules?: Omit<CreateShippingOptionRuleDTO, "shipping_option_id">[]
|
||||
|
||||
/**
|
||||
* The shipping option pricing
|
||||
*/
|
||||
prices: (
|
||||
| { currency_code: string; amount: number }
|
||||
| { region_id: string; amount: number }
|
||||
)[]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,14 +112,6 @@ export interface UpdateShippingOptionDTO {
|
||||
id: string
|
||||
}
|
||||
)[]
|
||||
|
||||
/**
|
||||
* The shipping option pricing
|
||||
*/
|
||||
prices: (
|
||||
| { currency_code: string; amount: number; id?: string }
|
||||
| { region_id: string; amount: number; id?: string }
|
||||
)[]
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,8 +30,8 @@ export interface IMessageAggregator {
|
||||
clearMessages(): void
|
||||
saveRawMessageData<T>(
|
||||
messageData:
|
||||
| EventBusTypes.MessageFormat<T>
|
||||
| EventBusTypes.MessageFormat<T>[],
|
||||
| EventBusTypes.RawMessageFormat<T>
|
||||
| EventBusTypes.RawMessageFormat<T>[],
|
||||
options?: Record<string, unknown>
|
||||
): void
|
||||
}
|
||||
|
||||
@@ -1,39 +1,4 @@
|
||||
import { Context, EventBusTypes } from "@medusajs/types"
|
||||
import { CommonEvents } from "./common-events"
|
||||
|
||||
/**
|
||||
* Build messages from message data to be consumed by the event bus and emitted to the consumer
|
||||
* @param MessageFormat
|
||||
* @param options
|
||||
*/
|
||||
export function buildEventMessages<T>(
|
||||
messageData:
|
||||
| EventBusTypes.MessageFormat<T>
|
||||
| EventBusTypes.MessageFormat<T>[],
|
||||
options?: Record<string, unknown>
|
||||
): EventBusTypes.Message<T>[] {
|
||||
const messageData_ = Array.isArray(messageData) ? messageData : [messageData]
|
||||
const messages: EventBusTypes.Message<any>[] = []
|
||||
|
||||
messageData_.map((data) => {
|
||||
const data_ = Array.isArray(data.data) ? data.data : [data.data]
|
||||
data_.forEach((bodyData) => {
|
||||
const message = composeMessage(data.eventName, {
|
||||
data: bodyData,
|
||||
service: data.metadata.service,
|
||||
entity: data.metadata.object,
|
||||
action: data.metadata.action,
|
||||
context: {
|
||||
eventGroupId: data.metadata.eventGroupId,
|
||||
} as Context,
|
||||
options,
|
||||
})
|
||||
messages.push(message)
|
||||
})
|
||||
})
|
||||
|
||||
return messages
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to compose and normalize a Message to be emitted by EventBus Module
|
||||
@@ -48,27 +13,29 @@ export function composeMessage(
|
||||
{
|
||||
data,
|
||||
service,
|
||||
entity,
|
||||
object,
|
||||
action,
|
||||
context = {},
|
||||
options,
|
||||
}: {
|
||||
data: unknown
|
||||
data: any
|
||||
service: string
|
||||
entity: string
|
||||
object: string
|
||||
action?: string
|
||||
context?: Context
|
||||
options?: Record<string, unknown>
|
||||
options?: Record<string, any>
|
||||
}
|
||||
): EventBusTypes.Message {
|
||||
const act = action || eventName.split(".").pop()
|
||||
if (!action && !Object.values(CommonEvents).includes(act as CommonEvents)) {
|
||||
if (
|
||||
!action /* && !Object.values(CommonEvents).includes(act as CommonEvents)*/
|
||||
) {
|
||||
throw new Error("Action is required if eventName is not a CommonEvent")
|
||||
}
|
||||
|
||||
const metadata: EventBusTypes.MessageBody["metadata"] = {
|
||||
service,
|
||||
object: entity,
|
||||
object,
|
||||
action: act!,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {
|
||||
Context,
|
||||
EventBusTypes,
|
||||
IMessageAggregator,
|
||||
Message,
|
||||
MessageAggregatorFormat,
|
||||
} from "@medusajs/types"
|
||||
|
||||
import { buildEventMessages } from "./build-event-messages"
|
||||
import { composeMessage } from "./build-event-messages"
|
||||
|
||||
export class MessageAggregator implements IMessageAggregator {
|
||||
private messages: Message[]
|
||||
@@ -28,11 +29,25 @@ export class MessageAggregator implements IMessageAggregator {
|
||||
|
||||
saveRawMessageData<T>(
|
||||
messageData:
|
||||
| EventBusTypes.MessageFormat<T>
|
||||
| EventBusTypes.MessageFormat<T>[],
|
||||
options?: Record<string, unknown>
|
||||
| EventBusTypes.RawMessageFormat<T>
|
||||
| EventBusTypes.RawMessageFormat<T>[],
|
||||
{
|
||||
options,
|
||||
sharedContext,
|
||||
}: { options?: Record<string, unknown>; sharedContext?: Context } = {}
|
||||
): void {
|
||||
this.save(buildEventMessages(messageData, options))
|
||||
const messages = Array.isArray(messageData) ? messageData : [messageData]
|
||||
const composedMessages = messages.map((message) => {
|
||||
return composeMessage(message.eventName, {
|
||||
data: message.data,
|
||||
service: message.service,
|
||||
object: message.object,
|
||||
action: message.action,
|
||||
options,
|
||||
context: sharedContext,
|
||||
})
|
||||
})
|
||||
this.save(composedMessages)
|
||||
}
|
||||
|
||||
getMessages(format?: MessageAggregatorFormat): {
|
||||
|
||||
@@ -58,7 +58,8 @@ type ReturnType<TNames extends string[]> = TNames extends [
|
||||
* @param names
|
||||
*/
|
||||
export function buildEventNamesFromEntityName<TNames extends string[]>(
|
||||
names: TNames
|
||||
names: TNames,
|
||||
prefix?: string
|
||||
): ReturnType<TNames> {
|
||||
const events = {}
|
||||
|
||||
@@ -69,16 +70,15 @@ export function buildEventNamesFromEntityName<TNames extends string[]>(
|
||||
|
||||
if (i === 0) {
|
||||
for (const event of Object.values(CommonEvents) as string[]) {
|
||||
events[event] = `${kebabCaseName}.${event}`
|
||||
events[event] = `${prefix ? prefix + "." : ""}${kebabCaseName}.${event}`
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
for (const event of Object.values(CommonEvents) as string[]) {
|
||||
events[`${snakedCaseName}_${event}`] =
|
||||
`${kebabCaseName}.${event}` as `${KebabCase<
|
||||
typeof name
|
||||
>}.${typeof event}`
|
||||
events[`${snakedCaseName}_${event}`] = `${
|
||||
prefix ? prefix + "." : ""
|
||||
}${kebabCaseName}.${event}` as `${KebabCase<typeof name>}.${typeof event}`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,33 @@
|
||||
import { buildEventNamesFromEntityName } from "../event-bus"
|
||||
import { Modules } from "../modules-sdk"
|
||||
|
||||
const eventBaseNames: [
|
||||
"fulfillmentSet",
|
||||
"serviceZone",
|
||||
"geoZone",
|
||||
"shippingOption",
|
||||
"shippingOptionType",
|
||||
"shippingProfile",
|
||||
"shippingOptionRule",
|
||||
"fulfillment"
|
||||
"fulfillment",
|
||||
"fulfillmentAddress",
|
||||
"fulfillmentItem",
|
||||
"fulfillmentLabel"
|
||||
] = [
|
||||
"fulfillmentSet",
|
||||
"serviceZone",
|
||||
"geoZone",
|
||||
"shippingOption",
|
||||
"shippingOptionType",
|
||||
"shippingProfile",
|
||||
"shippingOptionRule",
|
||||
"fulfillment",
|
||||
"fulfillmentAddress",
|
||||
"fulfillmentItem",
|
||||
"fulfillmentLabel",
|
||||
]
|
||||
|
||||
export const FulfillmentEvents = buildEventNamesFromEntityName(eventBaseNames)
|
||||
export const FulfillmentEvents = buildEventNamesFromEntityName(
|
||||
eventBaseNames,
|
||||
Modules.FULFILLMENT
|
||||
)
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { CommonEvents } from "../event-bus"
|
||||
import { buildEventNamesFromEntityName } from "../event-bus"
|
||||
import { Modules } from "../modules-sdk"
|
||||
|
||||
export const InventoryEvents = {
|
||||
created: "inventory-item." + CommonEvents.CREATED,
|
||||
updated: "inventory-item." + CommonEvents.UPDATED,
|
||||
deleted: "inventory-item." + CommonEvents.DELETED,
|
||||
restored: "inventory-item." + CommonEvents.RESTORED,
|
||||
reservation_item_created: "reservation-item." + CommonEvents.CREATED,
|
||||
reservation_item_updated: "reservation-item." + CommonEvents.UPDATED,
|
||||
reservation_item_deleted: "reservation-item." + CommonEvents.DELETED,
|
||||
inventory_level_deleted: "inventory-level." + CommonEvents.DELETED,
|
||||
inventory_level_created: "inventory-level." + CommonEvents.CREATED,
|
||||
inventory_level_updated: "inventory-level." + CommonEvents.UPDATED,
|
||||
}
|
||||
const eventBaseNames: ["inventoryItem", "reservationItem", "inventoryLevel"] = [
|
||||
"inventoryItem",
|
||||
"reservationItem",
|
||||
"inventoryLevel",
|
||||
]
|
||||
|
||||
export const InventoryEvents = buildEventNamesFromEntityName(
|
||||
eventBaseNames,
|
||||
Modules.INVENTORY
|
||||
)
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { MessageAggregator } from "../../event-bus"
|
||||
import { InjectIntoContext } from "./inject-into-context"
|
||||
import {MessageAggregatorFormat} from "@medusajs/types";
|
||||
import { MessageAggregatorFormat } from "@medusajs/types"
|
||||
|
||||
export function EmitEvents(options: MessageAggregatorFormat = {} as MessageAggregatorFormat) {
|
||||
export function EmitEvents(
|
||||
options: MessageAggregatorFormat = {} as MessageAggregatorFormat
|
||||
) {
|
||||
return function (
|
||||
target: any,
|
||||
propertyKey: string | symbol,
|
||||
descriptor: any
|
||||
): void {
|
||||
const aggregator = new MessageAggregator()
|
||||
InjectIntoContext({
|
||||
messageAggregator: () => aggregator,
|
||||
messageAggregator: () => new MessageAggregator(),
|
||||
})(target, propertyKey, descriptor)
|
||||
|
||||
const original = descriptor.value
|
||||
@@ -18,6 +19,17 @@ export function EmitEvents(options: MessageAggregatorFormat = {} as MessageAggre
|
||||
descriptor.value = async function (...args: any[]) {
|
||||
const result = await original.apply(this, args)
|
||||
|
||||
if (!target.emitEvents_) {
|
||||
const logger = Object.keys(this.__container__ ?? {}).includes("logger")
|
||||
? this.__container__.logger
|
||||
: console
|
||||
logger.warn(
|
||||
`No emitEvents_ method found on ${target.constructor.name}. No events emitted. To be able to use the @EmitEvents() you need to have the emitEvents_ method implemented in the class.`
|
||||
)
|
||||
}
|
||||
|
||||
const argIndex = target.MedusaContextIndex_[propertyKey]
|
||||
const aggregator = args[argIndex].messageAggregator as MessageAggregator
|
||||
await target.emitEvents_.apply(this, [aggregator.getMessages(options)])
|
||||
|
||||
aggregator.clearMessages()
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { MessageAggregator } from "../../event-bus"
|
||||
|
||||
export function InjectIntoContext(
|
||||
properties: Record<string, unknown | Function>
|
||||
): MethodDecorator {
|
||||
|
||||
67
packages/core/utils/src/modules-sdk/event-builder-factory.ts
Normal file
67
packages/core/utils/src/modules-sdk/event-builder-factory.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { Context, EventBusTypes } from "@medusajs/types"
|
||||
|
||||
/**
|
||||
* Factory function to create event builders for different entities
|
||||
*
|
||||
* @example
|
||||
* const createdFulfillment = eventBuilderFactory({
|
||||
* service: Modules.FULFILLMENT,
|
||||
* action: CommonEvents.CREATED,
|
||||
* object: "fulfillment",
|
||||
* eventsEnum: FulfillmentEvents,
|
||||
* })
|
||||
*
|
||||
* createdFulfillment({
|
||||
* data,
|
||||
* sharedContext,
|
||||
* })
|
||||
*
|
||||
* @param isMainEntity
|
||||
* @param action
|
||||
* @param object
|
||||
* @param eventsEnum
|
||||
* @param service
|
||||
*/
|
||||
export function eventBuilderFactory({
|
||||
isMainEntity,
|
||||
action,
|
||||
object,
|
||||
eventsEnum,
|
||||
service,
|
||||
}: {
|
||||
isMainEntity?: boolean
|
||||
action: string
|
||||
object: string
|
||||
eventsEnum: Record<string, string>
|
||||
service: string
|
||||
}) {
|
||||
return function ({
|
||||
data,
|
||||
sharedContext,
|
||||
}: {
|
||||
data: { id: string }[]
|
||||
sharedContext: Context
|
||||
}) {
|
||||
if (!data.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const aggregator = sharedContext.messageAggregator!
|
||||
const messages: EventBusTypes.RawMessageFormat[] = []
|
||||
|
||||
data.forEach((dataItem) => {
|
||||
messages.push({
|
||||
service,
|
||||
action,
|
||||
context: sharedContext,
|
||||
data: { id: dataItem.id },
|
||||
eventName: isMainEntity
|
||||
? eventsEnum[action]
|
||||
: eventsEnum[`${object}_${action}`],
|
||||
object,
|
||||
})
|
||||
})
|
||||
|
||||
aggregator.saveRawMessageData(messages)
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,4 @@ export * from "./migration-scripts"
|
||||
export * from "./internal-module-service-factory"
|
||||
export * from "./abstract-module-service-factory"
|
||||
export * from "./definition"
|
||||
export * from "./event-builder-factory"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { CommonEvents } from "../event-bus"
|
||||
import { buildEventNamesFromEntityName } from "../event-bus"
|
||||
import { Modules } from "../modules-sdk"
|
||||
|
||||
const eventBaseNames: ["user", "invite"] = ["user", "invite"]
|
||||
|
||||
export const UserEvents = {
|
||||
created: "user." + CommonEvents.CREATED,
|
||||
updated: "user." + CommonEvents.UPDATED,
|
||||
invite_created: "invite." + CommonEvents.CREATED,
|
||||
invite_updated: "invite." + CommonEvents.UPDATED,
|
||||
invite_token_generated: "invite.token_generated",
|
||||
...buildEventNamesFromEntityName(eventBaseNames, Modules.USER),
|
||||
invite_token_generated: `${Modules.USER}.user.invite.token_generated`,
|
||||
}
|
||||
|
||||
@@ -7,15 +7,15 @@ import {
|
||||
UpdateFulfillmentSetDTO,
|
||||
} from "@medusajs/types"
|
||||
import { FulfillmentEvents, GeoZoneType } from "@medusajs/utils"
|
||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
||||
import { moduleIntegrationTestRunner } from "medusa-test-utils"
|
||||
import { MockEventBusService } from "medusa-test-utils/dist"
|
||||
import { buildExpectedEventMessageShape } from "../../__fixtures__"
|
||||
|
||||
jest.setTimeout(100000)
|
||||
|
||||
moduleIntegrationTestRunner({
|
||||
moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
|
||||
testSuite: ({ service }) => {
|
||||
let eventBusEmitSpy
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -625,6 +625,15 @@ moduleIntegrationTestRunner({
|
||||
type: updateData.type,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.updated,
|
||||
action: "updated",
|
||||
object: "fulfillment_set",
|
||||
data: { id: updatedFulfillmentSets.id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should update a collection of fulfillment sets", async function () {
|
||||
@@ -655,6 +664,7 @@ moduleIntegrationTestRunner({
|
||||
})
|
||||
|
||||
expect(updatedFulfillmentSets).toHaveLength(2)
|
||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(2)
|
||||
|
||||
for (const data_ of updateData) {
|
||||
const currentFullfillmentSet = fullfillmentSets.find(
|
||||
@@ -668,6 +678,17 @@ moduleIntegrationTestRunner({
|
||||
type: data_.type,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.updated,
|
||||
action: "updated",
|
||||
object: "fulfillment_set",
|
||||
data: { id: currentFullfillmentSet.id },
|
||||
}),
|
||||
])
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -742,6 +763,46 @@ moduleIntegrationTestRunner({
|
||||
id: updatedFulfillmentSet.service_zones[0].id,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(5)
|
||||
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.updated,
|
||||
action: "updated",
|
||||
object: "fulfillment_set",
|
||||
data: { id: updatedFulfillmentSet.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.service_zone_created,
|
||||
action: "created",
|
||||
object: "service_zone",
|
||||
data: { id: updatedFulfillmentSet.service_zones[0].id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_created,
|
||||
action: "created",
|
||||
object: "geo_zone",
|
||||
data: {
|
||||
id: updatedFulfillmentSet.service_zones[0].geo_zones[0].id,
|
||||
},
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.service_zone_deleted,
|
||||
action: "deleted",
|
||||
object: "service_zone",
|
||||
data: { id: createdFulfillmentSet.service_zones[0].id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_deleted,
|
||||
action: "deleted",
|
||||
object: "geo_zone",
|
||||
data: {
|
||||
id: createdFulfillmentSet.service_zones[0].geo_zones[0].id,
|
||||
},
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should update an existing fulfillment set and add a new service zone", async function () {
|
||||
@@ -812,6 +873,36 @@ moduleIntegrationTestRunner({
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
const createdServiceZone = updatedFulfillmentSet.service_zones.find(
|
||||
(s) => s.name === "service-zone-test2"
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(3)
|
||||
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.updated,
|
||||
action: "updated",
|
||||
object: "fulfillment_set",
|
||||
data: { id: updatedFulfillmentSet.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.service_zone_created,
|
||||
action: "created",
|
||||
object: "service_zone",
|
||||
data: { id: createdServiceZone.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_created,
|
||||
action: "created",
|
||||
object: "geo_zone",
|
||||
data: {
|
||||
id: createdServiceZone.geo_zones[0].id,
|
||||
},
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should fail on duplicated fulfillment set name", async function () {
|
||||
@@ -897,11 +988,16 @@ moduleIntegrationTestRunner({
|
||||
const updatedFulfillmentSets = await service.update(updateData)
|
||||
|
||||
expect(updatedFulfillmentSets).toHaveLength(2)
|
||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(10)
|
||||
|
||||
for (const data_ of updateData) {
|
||||
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
||||
(f) => f.id === data_.id
|
||||
)
|
||||
const originalFulfillmentSet = createdFulfillmentSets.find(
|
||||
(f) => f.id === data_.id
|
||||
)
|
||||
|
||||
expect(expectedFulfillmentSet).toEqual(
|
||||
expect.objectContaining({
|
||||
id: data_.id,
|
||||
@@ -925,6 +1021,47 @@ moduleIntegrationTestRunner({
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.updated,
|
||||
action: "updated",
|
||||
object: "fulfillment_set",
|
||||
data: { id: expectedFulfillmentSet.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.service_zone_created,
|
||||
action: "created",
|
||||
object: "service_zone",
|
||||
data: { id: expectedFulfillmentSet.service_zones[0].id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_created,
|
||||
action: "created",
|
||||
object: "geo_zone",
|
||||
data: {
|
||||
id: expectedFulfillmentSet.service_zones[0].geo_zones[0]
|
||||
.id,
|
||||
},
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.service_zone_deleted,
|
||||
action: "deleted",
|
||||
object: "service_zone",
|
||||
data: { id: originalFulfillmentSet.service_zones[0].id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_deleted,
|
||||
action: "deleted",
|
||||
object: "geo_zone",
|
||||
data: {
|
||||
id: originalFulfillmentSet.service_zones[0].geo_zones[0]
|
||||
.id,
|
||||
},
|
||||
}),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
const serviceZones = await service.listServiceZones()
|
||||
@@ -1002,6 +1139,7 @@ moduleIntegrationTestRunner({
|
||||
const updatedFulfillmentSets = await service.update(updateData)
|
||||
|
||||
expect(updatedFulfillmentSets).toHaveLength(2)
|
||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(6)
|
||||
|
||||
for (const data_ of updateData) {
|
||||
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
||||
@@ -1033,6 +1171,36 @@ moduleIntegrationTestRunner({
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
const createdServiceZone =
|
||||
expectedFulfillmentSet.service_zones.find((s) =>
|
||||
s.name.includes(`added-service-zone-test`)
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenLastCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.updated,
|
||||
action: "updated",
|
||||
object: "fulfillment_set",
|
||||
data: { id: expectedFulfillmentSet.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.service_zone_created,
|
||||
action: "created",
|
||||
object: "service_zone",
|
||||
data: { id: createdServiceZone.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_created,
|
||||
action: "created",
|
||||
object: "geo_zone",
|
||||
data: {
|
||||
id: createdServiceZone.geo_zones[0].id,
|
||||
},
|
||||
}),
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
const serviceZones = await service.listServiceZones()
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
import { resolve } from "path"
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import { IFulfillmentModuleService } from "@medusajs/types"
|
||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
||||
import {
|
||||
IFulfillmentModuleService,
|
||||
UpdateFulfillmentDTO,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
MockEventBusService,
|
||||
moduleIntegrationTestRunner,
|
||||
} from "medusa-test-utils"
|
||||
import {
|
||||
buildExpectedEventMessageShape,
|
||||
generateCreateFulfillmentData,
|
||||
generateCreateShippingOptionsData,
|
||||
} from "../../__fixtures__"
|
||||
import { FulfillmentEvents } from "@medusajs/utils"
|
||||
|
||||
jest.setTimeout(100000)
|
||||
|
||||
@@ -27,10 +35,20 @@ const moduleOptions = {
|
||||
|
||||
const providerId = "fixtures-fulfillment-provider_test-provider"
|
||||
|
||||
moduleIntegrationTestRunner({
|
||||
moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
moduleOptions: moduleOptions,
|
||||
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
|
||||
testSuite: ({ service }) => {
|
||||
let eventBusEmitSpy
|
||||
|
||||
beforeEach(() => {
|
||||
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe("Fulfillment Module Service", () => {
|
||||
describe("read", () => {
|
||||
it("should list fulfillment", async () => {
|
||||
@@ -103,6 +121,8 @@ moduleIntegrationTestRunner({
|
||||
})
|
||||
)
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const fulfillment = await service.createFulfillment(
|
||||
generateCreateFulfillmentData({
|
||||
provider_id: providerId,
|
||||
@@ -136,6 +156,34 @@ moduleIntegrationTestRunner({
|
||||
],
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_created,
|
||||
action: "created",
|
||||
object: "fulfillment",
|
||||
data: { id: fulfillment.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_address_created,
|
||||
action: "created",
|
||||
object: "fulfillment_address",
|
||||
data: { id: fulfillment.delivery_address.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_item_created,
|
||||
action: "created",
|
||||
object: "fulfillment_item",
|
||||
data: { id: fulfillment.items[0].id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_label_created,
|
||||
action: "created",
|
||||
object: "fulfillment_label",
|
||||
data: { id: fulfillment.labels[0].id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should create a return fulfillment", async () => {
|
||||
@@ -160,6 +208,8 @@ moduleIntegrationTestRunner({
|
||||
})
|
||||
)
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const fulfillment = await service.createReturnFulfillment(
|
||||
generateCreateFulfillmentData({
|
||||
provider_id: providerId,
|
||||
@@ -193,6 +243,169 @@ moduleIntegrationTestRunner({
|
||||
],
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_created,
|
||||
action: "created",
|
||||
object: "fulfillment",
|
||||
data: { id: fulfillment.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_address_created,
|
||||
action: "created",
|
||||
object: "fulfillment_address",
|
||||
data: { id: fulfillment.delivery_address.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_item_created,
|
||||
action: "created",
|
||||
object: "fulfillment_item",
|
||||
data: { id: fulfillment.items[0].id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_label_created,
|
||||
action: "created",
|
||||
object: "fulfillment_label",
|
||||
data: { id: fulfillment.labels[0].id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("on update", () => {
|
||||
it("should update a fulfillment", async () => {
|
||||
const shippingProfile = await service.createShippingProfiles({
|
||||
name: "test",
|
||||
type: "default",
|
||||
})
|
||||
const fulfillmentSet = await service.create({
|
||||
name: "test",
|
||||
type: "test-type",
|
||||
})
|
||||
const serviceZone = await service.createServiceZones({
|
||||
name: "test",
|
||||
fulfillment_set_id: fulfillmentSet.id,
|
||||
})
|
||||
|
||||
const shippingOption = await service.createShippingOptions(
|
||||
generateCreateShippingOptionsData({
|
||||
provider_id: providerId,
|
||||
service_zone_id: serviceZone.id,
|
||||
shipping_profile_id: shippingProfile.id,
|
||||
})
|
||||
)
|
||||
|
||||
const fulfillment = await service.createFulfillment(
|
||||
generateCreateFulfillmentData({
|
||||
provider_id: providerId,
|
||||
shipping_option_id: shippingOption.id,
|
||||
labels: [
|
||||
{
|
||||
tracking_number: "test-tracking-number-1",
|
||||
tracking_url: "test-tracking-url-1",
|
||||
label_url: "test-label-url-1",
|
||||
},
|
||||
{
|
||||
tracking_number: "test-tracking-number-2",
|
||||
tracking_url: "test-tracking-url-2",
|
||||
label_url: "test-label-url-2",
|
||||
},
|
||||
{
|
||||
tracking_number: "test-tracking-number-3",
|
||||
tracking_url: "test-tracking-url-3",
|
||||
label_url: "test-label-url-3",
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
|
||||
const label1 = fulfillment.labels.find(
|
||||
(l) => l.tracking_number === "test-tracking-number-1"
|
||||
)!
|
||||
const label2 = fulfillment.labels.find(
|
||||
(l) => l.tracking_number === "test-tracking-number-2"
|
||||
)!
|
||||
const label3 = fulfillment.labels.find(
|
||||
(l) => l.tracking_number === "test-tracking-number-3"
|
||||
)!
|
||||
|
||||
const updateData: UpdateFulfillmentDTO = {
|
||||
id: fulfillment.id,
|
||||
labels: [
|
||||
{ id: label1.id },
|
||||
{ ...label2, label_url: "updated-test-label-url-2" },
|
||||
{
|
||||
tracking_number: "test-tracking-number-4",
|
||||
tracking_url: "test-tracking-url-4",
|
||||
label_url: "test-label-url-4",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const updatedFulfillment = await service.updateFulfillment(
|
||||
fulfillment.id,
|
||||
updateData
|
||||
)
|
||||
|
||||
const label4 = updatedFulfillment.labels.find(
|
||||
(l) => l.tracking_number === "test-tracking-number-4"
|
||||
)!
|
||||
|
||||
expect(updatedFulfillment.labels).toHaveLength(3)
|
||||
expect(updatedFulfillment).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
labels: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
tracking_number: "test-tracking-number-1",
|
||||
tracking_url: "test-tracking-url-1",
|
||||
label_url: "test-label-url-1",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
tracking_number: "test-tracking-number-2",
|
||||
tracking_url: "test-tracking-url-2",
|
||||
label_url: "updated-test-label-url-2",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
tracking_number: "test-tracking-number-4",
|
||||
tracking_url: "test-tracking-url-4",
|
||||
label_url: "test-label-url-4",
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_updated,
|
||||
action: "updated",
|
||||
object: "fulfillment",
|
||||
data: { id: updatedFulfillment.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_label_deleted,
|
||||
action: "deleted",
|
||||
object: "fulfillment_label",
|
||||
data: { id: label3.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_label_updated,
|
||||
action: "updated",
|
||||
object: "fulfillment_label",
|
||||
data: { id: label2.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_label_created,
|
||||
action: "created",
|
||||
object: "fulfillment_label",
|
||||
data: { id: label4.id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -227,6 +440,8 @@ moduleIntegrationTestRunner({
|
||||
shipping_option_id: shippingOption.id,
|
||||
})
|
||||
)
|
||||
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("should cancel a fulfillment successfully", async () => {
|
||||
@@ -239,6 +454,16 @@ moduleIntegrationTestRunner({
|
||||
expect(result.canceled_at).not.toBeNull()
|
||||
expect(idempotentResult.canceled_at).not.toBeNull()
|
||||
expect(idempotentResult.canceled_at).toEqual(result.canceled_at)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
||||
expect(eventBusEmitSpy).toHaveBeenNthCalledWith(1, [
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.fulfillment_updated,
|
||||
action: "updated",
|
||||
object: "fulfillment",
|
||||
data: { id: fulfillment.id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should fail to cancel a fulfillment that is already shipped", async () => {
|
||||
|
||||
@@ -4,14 +4,28 @@ import {
|
||||
IFulfillmentModuleService,
|
||||
UpdateGeoZoneDTO,
|
||||
} from "@medusajs/types"
|
||||
import { GeoZoneType } from "@medusajs/utils"
|
||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
||||
import { FulfillmentEvents, GeoZoneType } from "@medusajs/utils"
|
||||
import {
|
||||
MockEventBusService,
|
||||
moduleIntegrationTestRunner,
|
||||
} from "medusa-test-utils"
|
||||
import { buildExpectedEventMessageShape } from "../../__fixtures__"
|
||||
|
||||
jest.setTimeout(100000)
|
||||
|
||||
moduleIntegrationTestRunner({
|
||||
moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
|
||||
testSuite: ({ service }) => {
|
||||
let eventBusEmitSpy
|
||||
|
||||
beforeEach(() => {
|
||||
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe("Fulfillment Module Service", () => {
|
||||
describe("read", () => {
|
||||
it("should list geo zones with a filter", async function () {
|
||||
@@ -81,6 +95,8 @@ moduleIntegrationTestRunner({
|
||||
country_code: "fr",
|
||||
}
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const geoZone = await service.createGeoZones(data)
|
||||
|
||||
expect(geoZone).toEqual(
|
||||
@@ -90,6 +106,16 @@ moduleIntegrationTestRunner({
|
||||
country_code: data.country_code,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_created,
|
||||
action: "created",
|
||||
object: "geo_zone",
|
||||
data: { id: geoZone.id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should create a collection of geo zones", async function () {
|
||||
@@ -115,9 +141,12 @@ moduleIntegrationTestRunner({
|
||||
},
|
||||
]
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const geoZones = await service.createGeoZones(data)
|
||||
|
||||
expect(geoZones).toHaveLength(2)
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
||||
|
||||
let i = 0
|
||||
for (const data_ of data) {
|
||||
@@ -128,6 +157,18 @@ moduleIntegrationTestRunner({
|
||||
country_code: data_.country_code,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_created,
|
||||
action: "created",
|
||||
object: "geo_zone",
|
||||
data: { id: geoZones[i].id },
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
++i
|
||||
}
|
||||
})
|
||||
@@ -213,6 +254,8 @@ moduleIntegrationTestRunner({
|
||||
country_code: "us",
|
||||
}
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const updatedGeoZone = await service.updateGeoZones(updateData)
|
||||
|
||||
expect(updatedGeoZone).toEqual(
|
||||
@@ -222,6 +265,15 @@ moduleIntegrationTestRunner({
|
||||
country_code: updateData.country_code,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_updated,
|
||||
action: "updated",
|
||||
object: "geo_zone",
|
||||
data: { id: updatedGeoZone.id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should update a collection of geo zones", async function () {
|
||||
@@ -258,14 +310,18 @@ moduleIntegrationTestRunner({
|
||||
})
|
||||
)
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const updatedGeoZones = await service.updateGeoZones(updateData)
|
||||
|
||||
expect(updatedGeoZones).toHaveLength(2)
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
||||
|
||||
for (const data_ of updateData) {
|
||||
const expectedGeoZone = updatedGeoZones.find(
|
||||
(geoZone) => geoZone.id === data_.id
|
||||
)
|
||||
)!
|
||||
|
||||
expect(expectedGeoZone).toEqual(
|
||||
expect.objectContaining({
|
||||
id: data_.id,
|
||||
@@ -273,6 +329,17 @@ moduleIntegrationTestRunner({
|
||||
country_code: data_.country_code,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_updated,
|
||||
action: "updated",
|
||||
object: "geo_zone",
|
||||
data: { id: expectedGeoZone.id },
|
||||
}),
|
||||
])
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -5,14 +5,28 @@ import {
|
||||
IFulfillmentModuleService,
|
||||
UpdateServiceZoneDTO,
|
||||
} from "@medusajs/types"
|
||||
import { GeoZoneType } from "@medusajs/utils"
|
||||
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
|
||||
import { FulfillmentEvents, GeoZoneType } from "@medusajs/utils"
|
||||
import {
|
||||
MockEventBusService,
|
||||
moduleIntegrationTestRunner,
|
||||
} from "medusa-test-utils"
|
||||
import { buildExpectedEventMessageShape } from "../../__fixtures__"
|
||||
|
||||
jest.setTimeout(100000)
|
||||
|
||||
moduleIntegrationTestRunner({
|
||||
moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
|
||||
testSuite: ({ service }) => {
|
||||
let eventBusEmitSpy
|
||||
|
||||
beforeEach(() => {
|
||||
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe("Fulfillment Module Service", () => {
|
||||
describe("read", () => {
|
||||
it("should list service zones with a filter", async function () {
|
||||
@@ -276,6 +290,14 @@ moduleIntegrationTestRunner({
|
||||
type: GeoZoneType.COUNTRY,
|
||||
country_code: "fr",
|
||||
},
|
||||
{
|
||||
type: GeoZoneType.COUNTRY,
|
||||
country_code: "us",
|
||||
},
|
||||
{
|
||||
type: GeoZoneType.COUNTRY,
|
||||
country_code: "uk",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -283,35 +305,94 @@ moduleIntegrationTestRunner({
|
||||
createData
|
||||
)
|
||||
|
||||
const updateData = {
|
||||
const usGeoZone = createdServiceZone.geo_zones.find(
|
||||
(geoZone) => geoZone.country_code === "us"
|
||||
)!
|
||||
const frGeoZone = createdServiceZone.geo_zones.find(
|
||||
(geoZone) => geoZone.country_code === "fr"
|
||||
)!
|
||||
const ukGeoZone = createdServiceZone.geo_zones.find(
|
||||
(geoZone) => geoZone.country_code === "uk"
|
||||
)!
|
||||
|
||||
const updateData: UpdateServiceZoneDTO = {
|
||||
name: "updated-service-zone-test",
|
||||
geo_zones: [
|
||||
{
|
||||
id: createdServiceZone.geo_zones[0].id,
|
||||
id: usGeoZone.id,
|
||||
type: GeoZoneType.COUNTRY,
|
||||
country_code: "us",
|
||||
country_code: "es",
|
||||
},
|
||||
{
|
||||
type: GeoZoneType.COUNTRY,
|
||||
country_code: "ch",
|
||||
},
|
||||
{ id: frGeoZone.id },
|
||||
],
|
||||
}
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const updatedServiceZone = await service.updateServiceZones(
|
||||
createdServiceZone.id,
|
||||
updateData
|
||||
)
|
||||
|
||||
expect(updatedServiceZone.geo_zones).toHaveLength(3)
|
||||
|
||||
expect(updatedServiceZone).toEqual(
|
||||
expect.objectContaining({
|
||||
id: createdServiceZone.id,
|
||||
name: updateData.name,
|
||||
geo_zones: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: updateData.geo_zones[0].id,
|
||||
type: updateData.geo_zones[0].type,
|
||||
country_code: updateData.geo_zones[0].country_code,
|
||||
id: frGeoZone.id,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: usGeoZone.id,
|
||||
type: GeoZoneType.COUNTRY,
|
||||
country_code: "es",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
type: GeoZoneType.COUNTRY,
|
||||
country_code: "ch",
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
const chGeoZone = updatedServiceZone.geo_zones.find(
|
||||
(geoZone) => geoZone.country_code === "ch"
|
||||
)!
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(4)
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_deleted,
|
||||
action: "deleted",
|
||||
object: "geo_zone",
|
||||
data: { id: ukGeoZone.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.service_zone_updated,
|
||||
action: "updated",
|
||||
object: "service_zone",
|
||||
data: { id: updatedServiceZone.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_created,
|
||||
action: "created",
|
||||
object: "geo_zone",
|
||||
data: { id: chGeoZone.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.geo_zone_updated,
|
||||
action: "updated",
|
||||
object: "geo_zone",
|
||||
data: { id: usGeoZone.id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should fail on duplicated service zone name", async function () {
|
||||
@@ -413,12 +494,16 @@ moduleIntegrationTestRunner({
|
||||
})
|
||||
)
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const updatedServiceZones = await service.upsertServiceZones(
|
||||
updateData
|
||||
)
|
||||
|
||||
expect(updatedServiceZones).toHaveLength(2)
|
||||
|
||||
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) {
|
||||
const expectedServiceZone = updatedServiceZones.find(
|
||||
(serviceZone) => serviceZone.id === data_.id
|
||||
|
||||
@@ -3,12 +3,18 @@ import {
|
||||
CreateShippingOptionDTO,
|
||||
IFulfillmentModuleService,
|
||||
} from "@medusajs/types"
|
||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
||||
import { generateCreateShippingOptionsData } from "../../__fixtures__"
|
||||
import {
|
||||
MockEventBusService,
|
||||
moduleIntegrationTestRunner,
|
||||
} from "medusa-test-utils"
|
||||
import {
|
||||
buildExpectedEventMessageShape,
|
||||
generateCreateShippingOptionsData,
|
||||
} from "../../__fixtures__"
|
||||
import { resolve } from "path"
|
||||
import { FulfillmentProviderService } from "@services"
|
||||
import { FulfillmentProviderServiceFixtures } from "../../__fixtures__/providers"
|
||||
import { GeoZoneType } from "@medusajs/utils"
|
||||
import { FulfillmentEvents, GeoZoneType } from "@medusajs/utils"
|
||||
import { UpdateShippingOptionDTO } from "@medusajs/types/src"
|
||||
|
||||
jest.setTimeout(100000)
|
||||
@@ -34,10 +40,20 @@ const providerId = FulfillmentProviderService.getRegistrationIdentifier(
|
||||
"test-provider"
|
||||
)
|
||||
|
||||
moduleIntegrationTestRunner({
|
||||
moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
moduleOptions,
|
||||
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
|
||||
testSuite: ({ service }) => {
|
||||
let eventBusEmitSpy
|
||||
|
||||
beforeEach(() => {
|
||||
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe("Fulfillment Module Service", () => {
|
||||
describe("read", () => {
|
||||
it("should list shipping options with a filter", async function () {
|
||||
@@ -432,6 +448,8 @@ moduleIntegrationTestRunner({
|
||||
provider_id: providerId,
|
||||
})
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const createdShippingOption = await service.createShippingOptions(
|
||||
createData
|
||||
)
|
||||
@@ -462,6 +480,28 @@ moduleIntegrationTestRunner({
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(3)
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_created,
|
||||
action: "created",
|
||||
object: "shipping_option",
|
||||
data: { id: createdShippingOption.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_type_created,
|
||||
action: "created",
|
||||
object: "shipping_option_type",
|
||||
data: { id: createdShippingOption.type.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_rule_created,
|
||||
action: "created",
|
||||
object: "shipping_option_rule",
|
||||
data: { id: createdShippingOption.rules[0].id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should create multiple new shipping options", async function () {
|
||||
@@ -491,11 +531,14 @@ moduleIntegrationTestRunner({
|
||||
}),
|
||||
]
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const createdShippingOptions = await service.createShippingOptions(
|
||||
createData
|
||||
)
|
||||
|
||||
expect(createdShippingOptions).toHaveLength(2)
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(6)
|
||||
|
||||
let i = 0
|
||||
for (const data_ of createData) {
|
||||
@@ -525,6 +568,30 @@ moduleIntegrationTestRunner({
|
||||
]),
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_created,
|
||||
action: "created",
|
||||
object: "shipping_option",
|
||||
data: { id: createdShippingOptions[i].id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_type_created,
|
||||
action: "created",
|
||||
object: "shipping_option_type",
|
||||
data: { id: createdShippingOptions[i].type.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_rule_created,
|
||||
action: "created",
|
||||
object: "shipping_option_rule",
|
||||
data: { id: createdShippingOptions[i].rules[0].id },
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
++i
|
||||
}
|
||||
})
|
||||
@@ -623,6 +690,8 @@ moduleIntegrationTestRunner({
|
||||
],
|
||||
}
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const updatedShippingOption = await service.updateShippingOptions(
|
||||
updateData.id!,
|
||||
updateData
|
||||
@@ -681,6 +750,42 @@ moduleIntegrationTestRunner({
|
||||
label: updateData.type.label,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(5)
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_updated,
|
||||
action: "updated",
|
||||
object: "shipping_option",
|
||||
data: { id: updatedShippingOption.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_type_deleted,
|
||||
action: "deleted",
|
||||
object: "shipping_option_type",
|
||||
data: { id: shippingOption.type.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_type_created,
|
||||
action: "created",
|
||||
object: "shipping_option_type",
|
||||
data: { id: updatedShippingOption.type.id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_rule_created,
|
||||
action: "created",
|
||||
object: "shipping_option_rule",
|
||||
data: { id: updatedShippingOption.rules[1].id },
|
||||
}),
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_rule_updated,
|
||||
action: "updated",
|
||||
object: "shipping_option_rule",
|
||||
data: { id: updatedShippingOption.rules[0].id },
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should update a shipping option without updating the rules or the type", async () => {
|
||||
@@ -1092,6 +1197,8 @@ moduleIntegrationTestRunner({
|
||||
shipping_option_id: shippingOption.id,
|
||||
}
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const rule = await service.createShippingOptionRules(ruleData)
|
||||
|
||||
expect(rule).toEqual(
|
||||
@@ -1104,6 +1211,16 @@ moduleIntegrationTestRunner({
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_rule_created,
|
||||
action: "created",
|
||||
object: "shipping_option_rule",
|
||||
data: { id: rule.id },
|
||||
}),
|
||||
])
|
||||
|
||||
const rules = await service.listShippingOptionRules()
|
||||
expect(rules).toHaveLength(2)
|
||||
expect(rules).toEqual(
|
||||
@@ -1157,6 +1274,8 @@ moduleIntegrationTestRunner({
|
||||
value: "updated-test",
|
||||
}
|
||||
|
||||
jest.clearAllMocks()
|
||||
|
||||
const updatedRule = await service.updateShippingOptionRules(
|
||||
updateData
|
||||
)
|
||||
@@ -1169,6 +1288,15 @@ moduleIntegrationTestRunner({
|
||||
value: updateData.value,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_option_rule_updated,
|
||||
action: "updated",
|
||||
object: "shipping_option_rule",
|
||||
data: { id: updatedRule.id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should fail to update a non-existent shipping option rule", async () => {
|
||||
|
||||
@@ -3,13 +3,28 @@ import {
|
||||
CreateShippingProfileDTO,
|
||||
IFulfillmentModuleService,
|
||||
} from "@medusajs/types"
|
||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
||||
import {
|
||||
MockEventBusService,
|
||||
moduleIntegrationTestRunner,
|
||||
} from "medusa-test-utils"
|
||||
import { buildExpectedEventMessageShape } from "../../__fixtures__"
|
||||
import { FulfillmentEvents } from "@medusajs/utils"
|
||||
|
||||
jest.setTimeout(100000)
|
||||
|
||||
moduleIntegrationTestRunner({
|
||||
moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
testSuite: ({ service }: SuiteOptions<IFulfillmentModuleService>) => {
|
||||
testSuite: ({ service }) => {
|
||||
let eventBusEmitSpy
|
||||
|
||||
beforeEach(() => {
|
||||
eventBusEmitSpy = jest.spyOn(MockEventBusService.prototype, "emit")
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe("Fulfillment Module Service", () => {
|
||||
describe("mutations", () => {
|
||||
describe("on create", () => {
|
||||
@@ -29,6 +44,16 @@ moduleIntegrationTestRunner({
|
||||
type: createData.type,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_profile_created,
|
||||
action: "created",
|
||||
object: "shipping_profile",
|
||||
data: { id: createdShippingProfile.id },
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should create multiple new shipping profiles", async function () {
|
||||
@@ -47,6 +72,7 @@ moduleIntegrationTestRunner({
|
||||
await service.createShippingProfiles(createData)
|
||||
|
||||
expect(createdShippingProfiles).toHaveLength(2)
|
||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
||||
|
||||
let i = 0
|
||||
for (const data_ of createData) {
|
||||
@@ -56,6 +82,18 @@ moduleIntegrationTestRunner({
|
||||
type: data_.type,
|
||||
})
|
||||
)
|
||||
|
||||
expect(eventBusEmitSpy).toHaveBeenCalledWith(
|
||||
expect.arrayContaining([
|
||||
buildExpectedEventMessageShape({
|
||||
eventName: FulfillmentEvents.shipping_profile_created,
|
||||
action: "created",
|
||||
object: "shipping_profile",
|
||||
data: { id: createdShippingProfiles[i].id },
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
++i
|
||||
}
|
||||
})
|
||||
|
||||
@@ -115,7 +115,7 @@ export default class GeoZone {
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, " fgz")
|
||||
this.id = generateEntityId(this.id, "fgz")
|
||||
this.service_zone_id ??= this.service_zone?.id
|
||||
}
|
||||
|
||||
|
||||
@@ -15,15 +15,16 @@ import {
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
arrayDifference,
|
||||
deepEqualObj,
|
||||
EmitEvents,
|
||||
FulfillmentUtils,
|
||||
getSetDifference,
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
isDefined,
|
||||
isPresent,
|
||||
isString,
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
Modules,
|
||||
ModulesSdkUtils,
|
||||
promiseAll,
|
||||
} from "@medusajs/utils"
|
||||
@@ -38,10 +39,18 @@ import {
|
||||
ShippingOptionType,
|
||||
ShippingProfile,
|
||||
} from "@models"
|
||||
import { isContextValid, validateAndNormalizeRules } from "@utils"
|
||||
import {
|
||||
buildCreatedFulfillmentEvents,
|
||||
buildCreatedFulfillmentSetEvents,
|
||||
buildCreatedServiceZoneEvents,
|
||||
eventBuilders,
|
||||
isContextValid,
|
||||
validateAndNormalizeRules,
|
||||
} from "@utils"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { UpdateShippingOptionsInput } from "../types/service"
|
||||
import FulfillmentProviderService from "./fulfillment-provider"
|
||||
import { buildCreatedShippingOptionEvents } from "../utils/events"
|
||||
|
||||
const generateMethodForModels = [
|
||||
ServiceZone,
|
||||
@@ -271,9 +280,13 @@ export default class FulfillmentModuleService<
|
||||
> {
|
||||
const createdFulfillmentSets = await this.create_(data, sharedContext)
|
||||
|
||||
const returnedFulfillmentSets = Array.isArray(data)
|
||||
? createdFulfillmentSets
|
||||
: createdFulfillmentSets[0]
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
||||
>(createdFulfillmentSets)
|
||||
>(returnedFulfillmentSets)
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@@ -282,7 +295,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity | TEntity[]> {
|
||||
): Promise<TEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -304,14 +317,12 @@ export default class FulfillmentModuleService<
|
||||
sharedContext
|
||||
)
|
||||
|
||||
this.aggregateFulfillmentSetCreatedEvents(
|
||||
createdFulfillmentSets,
|
||||
sharedContext
|
||||
)
|
||||
buildCreatedFulfillmentSetEvents({
|
||||
fulfillmentSets: createdFulfillmentSets,
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return Array.isArray(data)
|
||||
? createdFulfillmentSets
|
||||
: createdFulfillmentSets[0]
|
||||
return createdFulfillmentSets
|
||||
}
|
||||
|
||||
createServiceZones(
|
||||
@@ -324,6 +335,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.ServiceZoneDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async createServiceZones(
|
||||
data:
|
||||
| FulfillmentTypes.CreateServiceZoneDTO[]
|
||||
@@ -339,7 +351,7 @@ export default class FulfillmentModuleService<
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.ServiceZoneDTO | FulfillmentTypes.ServiceZoneDTO[]
|
||||
>(createdServiceZones)
|
||||
>(Array.isArray(data) ? createdServiceZones : createdServiceZones[0])
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@@ -348,7 +360,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.CreateServiceZoneDTO[]
|
||||
| FulfillmentTypes.CreateServiceZoneDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TServiceZoneEntity | TServiceZoneEntity[]> {
|
||||
): Promise<TServiceZoneEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -368,7 +380,12 @@ export default class FulfillmentModuleService<
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return Array.isArray(data) ? createdServiceZones : createdServiceZones[0]
|
||||
buildCreatedServiceZoneEvents({
|
||||
serviceZones: createdServiceZones,
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return createdServiceZones
|
||||
}
|
||||
|
||||
createShippingOptions(
|
||||
@@ -381,6 +398,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.ShippingOptionDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async createShippingOptions(
|
||||
data:
|
||||
| FulfillmentTypes.CreateShippingOptionDTO[]
|
||||
@@ -396,7 +414,7 @@ export default class FulfillmentModuleService<
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.ShippingOptionDTO | FulfillmentTypes.ShippingOptionDTO[]
|
||||
>(createdShippingOptions)
|
||||
>(Array.isArray(data) ? createdShippingOptions : createdShippingOptions[0])
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@@ -405,7 +423,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.CreateShippingOptionDTO[]
|
||||
| FulfillmentTypes.CreateShippingOptionDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TShippingOptionEntity | TShippingOptionEntity[]> {
|
||||
): Promise<TShippingOptionEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -417,14 +435,17 @@ export default class FulfillmentModuleService<
|
||||
validateAndNormalizeRules(rules as Record<string, unknown>[])
|
||||
}
|
||||
|
||||
const createdShippingOptions = await this.shippingOptionService_.create(
|
||||
const createdSO = await this.shippingOptionService_.create(
|
||||
data_,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return Array.isArray(data)
|
||||
? createdShippingOptions
|
||||
: createdShippingOptions[0]
|
||||
buildCreatedShippingOptionEvents({
|
||||
shippingOptions: createdSO,
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return createdSO
|
||||
}
|
||||
|
||||
createShippingProfiles(
|
||||
@@ -437,6 +458,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.ShippingProfileDTO>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async createShippingProfiles(
|
||||
data:
|
||||
| FulfillmentTypes.CreateShippingProfileDTO[]
|
||||
@@ -450,10 +472,17 @@ export default class FulfillmentModuleService<
|
||||
sharedContext
|
||||
)
|
||||
|
||||
eventBuilders.createdShippingProfile({
|
||||
data: createdShippingProfiles,
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
| FulfillmentTypes.ShippingProfileDTO
|
||||
| FulfillmentTypes.ShippingProfileDTO[]
|
||||
>(createdShippingProfiles)
|
||||
>(
|
||||
Array.isArray(data) ? createdShippingProfiles : createdShippingProfiles[0]
|
||||
)
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@@ -462,21 +491,14 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.CreateShippingProfileDTO[]
|
||||
| FulfillmentTypes.CreateShippingProfileDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TShippingProfileEntity[] | TShippingProfileEntity> {
|
||||
): Promise<TShippingProfileEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
const createdShippingProfiles = await this.shippingProfileService_.create(
|
||||
data_,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return Array.isArray(data)
|
||||
? createdShippingProfiles
|
||||
: createdShippingProfiles[0]
|
||||
return await this.shippingProfileService_.create(data_, sharedContext)
|
||||
}
|
||||
|
||||
createGeoZones(
|
||||
@@ -489,6 +511,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.GeoZoneDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async createGeoZones(
|
||||
data:
|
||||
| FulfillmentTypes.CreateGeoZoneDTO
|
||||
@@ -504,6 +527,11 @@ export default class FulfillmentModuleService<
|
||||
sharedContext
|
||||
)
|
||||
|
||||
eventBuilders.createdGeoZone({
|
||||
data: createdGeoZones,
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return await this.baseRepository_.serialize<FulfillmentTypes.GeoZoneDTO[]>(
|
||||
Array.isArray(data) ? createdGeoZones : createdGeoZones[0]
|
||||
)
|
||||
@@ -519,6 +547,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.ShippingOptionRuleDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async createShippingOptionRules(
|
||||
data:
|
||||
| FulfillmentTypes.CreateShippingOptionRuleDTO[]
|
||||
@@ -536,7 +565,11 @@ export default class FulfillmentModuleService<
|
||||
return await this.baseRepository_.serialize<
|
||||
| FulfillmentTypes.ShippingOptionRuleDTO
|
||||
| FulfillmentTypes.ShippingOptionRuleDTO[]
|
||||
>(createdShippingOptionRules)
|
||||
>(
|
||||
Array.isArray(data)
|
||||
? createdShippingOptionRules
|
||||
: createdShippingOptionRules[0]
|
||||
)
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@@ -545,7 +578,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.CreateShippingOptionRuleDTO[]
|
||||
| FulfillmentTypes.CreateShippingOptionRuleDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TShippingOptionRuleEntity | TShippingOptionRuleEntity[]> {
|
||||
): Promise<TShippingOptionRuleEntity[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -554,15 +587,21 @@ export default class FulfillmentModuleService<
|
||||
|
||||
validateAndNormalizeRules(data_ as unknown as Record<string, unknown>[])
|
||||
|
||||
const createdShippingOptionRules =
|
||||
await this.shippingOptionRuleService_.create(data_, sharedContext)
|
||||
const createdSORules = await this.shippingOptionRuleService_.create(
|
||||
data_,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return Array.isArray(data)
|
||||
? createdShippingOptionRules
|
||||
: createdShippingOptionRules[0]
|
||||
eventBuilders.createdShippingOptionRule({
|
||||
data: createdSORules.map((sor) => ({ id: sor.id })),
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return createdSORules
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async createFulfillment(
|
||||
data: FulfillmentTypes.CreateFulfillmentDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
@@ -603,12 +642,18 @@ export default class FulfillmentModuleService<
|
||||
throw error
|
||||
}
|
||||
|
||||
buildCreatedFulfillmentEvents({
|
||||
fulfillments: [fulfillment],
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||
fulfillment
|
||||
)
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async createReturnFulfillment(
|
||||
data: FulfillmentTypes.CreateFulfillmentDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
@@ -639,6 +684,11 @@ export default class FulfillmentModuleService<
|
||||
throw error
|
||||
}
|
||||
|
||||
buildCreatedFulfillmentEvents({
|
||||
fulfillments: [fulfillment],
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||
fulfillment
|
||||
)
|
||||
@@ -654,6 +704,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.FulfillmentSetDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async update(
|
||||
data: UpdateFulfillmentSetDTO[] | UpdateFulfillmentSetDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
@@ -714,9 +765,11 @@ export default class FulfillmentModuleService<
|
||||
fulfillmentSets.map((f) => [f.id, f])
|
||||
)
|
||||
|
||||
// find service zones to delete
|
||||
const serviceZoneIdsToDelete: string[] = []
|
||||
const geoZoneIdsToDelete: string[] = []
|
||||
const existingServiceZoneIds: string[] = []
|
||||
const existingGeoZoneIds: string[] = []
|
||||
|
||||
data_.forEach((fulfillmentSet) => {
|
||||
if (fulfillmentSet.service_zones) {
|
||||
/**
|
||||
@@ -734,6 +787,7 @@ export default class FulfillmentModuleService<
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
)
|
||||
|
||||
if (toDeleteServiceZoneIds.size) {
|
||||
serviceZoneIdsToDelete.push(...Array.from(toDeleteServiceZoneIds))
|
||||
geoZoneIdsToDelete.push(
|
||||
@@ -758,11 +812,13 @@ export default class FulfillmentModuleService<
|
||||
.map((s) => "id" in s && s.id)
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
|
||||
const expectedServiceZoneSet = new Set(
|
||||
fulfillmentSet.service_zones
|
||||
.map((s) => "id" in s && s.id)
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
|
||||
const missingServiceZoneIds = getSetDifference(
|
||||
expectedServiceZoneSet,
|
||||
serviceZonesSet
|
||||
@@ -789,6 +845,16 @@ export default class FulfillmentModuleService<
|
||||
}
|
||||
return serviceZone
|
||||
}
|
||||
|
||||
const existingServiceZone = serviceZonesMap.get(serviceZone.id)!
|
||||
existingServiceZoneIds.push(existingServiceZone.id)
|
||||
|
||||
if (existingServiceZone.geo_zones.length) {
|
||||
existingGeoZoneIds.push(
|
||||
...existingServiceZone.geo_zones.map((g) => g.id)
|
||||
)
|
||||
}
|
||||
|
||||
return serviceZonesMap.get(serviceZone.id)!
|
||||
}
|
||||
)
|
||||
@@ -797,6 +863,15 @@ export default class FulfillmentModuleService<
|
||||
})
|
||||
|
||||
if (serviceZoneIdsToDelete.length) {
|
||||
eventBuilders.deletedServiceZone({
|
||||
data: serviceZoneIdsToDelete.map((id) => ({ id })),
|
||||
sharedContext,
|
||||
})
|
||||
eventBuilders.deletedGeoZone({
|
||||
data: geoZoneIdsToDelete.map((id) => ({ id })),
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
await promiseAll([
|
||||
this.geoZoneService_.delete(
|
||||
{
|
||||
@@ -818,6 +893,32 @@ export default class FulfillmentModuleService<
|
||||
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)
|
||||
? updatedFulfillmentSets
|
||||
: updatedFulfillmentSets[0]
|
||||
@@ -835,6 +936,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.ServiceZoneDTO[]>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async updateServiceZones(
|
||||
idOrSelector: string | FulfillmentTypes.FilterableServiceZoneProps,
|
||||
data: FulfillmentTypes.UpdateServiceZoneDTO,
|
||||
@@ -926,20 +1028,28 @@ export default class FulfillmentModuleService<
|
||||
)
|
||||
|
||||
const geoZoneIdsToDelete: string[] = []
|
||||
const existingGeoZoneIds: string[] = []
|
||||
const updatedGeoZoneIds: string[] = []
|
||||
|
||||
data_.forEach((serviceZone) => {
|
||||
if (serviceZone.geo_zones) {
|
||||
const existingServiceZone = serviceZoneMap.get(serviceZone.id!)!
|
||||
const existingGeoZones = existingServiceZone.geo_zones
|
||||
const updatedGeoZones = serviceZone.geo_zones
|
||||
const existingGeoZoneIdsForServiceZone = existingGeoZones.map(
|
||||
(g) => g.id
|
||||
)
|
||||
const toDeleteGeoZoneIds = getSetDifference(
|
||||
new Set(existingGeoZones.map((g) => g.id)),
|
||||
new Set(existingGeoZoneIdsForServiceZone),
|
||||
new Set(
|
||||
updatedGeoZones
|
||||
.map((g) => "id" in g && g.id)
|
||||
.filter((id): id is string => !!id)
|
||||
)
|
||||
)
|
||||
|
||||
existingGeoZoneIds.push(...existingGeoZoneIdsForServiceZone)
|
||||
|
||||
if (toDeleteGeoZoneIds.size) {
|
||||
geoZoneIdsToDelete.push(...Array.from(toDeleteGeoZoneIds))
|
||||
}
|
||||
@@ -978,12 +1088,25 @@ export default class FulfillmentModuleService<
|
||||
}
|
||||
const existing = geoZonesMap.get(geoZone.id)!
|
||||
|
||||
// If only the id is provided we dont consider it as an update
|
||||
if (
|
||||
Object.keys(geoZone).length > 1 &&
|
||||
!deepEqualObj(existing, geoZone)
|
||||
) {
|
||||
updatedGeoZoneIds.push(geoZone.id)
|
||||
}
|
||||
|
||||
return { ...existing, ...geoZone }
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (geoZoneIdsToDelete.length) {
|
||||
eventBuilders.deletedGeoZone({
|
||||
data: geoZoneIdsToDelete.map((id) => ({ id })),
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
await this.geoZoneService_.delete(
|
||||
{
|
||||
id: geoZoneIdsToDelete,
|
||||
@@ -997,6 +1120,26 @@ export default class FulfillmentModuleService<
|
||||
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]
|
||||
}
|
||||
|
||||
@@ -1010,11 +1153,12 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.ServiceZoneDTO[]>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async upsertServiceZones(
|
||||
data:
|
||||
| FulfillmentTypes.UpsertServiceZoneDTO
|
||||
| FulfillmentTypes.UpsertServiceZoneDTO[],
|
||||
sharedContext?: Context
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
FulfillmentTypes.ServiceZoneDTO | FulfillmentTypes.ServiceZoneDTO[]
|
||||
> {
|
||||
@@ -1055,9 +1199,11 @@ export default class FulfillmentModuleService<
|
||||
forCreate,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const toPush = Array.isArray(createdServiceZones)
|
||||
? createdServiceZones
|
||||
: [createdServiceZones]
|
||||
|
||||
created.push(...toPush)
|
||||
}
|
||||
|
||||
@@ -1066,9 +1212,11 @@ export default class FulfillmentModuleService<
|
||||
forUpdate,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const toPush = Array.isArray(updatedServiceZones)
|
||||
? updatedServiceZones
|
||||
: [updatedServiceZones]
|
||||
|
||||
updated.push(...toPush)
|
||||
}
|
||||
|
||||
@@ -1087,6 +1235,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.ShippingOptionDTO[]>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async updateShippingOptions(
|
||||
idOrSelector: string | FulfillmentTypes.FilterableShippingOptionProps,
|
||||
data: FulfillmentTypes.UpdateShippingOptionDTO,
|
||||
@@ -1142,7 +1291,7 @@ export default class FulfillmentModuleService<
|
||||
id: shippingOptionIds,
|
||||
},
|
||||
{
|
||||
relations: ["rules"],
|
||||
relations: ["rules", "type"],
|
||||
take: shippingOptionIds.length,
|
||||
},
|
||||
sharedContext
|
||||
@@ -1157,16 +1306,28 @@ export default class FulfillmentModuleService<
|
||||
)
|
||||
|
||||
const ruleIdsToDelete: string[] = []
|
||||
const updatedRuleIds: string[] = []
|
||||
const existingRuleIds: string[] = []
|
||||
|
||||
const optionTypeDeletedIds: string[] = []
|
||||
|
||||
dataArray.forEach((shippingOption) => {
|
||||
const existingShippingOption = existingShippingOptions.get(
|
||||
shippingOption.id
|
||||
)! // Garuantueed to exist since the validation above have been performed
|
||||
|
||||
if (shippingOption.type && !("id" in shippingOption.type)) {
|
||||
optionTypeDeletedIds.push(existingShippingOption.type.id)
|
||||
}
|
||||
|
||||
if (!shippingOption.rules) {
|
||||
return
|
||||
}
|
||||
|
||||
const existingShippingOption = existingShippingOptions.get(
|
||||
shippingOption.id
|
||||
)! // Garuantueed to exist since the validation above have been performed
|
||||
const existingRules = existingShippingOption.rules
|
||||
|
||||
existingRuleIds.push(...existingRules.map((r) => r.id))
|
||||
|
||||
FulfillmentModuleService.validateMissingShippingOptionRules(
|
||||
existingShippingOption,
|
||||
shippingOption
|
||||
@@ -1183,6 +1344,10 @@ export default class FulfillmentModuleService<
|
||||
const existingRule = (existingRulesMap.get(rule.id) ??
|
||||
{}) as FulfillmentTypes.UpdateShippingOptionRuleDTO
|
||||
|
||||
if (existingRulesMap.get(rule.id)) {
|
||||
updatedRuleIds.push(rule.id)
|
||||
}
|
||||
|
||||
const ruleData: FulfillmentTypes.UpdateShippingOptionRuleDTO = {
|
||||
...existingRule,
|
||||
...rule,
|
||||
@@ -1198,8 +1363,6 @@ export default class FulfillmentModuleService<
|
||||
|
||||
validateAndNormalizeRules(updatedRules)
|
||||
|
||||
const updatedRuleIds = updatedRules.map((r) => "id" in r && r.id)
|
||||
|
||||
const toDeleteRuleIds = arrayDifference(
|
||||
updatedRuleIds,
|
||||
Array.from(existingRulesMap.keys())
|
||||
@@ -1219,6 +1382,11 @@ export default class FulfillmentModuleService<
|
||||
})
|
||||
|
||||
if (ruleIdsToDelete.length) {
|
||||
eventBuilders.deletedShippingOptionRule({
|
||||
data: ruleIdsToDelete.map((id) => ({ id })),
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
await this.shippingOptionRuleService_.delete(
|
||||
ruleIdsToDelete,
|
||||
sharedContext
|
||||
@@ -1230,11 +1398,71 @@ export default class FulfillmentModuleService<
|
||||
sharedContext
|
||||
)
|
||||
|
||||
this.handleShippingOptionUpdateEvents({
|
||||
shippingOptionsData: dataArray,
|
||||
updatedShippingOptions,
|
||||
optionTypeDeletedIds,
|
||||
updatedRuleIds,
|
||||
existingRuleIds,
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return Array.isArray(data)
|
||||
? updatedShippingOptions
|
||||
: 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 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(
|
||||
data: FulfillmentTypes.UpsertShippingOptionDTO[],
|
||||
sharedContext?: Context
|
||||
@@ -1245,6 +1473,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.ShippingOptionDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async upsertShippingOptions(
|
||||
data:
|
||||
| FulfillmentTypes.UpsertShippingOptionDTO[]
|
||||
@@ -1329,6 +1558,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<
|
||||
FulfillmentTypes.ShippingProfileDTO | FulfillmentTypes.ShippingProfileDTO[]
|
||||
> {
|
||||
// TODO: should we implement that or can we get rid of the profiles concept entirely and link to the so instead?
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -1342,6 +1572,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.GeoZoneDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async updateGeoZones(
|
||||
data:
|
||||
| FulfillmentTypes.UpdateGeoZoneDTO
|
||||
@@ -1357,10 +1588,15 @@ export default class FulfillmentModuleService<
|
||||
FulfillmentModuleService.validateGeoZones(data_)
|
||||
|
||||
const updatedGeoZones = await this.geoZoneService_.update(
|
||||
data,
|
||||
data_,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
eventBuilders.updatedGeoZone({
|
||||
data: updatedGeoZones,
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
const serialized = await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.GeoZoneDTO[]
|
||||
>(updatedGeoZones)
|
||||
@@ -1378,6 +1614,7 @@ export default class FulfillmentModuleService<
|
||||
): Promise<FulfillmentTypes.ShippingOptionRuleDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async updateShippingOptionRules(
|
||||
data:
|
||||
| FulfillmentTypes.UpdateShippingOptionRuleDTO[]
|
||||
@@ -1416,31 +1653,140 @@ export default class FulfillmentModuleService<
|
||||
const updatedShippingOptionRules =
|
||||
await this.shippingOptionRuleService_.update(data_, sharedContext)
|
||||
|
||||
eventBuilders.updatedShippingOptionRule({
|
||||
data: updatedShippingOptionRules.map((rule) => ({ id: rule.id })),
|
||||
sharedContext,
|
||||
})
|
||||
|
||||
return Array.isArray(data)
|
||||
? updatedShippingOptionRules
|
||||
: updatedShippingOptionRules[0]
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async updateFulfillment(
|
||||
id: string,
|
||||
data: FulfillmentTypes.UpdateFulfillmentDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<FulfillmentTypes.FulfillmentDTO> {
|
||||
const fulfillment = await this.fulfillmentService_.update(
|
||||
{ id, ...data },
|
||||
const fulfillment = await this.updateFulfillment_(id, data, sharedContext)
|
||||
|
||||
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||
fulfillment
|
||||
)
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
protected async updateFulfillment_(
|
||||
id: string,
|
||||
data: FulfillmentTypes.UpdateFulfillmentDTO,
|
||||
@MedusaContext() sharedContext: Context
|
||||
): Promise<TFulfillmentEntity> {
|
||||
const existingFulfillment: TFulfillmentEntity =
|
||||
await this.fulfillmentService_.retrieve(
|
||||
id,
|
||||
{
|
||||
relations: ["items", "labels"],
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const updatedLabelIds: string[] = []
|
||||
let deletedLabelIds: string[] = []
|
||||
|
||||
const existingLabelIds = existingFulfillment.labels.map((label) => label.id)
|
||||
|
||||
/**
|
||||
* @note
|
||||
* Since the relation is a one to many, the deletion, update and creation of labels
|
||||
* is handled b the orm. That means that we dont have to perform any manual deletions or update.
|
||||
* For some reason we use to have upsert and replace handled manually but we could simplify all that just like
|
||||
* we do below which will create the label, update some and delete the one that does not exists in the new data.
|
||||
*
|
||||
* There is a bit of logic as we need to reassign the data of those we want to keep
|
||||
* and we also need to emit the events later on.
|
||||
*/
|
||||
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) {
|
||||
if (!("id" in label)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const existingLabel = existingFulfillment.labels.find(
|
||||
({ id }) => id === label.id
|
||||
)!
|
||||
|
||||
if (
|
||||
!existingLabel ||
|
||||
Object.keys(label).length === 1 ||
|
||||
deepEqualObj(existingLabel, label)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
updatedLabelIds.push(label.id)
|
||||
const labelData = { ...label }
|
||||
Object.assign(label, existingLabel, labelData)
|
||||
}
|
||||
}
|
||||
|
||||
const [fulfillment] = await this.fulfillmentService_.update(
|
||||
[{ id, ...data }],
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const serialized =
|
||||
await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||
fulfillment
|
||||
)
|
||||
this.handleFulfillmentUpdateEvents(
|
||||
fulfillment,
|
||||
existingLabelIds,
|
||||
updatedLabelIds,
|
||||
deletedLabelIds,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return Array.isArray(serialized) ? serialized[0] : serialized
|
||||
return fulfillment
|
||||
}
|
||||
|
||||
private handleFulfillmentUpdateEvents(
|
||||
fulfillment: 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("baseRepository_")
|
||||
@EmitEvents()
|
||||
async cancelFulfillment(
|
||||
id: string,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
@@ -1473,6 +1819,11 @@ export default class FulfillmentModuleService<
|
||||
},
|
||||
sharedContext
|
||||
)
|
||||
|
||||
eventBuilders.updatedFulfillment({
|
||||
data: [{ id }],
|
||||
sharedContext,
|
||||
})
|
||||
}
|
||||
|
||||
const result = await this.baseRepository_.serialize(fulfillment)
|
||||
@@ -1791,60 +2142,4 @@ export default class FulfillmentModuleService<
|
||||
|
||||
return geoZoneConstraints
|
||||
}
|
||||
|
||||
protected aggregateFulfillmentSetCreatedEvents(
|
||||
createdFulfillmentSets: TEntity[],
|
||||
sharedContext: Context
|
||||
): void {
|
||||
const buildMessage = ({
|
||||
eventName,
|
||||
id,
|
||||
object,
|
||||
}: {
|
||||
eventName: string
|
||||
id: string
|
||||
object: string
|
||||
}) => {
|
||||
return {
|
||||
eventName,
|
||||
metadata: {
|
||||
object,
|
||||
service: Modules.FULFILLMENT,
|
||||
action: "created",
|
||||
eventGroupId: sharedContext.eventGroupId,
|
||||
},
|
||||
data: { id },
|
||||
}
|
||||
}
|
||||
|
||||
for (const fulfillmentSet of createdFulfillmentSets) {
|
||||
sharedContext.messageAggregator!.saveRawMessageData(
|
||||
buildMessage({
|
||||
eventName: FulfillmentUtils.FulfillmentEvents.created,
|
||||
id: fulfillmentSet.id,
|
||||
object: "fulfillment_set",
|
||||
})
|
||||
)
|
||||
|
||||
for (const serviceZone of fulfillmentSet.service_zones ?? []) {
|
||||
sharedContext.messageAggregator!.saveRawMessageData(
|
||||
buildMessage({
|
||||
eventName: FulfillmentUtils.FulfillmentEvents.service_zone_created,
|
||||
id: serviceZone.id,
|
||||
object: "service_zone",
|
||||
})
|
||||
)
|
||||
|
||||
for (const geoZone of serviceZone.geo_zones ?? []) {
|
||||
sharedContext.messageAggregator!.saveRawMessageData(
|
||||
buildMessage({
|
||||
eventName: FulfillmentUtils.FulfillmentEvents.geo_zone_created,
|
||||
id: geoZone.id,
|
||||
object: "geo_zone",
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
293
packages/modules/fulfillment/src/utils/events.ts
Normal file
293
packages/modules/fulfillment/src/utils/events.ts
Normal file
@@ -0,0 +1,293 @@
|
||||
import {
|
||||
Fulfillment,
|
||||
FulfillmentSet,
|
||||
GeoZone,
|
||||
ServiceZone,
|
||||
ShippingOption,
|
||||
ShippingOptionRule,
|
||||
ShippingOptionType,
|
||||
} from "@models"
|
||||
import { Context } from "@medusajs/types"
|
||||
import {
|
||||
CommonEvents,
|
||||
eventBuilderFactory,
|
||||
FulfillmentEvents,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
export const eventBuilders = {
|
||||
createdFulfillment: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "fulfillment",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
updatedFulfillment: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "fulfillment",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdFulfillmentAddress: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "fulfillment_address",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdFulfillmentItem: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "fulfillment_item",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdFulfillmentLabel: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "fulfillment_label",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
updatedFulfillmentLabel: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "fulfillment_label",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
deletedFulfillmentLabel: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "fulfillment_label",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdShippingProfile: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "shipping_profile",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdShippingOptionType: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "shipping_option_type",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
updatedShippingOptionType: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "shipping_option_type",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
deletedShippingOptionType: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "shipping_option_type",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdShippingOptionRule: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "shipping_option_rule",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
updatedShippingOptionRule: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "shipping_option_rule",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
deletedShippingOptionRule: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "shipping_option_rule",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdShippingOption: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "shipping_option",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
updatedShippingOption: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "shipping_option",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdFulfillmentSet: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "fulfillment_set",
|
||||
isMainEntity: true,
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
updatedFulfillmentSet: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "fulfillment_set",
|
||||
isMainEntity: true,
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
deletedFulfillmentSet: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "fulfillment_set",
|
||||
isMainEntity: true,
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdServiceZone: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "service_zone",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
updatedServiceZone: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "service_zone",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
deletedServiceZone: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "service_zone",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
createdGeoZone: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "geo_zone",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
updatedGeoZone: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "geo_zone",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
deletedGeoZone: eventBuilderFactory({
|
||||
service: Modules.FULFILLMENT,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "geo_zone",
|
||||
eventsEnum: FulfillmentEvents,
|
||||
}),
|
||||
}
|
||||
|
||||
export function buildCreatedFulfillmentEvents({
|
||||
fulfillments,
|
||||
sharedContext,
|
||||
}: {
|
||||
fulfillments: Fulfillment[]
|
||||
sharedContext: Context
|
||||
}) {
|
||||
if (!fulfillments.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const fulfillments_: { id: string }[] = []
|
||||
const addresses: { id: string }[] = []
|
||||
const items: { id: string }[] = []
|
||||
const labels: { id: string }[] = []
|
||||
|
||||
fulfillments.forEach((fulfillment) => {
|
||||
fulfillments_.push({ id: fulfillment.id })
|
||||
|
||||
if (fulfillment.delivery_address) {
|
||||
addresses.push({ id: fulfillment.delivery_address.id })
|
||||
}
|
||||
|
||||
if (fulfillment.items) {
|
||||
items.push(...fulfillment.items)
|
||||
}
|
||||
|
||||
if (fulfillment.labels) {
|
||||
labels.push(...fulfillment.labels)
|
||||
}
|
||||
})
|
||||
|
||||
eventBuilders.createdFulfillment({ data: fulfillments_, sharedContext })
|
||||
eventBuilders.createdFulfillmentAddress({ data: addresses, sharedContext })
|
||||
eventBuilders.createdFulfillmentItem({ data: items, sharedContext })
|
||||
eventBuilders.createdFulfillmentLabel({ data: labels, sharedContext })
|
||||
}
|
||||
|
||||
export function buildCreatedShippingOptionEvents({
|
||||
shippingOptions,
|
||||
sharedContext,
|
||||
}: {
|
||||
shippingOptions: ShippingOption[]
|
||||
sharedContext: Context
|
||||
}) {
|
||||
if (!shippingOptions.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const options: { id: string }[] = []
|
||||
const types: ShippingOptionType[] = []
|
||||
const rules: ShippingOptionRule[] = []
|
||||
|
||||
shippingOptions.forEach((shippingOption) => {
|
||||
options.push({ id: shippingOption.id })
|
||||
|
||||
if (shippingOption.type) {
|
||||
types.push(shippingOption.type)
|
||||
}
|
||||
|
||||
if (shippingOption.rules) {
|
||||
rules.push(...shippingOption.rules)
|
||||
}
|
||||
})
|
||||
|
||||
eventBuilders.createdShippingOption({ data: options, sharedContext })
|
||||
eventBuilders.createdShippingOptionType({ data: types, sharedContext })
|
||||
eventBuilders.createdShippingOptionRule({ data: rules, sharedContext })
|
||||
}
|
||||
|
||||
export function buildCreatedFulfillmentSetEvents({
|
||||
fulfillmentSets,
|
||||
sharedContext,
|
||||
}: {
|
||||
fulfillmentSets: FulfillmentSet[]
|
||||
sharedContext: Context
|
||||
}): void {
|
||||
if (!fulfillmentSets.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const serviceZones: ServiceZone[] = []
|
||||
|
||||
fulfillmentSets.forEach((fulfillmentSet) => {
|
||||
if (!fulfillmentSet.service_zones?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
serviceZones.push(...fulfillmentSet.service_zones)
|
||||
})
|
||||
|
||||
eventBuilders.createdFulfillmentSet({ data: fulfillmentSets, sharedContext })
|
||||
|
||||
buildCreatedServiceZoneEvents({ serviceZones, sharedContext })
|
||||
}
|
||||
|
||||
export function buildCreatedServiceZoneEvents({
|
||||
serviceZones,
|
||||
sharedContext,
|
||||
}: {
|
||||
serviceZones: ServiceZone[]
|
||||
sharedContext: Context
|
||||
}): void {
|
||||
if (!serviceZones.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const geoZones: GeoZone[] = []
|
||||
|
||||
serviceZones.forEach((serviceZone) => {
|
||||
if (!serviceZone.geo_zones.length) {
|
||||
return
|
||||
}
|
||||
|
||||
geoZones.push(...serviceZone.geo_zones)
|
||||
})
|
||||
|
||||
eventBuilders.createdServiceZone({ data: serviceZones, sharedContext })
|
||||
eventBuilders.createdGeoZone({ data: geoZones, sharedContext })
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
export * from './utils'
|
||||
export * from "./utils"
|
||||
export * from "./events"
|
||||
|
||||
@@ -15,11 +15,11 @@ import {
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
InventoryEvents,
|
||||
isDefined,
|
||||
isString,
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
ModulesSdkUtils,
|
||||
isDefined,
|
||||
isString,
|
||||
partitionArray,
|
||||
promiseAll,
|
||||
} from "@medusajs/utils"
|
||||
@@ -198,11 +198,10 @@ export default class InventoryModuleService<
|
||||
context.messageAggregator?.saveRawMessageData(
|
||||
created.map((reservationItem) => ({
|
||||
eventName: InventoryEvents.reservation_item_created,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "reservation-item",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "reservation-item",
|
||||
context,
|
||||
data: { id: reservationItem.id },
|
||||
}))
|
||||
)
|
||||
@@ -297,11 +296,10 @@ export default class InventoryModuleService<
|
||||
context.messageAggregator?.saveRawMessageData(
|
||||
result.map((inventoryItem) => ({
|
||||
eventName: InventoryEvents.created,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "inventory-item",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "inventory-item",
|
||||
context,
|
||||
data: { id: inventoryItem.id },
|
||||
}))
|
||||
)
|
||||
@@ -349,11 +347,10 @@ export default class InventoryModuleService<
|
||||
context.messageAggregator?.saveRawMessageData(
|
||||
created.map((inventoryLevel) => ({
|
||||
eventName: InventoryEvents.inventory_level_created,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "inventory-level",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "inventory-level",
|
||||
context,
|
||||
data: { id: inventoryLevel.id },
|
||||
}))
|
||||
)
|
||||
@@ -408,11 +405,10 @@ export default class InventoryModuleService<
|
||||
context.messageAggregator?.saveRawMessageData(
|
||||
result.map((inventoryItem) => ({
|
||||
eventName: InventoryEvents.updated,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "inventory-item",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "inventory-item",
|
||||
context,
|
||||
data: { id: inventoryItem.id },
|
||||
}))
|
||||
)
|
||||
@@ -448,11 +444,10 @@ export default class InventoryModuleService<
|
||||
context.messageAggregator?.saveRawMessageData(
|
||||
result[0].map((inventoryLevel) => ({
|
||||
eventName: InventoryEvents.inventory_level_deleted,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "inventory-level",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "inventory-level",
|
||||
context,
|
||||
data: { id: inventoryLevel.id },
|
||||
}))
|
||||
)
|
||||
@@ -480,11 +475,10 @@ export default class InventoryModuleService<
|
||||
|
||||
context.messageAggregator?.saveRawMessageData({
|
||||
eventName: InventoryEvents.inventory_level_deleted,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "inventory-level",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "inventory-level",
|
||||
context,
|
||||
data: { id: inventoryLevel.id },
|
||||
})
|
||||
|
||||
@@ -521,11 +515,10 @@ export default class InventoryModuleService<
|
||||
context.messageAggregator?.saveRawMessageData(
|
||||
levels.map((inventoryLevel) => ({
|
||||
eventName: InventoryEvents.inventory_level_updated,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "inventory-level",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "inventory-level",
|
||||
context,
|
||||
data: { id: inventoryLevel.id },
|
||||
}))
|
||||
)
|
||||
@@ -606,11 +599,10 @@ export default class InventoryModuleService<
|
||||
context.messageAggregator?.saveRawMessageData(
|
||||
result.map((reservationItem) => ({
|
||||
eventName: InventoryEvents.inventory_level_updated,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "reservation-item",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "reservation-item",
|
||||
context,
|
||||
data: { id: reservationItem.id },
|
||||
}))
|
||||
)
|
||||
@@ -738,11 +730,10 @@ export default class InventoryModuleService<
|
||||
context.messageAggregator?.saveRawMessageData(
|
||||
reservations.map((reservationItem) => ({
|
||||
eventName: InventoryEvents.reservation_item_deleted,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "reservation-item",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "reservation-item",
|
||||
context,
|
||||
data: { id: reservationItem.id },
|
||||
}))
|
||||
)
|
||||
@@ -781,11 +772,10 @@ export default class InventoryModuleService<
|
||||
context.messageAggregator?.saveRawMessageData(
|
||||
reservations.map((reservationItem) => ({
|
||||
eventName: InventoryEvents.reservation_item_deleted,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "reservation-item",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.DELETED,
|
||||
object: "reservation-item",
|
||||
context,
|
||||
data: { id: reservationItem.id },
|
||||
}))
|
||||
)
|
||||
@@ -851,11 +841,10 @@ export default class InventoryModuleService<
|
||||
|
||||
context.messageAggregator?.saveRawMessageData({
|
||||
eventName: InventoryEvents.inventory_level_updated,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "inventory-level",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "inventory-level",
|
||||
context,
|
||||
data: { id: result.id },
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import {
|
||||
Context,
|
||||
DAL,
|
||||
IEventBusModuleService,
|
||||
InternalModuleDeclaration,
|
||||
ModuleJoinerConfig,
|
||||
UserTypes,
|
||||
ModulesSdkTypes,
|
||||
IEventBusModuleService,
|
||||
UserTypes,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
CommonEvents,
|
||||
EmitEvents,
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
MedusaContext,
|
||||
ModulesSdkUtils,
|
||||
InjectManager,
|
||||
CommonEvents,
|
||||
UserEvents,
|
||||
} from "@medusajs/utils"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
@@ -94,11 +94,10 @@ export default class UserModuleService<
|
||||
sharedContext.messageAggregator?.saveRawMessageData(
|
||||
invites.map((invite) => ({
|
||||
eventName: UserEvents.invite_token_generated,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: "token_generated",
|
||||
object: "invite",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: "token_generated",
|
||||
object: "invite",
|
||||
context: sharedContext,
|
||||
data: { id: invite.id },
|
||||
}))
|
||||
)
|
||||
@@ -150,11 +149,10 @@ export default class UserModuleService<
|
||||
sharedContext.messageAggregator?.saveRawMessageData(
|
||||
users.map((user) => ({
|
||||
eventName: UserEvents.created,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "user",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "user",
|
||||
context: sharedContext,
|
||||
data: { id: user.id },
|
||||
}))
|
||||
)
|
||||
@@ -190,11 +188,10 @@ export default class UserModuleService<
|
||||
sharedContext.messageAggregator?.saveRawMessageData(
|
||||
updatedUsers.map((user) => ({
|
||||
eventName: UserEvents.updated,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "user",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "user",
|
||||
context: sharedContext,
|
||||
data: { id: user.id },
|
||||
}))
|
||||
)
|
||||
@@ -230,11 +227,10 @@ export default class UserModuleService<
|
||||
sharedContext.messageAggregator?.saveRawMessageData(
|
||||
invites.map((invite) => ({
|
||||
eventName: UserEvents.invite_created,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "invite",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.CREATED,
|
||||
object: "invite",
|
||||
context: sharedContext,
|
||||
data: { id: invite.id },
|
||||
}))
|
||||
)
|
||||
@@ -242,11 +238,10 @@ export default class UserModuleService<
|
||||
sharedContext.messageAggregator?.saveRawMessageData(
|
||||
invites.map((invite) => ({
|
||||
eventName: UserEvents.invite_token_generated,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: "token_generated",
|
||||
object: "invite",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: "token_generated",
|
||||
object: "invite",
|
||||
context: sharedContext,
|
||||
data: { id: invite.id },
|
||||
}))
|
||||
)
|
||||
@@ -301,11 +296,10 @@ export default class UserModuleService<
|
||||
sharedContext.messageAggregator?.saveRawMessageData(
|
||||
serializedInvites.map((invite) => ({
|
||||
eventName: UserEvents.invite_updated,
|
||||
metadata: {
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "invite",
|
||||
},
|
||||
service: this.constructor.name,
|
||||
action: CommonEvents.UPDATED,
|
||||
object: "invite",
|
||||
context: sharedContext,
|
||||
data: { id: invite.id },
|
||||
}))
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user