def phone_format(self, number, country=None, company=None): # Numbers without country are not formatted. if not self.country_id: return number # CRM option "Add international prefix" is set if self.env.user.company_id.phone_international_format == 'prefix': # We format all numbers according to company set for partner return phone_validation.phone_format( number, self.country_id.code, self.country_id.phone_code, always_international=True, raise_exception=False) # CRM option "No prefix" is set else: # Only local numbers must be formatted as local if self.env.user.company_id.country_id == self.country_id: return phone_validation.phone_format( number, self.country_id.code, self.country_id.phone_code, always_international=False, raise_exception=False) # All other countries are formatted with prefix else: return phone_validation.phone_format( number, self.country_id.code, self.country_id.phone_code, always_international=True, raise_exception=False)
def test_sms_schedule(self): with self.mockSMSGateway(): self._create_registrations(self.event_0, 3) # check subscription scheduler schedulers = self.env['event.mail'].search([ ('event_id', '=', self.event_0.id), ('interval_type', '=', 'after_sub') ]) self.assertEqual(len(schedulers), 1) self.assertEqual( schedulers.scheduled_date, self.event_0.create_date, 'event: incorrect scheduled date for checking controller') # verify that subscription scheduler was auto-executed after each registration self.assertEqual(len(schedulers.mail_registration_ids), 3) self.assertTrue( all(m.mail_sent is True for m in schedulers.mail_registration_ids)) self.assertEqual( schedulers.mapped('mail_registration_ids.registration_id'), self.event_0.registration_ids) sanitized_numbers = [] for registration in self.event_0.registration_ids: reg_sanitized_number = phone_validation.phone_format( registration.phone, 'BE', '32', force_format='E164') sanitized_numbers.append(reg_sanitized_number) self.assertSMSOutgoing(self.env['res.partner'], reg_sanitized_number, content='%s registration confirmation.' % self.event_0.organizer_id.name) # clear notification queue to avoid conflicts when checking next notifications self.env['mail.notification'].search([('sms_number', 'in', sanitized_numbers)]).unlink() self.env['sms.sms'].search([('number', 'in', sanitized_numbers) ]).unlink() # check before event scheduler schedulers = self.env['event.mail'].search([ ('event_id', '=', self.event_0.id), ('interval_type', '=', 'before_event') ]) self.assertEqual(len(schedulers), 1, 'event: wrong scheduler creation') self.assertEqual(schedulers[0].scheduled_date, self.event_0.date_begin + relativedelta(days=-3)) # execute event reminder scheduler explicitly with self.mockSMSGateway(): schedulers.execute() # verify that subscription scheduler was auto-executed after each registration for registration in self.event_0.registration_ids: reg_sanitized_number = phone_validation.phone_format( registration.phone, 'BE', '32', force_format='E164') self.assertSMSOutgoing(self.env['res.partner'], reg_sanitized_number, content='%s reminder' % self.event_0.organizer_id.name)
def setUpClass(cls): super(TestMassSMSCommon, cls).setUpClass() cls._test_body = 'Mass SMS in your face' records = cls.env['mail.test.sms'] partners = cls.env['res.partner'] country_be_id = cls.env.ref('base.be').id, country_us_id = cls.env.ref('base.us').id, for x in range(10): partners += cls.env['res.partner'].with_context( **cls._test_context).create({ 'name': 'Partner_%s' % (x), 'email': '*****@*****.**' % (x), 'country_id': country_be_id, 'mobile': '045600%s%s99' % (x, x) }) records += cls.env['mail.test.sms'].with_context( **cls._test_context).create({ 'name': 'MassSMSTest_%s' % (x), 'customer_id': partners[x].id, 'phone_nbr': '045600%s%s44' % (x, x) }) cls.records = cls._reset_mail_context(records) cls.records_numbers = [ phone_validation.phone_format(r.phone_nbr, 'BE', '32', force_format='E164') for r in cls.records ] cls.partners = partners cls.sms_template = cls.env['sms.template'].create({ 'name': 'Test Template', 'model_id': cls.env['ir.model']._get('mail.test.sms').id, 'body': 'Dear {{ object.display_name }} this is a mass SMS.', }) cls.partner_numbers = [ phone_validation.phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164') for partner in partners ]
def test_crm_lead_partner_sync_email_phone(self): """ Specifically test synchronize between a lead and its partner about phone and email fields. Phone especially has some corner cases due to automatic formatting (notably with onchange in form view). """ lead, partner = self.lead_1.with_user(self.env.user), self.contact_2 lead_form = Form(lead) # reset partner phone to a local number partner_phone, partner_email = '202 555 0999', partner.email partner_phone_formatted = phone_format(partner_phone, 'US', '1') partner_phone_sanitized = phone_format(partner_phone, 'US', '1', force_format='E164') self.assertEqual(partner_phone_formatted, '+1 202-555-0999') self.assertEqual(partner_phone_sanitized, '+12025550999') partner.phone = partner_phone # email & phone must be automatically set on the lead lead_form.partner_id = partner self.assertEqual(lead_form.email_from, partner_email) self.assertEqual(lead_form.phone, partner_phone_formatted) self.assertFalse(lead_form.partner_email_update) self.assertFalse(lead_form.partner_phone_update) lead_form.save() self.assertEqual(partner.phone, partner_phone) self.assertEqual(lead.phone, partner_phone_formatted) self.assertEqual(lead.phone_sanitized, partner_phone_sanitized) # writing on the lead field must change the partner field new_email = '"John Zoidberg" <*****@*****.**>' new_email_normalized = '*****@*****.**' lead_form.email_from = new_email self.assertTrue(lead_form.partner_email_update) new_phone = '+1 202 555 7799' new_phone_formatted = phone_format(new_phone, 'US', '1') lead_form.phone = new_phone self.assertEqual(lead_form.phone, new_phone_formatted) self.assertTrue(lead_form.partner_email_update) self.assertTrue(lead_form.partner_phone_update) lead_form.save() self.assertEqual(partner.email, new_email) self.assertEqual(partner.email_normalized, new_email_normalized) self.assertEqual(partner.phone, new_phone_formatted) # resetting lead values also resets partner lead_form.email_from, lead_form.phone = False, False self.assertTrue(lead_form.partner_email_update) self.assertTrue(lead_form.partner_phone_update) lead_form.save() self.assertFalse(partner.email) self.assertFalse(partner.email_normalized) self.assertFalse(partner.phone)
def setUpClass(cls): super(BaseFunctionalTest, cls).setUpClass() cls.user_employee.write({'login': '******'}) # update country to belgium in order to test sanitization of numbers cls.user_employee.company_id.write({'country_id': cls.env.ref('base.be').id}) # some numbers for testing cls.random_numbers_str = '+32456998877, 0456665544' cls.random_numbers = cls.random_numbers_str.split(', ') cls.random_numbers_san = [phone_validation.phone_format(number, 'BE', '32', force_format='E164') for number in cls.random_numbers] cls.test_numbers = ['+32456010203', '0456 04 05 06'] cls.test_numbers_san = [phone_validation.phone_format(number, 'BE', '32', force_format='E164') for number in cls.test_numbers]
def setUpClass(cls): super(TestSMSComposer, cls).setUpClass() cls._test_body = 'VOID CONTENT' cls.partner_numbers = [ phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164') for partner in (cls.partner_1 | cls.partner_2) ] cls.random_numbers_str = '+32475998877, 0475997788' cls.random_numbers = [ phone_format(number, 'BE', '32', force_format='E164') for number in ['+32475998877', '0475997788'] ]
def checkout_form_validate(self, mode, all_form_values, data): error = dict() error_message = [] if data.get("phone"): data["phone"] = data.get("phone").strip() standard_error, standard_error_message = super( WebsiteSalePhoneValidation, self).checkout_form_validate(mode, all_form_values, data) error.update(standard_error) error_message += standard_error_message if data.get("phone"): try: phone = data.get("phone") country = request.env["res.country"].sudo().browse( data.get("country_id")) data["phone"] = phone_validation.phone_format( phone, country.code if country else None, country.phone_code if country else None, force_format="INTERNATIONAL", raise_exception=True, ) except Exception as e: error["phone"] = "error" error_message.append(e.name) return error, error_message
def details_form_validate(self, data): if data.get("phone"): data["phone"] = data.get("phone").strip() error, error_message = super(CustomerPortalPhoneValidation, self).details_form_validate(data) if data.get("phone"): try: phone = data.get("phone") country = request.env["res.country"].sudo().browse( int(data.get("country_id"))) data["phone"] = phone_validation.phone_format( phone, country.code if country else None, country.phone_code if country else None, force_format="INTERNATIONAL", raise_exception=True, ) except Exception as e: error["phone"] = "error" error_message.append(e.name) return error, error_message
def setUpClass(cls): super(TestSMSComposerComment, cls).setUpClass() cls._test_body = 'VOID CONTENT' cls.partner_numbers = [ phone_validation.phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164') for partner in (cls.partner_1 | cls.partner_2) ] cls.test_record = cls.env['mail.test.sms'].with_context( **cls._test_context).create({ 'name': 'Test', 'customer_id': cls.partner_1.id, 'mobile_nbr': cls.test_numbers[0], 'phone_nbr': cls.test_numbers[1], }) cls.test_record = cls._reset_mail_context(cls.test_record) cls.sms_template = cls.env['sms.template'].create({ 'name': 'Test Template', 'model_id': cls.env['ir.model']._get('mail.test.sms').id, 'body': 'Dear ${object.display_name} this is an SMS.', })
def setUpClass(cls): super(TestSMSCommon, cls).setUpClass() cls.user_employee.write({'login': '******'}) # update country to belgium in order to test sanitization of numbers cls.user_employee.company_id.write({'country_id': cls.env.ref('base.be').id}) # some numbers for testing cls.random_numbers_str = '+32456998877, 0456665544' cls.random_numbers = cls.random_numbers_str.split(', ') cls.random_numbers_san = [phone_validation.phone_format(number, 'BE', '32', force_format='E164') for number in cls.random_numbers] cls.test_numbers = ['+32456010203', '0456 04 05 06', '0032456070809'] cls.test_numbers_san = [phone_validation.phone_format(number, 'BE', '32', force_format='E164') for number in cls.test_numbers] # some numbers for mass testing cls.mass_numbers = ['04561%s2%s3%s' % (x, x, x) for x in range(0, 10)] cls.mass_numbers_san = [phone_validation.phone_format(number, 'BE', '32', force_format='E164') for number in cls.mass_numbers]
def setUpClass(cls): super(TestRecipients, cls).setUpClass() cls.partner_numbers = [ phone_validation.phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164') for partner in (cls.partner_1 | cls.partner_2) ]
def phone_format(self, number, country=None, company=None): country_code = country.code if country else self._phone_get_country_code() always_international = company.phone_international_format if company else self._phone_get_always_international() return phone_validation.phone_format( number, country_code if country_code else None, always_international=always_international, raise_exception=True )
def phone_format(self, number, country=None, company=None): country = country or self._phone_get_country() if not country: return number return phone_validation.phone_format( number, country.code if country else None, country.phone_code if country else None, force_format='INTERNATIONAL', raise_exception=False)
def phone_format(self, number, country=None, company=None): country = country or self._phone_get_country() always_international = company.phone_international_format == 'prefix' if company else self._phone_get_always_international( ) return phone_validation.phone_format( number, country.code if country else None, country.phone_code if country else None, always_international=always_international, raise_exception=True)
def phone_format(self, number, country=None, company=None): country = country or self._phone_get_country() if not country: return number always_international = company.phone_international_format == 'prefix' if company else self._phone_get_always_international() return phone_validation.phone_format( number, country.code if country else None, country.phone_code if country else None, force_format='INTERNATIONAL' if always_international else 'NATIONAL', raise_exception=False )
def phone_format(self, number, country=None, company=None): country = country or self._phone_get_country() if not country: return number always_international = company.phone_international_format == 'prefix' if company else self._phone_get_always_international() return phone_validation.phone_format( number, country.code if country else None, country.phone_code if country else None, always_international=always_international, raise_exception=False )
def phone_format(self, field_label, field_input, country=None): if country and not isinstance(country, models.Model): try: country = request.env['res.country'].browse(int(country)) except Exception: return ValueError( _('Could not convert phone number (wrong country id format: {})' ).format(country)) return phone_validation.phone_format( field_input, country.code if country else None, country.phone_code if country else None, force_format='INTERNATIONAL', raise_exception=False)
def _handle_website_form(self, model_name, **kwargs): model_record = request.env['ir.model'].sudo().search([ ('model', '=', model_name), ('website_form_access', '=', True) ]) if model_record and hasattr( request.env[model_name], '_phone_format') or hasattr( request.env[model_name], 'phone_get_sanitized_number'): # filter on either custom _phone_format method, either phone_get_sanitized_number but directly # call phone_format from phone validation herebelow to simplify things as we don't have real # records but a dictionary of value at this point (record.phone_get_sanitized_number would # not work) try: data = self.extract_data(model_record, request.params) except: # no specific management, super will do it pass else: record = data.get('record', {}) phone_fields = self._get_phone_fields_to_validate() country = request.env['res.country'].browse( record.get('country_id')) contact_country = country if country.exists( ) else self._get_country() for phone_field in phone_fields: if not record.get(phone_field): continue number = record[phone_field] fmt_number = phone_validation.phone_format( number, contact_country.code if contact_country else None, contact_country.phone_code if contact_country else None, force_format='INTERNATIONAL', raise_exception=False) request.params.update({phone_field: fmt_number}) if model_name == 'crm.lead' and not request.params.get('state_id'): geoip_country_code = request.session.get('geoip', {}).get('country_code') geoip_state_code = request.session.get('geoip', {}).get('region') if geoip_country_code and geoip_state_code: state = request.env['res.country.state'].search([ ('code', '=', geoip_state_code), ('country_id.code', '=', geoip_country_code) ]) if state: request.params['state_id'] = state.id return super(WebsiteForm, self)._handle_website_form(model_name, **kwargs)
def setUpClass(cls): super(TestSMSPost, cls).setUpClass() cls._test_body = 'VOID CONTENT' cls.partner_numbers = [ phone_validation.phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164') for partner in (cls.partner_1 | cls.partner_2) ] cls.test_record = cls.env['mail.test.sms'].with_context(**cls._test_context).create({ 'name': 'Test', 'customer_id': cls.partner_1.id, 'mobile_nbr': cls.test_numbers[0], 'phone_nbr': cls.test_numbers[1], }) cls.test_record = cls._reset_mail_context(cls.test_record)
def create_lead_from_http(self, **post): # logging request vals = { 'url': request.httprequest.url or '', 'charset': request.httprequest.charset or '', 'content_type': request.httprequest.content_type or '', 'mimetype': request.httprequest.mimetype or '', 'method': request.httprequest.method or '', 'params': ', '.join( ['{}:{}'.format(k, v) for k, v in request.params.items()]), 'form_data': ', '.join([ '{}:{}'.format(k, v) for k, v in request.httprequest.form.items() ]) } request.env['crm.lead.creation.log'].sudo().create(vals) if post.get('source') == 'Bobex' and ( post.get('your-tel') or post.get('your-email')) and post.get('your-name'): tag_ids = [] if 'services[]' in post: formatted_services = re.sub('\s*,\s*', ',', post['services[]']) tag_names = formatted_services.split(',') for tag_name in tag_names: tag = request.env['crm.lead.tag'].sudo().search( [('technical_name', '=', tag_name)], limit=1) if tag: tag_ids.append(tag.id) formatted_name = ' '.join([ x for x in (post.get('your-name', ''), post.get('your-firstname', '')) if x != '' ]) vals = { 'name': '[Bobex] {}'.format(formatted_name), 'type': 'lead', 'country_id': request.env['res.country'].search([('code', '=', 'BE')]).id or False, 'lang_id': request.env['res.lang'].search([('code', '=', post.get('your-lang'))]).id if post.get('your-lang') else request.env['res.lang'].search( [('code', '=', 'fr_BE')]).id or False, 'contact_name': formatted_name, 'email_from': tools.formataddr((formatted_name, post.get('your-email'))) if post.get('your-email') else '', 'phone': phone_validation.phone_format(post.get('your-tel'), 'BE', '32', force_format='INTERNATIONAL', raise_exception=False) or '', 'street': post.get('your-adres', ''), 'city': post.get('your-local', ''), 'zip': post.get('your-postal', ''), 'description': _('Bobex Reference: {}\n{}').format( post.get('sourceref', ''), post.get('your-message', '')), 'source_id': request.env['utm.source'].sudo().search( [('technical_name', '=', 'bobex')]).id or False, 'tag_ids': [(6, 0, tag_ids)] } request.env['crm.lead'].sudo().create(vals) return 'OK' elif post.get('menu-demande') == 'Demande de devis gratuit' and ( post.get('your-tel') or post.get('your-email')) and post.get('your-name'): tags = request.httprequest.form.getlist('services[]') tag_ids = [] for tag in tags: tag_id = request.env['crm.lead.tag'].sudo().search([ ('technical_name', '=', tag) ]) if tag_id: tag_ids.append(tag_id.id) vals = { 'name': '{} - {}'.format(' ,'.join(tags), post['your-name']), 'type': 'lead', 'country_id': request.env['res.country'].search([('code', '=', 'BE')]).id or False, 'lang_id': request.env['res.lang'].search([('code', '=', 'fr_BE')]).id or False, 'contact_name': post['your-name'], 'email_from': tools.formataddr((post['your-name'], post.get('your-email'))) if post.get('your-email') else '', 'phone': phone_validation.phone_format(post.get('your-tel'), 'BE', '32', force_format='INTERNATIONAL', raise_exception=False) or '', 'street': post.get('your-adres', ''), 'city': post.get('your-local', ''), 'zip': post.get('your-postal', ''), 'description': post.get('your-message', ''), 'source_id': request.env['utm.source'].sudo().search( [('technical_name', '=', 'website')]).id or False, 'tag_ids': [(6, 0, tag_ids)] } request.env['crm.lead'].sudo().create(vals) return 'OK' elif post.get('secret') and (post.get('phone') or post.get('email') ) and post.get('last_name'): try: data_list = request.httprequest.form.getlist('additional_data') data = '\n'.join(data_list) except Exception: data = post.get('additional_data', '') try: product_list = request.httprequest.form.getlist('products') products = '\n'.join(product_list) except Exception: products = post.get('products', '') formatted_name = ' '.join([ x for x in (post.get('last_name', ''), post.get('first_name', '')) if x != '' ]) vals = { 'name': '[Solvari] {}'.format(formatted_name), 'type': 'lead', 'country_id': request.env['res.country'].search([('code', '=', 'BE')]).id or False, 'lang_id': request.env['res.lang'].search([('code', '=', 'fr_BE')]).id or False, 'contact_name': formatted_name, 'email_from': tools.formataddr( (post['last_name'], post.get('email'))) if post.get('email') else '', 'phone': phone_validation.phone_format(post.get('phone'), 'BE', '32', force_format='INTERNATIONAL', raise_exception=False) or '', 'street': ', '.join([ x for x in (post.get('street', ''), post.get('house_nr', '')) if x != '' ]), 'city': post.get('city', ''), 'zip': post.get('zip_code', ''), 'description': '{}{}{}{}{}'.format( _('Message By Solvari: {}\n').format( post.get('message_by_solvari')) if post.get('message_by_solvari') else '', _('Amount of Competitors: {}\n').format( post.get('competitors')) if post.get('competitors') else '', _('Description: {}\n').format(post.get('description')) if post.get('description') else '', _('Questions: {}\n').format(data), _('Products: {}\n').format(products)), 'source_id': request.env['utm.source'].sudo().search( [('technical_name', '=', 'solvari')]).id or False, } request.env['crm.lead'].sudo().create(vals) return json.dumps({'success': True}) else: return Response("Wrong parameters", status=400)
def test_mass_sms_internals_errors(self): # same customer, specific different number on record -> should be valid new_record_1 = self.env['mail.test.sms'].create({ 'name': 'MassSMSTest_nr1', 'customer_id': self.partners[0].id, 'phone_nbr': '0456999999', }) void_record = self.env['mail.test.sms'].create({ 'name': 'MassSMSTest_void', 'customer_id': False, 'phone_nbr': '', }) falsy_record_1 = self.env['mail.test.sms'].create({ 'name': 'MassSMSTest_falsy_1', 'customer_id': False, 'phone_nbr': 'abcd', }) falsy_record_2 = self.env['mail.test.sms'].create({ 'name': 'MassSMSTest_falsy_2', 'customer_id': False, 'phone_nbr': '04561122', }) bl_record_1 = self.env['mail.test.sms'].create({ 'name': 'MassSMSTest_bl_1', 'customer_id': False, 'phone_nbr': '0456110011', }) self.env['phone.blacklist'].sudo().create({'number': '0456110011'}) # new customer, number already on record -> should be ignored country_be_id = self.env.ref('base.be').id nr2_partner = self.env['res.partner'].create({ 'name': 'Partner_nr2', 'country_id': country_be_id, 'mobile': '0456449999', }) new_record_2 = self.env['mail.test.sms'].create({ 'name': 'MassSMSTest_nr2', 'customer_id': nr2_partner.id, 'phone_nbr': self.records[0].phone_nbr, }) records_numbers = self.records_numbers + ['+32456999999'] mailing = self.env['mailing.mailing'].browse(self.mailing_sms.ids) mailing.write({'sms_force_send': False}) # force outgoing sms, not sent with self.with_user('user_marketing'): with self.mockSMSGateway(): mailing.action_send_sms() self.assertSMSTraces( [{ 'partner': record.customer_id, 'number': records_numbers[i], 'content': 'Dear %s this is a mass SMS' % record.display_name } for i, record in enumerate(self.records | new_record_1)], mailing, self.records | new_record_1, ) # duplicates self.assertSMSTraces( [{ 'partner': new_record_2.customer_id, 'number': self.records_numbers[0], 'content': 'Dear %s this is a mass SMS' % new_record_2.display_name, 'trace_status': 'cancel', 'failure_type': 'sms_duplicate' }], mailing, new_record_2, ) # blacklist self.assertSMSTraces( [{ 'partner': self.env['res.partner'], 'number': phone_validation.phone_format( bl_record_1.phone_nbr, 'BE', '32', force_format='E164'), 'content': 'Dear %s this is a mass SMS' % bl_record_1.display_name, 'trace_status': 'cancel', 'failure_type': 'sms_blacklist' }], mailing, bl_record_1, ) # missing number self.assertSMSTraces( [{ 'partner': self.env['res.partner'], 'number': False, 'content': 'Dear %s this is a mass SMS' % void_record.display_name, 'trace_status': 'cancel', 'failure_type': 'sms_number_missing' }], mailing, void_record, ) # wrong values self.assertSMSTraces( [{ 'partner': self.env['res.partner'], 'number': record.phone_nbr, 'content': 'Dear %s this is a mass SMS' % record.display_name, 'trace_status': 'cancel', 'failure_type': 'sms_number_format' } for record in falsy_record_1 + falsy_record_2], mailing, falsy_record_1 + falsy_record_2, )
def _create_leads_batch(self, lead_type='lead', count=10, email_dup_count=0, partner_count=0, partner_ids=None, user_ids=None, country_ids=None, probabilities=None): """ Helper tool method creating a batch of leads, useful when dealing with batch processes. Please update me. :param string type: 'lead', 'opportunity', 'mixed' (lead then opp), None (depends on configuration); :param partner_count: if not partner_ids is given, generate partner count customers; other leads will have no customer; :param partner_ids: a set of partner ids to cycle when creating leads; :param user_ids: a set of user ids to cycle when creating leads; :return: create leads """ types = ['lead', 'opportunity'] leads_data = [{ 'name': 'TestLead_%04d' % (x), 'type': lead_type if lead_type else types[x % 2], 'priority': '%s' % (x % 3), } for x in range(count)] # generate customer information partners = [] if partner_count: partners = self.env['res.partner'].create([{ 'name': 'AutoPartner_%04d' % (x), 'email': tools.formataddr(( 'AutoPartner_%04d' % (x), '*****@*****.**' % (x), )), } for x in range(partner_count)]) # customer information if partner_ids: for idx, lead_data in enumerate(leads_data): lead_data['partner_id'] = partner_ids[idx % len(partner_ids)] else: for idx, lead_data in enumerate(leads_data): if partner_count and idx < partner_count: lead_data['partner_id'] = partners[idx].id else: lead_data['email_from'] = tools.formataddr( ('TestCustomer_%02d' % (idx), '*****@*****.**' % (idx))) # country + phone information if country_ids: cid_to_country = dict( (country.id, country) for country in self.env['res.country'].browse( [cid for cid in country_ids if cid])) for idx, lead_data in enumerate(leads_data): country_id = country_ids[idx % len(country_ids)] country = cid_to_country.get(country_id, self.env['res.country']) lead_data['country_id'] = country.id if lead_data['country_id']: lead_data['phone'] = phone_validation.phone_format( '0456%04d99' % (idx), country.code, country.phone_code, force_format='E164') else: lead_data['phone'] = '+32456%04d99' % (idx) # salesteam information if user_ids: for idx, lead_data in enumerate(leads_data): lead_data['user_id'] = user_ids[idx % len(user_ids)] # probabilities if probabilities: for idx, lead_data in enumerate(leads_data): lead_data['probability'] = probabilities[idx % len(probabilities)] # duplicates (currently only with email) dups_data = [] if email_dup_count and not partner_ids: for idx, lead_data in enumerate(leads_data): if not lead_data.get('partner_id') and lead_data['email_from']: dup_data = dict(lead_data) dup_data['name'] = 'Duplicated-%s' % dup_data['name'] dups_data.append(dup_data) if len(dups_data) >= email_dup_count: break return self.env['crm.lead'].create(leads_data + dups_data)
def test_crm_lead_partner_sync_email_phone(self): """ Specifically test synchronize between a lead and its partner about phone and email fields. Phone especially has some corner cases due to automatic formatting (notably with onchange in form view). """ lead, partner = self.lead_1.with_user(self.env.user), self.contact_2 lead_form = Form(lead) # reset partner phone to a local number and prepare formatted / sanitized values partner_phone, partner_mobile = self.test_phone_data[ 2], self.test_phone_data[1] partner_phone_formatted = phone_format(partner_phone, 'US', '1') partner_phone_sanitized = phone_format(partner_phone, 'US', '1', force_format='E164') partner_mobile_formatted = phone_format(partner_mobile, 'US', '1') partner_mobile_sanitized = phone_format(partner_mobile, 'US', '1', force_format='E164') partner_email, partner_email_normalized = self.test_email_data[ 2], self.test_email_data_normalized[2] self.assertEqual(partner_phone_formatted, '+1 202-555-0888') self.assertEqual(partner_phone_sanitized, self.test_phone_data_sanitized[2]) self.assertEqual(partner_mobile_formatted, '+1 202-555-0999') self.assertEqual(partner_mobile_sanitized, self.test_phone_data_sanitized[1]) # ensure initial data self.assertEqual(partner.phone, partner_phone) self.assertEqual(partner.mobile, partner_mobile) self.assertEqual(partner.email, partner_email) # LEAD/PARTNER SYNC: email and phone are propagated to lead # as well as mobile (who does not trigger the reverse sync) lead_form.partner_id = partner self.assertEqual(lead_form.email_from, partner_email) self.assertEqual(lead_form.phone, partner_phone_formatted, 'Lead: form automatically formats numbers') self.assertEqual(lead_form.mobile, partner_mobile_formatted, 'Lead: form automatically formats numbers') self.assertFalse(lead_form.partner_email_update) self.assertFalse(lead_form.partner_phone_update) lead_form.save() self.assertEqual(partner.phone, partner_phone, 'Lead / Partner: partner values sent to lead') self.assertEqual(lead.email_from, partner_email, 'Lead / Partner: partner values sent to lead') self.assertEqual( lead.email_normalized, partner_email_normalized, 'Lead / Partner: equal emails should lead to equal normalized emails' ) self.assertEqual( lead.phone, partner_phone_formatted, 'Lead / Partner: partner values (formatted) sent to lead') self.assertEqual( lead.mobile, partner_mobile_formatted, 'Lead / Partner: partner values (formatted) sent to lead') self.assertEqual(lead.phone_sanitized, partner_mobile_sanitized, 'Lead: phone_sanitized computed field on mobile') # for email_from, if only formatting differs, warning should not appear and # email on partner should not be updated lead_form.email_from = '"Hermes Conrad" <%s>' % partner_email_normalized self.assertFalse(lead_form.partner_email_update) lead_form.save() self.assertEqual(partner.email, partner_email) # for phone, if only formatting differs, warning should not appear and # phone on partner should not be updated lead_form.phone = partner_phone_sanitized self.assertFalse(lead_form.partner_phone_update) lead_form.save() self.assertEqual(partner.phone, partner_phone) # LEAD/PARTNER SYNC: lead updates partner new_email = '"John Zoidberg" <*****@*****.**>' new_email_normalized = '*****@*****.**' lead_form.email_from = new_email self.assertTrue(lead_form.partner_email_update) new_phone = '+1 202 555 7799' new_phone_formatted = phone_format(new_phone, 'US', '1') lead_form.phone = new_phone self.assertEqual(lead_form.phone, new_phone_formatted) self.assertTrue(lead_form.partner_email_update) self.assertTrue(lead_form.partner_phone_update) lead_form.save() self.assertEqual(partner.email, new_email) self.assertEqual(partner.email_normalized, new_email_normalized) self.assertEqual(partner.phone, new_phone_formatted) # LEAD/PARTNER SYNC: mobile does not update partner new_mobile = '+1 202 555 6543' new_mobile_formatted = phone_format(new_mobile, 'US', '1') lead_form.mobile = new_mobile lead_form.save() self.assertEqual(lead.mobile, new_mobile_formatted) self.assertEqual(partner.mobile, partner_mobile) # LEAD/PARTNER SYNC: reseting lead values also resets partner for email # and phone, but not for mobile lead_form.email_from, lead_form.phone, lead.mobile = False, False, False self.assertTrue(lead_form.partner_email_update) self.assertTrue(lead_form.partner_phone_update) lead_form.save() self.assertFalse(partner.email) self.assertFalse(partner.email_normalized) self.assertFalse(partner.phone) self.assertFalse(lead.phone) self.assertFalse(lead.mobile) self.assertFalse(lead.phone_sanitized) self.assertEqual(partner.mobile, partner_mobile) self.assertEqual(partner.phone_sanitized, partner_mobile_sanitized, 'Partner sanitized should be computed on mobile')