From 5a9476422cfff05889484cce42372b3b757a11eb Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 15 Dec 2020 12:35:14 +0100 Subject: [PATCH] [MIG] base_partner_one2many_phone from v10 to v14 --- base_partner_one2many_phone/__init__.py | 1 - base_partner_one2many_phone/__manifest__.py | 10 +-- .../migrations/10.0.2.0.0/post-migration.py | 79 ------------------- base_partner_one2many_phone/partner_phone.py | 38 +++++---- .../partner_phone_view.xml | 37 +++++++-- base_partner_one2many_phone/post_install.py | 11 +-- .../security/ir.model.access.csv | 1 - .../tests/test_partner_phone.py | 40 ++++------ 8 files changed, 69 insertions(+), 148 deletions(-) delete mode 100644 base_partner_one2many_phone/migrations/10.0.2.0.0/post-migration.py diff --git a/base_partner_one2many_phone/__init__.py b/base_partner_one2many_phone/__init__.py index 1a8f37a..361d25d 100644 --- a/base_partner_one2many_phone/__init__.py +++ b/base_partner_one2many_phone/__init__.py @@ -1,3 +1,2 @@ -# -*- encoding: utf-8 -*- from . import partner_phone from .post_install import migrate_to_partner_phone diff --git a/base_partner_one2many_phone/__manifest__.py b/base_partner_one2many_phone/__manifest__.py index 90af8c1..d28b288 100644 --- a/base_partner_one2many_phone/__manifest__.py +++ b/base_partner_one2many_phone/__manifest__.py @@ -1,13 +1,12 @@ -# -*- coding: utf-8 -*- -# © 2014-2016 Abbaye du Barroux (http://www.barroux.org) -# © 2016 Akretion (http://www.akretion.com>) +# Copyright 2014-2020 Abbaye du Barroux (http://www.barroux.org) +# Copyright 2014-2020 Akretion (http://www.akretion.com>) # @author: Frère Bernard # @author: Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { 'name': 'Base Partner One2many Phone', - 'version': '10.0.2.0.0', + 'version': '14.0.1.0.0', 'category': 'Phone', 'license': 'AGPL-3', 'summary': 'One2many link between partners and phone numbers/emails', @@ -21,7 +20,8 @@ It has been developped by brother Bernard from Barroux Abbey and Alexis de Lattr """, 'author': 'Akretion', 'website': 'https://akretion.com/', - 'depends': ['base_phone', 'sales_team', 'base_usability'], + 'depends': ['contacts', 'base_usability', 'phone_validation'], + 'excludes': ['sms'], # because sms introduces big changes in partner form view 'data': [ 'partner_phone_view.xml', 'security/ir.model.access.csv', diff --git a/base_partner_one2many_phone/migrations/10.0.2.0.0/post-migration.py b/base_partner_one2many_phone/migrations/10.0.2.0.0/post-migration.py deleted file mode 100644 index 85c1c6c..0000000 --- a/base_partner_one2many_phone/migrations/10.0.2.0.0/post-migration.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 Akretion France (http://www.akretion.com/) -# @author: Alexis de Lattre -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import api, SUPERUSER_ID - -oldtype2label = { - '1_home': 'Ancien type : Maison', -# '2_mobile': 'Ancien type : Portable', - '3_office': 'Ancien type : Bureau', - '4_home_fax': 'Ancien type : Fax maison', - '5_office_fax': 'Ancien type : Fax bureau', - '6_phone_fax_home': u'Ancien type : Tél/fax maison', - '7_other': 'Ancien type : Autre', - } - - -def migrate(cr, version): - if not version: - return - - with api.Environment.manage(): - env = api.Environment(cr, SUPERUSER_ID, {}) - rppo = env['res.partner.phone'] - - wdict = {} # key = partnerID, values = {id: {'type': '1_home', 'phone': '+33'}} - for rec in rppo.search_read([('type', '!=', False)], ['type', 'phone', 'partner_id', 'note']): - if rec['partner_id'][0] not in wdict: - wdict[rec['partner_id'][0]] = {} - wdict[rec['partner_id'][0]][rec['id']] = rec - - # first pass for primary phone - for partner_id, xdict in wdict.items(): - mig_phone_entries(cr, xdict, '3_phone_primary', '4_phone_secondary', ['1_home', '6_phone_fax_home', '3_office', '7_other']) - mig_phone_entries(cr, xdict, '5_mobile_primary', '6_mobile_secondary', ['2_mobile']) - mig_phone_entries(cr, xdict, '7_fax_primary', '8_fax_secondary', ['4_home_fax', '5_office_fax']) - cr.execute('select id, email from res_partner where email is not null order by id') - for partner in cr.dictfetchall(): - print('partner_id=', partner['id']) - old_email = partner['email'].strip() - if old_email: - email_split = old_email.split(',') - clean_email_split = [x.strip() for x in email_split if x.strip()] - # primary: - email_primary = clean_email_split.pop(0) - rppo.create({ - 'type': '1_email_primary', - 'partner_id': partner['id'], - 'email': email_primary, - }) - cr.execute('UPDATE res_partner set email=%s where id=%s', (email_primary, partner['id'])) - for email_sec in clean_email_split: - email_sec = email_sec.strip() - if email_sec: - rppo.create({ - 'type': '2_email_secondary', - 'partner_id': partner['id'], - 'email': email_sec.strip(), - }) - - -def mig_phone_entries(cr, xdict, new_type_primary, new_type_secondary, old_type_list): - zdict = {} - for phone_id, values in xdict.items(): - if values['type'] in old_type_list: - zdict[phone_id] = values - if zdict: - values_sorted = sorted(zdict.values(), key=lambda x: x['type']) - primary_phone_val = values_sorted[0] - cr.execute("""UPDATE res_partner_phone SET type=%s WHERE id=%s""", (new_type_primary, primary_phone_val['id'])) - if not primary_phone_val.get('note') and oldtype2label.get(primary_phone_val['type']): - cr.execute("""UPDATE res_partner_phone SET note=%s WHERE id=%s""", (oldtype2label[primary_phone_val['type']], primary_phone_val['id'])) - - zdict.pop(primary_phone_val['id']) - for secondary_phone_val in zdict.values(): - cr.execute("""UPDATE res_partner_phone SET type=%s WHERE id=%s""", (new_type_secondary, secondary_phone_val['id'])) - if not secondary_phone_val.get('note') and oldtype2label.get(secondary_phone_val['type']): - cr.execute("""UPDATE res_partner_phone SET note=%s WHERE id=%s""", (oldtype2label[secondary_phone_val['type']], secondary_phone_val['id'])) diff --git a/base_partner_one2many_phone/partner_phone.py b/base_partner_one2many_phone/partner_phone.py index 24af43e..b99db28 100644 --- a/base_partner_one2many_phone/partner_phone.py +++ b/base_partner_one2many_phone/partner_phone.py @@ -1,13 +1,11 @@ -# -*- coding: utf-8 -*- -# © 2014-2016 Abbaye du Barroux (http://www.barroux.org) -# © 2016 Akretion (http://www.akretion.com>) +# Copyright 2014-2020 Abbaye du Barroux (http://www.barroux.org) +# Copyright 2016-2020 Akretion (http://www.akretion.com>) # @author: Frère Bernard # @author: Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models, fields, api, _ +from odoo import api, fields, models, _ from odoo.exceptions import ValidationError -from odoo.addons.base_phone.fields import Phone, Fax EMAIL_TYPES = ('1_email_primary', '2_email_secondary') PHONE_TYPES = ('3_phone_primary', '4_phone_secondary', '5_mobile_primary', '6_mobile_secondary', '7_fax_primary', '8_fax_secondary') @@ -17,6 +15,8 @@ class ResPartnerPhone(models.Model): _name = 'res.partner.phone' _order = 'partner_id, type' _phone_name_sequence = 8 + _inherit = ['phone.validation.mixin'] + _description = 'Multiple emails and phones for partners' partner_id = fields.Many2one( 'res.partner', string='Related Partner', index=True, ondelete='cascade') @@ -31,7 +31,7 @@ class ResPartnerPhone(models.Model): ('8_fax_secondary', 'Secondary Fax'), ], string='Type', required=True, index=True) - phone = Phone('Phone', required=False, partner_field='partner_id') + phone = fields.Char(string='Phone') email = fields.Char(string='E-Mail') note = fields.Char('Note') @@ -43,6 +43,11 @@ class ResPartnerPhone(models.Model): elif self.type in PHONE_TYPES: self.email = False + @api.onchange('phone', 'partner_id') + def _onchange_phone_validation(self): + if self.phone: + self.phone = self.phone_format(self.phone) + @api.constrains('type', 'phone', 'email') def _check_partner_phone(self): for rec in self: @@ -74,7 +79,6 @@ class ResPartnerPhone(models.Model): res.append((pphone.id, name)) return res - @api.model_cr def init(self): self._cr.execute(''' CREATE UNIQUE INDEX IF NOT EXISTS single_email_primary @@ -111,14 +115,11 @@ class ResPartner(models.Model): # for the future :) phone_ids = fields.One2many( - 'res.partner.phone', 'partner_id', string='Phones') - phone = Phone( + 'res.partner.phone', 'partner_id', string='Phones/Emails') + phone = fields.Char( compute='_compute_partner_phone', store=True, readonly=True, compute_sudo=True) - mobile = Phone( - compute='_compute_partner_phone', - store=True, readonly=True, compute_sudo=True) - fax = Fax( + mobile = fields.Char( compute='_compute_partner_phone', store=True, readonly=True, compute_sudo=True) email = fields.Char( @@ -128,20 +129,17 @@ class ResPartner(models.Model): @api.depends('phone_ids.phone', 'phone_ids.type', 'phone_ids.email') def _compute_partner_phone(self): for partner in self: - phone = mobile = fax = email = False + phone = mobile = email = False for pphone in partner.phone_ids: if pphone.type == '1_email_primary' and pphone.email: email = pphone.email elif pphone.phone: if pphone.type == '5_mobile_primary': mobile = pphone.phone - elif pphone.type == '7_fax_primary': - fax = pphone.phone elif pphone.type == '3_phone_primary': phone = pphone.phone partner.phone = phone partner.mobile = mobile - partner.fax = fax partner.email = email def _update_create_vals( @@ -157,8 +155,8 @@ class ResPartner(models.Model): self._update_create_vals(vals, '1_email_primary', 'email', 'email') self._update_create_vals(vals, '3_phone_primary', 'phone', 'phone') self._update_create_vals(vals, '5_mobile_primary', 'mobile', 'phone') - self._update_create_vals(vals, '7_fax_primary', 'fax', 'phone') - return super(ResPartner, self).create(vals) + # self._update_create_vals(vals, '7_fax_primary', 'fax', 'phone') + return super().create(vals) def _update_write_vals( self, vals, type, partner_field, partner_phone_field): @@ -192,4 +190,4 @@ class ResPartner(models.Model): super(ResPartner, rec).write(vals) return True else: - return super(ResPartner, self).write(vals) + return super().write(vals) diff --git a/base_partner_one2many_phone/partner_phone_view.xml b/base_partner_one2many_phone/partner_phone_view.xml index f759640..f1e12bd 100644 --- a/base_partner_one2many_phone/partner_phone_view.xml +++ b/base_partner_one2many_phone/partner_phone_view.xml @@ -1,7 +1,7 @@ @@ -79,9 +83,6 @@ 1 - - 1 - 1 @@ -127,6 +128,26 @@ + + add.phone_ids.on.res.partner.private.form + res.partner + + + + + + + 1 + + + 1 + + + 1 + + + + phone.one2many.res.partner.search res.partner diff --git a/base_partner_one2many_phone/post_install.py b/base_partner_one2many_phone/post_install.py index 00d21a7..128fc9b 100644 --- a/base_partner_one2many_phone/post_install.py +++ b/base_partner_one2many_phone/post_install.py @@ -1,5 +1,5 @@ -# -*- coding: utf-8 -*- -# © 2017 Akretion (Alexis de Lattre ) +# Copyright 2017-2020 Akretion France (http://www.akretion.com/) +# @author Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import api, SUPERUSER_ID @@ -41,13 +41,8 @@ def migrate_to_partner_phone(cr, registry): to_create = [] to_create += create_partner_phone(cr, 'phone', '3_phone_primary') to_create += create_partner_phone(cr, 'mobile', '5_mobile_primary') - to_create += create_partner_phone(cr, 'fax', '7_fax_primary') to_create += create_partner_email(cr) # I need to create all at the end for invalidation purposes - for vals in to_create: - rppo.create(vals) - logger.info( - 'partner_phone type %s phone %s email %s created for partner ID %d', - vals['type'], vals.get('phone'), vals.get('mail'), vals['partner_id']) + rppo.create(to_create) logger.info('end data migration for one2many_phone') return diff --git a/base_partner_one2many_phone/security/ir.model.access.csv b/base_partner_one2many_phone/security/ir.model.access.csv index 4189fcb..64c685a 100644 --- a/base_partner_one2many_phone/security/ir.model.access.csv +++ b/base_partner_one2many_phone/security/ir.model.access.csv @@ -1,4 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_partner_phone_full,Full access on res.partner.phone to Contact Manager grp,model_res_partner_phone,base.group_partner_manager,1,1,1,1 access_partner_phone_read,Read access on res.partner.phone to Employees grp,model_res_partner_phone,base.group_user,1,0,0,0 -access_callerid_partner_phone_read,Read access on res.partner.phone to callerID group,model_res_partner_phone,base_phone.group_callerid,1,0,0,0 diff --git a/base_partner_one2many_phone/tests/test_partner_phone.py b/base_partner_one2many_phone/tests/test_partner_phone.py index 85a2400..3515d20 100644 --- a/base_partner_one2many_phone/tests/test_partner_phone.py +++ b/base_partner_one2many_phone/tests/test_partner_phone.py @@ -16,24 +16,20 @@ class TestPartnerPhone(TransactionCase): pphone_email = rppo.search( [('type', '=', '1_email_primary'), ('partner_id', '=', partner.id)]) if result['email']: - self.assertEquals(partner.email, result['email']) - self.assertEquals(len(pphone_email), 1) - self.assertEquals(pphone_email.email, result['email']) + self.assertEqual(partner.email, result['email']) + self.assertEqual(len(pphone_email), 1) + self.assertEqual(pphone_email.email, result['email']) else: self.assertFalse(partner.email) self.assertFalse(pphone_email) if result['phone']: - self.assertEquals(partner.phone.replace(u'\xa0', ''), result['phone']) + self.assertEqual(partner.phone, result['phone']) else: self.assertFalse(partner.phone) if result['mobile']: - self.assertEquals(partner.mobile.replace(u'\xa0', ''), result['mobile']) + self.assertEqual(partner.mobile, result['mobile']) else: self.assertFalse(partner.mobile) - if result['fax']: - self.assertEquals(partner.fax.replace(u'\xa0', ''), result['fax']) - else: - self.assertFalse(partner.fax) field2type = { 'phone': '3_phone_primary', 'mobile': '5_mobile_primary', @@ -45,8 +41,8 @@ class TestPartnerPhone(TransactionCase): pphone = rppo.search( [('type', '=', type), ('partner_id', '=', partner.id)]) if value: - self.assertEquals(len(pphone), 1) - self.assertEquals(pphone.phone.replace(u'\xa0', ''), value) + self.assertEqual(len(pphone), 1) + self.assertEqual(pphone.phone, value) else: self.assertFalse(pphone) @@ -55,40 +51,36 @@ class TestPartnerPhone(TransactionCase): p = rpo.create({ 'name': 'Test Me', 'email': 'testme@example.com', - 'phone': '0198089246', - 'mobile': '0198089247', - 'fax': '0198089248', + 'phone': '+33198089246', + 'mobile': '+33198089247', }) result = { 'email': 'testme@example.com', 'phone': '+33198089246', 'mobile': '+33198089247', - 'fax': '+33198089248', } self._check_result(p, result) p2 = rpo.create({ 'name': 'Test me now', 'email': 'testmenow@example.com', - 'phone': '0972727272', + 'phone': '+33972727272', }) result = { 'email': 'testmenow@example.com', 'phone': '+33972727272', 'mobile': False, - 'fax': False, } self._check_result(p2, result) p3 = rpo.create({ 'name': 'Test me now', 'phone_ids': [ - (0, 0, {'type': '3_phone_primary', 'phone': '0972727272'}), + (0, 0, {'type': '3_phone_primary', 'phone': '+33972727272'}), (0, 0, {'type': '1_email_primary', 'email': 'tutu@example.fr'})], }) result = { 'email': 'tutu@example.fr', 'phone': '+33972727272', 'mobile': False, - 'fax': False, } self._check_result(p3, result) @@ -101,30 +93,27 @@ class TestPartnerPhone(TransactionCase): 'email': False, 'phone': False, 'mobile': False, - 'fax': False, } self._check_result(p1, result_none) p1.write({ - 'mobile': '0198089247', + 'mobile': '+33198089247', 'email': 'testmenow@example.com', }) result = { 'email': 'testmenow@example.com', 'phone': False, 'mobile': '+33198089247', - 'fax': False, } self._check_result(p1, result) p1.write({ 'email': 'testmenow2@example.com', 'phone': False, - 'mobile': '04.72.72.72.72', + 'mobile': '+33472727272', }) result = { 'email': 'testmenow2@example.com', 'phone': False, 'mobile': '+33472727272', - 'fax': False, } self._check_result(p1, result) p1.write({ @@ -135,12 +124,11 @@ class TestPartnerPhone(TransactionCase): self._check_result(p1, result_none) p2 = self.env['res.partner'].create({'name': 'Toto', 'email': 'toto@example.com'}) p_multi = p1 + p2 - p_multi.write({'email': 'all@example.com', 'phone': '05.60.60.60.70'}) + p_multi.write({'email': 'all@example.com', 'phone': '+33560606070'}) result = { 'email': 'all@example.com', 'phone': '+33560606070', 'mobile': False, - 'fax': False, } self._check_result(p1, result) self._check_result(p2, result)