质量模块和库存扫码
This commit is contained in:
5
quality_control/tests/__init__.py
Normal file
5
quality_control/tests/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from . import test_common
|
||||
from . import test_picking_quality_check
|
||||
from . import test_purchase_quality_check
|
||||
38
quality_control/tests/test_common.py
Normal file
38
quality_control/tests/test_common.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestQualityCommon(common.TransactionCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
cls.product_category_base = cls.env.ref('product.product_category_1')
|
||||
cls.product_category_1 = cls.env['product.category'].create({
|
||||
'name': 'Office furnitures',
|
||||
'parent_id': cls.product_category_base.id
|
||||
})
|
||||
cls.product = cls.env['product.product'].create({
|
||||
'name': 'Office Chair',
|
||||
'categ_id': cls.product_category_1.id
|
||||
})
|
||||
cls.product_2 = cls.env['product.product'].create({
|
||||
'name': 'Test Product',
|
||||
'categ_id': cls.product_category_base.parent_id.id
|
||||
})
|
||||
cls.product_3 = cls.env['product.product'].create({
|
||||
'name': 'Another Test Product',
|
||||
'categ_id': cls.product_category_base.parent_id.id
|
||||
})
|
||||
cls.product_4 = cls.env['product.product'].create({
|
||||
'name': 'Saleable Product',
|
||||
'categ_id': cls.product_category_base.id
|
||||
})
|
||||
cls.product_tmpl_id = cls.product.product_tmpl_id.id
|
||||
cls.partner_id = cls.env['res.partner'].create({'name': 'A Test Partner'}).id
|
||||
cls.picking_type_id = cls.env.ref('stock.picking_type_in').id
|
||||
cls.location_id = cls.env.ref('stock.stock_location_suppliers').id
|
||||
cls.location_dest_id = cls.env.ref('stock.stock_location_stock').id
|
||||
641
quality_control/tests/test_picking_quality_check.py
Normal file
641
quality_control/tests/test_picking_quality_check.py
Normal file
@@ -0,0 +1,641 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from .test_common import TestQualityCommon
|
||||
|
||||
class TestQualityCheck(TestQualityCommon):
|
||||
|
||||
def test_00_picking_quality_check(self):
|
||||
|
||||
"""Test quality check on incoming shipment."""
|
||||
|
||||
# Create Quality Point for incoming shipment.
|
||||
self.qality_point_test = self.env['quality.point'].create({
|
||||
'product_ids': [(4, self.product.id)],
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
})
|
||||
|
||||
# Check that quality point created.
|
||||
self.assertTrue(self.qality_point_test, "First Quality Point not created for Laptop Customized.")
|
||||
|
||||
# Create incoming shipment.
|
||||
self.picking_in = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id,
|
||||
})
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id})
|
||||
|
||||
# Check that incoming shipment is created.
|
||||
self.assertTrue(self.picking_in, "Incoming shipment not created.")
|
||||
|
||||
# Confirm incoming shipment.
|
||||
self.picking_in.action_confirm()
|
||||
|
||||
# Check Quality Check for incoming shipment is created and check it's state is 'none'.
|
||||
self.assertEqual(len(self.picking_in.check_ids), 1)
|
||||
self.assertEqual(self.picking_in.check_ids.quality_state, 'none')
|
||||
|
||||
# 'Pass' Quality Checks of incoming shipment.
|
||||
self.picking_in.check_ids.do_pass()
|
||||
|
||||
# Validate incoming shipment.
|
||||
self.picking_in.button_validate()
|
||||
|
||||
# Now check state of quality check.
|
||||
self.assertEqual(self.picking_in.check_ids.quality_state, 'pass')
|
||||
|
||||
def test_01_picking_quality_check_type_text(self):
|
||||
|
||||
""" Test a Quality Check on a picking with 'Instruction'
|
||||
as test type.
|
||||
"""
|
||||
# Create Quality Point for incoming shipment with 'Instructions' as test type
|
||||
self.qality_point_test = self.env['quality.point'].create({
|
||||
'product_ids': [(4, self.product.id)],
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
'test_type_id': self.env.ref('quality.test_type_instructions').id
|
||||
})
|
||||
|
||||
# Check that quality point created.
|
||||
self.assertTrue(self.qality_point_test, "Quality Point not created")
|
||||
|
||||
# Create incoming shipment.
|
||||
self.picking_in = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id,
|
||||
})
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id})
|
||||
|
||||
# Check that incoming shipment is created.
|
||||
self.assertTrue(self.picking_in, "Incoming shipment not created.")
|
||||
|
||||
# Confirm incoming shipment.
|
||||
self.picking_in.action_confirm()
|
||||
|
||||
# Check Quality Check for incoming shipment is created and check it's state is 'none'.
|
||||
self.assertEqual(len(self.picking_in.check_ids), 1)
|
||||
self.assertEqual(self.picking_in.check_ids.quality_state, 'none')
|
||||
|
||||
# Check that the Quality Check on the picking has 'instruction' as test_type
|
||||
self.assertEqual(self.picking_in.check_ids[0].test_type, 'instructions')
|
||||
|
||||
def test_02_picking_quality_check_type_picture(self):
|
||||
|
||||
""" Test a Quality Check on a picking with 'Take Picture'
|
||||
as test type.
|
||||
"""
|
||||
# Create Quality Point for incoming shipment with 'Take Picture' as test type
|
||||
self.qality_point_test = self.env['quality.point'].create({
|
||||
'product_ids': [(4, self.product.id)],
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
'test_type_id': self.env.ref('quality.test_type_picture').id
|
||||
})
|
||||
# Check that quality point created.
|
||||
self.assertTrue(self.qality_point_test, "Quality Point not created")
|
||||
# Create incoming shipment.
|
||||
self.picking_in = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id,
|
||||
})
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id})
|
||||
# Check that incoming shipment is created.
|
||||
self.assertTrue(self.picking_in, "Incoming shipment not created.")
|
||||
# Confirm incoming shipment.
|
||||
self.picking_in.action_confirm()
|
||||
# Check Quality Check for incoming shipment is created and check it's state is 'none'.
|
||||
self.assertEqual(len(self.picking_in.check_ids), 1)
|
||||
self.assertEqual(self.picking_in.check_ids.quality_state, 'none')
|
||||
|
||||
# Check that the Quality Check on the picking has 'picture' as test_type
|
||||
self.assertEqual(self.picking_in.check_ids[0].test_type, 'picture')
|
||||
|
||||
def test_03_lot_quality_check(self):
|
||||
""" Test a Quality Check at the lot level.
|
||||
"""
|
||||
product_tracked_by_lot = self.env['product.product'].create({
|
||||
'name': 'Product tracked by lot',
|
||||
'tracking': 'lot',
|
||||
})
|
||||
|
||||
product = self.env['product.product'].create({
|
||||
'name': 'Product',
|
||||
'tracking': 'none',
|
||||
})
|
||||
|
||||
# Create Quality Point for incoming shipment on lots with 'Measure' as test type
|
||||
self.quality_point_test1 = self.env['quality.point'].create({
|
||||
'product_ids': [product_tracked_by_lot.id],
|
||||
'picking_type_ids': [self.picking_type_id],
|
||||
'test_type_id': self.env.ref('quality_control.test_type_measure').id,
|
||||
'is_lot_tested_fractionally': True,
|
||||
'testing_percentage_within_lot': 10.02,
|
||||
'measure_on': 'move_line',
|
||||
'norm': 5.,
|
||||
'tolerance_min': 4.,
|
||||
'tolerance_max': 6.,
|
||||
})
|
||||
|
||||
# Create Quality Point for incoming shipment on lots for all products
|
||||
self.quality_point_test2 = self.env['quality.point'].create({
|
||||
'picking_type_ids': [self.picking_type_id],
|
||||
'test_type_id': self.env.ref('quality_control.test_type_measure').id,
|
||||
'measure_on': 'move_line',
|
||||
})
|
||||
|
||||
# Create Quality Point for product without tracking
|
||||
self.quality_point_test3 = self.env['quality.point'].create({
|
||||
'product_ids': [product.id],
|
||||
'picking_type_ids': [self.picking_type_id],
|
||||
'test_type_id': self.env.ref('quality_control.test_type_measure').id,
|
||||
'measure_on': 'move_line',
|
||||
})
|
||||
|
||||
# Check that the quality points are created
|
||||
self.assertTrue(self.quality_point_test1, "Quality Point not created")
|
||||
self.assertTrue(self.quality_point_test2, "Quality Point not created")
|
||||
self.assertTrue(self.quality_point_test3, "Quality Point not created")
|
||||
|
||||
# Create incoming shipment
|
||||
self.picking_in = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id,
|
||||
})
|
||||
|
||||
move = self.env['stock.move'].create({
|
||||
'name': product_tracked_by_lot.name,
|
||||
'product_id': product_tracked_by_lot.id,
|
||||
'product_uom_qty': 11,
|
||||
'product_uom': product_tracked_by_lot.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id})
|
||||
|
||||
# Check that incoming shipment is created
|
||||
self.assertTrue(self.picking_in, "Incoming shipment not created.")
|
||||
|
||||
# Creating move lines with the serial number widget
|
||||
move.next_serial = "1"
|
||||
move._generate_serial_numbers(next_serial_count=10)
|
||||
self.assertTrue(len(move.move_line_ids) == 10, "Not all move lines are created with _generate_serial_number")
|
||||
|
||||
# Check that quality checks were created
|
||||
self.assertTrue(len(move.move_line_ids.check_ids) == 20, "Wrong number of Quality Checks created on the move lines")
|
||||
|
||||
# Create move line without qty_done and setting it after
|
||||
move_line_vals = move._prepare_move_line_vals()
|
||||
move_line = self.env['stock.move.line'].create(move_line_vals)
|
||||
move_line.qty_done = 1.
|
||||
self.assertTrue(len(move.move_line_ids.check_ids) == 22, "Wrong number of Quality Checks created on the move lines")
|
||||
|
||||
# Updating quantity of one move line
|
||||
move.move_line_ids[0].qty_done = 2
|
||||
check_line1 = move.move_line_ids[0].check_ids[0]
|
||||
check_line2 = move.move_line_ids[1].check_ids[0]
|
||||
|
||||
# Check that the percentage of the lot to check is correct
|
||||
self.assertTrue(check_line1.qty_to_test == 0.21, "Quantity to test within lot not well calculated (check rounding)")
|
||||
self.assertTrue(check_line2.qty_to_test == 0.11, "Quantity to test within lot not well calculated (check rounding)")
|
||||
|
||||
# Check that tests are failing and succeeding properly
|
||||
check_line1.measure = 3.
|
||||
check_line2.measure = 4.5
|
||||
check_line1.do_measure()
|
||||
check_line2.do_measure()
|
||||
self.assertTrue(check_line1.quality_state == 'fail', "Quality Check of type 'measure' not failing on move line")
|
||||
self.assertTrue(check_line2.quality_state == 'pass', "Quality Check of type 'measure' not passing on move line")
|
||||
|
||||
# Create move with a product without tracking with done quantity
|
||||
move_without_tracking1 = self.env['stock.move'].create({
|
||||
'name': product.name,
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': 1,
|
||||
'quantity_done': 1,
|
||||
'product_uom': product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
self.assertTrue(len(move_without_tracking1.move_line_ids.check_ids) == 2, "Wrong number of Quality Checks created on the move lines")
|
||||
|
||||
# Create move with a product without tracking without done quantity and changing done quantity after
|
||||
move_without_tracking2 = self.env['stock.move'].create({
|
||||
'name': product.name,
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': 1,
|
||||
'quantity_done': 0,
|
||||
'product_uom': product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
move_without_tracking2.quantity_done = 1
|
||||
self.assertTrue(len(move_without_tracking2.move_line_ids.check_ids) == 2, "Wrong number of Quality Checks created on the move lines")
|
||||
|
||||
def test_04_picking_quality_check_creation_no_products_no_categories(self):
|
||||
|
||||
""" Test Quality Check creation on incoming shipment from a Quality Point
|
||||
with no products and no product_categories set
|
||||
"""
|
||||
# Create Quality Point for incoming shipment with no product or product_category set.
|
||||
self.quality_point_test = self.env['quality.point'].create({
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
'test_type_id': self.env.ref('quality_control.test_type_passfail').id
|
||||
})
|
||||
# Check that Quality Point has been created.
|
||||
self.assertTrue(self.quality_point_test, "Quality Point not created.")
|
||||
# Create incoming shipment.
|
||||
self.picking_in = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Check that incoming shipment has been created.
|
||||
self.assertTrue(self.picking_in, "Incoming shipment not created.")
|
||||
# Confirm incoming shipment.
|
||||
self.picking_in.action_confirm()
|
||||
# Check that Quality Check for incoming shipment has been created.
|
||||
self.assertEqual(len(self.picking_in.check_ids), 1)
|
||||
|
||||
def test_05_picking_quality_check_creation_with_product_no_categories(self):
|
||||
|
||||
""" Test Quality Check creation on incoming shipment from a Quality Point
|
||||
with products and no product_categories set
|
||||
"""
|
||||
# Create Quality Point for incoming shipment with only a product set.
|
||||
self.quality_point_test = self.env['quality.point'].create({
|
||||
'product_ids': [(4, self.product.id)],
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
'test_type_id': self.env.ref('quality_control.test_type_passfail').id
|
||||
})
|
||||
# Check that Quality Point has been created.
|
||||
self.assertTrue(self.quality_point_test, "Quality Point not created.")
|
||||
# Create incoming shipment.
|
||||
self.picking_in = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with right product.
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with wrong product.
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product_2.name,
|
||||
'product_id': self.product_2.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product_2.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Check that incoming shipment has been created.
|
||||
self.assertTrue(self.picking_in, "Incoming shipment not created.")
|
||||
# Confirm incoming shipment.
|
||||
self.picking_in.action_confirm()
|
||||
# Check that only one Quality Check for incoming shipment has been created for the right product.
|
||||
self.assertEqual(len(self.picking_in.check_ids), 1)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product.id)), 1)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product_2.id)), 0)
|
||||
|
||||
def test_06_picking_quality_check_creation_no_product_with_categories(self):
|
||||
|
||||
""" Test Quality Check creation on incoming shipment from a Quality Point
|
||||
with no products and product_categories set
|
||||
"""
|
||||
# Create Quality Point for incoming shipment with only a product_category set.
|
||||
self.quality_point_test = self.env['quality.point'].create({
|
||||
'product_category_ids': [(4, self.product_category_base.id)],
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
'test_type_id': self.env.ref('quality_control.test_type_passfail').id
|
||||
})
|
||||
# Check that Quality Point has been created.
|
||||
self.assertTrue(self.quality_point_test, "Quality Point not created.")
|
||||
# Create incoming shipment.
|
||||
self.picking_in = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with product having right category (child of Quality Point set category).
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with product having wrong category (parent of Quality Point set category).
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product_2.name,
|
||||
'product_id': self.product_2.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product_2.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Check that incoming shipment has been created.
|
||||
self.assertTrue(self.picking_in, "Incoming shipment not created.")
|
||||
# Confirm incoming shipment.
|
||||
self.picking_in.action_confirm()
|
||||
# Check that only one Quality Check for incoming shipment has been created for the right category.
|
||||
self.assertEqual(len(self.picking_in.check_ids), 1)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product.id)), 1)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product_2.id)), 0)
|
||||
|
||||
def test_07_picking_quality_check_creation_with_product_and_categories(self):
|
||||
|
||||
""" Test Quality Check creation on incoming shipment from a Quality Point
|
||||
with both products and product_categories set
|
||||
"""
|
||||
# Create Quality Point for incoming shipment with only a product_category set.
|
||||
self.quality_point_test = self.env['quality.point'].create({
|
||||
'product_ids': [(4, self.product_2.id), (4, self.product_4.id)],
|
||||
'product_category_ids': [(4, self.product_category_base.id)],
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
'test_type_id': self.env.ref('quality_control.test_type_passfail').id
|
||||
})
|
||||
# Check that Quality Point has been created.
|
||||
self.assertTrue(self.quality_point_test, "Quality Point not created.")
|
||||
# Create incoming shipment.
|
||||
self.picking_in = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with wrong product but having right category (child of Quality Point set category.
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with right product but having wrong category (parent of Quality Point set category).
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product_2.name,
|
||||
'product_id': self.product_2.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product_2.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with wrong product and having wrong category (parent of Quality Point set category).
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product_3.name,
|
||||
'product_id': self.product_3.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product_3.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with right product having right category
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product_4.name,
|
||||
'product_id': self.product_4.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product_4.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Check that incoming shipment has been created.
|
||||
self.assertTrue(self.picking_in, "Incoming shipment not created.")
|
||||
# Confirm incoming shipment.
|
||||
self.picking_in.action_confirm()
|
||||
# Check that Quality Check for incoming shipment have been created only for the right product / category.
|
||||
self.assertEqual(len(self.picking_in.check_ids), 3)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product.id)), 1)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product_2.id)), 1)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product_3.id)), 0)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product_4.id)), 1)
|
||||
|
||||
def test_08_on_product_creation_with_product_and_categories(self):
|
||||
|
||||
""" Test Quality Check creation on incoming shipment from a Quality Point
|
||||
with both products and product_categories set
|
||||
"""
|
||||
# Create Quality Point for incoming shipment with only a product_category set.
|
||||
self.quality_point_test = self.env['quality.point'].create({
|
||||
'product_ids': [(4, self.product_2.id), (4, self.product_4.id)],
|
||||
'product_category_ids': [(4, self.product_category_base.id)],
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
'measure_on': 'move_line',
|
||||
'test_type_id': self.env.ref('quality_control.test_type_passfail').id
|
||||
})
|
||||
# Create incoming shipment.
|
||||
self.picking_in = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with wrong product but having right category (child of Quality Point set category.
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with right product but having wrong category (parent of Quality Point set category).
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product_2.name,
|
||||
'product_id': self.product_2.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product_2.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with wrong product and having wrong category (parent of Quality Point set category).
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product_3.name,
|
||||
'product_id': self.product_3.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product_3.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Create move with right product having right category
|
||||
self.env['stock.move'].create({
|
||||
'name': self.product_4.name,
|
||||
'product_id': self.product_4.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product_4.uom_id.id,
|
||||
'picking_id': self.picking_in.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id
|
||||
})
|
||||
# Confirm incoming shipment.
|
||||
self.picking_in.action_confirm()
|
||||
for line in self.picking_in.move_line_ids:
|
||||
line.qty_done = line.reserved_qty
|
||||
# Check that Quality Check for incoming shipment have been created for all the good move lines
|
||||
self.assertEqual(len(self.picking_in.check_ids), 3)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product.id)), 1)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product_2.id)), 1)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product_3.id)), 0)
|
||||
self.assertEqual(len(self.picking_in.check_ids.filtered(lambda c: c.product_id.id == self.product_4.id)), 1)
|
||||
|
||||
def test_09_quality_check_on_operations(self):
|
||||
|
||||
""" Test Quality Check creation of 'operation' type, meaning only one QC will be created per picking.
|
||||
"""
|
||||
# Create Quality Point for incoming shipment with only a product_category set.
|
||||
quality_point_operation_type = self.env['quality.point'].create({
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
'measure_on': 'operation',
|
||||
'test_type_id': self.env.ref('quality_control.test_type_passfail').id
|
||||
})
|
||||
receipt = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id,
|
||||
})
|
||||
self.env['stock.move'].create([{
|
||||
'name': product.name,
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': 1,
|
||||
'product_uom': product.uom_id.id,
|
||||
'picking_id': receipt.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': self.location_dest_id,
|
||||
} for product in (self.product, self.product_2)])
|
||||
receipt.action_confirm()
|
||||
|
||||
self.assertEqual(len(receipt.check_ids), 1)
|
||||
self.assertEqual(receipt.check_ids.point_id, quality_point_operation_type)
|
||||
self.assertEqual(receipt.check_ids.picking_id, receipt)
|
||||
|
||||
def test_checks_removal_on_SM_cancellation(self):
|
||||
"""
|
||||
Configuration:
|
||||
- 2 storable products P1 and P2
|
||||
- Receipt in 2 steps
|
||||
- QCP for internal pickings
|
||||
Process a first receipt with P1 and P2 (an internal picking and two
|
||||
quality checks are created)
|
||||
Process a second receipt with P1. The SM input->stock should be merged
|
||||
into the existing one and the quality checks should still exist
|
||||
"""
|
||||
warehouse = self.env['stock.warehouse'].search([], limit=1)
|
||||
warehouse.reception_steps = 'two_steps'
|
||||
|
||||
p01, p02 = self.env['product.product'].create([{
|
||||
'name': name,
|
||||
'type': 'product',
|
||||
} for name in ('SuperProduct01', 'SuperProduct02')])
|
||||
|
||||
self.env['quality.point'].create([{
|
||||
'product_ids': [(4, product.id)],
|
||||
'picking_type_ids': [(4, warehouse.int_type_id.id)],
|
||||
} for product in (p01, p02)])
|
||||
|
||||
receipt = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': warehouse.wh_input_stock_loc_id.id,
|
||||
})
|
||||
self.env['stock.move'].create([{
|
||||
'name': product.name,
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': 1,
|
||||
'product_uom': product.uom_id.id,
|
||||
'picking_id': receipt.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': warehouse.wh_input_stock_loc_id.id,
|
||||
} for product in (p01, p02)])
|
||||
receipt.action_confirm()
|
||||
receipt.move_ids.quantity_done = 1
|
||||
receipt.button_validate()
|
||||
|
||||
internal_transfer = self.env['stock.picking'].search(
|
||||
[('location_id', '=', warehouse.wh_input_stock_loc_id.id), ('picking_type_id', '=', warehouse.int_type_id.id)],
|
||||
order='id desc', limit=1)
|
||||
self.assertEqual(internal_transfer.check_ids.product_id, p01 + p02)
|
||||
|
||||
receipt = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_id,
|
||||
'partner_id': self.partner_id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': warehouse.wh_input_stock_loc_id.id,
|
||||
})
|
||||
self.env['stock.move'].create({
|
||||
'name': p01.name,
|
||||
'product_id': p01.id,
|
||||
'product_uom_qty': 1,
|
||||
'product_uom': p01.uom_id.id,
|
||||
'picking_id': receipt.id,
|
||||
'location_id': self.location_id,
|
||||
'location_dest_id': warehouse.wh_input_stock_loc_id.id,
|
||||
})
|
||||
receipt.action_confirm()
|
||||
receipt.move_ids.quantity_done = 1
|
||||
receipt.button_validate()
|
||||
|
||||
self.assertRecordValues(internal_transfer.move_ids, [
|
||||
{'product_id': p01.id, 'product_uom_qty': 2},
|
||||
{'product_id': p02.id, 'product_uom_qty': 1},
|
||||
])
|
||||
self.assertEqual(internal_transfer.check_ids.product_id, p01 + p02)
|
||||
70
quality_control/tests/test_purchase_quality_check.py
Normal file
70
quality_control/tests/test_purchase_quality_check.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from .test_common import TestQualityCommon
|
||||
from odoo import fields
|
||||
from odoo.tests import tagged, users
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestPurchaseQualityCheck(TestQualityCommon):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
if 'purchase.order' not in self.env:
|
||||
self.skipTest('`purchase` is not installed')
|
||||
|
||||
self.buyer = self.env['res.users'].create({
|
||||
'name': 'Buyer',
|
||||
'login': 'buyer',
|
||||
'email': 'superbuyer@example.com',
|
||||
'groups_id': [
|
||||
# Internal
|
||||
(4, self.ref('base.group_user')),
|
||||
# Purchase: User:
|
||||
(4, self.ref('purchase.group_purchase_user')),
|
||||
],
|
||||
})
|
||||
|
||||
# Create Quality Point for incoming shipment.
|
||||
self.quality_point_test = self.env['quality.point'].create({
|
||||
'product_ids': [(4, self.product.id)],
|
||||
'picking_type_ids': [(4, self.picking_type_id)],
|
||||
})
|
||||
|
||||
@users('buyer')
|
||||
def test_purchase_quality_check(self):
|
||||
"""
|
||||
Test that the Quality Check is created with the 'none' status when the PO is confirmed,
|
||||
and removed when the PO is cancelled.
|
||||
"""
|
||||
# Create a Purchase Order
|
||||
po = self.env['purchase.order'].create({
|
||||
'partner_id': self.partner_id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_qty': 1.0,
|
||||
'product_uom': self.product.uom_po_id.id,
|
||||
'price_unit': 1.0,
|
||||
'date_planned': fields.Datetime.now(),
|
||||
})]
|
||||
})
|
||||
po.button_confirm()
|
||||
|
||||
# Check if the incoming shipment is created.
|
||||
po_sudo = po.sudo()
|
||||
self.assertTrue(po_sudo.picking_ids, "Incoming shipment not created.")
|
||||
|
||||
# Check if the Quality Check for incoming shipment is created and check it's state is 'none'.
|
||||
self.assertEqual(len(po_sudo.picking_ids.check_ids), 1)
|
||||
self.assertEqual(po_sudo.picking_ids.check_ids.quality_state, 'none')
|
||||
|
||||
self.env['stock.move.line'].invalidate_model()
|
||||
po.button_cancel()
|
||||
|
||||
# Check that the picking is canceled
|
||||
self.assertEqual(po_sudo.picking_ids.state, 'cancel', 'The picking should be canceled after the PO cancellation')
|
||||
# Check that the quality check is removed
|
||||
self.assertFalse(po_sudo.picking_ids.check_ids, 'The quality check should be removed after the picking cancellation')
|
||||
Reference in New Issue
Block a user