1 2import collections 3import logging 4 5from odoo import models 6from odoo.tools import populate 7 8_logger = logging.getLogger(__name__) 9 10 11class Partner(models.Model): 12 _inherit = "res.partner" 13 _populate_dependencies = ["res.company", "res.partner.industry"] 14 15 _populate_sizes = { 16 'small': 10, 17 'medium': 2000, 18 'large': 100000, 19 } 20 21 def _populate_factories(self): 22 23 # example of more complex generator composed of multiple sub generators 24 # this define one subgenerator per "country" 25 address_factories_groups = [ 26 [ # Falsy, 2 records 27 ('street', populate.iterate([False, ''])), 28 ('street2', populate.iterate([False, ''])), 29 ('city', populate.iterate([False, ''])), 30 ('zip', populate.iterate([False, ''])), 31 ('country_id', populate.iterate([False])), 32 ], [ # BE, 1 record 33 ('street', populate.iterate(['Boulevard Tintin {counter}'])), 34 ('city', populate.iterate(['Brussels'])), 35 ('zip', populate.iterate([1020])), 36 ('country_id', populate.iterate([self.env.ref('base.be').id])), 37 ], [ # US, 3 records 38 ('street', populate.iterate(['Main street', '3th street {counter}', False])), 39 ('street2', populate.iterate([False, '', 'Behind the tree {counter}'], [90, 5, 5])), 40 ('city', populate.randomize(['Sans Fransisco', 'Los Angeles', '', False])), 41 ('zip', populate.iterate([False, '', '50231'])), 42 ('country_id', populate.iterate([self.env.ref('base.us').id])), 43 ], [ # IN, 2 records 44 ('street', populate.iterate(['Main Street', 'Some Street {counter}'])), 45 ('city', populate.iterate(['ગાંધીનગર (Gandhinagar)'])), 46 ('zip', populate.randomize(['382002', '382008'])), 47 ('country_id', populate.randomize([self.env.ref('base.in').id])), 48 ], [ # other corner cases, 4 records 49 ('street', populate.iterate(['万泉寺村', 'საბჭოს სკვერი {counter}', '10th Street {counter}'])), 50 ('city', populate.iterate(['北京市', 'თბილისი', 'دبي'])), 51 ('zip', populate.iterate([False, 'UF47', '0', '10201'])), 52 ('country_id', populate.randomize([False] + self.env['res.country'].search([]).ids)), 53 ] 54 ] 55 56 def generate_address(iterator, *args): 57 address_generators = [populate.chain_factories(address_factories, self._name) for address_factories in address_factories_groups] 58 # first, exhaust all address_generators 59 for adress_generator in address_generators: 60 for adress_values in adress_generator: 61 if adress_values['__complete']: 62 break 63 values = next(iterator) # only consume main iterator if usefull 64 yield {**values, **adress_values} 65 66 # then, go pseudorandom between generators 67 r = populate.Random('res.partner+address_generator_selector') 68 for values in iterator: 69 adress_generator = r.choice(address_generators) 70 adress_values = next(adress_generator) 71 yield {**adress_values, **values} 72 73 # state based on country 74 states = self.env['res.country.state'].search([]) 75 states_per_country = collections.defaultdict(list) 76 for state in states: 77 states_per_country[state.country_id.id].append(state.id) 78 79 def get_state(values=None, random=None, **kwargs): 80 country_id = values['country_id'] 81 if not country_id: 82 return False 83 return random.choice([False] + states_per_country[country_id]) 84 85 def get_name(values=None, counter=0, **kwargs): 86 is_company = values['is_company'] 87 complete = values['__complete'] 88 return '%s_%s_%s' % ('company' if is_company else 'partner', int(complete), counter) 89 90 industry_ids = self.env.registry.populated_models['res.partner.industry'] 91 company_ids = self.env.registry.populated_models['res.company'] 92 93 # not defined fields: vat, partner_longitude, date, partner_latitude, color, company_name, employee, lang, user_id 94 return [ 95 ('active', populate.cartesian([True, False], [0.9, 0.1])), 96 ('employee', populate.cartesian([True, False], [0.1, 0.9])), 97 ('email', populate.iterate( 98 [False, '', 'email{counter}@example.com', '<contact 万> contact{counter}@anotherexample.com', 'invalid_email'])), 99 ('type', populate.constant('contact')), # todo add more logic, manage 'invoice', 'delivery', 'other', 'private' 100 ('is_company', populate.iterate([True, False], [0.05, 0.95])), 101 ('_address', generate_address), 102 ('state_id', populate.compute(get_state)), 103 ('phone', populate.randomize([False, '', '+3212345678', '003212345678', '12345678'])), 104 ('mobile', populate.randomize([False, '', '+32412345678', '0032412345678', '412345678'])), 105 ('title', populate.randomize(self.env['res.partner.title'].search([]).ids)), 106 ('function', populate.randomize( 107 [False, '', 'President of Sales', 'Senior Consultant', 'Product owner', 'Functional Consultant', 'Chief Executive Officer'], 108 [50, 10, 2, 20, 5, 10, 1])), 109 ('tz', populate.randomize([tz for tz in self.env['res.partner']._fields['tz'].get_values(self.env)])), 110 ('website', populate.randomize([False, '', 'http://www.example.com'])), 111 ('credit_limit', populate.randomize( 112 [False, 0, 500, 2500, 5000, 10000], 113 [50, 30, 5, 5, 5, 5])), 114 ('name', populate.compute(get_name)), # keep after is_company 115 ('ref', populate.randomize([False, '', '{counter}', 'p-{counter}'], [10, 10, 30, 50])), 116 ('industry_id', populate.randomize( 117 [False] + industry_ids, 118 [0.5] + ([0.5/(len(industry_ids) or 1)] * len(industry_ids)))), 119 ('comment', populate.iterate([False, '', 'This is a partner {counter}'])), 120 ('company_id', populate.iterate( 121 [False, self.env.ref('base.main_company').id] + company_ids, 122 [1, 1] + [1/(len(company_ids) or 1)]*len(company_ids))), 123 ('parent_id', populate.constant(False)), # will be setted in _populate override 124 ] 125 126 def _populate(self, size): 127 records = super()._populate(size) 128 # set parent_ids 129 self._populate_set_companies(records) 130 return records 131 132 def _populate_set_companies(self, records): 133 _logger.info('Setting companies') 134 r_company = populate.Random('res.partner+company_has_partners') # 50% change to have partners 135 companies = records.filtered(lambda p: p.is_company and r_company.getrandbits(1)) 136 partners = records - companies 137 r_partner = populate.Random('res.partner+partner_has_company') 138 r_company_pick = populate.Random('res.partner+partner_company_pick=') 139 companies_partners = collections.defaultdict(lambda: self.env['res.partner']) 140 for count, partner in enumerate(partners): 141 if bool(r_partner.getrandbits(1)): # 50% change to have a company 142 companies_partners[r_company_pick.choice(companies)] |= partner 143 144 # batching company write improves performances a lot (~40% faster for total partner creation). 145 for count, (company, partners) in enumerate(companies_partners.items()): 146 if (count + 1) % 100 == 0: 147 _logger.info('Setting company: %s/%s', count + 1, len(companies)) 148 partners.write({'parent_id': company.id}) 149 150class ResPartnerIndustry(models.Model): 151 _inherit = "res.partner.industry" 152 153 _populate_sizes = { 154 'small': 15, 155 'medium': 60, 156 'large': 300, 157 } 158 159 def _populate_factories(self): 160 return [ 161 ('active', populate.cartesian([False, True], [0.1, 0.9])), 162 ('name', populate.cartesian( 163 [False, 'Industry name', 'Industry name {counter}'], 164 [0.08, 0.01, 0.9])), 165 ('full_name', populate.iterate([False, 'Industry full name %s'])) 166 ] 167