Skip to content

Conversation

fPolic
Copy link
Contributor

@fPolic fPolic commented Oct 6, 2025

What

  • limit promotion use per promo code

@fPolic fPolic requested a review from a team as a code owner October 6, 2025 12:41
Copy link

changeset-bot bot commented Oct 6, 2025

⚠️ No Changeset found

Latest commit: fdf6a19

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

vercel bot commented Oct 6, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

8 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
api-reference Ignored Ignored Oct 9, 2025 2:31pm
api-reference-v2 Ignored Ignored Preview Oct 9, 2025 2:31pm
cloud-docs Ignored Ignored Preview Oct 9, 2025 2:31pm
docs-ui Ignored Ignored Preview Oct 9, 2025 2:31pm
docs-v2 Ignored Ignored Preview Oct 9, 2025 2:31pm
medusa-docs Ignored Ignored Preview Oct 9, 2025 2:31pm
resources-docs Ignored Ignored Preview Oct 9, 2025 2:31pm
user-guide Ignored Ignored Preview Oct 9, 2025 2:31pm

"title": "Usage",
"description": "Set a limit on how many times the promotion can be used."
},
"use_by_attribute": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why snake case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EDIT: some properties are snake and others are camel... huh haha

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, will fix that

? t("campaigns.budget.fields.limitBudgetAttributeCustomer")
: t("campaigns.budget.fields.limitBudgetAttributeEmail")
? t("campaigns.budget.fields.totalUsedByAttribute", {
attribute: campaign.budget?.attribute,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The attribute here will always be in English even if we get the translation from another language right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is the name of the attribute, it can be anything user defines in theory

Comment on lines 419 to 423
const attributeValue = (
attribute === "promotion_code"
? registrationContext[attribute]
: promotion.code
) as string | null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: Tbh. I am not a huge fan of this; it feels dirty to have hard-coded exceptions like this in the code.

I think we should consider adding a limit directly on the promotion as an alternative solution. That limit could be combined with a campaign budget to solve this use case.

I am curious to hear what you and others think @medusajs/os

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context, the use case we are trying to solve here is:

Some of our users would like to create a single campaign called Customer Service Promos under which their team can create one-time promotions for individual customers. However, the current implementation prevents this because the limit applies at the campaign level rather than per promotion. They are once again left with creating a new campaign for recurring customers (i.e. customers that have already received a code from the campaign in the past).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah wasn't happy with that either.

Wdyt about modifying CampaignBudgetUsageContext to have scopes that are applied per promotion, for example:

export type CampaignBudgetUsageContext = {
 /** applied on all promotions **/
  customer_id: string | null
  customer_email: string | null

   /** applied only on matching promotions **/  
  promotions_context: {
    [promo_id]: {
      code: string | null
    }
  }
}

Then, when we iterate over promotions when computing actions or registering usage, we merge the context that is scoped for that promotion?

@fPolic fPolic force-pushed the feat/limit-promotion-promo-code branch from 6653df7 to cf767f1 Compare October 9, 2025 12:45
@fPolic fPolic changed the base branch from feat/limit-promotion-per-customer-data-model to develop October 9, 2025 12:45
@fPolic fPolic force-pushed the feat/limit-promotion-promo-code branch from cf767f1 to 2c5985a Compare October 9, 2025 12:48
@fPolic fPolic changed the title feat(dashboard, promotion): limit promotion use per promo code feat(core-flows, promotion): limit promotion use per promo code Oct 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants