feat(core-flows,dashboard,js-sdk,promotion,medusa,types,utils): limit promotion usage per customer (#13451)
**What** - implement promotion usage limits per customer/email - fix registering spend usage over the limit - fix type errors in promotion module tests **How** - introduce a new type of campaign budget that can be defined by an attribute such as customer id or email - add `CampaignBudgetUsage` entity to keep track of the number of uses per attribute value - update `registerUsage` and `computeActions` in the promotion module to work with the new type - update `core-flows` to pass context needed for usage calculation to the promotion module **Breaking** - registering promotion usage now throws (and cart complete fails) if the budget limit is exceeded or if the cart completion would result in a breached limit --- CLOSES CORE-1172 CLOSES CORE-1173 CLOSES CORE-1174 CLOSES CORE-1175 Co-authored-by: Adrien de Peretti <25098370+adrien2p@users.noreply.github.com>
This commit is contained in:
co-authored by
Adrien de Peretti
parent
924564bee5
commit
7dc3b0c5ff
@@ -2,6 +2,7 @@
|
||||
// Always ensure that cartFieldsForCalculateShippingOptionsPrices is present in cartFieldsForRefreshSteps
|
||||
export const cartFieldsForRefreshSteps = [
|
||||
"id",
|
||||
"email",
|
||||
"currency_code",
|
||||
"quantity",
|
||||
"subtotal",
|
||||
|
||||
@@ -338,7 +338,13 @@ export const completeCartWorkflow = createWorkflow(
|
||||
})
|
||||
}
|
||||
|
||||
return promotionUsage
|
||||
return {
|
||||
computedActions: promotionUsage,
|
||||
registrationContext: {
|
||||
customer_id: cart.customer?.id || null,
|
||||
customer_email: cart.email || null,
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
CampaignBudgetUsageContext,
|
||||
IPromotionModuleService,
|
||||
UsageComputedActions,
|
||||
} from "@medusajs/framework/types"
|
||||
@@ -6,26 +7,37 @@ import { Modules } from "@medusajs/framework/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const registerUsageStepId = "register-usage"
|
||||
|
||||
type RegisterUsageStepInput = {
|
||||
computedActions: UsageComputedActions[]
|
||||
registrationContext: CampaignBudgetUsageContext
|
||||
}
|
||||
/**
|
||||
* This step registers usage for a promotion.
|
||||
*/
|
||||
export const registerUsageStep = createStep(
|
||||
registerUsageStepId,
|
||||
async (data: UsageComputedActions[], { container }) => {
|
||||
if (!data.length) {
|
||||
return new StepResponse(null, [])
|
||||
async (data: RegisterUsageStepInput, { container }) => {
|
||||
if (!data.computedActions.length) {
|
||||
return new StepResponse(null, {
|
||||
computedActions: [],
|
||||
registrationContext: data.registrationContext,
|
||||
})
|
||||
}
|
||||
|
||||
const promotionModule = container.resolve<IPromotionModuleService>(
|
||||
Modules.PROMOTION
|
||||
)
|
||||
|
||||
await promotionModule.registerUsage(data)
|
||||
await promotionModule.registerUsage(
|
||||
data.computedActions,
|
||||
data.registrationContext
|
||||
)
|
||||
|
||||
return new StepResponse(null, data)
|
||||
},
|
||||
async (revertData, { container }) => {
|
||||
if (!revertData?.length) {
|
||||
if (!revertData?.computedActions.length) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -33,6 +45,9 @@ export const registerUsageStep = createStep(
|
||||
Modules.PROMOTION
|
||||
)
|
||||
|
||||
await promotionModule.revertUsage(revertData)
|
||||
await promotionModule.revertUsage(
|
||||
revertData.computedActions,
|
||||
revertData.registrationContext
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -15,26 +15,26 @@ export class Campaign {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method retrieves a campaign by its ID. It sends a request to the
|
||||
* This method retrieves a campaign by its ID. It sends a request to the
|
||||
* [Get Campaign](https://docs.medusajs.com/api/admin#campaigns_getcampaignsid) API route.
|
||||
*
|
||||
*
|
||||
* @param id - The campaign's ID.
|
||||
* @param query - Configure the fields to retrieve in the campaign.
|
||||
* @param headers - Headers to pass in the request
|
||||
* @returns The campaign's details.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* To retrieve a campaign by its ID:
|
||||
*
|
||||
*
|
||||
* ```ts
|
||||
* sdk.admin.campaign.retrieve("procamp_123")
|
||||
* .then(({ campaign }) => {
|
||||
* console.log(campaign)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* To specify the fields and relations to retrieve:
|
||||
*
|
||||
*
|
||||
* ```ts
|
||||
* sdk.admin.campaign.retrieve("procamp_123", {
|
||||
* fields: "id,*budget"
|
||||
@@ -43,7 +43,7 @@ export class Campaign {
|
||||
* console.log(campaign)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
|
||||
*/
|
||||
async retrieve(
|
||||
@@ -61,27 +61,27 @@ export class Campaign {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method retrieves a paginated list of campaigns. It sends a request to the
|
||||
* This method retrieves a paginated list of campaigns. It sends a request to the
|
||||
* [List Campaigns](https://docs.medusajs.com/api/admin#campaigns_getcampaigns) API route.
|
||||
*
|
||||
*
|
||||
* @param query - Filters and pagination configurations.
|
||||
* @param headers - Headers to pass in the request.
|
||||
* @returns The paginated list of campaigns.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* To retrieve the list of campaigns:
|
||||
*
|
||||
*
|
||||
* ```ts
|
||||
* sdk.admin.campaign.list()
|
||||
* .then(({ campaigns, count, limit, offset }) => {
|
||||
* console.log(campaigns)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* To configure the pagination, pass the `limit` and `offset` query parameters.
|
||||
*
|
||||
*
|
||||
* For example, to retrieve only 10 items and skip 10 items:
|
||||
*
|
||||
*
|
||||
* ```ts
|
||||
* sdk.admin.campaign.list({
|
||||
* limit: 10,
|
||||
@@ -91,10 +91,10 @@ export class Campaign {
|
||||
* console.log(campaigns)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* Using the `fields` query parameter, you can specify the fields and relations to retrieve
|
||||
* in each campaign:
|
||||
*
|
||||
*
|
||||
* ```ts
|
||||
* sdk.admin.campaign.list({
|
||||
* fields: "id,*budget"
|
||||
@@ -103,7 +103,7 @@ export class Campaign {
|
||||
* console.log(campaigns)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
|
||||
*/
|
||||
async list(
|
||||
@@ -120,13 +120,13 @@ export class Campaign {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a campaign. It sends a request to the
|
||||
* This method creates a campaign. It sends a request to the
|
||||
* [Create Campaign](https://docs.medusajs.com/api/admin#campaigns_postcampaigns) API route.
|
||||
*
|
||||
*
|
||||
* @param payload - The details of the campaign to create.
|
||||
* @param headers - Headers to pass in the request
|
||||
* @returns The campaign's details.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* sdk.admin.campaign.create({
|
||||
* name: "Summer Campaign"
|
||||
@@ -150,14 +150,14 @@ export class Campaign {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method updates a campaign. It sends a request to the
|
||||
* This method updates a campaign. It sends a request to the
|
||||
* [Update Campaign](https://docs.medusajs.com/api/admin#campaigns_postcampaignsid) API route.
|
||||
*
|
||||
*
|
||||
* @param id - The campaign's ID.
|
||||
* @param payload - The data to update in the campaign.
|
||||
* @param headers - Headers to pass in the request
|
||||
* @returns The campaign's details.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* sdk.admin.campaign.update("procamp_123", {
|
||||
* name: "Summer Campaign"
|
||||
@@ -184,11 +184,11 @@ export class Campaign {
|
||||
/**
|
||||
* This method deletes a campaign by its ID. It sends a request to the
|
||||
* [Delete Campaign](https://docs.medusajs.com/api/admin#campaigns_deletecampaignsid) API route.
|
||||
*
|
||||
*
|
||||
* @param id - The campaign's ID.
|
||||
* @param headers - Headers to pass in the request
|
||||
* @returns The deletion's details.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* sdk.admin.campaign.delete("procamp_123")
|
||||
* .then(({ deleted }) => {
|
||||
@@ -209,12 +209,12 @@ export class Campaign {
|
||||
* This method manages the promotions of a campaign to either add or remove the association between them.
|
||||
* It sends a request to the [Manage Promotions](https://docs.medusajs.com/api/admin#campaigns_postcampaignsidpromotions)
|
||||
* API route.
|
||||
*
|
||||
*
|
||||
* @param id - The campaign's ID.
|
||||
* @param payload - The promotions to add or remove associations to them.
|
||||
* @param headers - Headers to pass in the request
|
||||
* @returns The campaign's details.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* sdk.admin.campaign.batchPromotions("procamp_123", {
|
||||
* add: ["prom_123", "prom_456"],
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface AdminCreateCampaign {
|
||||
description?: string
|
||||
/**
|
||||
* The campaign's currency code.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* usd
|
||||
*/
|
||||
@@ -33,13 +33,13 @@ export interface AdminCreateCampaign {
|
||||
*/
|
||||
budget?: {
|
||||
/**
|
||||
* The budget's type. `spend` means the limit is set on the total amount discounted by the campaign's promotions;
|
||||
* The budget's type. `spend` means the limit is set on the total amount discounted by the campaign's promotions;
|
||||
* `usage` means the limit is set on the total number of times the campaign's promotions can be used.
|
||||
*/
|
||||
type?: CampaignBudgetTypeValues
|
||||
/**
|
||||
* The budget's currency code.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* usd
|
||||
*/
|
||||
@@ -48,6 +48,10 @@ export interface AdminCreateCampaign {
|
||||
* The budget's limit.
|
||||
*/
|
||||
limit?: number | null
|
||||
/**
|
||||
* The budget's attribute.
|
||||
*/
|
||||
attribute?: string | null
|
||||
} | null
|
||||
}
|
||||
|
||||
@@ -62,7 +66,7 @@ export interface AdminUpdateCampaign {
|
||||
description?: string
|
||||
/**
|
||||
* The campaign's currency code.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* usd
|
||||
*/
|
||||
@@ -84,13 +88,13 @@ export interface AdminUpdateCampaign {
|
||||
*/
|
||||
budget?: {
|
||||
/**
|
||||
* The budget's type. `spend` means the limit is set on the total amount discounted by the campaign's promotions;
|
||||
* The budget's type. `spend` means the limit is set on the total amount discounted by the campaign's promotions;
|
||||
* `usage` means the limit is set on the total number of times the campaign's promotions can be used.
|
||||
*/
|
||||
type?: CampaignBudgetTypeValues
|
||||
/**
|
||||
* The budget's currency code.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* usd
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface AdminCampaign {
|
||||
description: string
|
||||
/**
|
||||
* The campaign's currency code.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* usd
|
||||
*/
|
||||
@@ -42,13 +42,13 @@ export interface AdminCampaign {
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* The budget's type. `spend` means the limit is set on the total amount discounted by the campaign's promotions;
|
||||
* The budget's type. `spend` means the limit is set on the total amount discounted by the campaign's promotions;
|
||||
* `usage` means the limit is set on the total number of times the campaign's promotions can be used.
|
||||
*/
|
||||
type: CampaignBudgetTypeValues
|
||||
/**
|
||||
* The budget's currency code.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* usd
|
||||
*/
|
||||
@@ -58,11 +58,15 @@ export interface AdminCampaign {
|
||||
*/
|
||||
limit: number
|
||||
/**
|
||||
* How much of the budget has been used. If the limit is `spend`, this property holds the total amount
|
||||
* How much of the budget has been used. If the limit is `spend`, this property holds the total amount
|
||||
* discounted so far. If the limit is `usage`, it holds the number of times the campaign's
|
||||
* promotions have been used so far.
|
||||
*/
|
||||
used: number
|
||||
/**
|
||||
* The budget's attribute if type is `use_by_attribute`.
|
||||
*/
|
||||
attribute: string
|
||||
}
|
||||
created_at: string
|
||||
updated_at: string
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { BaseFilterable } from "../../dal"
|
||||
import { CampaignBudgetUsageDTO } from "./campaing-budget-usage"
|
||||
|
||||
/**
|
||||
* The campaign budget's possible types.
|
||||
*/
|
||||
export type CampaignBudgetTypeValues = "spend" | "usage"
|
||||
export type CampaignBudgetTypeValues =
|
||||
| "spend"
|
||||
| "usage"
|
||||
| "use_by_attribute"
|
||||
| "spend_by_attribute"
|
||||
|
||||
/**
|
||||
* The campaign budget details.
|
||||
@@ -19,6 +24,8 @@ export interface CampaignBudgetDTO {
|
||||
*
|
||||
* - `spend` indicates that the budget is limited by the amount discounted by the promotions in the associated campaign.
|
||||
* - `usage` indicates that the budget is limited by the number of times the promotions of the associated campaign have been used.
|
||||
* - `use_by_attribute` indicates that the budget is limited by the number of times the promotions of the associated campaign have been used by a specific attribute value.
|
||||
* - `spend_by_attribute` indicates that the budget is limited by the amount discounted by the promotions in the associated campaign by a specific attribute value.
|
||||
*
|
||||
*/
|
||||
type?: CampaignBudgetTypeValues
|
||||
@@ -41,6 +48,16 @@ export interface CampaignBudgetDTO {
|
||||
* The currency of the campaign.
|
||||
*/
|
||||
currency_code?: string
|
||||
|
||||
/**
|
||||
* The attribute of the campaign budget.
|
||||
*/
|
||||
attribute?: string
|
||||
|
||||
/**
|
||||
* The usages of the campaign budget.
|
||||
*/
|
||||
usages?: CampaignBudgetUsageDTO[]
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* The context passed when promotion use is registered, reverted or limit is checked.
|
||||
*/
|
||||
export type CampaignBudgetUsageContext = {
|
||||
/**
|
||||
* The ID of the customer.
|
||||
*/
|
||||
customer_id: string | null
|
||||
/**
|
||||
* The email of the customer.
|
||||
*/
|
||||
customer_email: string | null
|
||||
}
|
||||
/**
|
||||
* Record of promotion usage as part of a campaign
|
||||
*/
|
||||
export interface CampaignBudgetUsageDTO {
|
||||
/**
|
||||
* The ID of the campaign budget usage.
|
||||
*/
|
||||
id: string
|
||||
/**
|
||||
* The value of the attribute that the promotion was used by.
|
||||
* e.g. if budget campaign is defined on `email` as a useage attribute,
|
||||
* `attribute_value` could contains email addresses
|
||||
*/
|
||||
attribute_value: string
|
||||
/**
|
||||
* The amount of times the promotion was used or
|
||||
* the amount of money discounted by the promotion.
|
||||
* Depends on the CampaignBudget type.
|
||||
*/
|
||||
used: number
|
||||
/**
|
||||
* The ID of the campaign budget.
|
||||
*/
|
||||
budget_id: string
|
||||
/**
|
||||
* The raw used value.
|
||||
*/
|
||||
raw_used: Record<string, any>
|
||||
/**
|
||||
* The date and time the campaign budget usage was created.
|
||||
*/
|
||||
created_at: string
|
||||
/**
|
||||
* The date and time the campaign budget usage was updated.
|
||||
*/
|
||||
updated_at: string
|
||||
/**
|
||||
* The date and time the campaign budget usage was deleted.
|
||||
*/
|
||||
deleted_at: string
|
||||
}
|
||||
@@ -15,7 +15,7 @@ export type ComputeActions =
|
||||
*/
|
||||
export type UsageComputedActions = {
|
||||
/**
|
||||
* The amount to remove off the shipping method's total.
|
||||
* The amount (of usage or money) to adjust the campaign budget by.
|
||||
*/
|
||||
amount: BigNumberInput
|
||||
|
||||
@@ -242,6 +242,11 @@ export interface ComputeActionContext extends Record<string, unknown> {
|
||||
*/
|
||||
currency_code: string
|
||||
|
||||
/**
|
||||
* The cart's email
|
||||
*/
|
||||
email?: string
|
||||
|
||||
/**
|
||||
* The cart's line items.
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,7 @@ export * from "./application-method"
|
||||
export * from "./campaign"
|
||||
export * from "./campaign-budget"
|
||||
export * from "./compute-actions"
|
||||
export * from "./campaing-budget-usage"
|
||||
export * from "./promotion"
|
||||
export * from "./promotion-rule"
|
||||
export * from "./promotion-rule-value"
|
||||
|
||||
@@ -23,6 +23,11 @@ export interface CreateCampaignBudgetDTO {
|
||||
* The currency of the campaign.
|
||||
*/
|
||||
currency_code?: string | null
|
||||
|
||||
/**
|
||||
* The attribute by which the campaign budget usage is limited.
|
||||
*/
|
||||
attribute?: string | null
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@ import { IModuleService } from "../modules-sdk"
|
||||
import { Context } from "../shared-context"
|
||||
import {
|
||||
CampaignDTO,
|
||||
CampaignBudgetUsageContext,
|
||||
ComputeActionContext,
|
||||
ComputeActions,
|
||||
CreatePromotionDTO,
|
||||
@@ -34,6 +35,7 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* computed actions.
|
||||
*
|
||||
* @param {UsageComputedActions[]} computedActions - The computed actions to adjust their promotion's campaign budget.
|
||||
* @param {CampaignBudgetUsageContext} registrationContext - The context of the campaign budget usage.
|
||||
* @returns {Promise<void>} Resolves when the campaign budgets have been adjusted successfully.
|
||||
*
|
||||
* @example
|
||||
@@ -48,13 +50,17 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* },
|
||||
* ])
|
||||
*/
|
||||
registerUsage(computedActions: UsageComputedActions[]): Promise<void>
|
||||
registerUsage(
|
||||
computedActions: UsageComputedActions[],
|
||||
registrationContext: CampaignBudgetUsageContext
|
||||
): Promise<void>
|
||||
|
||||
/**
|
||||
* This method is used to revert the changes made by registerUsage action
|
||||
*
|
||||
* @param {UsageComputedActions[]} computedActions - The computed actions to adjust their promotion's campaign budget.
|
||||
* @returns {Promise<void>} Resolves when the campaign budgets have been adjusted successfully.
|
||||
* @param {CampaignBudgetUsageContext} registrationContext - The context of the campaign budget usage.
|
||||
* @returns {Promise<void>} Resolves when the campaign budgets have been reverted successfully.
|
||||
*
|
||||
* @example
|
||||
* await promotionModuleService.revertUsage([
|
||||
@@ -68,7 +74,10 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* },
|
||||
* ])
|
||||
*/
|
||||
revertUsage(computedActions: UsageComputedActions[]): Promise<void>
|
||||
revertUsage(
|
||||
computedActions: UsageComputedActions[],
|
||||
registrationContext: CampaignBudgetUsageContext
|
||||
): Promise<void>
|
||||
|
||||
/**
|
||||
* This method provides the actions to perform on a cart based on the specified promotions
|
||||
@@ -276,12 +285,12 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* ```
|
||||
*
|
||||
* To specify relations that should be retrieved within the promotions:
|
||||
*
|
||||
*
|
||||
* :::note
|
||||
*
|
||||
*
|
||||
* You can only retrieve data models defined in the same module. To retrieve linked data models
|
||||
* from other modules, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query) instead.
|
||||
*
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* ```ts
|
||||
@@ -336,12 +345,12 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* ```
|
||||
*
|
||||
* To specify relations that should be retrieved within the promotions:
|
||||
*
|
||||
*
|
||||
* :::note
|
||||
*
|
||||
*
|
||||
* You can only retrieve data models defined in the same module. To retrieve linked data models
|
||||
* from other modules, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query) instead.
|
||||
*
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* ```ts
|
||||
@@ -396,12 +405,12 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* ```
|
||||
*
|
||||
* To specify relations that should be retrieved:
|
||||
*
|
||||
*
|
||||
* :::note
|
||||
*
|
||||
*
|
||||
* You can only retrieve data models defined in the same module. To retrieve linked data models
|
||||
* from other modules, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query) instead.
|
||||
*
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* ```ts
|
||||
@@ -744,12 +753,12 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* ```
|
||||
*
|
||||
* To specify relations that should be retrieved within the promotion rules:
|
||||
*
|
||||
*
|
||||
* :::note
|
||||
*
|
||||
*
|
||||
* You can only retrieve data models defined in the same module. To retrieve linked data models
|
||||
* from other modules, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query) instead.
|
||||
*
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* ```ts
|
||||
@@ -826,12 +835,12 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* ```
|
||||
*
|
||||
* To specify relations that should be retrieved within the campaigns:
|
||||
*
|
||||
*
|
||||
* :::note
|
||||
*
|
||||
*
|
||||
* You can only retrieve data models defined in the same module. To retrieve linked data models
|
||||
* from other modules, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query) instead.
|
||||
*
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* ```ts
|
||||
@@ -886,12 +895,12 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* ```
|
||||
*
|
||||
* To specify relations that should be retrieved within the campaigns:
|
||||
*
|
||||
*
|
||||
* :::note
|
||||
*
|
||||
*
|
||||
* You can only retrieve data models defined in the same module. To retrieve linked data models
|
||||
* from other modules, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query) instead.
|
||||
*
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* ```ts
|
||||
@@ -946,12 +955,12 @@ export interface IPromotionModuleService extends IModuleService {
|
||||
* ```
|
||||
*
|
||||
* To specify relations that should be retrieved:
|
||||
*
|
||||
*
|
||||
* :::note
|
||||
*
|
||||
*
|
||||
* You can only retrieve data models defined in the same module. To retrieve linked data models
|
||||
* from other modules, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query) instead.
|
||||
*
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* ```ts
|
||||
|
||||
@@ -38,6 +38,8 @@ export enum PromotionRuleOperator {
|
||||
export enum CampaignBudgetType {
|
||||
SPEND = "spend",
|
||||
USAGE = "usage",
|
||||
USE_BY_ATTRIBUTE = "use_by_attribute",
|
||||
SPEND_BY_ATTRIBUTE = "spend_by_attribute",
|
||||
}
|
||||
|
||||
export enum ComputedActions {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { BigNumberInput } from "@medusajs/types"
|
||||
import { ApplicationMethodAllocation, ApplicationMethodType, } from "../../promotion"
|
||||
import {
|
||||
ApplicationMethodAllocation,
|
||||
ApplicationMethodType,
|
||||
} from "../../promotion"
|
||||
import { MathBN } from "../math"
|
||||
import { MEDUSA_EPSILON } from "../big-number"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user