~unifield-team/unifield-wm/us-671-homere

« back to all changes in this revision

Viewing changes to threshold_value/threshold_value.py

[UF-43] fix added noupdate to demo data

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# -*- encoding: utf-8 -*-
3
 
##############################################################################
4
 
#
5
 
#    OpenERP, Open Source Management Solution
6
 
#    Copyright (C) 2011 TeMPO Consulting, MSF
7
 
#
8
 
#    This program is free software: you can redistribute it and/or modify
9
 
#    it under the terms of the GNU Affero General Public License as
10
 
#    published by the Free Software Foundation, either version 3 of the
11
 
#    License, or (at your option) any later version.
12
 
#
13
 
#    This program is distributed in the hope that it will be useful,
14
 
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
#    GNU Affero General Public License for more details.
17
 
#
18
 
#    You should have received a copy of the GNU Affero General Public License
19
 
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 
#
21
 
##############################################################################
22
 
 
23
 
from osv import osv
24
 
from osv import fields
25
 
from tools.translate import _
26
 
 
27
 
from mx.DateTime import DateFrom
28
 
from mx.DateTime import now
29
 
from mx.DateTime import RelativeDate
30
 
 
31
 
class threshold_value(osv.osv):
32
 
    _name = 'threshold.value'
33
 
    _description = 'Threshold value'
34
 
    
35
 
    def _get_product_ids(self, cr, uid, ids, field_name, arg, context=None):
36
 
        '''
37
 
        Returns a list of products for the rule
38
 
        '''
39
 
        res = {}
40
 
        
41
 
        for rule in self.browse(cr, uid, ids, context=context):
42
 
            res[rule.id] = []
43
 
            for line in rule.line_ids:
44
 
                res[rule.id].append(line.product_id.id)
45
 
        
46
 
        return res
47
 
    
48
 
    def _src_product_ids(self, cr, uid, obj, name, args, context=None):
49
 
        if not context:
50
 
            context = {}
51
 
            
52
 
        res = []
53
 
            
54
 
        for arg in args:
55
 
            if arg[0] == 'product_ids':
56
 
                rule_ids = []
57
 
                line_ids = self.pool.get('threshold.value.line').search(cr, uid, [('product_id', arg[1], arg[2])])
58
 
                for l in self.pool.get('threshold.value.line').browse(cr, uid, line_ids):
59
 
                    if l.threshold_value_id.id not in rule_ids:
60
 
                        rule_ids.append(l.threshold_value_id.id)
61
 
                res.append(('id', 'in', rule_ids))
62
 
                
63
 
        return res
64
 
    
65
 
    _columns = {
66
 
        'name': fields.char(size=128, string='Reference', required=True),
67
 
        'active': fields.boolean(string='Active'),
68
 
        'warehouse_id': fields.many2one('stock.warehouse', string='Warehouse', required=True),
69
 
        'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete="cascade", 
70
 
                                       domain="[('is_replenishment', '=', warehouse_id)]",
71
 
                                       help='Location where the computation is made'),
72
 
        'compute_method': fields.selection([('fixed', 'Fixed values'), ('computed', 'Computed values')],
73
 
                                           string='Method of computation', required=True,
74
 
                                           help="""If 'Fixed values', the scheduler will compare stock of product with the threshold value of the line. \n
75
 
                                           If 'Computed values', the threshold value and the ordered quantity will be calculated according to defined parameters"""),
76
 
        'consumption_method': fields.selection([('amc', 'Average Monthly Consumption'), ('fmc', 'Forecasted Monthly Consumption')],
77
 
                                               string='Consumption Method',
78
 
                                               help='Method used to compute the consumption of products.'),
79
 
        'consumption_period_from': fields.date(string='Period of calculation', 
80
 
                                             help='This period is a number of past months the system has to consider for AMC calculation.'\
81
 
                                             'By default this value is equal to the frequency in the Threshold.'),
82
 
        'consumption_period_to': fields.date(string='-'),
83
 
        'frequency': fields.float(digits=(16,2), string='Order frequency', 
84
 
                                  help='The time between two replenishments. Will be used to compute the quantity to order.'),
