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

« back to all changes in this revision

Viewing changes to consumption_calculation/expiry_calculation.py

  • Committer: jf
  • Date: 2012-01-10 20:57:37 UTC
  • mto: (559.2.21 unifield-wm)
  • mto: This revision was merged to the branch mainline in revision 562.
  • Revision ID: jf@ubuntu-20120110205737-gr6hukgf5ggimfup
Data supply

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
    _name = 'expiry.quantity.report'
32
32
    _description = 'Products Expired'
33
33
    
34
 
    def _get_date_to(self, cr, uid, ids, field_name, arg, context=None):
 
34
    def _get_date_to(self, cr, uid, ids, field_name, arg, context={}):
35
35
        '''
36
36
        Compute the end date for the calculation
37
37
        '''
53
53
        'line_ids': fields.one2many('expiry.quantity.report.line', 'report_id', string='Products', readonly=True),
54
54
    }
55
55
    
56
 
    def print_report_wizard(self, cr, uid, ids, context=None):
57
 
        '''
58
 
        Print the report directly from the wizard
59
 
        '''
60
 
        self.process_lines(cr, uid, ids, context=context)
61
 
        return self.print_report(cr, uid, ids, context=context)
62
 
    
63
 
    def print_report(self, cr, uid, ids, context=None):
64
 
        '''
65
 
        Print the report of expiry report
66
 
        '''
67
 
        datas = {'ids': ids} 
68
 
        
69
 
        return {
70
 
            'type': 'ir.actions.report.xml',
71
 
            'report_name': 'expiry.report',
72
 
            'datas': datas,
73
 
            'nodestroy': True,
74
 
            'context': context,
75
 
        }
76
 
        
77
 
    
78
 
    def process_lines(self, cr, uid, ids, context=None):
 
56
    def process_lines(self, cr, uid, ids, context={}):
79
57
        '''
80
58
        Creates all lines of expired products
81
59
        '''
147
125
                                                                                  'expiry_date': lot_brw.life_date,
148
126
                                                                                  'location_id': location,
149
127
                                                                                  'report_id': ids[0],
150
 
                                                                                  }, context=context)
 
128
                                                                                  })        
151
129
            
152
130
        return {'type': 'ir.actions.act_window',
153
131
                'res_model': 'expiry.quantity.report',
154
132
                'view_type': 'form',
155
133
                'view_mode': 'form',
156
 
                'nodestroy': True,
157
134
                'view_id': [view_id],
158
135
                'res_id': ids[0],
159
136
        }
169
146
    _columns = {
170
147
        'report_id': fields.many2one('expiry.quantity.report', string='Report', required=True),
171
148
        'product_id': fields.many2one('product.product', string='Product', required=True),
172
 
        'product_code': fields.related('product_id', 'default_code', string='Ref.', type='char'),
 
149
        'product_code': fields.related('product_id', 'default_code', string='Reference', type='char'),
173
150
        'product_name': fields.related('product_id', 'name', string='Name', type='char'),
174
151
        'uom_id': fields.related('product_id', 'uom_id', string='UoM', type='many2one', relation='product.uom'),
175
 
        'real_stock': fields.float(digits=(16, 2), string='Real stock'),
176
 
        'expired_qty': fields.float(digits=(16, 2), string='Batch exp.'),
177
 
        #'batch_number': fields.many2one('production.lot', string='Batch'),
178
 
        'batch_number': fields.char(size=64, string='Batch'),
179
 
        'expiry_date': fields.date(string='Exp. date'),
180
 
        'location_id': fields.many2one('stock.location', string='Loc.'),
 
152
        'real_stock': fields.float(digits=(16, 2), string='Total product real stock in location'),
 
153
        'expired_qty': fields.float(digits=(16, 2), string='Batch expired quantity in location'),
 
154
        'batch_number': fields.many2one('production.lot', string='Batch number'),
 
155
        'expiry_date': fields.date(string='Expiry date'),
 
156
        'location_id': fields.many2one('stock.location', string='Location'),
181
157
    }
182
158
    
