diff --git a/partner_relations/__init__.py b/partner_relations/__init__.py index 9da2ac3b6..193512b44 100644 --- a/partner_relations/__init__.py +++ b/partner_relations/__init__.py @@ -1,21 +1,4 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2013 Therp BV (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2013-2017 Therp BV . +# License AGPL-3.0 or later . from . import model diff --git a/partner_relations/__openerp__.py b/partner_relations/__openerp__.py index f70ab862f..f76697748 100644 --- a/partner_relations/__openerp__.py +++ b/partner_relations/__openerp__.py @@ -1,27 +1,11 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2013 Therp BV (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2013-2017 Therp BV . +# License AGPL-3.0 or later . { "name": "Partner relations", - "version": "1.1", + "version": "7.0.1.1.1", "author": "Therp BV,Odoo Community Association (OCA)", + "license": "AGPL-3", "complexity": "normal", "description": """ Introduction @@ -83,15 +67,6 @@ date.""", 'view/menu.xml', 'security/ir.model.access.csv', ], - "js": [ - ], - "css": [ - ], - "qweb": [ - ], "auto_install": False, "installable": True, - "external_dependencies": { - 'python': [], - }, } diff --git a/partner_relations/model/__init__.py b/partner_relations/model/__init__.py index b5afe7aa1..2ce8bb72a 100644 --- a/partner_relations/model/__init__.py +++ b/partner_relations/model/__init__.py @@ -1,23 +1,6 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2013 Therp BV (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2013-2017 Therp BV . +# License AGPL-3.0 or later . from . import res_partner from . import res_partner_relation from . import res_partner_relation_type diff --git a/partner_relations/model/res_partner.py b/partner_relations/model/res_partner.py index 0fe49815a..570eb9f10 100644 --- a/partner_relations/model/res_partner.py +++ b/partner_relations/model/res_partner.py @@ -1,25 +1,8 @@ # -*- coding: utf-8 -*- -'''Extend res.partner model''' -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2013 Therp BV (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2013-2017 Therp BV . +# License AGPL-3.0 or later . import time + from openerp.osv import orm, fields from openerp.osv.expression import is_leaf, AND, OR, FALSE_LEAF from openerp.tools import DEFAULT_SERVER_DATE_FORMAT @@ -31,12 +14,12 @@ class ResPartner(orm.Model): def _get_relation_ids_select(self, cr, uid, ids, field_name, arg, context=None): - '''return the partners' relations as tuple - (id, left_partner_id, right_partner_id)''' + """return the partners' relations as tuple + (id, left_partner_id, right_partner_id)""" cr.execute( - '''select id, left_partner_id, right_partner_id + """select id, left_partner_id, right_partner_id from res_partner_relation - where (left_partner_id in %s or right_partner_id in %s)''' + + where (left_partner_id in %s or right_partner_id in %s)""" + ' order by ' + self.pool['res.partner.relation']._order, (tuple(ids), tuple(ids)) ) @@ -44,7 +27,7 @@ class ResPartner(orm.Model): def _get_relation_ids( self, cr, uid, ids, field_name, arg, context=None): - '''getter for relation_ids''' + """getter for relation_ids""" if context is None: context = {} result = dict([(i, []) for i in ids]) @@ -60,7 +43,7 @@ class ResPartner(orm.Model): def _set_relation_ids( self, cr, uid, ids, dummy_name, field_value, dummy_arg, context=None): - '''setter for relation_ids''' + """setter for relation_ids""" if context is None: context = {} relation_obj = self.pool.get('res.partner.relation') diff --git a/partner_relations/model/res_partner_relation.py b/partner_relations/model/res_partner_relation.py index f969ad26e..a8c5c2252 100644 --- a/partner_relations/model/res_partner_relation.py +++ b/partner_relations/model/res_partner_relation.py @@ -1,31 +1,13 @@ # -*- coding: utf-8 -*- -'''Define model res.partner.relation''' -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2013 Therp BV (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2013-2017 Therp BV . +# License AGPL-3.0 or later . from openerp.osv.orm import Model, except_orm from openerp.osv import fields from openerp.tools.translate import _ class ResPartnerRelation(Model): - '''Model res.partner.relation is used to describe all links or relations + """Model res.partner.relation is used to describe all links or relations between partners in the database. In many parts of the code we have to know whether the active partner is @@ -35,23 +17,14 @@ class ResPartnerRelation(Model): Because the active partner is crucial for the working of partner relationships, we make sure on the res.partner model that the partner id is set in the context where needed. - ''' + """ _name = 'res.partner.relation' _description = 'Partner relation' _order = 'active desc, date_start desc, date_end desc' - def _on_right_partner(self, cr, uid, right_partner_id, context=None): - '''Determine wether functions are called in a situation where the - active partner is the right partner. Default False! - ''' - if (context and 'active_ids' in context and - right_partner_id in context.get('active_ids', [])): - return True - return False - def _correct_vals(self, cr, uid, vals, context=None): - '''Fill type and left and right partner id, according to wether - we have a normal relation type or an inverse relation type''' + """Fill type and left and right partner id, according to wether + we have a normal relation type or an inverse relation type""" vals = vals.copy() # If type_selection_id ends in 1, it is a reverse relation type if 'type_selection_id' in vals: @@ -75,13 +48,16 @@ class ResPartnerRelation(Model): def _get_computed_fields( self, cr, uid, ids, field_names, arg, context=None): - '''Return a dictionary of dictionaries, with for every partner for - ids, the computed values.''' + """Return a dictionary of dictionaries, with for every partner for + ids, the computed values.""" def get_values(self, dummy_field_names, dummy_arg, context=None): - '''Get computed values for record''' + """Get computed values for record""" values = {} - on_right_partner = self._on_right_partner( - cr, uid, self.right_partner_id.id, context=context) + on_right_partner = ( + 'active_ids' in context and + self.right_partner_id.id in context.get('active_ids', []) or + False + ) # type_selection_id values['type_selection_id'] = ( ((self.type_id.id) * 10) + (on_right_partner and 1 or 0)) @@ -99,26 +75,27 @@ class ResPartnerRelation(Model): values['is_relation_future'] = self.date_start > today return values + context = context or {} return dict([ (i.id, get_values(i, field_names, arg, context=context)) for i in self.browse(cr, uid, ids, context=context) ]) def write(self, cr, uid, ids, vals, context=None): - '''Override write to correct values, before being stored.''' + """Override write to correct values, before being stored.""" vals = self._correct_vals(cr, uid, vals, context=context) return super(ResPartnerRelation, self).write( cr, uid, ids, vals, context=context) def create(self, cr, uid, vals, context=None): - '''Override create to correct values, before being stored.''' + """Override create to correct values, before being stored.""" vals = self._correct_vals(cr, uid, vals, context=context) return super(ResPartnerRelation, self).create( cr, uid, vals, context=context) def on_change_type_selection_id( self, cr, uid, dummy_ids, type_selection_id, context=None): - '''Set domain on partner_id_display, when selection a relation type''' + """Set domain on partner_id_display, when selection a relation type""" result = { 'domain': {'partner_id_display': []}, 'value': {'type_id': False} @@ -198,13 +175,12 @@ class ResPartnerRelation(Model): ), 'active': fields.boolean('Active'), } - _defaults = { 'active': True, } def _check_dates(self, cr, uid, ids, context=None): - '''End date should not be before start date, if noth filled''' + """End date should not be before start date, if noth filled""" for line in self.browse(cr, uid, ids, context=context): if line.date_start and line.date_end: if line.date_start > line.date_end: @@ -212,7 +188,7 @@ class ResPartnerRelation(Model): return True def _check_partner_type_left(self, cr, uid, ids, context=None): - '''Check left partner for required company or person''' + """Check left partner for required company or person""" for this in self.browse(cr, uid, ids, context=context): ptype = this.type_id.contact_type_left company = this.left_partner_id.is_company @@ -221,7 +197,7 @@ class ResPartnerRelation(Model): return True def _check_partner_type_right(self, cr, uid, ids, context=None): - '''Check right partner for required company or person''' + """Check right partner for required company or person""" for this in self.browse(cr, uid, ids, context=context): ptype = this.type_id.contact_type_right company = this.right_partner_id.is_company @@ -230,15 +206,15 @@ class ResPartnerRelation(Model): return True def _check_not_with_self(self, cr, uid, ids, context=None): - '''Not allowed to link partner to same partner''' + """Not allowed to link partner to same partner""" for this in self.browse(cr, uid, ids, context=context): if this.left_partner_id == this.right_partner_id: return False return True def _check_relation_uniqueness(self, cr, uid, ids, context=None): - '''Forbid multiple active relations of the same type between the same - partners''' + """Forbid multiple active relations of the same type between the same + partners""" for this in self.browse(cr, uid, ids, context=context): if not this.active: continue @@ -250,17 +226,21 @@ class ResPartnerRelation(Model): ('right_partner_id', '=', this.right_partner_id.id), ] if this.date_start: - domain += ['|', ('date_end', '=', False), - ('date_end', '>=', this.date_start)] + domain += [ + '|', ('date_end', '=', False), + ('date_end', '>=', this.date_start), + ] if this.date_end: - domain += ['|', ('date_start', '=', False), - ('date_start', '<=', this.date_end)] + domain += [ + '|', ('date_start', '=', False), + ('date_start', '<=', this.date_end), + ] if self.search(cr, uid, domain, context=context): raise except_orm( _('Overlapping relation'), _('There is already a similar relation ' - 'with overlapping dates')) - + 'with overlapping dates') + ) return True _constraints = [ @@ -292,12 +272,13 @@ class ResPartnerRelation(Model): ] def get_action_related_partners(self, cr, uid, ids, context=None): - '''return a window action showing a list of partners taking part in the + """return a window action showing a list of partners taking part in the relations names by ids. Context key 'partner_relations_show_side' determines if we show 'left' side, 'right' side or 'all' (default) partners. If active_model is res.partner.relation.all, left=this and - right=other''' + right=other + """ if context is None: context = {} diff --git a/partner_relations/model/res_partner_relation_all.py b/partner_relations/model/res_partner_relation_all.py index 2f3e71b9d..a5ed94bcc 100644 --- a/partner_relations/model/res_partner_relation_all.py +++ b/partner_relations/model/res_partner_relation_all.py @@ -1,28 +1,12 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2014 Therp BV (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2013-2017 Therp BV . +# License AGPL-3.0 or later . +from psycopg2.extensions import AsIs + from openerp.osv.orm import Model from openerp.osv import fields from openerp.tools import drop_view_if_exists -from .res_partner_relation_type_selection\ - import ResPartnerRelationTypeSelection +from .res_partner_relation_type_selection import _RECORD_TYPES class ResPartnerRelationAll(Model): @@ -32,7 +16,7 @@ class ResPartnerRelationAll(Model): _description = 'All (non-inverse + inverse) relations between partners' _additional_view_fields = [] - '''append to this list if you added fields to res_partner_relation that + """append to this list if you added fields to res_partner_relation that you need in this model and related fields are not adequate (ie for sorting) You must use the same name as in res_partner_relation. Don't overwrite this list in your declatarion but append in _auto_init: @@ -45,15 +29,16 @@ class ResPartnerRelationAll(Model): _columns = { 'my_field': .... } - ''' + """ def _auto_init(self, cr, context=None): + """Create view instead of table.""" drop_view_if_exists(cr, self._table) additional_view_fields = ','.join(self._additional_view_fields) additional_view_fields = (',' + additional_view_fields)\ if additional_view_fields else '' cr.execute( - '''create or replace view %s as + """create or replace view %s as select id * 10 as id, id as relation_id, @@ -79,20 +64,23 @@ class ResPartnerRelationAll(Model): active, type_id * 10 + 1 %s - from res_partner_relation''' % ( - self._table, - additional_view_fields, - additional_view_fields, + from res_partner_relation + """, + params=( + AsIs(self._table), + AsIs(additional_view_fields), + AsIs(additional_view_fields), ) ) - return super(ResPartnerRelationAll, self)._auto_init( cr, context=context) _columns = { 'record_type': fields.selection( - ResPartnerRelationTypeSelection._RECORD_TYPES, 'Record type', - readonly=True), + _RECORD_TYPES, + 'Record type', + readonly=True, + ), 'relation_id': fields.many2one( 'res.partner.relation', 'Relation', readonly=True), 'type_id': fields.many2one( @@ -110,6 +98,7 @@ class ResPartnerRelationAll(Model): } def name_get(self, cr, uid, ids, context=None): + """Create name from both partners and relation.""" return dict([ (this.id, '%s %s %s' % ( this.this_partner_id.name, @@ -119,7 +108,8 @@ class ResPartnerRelationAll(Model): for this in self.browse(cr, uid, ids, context=context)]) def write(self, cr, uid, ids, vals, context=None): - '''divert non-problematic writes to underlying table''' + """divert non-problematic writes to underlying table""" + # pylint: disable=W8106 return self.pool['res.partner.relation'].write( cr, uid, [i / 10 for i in ids], diff --git a/partner_relations/model/res_partner_relation_type.py b/partner_relations/model/res_partner_relation_type.py index 6e19eb47e..def398cf9 100644 --- a/partner_relations/model/res_partner_relation_type.py +++ b/partner_relations/model/res_partner_relation_type.py @@ -1,30 +1,12 @@ # -*- coding: utf-8 -*- -'''Define model res.partner.relation.type''' -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2013 Therp BV (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2013-2017 Therp BV . +# License AGPL-3.0 or later . from openerp.osv.orm import Model from openerp.osv import fields class ResPartnerRelationType(Model): - '''Model that defines relation types that might exist between partners''' + """Model that defines relation types that might exist between partners""" _name = 'res.partner.relation.type' _description = 'Parter relation type' _order = 'name' diff --git a/partner_relations/model/res_partner_relation_type_selection.py b/partner_relations/model/res_partner_relation_type_selection.py index e691936cf..5b5e29cb8 100644 --- a/partner_relations/model/res_partner_relation_type_selection.py +++ b/partner_relations/model/res_partner_relation_type_selection.py @@ -1,65 +1,61 @@ -# -*- coding: UTF-8 -*- -''' -Created on 23 may 2014 +# -*- coding: utf-8 -*- +# © 2014-2017 Therp BV . +# License AGPL-3.0 or later . +from psycopg2.extensions import AsIs -@author: Ronald Portier, Therp - -rportier@therp.nl -http://www.therp.nl - -For the model defined here _auto is set to False to prevent creating a -database file. All i/o operations are overridden to use a sql SELECT that -takes data from res_partner_connection_type where each type is included in the -result set twice, so it appears that the connection type and the inverse -type are separate records.. - -The original function _auto_init is still called because this function -normally (if _auto == True) not only creates the db tables, but it also takes -care of registering all fields in ir_model_fields. This is needed to make -the field labels translatable. - -example content for last lines of _statement: -select id, record_type, - customer_id, customer_name, customer_city, customer_zip, customer_street, - caller_id, caller_name, caller_phone, caller_fax, caller_email -from FULL_LIST as ResPartnerRelationTypeSelection where record_type = 'c' -ORDER BY ResPartnerRelationTypeSelection.customer_name asc, -ResPartnerRelationTypeSelection.caller_name asc; - -''' from openerp.osv import fields from openerp.osv import orm from openerp.tools import drop_view_if_exists -from openerp.addons.partner_relations.model.res_partner_relation_type\ - import ResPartnerRelationType +from .res_partner_relation_type import ResPartnerRelationType -class ResPartnerRelationTypeSelection(orm.Model): - '''Virtual relation types''' +_RECORD_TYPES = [ + ('a', 'Type'), + ('b', 'Inverse type'), +] - _RECORD_TYPES = [ - ('a', 'Type'), - ('b', 'Inverse type'), - ] +class ResPartnerRelationTypeSelection(orm.Model): + """Virtual relation types. + + For the model defined here _auto is set to False to prevent creating a + database file. All i/o operations are overridden to use a sql SELECT that + takes data from res_partner_connection_type where each type is included + in the result set twice, so it appears that the connection type and + the inverse type are separate records.. + + The original function _auto_init is still called because this function + normally (if _auto == True) not only creates the db tables, but it also + takes care of registering all fields in ir_model_fields. This is needed + to make the field labels translatable. + + example content for last lines of _statement: + select id, record_type, + customer_id, customer_name, customer_city, customer_zip, customer_street, + caller_id, caller_name, caller_phone, caller_fax, caller_email + from FULL_LIST as ResPartnerRelationTypeSelection where record_type = 'c' + ORDER BY ResPartnerRelationTypeSelection.customer_name asc, + ResPartnerRelationTypeSelection.caller_name asc; + """ _auto = False # Do not try to create table in _auto_init(..) _log_access = False def get_type_from_selection_id(self, cr, uid, selection_id): - '''Selection id ic computed from id of underlying type and the + """Selection id ic computed from id of underlying type and the kind of record. This function does the inverse computation to give - back the original type id, and about the record type.''' + back the original type id, and about the record type.""" type_id = selection_id / 10 is_reverse = (selection_id % 10) > 0 return (type_id, is_reverse) def _auto_init(self, cr, context=None): + """Create view instead of table.""" drop_view_if_exists(cr, self._table) # TODO: we lose field value's translations here. # probably we need to patch ir_translation.get_source for that # to get res_partner_relation_type's translations cr.execute( - '''create or replace view %s as + """create or replace view %s as select id * 10 as id, id as type_id, @@ -79,15 +75,18 @@ class ResPartnerRelationTypeSelection(orm.Model): contact_type_left, partner_category_right, partner_category_left - from res_partner_relation_type''' % self._table) - + from res_partner_relation_type + """, + params=( + AsIs(self._table), + ) + ) return super(ResPartnerRelationTypeSelection, self)._auto_init( cr, context=context) - def _search_partner_category_this(self, cr, uid, obj, field_name, args, - context=None): + def _search_partner_category_this( + self, cr, uid, obj, field_name, args, context=None): category_ids = [] - for arg in args: if isinstance(arg, tuple) and arg[0] == field_name\ and (arg[1] == '=' or arg[1] == 'in'): @@ -95,7 +94,6 @@ class ResPartnerRelationTypeSelection(orm.Model): for delta in arg[2]: if delta[0] == 6: category_ids.extend(delta[2]) - if category_ids: return [ '|',