feat: Preserve quality check states and allow pre-lot checks for receipt operations by modifying quality.check and stock.move.line logic.

This commit is contained in:
Suherdy Yacob 2026-01-15 09:36:53 +07:00
parent c5cd69b33a
commit 66c6c5af8e
32 changed files with 57 additions and 146 deletions

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
# Odoo
*.pot
*.po
# Editor
.vscode/
.idea/
*.swp
*~

156
README.md Normal file → Executable file
View File

@ -1,153 +1,17 @@
# Quality Check Lot Preserve # Quality Check Lot Preserve
## Overview ## 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. ## 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.
## Problem Statement - **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.
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 ✓
## Technical Details ## 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 ## Dependencies
- `quality_control`
#### stock.move.line - `stock`
- 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

0
__init__.py Normal file → Executable file
View File

0
__manifest__.py Normal file → Executable file
View File

Binary file not shown.

0
__pycache__/__manifest__.cpython-312.pyc Normal file → Executable file
View File

0
models/__init__.py Normal file → Executable file
View File

31
models/quality_check.py Normal file → Executable file
View File

@ -195,3 +195,34 @@ class QualityCheck(models.Model):
) )
# Invalidate cache to ensure the updated values are reflected # Invalidate cache to ensure the updated values are reflected
self.invalidate_recordset(['quality_state', 'user_id', 'control_date']) self.invalidate_recordset(['quality_state', 'user_id', 'control_date'])
def _is_to_do(self, checkable_products, check_picked=False):
"""
Override to allow quality checks on receipt operations even if lot is not yet assigned.
"""
self.ensure_one()
# If this is a receipt operation, we want to allow the check even if lot is missing
# because our module supports assigning the lot later or during the check
if self._is_receipt_operation():
# Standard logic from quality_control.quality_check._is_to_do
# but skipping the lot requirement for tracked products on receipt
if self.quality_state != 'none':
return False
if self.measure_on != 'operation':
if self.product_id not in checkable_products:
return False
if self.move_line_id:
if not self.move_line_id._is_checkable(check_picked):
return False
# This is the part we're effectively skipping for receipt operations:
# "Only process qc related to tracked product if its lot is set"
# We skip this check because we want to allow it.
return True
# For non-receipt operations, fall back to standard behavior
return super(QualityCheck, self)._is_to_do(checkable_products, check_picked)

0
models/stock_move_line.py Normal file → Executable file
View File

0
tests/__init__.py Normal file → Executable file
View File

0
tests/__pycache__/__init__.cpython-312.pyc Normal file → Executable file
View File

View File

0
tests/__pycache__/test_edge_cases.cpython-312.pyc Normal file → Executable file
View File

0
tests/__pycache__/test_integration.cpython-312.pyc Normal file → Executable file
View File

View File

View File

View File

View File

View File

View File

0
tests/test_basic_functionality.py Normal file → Executable file
View File

0
tests/test_edge_cases.py Normal file → Executable file
View File

0
tests/test_integration.py Normal file → Executable file
View File

0
tests/test_property_lot_propagation.py Normal file → Executable file
View File

0
tests/test_property_lot_update.py Normal file → Executable file
View File

0
tests/test_property_non_receipt_operation.py Normal file → Executable file
View File

0
tests/test_property_receipt_operation.py Normal file → Executable file
View File

0
tests/test_property_relationship_integrity.py Normal file → Executable file
View File

0
tests/test_property_state_preservation.py Normal file → Executable file
View File