~unifield-team/unifield-wm/us-826

« back to all changes in this revision

Viewing changes to consumption_calculation/history_consumption.py

  • Committer: Olivier DOSSMANN
  • Date: 2014-03-31 09:31:46 UTC
  • mto: This revision was merged to the branch mainline in revision 2086.
  • Revision ID: od@tempo-consulting.fr-20140331093146-tgvxnly1kc1hbv1s
UF-2171 [ADD] Analytic distribution reset button for recurring models

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
from osv import fields
24
24
from mx.DateTime import *
25
25
from lxml import etree
 
26
from tools.translate import _
26
27
 
27
28
import time
28
29
 
 
30
HIST_STATUS = [('draft', 'Draft'), ('in_progress', 'In Progress'), ('ready', 'Ready')]
29
31
 
30
 
class product_history_consumption(osv.osv_memory):
 
32
class product_history_consumption(osv.osv):
31
33
    _name = 'product.history.consumption'
 
34
    _rec_name = 'location_id'
 
35
 
 
36
    def _get_status(self, cr, uid, ids, field_name, args, context=None):
 
37
        '''
 
38
        Return the same status as status
 
39
        '''
 
40
        res = {}
 
41
 
 
42
        for obj in self.browse(cr, uid, ids, context=context):
 
43
            res[obj.id] = obj.status
 
44
 
 
45
        return res
32
46
 
33
47
    _columns = {
34
 
        'date_from': fields.date(string='From date', required=True),
35
 
        'date_to': fields.date(string='To date', required=True),
 
48
        'date_from': fields.date(string='From date'),
 
49
        'date_to': fields.date(string='To date'),
36
50
        'month_ids': fields.one2many('product.history.consumption.month', 'history_id', string='Months'),
37
51
        'consumption_type': fields.selection([('rac', 'Real Average Consumption'), ('amc', 'Average Monthly Consumption')],
38
 
                                             string='Consumption type', required=True),
 
52
                                             string='Consumption type'),
39
53
        'location_id': fields.many2one('stock.location', string='Location', domain="[('usage', '=', 'internal')]"),
40
54
        'sublist_id': fields.many2one('product.list', string='List/Sublist'),
41
55
        'nomen_id': fields.many2one('product.nomenclature', string='Products\' nomenclature level'),
 
56
        'nomen_manda_0': fields.many2one('product.nomenclature', 'Main Type'),
 
57
        'nomen_manda_1': fields.many2one('product.nomenclature', 'Group'),
 
58
        'nomen_manda_2': fields.many2one('product.nomenclature', 'Family'),
 
59
        'nomen_manda_3': fields.many2one('product.nomenclature', 'Root'),
 
60
        'requestor_id': fields.many2one('res.users', string='Requestor'),
 
61
        'requestor_date': fields.datetime(string='Date of the demand'),
 
62
        'fake_status': fields.function(_get_status, method=True, type='selection', selection=HIST_STATUS, readonly=True, string='Status'),
 
63
        'status': fields.selection(HIST_STATUS, string='Status'),
42
64
    }
43
65
 
44
66
    _defaults = {
45
 
        'date_to': lambda *a: time.strftime('%Y-%m-%d'),
 
67
        'date_to': lambda *a: (DateFrom(time.strftime('%Y-%m-%d')) + RelativeDateTime(months=1, day=1, days=-1)).strftime('%Y-%m-%d'),
 
68
        'requestor_id': lambda obj, cr, uid, c: uid,
 
69
        'requestor_date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
 
70
        'status': 'draft',
46
71
    }
47
72
 
48
 
    def open_history_consumption(self, cr, uid, ids, context={}):
 
73
    def open_history_consumption(self, cr, uid, ids, context=None):
49
74
        if not context:
50
75
            context = {}
51
76
        new_id = self.create(cr, uid, {}, context=context)
52
77
        return {'type': 'ir.actions.act_window',
53
78
                'res_model': 'product.history.consumption',
54
79
                'res_id': new_id,
55
 
                'context': {'active_id': new_id, 'active_ids': [new_id]},
 
80
                'context': {'active_id': new_id, 'active_ids': [new_id], 'withnum': 1},
56
81
                'view_type': 'form',
57
82
                'view_mode': 'form',
58
83
                'target': 'dummy'}
59
84
 
60
 
    def date_change(self, cr, uid, ids, date_from, date_to, context={}):
 
