Workflows
This documentation provides a reference to the batchVendorPromotionRulesWorkflow. It belongs to the @mercurjs/b2c-core package.
This workflow performs batch operations on promotion rules, including creating and deleting rules. When creating target rules, it validates that the seller owns all products being targeted by the rules.
Source code
Examples
packages/modules/b2c-core/src/api/vendor/promotions/[id]/target-rules/batch/route.ts
import {
AuthenticatedMedusaRequest ,
MedusaResponse
} from '@medusajs/framework/http'
import { ContainerRegistrationKeys , RuleType } from '@medusajs/framework/utils'
import { fetchSellerByAuthActorId } from '../../../../../../shared/infra/http/utils'
import { batchVendorPromotionRulesWorkflow } from '../../../../../../workflows/promotions/workflows'
import { VendorBatchPromotionRulesType } from '../../../validators'
export const POST = async (
req : AuthenticatedMedusaRequest < VendorBatchPromotionRulesType >,
res : MedusaResponse
) => {
const query = req . scope . resolve ( ContainerRegistrationKeys . QUERY )
const id = req . params . id
const seller = await fetchSellerByAuthActorId (
req . auth_context . actor_id ,
req . scope
)
await batchVendorPromotionRulesWorkflow ( req . scope ). run ({
input: {
data: {
id ,
rule_type: RuleType . TARGET_RULES ,
create: req . validatedBody . create ,
delete: req . validatedBody . delete
},
seller_id: seller . id
}
})
const {
data : [ promotion ]
} = await query . graph ({
entity: 'promotion' ,
fields: req . queryConfig . fields ,
filters: {
id: req . params . id
}
})
res . json ({ promotion })
}
Steps
verifyVendorTargetPromotionRulesStep : Validates seller ownership of products in target rules (only for target_rules type).
batchPromotionRulesWorkflow : Creates and deletes promotion rules using Medusa’s core workflow.
The batch promotion rules operation details. data
BatchPromotionRulesWorkflowInput
required
The batch operation data. The type of rules to batch. Available types:
rules - Standard promotion rules
target_rules - Target rules (product targeting)
buy_rules - Buy X get Y rules
create
CreatePromotionRuleDTO[]
required
Array of rules to create. The attribute to match (e.g., “items.product.id”).
The operator for the rule (e.g., “in”, “eq”).
values
string | string[]
required
The values to match against.
Optional description of the rule.
Array of rule IDs to delete.
The ID of the seller performing the operation.
Output
This workflow does not return a value.
This documentation provides a reference to the createVendorPromotionWorkflow. It belongs to the @mercurjs/b2c-core package.
This workflow creates a promotion for a seller and links it to the seller. It validates that the seller owns the campaign (if specified), that the promotion uses the correct target type, and that all targeted products belong to the seller.
Source code
Examples
packages/modules/b2c-core/src/api/vendor/promotions/route.ts
import { AuthenticatedMedusaRequest , MedusaResponse } from '@medusajs/framework'
import { ContainerRegistrationKeys } from '@medusajs/framework/utils'
import { fetchSellerByAuthActorId } from '../../../shared/infra/http/utils'
import { createVendorPromotionWorkflow } from '../../../workflows/promotions/workflows'
import { VendorCreatePromotionType } from './validators'
export const POST = async (
req : AuthenticatedMedusaRequest < VendorCreatePromotionType >,
res : MedusaResponse
) => {
const query = req . scope . resolve ( ContainerRegistrationKeys . QUERY )
const seller = await fetchSellerByAuthActorId (
req . auth_context ?. actor_id ,
req . scope
)
const { result } = await createVendorPromotionWorkflow . run ({
container: req . scope ,
input: { promotion: req . validatedBody , seller_id: seller . id }
})
const {
data : [ promotion ]
} = await query . graph ({
entity: 'promotion' ,
fields: req . queryConfig . fields ,
filters: {
id: result [ 0 ]. id
}
})
res . status ( 201 ). json ({ promotion })
}
Steps
verifyVendorCampaignStep : Validates that the campaign (if specified) belongs to the seller.
verifyVendorPromotionStep : Validates that the promotion uses the correct target type (items only).
verifyVendorTargetPromotionRulesStep : Validates that all targeted products belong to the seller.
createPromotionsWorkflow : Creates the promotion using Medusa’s core workflow.
createRemoteLinkStep : Links the promotion (and optionally the campaign) to the seller.
The promotion creation details. promotion
CreatePromotionDTO
required
The promotion details. The promotion code (e.g., “SUMMER2024”).
The type of the promotion. For vendors, must be standard.
Whether the promotion is applied automatically. Default: false.
The status of the promotion. Available statuses:
draft - Promotion is in draft mode
active - Promotion is active
inactive - Promotion is inactive
The ID of the campaign to associate with (must be seller’s own campaign).
Inline campaign creation data.
The application method configuration. type
ApplicationMethodType
required
The discount type. For vendors, must be percentage.
target_type
ApplicationMethodTargetType
required
The target type. For vendors, must be items.
The percentage discount value.
allocation
ApplicationMethodAllocation
required
How the discount is allocated:
each - Applied to each item
across - Applied across all items
target_rules
CreatePromotionRuleDTO[]
required
Rules defining which products the promotion targets.
Maximum quantity of items the promotion can be applied to.
Number of items to apply the discount to.
Minimum quantity to buy for “Buy X Get Y” promotions.
Description of the application method.
Standard promotion rules (conditions for applying the promotion).
The ID of the seller creating the promotion.
Output
Array containing the created promotion. The type of the promotion.
The status of the promotion.
Whether the promotion is applied automatically.
The ID of the associated campaign.
The associated campaign details.
The date the promotion was created.
The date the promotion was last updated.
This documentation provides a reference to the updateVendorPromotionWorkflow. It belongs to the @mercurjs/b2c-core package.
This workflow updates an existing promotion. It validates that any new campaign association belongs to the seller.
Source code
Examples
packages/modules/b2c-core/src/api/vendor/promotions/[id]/route.ts
import { AuthenticatedMedusaRequest , MedusaResponse } from '@medusajs/framework'
import { ContainerRegistrationKeys } from '@medusajs/framework/utils'
import { fetchSellerByAuthActorId } from '../../../../shared/infra/http/utils'
import { updateVendorPromotionWorkflow } from '../../../../workflows/promotions/workflows'
import { VendorUpdatePromotionType } from '../validators'
export const POST = async (
req : AuthenticatedMedusaRequest < VendorUpdatePromotionType >,
res : MedusaResponse
) => {
const query = req . scope . resolve ( ContainerRegistrationKeys . QUERY )
const seller = await fetchSellerByAuthActorId (
req . auth_context . actor_id ,
req . scope
)
await updateVendorPromotionWorkflow . run ({
container: req . scope ,
input: {
promotion: {
id: req . params . id ,
... req . validatedBody
},
seller_id: seller . id
}
})
const {
data : [ promotion ]
} = await query . graph ({
entity: 'promotion' ,
fields: req . queryConfig . fields ,
filters: {
id: req . params . id
}
})
res . status ( 200 ). json ({ promotion })
}
Steps
verifyVendorCampaignStep : Validates that the campaign (if being updated) belongs to the seller.
updatePromotionsWorkflow : Updates the promotion using Medusa’s core workflow.
The promotion update details. promotion
UpdatePromotionDTO
required
The promotion update data. The ID of the promotion to update.
Whether the promotion should be applied automatically.
The new status (draft, active, or inactive).
The ID of a campaign to associate with.
Updates to the application method. The new percentage discount value.
The new maximum quantity.
The new apply to quantity.
The new buy rules minimum quantity.
The ID of the seller updating the promotion.
Output
Array containing the updated promotion.
Steps
registerUsageStep
Registers promotion usage when a promotion is applied to a cart. This step tracks how many times a promotion code has been used and includes a compensation function to revert the usage if the order is not completed.
Source code
Examples
packages/modules/b2c-core/src/workflows/cart/workflows/split-and-complete-cart.ts
import { registerUsageStep } from "../../promotions/steps" ;
// ... inside splitAndCompleteCartWorkflow
const promotionUsage = transform (
{ lineItemAdjustments , shippingAdjustments },
({ lineItemAdjustments , shippingAdjustments }) => {
const promotionUsage = [];
for ( const adjustment of lineItemAdjustments ) {
promotionUsage . push ({
amount: adjustment . amount ,
code: adjustment . code ! ,
});
}
for ( const adjustment of shippingAdjustments ) {
promotionUsage . push ({
amount: adjustment . amount ,
code: adjustment . code ! ,
});
}
return promotionUsage ;
}
);
registerUsageStep ( promotionUsage );
data
UsageComputedActions[]
required
Array of promotion usage records to register. The discount amount applied.
The promotion code that was used.
Output
This step does not return a value.
verifyVendorCampaignStep
Validates that a campaign belongs to the seller. If no campaign is specified, the validation is skipped.
Source code
The promotion data. The ID of the campaign to verify.
Output
Throws an INVALID_DATA error if the campaign doesn’t belong to the seller.
Validates that a vendor promotion uses the correct target type. Vendor promotions must target items only, not shipping or order totals.
Source code
promotion
CreatePromotionDTO
required
The promotion data to validate.
Output
Throws an INVALID_DATA error if the target_type is not “items”.
Validates that target promotion rules only use the allowed attribute (items.product.id) and that all targeted products belong to the seller. This ensures vendors can only create promotions for their own products.
Source code
Array of target rules to validate.
Output
Throws an INVALID_DATA error if:
Rules use attributes other than “items.product.id”
Any targeted product doesn’t belong to the seller