Browse Source

[FIX] partner_multi_relation. Extendable but threadsafe.

pull/654/head
Ronald Portier 7 years ago
committed by Pedro M. Baeza
parent
commit
4de348d45d
  1. 108
      partner_multi_relation/models/res_partner_relation_all.py

108
partner_multi_relation/models/res_partner_relation_all.py

@ -1,7 +1,7 @@
# Copyright 2014-2017 Therp BV <http://therp.nl>
# -*- coding: utf-8 -*-
# Copyright 2014-2018 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# pylint: disable=method-required-super # pylint: disable=method-required-super
"""Abstract model to show each relation from two sides."""
import collections import collections
import logging import logging
@ -15,55 +15,8 @@ from openerp.tools import drop_view_if_exists
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
_last_key_offset = -1
_specification_register = collections.OrderedDict()
def register_select_specification(base_name, is_inverse, select_sql):
"""Register SELECT clause for rows to be included in view.
Each SELECT clause must contain a first column in the form:
'<base_keyfield> * %%(padding)s + %(key_offset),'
The %%(padding)s will be used as a parameter for the
cursor.execute function, the %(key_offset) will be replaced
by dictionary replacement.
The columns for each SELECT clause must be ordered as follows:
id - specified as defined above:
res_model: model._name of the underlying table,
res_id: base key in the underlying table,
this_partner_id: must refer to a partner
other_partner_id: must refer to a related partner
type_id: refers to res.partner.relation.type,
date_start: start date of relation if relevant or NULL,
date_end: end date of relation if relevant or NULL,
%(is_inverse)s as is_inverse: used to determine type_selection_id,
"""
global _last_key_offset
key_name = base_name + (is_inverse and '_inverse' or '')
assert key_name not in _specification_register
assert '%%(padding)s' in select_sql
assert '%(key_offset)s' in select_sql
assert '%(is_inverse)s' in select_sql
_last_key_offset += 1
_specification_register[key_name] = dict(
base_name=base_name,
is_inverse=is_inverse,
key_offset=_last_key_offset,
select_sql=select_sql % {
'key_offset': _last_key_offset,
'is_inverse': is_inverse})
def get_select_specification(base_name, is_inverse):
key_name = base_name + (is_inverse and '_inverse' or '')
return _specification_register[key_name]
# Register relations # Register relations
register_select_specification(
base_name='relation',
is_inverse=False,
select_sql="""\
RELATIONS_SQL = """\
SELECT SELECT
(rel.id * %%(padding)s) + %(key_offset)s AS id, (rel.id * %%(padding)s) + %(key_offset)s AS id,
'res.partner.relation' AS res_model, 'res.partner.relation' AS res_model,
@ -74,14 +27,10 @@ SELECT
rel.date_start, rel.date_start,
rel.date_end, rel.date_end,
%(is_inverse)s as is_inverse %(is_inverse)s as is_inverse
FROM res_partner_relation rel
""")
FROM res_partner_relation rel"""
# Register inverse relations # Register inverse relations
register_select_specification(
base_name='relation',
is_inverse=True,
select_sql="""\
RELATIONS_SQL_INVERSE = """\
SELECT SELECT
(rel.id * %%(padding)s) + %(key_offset)s AS id, (rel.id * %%(padding)s) + %(key_offset)s AS id,
'res.partner.relation', 'res.partner.relation',
@ -92,8 +41,7 @@ SELECT
rel.date_start, rel.date_start,
rel.date_end, rel.date_end,
%(is_inverse)s as is_inverse %(is_inverse)s as is_inverse
FROM res_partner_relation rel
""")
FROM res_partner_relation rel"""
class ResPartnerRelationAll(models.AbstractModel): class ResPartnerRelationAll(models.AbstractModel):
@ -148,20 +96,44 @@ class ResPartnerRelationAll(models.AbstractModel):
compute=lambda self: None, compute=lambda self: None,
search='_search_any_partner_id') search='_search_any_partner_id')
def _get_active_selects(self):
"""Return selects actually to be used.
def register_specification(
self, register, base_name, is_inverse, select_sql):
_last_key_offset = register['_lastkey']
key_name = base_name + (is_inverse and '_inverse' or '')
assert key_name not in register
assert '%%(padding)s' in select_sql
assert '%(key_offset)s' in select_sql
assert '%(is_inverse)s' in select_sql
_last_key_offset += 1
register['_lastkey'] = _last_key_offset
register[key_name] = dict(
base_name=base_name,
is_inverse=is_inverse,
key_offset=_last_key_offset,
select_sql=select_sql % {
'key_offset': _last_key_offset,
'is_inverse': is_inverse})
Selects are registered from all modules PRESENT. But should only be
used to build view if module actually INSTALLED.
"""
return ['relation', 'relation_inverse']
def get_register(self):
register = collections.OrderedDict()
register['_lastkey'] = -1
self.register_specification(
register, 'relation', False, RELATIONS_SQL)
self.register_specification(
register, 'relation', True, RELATIONS_SQL_INVERSE)
return register
def get_select_specification(self, base_name, is_inverse):
register = self.get_register()
key_name = base_name + (is_inverse and '_inverse' or '')
return register[key_name]
def _get_statement(self): def _get_statement(self):
"""Allow other modules to add to statement.""" """Allow other modules to add to statement."""
active_selects = self._get_active_selects()
register = self.get_register()
union_select = ' UNION '.join( union_select = ' UNION '.join(
[_specification_register[key]['select_sql']
for key in active_selects])
[register[key]['select_sql']
for key in register.iterkeys() if key != '_lastkey'])
return """\ return """\
CREATE OR REPLACE VIEW %%(table)s AS CREATE OR REPLACE VIEW %%(table)s AS
WITH base_selection AS (%(union_select)s) WITH base_selection AS (%(union_select)s)
@ -441,7 +413,7 @@ CREATE OR REPLACE VIEW %%(table)s AS
def _compute_id(self, base_resource, type_selection): def _compute_id(self, base_resource, type_selection):
"""Compute id. Allow for enhancements in inherit model.""" """Compute id. Allow for enhancements in inherit model."""
base_name = self._compute_base_name(type_selection) base_name = self._compute_base_name(type_selection)
key_offset = get_select_specification(
key_offset = self.get_select_specification(
base_name, type_selection.is_inverse)['key_offset'] base_name, type_selection.is_inverse)['key_offset']
return base_resource.id * self._get_padding() + key_offset return base_resource.id * self._get_padding() + key_offset

Loading…
Cancel
Save