85
    def date_change(self, cr, uid, ids, date_from, date_to, context=None):
61
86
        '''
62
87
        Add the list of months in the defined period
63
88
        '''
64
89
        if not context:
65
90
            context = {}
66
 
        res = {}
 
91
        res = {'value': {}}
67
92
        month_obj = self.pool.get('product.history.consumption.month')
 
93
        
 
94
        if date_from:
 
95
            date_from = (DateFrom(date_from) + RelativeDateTime(day=1)).strftime('%Y-%m-%d')
 
96
            res['value'].update({'date_from': date_from})
 
97
        if date_to:
 
98
            date_to = (DateFrom(date_to) + RelativeDateTime(months=1, day=1, days=-1)).strftime('%Y-%m-%d')
 
99
            res['value'].update({'date_to': date_to})
68
100
 
69
101
        # If a period is defined
70
102
        if date_from and date_to:
71
 
            res['value'] = {'month_ids': []}
 
103
            res['value'].update({'month_ids': []})
72
104
            current_date = DateFrom(date_from) + RelativeDateTime(day=1)
 
105
            if current_date > (DateFrom(date_to) + RelativeDateTime(months=1, day=1, days=-1)):
 
106
                return {'warning': {'title': _('Error'),
 
107
                                    'message':  _('The \'To Date\' should be greater than \'From Date\'')}}
73
108
            # For all months in the period
74
109
            while current_date <= (DateFrom(date_to) + RelativeDateTime(months=1, day=1, days=-1)):
75
110
                search_ids = month_obj.search(cr, uid, [('name', '=', current_date.strftime('%m/%Y')), ('history_id', 'in', ids)], context=context)
76
111
                # If the month is in the period and not in the list, create it
77
112
                if not search_ids:
78
 
                    month_id = month_obj.create(cr, uid, {'name': current_date.strftime('%m/%Y'),
79
 
                                                          'date_from': current_date.strftime('%Y-%m-%d'),
80
 
                                                          'date_to': (current_date + RelativeDateTime(months=1, day=1, days=-1)).strftime('%Y-%m-%d'),
81
 
                                                          'history_id': ids[0]})
82
 
                    res['value']['month_ids'].append(month_id)
 
113
#                    month_id = month_obj.create(cr, uid, {'name': current_date.strftime('%m/%Y'),
 
114
#                                                          'date_from': current_date.strftime('%Y-%m-%d'),
 
115
#                                                          'date_to': (current_date + RelativeDateTime(months=1, day=1, days=-1)).strftime('%Y-%m-%d'),
 
116
#                                                          'history_id': ids[0]}, context=context)
 
117
#                    res['value']['month_ids'].append(month_id)
 
118
                    res['value']['month_ids'].append({'name': current_date.strftime('%m/%Y'),
 
119
                                                      'date_from': current_date.strftime('%Y-%m-%d'),
 
120
                                                      'date_to': (current_date + RelativeDateTime(months=1, day=1, days=-1)).strftime('%Y-%m-%d')})
83
121
                else:
84
122
                    res['value']['month_ids'].extend(search_ids)
85
123
                current_date = current_date + RelativeDateTime(months=1)
86
124
        else:
87
 
            res['value'] = {'month_ids': [False]}
 
125
            res['value'] = {'month_ids': []}
88
126
 
89
127
        # Delete all months out of the period
90
128
        del_months = []
97
135
        return res
98
136
 
99
137
 
100
 
    def create_lines(self, cr, uid, ids, context={}):
 
138
    def get_data(self, cr, uid, ids, context=None):
101
139
        '''
102
 
        Create one line by product for the period
 
140
        Get parameters of the report
103
141
        '''
104
142
        if not context:
105
143
            context = {}
119
157
        nb_months = len(months)
120
158
        total_consumption = {}
121
159
 
122
 
        if obj.nomen_id:
123
 
            nomen_id = obj.nomen_id.id
124
 
            nomen = self.pool.get('product.nomenclature').browse(cr, uid, nomen_id, context=context)
125
 
            if nomen.type == 'mandatory':
126
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_manda_0', '=', nomen_id)], context=context))
127
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_manda_1', '=', nomen_id)], context=context))
128
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_manda_2', '=', nomen_id)], context=context))
129
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_manda_3', '=', nomen_id)], context=context))
130
 
                # Prefill the search view
