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

« back to all changes in this revision

Viewing changes to consumption_calculation/history_consumption.py

  • Committer: Quentin THEURET
  • Date: 2014-03-05 16:51:14 UTC
  • mto: (2004.1.33 unifield-wm)
  • mto: This revision was merged to the branch mainline in revision 2016.
  • Revision ID: qt@tempo-consulting.fr-20140305165114-m3n5p978sisi4n3f
REF-27 [FIX] Fix import of tools.translate

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 
28
28
import time
29
29
 
 
30
HIST_STATUS = [('draft', 'Draft'), ('in_progress', 'In Progress'), ('ready', 'Ready')]
30
31
 
31
 
class product_history_consumption(osv.osv_memory):
 
32
class product_history_consumption(osv.osv):
32
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
33
46
 
34
47
    _columns = {
35
 
        'date_from': fields.date(string='From date', required=True),
36
 
        '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'),
37
50
        'month_ids': fields.one2many('product.history.consumption.month', 'history_id', string='Months'),
38
51
        'consumption_type': fields.selection([('rac', 'Real Average Consumption'), ('amc', 'Average Monthly Consumption')],
39
 
                                             string='Consumption type', required=True),
 
52
                                             string='Consumption type'),
40
53
        'location_id': fields.many2one('stock.location', string='Location', domain="[('usage', '=', 'internal')]"),
41
54
        'sublist_id': fields.many2one('product.list', string='List/Sublist'),
42
55
        'nomen_id': fields.many2one('product.nomenclature', string='Products\' nomenclature level'),
44
57
        'nomen_manda_1': fields.many2one('product.nomenclature', 'Group'),
45
58
        'nomen_manda_2': fields.many2one('product.nomenclature', 'Family'),
46
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'),
47
64
    }
48
65
 
49
66
    _defaults = {
50
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',
51
71
    }
52
72
 
53
73
    def open_history_consumption(self, cr, uid, ids, context=None):
82
102
        if date_from and date_to:
83
103
            res['value'].update({'month_ids': []})
84
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\'')}}
85
108
            # For all months in the period
86
109
            while current_date <= (DateFrom(date_to) + RelativeDateTime(months=1, day=1, days=-1)):
87
110
                search_ids = month_obj.search(cr, uid, [('name', '=', current_date.strftime('%m/%Y')), ('history_id', 'in', ids)], context=context)
88
111
                # If the month is in the period and not in the list, create it
89
112
                if not search_ids:
90
 
                    month_id = month_obj.create(cr, uid, {'name': current_date.strftime('%m/%Y'),
91
 
                                                          'date_from': current_date.strftime('%Y-%m-%d'),
92
 
                                                          'date_to': (current_date + RelativeDateTime(months=1, day=1, days=-1)).strftime('%Y-%m-%d'),
93
 
                                                          'history_id': ids[0]})
94
 
                    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')})
95
121
                else:
96
122
                    res['value']['month_ids'].extend(search_ids)
97
123
                current_date = current_date + RelativeDateTime(months=1)
98
124
        else:
99
 
            res['value'] = {'month_ids': [False]}
 
125
            res['value'] = {'month_ids': []}
100
126
 
101
127
        # Delete all months out of the period
102
128
        del_months = []
109
135
        return res
110
136
 
111
137
 
112
 
    def create_lines(self, cr, uid, ids, context=None):
 
138
    def get_data(self, cr, uid, ids, context=None):
113
139
        '''
114
 
        Create one line by product for the period
 
140
        Get parameters of the report
115
141
        '''
116
142
        if not context:
117
143
            context = {}
131
157
        nb_months = len(months)
132
158
        total_consumption = {}
133
159
 
 
160
        if not months:
 
161
            raise osv.except_osv(_('Error'), _('You have to choose at least one month for consumption history'))
 
162
 
134
163
        if obj.nomen_manda_0:
135
164
            for report in self.browse(cr, uid, ids, context=context):
136
165
                product_ids = []
158
187
                if product.id not in products:
159
188
                    batch_mandatory = product.batch_management or product.perishable
160
189
                    date_mandatory = not product.batch_management and product.perishable
161
 
                    self.pool.get('product.product').write(cr, uid, ids, {'name': product.id,})
162
190
 
163
191
        if obj.sublist_id:
164
192
            context.update({'search_default_list_ids': obj.sublist_id.id})
171
199
            domain = []
172
200
 
173
201
        new_context = context.copy()
174
 
        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})
175
203
 
176
204
        # For each month, compute the RAC
177
205
        for month in self.pool.get('product.history.consumption.month').browse(cr, uid, months, context=context):
178
206
            new_context['months'].append({'date_from': month.date_from, 'date_to': month.date_to})
179
207
 
180
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
        try:
 
