| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Inventory (stock)
• Invoicing (account) • Discuss (mail) • Purchase (purchase) |
| Lines of code | 460 |
| Technical Name |
suite_data_guard |
| License | OPL-1 |
| Website | https://suitestate.com |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Inventory (stock)
• Invoicing (account) • Discuss (mail) • Purchase (purchase) |
| Lines of code | 460 |
| Technical Name |
suite_data_guard |
| License | OPL-1 |
| Website | https://suitestate.com |
Data Guard
Protect data, not block operations — ORM-level document protection for Odoo 19
The Problem
Odoo lets users freely edit Sales Orders after delivery, modify Purchase Orders after receipt, reset posted invoices to draft, and reset payments to draft even within a locked fiscal period — creating silent data mismatches between your orders, warehouse, and books.
You need protection that guards the data without locking down your workflow.
Two Anchors, One Guard
Data Guard uses two different anchoring strategies tailored to how each business area actually operates:
- Sales & Purchase Orders — anchored on actual delivered / received quantity per line.
- Accounting documents — anchored on the fiscal lock date.
Daily operations stay free and unobstructed, while improper edits to completed data are blocked at the ORM level — not just hidden in the UI.
Settings
One toggle in General Settings. Enable to activate all protections. Disable temporarily for administrator-level corrections, then re-enable. No module reinstall required.
Sales & Purchase Order Protection
Protection is per-line, based on actual stock movement quantity (qty_delivered / qty_received). Only lines with qty > 0 are locked. Cancel, reset to draft, adding new lines, and editing undelivered lines remain fully available. If a warehouse return brings the qty back to zero, protection lifts automatically.
Per-line protection matrix
| Action | Line with qty > 0 | Line with qty = 0 |
|---|---|---|
| Edit product, UoM, unit price | Blocked | Allowed |
| Reduce quantity | Cannot go below delivered/received | Allowed |
| Increase quantity | Allowed | Allowed |
| Delete line | Blocked | Allowed |
| Add new lines | Always allowed | |
| Cancel / Reset to Draft | Always allowed | |
| Edit partner, currency (header) | Blocked when ANY line has qty > 0 | |
Stock Picking Source Enforcement
Receipts and deliveries containing storable products must originate from a Purchase Order, Sales Order, or a valid return. Manual pickings without a source document are blocked at validation — preventing rogue stock movements that corrupt your inventory data. Consignment receipts (with an Owner assigned) and internal transfers are exempt.
Journal Entry & Invoice Protection
Posted invoices, bills, and credit notes within the fiscal lock period cannot be reset to draft. Invoice and bill lines linked to a SO or PO are checked for quantity and price mismatches — discrepancies trigger a warning banner and list-view highlighting. Standalone invoices/bills without a source order are not covered by mismatch detection and should be reviewed manually.
Payment Protection (Native Gap Fix)
Odoo 19 decoupled payments from journal entries — native lock dates do not prevent resetting a payment to draft. This module closes that gap: any non-draft, non-canceled payment within the lock period cannot be reset to draft (covers in_process, paid, and rejected states).
Lock Date Protection & Dashboard
All five lock date fields are protected while Data Guard is enabled: fiscalyear_lock_date, tax_lock_date, sale_lock_date, purchase_lock_date, hard_lock_date.
Only users in the dedicated "Data Guard: Lock Date Manager" group can modify these fields. This group is independent — it is NOT inherited by Accounting Administrator and must be assigned explicitly. A Lock Date Dashboard under Accounting > Configuration shows all current lock dates in one place.
Full Protection Summary
| Document | Trigger | What Is Protected | What Is NOT Blocked |
|---|---|---|---|
| Sales Order | qty_delivered > 0 | Header: partner, currency, company. Line: product, UoM, price. Qty floor. No delete. | Cancel, reset to draft, add lines, edit undelivered lines, increase qty |
| Purchase Order | qty_received > 0 | Header: partner, currency, company. Line: product, UoM, price. Qty floor. No delete. | Cancel, reset to draft, add lines, edit unreceived lines, increase qty |
| Stock Picking | Validation | Storable products require PO / SO source or valid return | Consignment (with Owner), internal transfers |
| Invoice / Bill | Fiscal lock date | Cannot reset to draft within locked period. SO/PO-linked lines checked for mismatch. | Current-period invoices are free. Standalone (no SO/PO) not mismatch-checked. |
| Payment | Fiscal lock date | Cannot reset to draft within locked period (native gap fix) | Current-period payments are free |
| Lock Dates (x5) | Guard enabled | Only Lock Date Manager group can modify | Lock Date Manager users can always adjust |
Key Features
- ORM-level protection — cannot be bypassed via UI tricks, API calls, or imports
- Per-line granularity — only lines with actual stock moves are locked
- Auto-unlock on return — qty back to zero lifts all protection
- Stock Picking source enforcement for storable products
- Invoice / SO / PO mismatch detection with visual warnings
- Multi-company aware — each company uses its own lock date
- All 5 lock date fields protected with dedicated manager group
- Lock Date Dashboard for at-a-glance status
- Global on / off toggle in Settings
- Zero dependencies beyond native Odoo modules
Why Not Just Hide the Buttons?
Many "protection" modules simply hide UI elements with CSS or view
inheritance. Users can still modify data via API calls, imports,
automated actions, or developer mode. Data Guard operates at the
ORM level — write(),
unlink(), and action methods are intercepted before any
change reaches the database.
Technical Notes
- No new models — pure
_inheriton existing Odoo models. - No scheduled actions, no background jobs, no performance overhead.
- Protection is synchronous and immediate on every write / unlink / action.
- Dependencies:
sale_stock,purchase_stock,account,account_payment,stock(all native Odoo). - Compatible with Odoo 19.0 Community and Enterprise.
- Emergency bypass: pass
suite_force_unlock: Truein ORM context.
License & support
Licensed under OPL-1 (Odoo Proprietary License v1).
Maintained by SuiteState (ElectroState FZCO).
For questions, bug reports, or feature requests, visit
suitestate.com or contact
hello@suitestate.com.
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