From 06e071f6de2342ddae6390f25be0a36fdd0f66f1 Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Thu, 26 Mar 2015 13:45:43 -0400 Subject: [PATCH] Fix Read Write, Create and Unlink for realtion_all --- partner_relations/model/__init__.py | 16 ++- partner_relations/model/res_partner.py | 13 +- .../model/res_partner_relation.py | 119 ++++++++-------- .../model/res_partner_relation_all.py | 129 ++++++++++++------ .../model/res_partner_relation_type.py | 17 ++- .../res_partner_relation_type_selection.py | 37 +++-- partner_relations/view/res_partner.xml | 2 +- .../view/res_partner_relation.xml | 41 +----- .../view/res_partner_relation_all.xml | 63 ++++++++- 9 files changed, 271 insertions(+), 166 deletions(-) diff --git a/partner_relations/model/__init__.py b/partner_relations/model/__init__.py index b5afe7aa1..9e65bc55b 100644 --- a/partner_relations/model/__init__.py +++ b/partner_relations/model/__init__.py @@ -18,8 +18,22 @@ # along with this program. If not, see . # ############################################################################## + +PADDING = 10 + + +def get_partner_type(partner): + """Get partner type for relation. + + :param partner: a res.partner either a company or not + :return: 'c' for company or 'p' for person + :rtype: str + """ + return 'c' if partner.is_company else 'p' + + from . import res_partner from . import res_partner_relation from . import res_partner_relation_type -from . import res_partner_relation_type_selection from . import res_partner_relation_all +from . import res_partner_relation_type_selection diff --git a/partner_relations/model/res_partner.py b/partner_relations/model/res_partner.py index 80edb05b2..2f1af81e1 100644 --- a/partner_relations/model/res_partner.py +++ b/partner_relations/model/res_partner.py @@ -112,9 +112,10 @@ class ResPartner(models.Model): if arg[1] == '=' and isinstance(arg[2], (long, int)): relation_type_selection_ids.append(arg[2]) elif arg[1] == '!=' and isinstance(arg[2], (long, int)): - type_id, is_inverse = relation_type_selection\ - .get_type_from_selection_id( - cr, uid, arg[2]) + type_id, is_inverse = ( + relation_type_selection.browse(arg[2]) + .get_type_from_selection_id() + ) result = OR([ result, [ @@ -144,9 +145,9 @@ class ResPartner(models.Model): result = AND([result, [FALSE_LEAF]]) for relation_type_selection_id in relation_type_selection_ids: - type_id, is_inverse = relation_type_selection\ - .get_type_from_selection_id( - cr, uid, relation_type_selection_id) + type_id, is_inverse = ( + relation_type_selection_id.get_type_from_selection_id() + ) result = OR([ result, diff --git a/partner_relations/model/res_partner_relation.py b/partner_relations/model/res_partner_relation.py index 667e07e2c..6459b20ae 100644 --- a/partner_relations/model/res_partner_relation.py +++ b/partner_relations/model/res_partner_relation.py @@ -19,12 +19,13 @@ # along with this program. If not, see . # ############################################################################## -from openerp.osv.orm import Model, except_orm -from openerp.osv import fields -from openerp.tools.translate import _ +from openerp import osv, models, fields, api, exceptions, _ -class ResPartnerRelation(Model): +from . import get_partner_type + + +class ResPartnerRelation(models.Model): '''Model res.partner.relation is used to describe all links or relations between partners in the database. @@ -40,6 +41,27 @@ class ResPartnerRelation(Model): _description = 'Partner relation' _order = 'active desc, date_start desc, date_end desc' + left_contact_type = fields.Selection( + lambda s: s.env['res.partner.relation.type']._get_partner_types(), + 'Left Partner Type', + compute='_get_partner_type', + store=True, + ) + + right_contact_type = fields.Selection( + lambda s: s.env['res.partner.relation.type']._get_partner_types(), + 'Right Partner Type', + compute='_get_partner_type', + store=True, + ) + + @api.one + @api.depends('left_partner_id', 'right_partner_id') + def _get_partner_type(self): + + self.left_contact_type = get_partner_type(self.left_partner_id) + self.right_contact_type = get_partner_type(self.right_partner_id) + 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! @@ -49,28 +71,38 @@ class ResPartnerRelation(Model): 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''' + def _correct_vals(self, vals): + """Fill type and left and right partner id, according to whether + 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: - prts_model = self.pool['res.partner.relation.type.selection'] + prts_model = self.env['res.partner.relation.type.selection'] type_selection_id = vals['type_selection_id'] (type_id, is_reverse) = ( - prts_model.get_type_from_selection_id( - cr, uid, type_selection_id)) + prts_model.browse(type_selection_id). + get_type_from_selection_id() + ) vals['type_id'] = type_id - if context.get('active_id'): + if self._context.get('active_id'): if is_reverse: - vals['right_partner_id'] = context['active_id'] + vals['right_partner_id'] = self._context['active_id'] else: - vals['left_partner_id'] = context['active_id'] + vals['left_partner_id'] = self._context['active_id'] if vals.get('partner_id_display'): if is_reverse: vals['left_partner_id'] = vals['partner_id_display'] else: vals['right_partner_id'] = vals['partner_id_display'] + if vals.get('other_partner_id'): + if is_reverse: + vals['left_partner_id'] = vals['other_partner_id'] + else: + vals['right_partner_id'] = vals['other_partner_id'] + del vals['other_partner_id'] + if vals.get('contact_type'): + del vals['contact_type'] return vals def _get_computed_fields( @@ -90,12 +122,6 @@ class ResPartnerRelation(Model): if on_right_partner else self.right_partner_id.id ) - # is_relation_expired - today = fields.date.context_today(self, cr, uid, context=context) - values['is_relation_expired'] = ( - self.date_end and (self.date_end < today)) - # is_relation_future - values['is_relation_future'] = self.date_start > today return values return dict([ @@ -103,17 +129,17 @@ class ResPartnerRelation(Model): 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.''' - vals = self._correct_vals(cr, uid, vals, context=context) - return super(ResPartnerRelation, self).write( - cr, uid, ids, vals, context=context) + @api.multi + def write(self, vals): + """Override write to correct values, before being stored.""" + vals = self._correct_vals(vals) + return super(ResPartnerRelation, self).write(vals) - def create(self, cr, uid, vals, context=None): - '''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) + @api.model + def create(self, vals): + """Override create to correct values, before being stored.""" + vals = self._correct_vals(vals) + return super(ResPartnerRelation, self).create(vals) def on_change_type_selection_id( self, cr, uid, dummy_ids, type_selection_id, context=None): @@ -156,46 +182,32 @@ class ResPartnerRelation(Model): return result _columns = { - 'left_partner_id': fields.many2one( + 'left_partner_id': osv.fields.many2one( 'res.partner', string='Left partner', required=True, auto_join=True, ondelete='cascade'), - 'right_partner_id': fields.many2one( + 'right_partner_id': osv.fields.many2one( 'res.partner', string='Right partner', required=True, auto_join=True, ondelete='cascade'), - 'type_id': fields.many2one( + 'type_id': osv.fields.many2one( 'res.partner.relation.type', string='Type', required=True, auto_join=True), - 'date_start': fields.date('Starting date'), - 'date_end': fields.date('Ending date'), - 'type_selection_id': fields.function( + 'date_start': osv.fields.date('Starting date'), + 'date_end': osv.fields.date('Ending date'), + 'type_selection_id': osv.fields.function( _get_computed_fields, multi="computed_fields", fnct_inv=lambda *args: None, type='many2one', obj='res.partner.relation.type.selection', string='Type', ), - 'partner_id_display': fields.function( + 'partner_id_display': osv.fields.function( _get_computed_fields, multi="computed_fields", fnct_inv=lambda *args: None, type='many2one', obj='res.partner', string='Partner' ), - 'is_relation_expired': fields.function( - _get_computed_fields, - multi="computed_fields", - type='boolean', - method=True, - string='Relation is expired', - ), - 'is_relation_future': fields.function( - _get_computed_fields, - multi="computed_fields", - type='boolean', - method=True, - string='Relation is in the future', - ), - 'active': fields.boolean('Active'), + 'active': osv.fields.boolean('Active'), } _defaults = { @@ -247,7 +259,7 @@ class ResPartnerRelation(Model): ('id', '!=', this.id), ('left_partner_id', '=', this.left_partner_id.id), ('right_partner_id', '=', this.right_partner_id.id), - ] + ] if this.date_start: domain += ['|', ('date_end', '=', False), ('date_end', '>=', this.date_start)] @@ -255,8 +267,7 @@ class ResPartnerRelation(Model): domain += ['|', ('date_start', '=', False), ('date_start', '<=', this.date_end)] if self.search(cr, uid, domain, context=context): - raise except_orm( - _('Overlapping relation'), + raise exceptions.Warning( _('There is already a similar relation ' 'with overlapping dates')) diff --git a/partner_relations/model/res_partner_relation_all.py b/partner_relations/model/res_partner_relation_all.py index 2f3e71b9d..280749f3e 100644 --- a/partner_relations/model/res_partner_relation_all.py +++ b/partner_relations/model/res_partner_relation_all.py @@ -18,24 +18,26 @@ # along with this program. If not, see . # ############################################################################## -from openerp.osv.orm import Model -from openerp.osv import fields + +from openerp import osv, models, fields, api from openerp.tools import drop_view_if_exists -from .res_partner_relation_type_selection\ - import ResPartnerRelationTypeSelection +from .res_partner_relation_type_selection import \ + ResPartnerRelationTypeSelection +from . import get_partner_type, PADDING -class ResPartnerRelationAll(Model): +class ResPartnerRelationAll(models.AbstractModel): _auto = False _log_access = False _name = 'res.partner.relation.all' + _overlays = 'res.partner.relation' _description = 'All (non-inverse + inverse) relations between partners' _additional_view_fields = [] '''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: + Don't overwrite this list in your declaration but append in _auto_init: def _auto_init(self, cr, context=None): self._additional_view_fields.append('my_field') @@ -53,61 +55,82 @@ class ResPartnerRelationAll(Model): additional_view_fields = (',' + additional_view_fields)\ if additional_view_fields else '' cr.execute( - '''create or replace view %s as + '''create or replace view %(table)s as select - id * 10 as id, + id * %(padding)d as id, id as relation_id, type_id, cast('a' as char(1)) as record_type, + left_contact_type as contact_type, left_partner_id as this_partner_id, right_partner_id as other_partner_id, date_start, date_end, active, - type_id * 10 as type_selection_id - %s - from res_partner_relation + type_id * %(padding)d as type_selection_id + %(additional_view_fields)s + from %(underlying_table)s union select - id * 10 + 1, + id * %(padding)d + 1, id, type_id, cast('b' as char(1)), + right_contact_type, right_partner_id, left_partner_id, date_start, date_end, active, - type_id * 10 + 1 - %s - from res_partner_relation''' % ( - self._table, - additional_view_fields, - additional_view_fields, - ) + type_id * %(padding)d + 1 + %(additional_view_fields)s + from %(underlying_table)s''' % { + 'table': self._table, + 'padding': PADDING, + 'additional_view_fields': additional_view_fields, + 'underlying_table': 'res_partner_relation', + } ) return super(ResPartnerRelationAll, self)._auto_init( cr, context=context) + @api.one + def get_underlying_object(self): + """Get the record on which this record is overlaid""" + return self.env[self._overlays].browse(self.id / PADDING) + + contact_type = fields.Selection( + lambda s: s.env['res.partner.relation.type']._get_partner_types(), + 'Partner Type', + default=lambda self: self._get_default_contact_type() + ) + _columns = { - 'record_type': fields.selection( + 'record_type': osv.fields.selection( ResPartnerRelationTypeSelection._RECORD_TYPES, 'Record type', readonly=True), - 'relation_id': fields.many2one( + 'relation_id': osv.fields.many2one( 'res.partner.relation', 'Relation', readonly=True), - 'type_id': fields.many2one( + 'type_id': osv.fields.many2one( 'res.partner.relation.type', 'Relation type', readonly=True), - 'type_selection_id': fields.many2one( + 'type_selection_id': osv.fields.many2one( 'res.partner.relation.type.selection', 'Relation type', - readonly=True), - 'this_partner_id': fields.many2one( + ), + 'this_partner_id': osv.fields.many2one( 'res.partner', 'Current partner', readonly=True), - 'other_partner_id': fields.many2one( - 'res.partner', 'Other partner', readonly=True), - 'date_start': fields.date('Starting date'), - 'date_end': fields.date('Ending date'), - 'active': fields.boolean('Active'), + 'other_partner_id': osv.fields.many2one( + 'res.partner', 'Other partner'), + 'date_start': osv.fields.date('Starting date'), + 'date_end': osv.fields.date('Ending date'), } + active = fields.Boolean('Active', default=True) + + def _get_default_contact_type(self): + partner_id = self._context.get('default_this_partner_id') + if partner_id: + partner = self.env['res.partner'].browse(partner_id) + return get_partner_type(partner) + return False def name_get(self, cr, uid, ids, context=None): return dict([ @@ -118,12 +141,40 @@ 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''' - return self.pool['res.partner.relation'].write( - cr, uid, - [i / 10 for i in ids], - dict([(k, vals[k]) - for k in vals - if not self._columns[k].readonly]), - context=context) + @api.one + def write(self, vals): + """divert non-problematic writes to underlying table""" + underlying_objs = self.get_underlying_object() + vals = { + key: val + for key, val in vals.iteritems() + if not self._columns[key].readonly + } + vals['type_selection_id'] = vals.get( + 'type_selection_id', + underlying_objs.type_selection_id.id + ) + return underlying_objs.write(vals) + + @api.model + def create(self, vals): + """divert non-problematic creates to underlying table + + Create a res.partner.relation but return the converted id + """ + vals = { + key: val + for key, val in vals.iteritems() + if not self._columns[key].readonly + } + vals['type_selection_id'] = vals.get( + 'type_selection_id', + False, + ) + res = self.env[self._overlays].create(vals) + return self.browse(res.id * PADDING) + + @api.one + def unlink(self): + """divert non-problematic creates to underlying table""" + return self.get_underlying_object().unlink() diff --git a/partner_relations/model/res_partner_relation_type.py b/partner_relations/model/res_partner_relation_type.py index 6e19eb47e..c23e394af 100644 --- a/partner_relations/model/res_partner_relation_type.py +++ b/partner_relations/model/res_partner_relation_type.py @@ -19,18 +19,23 @@ # along with this program. If not, see . # ############################################################################## -from openerp.osv.orm import Model + from openerp.osv import fields +from openerp import models, api, _ -class ResPartnerRelationType(Model): - '''Model that defines relation types that might exist between partners''' +class ResPartnerRelationType(models.Model): + """Model that defines relation types that might exist between partners""" _name = 'res.partner.relation.type' - _description = 'Parter relation type' + _description = 'Partner Relation Type' _order = 'name' - def _get_partner_types(self, cr, uid, context=None): - return (('c', 'Company'), ('p', 'Person'),) + @api.model + def _get_partner_types(self): + return [ + ('c', _('Company')), + ('p', _('Person')), + ] _columns = { 'name': fields.char( diff --git a/partner_relations/model/res_partner_relation_type_selection.py b/partner_relations/model/res_partner_relation_type_selection.py index e691936cf..e8f8f0a48 100644 --- a/partner_relations/model/res_partner_relation_type_selection.py +++ b/partner_relations/model/res_partner_relation_type_selection.py @@ -27,11 +27,13 @@ ORDER BY ResPartnerRelationTypeSelection.customer_name asc, ResPartnerRelationTypeSelection.caller_name asc; ''' + +from openerp import api 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 +from . import PADDING class ResPartnerRelationTypeSelection(orm.Model): @@ -45,13 +47,14 @@ class ResPartnerRelationTypeSelection(orm.Model): _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 + @api.multi + def get_type_from_selection_id(self): + """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.''' - type_id = selection_id / 10 - is_reverse = (selection_id % 10) > 0 - return (type_id, is_reverse) + back the original type id, and about the record type.""" + type_id = self.id / PADDING + is_reverse = (self.id % PADDING) > 0 + return type_id, is_reverse def _auto_init(self, cr, context=None): drop_view_if_exists(cr, self._table) @@ -59,9 +62,9 @@ class ResPartnerRelationTypeSelection(orm.Model): # 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 %(table)s as select - id * 10 as id, + id * %(padding)d as id, id as type_id, cast('a' as char(1)) as record_type, name as name, @@ -69,9 +72,9 @@ class ResPartnerRelationTypeSelection(orm.Model): contact_type_right as contact_type_other, partner_category_left as partner_category_this, partner_category_right as partner_category_other - from res_partner_relation_type + from %(underlying_table)s union select - id * 10 + 1, + id * %(padding)d + 1, id, cast('b' as char(1)), name_inverse, @@ -79,7 +82,11 @@ class ResPartnerRelationTypeSelection(orm.Model): contact_type_left, partner_category_right, partner_category_left - from res_partner_relation_type''' % self._table) + from %(underlying_table)s''' % { + 'table': self._table, + 'padding': PADDING, + 'underlying_table': 'res_partner_relation_type', + }) return super(ResPartnerRelationTypeSelection, self)._auto_init( cr, context=context) @@ -161,8 +168,8 @@ class ResPartnerRelationTypeSelection(orm.Model): cr, uid, [ ('id', 'in', - map(lambda x: x * 10, relation_ids) + - map(lambda x: x * 10 + 1, inverse_relation_ids)), + map(lambda x: x * PADDING, relation_ids) + + map(lambda x: x * PADDING + 1, inverse_relation_ids)), ] + (args or []), context=context, limit=limit) return self.name_get(cr, uid, all_ids, context=context) diff --git a/partner_relations/view/res_partner.xml b/partner_relations/view/res_partner.xml index 4f777d6bd..d6446b0b4 100644 --- a/partner_relations/view/res_partner.xml +++ b/partner_relations/view/res_partner.xml @@ -34,7 +34,7 @@ 'active_ids': [id], 'active_test': False, }" - name="%(action_res_partner_relation)d" + name="%(action_res_partner_relation_all)d" icon="fa-users"> diff --git a/partner_relations/view/res_partner_relation.xml b/partner_relations/view/res_partner_relation.xml index 0366662be..bd5942b71 100644 --- a/partner_relations/view/res_partner_relation.xml +++ b/partner_relations/view/res_partner_relation.xml @@ -20,7 +20,7 @@ - - @@ -86,36 +78,5 @@ - - res.partner.relation - - - - - - - - - - - - - - - - Relations - res.partner.relation - form - tree - - - {"search_default_left_partner_id": active_id} - -

- Record and track your partners' relations. Relations may be linked to other partners with a type either directly or inversely. -

-
-
- diff --git a/partner_relations/view/res_partner_relation_all.xml b/partner_relations/view/res_partner_relation_all.xml index b05e28d42..ab336ab35 100644 --- a/partner_relations/view/res_partner_relation_all.xml +++ b/partner_relations/view/res_partner_relation_all.xml @@ -1,18 +1,42 @@ + res.partner.relation.all - - - - + + + + + + + res.partner.relation.all @@ -30,5 +54,36 @@ + + + res.partner.relation.all + + + + + + + + + + + + + + + Relations + res.partner.relation.all + form + tree + + + {"search_default_this_partner_id": active_id} + +

+ Record and track your partners' relations. Relations may be linked to other partners with a type either directly or inversely. +

+
+
+