~product-core-editors/openerp-product-attributes/github-6.1

« back to all changes in this revision

Viewing changes to production_lot_custom_attributes/lot.py

  • Committer: Yannick Vaucher
  • Author(s): unknown
  • Date: 2014-01-16 13:51:11 UTC
  • mfrom: (196.1.8)
  • Revision ID: git-v1:007dcee7b99e1a69ae204175c38da7d52d9cdee2
[MRG] [imp] search all attributes, both serialized and not

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.     #
22
22
#                                                                             #
23
23
###############################################################################
 
24
"""Production lot customization: custom attributes."""
24
25
 
25
26
from openerp.osv import fields, osv
26
27
from tools.translate import _
27
28
from lxml import etree
28
29
import re
 
30
import itertools
29
31
 
30
32
 
31
33
class stock_production_lot(osv.Model):
 
34
 
 
35
    """
 
36
    Add to the production lot custom attributes.
 
37
 
 
38
    This is done in a way similar to the custom attributes of the product.
 
39
 
 
40
    Additionally, we add a field to search in all attributes, stored or not,
 
41
    from the search view.
 
42
 
 
43
    """
 
44
 
32
45
    _inherit = "stock.production.lot"
33
46
 
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.
36
49
 
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.
40
53
 
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.
44
57
 
45
58
        """
46
59
 
47
 
        def expand_arg(arg):
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(
 
64
                cr, uid, [
 
65
                    ('name', '=', self._name),
 
66
                    ('serialized', '=', True),
 
67
                ], context=context)
50
68
 
51
 
            """
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.
 
72
            if ser_attributes:
53
73
                if arg[1] == 'like':
54
74
                    operator = '~'
55
75
                elif arg[1] == 'ilike':
64
84
                        select id
65
85
                        from {0}
66
86
                        where x_custom_json_attrs {1} %s;
67
 
                    """.format(
68
 
                        self._table,
69
 
                        operator
70
 
                    ),
71
 
                    (ur'.*: "[^"]*%s' % re.escape(arg[2]) ,)
 
87
                    """.format(self._table, operator),
 
88
                    (ur'.*: "[^"]*%s' % re.escape(arg[2]),)
72
89
                )
73
90
                sql_ids = [line[0] for line in cr.fetchall()]
74
 
                return ('id', 'in', sql_ids)
75
 
            else:
76
 
                return arg
77
 
 
78
 
        return [expand_arg(arg) for arg in args]
 
91
                return [('id', 'in', sql_ids)]
 
92
            else:
 
93
                return [('id', 'in', [])]
 
94
 
 
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'))
 
103
 
 
104
            attribute_pool = self.pool.get('attribute.attribute')
 
105
 
 
106
            field_ids = attribute_pool.search(cr, uid, [
 
107
                ('model_id.model', '=', self._name),
 
108
                ('serialized', '=', False),
 
109
                ('attribute_type', '=', 'char'),
 
110
            ], context=context)
 
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
 
114
 
 
115
        def expand(arg):
 
116
            """Expand each argument in a domain we can pass upstream"""
 
117
            if isinstance(arg, tuple) and arg[0] == name:
 
118
                return (
 
119
                    ['|'] +
 
120
                    expand_serialized(arg) +
 
121
                    expand_not_serialized(arg)
 
122
                )
 
123
            else:
 
124
                return [arg]
 
125
        return list(itertools.chain.from_iterable(expand(arg) for arg in args))
79
126
 
80
127
    _columns = {
81
128
        'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'),
94
141
    }
95
142
 
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.
 
145
 
 
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
107
156
        return result
108
157
 
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.
111
160
 
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.
148
197
            }
149
198
 
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'}
152
202
 
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.
156
206
 
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