30
HIST_STATUS = [('draft', 'Draft'), ('in_progress', 'In Progress'), ('ready', 'Ready')]
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'
36
def _get_status(self, cr, uid, ids, field_name, args, context=None):
38
Return the same status as status
42
for obj in self.browse(cr, uid, ids, context=context):
43
res[obj.id] = obj.status
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'),
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')})
96
122
res['value']['month_ids'].extend(search_ids)
97
123
current_date = current_date + RelativeDateTime(months=1)
99
res['value'] = {'month_ids': [False]}
125
res['value'] = {'month_ids': []}
101
127
# Delete all months out of the period
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})
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})
209
return product_ids, domain, new_context
211
def create_lines(self, cr, uid, ids, context=None):
213
Create one line by product for the period
218
product_ids, domain, new_context = self.get_data(cr, uid, ids, context=context)
221
product_ids = self.pool.get('product.product').search(cr, uid, [], context=new_context)
224
self.write(cr, uid, ids, {'status': 'in_progress'}, context=context)
226
new_thread = threading.Thread(target=self._create_lines, args=(cr, uid, ids, product_ids, new_context))
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',
236
'view_id': [view_id],
237
'context': new_context,
240
return self.open_report(cr, uid, ids, context=new_context)
242
def _create_lines(self, cr, uid, ids, product_ids, context=None):
244
Create lines in background
247
new_cr = pooler.get_db(cr.dbname).cursor()
250
self.pool.get('product.product').read(new_cr, uid, product_ids, ['average'], context=context)
253
self.write(new_cr, uid, ids, {'status': 'ready'}, context=context)
260
def open_report(self, cr, uid, ids, context=None):
267
product_ids, domain, new_context = self.get_data(cr, uid, ids, context=context)
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'}
277
def unlink(self, cr, uid, ids, context=None):
279
Remove the data saved in DB
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)
287
def in_progress(self, cr, uid, ids, context=None):
291
return self.go_to_list(cr, uid, ids, context=context)
293
def go_to_list(self, cr, uid, ids, context=None):
295
Returns to the list of reports
297
return {'type': 'ir.actions.act_window',
298
'res_model': 'product.history.consumption',
299
'view_mode': 'tree,form',
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
230
345
_name = 'product.product'
231
346
_inherit = 'product.product'
348
def export_data(self, cr, uid, ids, fields_to_export, context=None):
350
Override the export_data function to add fictive fields
356
new_fields_to_export = []
359
default_code_index = False
360
remove_default_code = False
361
history_cons_in_context = context.get('history_cons', False)
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')
370
if 'default_code' not in fields_to_export:
371
fields_to_export.append('default_code')
372
remove_default_code = True
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)
379
# Prepare normal fields to export to avoid error on export data with fictive fields
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
388
# We save the order of the fields to read them in the good order
389
fields_sort.update({sort_iter2: f})
392
new_fields_to_export = fields_to_export
394
res = super(product_product, self).export_data(cr, uid, ids, new_fields_to_export, context=context)
396
# Set the fields in the good order
397
if history_cons_in_context:
398
context['history_cons'] = True
400
for r in res['datas']:
402
product_id = self.search(cr, uid, [('default_code', '=', r[default_code_index])], context=context)
405
datas = self.read(cr, uid, product_id, history_fields + ['default_code', 'id'], context=context)[0]
408
for j in range(sort_iter2):
411
if f == 'default_code' and remove_default_code:
414
if f in history_fields:
415
new_r.append(str(datas.get(f, 0.00)))
417
new_r.append(r[iter_r])
419
new_data.append(new_r)
421
res['datas'] = new_data
233
425
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
317
512
raise osv.except_osv(_('Error'), _('No months found !'))
319
514
obj_id = context.get('obj_id')
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)
528
consumption = cons_prod_obj.browse(cr, uid, cons_id[0], context=context).value
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,
535
'value': consumption}, context=context)
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)
540
consumption = cons_prod_obj.browse(cr, uid, cons_id[0], context=context).value
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,
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})
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)
560
cons_prod_obj.write(cr, uid, cons_id, {'value': r['average']}, context=context)
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)
338
568
res = super(product_product, self).read(cr, uid, ids, vals, context=context, load=load)
572
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
574
Update the search method to sort by fictive fields if needed
579
hist_obj = self.pool.get('product.history.consumption.product')
581
res = super(product_product, self).search(cr, uid, args, offset, limit, order, context, count)
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'))
588
hist_domain.append(('cons_type', '=', 'fmc'))
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))
342
602
product_product()
605
class product_history_consumption_product(osv.osv):
606
_name = 'product.history.consumption.product'
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'),
616
def read(self, cr, uid, ids, fields, context=None, load='_classic_read'):
618
Return the result in the same order as given in ids
620
res = super(product_history_consumption_product, self).read(cr, uid, ids, fields, context=context, load=load)
622
res_final = [None]*len(ids)
624
r_index = ids.index(r['id'])
625
res_final[r_index] = r
629
product_history_consumption_product()
344
631
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: