Skip to content

Conversation

@fPolic
Copy link
Contributor

@fPolic fPolic commented Oct 15, 2025

What

  • define promotion usage limit directly on promotion (without campaign)

Note

Adds promotion usage limits (limit/used) with backend enforcement and tracking, admin create/display UI, type updates, DB migration, and integration tests.

  • Backend/API:
    • Add limit and used to promotion; expose in admin responses (query-config).
    • Enforce limits in computeActions (emit promotionLimitExceeded) and on usage registration/revert; increment/decrement used on order completion/revert.
    • Validation: disallow limits on is_automatic promos; prevent lowering limit below current used.
    • Update validators and service logic; extend computed actions enum.
  • Admin Dashboard:
    • Promotion create form: new limit field; schema validation; i18n strings.
    • Promotion detail: display Usage Limit as used / limit.
  • Types/Utils:
    • Extend promotion and payload DTOs with limit/used; add promotionLimitExceeded action.
  • Database:
    • Migration adds limit (nullable int) and used (int, default 0) to promotion; model/snapshot updated.
  • Tests:
    • New integration tests covering creation, usage increment, limit enforcement, update validation, and interaction with campaign budgets.

Written by Cursor Bugbot for commit f488408. This will update automatically on new commits. Configure here.

@changeset-bot
Copy link

changeset-bot bot commented Oct 15, 2025

🦋 Changeset detected

Latest commit: f488408

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 74 packages
Name Type
@medusajs/promotion Patch
@medusajs/dashboard Patch
@medusajs/types Patch
@medusajs/utils Patch
@medusajs/medusa Patch
integration-tests-http Patch
@medusajs/admin-bundler Patch
@medusajs/draft-order Patch
@medusajs/framework Patch
@medusajs/js-sdk Patch
@medusajs/modules-sdk Patch
@medusajs/orchestration Patch
@medusajs/workflows-sdk Patch
@medusajs/medusa-oas-cli Patch
@medusajs/cli Patch
@medusajs/test-utils Patch
@medusajs/analytics Patch
@medusajs/api-key Patch
@medusajs/auth Patch
@medusajs/cache-inmemory Patch
@medusajs/cache-redis Patch
@medusajs/caching Patch
@medusajs/cart Patch
@medusajs/currency Patch
@medusajs/customer Patch
@medusajs/event-bus-local Patch
@medusajs/event-bus-redis Patch
@medusajs/file Patch
@medusajs/fulfillment Patch
@medusajs/index Patch
@medusajs/inventory Patch
@medusajs/link-modules Patch
@medusajs/locking Patch
@medusajs/notification Patch
@medusajs/order Patch
@medusajs/payment Patch
@medusajs/pricing Patch
@medusajs/product Patch
@medusajs/region Patch
@medusajs/sales-channel Patch
@medusajs/settings Patch
@medusajs/stock-location Patch
@medusajs/store Patch
@medusajs/tax Patch
@medusajs/user Patch
@medusajs/workflow-engine-inmemory Patch
@medusajs/workflow-engine-redis Patch
@medusajs/analytics-local Patch
@medusajs/analytics-posthog Patch
@medusajs/auth-emailpass Patch
@medusajs/auth-github Patch
@medusajs/auth-google Patch
@medusajs/caching-redis Patch
@medusajs/file-local Patch
@medusajs/file-s3 Patch
@medusajs/fulfillment-manual Patch
@medusajs/locking-postgres Patch
@medusajs/locking-redis Patch
@medusajs/notification-local Patch
@medusajs/notification-sendgrid Patch
@medusajs/payment-stripe Patch
@medusajs/core-flows Patch
@medusajs/oas-github-ci Patch
@medusajs/deps Patch
@medusajs/telemetry Patch
@medusajs/admin-sdk Patch
@medusajs/admin-shared Patch
@medusajs/admin-vite-plugin Patch
@medusajs/icons Patch
@medusajs/toolbox Patch
@medusajs/ui-preset Patch
create-medusa-app Patch
medusa-dev-cli Patch
@medusajs/ui Patch

Not sure what this means? Click here to learn what changesets are.

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

@vercel
Copy link

vercel bot commented Oct 15, 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 Nov 17, 2025 9:46am
api-reference-v2 Ignored Ignored Preview Nov 17, 2025 9:46am
cloud-docs Ignored Ignored Preview Nov 17, 2025 9:46am
docs-ui Ignored Ignored Preview Nov 17, 2025 9:46am
docs-v2 Ignored Ignored Preview Nov 17, 2025 9:46am
medusa-docs Ignored Ignored Preview Nov 17, 2025 9:46am
resources-docs Ignored Ignored Preview Nov 17, 2025 9:46am
user-guide Ignored Ignored Preview Nov 17, 2025 9:46am

@fPolic fPolic changed the title proposal: promotion usage limit feat: promotion usage limit Oct 16, 2025
@fPolic fPolic marked this pull request as ready for review October 16, 2025 16:32
@fPolic fPolic requested a review from a team as a code owner October 16, 2025 16:32
cursor[bot]

This comment was marked as outdated.

id: promotion.id,
used: newUsedValue,
})
}
Copy link

Choose a reason for hiding this comment

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

Bug: Race Condition in Promotion Usage Limit Checks

Race condition in promotion usage limit check: The promotion usage limit is checked by reading the current used value and comparing it with limit, then later updating the database. However, if multiple concurrent requests complete orders with the same promotion code, they could all pass the limit check before any of them updates the database, allowing the promotion to be used more times than the limit allows. For example, if limit is 10 and used is 9, two concurrent requests could both see used=9, pass the check (9+1 <= 10), and both complete successfully, resulting in used=11 which exceeds the limit of 10.

Fix in Cursor Fix in Web

message: "Automatic promotions cannot have a usage limit",
path: ["limit"],
}
)
Copy link

Choose a reason for hiding this comment

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

Bug: Incomplete Validation Allows Invalid Promotion State

Validation gap allows automatic promotions to have usage limits when updated separately. The refinement only validates fields in the current update request, not the combination with existing promotion state. A promotion with limit: 5 can be updated to is_automatic: true, or vice versa, bypassing the "Automatic promotions cannot have a usage limit" rule. The validation needs to consider both the incoming update data and the existing promotion's current values.

Fix in Cursor Fix in Web

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.

2 participants