# Part of Odoo. See LICENSE file for full copyright and licensing details. import logging import optparse import sys import time from pathlib import Path from . import Command import odoo from odoo.modules.registry import Registry from odoo.tools.populate import populate_models from odoo.api import Environment DEFAULT_FACTOR = '10000' DEFAULT_SEPARATOR = '_' DEFAULT_MODELS = 'res.partner,product.template,account.move,sale.order,crm.lead,stock.picking,project.task' _logger = logging.getLogger(__name__) class Populate(Command): """Populate database via duplication of existing data for testing/demo purposes""" def run(self, cmdargs): parser = odoo.tools.config.parser parser.prog = f'{Path(sys.argv[0]).name} {self.name}' group = optparse.OptionGroup(parser, "Populate Configuration") group.add_option("--factors", dest="factors", help="Comma separated list of factors for each model, or just a single factor." "(Ex: a factor of 3 means the given model will be copied 3 times, reaching 4x it's original size)" "The last factor is propagated to the remaining models without a factor.", default=DEFAULT_FACTOR) group.add_option("--models", dest='models_to_populate', help="Comma separated list of models", default=DEFAULT_MODELS) group.add_option("--sep", dest='separator', help="Single character separator for char/text fields.", default=DEFAULT_SEPARATOR) parser.add_option_group(group) opt = odoo.tools.config.parse_config(cmdargs, setup_logging=True) # deduplicate models if necessary, and keep the last corresponding # factor for each model opt_factors = [int(f) for f in opt.factors.split(',')] model_factors = { model_name: opt_factors[index] if index < len(opt_factors) else opt_factors[-1] for index, model_name in enumerate(opt.models_to_populate.split(',')) } try: separator_code = ord(opt.separator) except TypeError: raise ValueError("Separator must be a single Unicode character.") dbname = odoo.tools.config['db_name'] registry = Registry(dbname) with registry.cursor() as cr: env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {'active_test': False}) self.populate(env, model_factors, separator_code) @classmethod def populate(cls, env: Environment, modelname_factors: dict[str, int], separator_code: int): model_factors = { model: factor for model_name, factor in modelname_factors.items() if (model := env.get(model_name)) is not None and not (model._transient or model._abstract) } _logger.log(25, 'Populating models %s', list(model_factors)) t0 = time.time() populate_models(model_factors, separator_code) env.flush_all() model_time = time.time() - t0 _logger.info('Populated models %s (total: %fs)', list(model_factors), model_time)