250
            self.pool.get('product.product').read(new_cr, uid, product_ids, ['average'], context=context)
 
251
        except Exception, e:
 
252
            cr.rollback()
 
253
        self.write(new_cr, uid, ids, {'status': 'ready'}, context=context)
 
254
 
 
255
        new_cr.commit()
 
256
        new_cr.close()
 
257
 
 
258
        return
 
259
 
 
260
    def open_report(self, cr, uid, ids, context=None):
 
261
        '''
 
262
        Open the report
 
263
        '''
 
264
        if not context:
 
265
            context = {}
 
266
 
 
267
        product_ids, domain, new_context = self.get_data(cr, uid, ids, context=context)
 
268
 
181
269
        return {'type': 'ir.actions.act_window',
182
270
                'res_model': 'product.product',
183
271
                'domain': domain,
186
274
                'context': new_context,
187
275
                'target': 'dummy'}
188
276
 
 
277
    def unlink(self, cr, uid, ids, context=None):
 
278
        '''
 
279
        Remove the data saved in DB
 
280
        '''
 
281
        hist_obj = self.pool.get('product.history.consumption.product')
 
282
        for cons in self.browse(cr, uid, ids, context=context):
 
283
            hist_ids = hist_obj.search(cr, uid, [('consumption_id', '=', cons.id)], context=context)
 
284
            hist_obj.unlink(cr, uid, hist_ids, context=context)
 
285
        return super(product_history_consumption, self).unlink(cr, uid, ids, context=context)
 
286
 
 
287
    def in_progress(self, cr, uid, ids, context=None):
 
288
        '''
 
289
        Return dummy
 
290
        '''
 
291
        return self.go_to_list(cr, uid, ids, context=context)
 
292
 
 
293
    def go_to_list(self, cr, uid, ids, context=None):
 
294
        '''
 
295
        Returns to the list of reports
 
296
        '''
 
297
        return {'type': 'ir.actions.act_window',
 
298
                'res_model': 'product.history.consumption',
 
299
                'view_mode': 'tree,form',
 
300
                'view_type': 'form',
 
301
                'target': 'dummy',
 
302
                'context': context}
 
303
 
189
304
##############################################################################################################################
190
305
# The code below aims to enable filtering products regarding their nomenclature.
191
306
# NB: the difference with the other same kind of product filters (with nomenclature and sublist) is that here we are dealing with osv_memory
212
327
 
213
328
product_history_consumption()
214
329
 
215
 
class product_history_consumption_month(osv.osv_memory):
 
330
class product_history_consumption_month(osv.osv):
216
331
    _name = 'product.history.consumption.month'
217
332
    _order = 'name, date_from, date_to'
218
333
 
220
335
        'name': fields.char(size=64, string='Month'),
221
336
        'date_from': fields.date(string='Date from'),
222
337
        'date_to': fields.date(string='Date to'),
223
 
        'history_id': fields.many2one('product.history.consumption', string='History'),
 
338
        'history_id': fields.many2one('product.history.consumption', string='History', ondelete='cascade'),
224
339
    }
225
340
 
226
341
product_history_consumption_month()
230
345
    _name = 'product.product'
231
346
    _inherit = 'product.product'
232
347
 
 
348
    def export_data(self, cr, uid, ids, fields_to_export, context=None):
 
349
        '''
 
350
        Override the export_data function to add fictive fields
 
351
        '''
 
352
        if not context:
 
353
            context = {}
 
354
 
 
355
        history_fields = []
 
356
        new_fields_to_export = []
 
357
        fields_sort = {}
 
358
        sort_iter2 = 0
 
359
        default_code_index = False
 
360
        remove_default_code = False
 
361
        history_cons_in_context = context.get('history_cons', False)
 
362
 
 
363
        # Add fictive fields
 
364
        if history_cons_in_context:
 
365
            months = context.get('months', [])
 
366
            del context['history_cons']
 
367
            if context.get('amc', False) and 'average' in fields_to_export:
 
368
                history_fields.append('average')
 
369
 
 
370
            if 'default_code' not in fields_to_export:
 
371
                fields_to_export.append('default_code')
 
372
                remove_default_code = True
 
373
 
 
374
            for month in months:
 
375
                field_name = DateFrom(month.get('date_from')).strftime('%m_%Y')
 
376
                if field_name in fields_to_export:
 
377
                    history_fields.append(field_name)
 
378
 
 
379
            # Prepare normal fields to export to avoid error on export data with fictive fields
 
380
            to_export_iter = 0
 
381
            for f in fields_to_export:
 
382
                if f not in history_fields:
 
383
                    new_fields_to_export.append(f)
 
384
                    if f == 'default_code':
 
385
                        default_code_index = to_export_iter
 
386
                    to_export_iter += 1
 
387
 
 
388
                # We save the order of the fields to read them in the good order
 