85
 
        'safety_month': fields.float(digits=(16,2), string='Safety Stock in months',
86
 
                                     help='In months. Period during the stock is not empty but need to be replenish. \
87
 
                                     Used to compute the quantity to order.'),
88
 
        'lead_time': fields.float(digits=(16,2), string='Fixed Lead Time in months',
89
 
                                  help='In months. Time to be delivered after processing the purchase order.'),
90
 
        'supplier_lt': fields.boolean(string='Product\'s supplier LT',
91
 
                                      help='If checked, use the lead time set in the supplier form.'),
92
 
        'line_ids': fields.one2many('threshold.value.line', 'threshold_value_id', string="Products"),
93
 
        'fixed_line_ids': fields.one2many('threshold.value.line', 'threshold_value_id2', string="Products"),
94
 
        'product_ids': fields.function(_get_product_ids, fnct_search=_src_product_ids, 
95
 
                                    type='many2many', relation='product.product', method=True, string='Products'),
96
 
        'sublist_id': fields.many2one('product.list', string='List/Sublist', ondelete='set null'),
97
 
        'nomen_manda_0': fields.many2one('product.nomenclature', 'Main Type', ondelete='set null'),
98
 
        'nomen_manda_1': fields.many2one('product.nomenclature', 'Group', ondelete='set null'),
99
 
        'nomen_manda_2': fields.many2one('product.nomenclature', 'Family', ondelete='set null'),
100
 
        'nomen_manda_3': fields.many2one('product.nomenclature', 'Root', ondelete='set null'),
101
 
    }
102
 
    
103
 
    _defaults = {
104
 
        'name': lambda obj, cr, uid, context=None: obj.pool.get('ir.sequence').get(cr, uid, 'threshold.value') or '',
105
 
        'active': lambda *a: True,
106
 
        'frequency': lambda *a: 3,
107
 
        'consumption_method': lambda *a: 'amc',
108
 
        'consumption_period_from': lambda *a: (now() + RelativeDate(day=1, months=-2)).strftime('%Y-%m-%d'),
109
 
        'consumption_period_to': lambda *a: (now() + RelativeDate(day=1)).strftime('%Y-%m-%d'),
110
 
    }
111
 
    
112
 
    def copy(self, cr, uid, ids, defaults={}, context=None):
113
 
        '''
114
 
        Increment the sequence
115
 
        '''
116
 
        name = self.pool.get('ir.sequence').get(cr, uid, 'threshold.value') or ''
117
 
        defaults.update({'name': name})
118
 
        
119
 
        return super(threshold_value, self).copy(cr, uid, ids, defaults, context=context)
120
 
    
121
 
    def default_get(self, cr, uid, fields, context=None):
122
 
        '''
123
 
        Get the default values for the replenishment rule
124
 
        '''
125
 
        res = super(threshold_value, self).default_get(cr, uid, fields, context=context)
126
 
        
127
 
        company_id = res.get('company_id')
128
 
        warehouse_id = res.get('warehouse_id')
129
 
        
130
 
        if not 'company_id' in res:
131
 
            company_id = self.pool.get('res.company')._company_default_get(cr, uid, 'stock.warehouse.automatic.supply', context=context)
132
 
            res.update({'company_id': company_id})
133
 
        
134
 
        if not 'warehouse_id' in res:
135
 
            warehouse_id = self.pool.get('stock.warehouse').search(cr, uid, [('company_id', '=', company_id)], context=context)[0]
136
 
            res.update({'warehouse_id': warehouse_id})
137
 
            
138
 
        if not 'location_id' in res:
139
 
            location_id = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context).lot_stock_id.id
140
 
            res.update({'location_id': location_id})
141
 
        
142
 
        return res
143
 
    
144
 
    def onchange_warehouse_id(self, cr, uid, ids, warehouse_id, context=None):
145
 
        """ Finds default stock location id for changed warehouse.
146
 
        @param warehouse_id: Changed id of warehouse.
147
 
        @return: Dictionary of values.
148
 
        """
149
 
        if warehouse_id:
150
 
            w = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context)
151
 
            v = {'location_id': w.lot_stock_id.id}
152
 
            return {'value': v}
153
 
        return {}
154
 
    
155
 
    def on_change_method(self, cr, uid, ids, method):
156
 
        '''
157
 
        Unfill the consumption period if the method is FMC
158
 
        '''
159
 
        res = {}
160
 
        
161
 
        if method and method == 'fmc':
162
 
            res.update({'consumption_period_from': False, 'consumption_period_to': False})
163
 
        elif method and method == 'amc':
