From eca2161f40640fcc4161830285e210de0a4f0eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Voet=20=28ryv=29?= Date: Mon, 26 Apr 2021 12:32:12 +0000 Subject: [PATCH] [IMP] sale: add populate Add populate script for the `sale.order` and `sale.order.line`. task-2446266 closes odoo/odoo#50566 closes odoo/odoo#68704 Signed-off-by: Victor Feyens (vfe) Co-authored-by: Feyensv --- addons/sale/__init__.py | 7 +- addons/sale/populate/__init__.py | 3 + addons/sale/populate/product.py | 14 ++++ addons/sale/populate/product_attribute.py | 42 ++++++++++ addons/sale/populate/sale_order.py | 95 +++++++++++++++++++++++ 5 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 addons/sale/populate/__init__.py create mode 100644 addons/sale/populate/product.py create mode 100644 addons/sale/populate/product_attribute.py create mode 100644 addons/sale/populate/sale_order.py diff --git a/addons/sale/__init__.py b/addons/sale/__init__.py index a92bcece423..b91ad4c9d06 100644 --- a/addons/sale/__init__.py +++ b/addons/sale/__init__.py @@ -5,9 +5,4 @@ from . import models from . import controllers from . import report from . import wizard - -from functools import partial -import odoo -from odoo import api, SUPERUSER_ID - - +from . import populate diff --git a/addons/sale/populate/__init__.py b/addons/sale/populate/__init__.py new file mode 100644 index 00000000000..469e7d1f97c --- /dev/null +++ b/addons/sale/populate/__init__.py @@ -0,0 +1,3 @@ +from . import product_attribute +from . import sale_order +from . import product diff --git a/addons/sale/populate/product.py b/addons/sale/populate/product.py new file mode 100644 index 00000000000..1c540800f4f --- /dev/null +++ b/addons/sale/populate/product.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models +from odoo.tools import populate + + +class ProductProduct(models.Model): + _inherit = "product.product" + + def _populate_get_product_factories(self): + """Populate the invoice_policy of product.product & product.template models.""" + return super()._populate_get_product_factories() + [ + ("invoice_policy", populate.randomize(['order', 'delivery'], [5, 5]))] diff --git a/addons/sale/populate/product_attribute.py b/addons/sale/populate/product_attribute.py new file mode 100644 index 00000000000..5733dde4f0c --- /dev/null +++ b/addons/sale/populate/product_attribute.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models +from odoo.tools import populate + + +class ProductAttribute(models.Model): + _inherit = "product.attribute" + + def _populate_factories(self): + + return super()._populate_factories() + [ + ("display_type", populate.randomize(['radio', 'select', 'color'], [6, 3, 1])), + ] + + +class ProductAttributeValue(models.Model): + _inherit = "product.attribute.value" + + def _populate_factories(self): + attribute_ids = self.env.registry.populated_models["product.attribute"] + color_attribute_ids = self.env["product.attribute"].search([ + ("id", "in", attribute_ids), + ("display_type", "=", "color"), + ]).ids + + def get_custom_values(iterator, field_group, model_name): + r = populate.Random('%s+fields+%s' % (model_name, field_group)) + for _, values in enumerate(iterator): + attribute_id = values.get("attribute_id") + if attribute_id in color_attribute_ids: + values["html_color"] = r.choice( + ["#FFFFFF", "#000000", "#FFC300", "#1BC56D", "#FFFF00", "#FF0000"], + ) + elif not r.getrandbits(4): + values["is_custom"] = True + yield values + + return super()._populate_factories() + [ + ("_custom_values", get_custom_values), + ] diff --git a/addons/sale/populate/sale_order.py b/addons/sale/populate/sale_order.py new file mode 100644 index 00000000000..95aec55a207 --- /dev/null +++ b/addons/sale/populate/sale_order.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +import logging + +from odoo import models +from odoo.tools import populate, groupby + +_logger = logging.getLogger(__name__) + + +class SaleOrder(models.Model): + _inherit = "sale.order" + _populate_sizes = {"small": 100, "medium": 2_000, "large": 20_000} + _populate_dependencies = ["res.partner", "res.company", "res.users", "product.pricelist"] + + def _populate_factories(self): + company_ids = self.env.registry.populated_models["res.company"] + + def x_ids_by_company(recordset, with_false=True): + x_by_company = dict(groupby(recordset, key=lambda x_record: x_record.company_id.id)) + if with_false: + x_inter_company = self.env[recordset._name].concat(*x_by_company.get(False, [])) + else: + x_inter_company = self.env[recordset._name] + return {com: (self.env[recordset._name].concat(*x_records) | x_inter_company).ids for com, x_records in x_by_company.items() if com} + + partners_ids_by_company = x_ids_by_company(self.env["res.partner"].browse(self.env.registry.populated_models["res.partner"])) + pricelist_ids_by_company = x_ids_by_company(self.env["product.pricelist"].browse(self.env.registry.populated_models["product.pricelist"])) + user_ids_by_company = x_ids_by_company(self.env["res.users"].browse(self.env.registry.populated_models["res.users"]), with_false=False) + + def get_company_info(iterator, field_name, model_name): + random = populate.Random("sale_order_company") + for values in iterator: + cid = values.get("company_id") + valid_partner_ids = partners_ids_by_company[cid] + valid_user_ids = user_ids_by_company[cid] + valid_pricelist_ids = pricelist_ids_by_company[cid] + values.update({ + "partner_id": random.choice(valid_partner_ids), + "user_id": random.choice(valid_user_ids), + "pricelist_id": random.choice(valid_pricelist_ids), + }) + yield values + + return [ + ("company_id", populate.randomize(company_ids)), + ("_company_limited_fields", get_company_info), + ("require_payment", populate.randomize([True, False])), + ("require_signature", populate.randomize([True, False])), + ] + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + _populate_sizes = {"small": 1_000, "medium": 50_000, "large": 100_000} + _populate_dependencies = ["sale.order", "product.product"] + + def _populate(self, size): + so_line = super()._populate(size) + + def confirm_sale_order(sample_ratio): + # Confirm sample_ratio * 100 % of picking + random = populate.Random('confirm_sale_order') + order_ids = so_line.order_id.ids + orders_to_confirm = self.env['sale.order'].browse(random.sample(order_ids, int(len(order_ids) * sample_ratio))) + _logger.info("Confirm %d sale orders", len(orders_to_confirm)) + orders_to_confirm.action_confirm() + return orders_to_confirm + + confirm_sale_order(0.50) + + return so_line + + def _populate_factories(self): + order_ids = self.env.registry.populated_models["sale.order"] + product_ids = self.env.registry.populated_models["product.product"] + # If we want more advanced products with multiple variants + # add a populate dependency on product template and the following lines + product_ids += self.env["product.product"].search([ + ('product_tmpl_id', 'in', self.env.registry.populated_models["product.template"]) + ]).ids + + self.env['product.product'].browse(product_ids).read(['uom_id']) # prefetch all uom_id + + def get_product_uom(values, counter, random): + return self.env['product.product'].browse(values['product_id']).uom_id.id + + # TODO sections & notes (display_type & name) + + return [ + ("order_id", populate.randomize(order_ids)), + ("product_id", populate.randomize(product_ids)), + ("product_uom", populate.compute(get_product_uom)), + ("product_uom_qty", populate.randint(1, 200)), + ]