Server IP : 127.0.0.2 / Your IP : 3.138.36.87 Web Server : Apache/2.4.18 (Ubuntu) System : User : www-data ( ) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : disk_free_space,disk_total_space,diskfreespace,dl,exec,fpaththru,getmyuid,getmypid,highlight_file,ignore_user_abord,leak,listen,link,opcache_get_configuration,opcache_get_status,passthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,php_uname,phpinfo,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,pclose,popen,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,shell_exec,source,show_source,system,virtual MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /opt/odoo/addons/mrp/tests/ |
Upload File : |
# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from datetime import datetime, timedelta from odoo.fields import Datetime as Dt from odoo.addons.mrp.tests.common import TestMrpCommon class TestMrpOrder(TestMrpCommon): def test_access_rights_manager(self): man_order = self.env['mrp.production'].sudo(self.user_mrp_manager).create({ 'name': 'Stick-0', 'product_id': self.product_4.id, 'product_uom_id': self.product_4.uom_id.id, 'product_qty': 5.0, 'bom_id': self.bom_1.id, 'location_src_id': self.location_1.id, 'location_dest_id': self.warehouse_1.wh_output_stock_loc_id.id, }) man_order.action_cancel() self.assertEqual(man_order.state, 'cancel', "Production order should be in cancel state.") man_order.unlink() def test_access_rights_user(self): man_order = self.env['mrp.production'].sudo(self.user_mrp_user).create({ 'name': 'Stick-0', 'product_id': self.product_4.id, 'product_uom_id': self.product_4.uom_id.id, 'product_qty': 5.0, 'bom_id': self.bom_1.id, 'location_src_id': self.location_1.id, 'location_dest_id': self.warehouse_1.wh_output_stock_loc_id.id, }) man_order.action_cancel() self.assertEqual(man_order.state, 'cancel', "Production order should be in cancel state.") man_order.unlink() def test_basic(self): """ Basic order test: no routing (thus no workorders), no lot """ inventory = self.env['stock.inventory'].create({ 'name': 'Initial inventory', 'filter': 'partial', 'line_ids': [(0, 0, { 'product_id': self.product_1.id, 'product_uom_id': self.product_1.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id }), (0, 0, { 'product_id': self.product_2.id, 'product_uom_id': self.product_2.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id })] }) inventory.action_done() test_date_planned = datetime.now() - timedelta(days=1) test_quantity = 2.0 self.bom_1.routing_id = False man_order = self.env['mrp.production'].sudo(self.user_mrp_user).create({ 'name': 'Stick-0', 'product_id': self.product_4.id, 'product_uom_id': self.product_4.uom_id.id, 'product_qty': test_quantity, 'bom_id': self.bom_1.id, 'date_planned_start': test_date_planned, 'location_src_id': self.location_1.id, 'location_dest_id': self.warehouse_1.wh_output_stock_loc_id.id, }) self.assertEqual(man_order.state, 'confirmed', "Production order should be in confirmed state.") # check production move production_move = man_order.move_finished_ids self.assertEqual(production_move.date, Dt.to_string(test_date_planned)) self.assertEqual(production_move.product_id, self.product_4) self.assertEqual(production_move.product_uom, man_order.product_uom_id) self.assertEqual(production_move.product_qty, man_order.product_qty) self.assertEqual(production_move.location_id, self.product_4.property_stock_production) self.assertEqual(production_move.location_dest_id, man_order.location_dest_id) # check consumption moves for move in man_order.move_raw_ids: self.assertEqual(move.date, Dt.to_string(test_date_planned)) first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_2) self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 2) first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_1) self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 4) # waste some material, create a scrap # scrap = self.env['stock.scrap'].with_context( # active_model='mrp.production', active_id=man_order.id # ).create({}) # scrap = self.env['stock.scrap'].create({ # 'production_id': man_order.id, # 'product_id': first_move.product_id.id, # 'product_uom_id': first_move.product_uom.id, # 'scrap_qty': 5.0, # }) # check created scrap # procurements = self.env['procurement.order'].search([('move_dest_id', 'in', man_order.move_raw_ids.ids)]) # print procurements # procurements = self.env['procurement.order'].search([('production_id', '=', man_order.id)]) # print procurements # for proc in self.env['procurement.order'].browse(procurements): # date_planned = self.mrp_production_test1.date_planned # if proc.product_id.type not in ('product', 'consu'): # continue # if proc.product_id.id == order_line.product_id.id: # self.assertEqual(proc.date_planned, date_planned, "Planned date does not correspond") # # procurement state should be `confirmed` at this stage, except if procurement_jit is installed, in which # # case it could already be in `running` or `exception` state (not enough stock) # expected_states = ('confirmed', 'running', 'exception') # self.assertEqual(proc.state in expected_states, 'Procurement state is `%s` for %s, expected one of %s' % (proc.state, proc.product_id.name, expected_states)) # Change production quantity qty_wizard = self.env['change.production.qty'].create({ 'mo_id': man_order.id, 'product_qty': 3.0, }) # qty_wizard.change_prod_qty() # # I check qty after changed in production order. # #self.assertEqual(self.mrp_production_test1.product_qty, 3, "Qty is not changed in order.") # move = self.mrp_production_test1.move_finished_ids[0] # self.assertEqual(move.product_qty, self.mrp_production_test1.product_qty, "Qty is not changed in move line.") # # I run scheduler. # self.env['procurement.order'].run_scheduler() # # The production order is Waiting Goods, will force production which should set consume lines as available # self.mrp_production_test1.button_plan() # # I check that production order in ready state after forcing production. # #self.assertEqual(self.mrp_production_test1.availability, 'assigned', 'Production order availability should be set as available') # produce product produce_wizard = self.env['mrp.product.produce'].sudo(self.user_mrp_user).with_context({ 'active_id': man_order.id, 'active_ids': [man_order.id], }).create({ 'product_qty': 1.0, }) produce_wizard.do_produce() # man_order.button_mark_done() man_order.button_mark_done() self.assertEqual(man_order.state, 'done', "Production order should be in done state.") def test_explode_from_order(self): # # bom3 produces 2 Dozen of Doors (p6), aka 24 # To produce 24 Units of Doors (p6) # - 2 Units of Tools (p5) -> need 4 # - 8 Dozen of Sticks (p4) -> need 16 # - 12 Units of Wood (p2) -> need 24 # bom2 produces 1 Unit of Sticks (p4) # To produce 1 Unit of Sticks (p4) # - 2 Dozen of Sticks (p4) -> need 8 # - 3 Dozen of Stones (p3) -> need 12 # Update capacity, start time, stop time, and time efficiency. # ------------------------------------------------------------ self.workcenter_1.write({'capacity': 1, 'time_start': 0, 'time_stop': 0, 'time_efficiency': 100}) # Set manual time cycle 20 and 10. # -------------------------------- self.operation_1.write({'time_cycle_manual': 20}) (self.operation_2 | self.operation_3).write({'time_cycle_manual': 10}) man_order = self.env['mrp.production'].create({ 'name': 'MO-Test', 'product_id': self.product_6.id, 'product_uom_id': self.product_6.uom_id.id, 'product_qty': 48, 'bom_id': self.bom_3.id, }) # reset quantities self.env['stock.change.product.qty'].create({ 'product_id': self.product_1.id, 'new_quantity': 0.0, 'location_id': self.warehouse_1.lot_stock_id.id, }).change_product_qty() (self.product_2 | self.product_4).write({ 'tracking': 'none', }) # assign consume material man_order.action_assign() self.assertEqual(man_order.availability, 'waiting', "Production order should be in waiting state.") # check consume materials of manufacturing order self.assertEqual(len(man_order.move_raw_ids), 4, "Consume material lines are not generated proper.") product_2_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_2) product_3_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_3) product_4_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_4) product_5_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_5) consume_qty_2 = product_2_consume_moves.product_uom_qty self.assertEqual(consume_qty_2, 24.0, "Consume material quantity of Wood should be 24 instead of %s" % str(consume_qty_2)) consume_qty_3 = product_3_consume_moves.product_uom_qty self.assertEqual(consume_qty_3, 12.0, "Consume material quantity of Stone should be 12 instead of %s" % str(consume_qty_3)) self.assertEqual(len(product_4_consume_moves), 2, "Consume move are not generated proper.") for consume_moves in product_4_consume_moves: consume_qty_4 = consume_moves.product_uom_qty self.assertIn(consume_qty_4, [8.0, 16.0], "Consume material quantity of Stick should be 8 or 16 instead of %s" % str(consume_qty_4)) self.assertFalse(product_5_consume_moves, "Move should not create for phantom bom") # create required lots lot_product_2 = self.env['stock.production.lot'].create({'product_id': self.product_2.id}) lot_product_4 = self.env['stock.production.lot'].create({'product_id': self.product_4.id}) # refuel stock inventory = self.env['stock.inventory'].create({ 'name': 'Inventory For Product C', 'filter': 'partial', 'line_ids': [(0, 0, { 'product_id': self.product_2.id, 'product_uom_id': self.product_2.uom_id.id, 'product_qty': 30, 'prod_lot_id': lot_product_2.id, 'location_id': self.ref('stock.stock_location_14') }), (0, 0, { 'product_id': self.product_3.id, 'product_uom_id': self.product_3.uom_id.id, 'product_qty': 60, 'location_id': self.ref('stock.stock_location_14') }), (0, 0, { 'product_id': self.product_4.id, 'product_uom_id': self.product_4.uom_id.id, 'product_qty': 60, 'prod_lot_id': lot_product_4.id, 'location_id': self.ref('stock.stock_location_14') })] }) inventory.prepare_inventory() inventory.action_done() # re-assign consume material man_order.action_assign() # Check production order status after assign. self.assertEqual(man_order.availability, 'assigned', "Production order should be in assigned state.") # Plan production order. man_order.button_plan() # check workorders # - main bom: Door: 2 operations # operation 1: Cutting # operation 2: Welding, waiting for the previous one # - kit bom: Stone Tool: 1 operation # operation 1: Gift Wrapping workorders = man_order.workorder_ids kit_wo = man_order.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_1) door_wo_1 = man_order.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_2) door_wo_2 = man_order.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_3) for workorder in workorders: self.assertEqual(workorder.workcenter_id, self.workcenter_1, "Workcenter does not match.") self.assertEqual(kit_wo.state, 'ready', "Workorder should be in ready state.") self.assertEqual(door_wo_1.state, 'ready', "Workorder should be in ready state.") self.assertEqual(door_wo_2.state, 'pending', "Workorder should be in pending state.") self.assertEqual(kit_wo.duration_expected, 80, "Workorder duration should be 80 instead of %s." % str(kit_wo.duration_expected)) self.assertEqual(door_wo_1.duration_expected, 20, "Workorder duration should be 20 instead of %s." % str(door_wo_1.duration_expected)) self.assertEqual(door_wo_2.duration_expected, 20, "Workorder duration should be 20 instead of %s." % str(door_wo_2.duration_expected)) # subbom: kit for stone tools kit_wo.button_start() finished_lot = self.env['stock.production.lot'].create({'product_id': man_order.product_id.id}) kit_wo.write({ 'final_lot_id': finished_lot.id, 'qty_producing': 48 }) kit_wo.record_production() self.assertEqual(kit_wo.state, 'done', "Workorder should be in done state.") # first operation of main bom finished_lot = self.env['stock.production.lot'].create({'product_id': man_order.product_id.id}) door_wo_1.write({ 'final_lot_id': finished_lot.id, 'qty_producing': 48 }) door_wo_1.record_production() self.assertEqual(door_wo_1.state, 'done', "Workorder should be in done state.") # second operation of main bom self.assertEqual(door_wo_2.state, 'ready', "Workorder should be in ready state.") door_wo_2.record_production() self.assertEqual(door_wo_2.state, 'done', "Workorder should be in done state.") def test_production_avialability(self): """ Test availability of production order. """ self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_5).unlink() self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_4).unlink() production_2 = self.env['mrp.production'].create({ 'name': 'MO-Test001', 'product_id': self.product_6.id, 'product_qty': 5.0, 'bom_id': self.bom_3.id, 'product_uom_id': self.product_6.uom_id.id, }) production_2.action_assign() # check sub product availability state is waiting self.assertEqual(production_2.availability, 'waiting', 'Production order should be availability for waiting state') # Update Inventory inventory_wizard = self.env['stock.change.product.qty'].create({ 'product_id': self.product_2.id, 'new_quantity': 2.0, }) inventory_wizard.change_product_qty() production_2.action_assign() # check sub product availability state is partially available self.assertEqual(production_2.availability, 'partially_available', 'Production order should be availability for partially available state') # Update Inventory inventory_wizard = self.env['stock.change.product.qty'].create({ 'product_id': self.product_2.id, 'new_quantity': 5.0, }) inventory_wizard.change_product_qty() production_2.action_assign() # check sub product availability state is assigned self.assertEqual(production_2.availability, 'assigned', 'Production order should be availability for assigned state') def test_empty_routing(self): """ Check what happens when you work with an empty routing""" routing = self.env['mrp.routing'].create({'name': 'Routing without operations', 'location_id': self.warehouse_1.wh_input_stock_loc_id.id,}) self.bom_3.routing_id = routing.id production = self.env['mrp.production'].create({'name': 'MO test', 'product_id': self.product_6.id, 'product_qty': 3, 'bom_id': self.bom_3.id, 'product_uom_id': self.product_6.uom_id.id,}) self.assertEqual(production.routing_id.id, False, 'The routing field should be empty on the mo') self.assertEqual(production.move_raw_ids[0].location_id.id, self.warehouse_1.wh_input_stock_loc_id.id, 'Raw moves start location should have altered.') def test_multiple_post_inventory(self): """ Check the consumed quants of the produced quants when intermediate calls to `post_inventory` during a MO.""" # create a bom for `custom_laptop` with components that aren't tracked unit = self.ref("product.product_uom_unit") custom_laptop = self.env.ref("product.product_product_27") custom_laptop.tracking = 'none' product_charger = self.env['product.product'].create({ 'name': 'Charger', 'type': 'product', 'uom_id': unit, 'uom_po_id': unit}) product_keybord = self.env['product.product'].create({ 'name': 'Usb Keybord', 'type': 'product', 'uom_id': unit, 'uom_po_id': unit}) bom_custom_laptop = self.env['mrp.bom'].create({ 'product_tmpl_id': custom_laptop.product_tmpl_id.id, 'product_qty': 1, 'product_uom_id': unit, 'bom_line_ids': [(0, 0, { 'product_id': product_charger.id, 'product_qty': 1, 'product_uom_id': unit }), (0, 0, { 'product_id': product_keybord.id, 'product_qty': 1, 'product_uom_id': unit })] }) # put the needed products in stock source_location_id = self.ref('stock.stock_location_14') inventory = self.env['stock.inventory'].create({ 'name': 'Inventory Product Table', 'filter': 'partial', 'line_ids': [(0, 0, { 'product_id': product_charger.id, 'product_uom_id': product_charger.uom_id.id, 'product_qty': 2, 'location_id': source_location_id }), (0, 0, { 'product_id': product_keybord.id, 'product_uom_id': product_keybord.uom_id.id, 'product_qty': 2, 'location_id': source_location_id })] }) inventory.action_done() # create a mo for this bom mo_custom_laptop = self.env['mrp.production'].create({ 'product_id': custom_laptop.id, 'product_qty': 2, 'product_uom_id': unit, 'bom_id': bom_custom_laptop.id }) mo_custom_laptop.action_assign() self.assertEqual(mo_custom_laptop.availability, 'assigned') # produce one item, call `post_inventory` context = {"active_ids": [mo_custom_laptop.id], "active_id": mo_custom_laptop.id} custom_laptop_produce = self.env['mrp.product.produce'].with_context(context).create({'product_qty': 1.00}) custom_laptop_produce.do_produce() mo_custom_laptop.post_inventory() # check the consumed quants of the produced quant first_move = mo_custom_laptop.move_finished_ids.filtered(lambda mo: mo.state == 'done') self.assertEquals(sum(first_move.quant_ids.mapped('consumed_quant_ids').mapped('qty')), 2) second_move = mo_custom_laptop.move_finished_ids.filtered(lambda mo: mo.state == 'confirmed') # produce the second item, call `post_inventory` context = {"active_ids": [mo_custom_laptop.id], "active_id": mo_custom_laptop.id} custom_laptop_produce = self.env['mrp.product.produce'].with_context(context).create({'product_qty': 1.00}) custom_laptop_produce.do_produce() mo_custom_laptop.post_inventory() # check the consumed quants of the newly produced quant self.assertEquals(sum(second_move.quant_ids.mapped('consumed_quant_ids').mapped('qty')), 2) def test_rounding(self): """ In previous versions we had rounding and efficiency fields. We check if we can still do the same, but with only the rounding on the UoM""" self.product_6.uom_id.rounding = 1.0 bom_eff = self.env['mrp.bom'].create({'product_id': self.product_6.id, 'product_tmpl_id': self.product_6.product_tmpl_id.id, 'product_qty': 1, 'product_uom_id': self.product_6.uom_id.id, 'type': 'normal', 'bom_line_ids': [ (0, 0, {'product_id': self.product_2.id, 'product_qty': 2.03}), (0, 0, {'product_id': self.product_8.id, 'product_qty': 4.16}) ]}) production = self.env['mrp.production'].create({'name': 'MO efficiency test', 'product_id': self.product_6.id, 'product_qty': 20, 'bom_id': bom_eff.id, 'product_uom_id': self.product_6.uom_id.id,}) #Check the production order has the right quantities self.assertEqual(production.move_raw_ids[0].product_qty, 41, 'The quantity should be rounded up') self.assertEqual(production.move_raw_ids[1].product_qty, 84, 'The quantity should be rounded up') # produce product produce_wizard = self.env['mrp.product.produce'].with_context({ 'active_id': production.id, 'active_ids': [production.id], }).create({ 'product_qty': 8, }) produce_wizard.do_produce() self.assertEqual(production.move_raw_ids[0].quantity_done, 16, 'Should use half-up rounding when producing') self.assertEqual(production.move_raw_ids[1].quantity_done, 34, 'Should use half-up rounding when producing')