Sales Quantity Limitation Extension for Magento2.x
Sales Quantity Limit - Feature Overview
Fair, automatic purchase limits per product and time period - enforced in the cart and checkout.
What Is It
Sales Quantity Limit lets you cap how much of a product a customer may buy per day, week, month, quarter, year or over their lifetime. Limits are set directly on the product, checked against the customer's real order history and enforced the moment a quantity is added or changed in the cart.
Key Features
🎯 Per-Product Limits
- Set a time period and a maximum quantity on each product
- Limits can differ per website
- Products without a limit are not affected
🗓️ Flexible Time Periods
- Day, week, month, quarter, year or lifetime
- Counts all orders in the current period; canceled orders are not counted
👥 Choose Who the Limit Applies To
- Per customer
- Per account relation or per company (when the matching Enobis / Proline modules are installed)
- Combined scopes such as company and customer
🛒 Enforced in the Cart
- Quantity changes are checked immediately
- Clear messages tell the customer the maximum available quantity and the period limit
- Works for simple and virtual products and for bundle components
- Quantities of the same product spread over several cart lines are added up
👀 Transparent for Customers
- Optional display of the remaining quantity on the product page
- Messages translated into German, English, French, Italian, Spanish, Polish and Russian
⚙️ Simple to Operate
- One switch to enable, one setting for the scope
- Own ACL resource to restrict who may change the settings
Who Is It For
| Target group | Benefit |
|---|---|
| B2B shops with contingents | Limit annual or monthly quantities per customer or company |
| Shops with scarce or regulated goods | Prevent hoarding and bulk buying |
| Promotions and special offers | Cap quantity per customer and period |
| Shop operators | No manual order checking |
How It Works
Product: limit value + period
|
Customer changes cart quantity
|
Module sums non-canceled orders in the current period (per scope)
|
Requested qty > remaining qty?
|-- yes --> cart error message with the maximum quantity
'-- no --> order can proceed
Integrations & Requirements
- Magento 2 (Framework 102.0.7+ / 103.0.3+), PHP 8.1 - 8.3
- Optional: Enobis Account Relation Switcher, Ecoplan Proline (extra scopes)
Use Cases
(inferred from the functionality - please review)
- A supplier allows each customer 100 units of a product per quarter
- A promotional item may be bought once per customer (lifetime)
- A company shares one monthly quota across all its users
Sales Quantity Limit - by Enobis
Sales Quantity Limit - Documentation
Table of Contents
- Requirements
- Installation
- Configuration
- Product attributes
- Features and behavior
- Scopes
- Data model
- Routes, events and extension points
- Security and permissions
- Localization
- Troubleshooting
1. Requirements
| Requirement | Version |
|---|---|
| PHP | ~8.1.0 | ~8.2.0 | ~8.3.0 |
| magento/framework | ^102.0.7 | ^103.0.3 |
| magento/module-backend | >= 102.0 |
| magento/module-catalog | >= 102.0 |
| Enobis_AccountRelationSwitcher | optional, needed for scopes relation* |
| Ecoplan_Proline | optional, needed for scopes company* |
The module is loaded after Magento_Catalog and Magento_Backend.
2. Installation
composer require enobis/module-sales-quantity-limit
bin/magento module:enable Enobis_SalesQuantityLimit
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
setup:upgrade creates the two product attributes (section 4).
3. Configuration
Path: Stores > Configuration > Enobis > Sales Quantity Limit. Visible in Default and Website scope.
About
| Field | Description |
|---|---|
| Module Version | Read-only information field |
| Composer Version | Read-only information field |
General
| Field | Config path | Type | Default | Scope | Description |
|---|---|---|---|---|---|
| Enabled | sales_quantity_limit/general/enabled |
Yes/No | No | Default, Website | Master switch. When off, no limit is evaluated and no error is added |
| Scope | sales_quantity_limit/general/scope |
Select | Customer | Default, Website | Whose orders are counted (section 6). Only shown when Enabled = Yes |
| Show Available Period Qty | sales_quantity_limit/general/show_available_period_qty |
Yes/No | No | Default, Website | Shows the remaining quantity on the product page. Only shown when Enabled = Yes |
4. Product attributes
Both attributes are created in the attribute group "General" with website scope, are not required and are available in product listings.
| Code | Label | Type | Input | Position |
|---|---|---|---|---|
sales_qty_limit_period |
Sales Qty Limit Period | varchar | Select | 120 |
sales_qty_limit_value |
Sales Qty Limit Value | decimal | Text | 130 |
Options for the period: NONE (empty), Day, Week, Month, Quarter, Year, Lifetime (stored values day, week, month, quarter, year, lifetime).
A product is limited only when the period is set and the module is enabled. Both attributes are included in the quote-item attribute group so they are available on cart items.
5. Features and behavior
Limit check in the cart
The check runs on the event sales_quote_item_qty_set_after whenever the quantity of a quote item is set.
- It is skipped when the module is disabled, for items without a product, and when the quote is in super mode (
is_super_mode, e.g. admin order creation). - The ordered quantity of the product in the current period is the sum of
qty_orderedoversales_order_itemof all orders whose status is notcanceled, filtered by the scope (section 6). - Remaining quantity = limit value - ordered quantity (minimum 0).
- If the requested row quantity, or the total quantity of the same product across several cart lines, exceeds the remaining quantity, an error is set on the cart item and the quote. The message names the maximum available quantity, the product name, the limit and the period.
- For bundle products, each selected option product that has a limit is checked with option quantity multiplied by cart quantity.
- A custom registry flag
sales_quantity_limitation_skip_applydisables the check for the current request.
Time periods
Orders are grouped by their creation date: day (Y-m-d), week, month (Y-m), quarter (Y-Qn), year (Y), lifetime (all orders). The current period is determined from the current date.
Display on product pages
When "Show Available Period Qty" is enabled, products of type simple, virtual and bundle show:
- "Available Period Qty: n / Period" - remaining quantity in the period
- "Available Total Qty: n" - shown only when the limitation data contains extended quantity information (
qty_extend)
The data is loaded by a POST AJAX request to salesquantitylimit/product/ajaxlimitation. The request does not trigger a customer-section reload.
6. Scopes
The scope decides which orders are counted. Every scope adds a filter on a column of sales_order.
| Scope value | Label | Filter column | Requires |
|---|---|---|---|
customer |
Customer | customer_id (guests: 0) |
- |
relation |
Relation | active_relation |
Enobis_AccountRelationSwitcher |
relation/customer |
Relation/Customer | active_relation and customer_id |
Enobis_AccountRelationSwitcher |
company |
Company | proline_company_id |
Ecoplan_Proline |
company/customer |
Company/Customer | proline_company_id and customer_id |
Ecoplan_Proline |
Scopes starting with relation or company appear in the dropdown only when the respective module is enabled. The columns active_relation and proline_company_id must exist on sales_order (provided by those modules).
7. Data model
The module adds no tables or columns. It adds two product EAV attributes (section 4) and reads sales_order and sales_order_item.
8. Routes, events and extension points
| Type | Identifier | Description |
|---|---|---|
| Frontend route | salesquantitylimit |
frontName |
| Controller | salesquantitylimit/product/ajaxlimitation |
POST, XHR only, JSON body {"productId": n}. Returns error, productId, productSku, productStatus, productAvailable and limitation (time_period, qty, value, scope, qty_base, qty_ordered, qty_available, qty_left). HTTP 400 for invalid requests |
| Observed event | sales_quote_item_qty_set_after |
Observer salesQuantityLimit |
| Dispatched event | sales_quantity_limit_controller_product_ajax_limitation |
Data: product, limitation, transport, request. Observers may change transport->response |
| DI | Enobis\SalesQuantityLimit\Model\Limitation\Scope |
Argument scopes lists the available scopes; additional scopes can be added via di.xml |
| Catalog attributes | group quote_item |
sales_qty_limit_period, sales_qty_limit_value |
| JS | Magento_Customer/js/section-config mixin |
Excludes the AJAX URL from section invalidation |
| Layout | catalog_product_view_type_simple, _virtual, _bundle |
Adds the available-quantity block to the product page |
9. Security and permissions
- ACL resource
Enobis_SalesQuantityLimit::config_sales_quantity_limit("Sales Quantity Limit Section") controls access to the configuration section (under Stores > Settings > Configuration). - The AJAX controller accepts only POST requests with XHR header and returns only the limit data of the requested product for the current customer/scope.
- The module is disabled by default.
10. Localization
Translations are included for de_DE, en_US, es_ES, fr_FR, it_IT, pl_PL and ru_RU.
11. Troubleshooting
| Symptom | Check |
|---|---|
| No limit is enforced | Module enabled for the website? Period set on the product (value not NONE) in the right website scope? Value set? |
| Relation/Company scopes missing in dropdown | The respective optional module must be enabled |
| Remaining quantity not shown on product page | "Show Available Period Qty" enabled; product has a limit; product type is simple, virtual or bundle; theme renders the product.info.*.extra container |
| Limits not applied in admin order creation | Quotes in super mode are not checked |
| Counts seem wrong | Canceled orders are not counted; all other statuses are. Check the selected scope |
| Settings not visible | Admin role needs the ACL resource for the Sales Quantity Limit section |
Changelog
1.2.2 (2026-10-13)
-
2026-10-13Support configurable products, add README config field (f47aa1a)Show the remaining period quantity for configurable products. The block now indexes limited child products by their super attribute values, and the JS requests limitation data for the selected variant (with response caching and ignoring outdated responses). A new layout file adds the block to configurable product pages, and the template passes the child index and period labels to the JS.
Also add an admin config field that renders the module README.md as HTML, add README, DOCUMENTATION, MARKETING and FINDINGS docs (FINDINGS is export-ignored), and bump the version to 1.2.2.
1.2.1 (2026-04-09)
-
2026-04-09Logging removed from the module (4d95f0f) -
2026-04-09Version: 1.2.1 (68e8754)- Logging removed from the module
1.2.0 (2026-03-20)
-
2026-03-20Tweak code (ddb40c5)Allow PHP
8.3Drop PHP7.4support -
2026-03-20Version 1.2.0 (d322a45)Allow PHP
8.3#14375
1.1.11 (2025-06-04)
-
2025-06-03- First use up the sales limit before it goes to the quota (3794966) -
2025-06-04Version: 1.1.11 (33a66cb)Fix:
- First use up the sales limit before it goes to the quota
1.1.10 (2025-05-26)
-
2025-05-26- Calculation logic adapted (dc5b907) -
2025-05-26Version: 1.1.10 (357d6db)Fix:
- Calculation logic adapted
1.1.9 (2025-05-23)
-
2025-05-23- Added the scope for queries (e9313dd) -
2025-05-23- Workaround so that the message section is not always reloaded for Ajax calls (1a8c280) -
2025-05-23Tweak code (fc4eed3) -
2025-05-23Version: 1.1.9 (28da0bf)Bugfix:
- Added the scope for queries
Optimisation:
- Workaround so that the message section is not always reloaded for Ajax calls
1.1.8 (2025-01-23)
-
2025-01-23Tweak code (7a3c90a) -
2025-01-23Introduce.gitattributesto exclude development files (1697694) -
2025-01-23PHP 8.2 support added (975967e) -
2025-01-23Version: 1.1.8 (9209e29)Optimization:
- PHP 8.2 support added
1.1.7 (2023-07-12)
-
2023-07-12add new period type "lifetime" (1d1279e) -
2023-07-12version 1.1.7 (2f11655)add new period type "lifetime"
1.1.6 (2023-03-09)
-
2023-03-09Version: 1.1.6 - Added Translation (3c6c4e2)Signed-off-by: karlbuedding-enobis karl.buedding@enobis.de
1.1.5 (2022-12-05)
-
2022-12-05Version: 1.1.5 - translations added (ee95d07)Signed-off-by: Karl Büdding karl.buedding@enobis.de
1.1.4 (2022-03-09)
-
2022-03-09Version: 1.1.4 - Translation added (893dc51)Signed-off-by: Karl Büdding karl.buedding@enobis.de
1.1.3 (2021-08-11)
-
2021-08-11Version 1.1.3 (c8d31a1)Optimisation;
- show available period qty on bundle product
1.1.2 (2020-12-18)
-
2020-12-18Version 1.1.2 (f0dd535)improvements show available period qty
1.1.1 (2020-12-17)
-
2020-12-17Version 1.1.1 (ca48f1d)improvements show available period qty
1.1.0 (2020-12-16)
-
2020-12-16Version 1.1.0 (7423942)show available period qty
1.0.2 (2020-12-16)
-
2020-05-29current spec (aebe9be) -
2020-06-08improve limitation validation process in cart to check composite products (bundle, etc.) too (7641a65) -
2020-06-08Merge branch 'composite-product-in-cart' (01f95e7) -
2020-06-08add about system configuration (28deb76) -
2020-06-08Version 1.0.0 (72c64fc)improve limitation validation process in cart to check composite products (bundle, etc.) too add about system configuration
-
2020-12-16re-add processing composite product in cart (grouped, bundle etc.) (ce5d1e6) -
2020-12-16Version 1.0.2 (29fd4c4)improve limitation validation process in cart to check composite products (bundle, etc.) too
1.0.1 (2020-12-07)
-
2020-12-07Version 0.1.6 (fa532cd)fix: sql unknown column error
-
2020-12-07Version 1.0.1 (b4a4ca7)fix: sql unknown column error
1.0.0 (2020-06-08)
-
2020-05-29current spec (aebe9be) -
2020-06-08improve limitation validation process in cart to check composite products (bundle, etc.) too (7641a65) -
2020-06-08Merge branch 'composite-product-in-cart' (01f95e7) -
2020-06-08add about system configuration (28deb76) -
2020-06-08Version 1.0.0 (72c64fc)improve limitation validation process in cart to check composite products (bundle, etc.) too add about system configuration
0.1.5 (2020-05-19)
-
2020-05-19Version 0.1.5 (a3ac2a3)fix: display wrong limitation qty for time period in error message
0.1.4 (2020-05-19)
-
2020-05-18fix: canceled orders not handled as expected (c5643b3) -
2020-05-18add product sku to limitation error messages (01690ab) -
2020-05-19Merge branch 'dev' (c2d10c0) -
2020-05-19Version 0.1.4 (a08a8cd)add product sku to limitation error messages fix: canceled orders not handled as expected
0.1.3 (2020-05-08)
-
2020-05-08Version 0.1.3 (e02ebf3)fix: fatal error on customer login
0.1.2 (2020-05-08)
-
2020-05-08add day time period (99936f7) -
2020-05-08fix: limitation not working when flat catalog enabled (3f21d9e) -
2020-05-08Version 0.1.2 (c96fe83)add day time period fix: limitation not working when flat catalog enabled
0.1.1 (2020-05-07)
-
2020-05-07fix: missing relation id when using limitation scope "relation" / "relation/customer" (67a4518) -
2020-05-07Version 0.1.1 (f880048)fix: missing relation id when using limitation scope "relation" / "relation/customer"
0.1.0 (2020-05-06)
-
2020-05-06Version 0.1.0 (2f9008b)first implementation
0.0.1 (2020-05-06)
2020-05-06base files (04f2c57)
README.md
Enobis Sales Quantity Limit
Limits how many units of a product a customer can order within a time period (day, week, month, quarter, year or lifetime) and shows the remaining quantity on the product page.
Facts
| Module name | Enobis_SalesQuantityLimit |
| Composer package | enobis/module-sales-quantity-limit |
| Package type | magento2-module |
| License | proprietary |
| Vendor / support | Enobis |
| Admin configuration | Stores > Configuration > Enobis > Sales Quantity Limit |
Requirements
- PHP 8.1, 8.2 or 8.3
- Magento Framework
^102.0.7 | ^103.0.3 magento/module-backend>= 102.0magento/module-catalog>= 102.0- Optional:
Enobis_AccountRelationSwitcher(scopes "Relation"),Ecoplan_Proline(scopes "Company")
Installation
composer require enobis/module-sales-quantity-limit
bin/magento module:enable Enobis_SalesQuantityLimit
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
Quick start
- Enable the module under Stores > Configuration > Enobis > Sales Quantity Limit > General.
- Choose the scope (who the limit applies to).
- Open a product, group "General": set Sales Qty Limit Period and Sales Qty Limit Value.
- Optionally enable "Show Available Period Qty" to display the remaining quantity on the product page.
Documentation
Documentation for all Enobis modules and themes is available at https://docs.enobis.de
- DOCUMENTATION.md - configuration, product attributes, behavior, troubleshooting
- MARKETING.md - feature overview