We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[13.0] stock_request error to create or selected product
I install stock_request but get error, at create new record or select product show this error, any idea??
![image](https://user-images.githubusercontent.com/7775116/95130511-4c944500-0722-11eb-9d81-47e63047fd3f.png)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `stock_request/models/stock_request_abstract.py`
Content:
```
1 # Copyright 2017-2020 ForgeFlow, S.L.
2 # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
3 
4 from odoo import _, api, fields, models
5 from odoo.exceptions import ValidationError
6 
7 
8 class StockRequest(models.AbstractModel):
9     _name = "stock.request.abstract"
10     _description = "Stock Request Template"
11     _inherit = ["mail.thread", "mail.activity.mixin"]
12 
13     @api.model
14     def default_get(self, fields):
15         res = super(StockRequest, self).default_get(fields)
16         warehouse = None
17         if "warehouse_id" not in res and res.get("company_id"):
18             warehouse = self.env["stock.warehouse"].search(
19                 [("company_id", "=", res["company_id"])], limit=1
20             )
21         if warehouse:
22             res["warehouse_id"] = warehouse.id
23             res["location_id"] = warehouse.lot_stock_id.id
24         return res
25 
26     @api.depends(
27         "product_id",
28         "product_uom_id",
29         "product_uom_qty",
30         "product_id.product_tmpl_id.uom_id",
31     )
32     def _compute_product_qty(self):
33         for rec in self:
34             rec.product_qty = rec.product_uom_id._compute_quantity(
35                 rec.product_uom_qty, rec.product_id.product_tmpl_id.uom_id
36             )
37 
38     name = fields.Char("Name", copy=False, required=True, readonly=True, default="/")
39     warehouse_id = fields.Many2one(
40         "stock.warehouse", "Warehouse", ondelete="cascade", required=True
41     )
42     location_id = fields.Many2one(
43         "stock.location",
44         "Location",
45         domain=[("usage", "in", ["internal", "transit"])],
46         ondelete="cascade",
47         required=True,
48     )
49     product_id = fields.Many2one(
50         "product.product",
51         "Product",
52         domain=[("type", "in", ["product", "consu"])],
53         ondelete="cascade",
54         required=True,
55     )
56     allow_virtual_location = fields.Boolean(
57         related="company_id.stock_request_allow_virtual_loc", readonly=True
58     )
59     product_uom_id = fields.Many2one(
60         "uom.uom",
61         "Product Unit of Measure",
62         required=True,
63         default=lambda self: self._context.get("product_uom_id", False),
64     )
65     product_uom_qty = fields.Float(
66         "Quantity",
67         digits="Product Unit of Measure",
68         required=True,
69         help="Quantity, specified in the unit of measure indicated in the request.",
70     )
71     product_qty = fields.Float(
72         "Real Quantity",
73         compute="_compute_product_qty",
74         store=True,
75         copy=False,
76         digits="Product Unit of Measure",
77         help="Quantity in the default UoM of the product",
78     )
79     procurement_group_id = fields.Many2one(
80         "procurement.group",
81         "Procurement Group",
82         help="Moves created through this stock request will be put in this "
83         "procurement group. If none is given, the moves generated by "
84         "procurement rules will be grouped into one big picking.",
85     )
86     company_id = fields.Many2one(
87         "res.company", "Company", required=True, default=lambda self: self.env.company
88     )
89     route_id = fields.Many2one(
90         "stock.location.route",
91         string="Route",
92         domain="[('id', 'in', route_ids)]",
93         ondelete="restrict",
94     )
95 
96     route_ids = fields.Many2many(
97         "stock.location.route",
98         string="Routes",
99         compute="_compute_route_ids",
100         readonly=True,
101     )
102 
103     _sql_constraints = [
104         ("name_uniq", "unique(name, company_id)", "Name must be unique")
105     ]
106 
107     @api.depends("product_id", "warehouse_id", "location_id")
108     def _compute_route_ids(self):
109         route_obj = self.env["stock.location.route"]
110         for wh in self.mapped("warehouse_id"):
111             wh_routes = route_obj.search([("warehouse_ids", "=", wh.id)])
112             for record in self.filtered(lambda r: r.warehouse_id == wh):
113                 routes = route_obj
114                 if record.product_id:
115                     routes += record.product_id.mapped(
116                         "route_ids"
117                     ) | record.product_id.mapped("categ_id").mapped("total_route_ids")
118                 if record.warehouse_id:
119                     routes |= wh_routes
120                 parents = record.get_parents().ids
121                 record.route_ids = routes.filtered(
122                     lambda r: any(p.location_id.id in parents for p in r.rule_ids)
123                 )
124 
125     def get_parents(self):
126         location = self.location_id
127         result = location
128         while location.location_id:
129             location = location.location_id
130             result |= location
131         return result
132 
133     @api.constrains(
134         "company_id", "product_id", "warehouse_id", "location_id", "route_id"
135     )
136     def _check_company_constrains(self):
137         """ Check if the related models have the same company """
138         for rec in self:
139             if (
140                 rec.product_id.company_id
141                 and rec.product_id.company_id != rec.company_id
142             ):
143                 raise ValidationError(
144                     _(
145                         "You have entered a product that is assigned "
146                         "to another company."
147                     )
148                 )
149             if (
150                 rec.location_id.company_id
151                 and rec.location_id.company_id != rec.company_id
152             ):
153                 raise ValidationError(
154                     _(
155                         "You have entered a location that is "
156                         "assigned to another company."
157                     )
158                 )
159             if rec.warehouse_id.company_id != rec.company_id:
160                 raise ValidationError(
161                     _(
162                         "You have entered a warehouse that is "
163                         "assigned to another company."
164                     )
165                 )
166             if (
167                 rec.route_id
168                 and rec.route_id.company_id
169                 and rec.route_id.company_id != rec.company_id
170             ):
171                 raise ValidationError(
172                     _(
173                         "You have entered a route that is "
174                         "assigned to another company."
175                     )
176                 )
177 
178     @api.constrains("product_id")
179     def _check_product_uom(self):
180         """ Check if the UoM has the same category as the
181         product standard UoM """
182         if any(
183             request.product_id.uom_id.category_id != request.product_uom_id.category_id
184             for request in self
185         ):
186             raise ValidationError(
187                 _(
188                     "You have to select a product unit of measure in the "
189                     "same category than the default unit "
190                     "of measure of the product"
191                 )
192             )
193 
194     @api.constrains("product_qty")
195     def _check_qty(self):
196         for rec in self:
197             if rec.product_qty <= 0:
198                 raise ValidationError(
199                     _("Stock Request product quantity has to be strictly positive.")
200                 )
201 
202     @api.onchange("warehouse_id")
203     def onchange_warehouse_id(self):
204         """ Finds location id for changed warehouse. """
205         res = {"domain": {}}
206         if self._name == "stock.request" and self.order_id:
207             # When the stock request is created from an order the wh and
208             # location are taken from the order and we rely on it to change
209             # all request associated. Thus, no need to apply
210             # the onchange, as it could lead to inconsistencies.
211             return res
212         if self.warehouse_id:
213             loc_wh = self.location_id.get_warehouse()
214             if self.warehouse_id != loc_wh:
215                 self.location_id = self.warehouse_id.lot_stock_id.id
216             if self.warehouse_id.company_id != self.company_id:
217                 self.company_id = self.warehouse_id.company_id
218         return res
219 
220     @api.onchange("location_id")
221     def onchange_location_id(self):
222         if self.location_id:
223             loc_wh = self.location_id.get_warehouse()
224             if loc_wh and self.warehouse_id != loc_wh:
225                 self.warehouse_id = loc_wh
226                 self.with_context(no_change_childs=True).onchange_warehouse_id()
227 
228     @api.onchange("allow_virtual_location")
229     def onchange_allow_virtual_location(self):
230         if self.allow_virtual_location:
231             return {"domain": {"location_id": []}}
232 
233     @api.onchange("company_id")
234     def onchange_company_id(self):
235         """ Sets a default warehouse when the company is changed and limits
236         the user selection of warehouses. """
237         if self.company_id and (
238             not self.warehouse_id or self.warehouse_id.company_id != self.company_id
239         ):
240             self.warehouse_id = self.env["stock.warehouse"].search(
241                 [("company_id", "=", self.company_id.id)], limit=1
242             )
243             self.onchange_warehouse_id()
244 
245         return {"domain": {"warehouse_id": [("company_id", "=", self.company_id.id)]}}
246 
247     @api.onchange("product_id")
248     def onchange_product_id(self):
249         res = {"domain": {}}
250         if self.product_id:
251             self.product_uom_id = self.product_id.uom_id.id
252             res["domain"]["product_uom_id"] = [
253                 ("category_id", "=", self.product_id.uom_id.category_id.id)
254             ]
255             return res
256         res["domain"]["product_uom_id"] = []
257         return res
258
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/stock_request/models/stock_request_abstract.py b/stock_request/models/stock_request_abstract.py
--- a/stock_request/models/stock_request_abstract.py
+++ b/stock_request/models/stock_request_abstract.py
@@ -107,20 +107,28 @@
     @api.depends("product_id", "warehouse_id", "location_id")
     def _compute_route_ids(self):
         route_obj = self.env["stock.location.route"]
-        for wh in self.mapped("warehouse_id"):
-            wh_routes = route_obj.search([("warehouse_ids", "=", wh.id)])
-            for record in self.filtered(lambda r: r.warehouse_id == wh):
-                routes = route_obj
-                if record.product_id:
-                    routes += record.product_id.mapped(
-                        "route_ids"
-                    ) | record.product_id.mapped("categ_id").mapped("total_route_ids")
-                if record.warehouse_id:
-                    routes |= wh_routes
-                parents = record.get_parents().ids
-                record.route_ids = routes.filtered(
-                    lambda r: any(p.location_id.id in parents for p in r.rule_ids)
+        routes = route_obj.search(
+            [("warehouse_ids", "in", self.mapped("warehouse_id").ids)]
+        )
+        routes_by_warehouse = {}
+        for route in routes:
+            for warehouse in route.warehouse_ids:
+                routes_by_warehouse.setdefault(
+                    warehouse.id, self.env["stock.location.route"]
                 )
+                routes_by_warehouse[warehouse.id] |= route
+        for record in self:
+            routes = route_obj
+            if record.product_id:
+                routes += record.product_id.mapped(
+                    "route_ids"
+                ) | record.product_id.mapped("categ_id").mapped("total_route_ids")
+            if record.warehouse_id and routes_by_warehouse.get(record.warehouse_id.id):
+                routes |= routes_by_warehouse[record.warehouse_id.id]
+            parents = record.get_parents().ids
+            record.route_ids = routes.filtered(
+                lambda r: any(p.location_id.id in parents for p in r.rule_ids)
+            )
 
     def get_parents(self):
         location = self.location_id

{"golden_diff": "diff --git a/stock_request/models/stock_request_abstract.py b/stock_request/models/stock_request_abstract.py\n--- a/stock_request/models/stock_request_abstract.py\n+++ b/stock_request/models/stock_request_abstract.py\n@@ -107,20 +107,28 @@\n     @api.depends(\"product_id\", \"warehouse_id\", \"location_id\")\n     def _compute_route_ids(self):\n         route_obj = self.env[\"stock.location.route\"]\n-        for wh in self.mapped(\"warehouse_id\"):\n-            wh_routes = route_obj.search([(\"warehouse_ids\", \"=\", wh.id)])\n-            for record in self.filtered(lambda r: r.warehouse_id == wh):\n-                routes = route_obj\n-                if record.product_id:\n-                    routes += record.product_id.mapped(\n-                        \"route_ids\"\n-                    ) | record.product_id.mapped(\"categ_id\").mapped(\"total_route_ids\")\n-                if record.warehouse_id:\n-                    routes |= wh_routes\n-                parents = record.get_parents().ids\n-                record.route_ids = routes.filtered(\n-                    lambda r: any(p.location_id.id in parents for p in r.rule_ids)\n+        routes = route_obj.search(\n+            [(\"warehouse_ids\", \"in\", self.mapped(\"warehouse_id\").ids)]\n+        )\n+        routes_by_warehouse = {}\n+        for route in routes:\n+            for warehouse in route.warehouse_ids:\n+                routes_by_warehouse.setdefault(\n+                    warehouse.id, self.env[\"stock.location.route\"]\n                 )\n+                routes_by_warehouse[warehouse.id] |= route\n+        for record in self:\n+            routes = route_obj\n+            if record.product_id:\n+                routes += record.product_id.mapped(\n+                    \"route_ids\"\n+                ) | record.product_id.mapped(\"categ_id\").mapped(\"total_route_ids\")\n+            if record.warehouse_id and routes_by_warehouse.get(record.warehouse_id.id):\n+                routes |= routes_by_warehouse[record.warehouse_id.id]\n+            parents = record.get_parents().ids\n+            record.route_ids = routes.filtered(\n+                lambda r: any(p.location_id.id in parents for p in r.rule_ids)\n+            )\n \n     def get_parents(self):\n         location = self.location_id\n", "issue": "[13.0] stock_request error to create or selected product\nI install stock_request but get error, at create new record or select product show this error, any idea??\r\n![image](https://user-images.githubusercontent.com/7775116/95130511-4c944500-0722-11eb-9d81-47e63047fd3f.png)\r\n\n", "before_files": [{"content": "# Copyright 2017-2020 ForgeFlow, S.L.\n# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).\n\nfrom odoo import _, api, fields, models\nfrom odoo.exceptions import ValidationError\n\n\nclass StockRequest(models.AbstractModel):\n    _name = \"stock.request.abstract\"\n    _description = \"Stock Request Template\"\n    _inherit = [\"mail.thread\", \"mail.activity.mixin\"]\n\n    @api.model\n    def default_get(self, fields):\n        res = super(StockRequest, self).default_get(fields)\n        warehouse = None\n        if \"warehouse_id\" not in res and res.get(\"company_id\"):\n            warehouse = self.env[\"stock.warehouse\"].search(\n                [(\"company_id\", \"=\", res[\"company_id\"])], limit=1\n            )\n        if warehouse:\n            res[\"warehouse_id\"] = warehouse.id\n            res[\"location_id\"] = warehouse.lot_stock_id.id\n        return res\n\n    @api.depends(\n        \"product_id\",\n        \"product_uom_id\",\n        \"product_uom_qty\",\n        \"product_id.product_tmpl_id.uom_id\",\n    )\n    def _compute_product_qty(self):\n        for rec in self:\n            rec.product_qty = rec.product_uom_id._compute_quantity(\n                rec.product_uom_qty, rec.product_id.product_tmpl_id.uom_id\n            )\n\n    name = fields.Char(\"Name\", copy=False, required=True, readonly=True, default=\"/\")\n    warehouse_id = fields.Many2one(\n        \"stock.warehouse\", \"Warehouse\", ondelete=\"cascade\", required=True\n    )\n    location_id = fields.Many2one(\n        \"stock.location\",\n        \"Location\",\n        domain=[(\"usage\", \"in\", [\"internal\", \"transit\"])],\n        ondelete=\"cascade\",\n        required=True,\n    )\n    product_id = fields.Many2one(\n        \"product.product\",\n        \"Product\",\n        domain=[(\"type\", \"in\", [\"product\", \"consu\"])],\n        ondelete=\"cascade\",\n        required=True,\n    )\n    allow_virtual_location = fields.Boolean(\n        related=\"company_id.stock_request_allow_virtual_loc\", readonly=True\n    )\n    product_uom_id = fields.Many2one(\n        \"uom.uom\",\n        \"Product Unit of Measure\",\n        required=True,\n        default=lambda self: self._context.get(\"product_uom_id\", False),\n    )\n    product_uom_qty = fields.Float(\n        \"Quantity\",\n        digits=\"Product Unit of Measure\",\n        required=True,\n        help=\"Quantity, specified in the unit of measure indicated in the request.\",\n    )\n    product_qty = fields.Float(\n        \"Real Quantity\",\n        compute=\"_compute_product_qty\",\n        store=True,\n        copy=False,\n        digits=\"Product Unit of Measure\",\n        help=\"Quantity in the default UoM of the product\",\n    )\n    procurement_group_id = fields.Many2one(\n        \"procurement.group\",\n        \"Procurement Group\",\n        help=\"Moves created through this stock request will be put in this \"\n        \"procurement group. If none is given, the moves generated by \"\n        \"procurement rules will be grouped into one big picking.\",\n    )\n    company_id = fields.Many2one(\n        \"res.company\", \"Company\", required=True, default=lambda self: self.env.company\n    )\n    route_id = fields.Many2one(\n        \"stock.location.route\",\n        string=\"Route\",\n        domain=\"[('id', 'in', route_ids)]\",\n        ondelete=\"restrict\",\n    )\n\n    route_ids = fields.Many2many(\n        \"stock.location.route\",\n        string=\"Routes\",\n        compute=\"_compute_route_ids\",\n        readonly=True,\n    )\n\n    _sql_constraints = [\n        (\"name_uniq\", \"unique(name, company_id)\", \"Name must be unique\")\n    ]\n\n    @api.depends(\"product_id\", \"warehouse_id\", \"location_id\")\n    def _compute_route_ids(self):\n        route_obj = self.env[\"stock.location.route\"]\n        for wh in self.mapped(\"warehouse_id\"):\n            wh_routes = route_obj.search([(\"warehouse_ids\", \"=\", wh.id)])\n            for record in self.filtered(lambda r: r.warehouse_id == wh):\n                routes = route_obj\n                if record.product_id:\n                    routes += record.product_id.mapped(\n                        \"route_ids\"\n                    ) | record.product_id.mapped(\"categ_id\").mapped(\"total_route_ids\")\n                if record.warehouse_id:\n                    routes |= wh_routes\n                parents = record.get_parents().ids\n                record.route_ids = routes.filtered(\n                    lambda r: any(p.location_id.id in parents for p in r.rule_ids)\n                )\n\n    def get_parents(self):\n        location = self.location_id\n        result = location\n        while location.location_id:\n            location = location.location_id\n            result |= location\n        return result\n\n    @api.constrains(\n        \"company_id\", \"product_id\", \"warehouse_id\", \"location_id\", \"route_id\"\n    )\n    def _check_company_constrains(self):\n        \"\"\" Check if the related models have the same company \"\"\"\n        for rec in self:\n            if (\n                rec.product_id.company_id\n                and rec.product_id.company_id != rec.company_id\n            ):\n                raise ValidationError(\n                    _(\n                        \"You have entered a product that is assigned \"\n                        \"to another company.\"\n                    )\n                )\n            if (\n                rec.location_id.company_id\n                and rec.location_id.company_id != rec.company_id\n            ):\n                raise ValidationError(\n                    _(\n                        \"You have entered a location that is \"\n                        \"assigned to another company.\"\n                    )\n                )\n            if rec.warehouse_id.company_id != rec.company_id:\n                raise ValidationError(\n                    _(\n                        \"You have entered a warehouse that is \"\n                        \"assigned to another company.\"\n                    )\n                )\n            if (\n                rec.route_id\n                and rec.route_id.company_id\n                and rec.route_id.company_id != rec.company_id\n            ):\n                raise ValidationError(\n                    _(\n                        \"You have entered a route that is \"\n                        \"assigned to another company.\"\n                    )\n                )\n\n    @api.constrains(\"product_id\")\n    def _check_product_uom(self):\n        \"\"\" Check if the UoM has the same category as the\n        product standard UoM \"\"\"\n        if any(\n            request.product_id.uom_id.category_id != request.product_uom_id.category_id\n            for request in self\n        ):\n            raise ValidationError(\n                _(\n                    \"You have to select a product unit of measure in the \"\n                    \"same category than the default unit \"\n                    \"of measure of the product\"\n                )\n            )\n\n    @api.constrains(\"product_qty\")\n    def _check_qty(self):\n        for rec in self:\n            if rec.product_qty <= 0:\n                raise ValidationError(\n                    _(\"Stock Request product quantity has to be strictly positive.\")\n                )\n\n    @api.onchange(\"warehouse_id\")\n    def onchange_warehouse_id(self):\n        \"\"\" Finds location id for changed warehouse. \"\"\"\n        res = {\"domain\": {}}\n        if self._name == \"stock.request\" and self.order_id:\n            # When the stock request is created from an order the wh and\n            # location are taken from the order and we rely on it to change\n            # all request associated. Thus, no need to apply\n            # the onchange, as it could lead to inconsistencies.\n            return res\n        if self.warehouse_id:\n            loc_wh = self.location_id.get_warehouse()\n            if self.warehouse_id != loc_wh:\n                self.location_id = self.warehouse_id.lot_stock_id.id\n            if self.warehouse_id.company_id != self.company_id:\n                self.company_id = self.warehouse_id.company_id\n        return res\n\n    @api.onchange(\"location_id\")\n    def onchange_location_id(self):\n        if self.location_id:\n            loc_wh = self.location_id.get_warehouse()\n            if loc_wh and self.warehouse_id != loc_wh:\n                self.warehouse_id = loc_wh\n                self.with_context(no_change_childs=True).onchange_warehouse_id()\n\n    @api.onchange(\"allow_virtual_location\")\n    def onchange_allow_virtual_location(self):\n        if self.allow_virtual_location:\n            return {\"domain\": {\"location_id\": []}}\n\n    @api.onchange(\"company_id\")\n    def onchange_company_id(self):\n        \"\"\" Sets a default warehouse when the company is changed and limits\n        the user selection of warehouses. \"\"\"\n        if self.company_id and (\n            not self.warehouse_id or self.warehouse_id.company_id != self.company_id\n        ):\n            self.warehouse_id = self.env[\"stock.warehouse\"].search(\n                [(\"company_id\", \"=\", self.company_id.id)], limit=1\n            )\n            self.onchange_warehouse_id()\n\n        return {\"domain\": {\"warehouse_id\": [(\"company_id\", \"=\", self.company_id.id)]}}\n\n    @api.onchange(\"product_id\")\n    def onchange_product_id(self):\n        res = {\"domain\": {}}\n        if self.product_id:\n            self.product_uom_id = self.product_id.uom_id.id\n            res[\"domain\"][\"product_uom_id\"] = [\n                (\"category_id\", \"=\", self.product_id.uom_id.category_id.id)\n            ]\n            return res\n        res[\"domain\"][\"product_uom_id\"] = []\n        return res\n", "path": "stock_request/models/stock_request_abstract.py"}], "after_files": [{"content": "# Copyright 2017-2020 ForgeFlow, S.L.\n# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).\n\nfrom odoo import _, api, fields, models\nfrom odoo.exceptions import ValidationError\n\n\nclass StockRequest(models.AbstractModel):\n    _name = \"stock.request.abstract\"\n    _description = \"Stock Request Template\"\n    _inherit = [\"mail.thread\", \"mail.activity.mixin\"]\n\n    @api.model\n    def default_get(self, fields):\n        res = super(StockRequest, self).default_get(fields)\n        warehouse = None\n        if \"warehouse_id\" not in res and res.get(\"company_id\"):\n            warehouse = self.env[\"stock.warehouse\"].search(\n                [(\"company_id\", \"=\", res[\"company_id\"])], limit=1\n            )\n        if warehouse:\n            res[\"warehouse_id\"] = warehouse.id\n            res[\"location_id\"] = warehouse.lot_stock_id.id\n        return res\n\n    @api.depends(\n        \"product_id\",\n        \"product_uom_id\",\n        \"product_uom_qty\",\n        \"product_id.product_tmpl_id.uom_id\",\n    )\n    def _compute_product_qty(self):\n        for rec in self:\n            rec.product_qty = rec.product_uom_id._compute_quantity(\n                rec.product_uom_qty, rec.product_id.product_tmpl_id.uom_id\n            )\n\n    name = fields.Char(\"Name\", copy=False, required=True, readonly=True, default=\"/\")\n    warehouse_id = fields.Many2one(\n        \"stock.warehouse\", \"Warehouse\", ondelete=\"cascade\", required=True\n    )\n    location_id = fields.Many2one(\n        \"stock.location\",\n        \"Location\",\n        domain=[(\"usage\", \"in\", [\"internal\", \"transit\"])],\n        ondelete=\"cascade\",\n        required=True,\n    )\n    product_id = fields.Many2one(\n        \"product.product\",\n        \"Product\",\n        domain=[(\"type\", \"in\", [\"product\", \"consu\"])],\n        ondelete=\"cascade\",\n        required=True,\n    )\n    allow_virtual_location = fields.Boolean(\n        related=\"company_id.stock_request_allow_virtual_loc\", readonly=True\n    )\n    product_uom_id = fields.Many2one(\n        \"uom.uom\",\n        \"Product Unit of Measure\",\n        required=True,\n        default=lambda self: self._context.get(\"product_uom_id\", False),\n    )\n    product_uom_qty = fields.Float(\n        \"Quantity\",\n        digits=\"Product Unit of Measure\",\n        required=True,\n        help=\"Quantity, specified in the unit of measure indicated in the request.\",\n    )\n    product_qty = fields.Float(\n        \"Real Quantity\",\n        compute=\"_compute_product_qty\",\n        store=True,\n        copy=False,\n        digits=\"Product Unit of Measure\",\n        help=\"Quantity in the default UoM of the product\",\n    )\n    procurement_group_id = fields.Many2one(\n        \"procurement.group\",\n        \"Procurement Group\",\n        help=\"Moves created through this stock request will be put in this \"\n        \"procurement group. If none is given, the moves generated by \"\n        \"procurement rules will be grouped into one big picking.\",\n    )\n    company_id = fields.Many2one(\n        \"res.company\", \"Company\", required=True, default=lambda self: self.env.company\n    )\n    route_id = fields.Many2one(\n        \"stock.location.route\",\n        string=\"Route\",\n        domain=\"[('id', 'in', route_ids)]\",\n        ondelete=\"restrict\",\n    )\n\n    route_ids = fields.Many2many(\n        \"stock.location.route\",\n        string=\"Routes\",\n        compute=\"_compute_route_ids\",\n        readonly=True,\n    )\n\n    _sql_constraints = [\n        (\"name_uniq\", \"unique(name, company_id)\", \"Name must be unique\")\n    ]\n\n    @api.depends(\"product_id\", \"warehouse_id\", \"location_id\")\n    def _compute_route_ids(self):\n        route_obj = self.env[\"stock.location.route\"]\n        routes = route_obj.search(\n            [(\"warehouse_ids\", \"in\", self.mapped(\"warehouse_id\").ids)]\n        )\n        routes_by_warehouse = {}\n        for route in routes:\n            for warehouse in route.warehouse_ids:\n                routes_by_warehouse.setdefault(\n                    warehouse.id, self.env[\"stock.location.route\"]\n                )\n                routes_by_warehouse[warehouse.id] |= route\n        for record in self:\n            routes = route_obj\n            if record.product_id:\n                routes += record.product_id.mapped(\n                    \"route_ids\"\n                ) | record.product_id.mapped(\"categ_id\").mapped(\"total_route_ids\")\n            if record.warehouse_id and routes_by_warehouse.get(record.warehouse_id.id):\n                routes |= routes_by_warehouse[record.warehouse_id.id]\n            parents = record.get_parents().ids\n            record.route_ids = routes.filtered(\n                lambda r: any(p.location_id.id in parents for p in r.rule_ids)\n            )\n\n    def get_parents(self):\n        location = self.location_id\n        result = location\n        while location.location_id:\n            location = location.location_id\n            result |= location\n        return result\n\n    @api.constrains(\n        \"company_id\", \"product_id\", \"warehouse_id\", \"location_id\", \"route_id\"\n    )\n    def _check_company_constrains(self):\n        \"\"\" Check if the related models have the same company \"\"\"\n        for rec in self:\n            if (\n                rec.product_id.company_id\n                and rec.product_id.company_id != rec.company_id\n            ):\n                raise ValidationError(\n                    _(\n                        \"You have entered a product that is assigned \"\n                        \"to another company.\"\n                    )\n                )\n            if (\n                rec.location_id.company_id\n                and rec.location_id.company_id != rec.company_id\n            ):\n                raise ValidationError(\n                    _(\n                        \"You have entered a location that is \"\n                        \"assigned to another company.\"\n                    )\n                )\n            if rec.warehouse_id.company_id != rec.company_id:\n                raise ValidationError(\n                    _(\n                        \"You have entered a warehouse that is \"\n                        \"assigned to another company.\"\n                    )\n                )\n            if (\n                rec.route_id\n                and rec.route_id.company_id\n                and rec.route_id.company_id != rec.company_id\n            ):\n                raise ValidationError(\n                    _(\n                        \"You have entered a route that is \"\n                        \"assigned to another company.\"\n                    )\n                )\n\n    @api.constrains(\"product_id\")\n    def _check_product_uom(self):\n        \"\"\" Check if the UoM has the same category as the\n        product standard UoM \"\"\"\n        if any(\n            request.product_id.uom_id.category_id != request.product_uom_id.category_id\n            for request in self\n        ):\n            raise ValidationError(\n                _(\n                    \"You have to select a product unit of measure in the \"\n                    \"same category than the default unit \"\n                    \"of measure of the product\"\n                )\n            )\n\n    @api.constrains(\"product_qty\")\n    def _check_qty(self):\n        for rec in self:\n            if rec.product_qty <= 0:\n                raise ValidationError(\n                    _(\"Stock Request product quantity has to be strictly positive.\")\n                )\n\n    @api.onchange(\"warehouse_id\")\n    def onchange_warehouse_id(self):\n        \"\"\" Finds location id for changed warehouse. \"\"\"\n        res = {\"domain\": {}}\n        if self._name == \"stock.request\" and self.order_id:\n            # When the stock request is created from an order the wh and\n            # location are taken from the order and we rely on it to change\n            # all request associated. Thus, no need to apply\n            # the onchange, as it could lead to inconsistencies.\n            return res\n        if self.warehouse_id:\n            loc_wh = self.location_id.get_warehouse()\n            if self.warehouse_id != loc_wh:\n                self.location_id = self.warehouse_id.lot_stock_id.id\n            if self.warehouse_id.company_id != self.company_id:\n                self.company_id = self.warehouse_id.company_id\n        return res\n\n    @api.onchange(\"location_id\")\n    def onchange_location_id(self):\n        if self.location_id:\n            loc_wh = self.location_id.get_warehouse()\n            if loc_wh and self.warehouse_id != loc_wh:\n                self.warehouse_id = loc_wh\n                self.with_context(no_change_childs=True).onchange_warehouse_id()\n\n    @api.onchange(\"allow_virtual_location\")\n    def onchange_allow_virtual_location(self):\n        if self.allow_virtual_location:\n            return {\"domain\": {\"location_id\": []}}\n\n    @api.onchange(\"company_id\")\n    def onchange_company_id(self):\n        \"\"\" Sets a default warehouse when the company is changed and limits\n        the user selection of warehouses. \"\"\"\n        if self.company_id and (\n            not self.warehouse_id or self.warehouse_id.company_id != self.company_id\n        ):\n            self.warehouse_id = self.env[\"stock.warehouse\"].search(\n                [(\"company_id\", \"=\", self.company_id.id)], limit=1\n            )\n            self.onchange_warehouse_id()\n\n        return {\"domain\": {\"warehouse_id\": [(\"company_id\", \"=\", self.company_id.id)]}}\n\n    @api.onchange(\"product_id\")\n    def onchange_product_id(self):\n        res = {\"domain\": {}}\n        if self.product_id:\n            self.product_uom_id = self.product_id.uom_id.id\n            res[\"domain\"][\"product_uom_id\"] = [\n                (\"category_id\", \"=\", self.product_id.uom_id.category_id.id)\n            ]\n            return res\n        res[\"domain\"][\"product_uom_id\"] = []\n        return res\n", "path": "stock_request/models/stock_request_abstract.py"}]}