183
159
expiry_quantity_report_line()
191
167
        'location_id': fields.many2one('stock.location', string='Location'),
192
168
        'msf_instance': fields.char(size=64, string='Location', readonly=True),
193
169
        'input_output_ok': fields.boolean(string='Exclude Input and Output locations'),
194
 
        'date_from': fields.date(string='From', required=True, readonly=True),
 
170
        'date_from': fields.date(string='From', required=True),
195
171
        'date_to': fields.date(string='To', required=True),
196
172
        'consumption_type': fields.selection([('fmc', 'FMC -- Forecasted Monthly Consumption'), 
197
173
                                              ('amc', 'AMC -- Average Monthly Consumption'), 
209
185
        'msf_instance': lambda *a: 'MSF Instance',
210
186
    }
211
187
 
212
 
    def period_change(self, cr, uid, ids, consumption_from, consumption_to, consumption_type, context=None):
 
188
    def period_change(self, cr, uid, ids, consumption_from, consumption_to, consumption_type, context={}):
213
189
        '''
214
190
        Get the first or last day of month
215
191
        '''
224
200
        return {'value': res}
225
201
            
226
202
    
227
 
    def _get_average_consumption(self, cr, uid, product_id, consumption_type, date_from, date_to, context=None):
 
203
    def _get_average_consumption(self, cr, uid, product_id, consumption_type, date_from, date_to, context={}):
228
204
        '''
229
205
        Return the average consumption for all locations
230
206
        '''
233
209
        
234
210
        product_obj = self.pool.get('product.product')
235
211
        res = 0.00
236
 
 
237
 
        if context.get('manual_consumption'):
238
 
            return context.get('manual_consumption')
239
212
        
240
213
        new_context = context.copy()
241
214
        new_context.update({'from_date': date_from,
250
223
            res = product_obj.browse(cr, uid, product_id, context=new_context).monthly_consumption
251
224
        
252
225
        return res
 
226
        
253
227
            
254
 
    def process_lines(self, cr, uid, ids, context=None):
 
228
    def process_lines(self, cr, uid, ids, context={}):
255
229
        '''
256
230
        Creates all moves with expiry quantities for all
257
231
        lot life date
286
260
        
287
261
        location_ids = []
288
262
        not_loc_ids = []
289
 
        only_product_ids = []
290
 
 
291
 
        if context.get('only_product_ids'):
292
 
            only_product_ids = context.get('only_product_ids')
293
263
 
294
264
        if report.input_output_ok:
295
265
            wh_ids = self.pool.get('stock.warehouse').search(cr, uid, [], context=context)
314
284
                        location_ids.append(move.location_dest_id.id)
315
285
            
316
286
        context.update({'location_id': location_ids, 'location': location_ids})
317
 
 
318
 
        lot_domain = [('stock_available', '>', 0.00)]
319
 
        if only_product_ids:
320
 
            lot_domain.append(('product_id', 'in', only_product_ids))
321
287
        
322
 
        lot_ids = lot_obj.search(cr, uid, lot_domain, order='product_id, life_date', context=context)
 
288
        lot_ids = lot_obj.search(cr, uid, [('stock_available', '>', 0.00)], order='product_id, life_date', context=context)
323
289
        
324
290
        from_date = DateFrom(report.date_from)
325
291
        to_date = DateFrom(report.date_to) + RelativeDateTime(day=1, months=1, days=-1)
345
311
                                                                                         'product_id': lot.product_id.id,
346
312
                                                                                         'in_stock': lot.product_id.qty_available,
347
313
                                                                                         'total_expired': 0.00,
348
 
                                                                                         'consumption': consumption,}, context=context)})
 
314
                                                                                         'consumption': consumption,})})
349
315
                
350
316
                # Create an item for each date
351
317
                seq = 0
356
322
                start_month_flag = True
357
323
                last_expiry_date = False
358
324
                for month in dates:
359
 
                    # Remove one day to include the expiry date as possible consumable day
360
 
                    if not last_expiry_date: last_expiry_date = month - RelativeDateTime(days=1)
 
325
                    if not last_expiry_date: last_expiry_date = month
361
326
                    
362
327
                    item_id = item_obj.create(cr, uid, {'name': month.strftime('%m/%y'), 
363
328
                                                        'line_id': products[lot.product_id.id]['line_id']}, context=context)
370
335
                             ('stock_available', '>', 0.00),
371
336
                             ('life_date', '<', (month + RelativeDateTime(months=1, day=1)).strftime('%Y-%m-%d'))]
372
337
 
 
338
                    # If we are not in the first month of the period, displayed all products already expired
373
339
                    if not start_month_flag:
374
340
                        domain.append(('life_date', '>=', month.strftime('%Y-%m-%d')))
375
341
                        item_obj.write(cr, uid, [item_id], {'period_start': (month + RelativeDateTime(day=1)).strftime('%Y-%m-%d')}, context=context)
376
342
                    else:
377
343
                        item_obj.write(cr, uid, [item_id], {'period_start': report.date_from}, context=context)
378
 
                        # Uncomment the first line if you want products already expired in the first month
379
 
                        #domain.append(('life_date', '>=', month.strftime('%Y-%m-01')))
380
 
                        # Comment line if you want all products already expired
381
 
                        #if not context.get('only_product_ids'):
382
 
                        #    domain.append(('life_date', '>=', month.strftime('%Y-%m-%d')))
383
 
                        
384
344
 
385
345
                    # Remove the token after the first month processing
386
346
                    start_month_flag = False
428
388
                                                               'lot_id': product_lot.id,
429
389
                                                               'location_id': location,
430
390
                                                               'available_qty': product2.qty_available,
431
 
                                                               'expired_qty': new_lot_expired}, context=context)
 
391
                                                               'expired_qty': new_lot_expired})
432
392
                            
433
393
                        available_qty += product.qty_available
434
394
                            
457
417
                'target': 'dummy'}
458
418
        
459
419
        
460
 
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
 
420
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context={}, toolbar=False, submenu=False):
461
421
        if not context:
462
422
            context = {}
463
423
            
502
462
            self.date = date
503
463
            return self.go_to_item
504
464
        else:
505
 
            return super(product_likely_expire_report_line, self).__getattr__(name, *args, **kwargs)
 
465
            return self.name
506
466
    
507
 
    def fields_get(self, cr, uid, fields=None, context=None):
 
467
    def fields_get(self, cr, uid, fields=None, context={}):
508
468
        if not context:
509
469
            context = {}
510
470
            
519
479
            
520
480
        return res
521
481
    
522
 
    def go_to_item(self, cr, uid, ids, context=None):
 
482
    def go_to_item(self, cr, uid, ids, context={}):
523
483
        if not context:
524
484
            context = {}
525
485
            
540
500
                'target': 'new'}
541
501
        
542
502
            
543
 
    def read(self, cr, uid, ids, vals, context=None, load='_classic_read'):
 
503
    def read(self, cr, uid, ids, vals, context={}, load='_classic_read'):
544
504
        '''
545
505
        Set values for all dates
546
506
        '''
587
547
    
588
548
    _columns = {
589
549
            'item_id': fields.many2one('product.likely.expire.report.item', strig='Item', ondelete='cascade'),
590
 
            'lot_id': fields.many2one('stock.production.lot', string='Batch number'),
 
550
            'lot_id': fields.many2one('stock.production.lot', string='Lot'),
591
551
            'location_id': fields.many2one('stock.location', string='Location'),
592
552
            'available_qty': fields.float(digits=(16,2), string='Available Qty.'),
593
553
            'expired_qty': fields.float(digits=(16,2), string='Expired Qty.'),
601
561
    _name = 'product.product'
602
562
    _inherit = 'product.product'
603
563
    
604
 
    def get_expiry_qty(self, cr, uid, product_id, location_id, monthly_consumption, d_values=None, context=None):
 
564
    def get_expiry_qty(self, cr, uid, product_id, location_id, monthly_consumption, context={}):
605
565
        '''
606
566
        Get the expired quantity of product
607
567
        '''
608
 
        if context is None:
609
 
            context = {}
610
 
 
611
 
        if d_values is None:
612
 
            d_values = {}
 
568
        move_obj = self.pool.get('stock.move')
 
569
        uom_obj = self.pool.get('product.uom')
 
570
        product_obj = self.pool.get('product.product')
 
571
        lot_obj = self.pool.get('stock.production.lot')
 
572
        stock_obj = self.pool.get('stock.location')
613
573
        
614
 
        monthly_consumption = 'rac'
 
574
        monthly_consumption = 0.00
615
575
        
616
576
        # Get the monthly consumption
617
 
        if d_values.get('reviewed_consumption', False):
618
 
            monthly_consumption = 'fmc'
619
 
        elif d_values.get('past_consumption', False):
620
 
            monthly_consumption = 'amc'
 
577
        if context.get('reviewed_consumption', False):
 
578
            monthly_consumption = product_obj.browse(cr, uid, product_id, context=context).reviewed_consumption
 
579
        elif context.get('monthly_consumption', False):
 
580
            monthly_consumption = product_obj.browse(cr, uid, product_id, context=context).monthly_consumption
621
581
        else:
622
 
            monthly_consumption = d_values.get('manual_consumption', 0.00)
623
 
            context.update({'manual_consumption': monthly_consumption})
624
 
 
625
 
        product = self.browse(cr, uid, product_id, context=context)
626
 
        # Get the delivery lead time of the product if the leadtime is not defined in rule and no supplier found in product form
627
 
        delivery_leadtime = product.procure_delay and round(int(product.procure_delay)/30.0, 2) or 1
628
 
        # Get the leadtime of the rule if defined
629
 
        if 'leadtime' in d_values and d_values.get('leadtime', 0.00) != 0.00:
630
 
            delivery_leadtime = d_values.get('leadtime')
631
 
        elif product.seller_ids:
632
 
            # Get the supplier lead time if supplier is defined
633
 
            # The seller delay is defined in days, so divide it by 30.0 to have a LT in months
634
 
            delivery_leadtime = product.seller_delay and round(int(product.seller_delay)/30.0, 2) or 1
635
 
            
636
 
        delta = (delivery_leadtime + d_values.get('coverage', 0.00))*30.0
637
 
 
638
 
        report_data = {'date_from': today().strftime('%Y-%m-%d'),
639
 
                       'date_to': (today() + RelativeDateTime(days=delta)).strftime('%Y-%m-%d'),
640
 
                       'consumption_type': monthly_consumption,
641
 
                       'consumption_from': d_values.get('consumption_period_from'),
642
 
                       'consumption_to': d_values.get('consumption_period_to'),
643
 
                       'location_id': location_id}
644
 
 
645
 
        report_obj = self.pool.get('product.likely.expire.report')
646
 
        line_obj = self.pool.get('product.likely.expire.report.line')
647
 
 
648
 
        exp_context = context.copy()
649
 
        exp_context.update({'only_product_ids': [product_id]})
650
 
        report_id = report_obj.create(cr, uid, report_data, context=exp_context)
651
 
        # Process report
652
 
        report_obj.process_lines(cr, uid, report_id, context=exp_context)
653
 
        
654
 
        lines = line_obj.search(cr, uid, [('report_id', '=', report_id)], context=context)
655
 
        for line in line_obj.browse(cr, uid, lines, context=context):
656
 
            if line.product_id.id == product_id:
657
 
                return line.total_expired
658
 
        
659
 
            
660
 
#        location_ids = stock_obj.search(cr, uid, [('location_id', 'child_of', location_id)])
661
 
#            
662
 
#        move_ids = move_obj.search(cr, uid, ['|', ('location_id', 'in', location_ids), ('location_dest_id', 'in', location_ids), 
663
 
#                                             ('product_id', '=', product_id), ('prodlot_id', '!=', False)], context=context)
664
 
#        
665
 
#        lots = []
666
 
#        for move in move_obj.browse(cr, uid, move_ids, context=context):
667
 
#            if not move.prodlot_id.id in lots:
668
 
#                lots.append(move.prodlot_id.id)
669
 
#        
670
 
#        # Get all lots for the product product_id
671
 
#        lot_ids = lot_obj.search(cr, uid, [('product_id', '=', product_id), ('stock_available', '>', 0.00), ('id', 'in', lots)], \
672
 
#                                order='life_date', context=context)
673
 
#
674
 
#
675
 
#        
676
 
#        # Sum of months before expiry
677
 
#        sum_ni = 0.00      
678
 
#        expired_qty = 0.00
679
 
#        last_date = now()
680
 
#        last_qty = False
681
 
#        
682
 
#        for lot in lot_obj.browse(cr, uid, lot_ids, context=context):
683
 
#            life_date = strptime(lot.life_date, '%Y-%m-%d')
684
 
#            rel_time = RelativeDateDiff(life_date, now())
685
 
#            ni = round((rel_time.months*30 + rel_time.days)/30.0, 2)
686
 
#            if last_qty == False:
687
 
#                last_qty = uom_obj._compute_qty(cr, uid, lot.product_id.uom_id.id, (ni-sum_ni)*monthly_consumption, lot.product_id.uom_id.id)
688
 
#            if last_date > life_date:
689
 
#                expired_qty = lot.stock_available                
690
 
#            elif ni - sum_ni > 0.00:
691
 
#                expired_qty += last_qty
692
 
#                last_qty = uom_obj._compute_qty(cr, uid, lot.product_id.uom_id.id, (ni-sum_ni)*monthly_consumption, lot.product_id.uom_id.id)
693
 
#                sum_ni += ni
694
 
#            else:
695
 
#                break
696
 
#        return expired_qty
 
582
            monthly_consumption = context.get('manual_consumption', 0.00)
 
583
            
 
584
        location_ids = stock_obj.search(cr, uid, [('location_id', 'child_of', location_id)])
 
585
            
 
586
        move_ids = move_obj.search(cr, uid, ['|', ('location_id', 'in', location_ids), ('location_dest_id', 'in', location_ids), 
 
587
                                             ('product_id', '=', product_id), ('prodlot_id', '!=', False)], context=context)
 
588
        
 
589
        lots = []
 
590
        for move in move_obj.browse(cr, uid, move_ids, context=context):
 
591
            if not move.prodlot_id.id in lots:
 
592
                lots.append(move.prodlot_id.id)
 
593
        
 
594
        # Get all lots for the product product_id
 
595
        lot_ids = lot_obj.search(cr, uid, [('product_id', '=', product_id), ('stock_available', '>', 0.00), ('id', 'in', lots)], \
 
596
                                order='life_date', context=context)
 
597
 
 
598
 
 
599
        
 
600
        # Sum of months before expiry
 
601
        sum_ni = 0.00      
 
602
        expired_qty = 0.00
 
603
        last_date = now()
 
604
        last_qty = False
 
605
        
 
606
        for lot in lot_obj.browse(cr, uid, lot_ids, context=context):
 
607
            life_date = strptime(lot.life_date, '%Y-%m-%d')
 
608
            rel_time = RelativeDateDiff(life_date, now())
 
609
            ni = round((rel_time.months*30 + rel_time.days)/30.0, 2)
 
610
            if last_qty == False:
 
611
                last_qty = uom_obj._compute_qty(cr, uid, lot.product_id.uom_id.id, (ni-sum_ni)*monthly_consumption, lot.product_id.uom_id.id)
 
612
            if last_date > life_date:
 
613
                expired_qty = lot.stock_available                
 
614
            elif ni - sum_ni > 0.00:
 
615
                expired_qty += last_qty
 
616
                last_qty = uom_obj._compute_qty(cr, uid, lot.product_id.uom_id.id, (ni-sum_ni)*monthly_consumption, lot.product_id.uom_id.id)
 
617
                sum_ni += ni
 
618
            else:
 
619
                break
 
620
        return expired_qty
697
621
    
698
622
product_product()
699
623