164
 
            res.update({'consumption_period_from': (now() + RelativeDate(day=1, months=-2)).strftime('%Y-%m-%d'),
165
 
                        'consumption_period_to': (now() + RelativeDate(day=1, months=1, days=-1)).strftime('%Y-%m-%d')})
166
 
        
167
 
        return {'value': res}
168
 
    
169
 
    def on_change_period(self, cr, uid, ids, from_date, to_date):
170
 
        '''
171
 
        Check if the from date is younger than the to date
172
 
        '''
173
 
        warn = {}
174
 
        val = {}
175
 
        
176
 
        if from_date and to_date and from_date > to_date:
177
 
            warn = {'title': 'Issue on date',
178
 
                    'message': 'The start date must be younger than end date'}
179
 
            
180
 
        if from_date:
181
 
            val.update({'consumption_period_from': (DateFrom(from_date) + RelativeDate(day=1)).strftime('%Y-%m-%d')})
182
 
            
183
 
        if to_date:
184
 
            val.update({'consumption_period_to': (DateFrom(to_date) + RelativeDate(months=1, day=1, days=-1)).strftime('%Y-%m-%d')})
185
 
        
186
 
        return {'value': val, 'warning': warn}
187
 
    
188
 
    ##############################################################################################################################
189
 
    # The code below aims to enable filtering products regarding their sublist or their nomenclature.
190
 
    # Then, we fill lines of the one2many object 'threshold.value.line' according to the filtered products
191
 
    ##############################################################################################################################
192
 
    def onChangeSearchNomenclature(self, cr, uid, id, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, num=True, context=None):
193
 
        return 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})
194
 
 
195
 
    def fill_lines(self, cr, uid, ids, context=None):
196
 
        '''
197
 
        Fill all lines according to defined nomenclature level and sublist
198
 
        '''
199
 
        if context is None:
200
 
            context = {}
201
 
        for report in self.browse(cr, uid, ids, context=context):
202
 
            product_ids = []
203
 
            products = []
204
 
            nom = False
205
 
            field = False
206
 
            # Get all products for the defined nomenclature
207
 
            if report.nomen_manda_3:
208
 
                nom = report.nomen_manda_3.id
209
 
                field = 'nomen_manda_3'
210
 
            elif report.nomen_manda_2:
211
 
                nom = report.nomen_manda_2.id
212
 
                field = 'nomen_manda_2'
213
 
            elif report.nomen_manda_1:
214
 
                nom = report.nomen_manda_1.id
215
 
                field = 'nomen_manda_1'
216
 
            elif report.nomen_manda_0:
217
 
                nom = report.nomen_manda_0.id
218
 
                field = 'nomen_manda_0'
219
 
            if nom:
220
 
                product_ids.extend(self.pool.get('product.product').search(cr, uid, [(field, '=', nom)], context=context))
221
 
 
222
 
            # Get all products for the defined list
223
 
            if report.sublist_id:
224
 
                for line in report.sublist_id.product_ids:
225
 
                    product_ids.append(line.name.id)
226
 
 
227
 
            # Check if products in already existing lines are in domain
228
 
            products = []
229
 
            for line in report.line_ids:
230
 
                if line.product_id.id in product_ids:
231
 
                    products.append(line.product_id.id)
232
 
                else:
233
 
                    self.pool.get('threshold.value.line').unlink(cr, uid, line.id, context=context)
234
 
 
235
 
            for product in self.pool.get('product.product').browse(cr, uid, product_ids, context=context):
236
 
                # Check if the product is not already on the report
237
 
                if product.type not in ('consu', 'service', 'service_recep') and product.id not in products:
238
 
                    self.pool.get('threshold.value.line').create(cr, uid, {'product_id': product.id,
239
 
                                                                                            'product_uom_id': product.uom_id.id,
240
 
                                                                                            'product_qty': 1.00,
241
 
                                                                                            'threshold_value_id': report.id})
242
 
        return {'type': 'ir.actions.act_window',
243
 
                'res_model': 'threshold.value',
244
 
                'view_type': 'form',
245
 
                'view_mode': 'form',
246
 
                'res_id': ids[0],
247
 
                'target': 'dummy',
248
 
                'context': context}
249
 
        
250
 
    def dummy(self, cr, uid, ids, context=None):
251
 
        return True
252
 
 
253
 
    def get_nomen(self, cr, uid, id, field):
