| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Inventory (stock)
• Point of Sale (point_of_sale) • Sales (sale_management) • Discuss (mail) • Invoicing (account) |
| Lines of code | 1216 |
| Technical Name |
negative_stock_restriction |
| License | OPL-1 |
| Versions | 17.0 18.0 19.0 |
📦 Negative Stock Restriction
Prevent negative inventory across Stock Transfers, Point of Sale, and Sale Orders — with real-time POS stock badges, manager PIN override, and per-product/category/warehouse exceptions.
📋 Overview
Negative Stock Restriction is a comprehensive inventory safeguard for Odoo 18. It prevents your stock from going negative across three key areas: Stock Transfers (delivery orders), Point of Sale, and Sale Order confirmation.
Choose between Hard Block (completely prevents the action) or Soft Warning (shows a warning but allows proceeding). Configure which quantity to check — On Hand, Available, or Forecast — and set granular exceptions at the product, category, or warehouse level.
In the POS, real-time color-coded stock badges appear on every product card, updating instantly after each sale. Out-of-stock products can be auto-hidden, and managers can override blocks with a PIN when needed.
📸 screenshot_overview.png — Full settings page with all options visible
⭐ Key Features
- ✓ Hard Block or Soft Warning: Choose to completely prevent negative stock or just warn the user and let them decide
- ✓ 3 Quantity Types: Check against On Hand, Available (on hand − reserved), or Forecast (available + incoming − outgoing)
- ✓ Stock Transfers: Block/warn on delivery orders when the move would cause negative stock
- ✓ Point of Sale: Block Pay and Validate buttons with stock check — includes bilingual EN/AR messages
- ✓ Sale Orders: Check stock on SO confirmation with warehouse-aware quantities
- ✓ Real-Time POS Badges: Green / Yellow / Red stock quantity badges on every product card
- ✓ Instant Refresh After Sale: Badges update immediately after each completed order — no session restart needed
- ✓ Auto-Hide Out-of-Stock: Optionally hide products with zero or negative stock from POS product list
- ✓ Low Stock Threshold: Configurable threshold — yellow badge when stock is running low
- ✓ Manager PIN Override: Managers can enter a PIN to override hard blocks in POS
- ✓ Per-Product Exceptions: Allow specific products to go negative (e.g. services sold as storable)
- ✓ Per-Category Exceptions: Exempt entire product categories from the restriction
- ✓ Per-Warehouse Exceptions: Allow specific warehouses to go negative (e.g. transit warehouses)
- ✓ Bypass Security Group: Authorized users can bypass restrictions entirely
- ✓ Manual Stock Check Button: Dedicated button in POS to check stock levels for current order
- ✓ Configurable Refresh Interval: Set how often POS badges auto-refresh (default 15s, or 0 to disable)
⚡ How It Works
|
🛒
Action Pay / Confirm / Deliver |
→ |
🔍
Check Stock Compare qty vs demand |
→ |
🚫
Block / Warn Hard block or soft warning |
→ |
🔑
Override Manager PIN or bypass group |
Where It Checks
| Area | Trigger Point | Hard Block | Soft Warning |
|---|---|---|---|
| Stock Transfers | _action_done() on outgoing moves |
UserError raised | Warning logged |
| Point of Sale | Pay button + Validate button | Error popup (or PIN override) | Confirm popup |
| Sale Orders | action_confirm() |
UserError raised | Warning logged + chatter note |
Exception Priority
Before blocking, the module checks exceptions in this order. If any exception is found, the product is skipped:
| 1 | Warehouse — allow_negative_stock on the warehouse |
| 2 | Product — allow_negative_stock on the product template or variant |
| 3 | Category — allow_negative_stock on the product category |
🏷️ POS Real-Time Stock Badges
When enabled, every product card in the POS displays a color-coded badge showing the current stock level at the POS location:
Refresh Triggers
| Trigger | When |
|---|---|
| After every sale | Badges refresh ~1.5s after order validation completes |
| Tab visibility | When user switches back to the POS browser tab |
| Auto-refresh interval | Configurable (default 15 seconds, set to 0 to disable) |
| Category switch | Badges re-applied when DOM changes (search, scroll, category) |
🛒 POS Payment & Validation Blocking
Hard Block Mode
When a cashier clicks Pay or Validate, the module checks stock for all order lines. If any product has insufficient stock and is not exempt, the action is completely blocked.
📸 screenshot_pos_hard_block.png — Hard block error popup showing insufficient stock details
Soft Warning Mode
In soft mode, a confirmation popup appears instead. The cashier can choose to proceed or cancel.
Manager PIN Override
When enabled, hard-blocked orders show a Manager Override popup instead of a flat error. A manager enters their PIN to authorize the sale.
Manual Stock Check Button
A red "فحص المخزون / Stock Check" button is added to the POS product screen. Click it anytime to see stock levels for all items in the current order.
📦 Stock Transfer Blocking
When validating a delivery order (outgoing stock move from internal location to customer/external), the module checks if the transfer would cause negative stock. Only outgoing moves are checked — internal transfers, receipts, and returns are unaffected.
📝 Sale Order Confirmation Blocking
When a salesperson clicks Confirm on a Sale Order, the module checks stock for every line against the order's warehouse. In soft mode, a warning is posted to the order chatter so there's a record of the low-stock confirmation.
📥 Installation
Requirements
| Requirement | Details |
|---|---|
| Odoo Version | 18.0 (Community & Enterprise) |
| Depends On |
stock,
point_of_sale,
sale_management
|
| Python Libraries | None (standard Odoo only) |
| License | LGPL-3 |
Steps
| 1 | Upload the module Copy negative_stock_restriction into your Odoo addons directory. |
| 2 | Update Apps List Go to Apps → Update Apps List |
| 3 | Install Search for "Negative Stock Restriction" and click Install. |
./odoo-bin -u negative_stock_restriction -d your_database --stop-after-init
⚙️ Configuration
Settings
Go to Settings → Inventory → Negative Stock Restriction
| Setting | Default | Description |
|---|---|---|
| Enable Negative Stock Restriction | ✅ On | Master toggle — turns the entire module on/off |
| Restriction Mode | Hard Block | Hard Block = prevent action | Soft Warning = warn and allow |
| Restrict in Stock Transfers | ✅ On | Check stock on delivery order validation |
| Restrict in Point of Sale | ✅ On | Check stock on POS Pay/Validate |
| Restrict in Sale Orders | ✅ On | Check stock on SO confirmation |
| Low Stock Warning Threshold | 5 | Yellow badge threshold in POS |
| Stock Quantity Type | Available | On Hand | Available (on hand − reserved) | Forecast |
| Show Stock on POS Product Cards | ✅ On | Display color-coded badges on product cards |
| Auto-Hide Out-of-Stock in POS | ❌ Off | Hide products with stock ≤ 0 from POS |
| POS Stock Refresh Interval | 15 sec | Auto-refresh period (0 = only after sales) |
| Allow Manager Override | ❌ Off | Enable PIN override in Hard Block mode |
| Manager Override PIN | 0000 | PIN required to override (displayed as dots) |
Security Groups
Go to Settings → Users & Companies → Users and assign groups in the Inventory section:
| Group | Effect |
|---|---|
| Bypass Negative Stock Restriction | User completely skips all restrictions (hard block becomes soft, soft proceeds silently) |
| Negative Stock Manager Override | User can enter the manager PIN to override hard blocks in POS |
Per-Entity Exceptions
Add the "Allow Negative Stock" toggle on individual records:
| Where | Location |
|---|---|
| Product | Product form → General Information section (only visible for storable products) |
| Category | Product Category form → first group |
| Warehouse | Warehouse form → "Negative Stock" section |
📊 Quantity Types Explained
| Type | Formula | Best For |
|---|---|---|
| On Hand | Total physical stock in the location | Simple retail / POS where reservations don't matter |
| Available Default | On Hand − Reserved quantities | Most businesses — accounts for pending orders |
| Forecast | Available + Incoming − Outgoing | When you want to allow sales against expected receipts |
❓ Frequently Asked Questions
Do I need to restart the POS session to see updated stock?
No. Stock badges refresh automatically after every completed sale (~1.5s delay), when you switch back to the POS tab, and on a configurable interval (default 15 seconds). You never need to close/reopen the session.
Can a cashier bypass the hard block?
Only if they are in the Bypass group (skips entirely) or if Manager Override is enabled and someone with the Manager Override group enters the correct PIN. Regular cashiers cannot proceed.
What happens if the network is down during a POS stock check?
The module is designed to fail open — if the stock check RPC call fails (network error, timeout), the sale is allowed to proceed. This prevents the POS from becoming unusable due to connectivity issues.
Does this work with multi-warehouse / multi-location POS?
Yes. The module uses the POS config's source location (from the operation type) to determine which location to check. Each POS can point to a different warehouse/location and will check the correct stock.
Are consumable / service products affected?
No. Only storable products (type = 'product') are checked.
Consumables and services always show as unlimited stock (9999999) and are never blocked.
What about lot/serial tracked products?
Stock transfers check lot-specific availability when lots are assigned to the move. In POS and SO, the check uses the overall product availability at the location.
🤝 Support
For questions, bug reports, or feature requests:
./odoo-bin -u negative_stock_restriction -d your_database --stop-after-init
Negative Stock Restriction v18.0.2.0.0 · LGPL-3 · Odoo 18.0
Made with ❤️ for Odoo
Odoo Proprietary License v1.0 This software and associated files (the "Software") may only be used (executed, modified, executed after modifications) if you have purchased a valid license from the authors, typically via Odoo Apps, or if you have received a written agreement from the authors of the Software (see the COPYRIGHT file). You may develop Odoo modules that use the Software as a library (typically by depending on it, importing it and using its resources), but without copying any source code or material from the Software. You may distribute those modules under the license of your choice, provided that this license is compatible with the terms of the Odoo Proprietary License (For example: LGPL, MIT, or proprietary licenses similar to this one). It is forbidden to publish, distribute, sublicense, or sell copies of the Software or modified copies of the Software. The above copyright notice and this permission notice must be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Please log in to comment on this module