131
 
                tmp_nomen = [nomen]
132
 
                while nomen.parent_id:
133
 
                    tmp_nomen.append(nomen.parent_id.id)
134
 
                    nomen = nomen.parent_id
135
 
 
136
 
                tmp_nomen.reverse()
137
 
 
138
 
                i = 0
139
 
                while i < len(tmp_nomen):
140
 
                    context.update({'search_default_nomen_manda_%s' %i: obj.sublist_id.id})
141
 
                    i += 1
142
 
            else:
143
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_sub_0', '=', nomen_id)], context=context))
144
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_sub_1', '=', nomen_id)], context=context))
145
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_sub_2', '=', nomen_id)], context=context))
146
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_sub_3', '=', nomen_id)], context=context))
147
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_sub_4', '=', nomen_id)], context=context))
148
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [('nomen_sub_5', '=', nomen_id)], context=context))
149
 
                # Prefill the search view
150
 
                tmp_nomen = [nomen]
151
 
                while nomen.parent_id:
152
 
                    tmp_nomen.append(nomen.parent_id.id)
153
 
                    nomen = nomen.parent_id
154
 
 
155
 
                tmp_nomen.reverse()
156
 
 
157
 
                i = 0
158
 
                while i < len(tmp_nomen):
159
 
                    if i > 3:
160
 
                        context.update({'search_default_nomen_sub_%s' % i-3: obj.sublist_id.id})
161
 
                    else:
162
 
                        context.update({'search_default_nomen_manda_%s' % i: obj.sublist_id.id})
163
 
                    i += 1
 
160
        if not months:
 
161
            raise osv.except_osv(_('Error'), _('You have to choose at least one month for consumption history'))
 
162
 
 
163
        if obj.nomen_manda_0:
 
164
            for report in self.browse(cr, uid, ids, context=context):
 
165
                product_ids = []
 
166
                products = []
 
167
    
 
168
                nom = False
 
169
                # Get all products for the defined nomenclature
 
170
                if report.nomen_manda_3:
 
171
                    nom = report.nomen_manda_3.id
 
172
                    field = 'nomen_manda_3'
 
173
                elif report.nomen_manda_2:
 
174
                    nom = report.nomen_manda_2.id
 
175
                    field = 'nomen_manda_2'
 
176
                elif report.nomen_manda_1:
 
177
                    nom = report.nomen_manda_1.id
 
178
                    field = 'nomen_manda_1'
 
179
                elif report.nomen_manda_0:
 
180
                    nom = report.nomen_manda_0.id
 
181
                    field = 'nomen_manda_0'
 
182
                if nom:
 
183
                    product_ids.extend(self.pool.get('product.product').search(cr, uid, [(field, '=', nom)], context=context))
 
184
                    
 
185
            for product in self.pool.get('product.product').browse(cr, uid, product_ids, context=context):
 
186
                # Check if the product is not already on the report
 
187
                if product.id not in products:
 
188
                    batch_mandatory = product.batch_management or product.perishable
 
189
                    date_mandatory = not product.batch_management and product.perishable
164
190
 
165
191
        if obj.sublist_id:
166
192
            context.update({'search_default_list_ids': obj.sublist_id.id})
169
195
 
170
196
        domain = [('id', 'in', product_ids)]
171
197
 
172
 
        if not obj.nomen_id and not obj.sublist_id:
 
198
        if not obj.nomen_manda_0 and not obj.sublist_id:
173
199
            domain = []
174
200
 
175
201
        new_context = context.copy()
176
 
        new_context.update({'months': [], 'amc': obj.consumption_type == 'amc' and 'AMC' or 'RAC', 'obj_id': obj.id, 'history_cons': True})
 
202
        new_context.update({'months': [], 'amc': obj.consumption_type == 'amc' and 'AMC' or 'RAC', 'obj_id': obj.id, 'history_cons': True, 'need_thread': True})
177
203
 
178
204
        # For each month, compute the RAC
179
205
        for month in self.pool.get('product.history.consumption.month').browse(cr, uid, months, context=context):
180
206
            new_context['months'].append({'date_from': month.date_from, 'date_to': month.date_to})
181
207
 
182
208
 
 
209
        return product_ids, domain, new_context
 
210
 
 
211
    def create_lines(self, cr, uid, ids, context=None):
 
212
        '''
 
213
        Create one line by product for the period
 
214
        '''
 