254
 
        return self.pool.get('product.nomenclature').get_nomen(cr, uid, self, id, field, context={'withnum': 1})
255
 
 
256
 
    def write(self, cr, uid, ids, vals, context=None):
257
 
        if vals.get('sublist_id',False):
258
 
            vals.update({'nomen_manda_0':False,'nomen_manda_1':False,'nomen_manda_2':False,'nomen_manda_3':False})
259
 
        if vals.get('nomen_manda_0',False):
260
 
            vals.update({'sublist_id':False})
261
 
        ret = super(threshold_value, self).write(cr, uid, ids, vals, context=context)
262
 
        return ret
263
 
 
264
 
    def on_change_compute_method(self, cr, uid, ids, compute_method,
265
 
        context=None):
266
 
        res = {}
267
 
        if compute_method and compute_method == 'computed':
268
 
            # UF-2511: switch from 'fixed' to 'compute' compute method
269
 
            # warn user to refresh values
270
 
            # (are not any more computed in 'fixed' mode)
271
 
            msg = "You switch from 'fixed values' to 'computed values'. " \
272
 
                "Please click on 'Refresh values' button to compute values."
273
 
            res = {
274
 
                'warning': {
275
 
                    'title': _('Warning'),
276
 
                    'message': _(msg),
277
 
                    },
278
 
            }
279
 
        return res
280
 
 
281
 
threshold_value()
282
 
 
283
 
class threshold_value_line(osv.osv):
284
 
    _name = 'threshold.value.line'
285
 
    _description = 'Threshold Value Line'
286
 
    _rec_name = 'product_id'
287
 
    
288
 
    def copy_data(self, cr, uid, ids, defaults={}, context=None):
289
 
        res = super(threshold_value_line, self).copy_data(cr, uid, ids, defaults, context=context)
290
 
        
291
 
        if isinstance(res, dict):
292
 
            if 'threshold_value_id' in res:
293
 
                del res['threshold_value_id']
294
 
            if 'threshold_value_id2' in res:
295
 
                del res['threshold_value_id2']
296
 
        
297
 
        return res
298
 
    
299
 
    def create(self, cr, uid, vals, context=None):
300
 
        '''
301
 
        Add the second link to the threshold value rule
302
 
        '''
303
 
        if 'threshold_value_id' in vals:
304
 
            vals.update({'threshold_value_id2': vals['threshold_value_id']})
305
 
        elif 'threshold_value_id2' in vals:
306
 
            vals.update({'threshold_value_id': vals['threshold_value_id2']})
307
 
        
308
 
        return super(threshold_value_line, self).create(cr, uid, vals, context=context)
309
 
    
310
 
    def write(self, cr, uid, ids, vals, context=None):
311
 
        '''
312
 
        Add the second link to the threshold value rule
313
 
        '''
314
 
        if 'threshold_value_id' in vals:
315
 
            vals.update({'threshold_value_id2': vals['threshold_value_id']})
316
 
        elif 'threshold_value_id2' in vals:
317
 
            vals.update({'threshold_value_id': vals['threshold_value_id2']})
318
 
            
319
 
        context.update({'fake_threshold_value': vals.get('fake_threshold_value', False)})
320
 
        vals.update({'fake_threshold_value': 0.00})
321
 
        
322
 
        return super(threshold_value_line, self).write(cr, uid, ids, vals, context=context)
323
 
    
324
 
    def _get_values(self, cr, uid, ids, field_name, arg, context=None):
325
 
        '''
326
 
        Compute and return the threshold value and qty to order
327
 
        '''
328
 
        res = {}
329
 
        if context is None:
330
 
            context = {}
331
 
        
332
 
        for line in self.browse(cr, uid, ids, context=context):
333
 
            if context.get('fake_threshold_value', False):
334
 
                res[line.id] = context.get('fake_threshold_value', 0.00)
335
 
                continue 
336
 
            res[line.id] = 0.00
337
 
            
338
 
            rule = line.threshold_value_id
339
 
            context.update({'location_id': rule.location_id.id, 'compute_child': True})
340
 
            product = self.pool.get('product.product').browse(cr, uid, line.product_id.id, context=context)
341
 
            result = self._get_threshold_value(cr, uid, line.id, product, rule.compute_method, rule.consumption_method, 
342
 
                                                     rule.consumption_period_from, rule.consumption_period_to, rule.frequency, 
343
 
                                                     rule.safety_month, rule.lead_time, rule.supplier_lt, line.product_uom_id.id, context)
