Merge lp:~vauxoo/openobject-server/7.0_field_property_searcheable-dev-hbto into lp:openobject-server

Proposed by hbto [Vauxoo] http://www.vauxoo.com
Status: Needs review
Proposed branch: lp:~vauxoo/openobject-server/7.0_field_property_searcheable-dev-hbto
Merge into: lp:openobject-server
Diff against target: 174 lines (+150/-0) (has conflicts)
1 file modified
openerp/osv/fields.py (+150/-0)
Text conflict in openerp/osv/fields.py
To merge this branch: bzr merge lp:~vauxoo/openobject-server/7.0_field_property_searcheable-dev-hbto
Reviewer Review Type Date Requested Status
Odoo Administrators Pending
Nhomar - Vauxoo Pending
Moisés López - http://www.vauxoo.com Pending
Review via email: mp+193676@code.launchpad.net

Description of the change

This proposal tries to solve the problem that arise when trying to
look for property values on models that use them

When searching for property value all records are returned

To post a comment you must log in.

Unmerged revisions

5117. By hbto [Vauxoo] http://www.vauxoo.com

[IMP][osv][fields][property] When There is no Default Value and none record
has been set to a value, a search like [('property_field','=',False)] should
return the whole universe of values

5116. By hbto [Vauxoo] http://www.vauxoo.com

[FIX][osv][fields][property] Changed variable model in the search that
was giving wrong results, mea culpa.

Some improvements have been made to avoid unneed computes

5115. By hbto [Vauxoo] http://www.vauxoo.com

[IMP][osv][fields][property]
* Operator '!=' is working for m2o fields
This operator was obvious to add

Missing operators to develop 'Set' and 'not set'

5114. By hbto [Vauxoo] http://www.vauxoo.com

[IMP][osv][fields][property]
* Operator 'not like' is working for m2o fields
* Records that use Default values are now being taken into account (Ghost Records)

5113. By hbto [Vauxoo] http://www.vauxoo.com

[FIX] Getting rid of pdb

5112. By hbto [Vauxoo] http://www.vauxoo.com

[IMP][osv][fields]
search has been implemented for this property fields.

'char': 'value_text', #
'float': 'value_float', #
'boolean' : 'value_integer', #
'integer': 'value_integer', #
'text': 'value_text', #
'many2one': 'value_reference', #
'date' : 'value_datetime', #
'datetime' : 'value_datetime', #

5111. By hbto [Vauxoo] http://www.vauxoo.com

[IMP][fields][property] We are in the process of converting the whole
property fields from non-searchable by default to searchable by default
It is not going to be easy

It could that we have to manage with a subset of features and not all the
features available as there are for the non-functional fields

As of now, only property many2one fields are searchable, with
operator ['ilike', 'in', '=']

Default values for the property fields are not taken into account

So now it is just working for those property values that are really belonging to
the records they have been assigned.

CAUTION: With this DIFF all your Property fields will become searchable, It means
that you will be able to pick them from Advance Search, Though it does not mean
that your search it's gonna work!!!

This webservice can be usefull to make a Proof of Concept about the
workability of this DIFF

Create a DB, name it 'property', set data demo to True
Copy & Paste the code below,
Change some of the accounts of your partners to an account
different than the one as Default e.g. 'Creditors (test)' or 'Debitors (test)'
run your new webservice.

I Works!!!.

=========================================================================

#!/usr/bin/python
import oerplib
DB = 'property'
oerp = oerplib.OERP(server='localhost',database=DB,port=8069,timeout=4000)
USERS = ['admin']
PSSWS = {}.fromkeys(USERS,'admin')