215
        if not context:
 
216
            context = {}
 
217
 
 
218
        product_ids, domain, new_context = self.get_data(cr, uid, ids, context=context)
 
219
 
 
220
        if not product_ids:
 
221
            product_ids = self.pool.get('product.product').search(cr, uid, [], context=new_context)
 
222
 
 
223
        import threading
 
224
        self.write(cr, uid, ids, {'status': 'in_progress'}, context=context)
 
225
        cr.commit()
 
226
        new_thread = threading.Thread(target=self._create_lines, args=(cr, uid, ids, product_ids, new_context))
 
227
        new_thread.start()
 
228
        new_thread.join(10.0)
 
229
        if new_thread.isAlive():
 
230
            view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'consumption_calculation', 'history_consumption_waiting_view')[1]
 
231
            return {'type': 'ir.actions.act_window',
 
232
                    'res_model': 'product.history.consumption',
 
233
                    'view_type': 'form',
 
234
                    'view_mode': 'form',
 
235
                    'res_id': ids[0],
 
236
                    'view_id': [view_id],
 
237
                    'context': new_context,
 
238
                    'target': 'same'}
 
239
 
 
240
        return self.open_report(cr, uid, ids, context=new_context)
 
241
 
 
242
    def _create_lines(self, cr, uid, ids, product_ids, context=None):
 
243
        '''
 
244
        Create lines in background
 
245
        '''
 
246
        import pooler
 
247
        new_cr = pooler.get_db(cr.dbname).cursor()
 
248
 
 
249
        # split ids into slices to not read a lot record in the same time (memory)
 
250
        ids_len = len(product_ids)
 
251
        slice_len = 500
 
252
        if ids_len > slice_len:
 
253
            slice_count = ids_len / slice_len
 
254
            if ids_len % slice_len:
 
255
                slice_count = slice_count + 1
 
256
            # http://www.garyrobinson.net/2008/04/splitting-a-pyt.html
 
257
            slices = [product_ids[i::slice_count] for i in range(slice_count)]
 
258
        else:
 
259
            slices = [product_ids]
 
260
 
 
261
        for slice_ids in slices:
 
262
            try:
 
263
                self.pool.get('product.product').read(new_cr, uid, slice_ids, ['average'], context=context)
 
264
            except Exception, e:
 
265
                new_cr.rollback()
 
266
        self.write(new_cr, uid, ids, {'status': 'ready'}, context=context)
 
267
 
 
268
        new_cr.commit()
 
269
        new_cr.close()
 
270
 
 
271
        return
 
272
 
 
273
    def open_report(self, cr, uid, ids, context=None):
 
274
        '''
 
275
        Open the report
 
276
        '''
 
277
        if context is None:
 
278
            context = {}
 
279
 
 
280
        product_ids, domain, new_context = self.get_data(cr, uid, ids, context=context)
 
281
        if new_context is None:
 
282
            new_context = {}
 
283
        new_context['search_default_average'] = 1  # UTP-501 positive Av.AMC/Av.RAC filter set to on by default
 
284
 
183
285
        return {'type': 'ir.actions.act_window',
184
286
                'res_model': 'product.product',
185
287
                'domain': domain,
188
290
                'context': new_context,
189
291
                'target': 'dummy'}
190
292
 
 
293
    def unlink(self, cr, uid, ids, context=None):
 
294
        '''
 
295
        Remove the data saved in DB
 
296
        '''
 
297
        hist_obj = self.pool.get('product.history.consumption.product')
 
298
        for cons in self.browse(cr, uid, ids, context=context):
 
299
            hist_ids = hist_obj.search(cr, uid, [('consumption_id', '=', cons.id)], context=context)
 
300
            hist_obj.unlink(cr, uid, hist_ids, context=context)
 
301
        return super(product_history_consumption, self).unlink(cr, uid, ids, context=context)
 
302
 
 
303
    def in_progress(self, cr, uid, ids, context=None):
 
304
        '''
 
305
        Return dummy
 
306
        '''
 
307
        return self.go_to_list(cr, uid, ids, context=context)
 
308
 
 
309
    def go_to_list(self, cr, uid, ids, context=None):
 
310
        '''
 
311
        Returns to the list of reports
 
312
        '''
 
