diff --git a/addons/mrp/models/stock_warehouse.py b/addons/mrp/models/stock_warehouse.py index d2ec6623ebf..436e0beacf7 100644 --- a/addons/mrp/models/stock_warehouse.py +++ b/addons/mrp/models/stock_warehouse.py @@ -13,13 +13,13 @@ class StockWarehouse(models.Model): 'Manufacture to Resupply', default=True, help="When products are manufactured, they can be manufactured in this warehouse.") manufacture_pull_id = fields.Many2one( - 'stock.rule', 'Manufacture Rule') + 'stock.rule', 'Manufacture Rule', copy=False) manufacture_mto_pull_id = fields.Many2one( - 'stock.rule', 'Manufacture MTO Rule') + 'stock.rule', 'Manufacture MTO Rule', copy=False) pbm_mto_pull_id = fields.Many2one( - 'stock.rule', 'Picking Before Manufacturing MTO Rule') + 'stock.rule', 'Picking Before Manufacturing MTO Rule', copy=False) sam_rule_id = fields.Many2one( - 'stock.rule', 'Stock After Manufacturing Rule') + 'stock.rule', 'Stock After Manufacturing Rule', copy=False) manu_type_id = fields.Many2one( 'stock.picking.type', 'Manufacturing Operation Type', domain="[('code', '=', 'mrp_operation'), ('company_id', '=', company_id)]", check_company=True) @@ -37,7 +37,7 @@ class StockWarehouse(models.Model): the components from the Stock to Input location first, and then\ transfer it to the Production location.") - pbm_route_id = fields.Many2one('stock.route', 'Picking Before Manufacturing Route', ondelete='restrict') + pbm_route_id = fields.Many2one('stock.route', 'Picking Before Manufacturing Route', ondelete='restrict', copy=False) pbm_loc_id = fields.Many2one('stock.location', 'Picking before Manufacturing Location', check_company=True) sam_loc_id = fields.Many2one('stock.location', 'Stock after Manufacturing Location', check_company=True) diff --git a/addons/mrp_subcontracting/models/stock_warehouse.py b/addons/mrp_subcontracting/models/stock_warehouse.py index c50de0abf10..dca3fde863e 100644 --- a/addons/mrp_subcontracting/models/stock_warehouse.py +++ b/addons/mrp_subcontracting/models/stock_warehouse.py @@ -10,19 +10,19 @@ class StockWarehouse(models.Model): subcontracting_to_resupply = fields.Boolean( 'Resupply Subcontractors', default=True) subcontracting_mto_pull_id = fields.Many2one( - 'stock.rule', 'Subcontracting MTO Rule') + 'stock.rule', 'Subcontracting MTO Rule', copy=False) subcontracting_pull_id = fields.Many2one( - 'stock.rule', 'Subcontracting MTS Rule' + 'stock.rule', 'Subcontracting MTS Rule', copy=False ) - subcontracting_route_id = fields.Many2one('stock.route', 'Resupply Subcontractor', ondelete='restrict') + subcontracting_route_id = fields.Many2one('stock.route', 'Resupply Subcontractor', ondelete='restrict', copy=False) subcontracting_type_id = fields.Many2one( 'stock.picking.type', 'Subcontracting Operation Type', - domain=[('code', '=', 'mrp_operation')]) + domain=[('code', '=', 'mrp_operation')], copy=False) subcontracting_resupply_type_id = fields.Many2one( 'stock.picking.type', 'Subcontracting Resupply Operation Type', - domain=[('code', '=', 'outgoing')]) + domain=[('code', '=', 'outgoing')], copy=False) @api.model_create_multi def create(self, vals_list): diff --git a/addons/mrp_subcontracting/tests/test_subcontracting.py b/addons/mrp_subcontracting/tests/test_subcontracting.py index 94b3af90295..3c159c96f9a 100644 --- a/addons/mrp_subcontracting/tests/test_subcontracting.py +++ b/addons/mrp_subcontracting/tests/test_subcontracting.py @@ -21,6 +21,43 @@ class TestSubcontractingBasic(TransactionCase): self.assertTrue(company2.subcontracting_location_id) self.assertTrue(self.env.company.subcontracting_location_id != company2.subcontracting_location_id) + def test_duplicating_warehouses_recreates_their_routes_and_operation_types(self): + """ Duplicating a warehouse should result in the creation of new routes and operation types. + Not reusing the existing routes and operation types""" + wh_original = self.env['stock.warehouse'].search([], limit=1) + wh_copy = wh_original.copy(default={'name': 'Dummy Warehouse (copy)', 'code': 'Dummy'}) + + # Check if warehouse routes got RECREATED (instead of reused) + route_types = [ + "route_ids", + "pbm_route_id", + "subcontracting_route_id", + "crossdock_route_id", + "reception_route_id", + "delivery_route_id" + ] + for route_type in route_types: + original_route_set = wh_original[route_type] + copy_route_set = wh_copy[route_type] + error_message = f"At least one {route_type} (route) got reused on duplication (should have been recreated)" + self.assertEqual(len(original_route_set & copy_route_set), 0, error_message) + + # Check if warehouse operation types (picking.type) got RECREATED (instead of reused) + operation_types = [ + "subcontracting_type_id", + "subcontracting_resupply_type_id", + "pick_type_id", + "pack_type_id", + "out_type_id", + "in_type_id", + "int_type_id" + ] + for operation_type in operation_types: + original_type_set = wh_original[operation_type] + copy_type_set = wh_copy[operation_type] + error_message = f"At least one {operation_type} (operation_type) got reused on duplication (should have been recreated)" + self.assertEqual(len(original_type_set & copy_type_set), 0, error_message) + @tagged('post_install', '-at_install') class TestSubcontractingFlows(TestMrpSubcontractingCommon): diff --git a/addons/mrp_subcontracting_dropshipping/models/stock_warehouse.py b/addons/mrp_subcontracting_dropshipping/models/stock_warehouse.py index 5f7592a2b16..a9921ae777f 100644 --- a/addons/mrp_subcontracting_dropshipping/models/stock_warehouse.py +++ b/addons/mrp_subcontracting_dropshipping/models/stock_warehouse.py @@ -12,7 +12,7 @@ class StockWarehouse(models.Model): help="Dropship subcontractors with components") subcontracting_dropshipping_pull_id = fields.Many2one( - 'stock.rule', 'Subcontracting-Dropshipping MTS Rule' + 'stock.rule', 'Subcontracting-Dropshipping MTS Rule', copy=False ) @api.model_create_multi diff --git a/addons/purchase_stock/models/stock.py b/addons/purchase_stock/models/stock.py index c055acb3192..48f3736ec55 100644 --- a/addons/purchase_stock/models/stock.py +++ b/addons/purchase_stock/models/stock.py @@ -19,7 +19,7 @@ class StockWarehouse(models.Model): buy_to_resupply = fields.Boolean('Buy to Resupply', default=True, help="When products are bought, they can be delivered to this warehouse") - buy_pull_id = fields.Many2one('stock.rule', 'Buy rule') + buy_pull_id = fields.Many2one('stock.rule', 'Buy rule', copy=False) def _generate_global_route_rules_values(self): rules = super()._generate_global_route_rules_values() diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py index 540e6566a9a..aba9b0a1c00 100644 --- a/addons/stock/models/stock_warehouse.py +++ b/addons/stock/models/stock_warehouse.py @@ -53,7 +53,7 @@ class Warehouse(models.Model): 'stock.route', 'stock_route_warehouse', 'warehouse_id', 'route_id', 'Routes', domain="[('warehouse_selectable', '=', True), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", - help='Defaults routes through the warehouse', check_company=True) + help='Defaults routes through the warehouse', check_company=True, copy=False) reception_steps = fields.Selection([ ('one_step', 'Receive goods directly (1 step)'), ('two_steps', 'Receive goods in input and then stock (2 steps)'), @@ -70,21 +70,21 @@ class Warehouse(models.Model): wh_qc_stock_loc_id = fields.Many2one('stock.location', 'Quality Control Location', check_company=True) wh_output_stock_loc_id = fields.Many2one('stock.location', 'Output Location', check_company=True) wh_pack_stock_loc_id = fields.Many2one('stock.location', 'Packing Location', check_company=True) - mto_pull_id = fields.Many2one('stock.rule', 'MTO rule') - pick_type_id = fields.Many2one('stock.picking.type', 'Pick Type', check_company=True) - pack_type_id = fields.Many2one('stock.picking.type', 'Pack Type', check_company=True) - out_type_id = fields.Many2one('stock.picking.type', 'Out Type', check_company=True) - in_type_id = fields.Many2one('stock.picking.type', 'In Type', check_company=True) - int_type_id = fields.Many2one('stock.picking.type', 'Internal Type', check_company=True) - crossdock_route_id = fields.Many2one('stock.route', 'Crossdock Route', ondelete='restrict') - reception_route_id = fields.Many2one('stock.route', 'Receipt Route', ondelete='restrict') - delivery_route_id = fields.Many2one('stock.route', 'Delivery Route', ondelete='restrict') + mto_pull_id = fields.Many2one('stock.rule', 'MTO rule', copy=False) + pick_type_id = fields.Many2one('stock.picking.type', 'Pick Type', check_company=True, copy=False) + pack_type_id = fields.Many2one('stock.picking.type', 'Pack Type', check_company=True, copy=False) + out_type_id = fields.Many2one('stock.picking.type', 'Out Type', check_company=True, copy=False) + in_type_id = fields.Many2one('stock.picking.type', 'In Type', check_company=True, copy=False) + int_type_id = fields.Many2one('stock.picking.type', 'Internal Type', check_company=True, copy=False) + crossdock_route_id = fields.Many2one('stock.route', 'Crossdock Route', ondelete='restrict', copy=False) + reception_route_id = fields.Many2one('stock.route', 'Receipt Route', ondelete='restrict', copy=False) + delivery_route_id = fields.Many2one('stock.route', 'Delivery Route', ondelete='restrict', copy=False) resupply_wh_ids = fields.Many2many( 'stock.warehouse', 'stock_wh_resupply_table', 'supplied_wh_id', 'supplier_wh_id', 'Resupply From', help="Routes will be created automatically to resupply this warehouse from the warehouses ticked") resupply_route_ids = fields.One2many( 'stock.route', 'supplied_wh_id', 'Resupply Routes', - help="Routes will be created for these resupply warehouses and you can select them on products and product categories") + help="Routes will be created for these resupply warehouses and you can select them on products and product categories", copy=False) sequence = fields.Integer(default=10, help="Gives the sequence of this line when displaying the warehouses.") _sql_constraints = [