for USER in USERS:
    oerp.login(user=USER, passwd=PSSWS[USER], database=DB)
    am_ids = oerp.search('res.partner',[
                           '|',
                           ('property_account_payable.type','=','payable'),
                           ('property_account_receivable.type','=','receivable'),
                           ])
    print 'AM IDS ',am_ids

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openerp/osv/fields.py'
2--- openerp/osv/fields.py 2013-10-30 10:23:13 +0000
3+++ openerp/osv/fields.py 2013-11-02 01:59:41 +0000
4@@ -51,6 +51,9 @@
5 import simplejson
6 from openerp import SUPERUSER_ID
7
8+TERM_OPERATORS = ('=', '!=', '<=', '<', '>', '>=', '=?', '=like', '=ilike',
9+ 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in',
10+ 'child_of')
11 _logger = logging.getLogger(__name__)
12
13 def _symbol_set(symb):
14@@ -1517,13 +1520,160 @@
15 self.field_id[cr.dbname] = res and res[0]
16 return self.field_id[cr.dbname]
17
18+<<<<<<< TREE
19
20 def __init__(self, **args):
21+=======
22+ def _fnct_search(self, tobj, cr, uid, obj, prop_name, args, context=None):
23+ context = context or {}
24+ prop = obj.pool.get('ir.property')
25+ # get the default values (for res_id = False) for the property fields
26+ default_val = self._get_default(obj, cr, uid, prop_name, context)
27+
28+ res = []
29+
30+ property_field = obj._all_columns.get(prop_name).column
31+ def_id = self._field_get(cr, uid, obj._name, prop_name)
32+ company = obj.pool.get('res.company')
33+ cid = company._company_default_get(cr, uid, obj._name, def_id,
34+ context=context)
35+ propdef = obj.pool.get('ir.model.fields').browse(cr, uid, def_id,
36+ context=context)
37+ from_clause = 'ir_property'
38+ where = " WHERE " + \
39+ "name = '%s' AND "% propdef.name + \
40+ "res_id like '%s,%%' AND "% obj._name + \
41+ "company_id = %s AND "% cid + \
42+ "fields_id = %s AND "% def_id + \
43+ "type = '%s'"% self._type
44+
45+ model_ids = []
46+
47+ type2field = {
48+ 'char': 'value_text', #
49+ 'float': 'value_float', #
50+ 'boolean' : 'value_integer', #
51+ 'integer': 'value_integer', #
52+ 'text': 'value_text', #
53+ 'binary': 'value_binary',
54+ 'many2one': 'value_reference', #
55+ 'date' : 'value_datetime', #
56+ 'datetime' : 'value_datetime', #
57+ }
58+ ghost = False
59+ where_str = ''
60+
61+ if property_field._type == 'many2one':
62+ model_obj = obj.pool.get(property_field._obj)
63+ left, operator, right = args[0]
64+ args1 = []
65+ if operator == '!=' and right == False:
66+ args1= [(1,'=',1)]
67+ elif operator == '=' and right == False and not default_val:
68+ ghost = True
69+ elif operator in ('ilike','not ilike','=','!='):
70+ args1= [(model_obj._rec_name,operator,right)]
71+ elif operator == 'in':
72+ args1= [('id',operator,right)]
73+ #/!\ By doing this I am forgetting the possible ghosts that could match
74+ model_ids = args1 and model_obj.search(cr,uid,args1,context=context) or []
75+ if model_ids:
76+ ghost = True if default_val and default_val.id in model_ids else False
77+ #/!\ This awful query has to be got rid, a better query should arise
78+ model_ids = map(lambda x:"'%s,%s'"%(model_obj._name,x),model_ids)
79+ model_ids = ",".join(model_ids)
80+ where_str += ' AND value_reference IN (%s)'%model_ids
81+ else:
82+ #/!\ Do not return anything in case that no arguments are passed
83+ #return [('id', '=', 0)]
84+ pass
85+
86+ elif property_field._type in ('date','datetime'):
87+ left, operator, right = args[0]
88+ args1 = []
89+ type_right = (type2field.get(property_field._type),right)
90+ if operator in ('=','!=','<=','<','>','>=','=?'):
91+ where_str += " AND %s = '%s'"%type_right%operator
92+ elif operator in ('=like' '=ilike', 'like', 'not like', 'ilike', 'not ilike'):
93+ #TODO: NotImplementedYet
94+ pass
95+ elif operator in ('in', 'not in', 'child_of'):
96+ #TODO: NotImplementedYet
97+ pass
98+
99+ elif property_field._type in ('float', 'boolean', 'integer'):
100+ left, operator, right = args[0]
101+ args1 = []
102+ type_right = (type2field.get(property_field._type),right)
103+ if operator in ('=','!=','<=','<','>','>=','=?'):
104+ where_str += " AND %s %%s %d"%type_right%operator
105+ elif operator in ('=like' '=ilike', 'like', 'not like', 'ilike', 'not ilike'):
106+ #TODO: NotImplementedYet
107+ pass
108+ elif operator in ('in', 'not in', 'child_of'):
109+ #TODO: NotImplementedYet
110+ pass
111+ elif property_field._type in ('char', 'text'):
112+ left, operator, right = args[0]
113+ args1 = []
114+ type_right = (type2field.get(property_field._type),right)
115+ if operator in ('=','!=','<=','<','>','>=','=?'):
116+ where_str += " AND %s = '%s'"%type_right%operator
117+ elif operator == '=like':
118+ where_str += " AND %s =like '%s%%'"%type_right
119+ elif operator == '=ilike':
120+ where_str += " AND %s =ilike '%s%%'"%type_right
121+ elif operator == 'like':
122+ where_str += " AND %s like '%s'"%type_right
123+ elif operator == 'not like':
124+ where_str += " AND %s not like '%s'"%type_right
125+ elif operator == 'ilike':
126+ where_str += " AND %s ilike '%s'"%type_right
127+ elif operator == 'not ilike':
128+ where_str += " AND %s not ilike '%s'"%type_right
129+ elif operator in ('in', 'not in', 'child_of'):
130+ #TODO: NotImplementedYet
131+ pass
132+ ghost_ids = []
133+ if ghost:
134+ # These are all the records from obj which actually have prop_name
135+ # set as a real property_field, the other records of obj just have
136+ # a 'ghost'
137+ query = "SELECT res_id FROM %s"%from_clause + where
138+ cr.execute(query)
139+ res = cr.fetchall()
140+ res = set(res)
141+ res = map(lambda x: int(x[1]), [x[0].split(',') for x in res])
142+
143+ #This ones are the ghosts
144+ ghost_ids = obj.search(cr,uid,[('id','not in',res)],context=context)
145+
146+ res = []
147+ if where_str:
148+ query = "SELECT res_id FROM %s"%from_clause + where + where_str
149+ cr.execute(query)
150+ res = cr.fetchall()
151+ res = set(res)
152+ res = map(lambda x: int(x[1]), [x[0].split(',') for x in res])
153+
154+ res += ghost_ids
155+ if not res:
156+ return [('id', '=', 0)]
157+ return [('id', 'in', res)]
158+
159+ def __init__(self, obj_prop, **args):
160+ # TODO remove obj_prop parameter (use many2one type)
161+>>>>>>> MERGE-SOURCE
162 self.field_id = {}
163+<<<<<<< TREE
164 if 'view_load' in args:
165 _logger.warning("view_load attribute is deprecated on ir.fields. Args: %r", args)
166 obj = 'relation' in args and args['relation'] or ''
167 function.__init__(self, self._fnct_read, False, self._fnct_write, obj=obj, multi='properties', **args)
168+=======
169+ function.__init__(self, self._fnct_read, False, self._fnct_write,
170+ obj_prop, multi='properties',fnct_search=self._fnct_search, **args)
171+>>>>>>> MERGE-SOURCE
172
173 def restart(self):
174 self.field_id = {}