313
        return {'type': 'ir.actions.act_window',
 
314
                'res_model': 'product.history.consumption',
 
315
                'view_mode': 'tree,form',
 
316
                'view_type': 'form',
 
317
                'target': 'dummy',
 
318
                'context': context}
 
319
 
 
320
##############################################################################################################################
 
321
# The code below aims to enable filtering products regarding their nomenclature.
 
322
# NB: the difference with the other same kind of product filters (with nomenclature and sublist) is that here we are dealing with osv_memory
 
323
##############################################################################################################################
 
324
    def onChangeSearchNomenclature(self, cr, uid, id, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, num=True, context=None):
 
325
        res = self.pool.get('product.product').onChangeSearchNomenclature(cr, uid, 0, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, False, context={'withnum': 1})
 
326
        return res
 
327
 
 
328
    def get_nomen(self, cr, uid, id, field):
 
329
        return self.pool.get('product.nomenclature').get_nomen(cr, uid, self, id, field, context={'withnum': 1})
 
330
 
 
331
    def write(self, cr, uid, ids, vals, context=None):
 
332
        if vals.get('sublist_id',False):
 
333
            vals.update({'nomen_manda_0':False,'nomen_manda_1':False,'nomen_manda_2':False,'nomen_manda_3':False})
 
334
        if vals.get('nomen_manda_0',False):
 
335
            vals.update({'sublist_id':False})
 
336
        if vals.get('nomen_manda_1',False):
 
337
            vals.update({'sublist_id':False})
 
338
        ret = super(product_history_consumption, self).write(cr, uid, ids, vals, context=context)
 
339
        return ret
 
340
##############################################################################
 
341
# END of the definition of the product filters and nomenclatures
 
342
##############################################################################
 
343
 
191
344
product_history_consumption()
192
345
 
193
 
 
194
 
class product_history_consumption_month(osv.osv_memory):
 
346
class product_history_consumption_month(osv.osv):
195
347
    _name = 'product.history.consumption.month'
196
348
    _order = 'name, date_from, date_to'
197
349
 
199
351
        'name': fields.char(size=64, string='Month'),
200
352
        'date_from': fields.date(string='Date from'),
201
353
        'date_to': fields.date(string='Date to'),
202
 
        'history_id': fields.many2one('product.history.consumption', string='History'),
 
354
        'history_id': fields.many2one('product.history.consumption', string='History', ondelete='cascade'),
203
355
    }
204
356
 
205
357
product_history_consumption_month()
209
361
    _name = 'product.product'
210
362
    _inherit = 'product.product'
211
363
 
212
 
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context={}, toolbar=False, submenu=False):
213
 
        if not context:
214
 
           context={}
215
 
 
216
 
        res = super(product_product, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu)
 
364
    def export_data(self, cr, uid, ids, fields_to_export, context=None):
 
365
        '''
 
366
        Override the export_data function to add fictive fields
 
367
        '''
 
368
        if not context:
 
369
            context = {}
 
370
 
 
371
        history_fields = []
 
372
        new_fields_to_export = []
 
373
        fields_sort = {}
 
374
        sort_iter2 = 0
 
375
        default_code_index = False
 
376
        remove_default_code = False
 
377
        history_cons_in_context = context.get('history_cons', False)
 
378
 
 
379
        # Add fictive fields
 
380
        if history_cons_in_context:
 
381
            months = context.get('months', [])
 
382
            del context['history_cons']
 
383
            if context.get('amc', False) and 'average' in fields_to_export:
 
384
                history_fields.append('average')
 
385
 
 
386
            if 'default_code' not in fields_to_export:
 
387
                fields_to_export.append('default_code')
 
388
                remove_default_code = True
 
389
 
 
390
            for month in months:
 
391
                field_name = DateFrom(month.get('date_from')).strftime('%m_%Y')
 
392
                if field_name in fields_to_export:
 
393
                    history_fields.append(field_name)
 
394
 
 
395
            # Prepare normal fields to export to avoid error on export data with fictive fields
 
396
            to_export_iter = 0
 
397
            for f in fields_to_export:
 
398
                if f not in history_fields:
 
399
                    new_fields_to_export.append(f)
 
400
                    if f == 'default_code':
 
401
                        default_code_index = to_export_iter
 
402
                    to_export_iter += 1
 
403
 
 
404
                # We save the order of the fields to read them in the good order
 
405
                fields_sort.update({sort_iter2: f})
 
406
                sort_iter2 += 1
 
