21
21
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
23
23
###############################################################################
24
"""Production lot customization: custom attributes."""
25
26
from openerp.osv import fields, osv
26
27
from tools.translate import _
27
28
from lxml import etree
31
33
class stock_production_lot(osv.Model):
36
Add to the production lot custom attributes.
38
This is done in a way similar to the custom attributes of the product.
40
Additionally, we add a field to search in all attributes, stored or not,
32
45
_inherit = "stock.production.lot"
34
47
def _search_all_attributes(self, cr, uid, obj, name, args, context):
35
"""Search in all serialized attributes
48
"""Search in all serialized attributes. Return domain.
37
50
Receives a domain in args, and expands all relevant terms into ids
38
51
to search into all attributes. The ORM will take care of security
39
52
afterwards, so it' OK to use SQL here.
41
In the future, we could consider storing attributes as native PostgreSQL
42
hstore or JSON instead of strings, and substitute this rough regexp
43
search with native PostgreSQL goodness.
54
In the future, we could consider storing attributes as native
55
PostgreSQL hstore or JSON instead of strings, and substitute this rough
56
regexp search with native PostgreSQL goodness.
48
"""Takes a single argument of the domain, and when possible expands
49
it to a trivial domain ('in', 'in', list)
60
def expand_serialized(arg):
61
"""Expand the args in a trivial domain ('id', 'in', ids)"""
62
attribute_pool = self.pool.get('attribute.attribute')
63
ser_attributes = attribute_pool.search(
65
('name', '=', self._name),
66
('serialized', '=', True),
52
if isinstance(arg, tuple) and arg[0] == name:
69
# we need this check, otherwise the column x_custom_json_attrs
70
# does not exist in the database. Because of transactions, we
71
# cannot try-pass errors on the database.
53
73
if arg[1] == 'like':
55
75
elif arg[1] == 'ilike':
66
86
where x_custom_json_attrs {1} %s;
71
(ur'.*: "[^"]*%s' % re.escape(arg[2]) ,)
87
""".format(self._table, operator),
88
(ur'.*: "[^"]*%s' % re.escape(arg[2]),)
73
90
sql_ids = [line[0] for line in cr.fetchall()]
74
return ('id', 'in', sql_ids)
78
return [expand_arg(arg) for arg in args]
91
return [('id', 'in', sql_ids)]
93
return [('id', 'in', [])]
95
def expand_not_serialized(arg):
96
"""Expand the args in a domain like
97
['|', ('real_field_1', operator, string),
98
('real_field_2', operator, string)"""
99
if arg[1] not in ('like', 'ilike'):
100
raise osv.except_osv(
101
_('Not Implemented!'),
102
_('Search not supported for this field'))
104
attribute_pool = self.pool.get('attribute.attribute')
106
field_ids = attribute_pool.search(cr, uid, [
107
('model_id.model', '=', self._name),
108
('serialized', '=', False),
109
('attribute_type', '=', 'char'),
111
fields = attribute_pool.browse(cr, uid, field_ids, context=context)
112
terms = [(f.name, arg[1], arg[2]) for f in fields]
113
return ['|'] * (len(terms) - 1) + terms
116
"""Expand each argument in a domain we can pass upstream"""
117
if isinstance(arg, tuple) and arg[0] == name:
120
expand_serialized(arg) +
121
expand_not_serialized(arg)
125
return list(itertools.chain.from_iterable(expand(arg) for arg in args))
81
128
'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'),
96
143
def _fix_size_bug(self, cr, uid, result, context=None):
97
"""When created a field text dynamicaly, its size is limited to 64 in
144
"""Workaround for the size of text fields. Return fixed fields.
146
When created a field text dinamically, its size is limited to 64 in
98
147
the view. The bug is fixed but not merged
99
148
https://code.launchpad.net/~openerp-dev/openerp-web/6.1-opw-579462-cpa
100
149
To remove when the fix will be merged
109
158
def open_attributes(self, cr, uid, ids, context=None):
110
"""Open the attributes of an object
159
"""Open the attributes of an object. Return action.
112
161
This method is called when the user presses the Open Attributes button
113
162
in the form view of the object. It opens a dinamically-built form view.
150
199
def save_and_close_lot_attributes(self, cr, uid, ids, context=None):
200
"""Button to save and close. Return action."""
151
201
return {'type': 'ir.actions.act_window_close'}
153
203
def fields_view_get(self, cr, uid, view_id=None, view_type='form',
154
204
context=None, toolbar=False, submenu=False):
155
"""Dinamically adds attributes to the view
205
"""Dinamically add attributes to the view. Return field_view_get.
157
207
Modifies dinamically the view to show the attributes. If the users
158
208
presses the Open Attributes button, the attributes are shown in a