From 66c6c5af8e563e0f70a0e90db9fc2d909433490f Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Thu, 15 Jan 2026 09:36:53 +0700 Subject: [PATCH] feat: Preserve quality check states and allow pre-lot checks for receipt operations by modifying quality.check and stock.move.line logic. --- .gitignore | 16 ++ README.md | 156 ++---------------- __init__.py | 0 __manifest__.py | 0 __pycache__/__init__.cpython-312.pyc | Bin 234 -> 216 bytes __pycache__/__manifest__.cpython-312.pyc | Bin models/__init__.py | 0 models/__pycache__/__init__.cpython-312.pyc | Bin 287 -> 269 bytes .../__pycache__/quality_check.cpython-312.pyc | Bin 8313 -> 9134 bytes .../stock_move_line.cpython-312.pyc | Bin 5452 -> 5484 bytes models/quality_check.py | 31 ++++ models/stock_move_line.py | 0 tests/__init__.py | 0 tests/__pycache__/__init__.cpython-312.pyc | Bin .../test_basic_functionality.cpython-312.pyc | Bin .../test_edge_cases.cpython-312.pyc | Bin .../test_integration.cpython-312.pyc | Bin ...t_property_lot_propagation.cpython-312.pyc | Bin .../test_property_lot_update.cpython-312.pyc | Bin ...erty_non_receipt_operation.cpython-312.pyc | Bin ...property_receipt_operation.cpython-312.pyc | Bin ...rty_relationship_integrity.cpython-312.pyc | Bin ...roperty_state_preservation.cpython-312.pyc | Bin tests/test_basic_functionality.py | 0 tests/test_edge_cases.py | 0 tests/test_integration.py | 0 tests/test_property_lot_propagation.py | 0 tests/test_property_lot_update.py | 0 tests/test_property_non_receipt_operation.py | 0 tests/test_property_receipt_operation.py | 0 tests/test_property_relationship_integrity.py | 0 tests/test_property_state_preservation.py | 0 32 files changed, 57 insertions(+), 146 deletions(-) create mode 100644 .gitignore mode change 100644 => 100755 README.md mode change 100644 => 100755 __init__.py mode change 100644 => 100755 __manifest__.py mode change 100644 => 100755 __pycache__/__manifest__.cpython-312.pyc mode change 100644 => 100755 models/__init__.py mode change 100644 => 100755 models/quality_check.py mode change 100644 => 100755 models/stock_move_line.py mode change 100644 => 100755 tests/__init__.py mode change 100644 => 100755 tests/__pycache__/__init__.cpython-312.pyc mode change 100644 => 100755 tests/__pycache__/test_basic_functionality.cpython-312.pyc mode change 100644 => 100755 tests/__pycache__/test_edge_cases.cpython-312.pyc mode change 100644 => 100755 tests/__pycache__/test_integration.cpython-312.pyc mode change 100644 => 100755 tests/__pycache__/test_property_lot_propagation.cpython-312.pyc mode change 100644 => 100755 tests/__pycache__/test_property_lot_update.cpython-312.pyc mode change 100644 => 100755 tests/__pycache__/test_property_non_receipt_operation.cpython-312.pyc mode change 100644 => 100755 tests/__pycache__/test_property_receipt_operation.cpython-312.pyc mode change 100644 => 100755 tests/__pycache__/test_property_relationship_integrity.cpython-312.pyc mode change 100644 => 100755 tests/__pycache__/test_property_state_preservation.cpython-312.pyc mode change 100644 => 100755 tests/test_basic_functionality.py mode change 100644 => 100755 tests/test_edge_cases.py mode change 100644 => 100755 tests/test_integration.py mode change 100644 => 100755 tests/test_property_lot_propagation.py mode change 100644 => 100755 tests/test_property_lot_update.py mode change 100644 => 100755 tests/test_property_non_receipt_operation.py mode change 100644 => 100755 tests/test_property_receipt_operation.py mode change 100644 => 100755 tests/test_property_relationship_integrity.py mode change 100644 => 100755 tests/test_property_state_preservation.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f2b0a61 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python + +# Odoo +*.pot +*.po + +# Editor +.vscode/ +.idea/ +*.swp +*~ diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 5b6bffa..f4a3ef3 --- a/README.md +++ b/README.md @@ -1,153 +1,17 @@ # Quality Check Lot Preserve ## Overview +This module preserves the state of Quality Checks (`quality.check`) when lot numbers are assigned during receipt operations. It is designed to support workflows where quality checks are performed *before* or *during* the assignment of Lot/Serial numbers. -This module modifies the standard Odoo 18 quality check behavior for receipt operations to preserve quality check states when lot numbers are assigned after quality checks have been completed. - -## Problem Statement - -In standard Odoo, when a quality check is completed before a lot number is assigned, the quality check automatically resets to "Todo" state when the lot number is later assigned. This creates inefficiency in warehouse operations where: - -1. Quality checks are performed immediately upon receipt -2. Lot numbers are generated or assigned later in the process -3. Quality checks must be re-done unnecessarily - -## Solution - -This module provides the following functionality: - -### 1. State Preservation -- Quality check states (Pass, Fail, In Progress) are preserved when lot numbers are assigned -- Applies only to receipt operations (incoming shipments) -- Other operation types (manufacturing, internal transfers, delivery) continue with standard Odoo behavior - -### 2. Automatic Lot Number Synchronization -- Lot numbers assigned to stock move lines are automatically copied to related quality checks -- Lot number changes are synchronized in real-time -- Maintains traceability between inventory and quality records - -### 3. Selective Application -- Custom behavior applies only to receipt operations -- Standard Odoo workflows remain unchanged for other operation types -- Seamless integration with existing quality control processes - -## Installation - -1. Copy this module to your Odoo addons directory (e.g., `customaddons/quality_check_lot_preserve`) -2. Update the apps list in Odoo -3. Install the "Quality Check Lot Preserve" module - -## Dependencies - -- `stock` - Odoo Inventory Management -- `quality_control` - Odoo Quality Control (Enterprise module) - -**Note:** This module requires Odoo Enterprise edition as it depends on the `quality_control` module. - -## Usage - -### Typical Workflow - -1. **Receive Products**: Create a purchase order and validate the receipt -2. **Perform Quality Checks**: Complete quality checks immediately upon receipt (before lot assignment) -3. **Assign Lot Numbers**: Generate or manually assign lot numbers to the stock move lines -4. **Result**: Quality check states remain unchanged, and lot numbers are automatically copied to quality checks - -### Example Scenario - -**Before this module:** -- Receive 100 units of Product A -- Complete quality check → Status: "Pass" -- Assign lot number "LOT001" -- Quality check resets → Status: "Todo" ❌ -- Must re-do quality check - -**With this module:** -- Receive 100 units of Product A -- Complete quality check → Status: "Pass" -- Assign lot number "LOT001" -- Quality check remains → Status: "Pass" ✓ -- Lot number automatically copied to quality check ✓ +## Features +- **Preserve Check State**: Prevents Quality Checks from generating new checks or resetting their state (Pass/Fail) when a user assigns a Lot Number to a move line. +- **Allow Pre-Lot Checks**: Overrides default strict Odoo behavior to allow Quality Checks to be initiated and processed on Receipt operations even if the tracked product does not yet have a Lot/Serial Number assigned. ## Technical Details +- Overrides `quality.check` `_is_to_do()` to permit checks on receipts without lots. +- Overrides `stock.move.line` `_create_check()` to prevent duplicates. +- Uses custom state preservation logic during `write()` operations on quality checks and move lines. -### Extended Models - -#### stock.move.line -- Monitors `lot_id` and `lot_name` field changes -- Identifies related quality checks for receipt operations -- Triggers quality check lot number updates - -#### quality.check -- Prevents state resets during lot assignment for receipt operations -- Accepts lot number updates from stock move lines -- Maintains standard behavior for non-receipt operations - -### Operation Type Detection - -The module identifies receipt operations by checking: -- `picking_type_code == 'incoming'` -- Fallback to `picking_id.picking_type_id.code` - -### Data Flow - -``` -Stock Move Line (Lot Assigned) - ↓ -Detect Change (write method) - ↓ -Find Related Quality Checks - ↓ -Check Operation Type (Receipt?) - ↓ Yes -Copy Lot Number + Preserve State - ↓ -Update Quality Check -``` - -### Security and Access Rights - -This module extends existing Odoo models (`stock.move.line` and `quality.check`) without creating new models or data structures. Therefore: - -- **No new access rights are required** -- Access rights are inherited from the base modules (`stock` and `quality_control`) -- Users with existing quality control and inventory permissions can use this module -- The `security/ir.model.access.csv` file is present but empty (only contains the header row) - -The module respects all existing Odoo security rules and group permissions. - -## Configuration - -No additional configuration is required. The module works automatically once installed. - -## Compatibility - -- **Odoo Version**: 18.0 -- **Edition**: Enterprise (requires quality_control module) -- **Database**: PostgreSQL - -## Limitations - -- Only applies to receipt operations (incoming shipments) -- Requires the quality_control Enterprise module -- Does not modify historical quality check records - -## Support - -For issues, questions, or feature requests, please contact your Odoo implementation partner or system administrator. - -## License - -LGPL-3 - -## Author - -Your Company - -## Version History - -### 1.0.0 (Initial Release) -- State preservation for quality checks during lot assignment -- Automatic lot number synchronization -- Receipt operation filtering -- Full integration with standard Odoo quality control workflows +## Dependencies +- `quality_control` +- `stock` diff --git a/__init__.py b/__init__.py old mode 100644 new mode 100755 diff --git a/__manifest__.py b/__manifest__.py old mode 100644 new mode 100755 diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc index 61d7d610c708632c9e75f40e4a0ad5db37fe4349..9a92657fae3b72dc03a784c7e8180d7cbdd20d1b 100644 GIT binary patch delta 37 rcmaFGc!QDqG%qg~0}yEBIZfma;tST#$j?pHFD}hUElR1JSepv~zYhy+ delta 55 zcmcb?_==JHG%qg~0}!yTP@Bjdq>!qgk)NBYUtF4zT9i_$SDBccpX896Sdf^fmz=Mc JnKCgu7XZhe5&ZxF diff --git a/__pycache__/__manifest__.cpython-312.pyc b/__pycache__/__manifest__.cpython-312.pyc old mode 100644 new mode 100755 diff --git a/models/__init__.py b/models/__init__.py old mode 100644 new mode 100755 diff --git a/models/__pycache__/__init__.cpython-312.pyc b/models/__pycache__/__init__.cpython-312.pyc index 160066d8d2924dbf613d7756ddbf5613c09b3977..c638e97a4e69bf03693b19bdf26ddd6511bef9a4 100644 GIT binary patch delta 37 rcmbQw)XT(unwOW00SGknoF;PD@UqRmjoL$j?pHFD}hUElR1>t4vJJPjbjjEJ)1LOU~EJ JOqn>X900Lu5!nC$ diff --git a/models/__pycache__/quality_check.cpython-312.pyc b/models/__pycache__/quality_check.cpython-312.pyc index 07996a62f6b728faa17633eeace99172c1a6fc63..2fd69849445da32ef16ff479e0998b2de746a45a 100644 GIT binary patch delta 746 zcmX|9&rcIU6rO2m?eA@9DYc7sYTA$r(kMm@X@WsPF9wMP6Jp$~-NCMu9WuKu7B?ve zP0GPQSre|9c+$iR7mwaNcxw1gzbTDY}k5?=TVQ5iA7wJePILu zI$}V3#HGVBq_AQ$_U*l}k72}k84J(qw)gNvO=ZbSmlo(~11M9HN+)W>49#{!-~+p~y8wM4N%l(uJy5~-Be1X-fimTkWvt3tkj^9$nR zBBsdds-CejZY!e^K_clc8nPnYr*%R{Ms53!W5SZ0U%(O_U}dWHw(NSVG|U`2&R``n zT@s73R=H^n8afsJY?ap-{9XkIF5vdBb8Fn5t9q6ZU$E&-ncmc%x1X_KxXC3HMgH3+aD$x zyZChXj~H^~;L$C3&M^bO1BRPua(Ie$SRX-6FgUP72#=fqrc97LbUw1f8Mtw6D_hV0 J0>|Wdz(2v6&Tjw! delta 107 zcmZ4I{?mc)G%qg~0}#yFrJgxWaU$O&#+r!>%egujDj1{qf*CZqH|sIxu`=3k-piIH z!KBGQSwX30@~Og2?^V|1Tfqbx06&%_wQIKgbX%|x583}8-? H7|?V8q;MVK diff --git a/models/__pycache__/stock_move_line.cpython-312.pyc b/models/__pycache__/stock_move_line.cpython-312.pyc index 6d9566767cce1def44b76351e3bf7ca9afa7bb66..b087a4c34ce15804fbd72e1ed4858f354921cdb1 100644 GIT binary patch delta 71 zcmX@3^+t>PG%qg~0}yEDIc?-#$;^0b@>XU|AbFp8uVSKpMt*LpesO6=YEeq1en4eO YMt)v$eoCr-eoB76p@shDxh(4i09$bx2mk;8 delta 39 tcmaE(bw-Q(G%qg~0}v$bRNu(Gl9}<>