407
        else:
 
408
            new_fields_to_export = fields_to_export
 
409
 
 
410
        res = super(product_product, self).export_data(cr, uid, ids, new_fields_to_export, context=context)
 
411
 
 
412
        # Set the fields in the good order
 
413
        if history_cons_in_context:
 
414
            context['history_cons'] = True
 
415
            new_data = []
 
416
            for r in res['datas']:
 
417
                new_r = []
 
418
                product_id = self.search(cr, uid, [('default_code', '=', r[default_code_index])], context=context)
 
419
                datas = {}
 
420
                if product_id:
 
421
                    datas = self.read(cr, uid, product_id, history_fields + ['default_code', 'id'], context=context)[0]
 
422
 
 
423
                iter_r = 0
 
424
                for j in range(sort_iter2):
 
425
                    f = fields_sort[j]
 
426
 
 
427
                    if f == 'default_code' and remove_default_code:
 
428
                        continue
 
429
 
 
430
                    if f in history_fields:
 
431
                        new_r.append(str(datas.get(f, 0.00)))
 
432
                    else:
 
433
                        new_r.append(r[iter_r])
 
434
                        iter_r += 1
 
435
                new_data.append(new_r)
 
436
 
 
437
            res['datas'] = new_data
 
438
        
 
439
        return res
 
440
 
 
441
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
 
442
        if not context:
 
443
           context = {}
 
444
        
 
445
        ctx = context.copy()
 
446
        if 'location' in context and type(context.get('location')) == type([]):
 
447
            ctx.update({'location': context.get('location')[0]})
 
448
        res = super(product_product, self).fields_view_get(cr, uid, view_id, view_type, context=ctx, toolbar=toolbar, submenu=submenu)
217
449
 
218
450
        if context.get('history_cons', False) and view_type == 'tree':