344
 
            res[line.id] = result.get(field_name, 0.00) 
345
 
        
346
 
        return res
347
 
 
348
 
    
349
 
    def _get_threshold(self, cr, uid, ids, context={}):
350
 
        res = {}
351
 
        for t in self.pool.get('threshold.value').browse(cr, uid, ids, context=context):
352
 
            for l in t.line_ids:
353
 
                res[l.id] = True
354
 
                
355
 
        return res.keys()
356
 
        
357
 
    def _get_data(self, cr, uid, ids, field_name, args, context=None):
358
 
        '''
359
 
        Compute some data
360
 
        '''
361
 
        product_obj = self.pool.get('product.product')
362
 
        proc_obj = self.pool.get('procurement.order')
363
 
 
364
 
        if isinstance(ids, (int, long)):
365
 
            ids = [ids]
366
 
 
367
 
        res = {}
368
 
 
369
 
        for line in self.browse(cr, uid, ids, context=context):
370
 
            if context and context.get('compute_method', False) == 'fixed':
371
 
                # UF-2511: do not compute in 'fixed' compute method mode
372
 
                res[line.id] = {
373
 
                    'consumption': 0.,
374
 
                    'real_stock': 0.,
375
 
                    'available_stock': 0.,
376
 
                    'expiry_before': False,
377
 
                    'supplier_id': False,
378
 
                    'required_date': False,
379
 
                }
380
 
                continue
381
 
 
382
 
            # Stock values
383
 
            location_id = line.threshold_value_id.location_id.id
384
 
            stock_product = product_obj.browse(cr, uid, line.product_id.id, context=dict(context, location=location_id))
385
 
            # Consumption values
386
 
            from_date = line.threshold_value_id.consumption_period_from
387
 
            to_date = line.threshold_value_id.consumption_period_to
388
 
            consu_product = product_obj.browse(cr, uid, line.product_id.id, context=dict(context, from_date=from_date, to_date=to_date))
389
 
            consu = 0.00
390
 
            if line.threshold_value_id.consumption_method == 'amc':
391
 
                consu = consu_product.product_amc
392
 
            elif line.threshold_value_id.consumption_method == 'fmc':
393
 
                consu = consu_product.reviewed_consumption
394
 
            else:
395
 
                consu = 0.00
396
 
 
397
 
            # Expiry values
398
 
            d_values = {'reviewed_consumption': line.threshold_value_id.consumption_method == 'fmc',
399
 
                        'past_consumption': line.threshold_value_id.consumption_method == 'amc',
400
 
                        'manual_consumption': 0.00,
401
 
                        'consumption_period_from': line.threshold_value_id.consumption_period_from,
402
 
                        'consumption_period_to': line.threshold_value_id.consumption_period_to,
403
 
                        'leadtime': line.threshold_value_id.lead_time,
404
 
                        'coverage': line.threshold_value_id.frequency,
405
 
                        'safety_stock': 0.00,
406
 
                        'safety_time': line.threshold_value_id.safety_month}
407
 
            expiry_product_qty = product_obj.get_expiry_qty(cr, uid, line.product_id.id, location_id, False, d_values, context=dict(context, location=location_id, compute_child=True))
408
 
 
409
 
            new_context = context.copy()
410
 
            new_context.update({'from_date': from_date,
411
 
                                'to_date': to_date,
412
 
                                'get_data': True,
413
 
                                'consumption_period_from': d_values['consumption_period_from'],
414
 
                                'consumption_period_to': d_values['consumption_period_to'],})
415
 
 
416
 
            qty_to_order, req_date = proc_obj._compute_quantity(cr, uid, False, line.product_id, line.threshold_value_id.location_id.id, d_values, context=new_context)
417
 
 
418
 
            res[line.id] = {'consumption': consu,
419
 
                            'real_stock': stock_product.qty_available,
420
 
                            'available_stock': stock_product.virtual_available,
421
 
                            'expiry_before': expiry_product_qty,
422
 
                            'supplier_id': stock_product.seller_id.id,
423
 
                            'required_date': req_date,
424
 
                            }
425
 
 
426
 
        return res
