quality_check_lot_preserve/tests/test_integration.py
2025-11-27 10:00:38 +07:00

306 lines
12 KiB
Python

# -*- coding: utf-8 -*-
from odoo.tests.common import TransactionCase
class TestIntegration(TransactionCase):
"""Integration tests for quality check lot preservation end-to-end workflows"""
def setUp(self):
super(TestIntegration, self).setUp()
# Get model references
self.StockMoveLine = self.env['stock.move.line']
self.QualityCheck = self.env['quality.check']
self.Product = self.env['product.product']
self.StockLocation = self.env['stock.location']
self.StockPicking = self.env['stock.picking']
self.StockPickingType = self.env['stock.picking.type']
self.StockMove = self.env['stock.move']
self.StockLot = self.env['stock.lot']
self.QualityPoint = self.env['quality.point']
self.Partner = self.env['res.partner']
# Create test product
self.product = self.Product.create({
'name': 'Test Product for Integration',
'type': 'consu',
'tracking': 'lot',
})
# Get or create locations
self.location_supplier = self.env.ref('stock.stock_location_suppliers')
self.location_stock = self.env.ref('stock.stock_location_stock')
# Get picking types
self.picking_type_in = self.env.ref('stock.picking_type_in')
# Create test supplier
self.supplier = self.Partner.create({
'name': 'Test Supplier',
})
# Get or create a quality team
self.quality_team = self.env['quality.alert.team'].search([], limit=1)
if not self.quality_team:
self.quality_team = self.env['quality.alert.team'].create({
'name': 'Test Quality Team',
})
# Get test type
self.test_type = self.env.ref('quality_control.test_type_passfail', raise_if_not_found=False)
if not self.test_type:
self.test_type = self.env['quality.point.test_type'].create({
'name': 'Pass/Fail Test',
'technical_name': 'passfail',
})
# Create quality point for the product
self.quality_point = self.QualityPoint.create({
'product_ids': [(4, self.product.id)],
'picking_type_ids': [(4, self.picking_type_in.id)],
'test_type_id': self.test_type.id,
'team_id': self.quality_team.id,
})
def _create_receipt_picking(self):
"""Helper to create a receipt picking"""
return self.StockPicking.create({
'picking_type_id': self.picking_type_in.id,
'location_id': self.location_supplier.id,
'location_dest_id': self.location_stock.id,
'partner_id': self.supplier.id,
})
def _create_stock_move(self, picking, qty=1.0):
"""Helper to create a stock move"""
return self.StockMove.create({
'name': 'Test Move',
'product_id': self.product.id,
'product_uom_qty': qty,
'product_uom': self.product.uom_id.id,
'picking_id': picking.id,
'location_id': picking.location_id.id,
'location_dest_id': picking.location_dest_id.id,
})
def _create_move_line(self, move, lot_id=False):
"""Helper to create a stock move line"""
return self.StockMoveLine.create({
'move_id': move.id,
'product_id': self.product.id,
'product_uom_id': self.product.uom_id.id,
'location_id': move.location_id.id,
'location_dest_id': move.location_dest_id.id,
'picking_id': move.picking_id.id,
'lot_id': lot_id,
'quantity': 1.0,
})
def _create_lot(self, name):
"""Helper to create a lot"""
return self.StockLot.create({
'name': name,
'product_id': self.product.id,
'company_id': self.env.company.id,
})
# Subtask 8.1: Create end-to-end receipt workflow test
def test_end_to_end_receipt_workflow(self):
"""
End-to-end test: Create receipt, generate quality checks,
complete quality checks before lot assignment, assign lot numbers,
verify quality check states are preserved and lot numbers are copied.
Requirements: 1.1, 2.1, 3.1
"""
# Step 1: Create receipt picking
receipt = self._create_receipt_picking()
self.assertEqual(receipt.picking_type_id.code, 'incoming',
"Picking should be a receipt operation")
# Create stock move
move = self._create_stock_move(receipt, qty=5.0)
# Step 2: Confirm the picking and create move line
receipt.action_confirm()
# Create move line
move_line = self._create_move_line(move)
# Create quality check manually
quality_check = self.QualityCheck.create({
'product_id': self.product.id,
'picking_id': receipt.id,
'move_line_id': move_line.id,
'test_type_id': self.test_type.id,
'quality_state': 'none',
'team_id': self.quality_team.id,
})
# Step 3: Complete quality checks before lot assignment
initial_state = 'pass'
quality_check.write({'quality_state': initial_state})
self.assertEqual(quality_check.quality_state, initial_state,
"Quality check should be marked as pass")
self.assertFalse(quality_check.lot_id,
"Quality check should not have lot assigned yet")
self.assertFalse(move_line.lot_id,
"Move line should not have lot assigned yet")
# Step 4: Assign lot numbers to stock move lines
lot = self._create_lot('LOT-E2E-001')
move_line.write({'lot_id': lot.id})
# Step 5: Verify quality check states are preserved
self.assertEqual(quality_check.quality_state, initial_state,
"Quality check state should be preserved after lot assignment")
# Step 6: Verify lot numbers are copied to quality checks
self.assertEqual(quality_check.lot_id.id, lot.id,
"Lot number should be copied to quality check")
# Additional verification: Ensure the relationship is intact
self.assertEqual(quality_check.move_line_id.id, move_line.id,
"Quality check should still be linked to move line")
def test_end_to_end_receipt_workflow_with_fail_state(self):
"""
End-to-end test with quality check in 'fail' state.
Verify fail state is preserved after lot assignment.
Requirements: 1.1, 1.2, 2.1
"""
# Create receipt picking
receipt = self._create_receipt_picking()
move = self._create_stock_move(receipt, qty=3.0)
receipt.action_confirm()
# Create move line
move_line = self._create_move_line(move)
# Create quality check and mark as fail
quality_check = self.QualityCheck.create({
'product_id': self.product.id,
'picking_id': receipt.id,
'move_line_id': move_line.id,
'test_type_id': self.test_type.id,
'quality_state': 'fail',
'team_id': self.quality_team.id,
})
# Assign lot number
lot = self._create_lot('LOT-E2E-FAIL-001')
move_line.write({'lot_id': lot.id})
# Verify fail state is preserved
self.assertEqual(quality_check.quality_state, 'fail',
"Fail state should be preserved after lot assignment")
self.assertEqual(quality_check.lot_id.id, lot.id,
"Lot should be assigned to quality check")
# Subtask 8.2: Create lot number change workflow test
def test_lot_number_change_workflow(self):
"""
Test lot number change workflow: Create receipt with quality check and initial lot,
change lot number on stock move line, verify quality check is updated with new lot,
verify quality check state remains unchanged.
Requirements: 3.1, 3.2
"""
# Step 1: Create receipt with quality check and initial lot number
receipt = self._create_receipt_picking()
move = self._create_stock_move(receipt, qty=2.0)
receipt.action_confirm()
# Create move line
move_line = self._create_move_line(move)
# Create initial lot and assign it
initial_lot = self._create_lot('LOT-CHANGE-INITIAL')
move_line.write({'lot_id': initial_lot.id})
# Create quality check with pass state
quality_check = self.QualityCheck.create({
'product_id': self.product.id,
'picking_id': receipt.id,
'move_line_id': move_line.id,
'test_type_id': self.test_type.id,
'quality_state': 'pass',
'lot_id': initial_lot.id,
'team_id': self.quality_team.id,
})
initial_state = quality_check.quality_state
self.assertEqual(initial_state, 'pass',
"Quality check should be in pass state")
self.assertEqual(quality_check.lot_id.id, initial_lot.id,
"Quality check should have initial lot")
# Step 2: Change lot number on stock move line
new_lot = self._create_lot('LOT-CHANGE-NEW')
move_line.write({'lot_id': new_lot.id})
# Step 3: Verify quality check is updated with new lot number
self.assertEqual(quality_check.lot_id.id, new_lot.id,
"Quality check should be updated with new lot number")
# Step 4: Verify quality check state remains unchanged
self.assertEqual(quality_check.quality_state, initial_state,
"Quality check state should remain unchanged after lot change")
# Additional verification: Ensure the relationship is intact
self.assertEqual(quality_check.move_line_id.id, move_line.id,
"Quality check should still be linked to move line")
def test_lot_number_change_workflow_multiple_changes(self):
"""
Test multiple lot number changes in sequence.
Verify quality check is updated each time and state is preserved.
Requirements: 3.1, 3.2
"""
# Create receipt with quality check
receipt = self._create_receipt_picking()
move = self._create_stock_move(receipt, qty=1.0)
receipt.action_confirm()
# Create move line
move_line = self._create_move_line(move)
# Create quality check with fail state
quality_check = self.QualityCheck.create({
'product_id': self.product.id,
'picking_id': receipt.id,
'move_line_id': move_line.id,
'test_type_id': self.test_type.id,
'quality_state': 'fail',
'team_id': self.quality_team.id,
})
initial_state = 'fail'
# First lot assignment
lot1 = self._create_lot('LOT-MULTI-CHANGE-001')
move_line.write({'lot_id': lot1.id})
self.assertEqual(quality_check.lot_id.id, lot1.id,
"Quality check should have first lot")
self.assertEqual(quality_check.quality_state, initial_state,
"State should be preserved after first change")
# Second lot change
lot2 = self._create_lot('LOT-MULTI-CHANGE-002')
move_line.write({'lot_id': lot2.id})
self.assertEqual(quality_check.lot_id.id, lot2.id,
"Quality check should have second lot")
self.assertEqual(quality_check.quality_state, initial_state,
"State should be preserved after second change")
# Third lot change
lot3 = self._create_lot('LOT-MULTI-CHANGE-003')
move_line.write({'lot_id': lot3.id})
self.assertEqual(quality_check.lot_id.id, lot3.id,
"Quality check should have third lot")
self.assertEqual(quality_check.quality_state, initial_state,
"State should be preserved after third change")