219
451
            line_view = """<tree string="Historical consumption">
231
463
            tmp_months.sort()
232
464
 
233
465
            for month in tmp_months:
234
 
                line_view += """<field name="%s" />""" % DateFrom(month).strftime('%m/%Y')
 
466
                line_view += """<field name="%s" />""" % DateFrom(month).strftime('%m_%Y')
235
467
 
236
468
            line_view += "</tree>"
237
469
 
239
471
                res['arch'] = line_view
240
472
        elif context.get('history_cons', False) and view_type == 'search':
241
473
            # Hard method !!!!!!
242
 
            # Remove the Group by group from the product view
 
474
            # Remove the Group by group from the product view
243
475
            xml_view = etree.fromstring(res['arch'])
244
476
            for element in xml_view.iter("group"):
245
477
                if element.get('string', '') == 'Group by...':
246
478
                    xml_view.remove(element)
247
479
            res['arch'] = etree.tostring(xml_view)
248
480
 
 
481
            # UTP-501 Positive AMC filter
 
482
            xml_view = etree.fromstring(res['arch'])
 
483
            new_separator = """<separator orientation="vertical" />"""
 
484
            separator_node = etree.fromstring(new_separator)
 
485
            xml_view.insert(0, separator_node)
 
486
            new_filter = """<filter string="Av.%s &gt; 0" name="average" icon="terp-accessories-archiver-minus" domain="[('average','>',0.)]" />""" % (context.get('amc', 'AMC'),)
 
487
            # generate new xml form$
 
488
            filter_node = etree.fromstring(new_filter)
 
489
            xml_view.insert(0, filter_node)
 
490
            res['arch'] = etree.tostring(xml_view)
 
491
 
249
492
        return res
250
493
 
251
 
    def fields_get(self, cr, uid, fields=None, context={}):
 
494
    def fields_get(self, cr, uid, fields=None, context=None):
252
495
        if not context:
253
496
            context = {}
254
497
 
258
501
            months = context.get('months', [])
259
502
 
260
503
            for month in months:
261
 
                res.update({DateFrom(month.get('date_from')).strftime('%m/%Y'): {'digits': (16,2),
 
504
                res.update({DateFrom(month.get('date_from')).strftime('%m_%Y'): {'digits': (16,2),
262
505
                                                                                 'selectable': True,
263
506
                                                                                 'type': 'float',
264
507
                                                                                 'string': '%s' % DateFrom(month.get('date_from')).strftime('%m/%Y')}})
271
514
 
272
515
        return res
273
516
 
274
 
    def read(self, cr, uid, ids, vals=None, context={}, load='_classic_read'):
 
517
    def read(self, cr, uid, ids, vals=None, context=None, load='_classic_read'):
275
518
        '''
276
519
        Set value for each month
277
520
        '''
 
521
        cons_prod_obj = self.pool.get('product.history.consumption.product')
 
522
 
 
523
        if context is None:
 
524
            context = {}
278
525
 
279
526
        if context.get('history_cons', False):
280
527
            res = super(product_product, self).read(cr, uid, ids, vals, context=context, load=load)
292
539
                raise osv.except_osv(_('Error'), _('No months found !'))
293
540
 
294
541
            obj_id = context.get('obj_id')
295
 
 
296
542
            for r in res:
297
543
                total_consumption = 0.00
298
544
                for month in context.get('months'):
299
 
                    field_name = DateFrom(month.get('date_from')).strftime('%m/%Y')
 
545
                    field_name = DateFrom(month.get('date_from')).strftime('%m_%Y')
300
546
                    cons_context = {'from_date': month.get('date_from'), 'to_date': month.get('date_to'), 'location_id': context.get('location_id')}
301
547
                    consumption = 0.00
 
548
                    cons_prod_domain = [('name', '=', field_name),
 
549
                                        ('product_id', '=', r['id']),
 
550
                                        ('consumption_id', '=', obj_id)]
302
551
                    if context.get('amc') == 'AMC':
303
 
                        consumption = self.pool.get('product.product').compute_amc(cr, uid, r['id'], context=cons_context)
 
552
                        cons_prod_domain.append(('cons_type', '=', 'amc'))
 
553
                        cons_id = cons_prod_obj.search(cr, uid, cons_prod_domain, context=context)
 
554
                        if cons_id:
 
555
                            consumption = cons_prod_obj.browse(cr, uid, cons_id[0], context=context).value
 
556
                        else:
 
557
                            consumption = self.pool.get('product.product').compute_amc(cr, uid, r['id'], context=cons_context) or 0.00
 
558
                            cons_prod_obj.create(cr, uid, {'name': field_name,
 
559
                                                           'product_id': r['id'],
 
560
                                                           'consumption_id': obj_id,
 
561
                                                           'cons_type': 'amc',
 
562
                                                           'value': consumption}, context=context)
304
563
                    else:
305
 
                        consumption = self.pool.get('product.product').browse(cr, uid, r['id'], context=cons_context).monthly_consumption
 
564
                        cons_prod_domain.append(('cons_type', '=', 'fmc'))
 
565
                        cons_id = cons_prod_obj.search(cr, uid, cons_prod_domain, context=context)
 
566
                        if cons_id:
 
567
                            consumption = cons_prod_obj.browse(cr, uid, cons_id[0], context=context).value
 
568
                        else:
 
569
                            consumption = self.pool.get('product.product').browse(cr, uid, r['id'], context=cons_context).monthly_consumption or 0.00
 
570
                            cons_prod_obj.create(cr, uid, {'name': field_name,
 
571
                                                           'product_id': r['id'],
 
572
                                                           'consumption_id': obj_id,
 
573
                                                           'cons_type': 'fmc',
 
574
                                                           'value': consumption}, context=context)
306
575
                    total_consumption += consumption
307
 
                    # Update the value for the month
 
576
                    # Update the value for the month
308
577
                    r.update({field_name: consumption})
309
578
 
310
 
                # Update the average field
 
579
                # Update the average field
 
580
                cons_prod_domain = [('name', '=', 'average'),
 
581
                                    ('product_id', '=', r['id']),
 
582
                                    ('consumption_id', '=', obj_id),
 
583
                                    ('cons_type', '=', context.get('amc') == 'AMC' and 'amc' or 'fmc')]
311
584
                r.update({'average': round(total_consumption/float(len(context.get('months'))),2)})
 
585
                cons_id = cons_prod_obj.search(cr, uid, cons_prod_domain, context=context)
 
586
                if cons_id:
 
587
                    cons_prod_obj.write(cr, uid, cons_id, {'value': r['average']}, context=context)
 
588
                else:
 
589
                    cons_prod_obj.create(cr, uid, {'name': 'average',
 
590
                                                   'product_id': r['id'],
 
591
                                                   'consumption_id': obj_id,
 
592
                                                   'cons_type': context.get('amc') == 'AMC' and 'amc' or 'fmc',
 
593
                                                   'value': r['average']}, context=context)
312
594
        else:
313
595
            res = super(product_product, self).read(cr, uid, ids, vals, context=context, load=load)
314
596
 
315
597
        return res
316
598
 
 
599
    def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
 
600
        '''
 
601
        Update the search method to sort by fictive fields if needed
 
602
        '''
 
603
        if not context:
 
604
            context = {}
 
605
 
 
606
        average_domain = False
 
607
        if context.get('history_cons', False):
 
608
            """UTP-501 'average' filter (filter button generated in fields_view_get)
 
