test_manual_consumption.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  2. # -*- coding: utf-8 -*-
  3. from odoo.addons.mrp.tests.common import TestMrpCommon
  4. from odoo.tests import tagged, Form, HttpCase
  5. @tagged('post_install', '-at_install')
  6. class TestTourManualConsumption(HttpCase):
  7. def test_mrp_manual_consumption(self):
  8. """Test manual consumption mechanism. Test when manual consumption is
  9. True, quantity_done won't be updated automatically. Bom line with tracked
  10. products or operations should be set to manual consumption automatically.
  11. Also test that when manually change quantity_done, manual consumption
  12. will be set to True. Also test when create backorder, the manual consumption
  13. should be set according to the bom.
  14. """
  15. Product = self.env['product.product']
  16. product_finish = Product.create({
  17. 'name': 'finish',
  18. 'type': 'product',
  19. 'tracking': 'none',})
  20. product_nt = Product.create({
  21. 'name': 'No tracking',
  22. 'type': 'product',
  23. 'tracking': 'none',})
  24. product_sn = Product.create({
  25. 'name': 'Serial',
  26. 'type': 'product',
  27. 'tracking': 'serial',})
  28. product_lot = Product.create({
  29. 'name': 'Lot',
  30. 'type': 'product',
  31. 'tracking': 'lot',})
  32. bom = self.env['mrp.bom'].create({
  33. 'product_id': product_finish.id,
  34. 'product_tmpl_id': product_finish.product_tmpl_id.id,
  35. 'product_qty': 1,
  36. 'type': 'normal',
  37. 'bom_line_ids': [
  38. (0, 0, {'product_id': product_nt.id, 'product_qty': 1}),
  39. (0, 0, {'product_id': product_sn.id, 'product_qty': 1}),
  40. (0, 0, {'product_id': product_lot.id, 'product_qty': 1}),
  41. ],
  42. })
  43. mo_form = Form(self.env['mrp.production'])
  44. mo_form.product_id = product_finish
  45. mo_form.bom_id = bom
  46. mo_form.product_qty = 10
  47. mo = mo_form.save()
  48. mo.action_confirm()
  49. mo.action_assign()
  50. # test no updating
  51. mo_form = Form(mo)
  52. mo_form.qty_producing = 5
  53. mo = mo_form.save()
  54. move_nt, move_sn, move_lot = mo.move_raw_ids
  55. self.assertEqual(move_nt.manual_consumption, False)
  56. self.assertEqual(move_nt.quantity_done, 5)
  57. self.assertEqual(move_sn.manual_consumption, True)
  58. self.assertEqual(move_sn.quantity_done, 0)
  59. self.assertEqual(move_lot.manual_consumption, True)
  60. self.assertEqual(move_lot.quantity_done, 0)
  61. action_id = self.env.ref('mrp.menu_mrp_production_action').action
  62. url = "/web#model=mrp.production&view_type=form&action=%s&id=%s" % (str(action_id.id), str(mo.id))
  63. self.start_tour(url, "test_mrp_manual_consumption", login="admin", timeout=200)
  64. self.assertEqual(move_nt.manual_consumption, True)
  65. self.assertEqual(move_nt.quantity_done, 6.0)
  66. self.assertEqual(move_sn.manual_consumption, True)
  67. self.assertEqual(move_sn.quantity_done, 0)
  68. self.assertEqual(move_lot.manual_consumption, True)
  69. self.assertEqual(move_lot.quantity_done, 0)
  70. backorder = mo.procurement_group_id.mrp_production_ids - mo
  71. move_nt = backorder.move_raw_ids.filtered(lambda m: m.product_id == product_nt)
  72. move_sn = backorder.move_raw_ids.filtered(lambda m: m.product_id == product_sn)
  73. move_lot = backorder.move_raw_ids.filtered(lambda m: m.product_id == product_lot)
  74. self.assertEqual(move_nt.manual_consumption, False)
  75. self.assertEqual(move_sn.manual_consumption, True)
  76. self.assertEqual(move_lot.manual_consumption, True)
  77. class TestManualConsumption(TestMrpCommon):
  78. @classmethod
  79. def setUpClass(cls):
  80. super().setUpClass()
  81. cls.stock_location = cls.env.ref('stock.stock_location_stock')
  82. def test_manual_consumption_backorder_00(self):
  83. """Test when use_auto_consume_components_lots is not set, manual consumption
  84. of the backorder is correctly set.
  85. """
  86. mo, _, _final, c1, c2 = self.generate_mo('none', 'lot', 'none', qty_final=2)
  87. self.assertTrue(mo.move_raw_ids.filtered(lambda m: m.product_id == c1).manual_consumption)
  88. self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == c2).manual_consumption)
  89. lot = self.env['stock.lot'].create({
  90. 'name': 'lot',
  91. 'product_id': c1.id,
  92. 'company_id': self.env.company.id,
  93. })
  94. self.env['stock.quant']._update_available_quantity(c1, self.stock_location, 8, lot_id=lot)
  95. self.env['stock.quant']._update_available_quantity(c2, self.stock_location, 2)
  96. mo.action_assign()
  97. mo_form = Form(mo)
  98. mo_form.qty_producing = 1
  99. mo_form.save()
  100. self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id.id == c1.id).mapped("quantity_done")), 0)
  101. self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id.id == c2.id).mapped("quantity_done")), 1)
  102. details_operation_form = Form(mo.move_raw_ids.filtered(lambda m: m.product_id == c1), view=self.env.ref('stock.view_stock_move_operations'))
  103. with details_operation_form.move_line_ids.edit(0) as ml:
  104. ml.qty_done = 4
  105. ml.lot_id = lot
  106. details_operation_form.save()
  107. action = mo.button_mark_done()
  108. backorder = Form(self.env['mrp.production.backorder'].with_context(**action['context']))
  109. backorder.save().action_backorder()
  110. backorder_mo = mo.procurement_group_id.mrp_production_ids[-1]
  111. self.assertTrue(backorder_mo.move_raw_ids.filtered(lambda m: m.product_id == c1).manual_consumption)
  112. self.assertFalse(backorder_mo.move_raw_ids.filtered(lambda m: m.product_id == c2).manual_consumption)
  113. def test_manual_consumption_backorder_01(self):
  114. """Test when use_auto_consume_components_lots is set, manual consumption
  115. of the backorder is correctly set.
  116. """
  117. picking_type = self.env['stock.picking.type'].search([('code', '=', 'mrp_operation')])[0]
  118. picking_type.use_auto_consume_components_lots = True
  119. mo, _, _final, c1, c2 = self.generate_mo('none', 'lot', 'none', qty_final=2)
  120. self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == c1).manual_consumption)
  121. self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == c2).manual_consumption)
  122. lot = self.env['stock.lot'].create({
  123. 'name': 'lot',
  124. 'product_id': c1.id,
  125. 'company_id': self.env.company.id,
  126. })
  127. self.env['stock.quant']._update_available_quantity(c1, self.stock_location, 8, lot_id=lot)
  128. self.env['stock.quant']._update_available_quantity(c2, self.stock_location, 2)
  129. mo.action_assign()
  130. mo_form = Form(mo)
  131. mo_form.qty_producing = 1
  132. mo_form.save()
  133. self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id.id == c1.id).mapped("quantity_done")), 4)
  134. self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id.id == c2.id).mapped("quantity_done")), 1)
  135. action = mo.button_mark_done()
  136. backorder = Form(self.env['mrp.production.backorder'].with_context(**action['context']))
  137. backorder.save().action_backorder()
  138. backorder_mo = mo.procurement_group_id.mrp_production_ids[-1]
  139. self.assertFalse(backorder_mo.move_raw_ids.filtered(lambda m: m.product_id == c1).manual_consumption)
  140. self.assertFalse(backorder_mo.move_raw_ids.filtered(lambda m: m.product_id == c2).manual_consumption)
  141. def test_manual_consumption_split_merge_00(self):
  142. """Test manual consumption is correctly set after split or merge.
  143. """
  144. # Change 'Units' rounding to 1 (integer only quantities)
  145. self.uom_unit.rounding = 1
  146. # Create a mo for 10 products
  147. mo, _, _, p1, p2 = self.generate_mo('none', 'lot', 'none', qty_final=10)
  148. self.assertTrue(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).manual_consumption)
  149. self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == p2).manual_consumption)
  150. # Split in 3 parts
  151. action = mo.action_split()
  152. wizard = Form(self.env[action['res_model']].with_context(action['context']))
  153. wizard.counter = 3
  154. action = wizard.save().action_split()
  155. for production in mo.procurement_group_id.mrp_production_ids:
  156. self.assertTrue(production.move_raw_ids.filtered(lambda m: m.product_id == p1).manual_consumption)
  157. self.assertFalse(production.move_raw_ids.filtered(lambda m: m.product_id == p2).manual_consumption)
  158. # Merge them back
  159. action = mo.procurement_group_id.mrp_production_ids.action_merge()
  160. mo = self.env[action['res_model']].browse(action['res_id'])
  161. self.assertTrue(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).manual_consumption)
  162. self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == p2).manual_consumption)