427
 
    
428
 
    _columns = {
429
 
        'product_id': fields.many2one('product.product', string='Product', required=True),
430
 
        'product_uom_id': fields.many2one('product.uom', string='Product UoM', required=True),
431
 
        'product_qty': fields.function(_get_values, method=True, type='float', string='Quantity to order'),
432
 
        'fake_threshold_value': fields.float(digits=(16,2), string='Threshold value'),
433
 
        'threshold_value': fields.function(_get_values, method=True, type='float', string='Threshold value',
434
 
                                           store={'threshold.value.line': (lambda self, cr, uid, ids, c=None: ids, ['product_id'],20),
435
 
                                                  'threshold.value': (_get_threshold, ['compute_method',
436
 
                                                                                       'consumption_method',
437
 
                                                                                       'consumption_period_from',
438
 
                                                                                       'consumption_period_to',
439
 
                                                                                       'frequency',
440
 
                                                                                       'safety_month',
441
 
                                                                                       'lead_time',
442
 
                                                                                       'supplier_lt'], 10)}),
443
 
        'fixed_product_qty': fields.float(digits=(16,2), string='Quantity to order'),
444
 
        'fixed_threshold_value': fields.float(digits=(16,2), string='Threshold value'),
445
 
        'threshold_value_id': fields.many2one('threshold.value', string='Threshold', ondelete='cascade', required=True),
446
 
        'threshold_value_id2': fields.many2one('threshold.value', string='Threshold', ondelete='cascade', required=True),
447
 
        'consumption': fields.function(_get_data, method=True, type='float', digits=(16,3), string='AMC/FMC', multi='data', readonly=True),
448
 
        'real_stock': fields.function(_get_data, method=True, type='float', digits=(16,3), string='Real stock', multi='data', readonly=True),
449
 
        'available_stock': fields.function(_get_data, method=True, type='float', digits=(16,3), string='Available stock', multi='data', readonly=True),
450
 
        'expiry_before': fields.function(_get_data, method=True, type='float', digits=(16,3), string='Exp. before consumption', multi='data', readonly=True),
451
 
        'supplier_id': fields.function(_get_data, method=True, type='many2one', relation='res.partner', string='Supplier', multi='data', readonly=True),
452
 
        'required_date': fields.function(_get_data, method=True, type='date', string='Required by date', multi='data', readonly=True),
453
 
    }
454
 
    
455
 
    def _check_uniqueness(self, cr, uid, ids, context=None):
456
 
        '''
457
 
        Check if the product is not already in the current rule
458
 
        '''
459
 
        for line in self.browse(cr, uid, ids, context=context):
460
 
            lines = self.search(cr, uid, [('id', '!=', line.id), 
461
 
                                          ('product_id', '=', line.product_id.id),
462
 
                                          '|',
463
 
                                          ('threshold_value_id2', '=', line.threshold_value_id2.id),
464
 
                                          ('threshold_value_id', '=', line.threshold_value_id.id)], context=context)
465
 
            if lines:
466
 
                return False
467
 
            
468
 
        return True
469
 
    
470
 
    _constraints = [
471
 
        (_check_uniqueness, 'You cannot have two times the same product on the same threshold value rule', ['product_id'])
472
 
    ]
473
 
    
474
 
    def _get_threshold_value(self, cr, uid, line_id, product, compute_method, consumption_method,
475
 
                                consumption_period_from, consumption_period_to, frequency,
476
 
                                safety_month, lead_time, supplier_lt, uom_id, context=None):
477
 
        '''
478
 
        Return the threshold value and ordered qty of a product line
479
 
        '''
480
 
        if not context:
481
 
            context = {}
482
 
 
483
 
        if line_id and isinstance(line_id, list):
484
 
            line_id = line_id[0]
485
 
        
486
 
        cons = 0.00
487
 
        threshold_value = 0.00
488
 
        qty_to_order = 0.00
489
 
        if compute_method == 'computed':
490
 
            # Get the product available before change the context (from_date and to_date in context)
491
 
            product_available = product.qty_available
492
 
            
493
 
            # Change the context to compute consumption
494
 
            c = context.copy()
495
 
            c.update({'from_date': consumption_period_from, 'to_date': consumption_period_to})
496
 
            product = self.pool.get('product.product').browse(cr, uid, product.id, context=c)
497
 
            cons = consumption_method == 'fmc' and product.reviewed_consumption or product.product_amc