389
                fields_sort.update({sort_iter2: f})
 
390
                sort_iter2 += 1
 
391
        else:
 
392
            new_fields_to_export = fields_to_export
 
393
 
 
394
        res = super(product_product, self).export_data(cr, uid, ids, new_fields_to_export, context=context)
 
395
 
 
396
        # Set the fields in the good order
 
397
        if history_cons_in_context:
 
398
            context['history_cons'] = True
 
399
            new_data = []
 
400
            for r in res['datas']:
 
401
                new_r = []
 
402
                product_id = self.search(cr, uid, [('default_code', '=', r[default_code_index])], context=context)
 
403
                datas = {}
 
404
                if product_id:
 
405
                    datas = self.read(cr, uid, product_id, history_fields + ['default_code', 'id'], context=context)[0]
 
406
 
 
407
                iter_r = 0
 
408
                for j in range(sort_iter2):
 
409
                    f = fields_sort[j]
 
410
 
 
411
                    if f == 'default_code' and remove_default_code:
 
412
                        continue
 
413
 
 
414
                    if f in history_fields:
 
415
                        new_r.append(str(datas.get(f, 0.00)))
 
416
                    else:
 
417
                        new_r.append(r[iter_r])
 
418
                        iter_r += 1
 
419
                new_data.append(new_r)
 
420
 
 
421
            res['datas'] = new_data
 
422
        
 
423
        return res
 
424
 
233
425
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
234
426
        if not context:
235
427
           context = {}
255
447
            tmp_months.sort()
256
448
 
257
449
            for month in tmp_months:
258
 
                line_view += """<field name="%s" />""" % DateFrom(month).strftime('%m/%Y')
 
450
                line_view += """<field name="%s" />""" % DateFrom(month).strftime('%m_%Y')
259
451
 
260
452
            line_view += "</tree>"
261
453
 
282
474
            months = context.get('months', [])
283
475
 
284
476
            for month in months:
