306 lines
12 KiB
Python
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")
|