498
 
            
499
 
            # Set lead time according to choices in threshold rule (supplier or manual lead time)
500
 
            lt = supplier_lt and float(product.seller_delay)/30.0 or lead_time
501
 
                
502
 
            # Compute the threshold value
503
 
            threshold_value = cons * (lt + safety_month)
504
 
            threshold_value = self.pool.get('product.uom')._compute_qty(cr, uid, product.uom_id.id, threshold_value, product.uom_id.id)
505
 
                
506
 
            # Compute the quantity to re-order
507
 
            qty_to_order = cons * (frequency + lt + safety_month)\
508
 
                            - product_available - product.incoming_qty + product.outgoing_qty 
509
 
            qty_to_order = self.pool.get('product.uom')._compute_qty(cr, uid, uom_id or product.uom_id.id, \
510
 
                                                                     qty_to_order, product.uom_id.id)
511
 
            qty_to_order = qty_to_order > 0.00 and qty_to_order or 0.00
512
 
        elif line_id:
513
 
            line = self.browse(cr, uid, line_id, context=context)
514
 
            threshold_value = line.fixed_threshold_value
515
 
            qty_to_order = line.fixed_product_qty
516
 
            
517
 
        return {'threshold_value': threshold_value, 'product_qty': qty_to_order}
518
 
 
519
 
    def onchange_product_id(self, cr, uid, ids, product_id, compute_method=False, consumption_method=False,
520
 
                                consumption_period_from=False, consumption_period_to=False, frequency=False,
521
 
                                safety_month=False, lead_time=False, supplier_lt=False, fixed_tv=0.00, 
522
 
                                fixed_qty=0.00, uom_id=False, field='product_id', context=None):
523
 
        """ Finds UoM for changed product.
524
 
        @param product_id: Changed id of product.
525
 
        @return: Dictionary of values.
526
 
        """
527
 
        if not context:
528
 
            context = {}
529
 
        
530
 
        res = {'value': {'product_uom_id': False,
531
 
                         'fake_threshold_value': 0.00,
532
 
                         'threshold_value': 0.00}}
533
 
        if product_id:
534
 
            prod = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
535
 
            if field == 'product_id':
536
 
                res['value'].update({'product_uom_id': prod.uom_id.id})
537
 
            elif uom_id:
538
 
                res['value'].update({'product_uom_id': uom_id})
539
 
            
540
 
            if compute_method:
541
 
                tv = self._get_threshold_value(cr, uid, ids, prod, compute_method, consumption_method,
542
 
                                               consumption_period_from, consumption_period_to, frequency,
543
 
                                               safety_month, lead_time, supplier_lt, uom_id or prod.uom_id.id, context=context)['threshold_value']
544
 
                res['value'].update({'fake_threshold_value': tv, 'threshold_value': tv})
545
 
 
546
 
                if prod.uom_id.id:
547
 
                    res = self.pool.get('product.uom')._change_round_up_qty(cr, uid, uom_id or prod.uom_id.id, tv, ['fixed_threshold_value', 'fixed_product_qty', 'threshold_value', 'fake_threshold_value'], result=res)
548
 
                if prod.uom_id.id and fixed_tv:
549
 
                    res = self.pool.get('product.uom')._change_round_up_qty(cr, uid, uom_id or prod.uom_id.id, fixed_tv, ['fixed_threshold_value'], result=res)
550
 
                if prod.uom_id.id and fixed_qty:
551
 
                    res = self.pool.get('product.uom')._change_round_up_qty(cr, uid, uom_id or prod.uom_id.id, fixed_tv, ['fixed_product_qty'], result=res)
552
 
 
553
 
        return res
554
 
 
555
 
    def onchange_uom_qty(self, cr, uid, ids, uom_id, tv_qty, product_qty):
556
 
        '''
557
 
        Check round of qty according to UoM
558
 
        '''
559
 
        res = {}
560
 
        uom_obj = self.pool.get('product.uom')
561
 
 
562
 
        if tv_qty:
563
 
            res = uom_obj._change_round_up_qty(cr, uid, uom_id, tv_qty, 'fixed_threshold_value', result=res)
564
 
 
565
 
        if product_qty:
566
 
            res = uom_obj._change_round_up_qty(cr, uid, uom_id, product_qty, 'fixed_product_qty', result=res)
567
 
 
568
 
        return res
569
 
 
570
 
threshold_value_line()