285
 
                res.update({DateFrom(month.get('date_from')).strftime('%m/%Y'): {'digits': (16,2),
 
477
                res.update({DateFrom(month.get('date_from')).strftime('%m_%Y'): {'digits': (16,2),
286
478
                                                                                 'selectable': True,
287
479
                                                                                 'type': 'float',
288
480
                                                                                 'string': '%s' % DateFrom(month.get('date_from')).strftime('%m/%Y')}})
299
491
        '''
300
492
        Set value for each month
301
493
        '''
 
494
        cons_prod_obj = self.pool.get('product.history.consumption.product')
 
495
 
302
496
        if context is None:
303
497
            context = {}
 
498
 
304
499
        if context.get('history_cons', False):
305
500
            res = super(product_product, self).read(cr, uid, ids, vals, context=context, load=load)
306
501
 
317
512
                raise osv.except_osv(_('Error'), _('No months found !'))
318
513
 
319
514
            obj_id = context.get('obj_id')
320
 
 
321
515
            for r in res:
322
516
                total_consumption = 0.00
323
517
                for month in context.get('months'):
324
 
                    field_name = DateFrom(month.get('date_from')).strftime('%m/%Y')
 
518
                    field_name = DateFrom(month.get('date_from')).strftime('%m_%Y')
325
519
                    cons_context = {'from_date': month.get('date_from'), 'to_date': month.get('date_to'), 'location_id': context.get('location_id')}
326
520
                    consumption = 0.00
 
521
                    cons_prod_domain = [('name', '=', field_name),
 
522
                                        ('product_id', '=', r['id']),
 
523
                                        ('consumption_id', '=', obj_id)]
327
524
                    if context.get('amc') == 'AMC':
328
 
                        consumption = self.pool.get('product.product').compute_amc(cr, uid, r['id'], context=cons_context)
 
525
                        cons_prod_domain.append(('cons_type', '=', 'amc'))
 
526
                        cons_id = cons_prod_obj.search(cr, uid, cons_prod_domain, context=context)
 
527
                        if cons_id:
 
528
                            consumption = cons_prod_obj.browse(cr, uid, cons_id[0], context=context).value
 
529
                        else:
 
530
                            consumption = self.pool.get('product.product').compute_amc(cr, uid, r['id'], context=cons_context) or 0.00
 
531
                            cons_prod_obj.create(cr, uid, {'name': field_name,
 
532
                                                           'product_id': r['id'],
 
533
                                                           'consumption_id': obj_id,
 
534
                                                           'cons_type': 'amc',
 
535
                                                           'value': consumption}, context=context)
329
536
                    else:
330
 
                        consumption = self.pool.get('product.product').browse(cr, uid, r['id'], context=cons_context).monthly_consumption
 
537
                        cons_prod_domain.append(('cons_type', '=', 'fmc'))
 
538
                        cons_id = cons_prod_obj.search(cr, uid, cons_prod_domain, context=context)
 
539
                        if cons_id:
 
540
                            consumption = cons_prod_obj.browse(cr, uid, cons_id[0], context=context).value
 
541
                        else:
 
542
                            consumption = self.pool.get('product.product').browse(cr, uid, r['id'], context=cons_context).monthly_consumption or 0.00
 
543
                            cons_prod_obj.create(cr, uid, {'name': field_name,
 
544
                                                           'product_id': r['id'],
 
545
                                                           'consumption_id': obj_id,
 
546
                                                           'cons_type': 'fmc',
 
547
                                                           'value': consumption}, context=context)
331
548
                    total_consumption += consumption
332
549
                    # Update the value for the month
333
550
                    r.update({field_name: consumption})
334
551
 
335
552
                # Update the average field
 
553
                cons_prod_domain = [('name', '=', 'average'),
 
554
                                    ('product_id', '=', r['id']),
 
555
                                    ('consumption_id', '=', obj_id),
 
556
                                    ('cons_type', '=', context.get('amc') == 'AMC' and 'amc' or 'fmc')]
336
557
                r.update({'average': round(total_consumption/float(len(context.get('months'))),2)})
 
558
                cons_id = cons_prod_obj.search(cr, uid, cons_prod_domain, context=context)
 
559
                if cons_id:
 
560
                    cons_prod_obj.write(cr, uid, cons_id, {'value': r['average']}, context=context)
 
561
                else:
 
562
                    cons_prod_obj.create(cr, uid, {'name': 'average',
 
563
                                                   'product_id': r['id'],
 
564
                                                   'consumption_id': obj_id,
 
565
                                                   'cons_type': context.get('amc') == 'AMC' and 'amc' or 'fmc',
 
566
                                                   'value': r['average']}, context=context)
337
567
        else:
338
568
            res = super(product_product, self).read(cr, uid, ids, vals, context=context, load=load)
339
569
 
340
570
        return res
341
571
 
 
572
    def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
 
573
        '''
 
574
        Update the search method to sort by fictive fields if needed
 
575
        '''
 
576
        if not context:
 
577
            context = {}
 
578
 
 
579
        hist_obj = self.pool.get('product.history.consumption.product')
 
580
 
 
581
        res = super(product_product, self).search(cr, uid, args, offset, limit, order, context, count)
 
582
 
 
583
        if context.get('history_cons', False) and context.get('obj_id', False) and order:
 
584
            hist_domain = [('consumption_id', '=', context.get('obj_id'))]
 
585
            if context.get('amc') == 'AMC':
 
586
                hist_domain.append(('cons_type', '=', 'amc'))
 
587
            else:
 
588
                hist_domain.append(('cons_type', '=', 'fmc'))
 
589
 
 
590
            for order_part in order.split(','):
 
591
                order_split = order_part.strip().split(' ')
 
592
                order_field = order_split[0]
 
593
                order_direction = order_split[1].strip() if len(order_split) == 2 else ''
 
594
                if order_field != 'id' and order_field not in self._columns and order_field not in self._inherit_fields:
 
595
                    hist_domain.append(('name', '=', order_field))
 
596
                    hist_ids = hist_obj.search(cr, uid, hist_domain, offset=offset, limit=limit, order='value %s' % order_direction, context=context)
 
597
                    res = list(x['product_id'][0] for x in hist_obj.read(cr, uid, hist_ids, ['product_id'], context=context))
 
598
                    break
 
599
 
 
600
        return res
 
601
 
342
602
product_product()
343
603
 
 
604
 
 
605
class product_history_consumption_product(osv.osv):
 
606
    _name = 'product.history.consumption.product'
 
607
 
 
608
    _columns = {
 
609
        'consumption_id': fields.many2one('product.history.consumption', string='Consumption id', select=1, ondelete='cascade'),
 
610
        'product_id': fields.many2one('product.product', string='Product'),
 
611
        'name': fields.char(size=64, string='Name'),
 
612
        'value': fields.float(digits=(16,2), string='Value', select=1),
 
613
        'cons_type': fields.selection([('amc', 'AMC'), ('fmc', 'FMC')], string='Consumption type'),
 
614
    }
 
615
 
 
616
    def read(self, cr, uid, ids, fields, context=None, load='_classic_read'):
 
617
        '''
 
618
        Return the result in the same order as given in ids
 
619
        '''
 
620
        res = super(product_history_consumption_product, self).read(cr, uid, ids, fields, context=context, load=load)
 
621
 
 
622
        res_final = [None]*len(ids)
 
623
        for r in res:
 
624
            r_index = ids.index(r['id'])
 
625
            res_final[r_index] = r
 
626
 
 
627
        return res_final
 
628
 
 
629
product_history_consumption_product()
 
630
 
344
631
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: