def _populate_set_companies(self, records): _logger.info('Setting companies') r_company = populate.Random('res.partner+company_has_partners') r_partner = populate.Random('res.partner+partner_has_company') r_company_pick = populate.Random('res.partner+partner_company_pick=') companies = records.filtered( lambda p: p.is_company and r_company.getrandbits( 1)) # 50% change to have partners partners = records.filtered( lambda p: not p.is_company and r_partner.getrandbits( 1)) # 50% change to have a company companies_partners = collections.defaultdict( lambda: self.env['res.partner']) for partner in partners: companies_partners[r_company_pick.choice(companies)] |= partner # batching company write improves performances a lot (~40% faster for total partner creation). for count, (company, partners) in enumerate(companies_partners.items(), start=1): if count % 100 == 0: _logger.info('Setting company: %s/%s', count, len(companies)) partners.write({'parent_id': company.id}) partners._onchange_company_id()
def _populate_factories(self): random = populate.Random('product_with_supplierinfo') company_ids = self.env.registry.populated_models[ 'res.company'][:COMPANY_NB_WITH_STOCK] + [False] partner_ids = self.env.registry.populated_models['res.partner'] product_templates_ids = self.env['product.product'].browse( self.env.registry.populated_models['product.product'] ).product_tmpl_id.ids product_templates_ids += self.env.registry.populated_models[ 'product.template'] product_templates_ids = random.sample( product_templates_ids, int(len(product_templates_ids) * 0.95)) def get_company_id(values, counter, random): partner = self.env['res.partner'].browse(values['name']) if partner.company_id: return partner.company_id.id return random.choice(company_ids) def get_delay(values, counter, random): # 5 % with huge delay (between 5 month and 6 month), otherwise between 1 and 10 days if random.random() > 0.95: return random.randint(150, 210) return random.randint(1, 10) return [ ('name', populate.randomize(partner_ids)), ('company_id', populate.compute(get_company_id)), ('product_tmpl_id', populate.iterate(product_templates_ids)), ('product_name', populate.constant("SI-{counter}")), ('sequence', populate.randint(1, 10)), ('min_qty', populate.randint(0, 10)), ('price', populate.randint(10, 100)), ('delay', populate.compute(get_delay)), ]
def _compute_default_locations(iterator, field_name, model_name): random = populate.Random('_compute_default_locations') locations_by_company = dict( groupby(internal_locations, key=lambda loc: loc.company_id.id)) locations_by_company = { company_id: self.env['stock.location'].concat(*locations) for company_id, locations in locations_by_company.items() } for values in iterator: locations_company = locations_by_company[values['company_id']] # TODO : choice only location child of warehouse.lot_stock_id inter_location = random.choice(locations_company) values['warehouse_id'] = inter_location.get_warehouse().id if values['code'] == 'internal': values['default_location_src_id'] = inter_location.id values['default_location_dest_id'] = random.choice( locations_company - inter_location).id elif values['code'] == 'incoming': values['default_location_dest_id'] = inter_location.id elif values['code'] == 'outgoing': values['default_location_src_id'] = inter_location.id yield values
def _populate(self, size): @lru_cache() def search_coa_ids(currency_id): return self.env['account.chart.template'].search([('currency_id', '=', currency_id)]) records = super()._populate(size) _logger.info('Loading Chart Template') default_chart_templates = self.env['account.chart.template'].search([], limit=1) if not default_chart_templates: # TODO install l10n_generic_coa ? raise UserError(_( "At least one localization is needed to be installed in order to populate the " "database with accounting" )) random = populate.Random('res.company+chart_template_selector') # Load the a chart of accounts matching the currency of the company for the 3 first created companies # We are loading an existing CoA and not populating it because: # * it reflects best real use cases. # * it allows checking reports by localization # * the config is complete with try_loading(), no need to adapt when the model changes # * it is way easier :-) # We are loading only for 3 companies because: # * It takes a few hundreds of a second to create account.move records in batch. # Because we want to have a lot of entries for at least one company (in order to test # reports, functions and widgets performances for instance), we can't afford to do it for # a lot of companies. # * it would be useless to have entries for all the companies, we can already do everything with # entries in only a few (but multiple) companies. # Note that we can still populate some new records on top of the CoA if it makes sense, # like account.journal for instance. for company in records[:3]: chart_templates_cur = search_coa_ids(company.currency_id.id) or default_chart_templates random.choice(chart_templates_cur).with_company(company.id).try_loading() return records
def _populate(self, size): res = super()._populate(size) # Set alternative workcenters _logger.info("Set alternative workcenters") # Valid workcenters by company_id (the workcenter without company can be the alternative of all workcenter) workcenters_by_company = defaultdict(OrderedSet) for workcenter in res: workcenters_by_company[workcenter.company_id.id].add(workcenter.id) workcenters_by_company = { company_id: self.env['mrp.workcenter'].browse(workcenters) for company_id, workcenters in workcenters_by_company.items() } workcenters_by_company = { company_id: workcenters | workcenters_by_company.get(False, self.env['mrp.workcenter']) for company_id, workcenters in workcenters_by_company.items() } random = populate.Random('set_alternative_workcenter') for workcenter in res: nb_alternative = max( random.randint(0, 3), len(workcenters_by_company[workcenter.company_id.id]) - 1) if nb_alternative > 0: alternatives_workcenter_ids = random.sample( (workcenters_by_company[workcenter.company_id.id] - workcenter).ids, nb_alternative) workcenter.alternative_workcenter_ids = [ (6, 0, alternatives_workcenter_ids) ] return res
def _populate_factories(self): # Take a subset (50%) of bom to have some of then without any operation random = populate.Random('byproduct_subset_bom') boms_ids = self.env.registry.populated_models['mrp.bom'] boms_ids = random.sample(boms_ids, int(len(boms_ids) * 0.5)) boms = self.env['mrp.bom'].search( [('id', 'in', self.env.registry.populated_models['mrp.bom'])], order='sequence, product_id, id') product_manu_ids = OrderedSet() for bom in boms: if bom.product_id: product_manu_ids.add(bom.product_id.id) else: for product_id in bom.product_tmpl_id.product_variant_ids: product_manu_ids.add(product_id.id) product_manu = self.env['product.product'].browse(product_manu_ids) # product_no_manu is products which don't have any bom (leaves in the BoM trees) product_no_manu = self.env['product.product'].browse( self.env.registry.populated_models['product.product'] ) - product_manu product_no_manu_ids = product_no_manu.ids def get_product_uom_id(values, counter, random): return self.env['product.product'].browse( values['product_id']).uom_id.id return [ ('bom_id', populate.iterate(boms_ids)), ('product_id', populate.randomize(product_no_manu_ids)), ('product_uom_id', populate.compute(get_product_uom_id)), ('product_qty', populate.randint(1, 10)), ]
def _compute_contact(iterator, *args): r = populate.Random('res.partner+contact_generator_selector') for values in iterator: if values['partner_id']: yield {**values} else: fn = r.choice(tools._p_forename_groups) mn = r.choices( [False] + tools._p_middlename_groups, weights=[1] + [1 / (len(tools._p_middlename_groups) or 1)] * len(tools._p_middlename_groups))[0] sn = r.choice(tools._p_surname_groups) mn_wseparator = f' "{mn}" ' contact_name = f'{fn}{mn_wseparator}{sn}' country_id = values['country_id'] if country_id not in phones_per_country.keys(): country_id = False mobile = r.choice(phones_per_country[country_id]) phone = r.choice(phones_per_country[country_id]) yield { **values, 'contact_name': contact_name, 'mobile': mobile, 'phone': phone, }
def confirm_prototype_mo(sample_ratio): # Confirm X % of prototype MO random = populate.Random('confirm_prototype_mo') mo_ids = moves.raw_material_production_id.ids mo_to_confirm = self.env['mrp.production'].browse( random.sample(mo_ids, int(len(mo_ids) * 0.8))) _logger.info("Confirm %d of prototype MO" % len(mo_to_confirm)) mo_to_confirm.action_confirm()
def confirm_bom_mo(sample_ratio): # Confirm X % of prototype MO random = populate.Random('confirm_bom_mo') mo_ids = productions.filtered('bom_id').ids mo_to_confirm = self.env['mrp.production'].browse( random.sample(mo_ids, int(len(mo_ids) * 0.8))) _logger.info("Confirm %d MO with BoM" % len(mo_to_confirm)) mo_to_confirm.action_confirm()
def start_inventory_sample(sample_ratio): random = populate.Random('start_inventory_sample') inventories_to_start = self.browse( random.sample(inventories.ids, int(len(inventories.ids) * sample_ratio))) # Start empty to let the stock.inventory.line populate create lines inventories_to_start.start_empty = True for inventory in inventories_to_start: inventory.action_start()
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
def _attach_to_record(iterator, field_name, model_name): random = populate.Random('_attach_to_record') fields, weights = self._populate_attach_record_weight() fields_generator = self._populate_attach_record_generator() for values in iterator: field = random.choices(fields, weights)[0] values[field] = next(fields_generator[field]) yield values
def confirm_pickings(sample_ratio): # Confirm sample_ratio * 100 % of picking random = populate.Random('confirm_pickings') picking_ids = moves.picking_id.ids picking_to_confirm = self.env['stock.picking'].browse( random.sample(picking_ids, int(len(picking_ids) * sample_ratio))) _logger.info("Confirm %d of pickings" % len(picking_to_confirm)) picking_to_confirm.action_confirm()
def _compute_address(iterator, *args): r = populate.Random('res.partner+address_generator_selector') for values in iterator: if values['partner_id']: yield {**values} else: address_gen = r.choice(address_generators) address_values = next(address_gen) yield {**values, **address_values}
def _populate(self, size): p_tmpl_ids = self.env.registry.populated_models["product.template"] ptavs = self.search([('product_tmpl_id', 'in', p_tmpl_ids)]) # ptavs are automatically created when specifying attribute lines on product templates. rand = populate.Random("ptav_extra_price_generator") for ptav in ptavs: if rand.random() < 0.50: # 50% of having a extra price ptav.price_extra = rand.randrange(500) * rand.random() return ptavs
def validate_inventory_sample(sample_ratio): # Validate the inventory adjustment, useful to have a stock at beginning inventories_ids = inventory_lines.inventory_id.ids random = populate.Random('validate_inventory') inventories_to_done = self.env['stock.inventory'].browse( random.sample(inventories_ids, int(len(inventories_ids) * sample_ratio))) _logger.info("Validate %d inventory adjustment" % len(inventories_to_done)) for inventory in inventories_to_done: inventory.action_validate()
def _compute_locations(iterator, field_name, model_name): locations_out = cross_company_locations.filtered_domain([ ('usage', '=', 'customer') ]) locations_in = cross_company_locations.filtered_domain([ ('usage', '=', 'supplier') ]) locations_internal = locations_companies.filtered_domain([ ('usage', '=', 'internal') ]) locations_by_company = dict( groupby(locations_companies, key=lambda loc: loc.company_id.id)) locations_by_company = { com: self.env['stock.location'].concat(*locs) for com, locs in locations_by_company.items() } random = populate.Random('_compute_locations') for values in iterator: picking_type = self.env['stock.picking.type'].browse( values['picking_type_id']) source_loc = picking_type.default_location_src_id dest_loc = picking_type.default_location_dest_id locations_company = locations_by_company[ picking_type.company_id.id] if not source_loc or random.random() > 0.8: if picking_type.code == 'incoming': source_loc = random.choice(locations_in) elif picking_type.code == 'outgoing': source_loc = random.choice(locations_internal & locations_company) elif picking_type.code == 'internal': source_loc = random.choice(locations_internal & locations_company) if not dest_loc or random.random() > 0.8: if picking_type.code == 'incoming': dest_loc = random.choice(locations_internal & locations_company) elif picking_type.code == 'outgoing': dest_loc = random.choice(locations_out) elif picking_type.code == 'internal': # Need at most 2 internal locations dest_loc = random.choice((locations_internal & locations_company) - source_loc) values['location_id'] = source_loc.id values['location_dest_id'] = dest_loc.id yield values
def _populate_set_manager(self, employees): manager_ids = [] rand = populate.Random('hr.employee+manager_generator') for employee in employees: if rand.random() >= 0.85: # 15% of employees are managers manager_ids.append(employee.id) for employee in employees: manager = rand.choice(manager_ids) if manager != employee.id: employee.parent_id = manager
def set_barcode_variant(sample_ratio): random = populate.Random('barcode_product_template') product_variants_ids = res.product_variant_ids.ids product_variants_ids = random.sample( product_variants_ids, int(len(product_variants_ids) * sample_ratio)) product_variants = self.env['product.product'].browse( product_variants_ids) _logger.info('Set barcode on product variants (%s)', len(product_variants)) for product in product_variants: product.barcode = "BARCODE-PT-%s" % product.id
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
def _populate_set_manager(self, employees): manager_ids = defaultdict(list) rand = populate.Random('hr.employee+manager_generator') for employee in employees: # 15% of employees are managers, at least one per company if rand.random() >= 0.85 or not manager_ids.get( employee.company_id): manager_ids[employee.company_id].append(employee.id) for employee in employees: manager = rand.choice(manager_ids[employee.company_id]) if manager != employee.id: employee.parent_id = manager
def get_target_info(iterator, field_name, model_name): random = populate.Random("pricelist_target") for values in iterator: # If product population is updated to consider multi company # the company of product would have to be considered # for product_id & product_tmpl_id applied_on = values["applied_on"] if applied_on == "0_product_variant": values["product_id"] = random.choice(product_ids) elif applied_on == "1_product": values["product_tmpl_id"] = random.choice(p_tmpl_ids) elif applied_on == "2_product_category": values["categ_id"] = random.choice(categ_ids) yield values
def _compute_picking_values(iterator, field_name, model_name): random = populate.Random('_compute_picking_values') for values in iterator: if values.get('picking_id'): picking = self.env['stock.picking'].browse( values['picking_id']) values['picking_id'] = picking.id values['location_id'] = picking.location_id.id values['location_dest_id'] = picking.location_dest_id.id values['name'] = picking.name values['date'] = picking.scheduled_date values['company_id'] = picking.company_id.id if picking.picking_type_id.code == 'incoming': values['price_unit'] = random.randint(1, 100) yield values
def _populate_set_parent_departments(self, departments, size): parent_ids = [] rand = populate.Random('hr.department+parent_generator') for dept in departments: if rand.random() > 0.3: parent_ids.append(dept.id) parent_children = defaultdict(lambda: self.env['hr.department']) for dept in departments: parent = rand.choice(parent_ids) if parent < dept.id: parent_children[parent] |= dept for parent, children in parent_children.items(): children.write({'parent_id': parent})
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
def _populate_factories(self): product_ids = self.env['product.product'].browse( self.env.registry.populated_models['product.product']).filtered( lambda p: p.type in ('product', 'consu')).ids random_products = populate.Random("move_product_sample") product_ids = random_products.sample(product_ids, int(len(product_ids) * 0.8)) def get_product_uom(values, counter, random): return self.env['product.product'].browse( values['product_id']).uom_id.id def _attach_to_record(iterator, field_name, model_name): random = populate.Random('_attach_to_record') fields, weights = self._populate_attach_record_weight() fields_generator = self._populate_attach_record_generator() for values in iterator: field = random.choices(fields, weights)[0] values[field] = next(fields_generator[field]) yield values def _compute_picking_values(iterator, field_name, model_name): random = populate.Random('_compute_picking_values') for values in iterator: if values.get('picking_id'): picking = self.env['stock.picking'].browse( values['picking_id']) values['picking_id'] = picking.id values['location_id'] = picking.location_id.id values['location_dest_id'] = picking.location_dest_id.id values['name'] = picking.name values['date'] = picking.scheduled_date values['company_id'] = picking.company_id.id if picking.picking_type_id.code == 'incoming': values['price_unit'] = random.randint(1, 100) yield values return [ ('product_id', populate.randomize(product_ids)), ('product_uom', populate.compute(get_product_uom)), ('product_uom_qty', populate.randint(1, 10)), ('sequence', populate.randint(1, 1000)), ('_attach_to_record', _attach_to_record), ('_compute_picking_values', _compute_picking_values), ]
def _populate_set_children_tasks(self, tasks, size): _logger.info('Setting parent tasks') rand = populate.Random('project.task+children_generator') parents = self.env["project.task"] for task in tasks: if not rand.getrandbits(4): parents |= task parent_ids = parents.ids tasks -= parents parent_childs = collections.defaultdict( lambda: self.env['project.task']) for count, task in enumerate(tasks): if not rand.getrandbits(4): parent_childs[rand.choice(parent_ids)] |= task for count, (parent, childs) in enumerate(parent_childs.items()): if (count + 1) % 100 == 0: _logger.info('Setting parent: %s/%s', count + 1, len(parent_childs)) childs.write({'parent_id': parent})
def generate_address(iterator, *args): address_generators = [ populate.chain_factories(address_factories, self._name) for address_factories in address_factories_groups ] # first, exhaust all address_generators for adress_generator in address_generators: for adress_values in adress_generator: if adress_values['__complete']: break values = next( iterator) # only consume main iterator if usefull yield {**values, **adress_values} # then, go pseudorandom between generators r = populate.Random('res.partner+address_generator_selector') for values in iterator: adress_generator = r.choice(address_generators) adress_values = next(adress_generator) yield {**adress_values, **values}
def compute_product_location(iterator, field_name, model_name): random = populate.Random('compute_product_location') # To avoid create twice the same line inventory (avoid _check_no_duplicate_line) : product/location (limitation for lot) # Use generator to avoid cartisian product in memory generator_product_loc_dict = {} for inventory in inventories: # TODO: randomize cartesian product generator_product_loc_dict[inventory.id] = cartesian_product( random.sample(inventory.location_ids, len(inventory.location_ids)), random.sample(inventory.product_ids, len(inventory.product_ids))) for values in iterator: loc_id, product = next( generator_product_loc_dict[values['inventory_id']]) values['product_id'] = product.id values['location_id'] = loc_id.id yield values
def get_prices(iterator, field_name, model_name): random = populate.Random("pricelist_prices") for values in iterator: # Fixed price, percentage, formula compute_price = values["compute_price"] if compute_price == "fixed": # base = "list_price" = default # fixed_price values["fixed_price"] = random.randint(1, 1000) elif compute_price == "percentage": # base = "list_price" = default # percent_price values["percent_price"] = random.randint(1, 100) else: # formula # pricelist base not considered atm. values["base"] = random.choice( ["list_price", "standard_price"]) values["price_discount"] = random.randint(0, 100) # price_min_margin, price_max_margin # price_round ??? price_discount, price_surcharge yield values