609
            if found, grab it, and remove it
 
610
            (bc 'average' field is unknown in super(product_product, self))
 
611
            """
 
612
            new_args = []
 
613
            for a in args:
 
614
                if len(a) == 3 and a[0] == 'average':
 
615
                    average_domain = a
 
616
                else:
 
617
                    new_args.append(a)
 
618
            args = new_args
 
619
 
 
620
        hist_obj = self.pool.get('product.history.consumption.product')
 
621
 
 
622
        res = super(product_product, self).search(cr, uid, args, offset, limit, order, context, count)
 
623
 
 
624
        if context.get('history_cons', False) and context.get('obj_id', False):
 
625
            if order or average_domain:
 
626
                hist_domain = [('consumption_id', '=', context.get('obj_id'))]
 
627
                if context.get('amc') == 'AMC':
 
628
                    hist_domain.append(('cons_type', '=', 'amc'))
 
629
                else:
 
630
                    hist_domain.append(('cons_type', '=', 'fmc'))
 
631
 
 
632
            if average_domain:
 
633
                # UTP-501 'average' filter
 
634
                hist_domain += [
 
635
                    ('name', '=', 'average'),
 
636
                    ('value', average_domain[1], average_domain[2])
 
637
                ]
 
638
 
 
639
            if order:
 
640
                # sorting with or without average_domain
 
641
                for order_part in order.split(','):
 
642
                    order_split = order_part.strip().split(' ')
 
643
                    order_field = order_split[0]
 
644
                    order_direction = order_split[1].strip() if len(order_split) == 2 else ''
 
645
                    if order_field != 'id' and order_field not in self._columns and order_field not in self._inherit_fields:
 
646
                        hist_domain.append(('name', '=', order_field))
 
647
                        hist_ids = hist_obj.search(cr, uid, hist_domain, offset=offset, limit=limit, order='value %s' % order_direction, context=context)
 
648
                        res = list(x['product_id'][0] for x in hist_obj.read(cr, uid, hist_ids, ['product_id'], context=context))
 
649
                        break
 
650
            elif average_domain:
 
651
                # UTP-501 'average' filter without sorting
 
652
                hist_ids = hist_obj.search(cr, uid, hist_domain, offset=offset, limit=limit, order=order, context=context)
 
653
                res = [x['product_id'][0] for x in hist_obj.read(cr, uid, hist_ids, ['product_id'], context=context)]
 
654
 
 
655
        return res
 
656
 
317
657
product_product()
318
658
 
 
659
 
 
660
class product_history_consumption_product(osv.osv):
 
661
    _name = 'product.history.consumption.product'
 
662
 
 
663
    _columns = {
 
664
        'consumption_id': fields.many2one('product.history.consumption', string='Consumption id', select=1, ondelete='cascade'),
 
665
        'product_id': fields.many2one('product.product', string='Product'),
 
666
        'name': fields.char(size=64, string='Name'),
 
667
        'value': fields.float(digits=(16,2), string='Value', select=1),
 
668
        'cons_type': fields.selection([('amc', 'AMC'), ('fmc', 'FMC')], string='Consumption type'),
 
669
    }
 
670
 
 
671
    def read(self, cr, uid, ids, fields, context=None, load='_classic_read'):
 
672
        '''
 
673
        Return the result in the same order as given in ids
 
674
        '''
 
675
        res = super(product_history_consumption_product, self).read(cr, uid, ids, fields, context=context, load=load)
 
676
 
 
677
        res_final = [None]*len(ids)
 
678
        for r in res:
 
679
            r_index = ids.index(r['id'])
 
680
            res_final[r_index] = r
 
681
 
 
682
        return res_final
 
683
 
 
684
product_history_consumption_product()
 
685
 
319
686
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: