205
205
supplier_info_obj = self.pool.get('product.supplierinfo')
206
206
location_obj = self.pool.get('stock.location')
207
207
cycle_obj = self.pool.get('stock.warehouse.order.cycle')
208
review_obj = self.pool.get('monthly.review.consumption')
209
review_line_obj = self.pool.get('monthly.review.consumption.line')
209
product = product_obj.browse(cr, uid, product_id)
210
location = location_obj.browse(cr, uid, location_id)
211
product = product_obj.browse(cr, uid, product_id, context=context)
212
location = location_obj.browse(cr, uid, location_id, context=context)
213
215
# Get the delivery lead time
214
delivery_leadtime = product.procure_delay and product.procure_delay/30.0 or 1
216
delivery_leadtime = product.seller_delay and product.seller_delay != 'N/A' and round(int(product.seller_delay)/30.0, 2) or 1
215
217
if 'leadtime' in d_values and d_values.get('leadtime', 0.00) != 0.00:
216
218
delivery_leadtime = d_values.get('leadtime')
219
221
for supplier_info in product.seller_ids:
220
222
if sequence and supplier_info.sequence < sequence:
221
223
sequence = supplier_info.sequence
222
delivery_leadtime = supplier_info.delay/30.0
224
delivery_leadtime = round(supplier_info.delay/30.0, 2)
223
225
elif not sequence:
224
226
sequence = supplier_info.sequence
225
delivery_leadtime = supplier_info.delay/30.0
227
delivery_leadtime = round(supplier_info.delay/30.0, 2)
227
229
# Get the monthly consumption
228
monthly_consumption = 1.0
230
monthly_consumption = 0.00
230
if cycle_id.product_id and cycle_id.product_id.id and d_values.get('manual_consumption', 0.00) != 0.00:
231
monthly_consumption = d_values.get('manual_consumption')
232
elif 'reviewed_consumption' in d_values and d_values.get('reviewed_consumption'):
232
if 'reviewed_consumption' in d_values and d_values.get('reviewed_consumption'):
233
233
monthly_consumption = product.reviewed_consumption
234
elif 'monthly_consumption' in d_values and d_values.get('monthly_consumption'):
235
monthly_consumption = product.product_amc
235
monthly_consumption = product.monthly_consumption
237
monthly_consumption = d_values.get('manual_consumption', 0.00)
237
239
# Get the order coverage
238
240
order_coverage = d_values.get('coverage', 3)
240
242
# Get the projected available quantity
241
243
available_qty = self.get_available(cr, uid, product_id, location_id, monthly_consumption, d_values)
243
return (delivery_leadtime * monthly_consumption) + (order_coverage * monthly_consumption) - available_qty
245
qty_to_order = (delivery_leadtime * monthly_consumption) + (order_coverage * monthly_consumption) - available_qty
247
return round(self.pool.get('product.uom')._compute_qty(cr, uid, product.uom_id.id, qty_to_order, product.uom_id.id), 2)
246
250
def get_available(self, cr, uid, product_id, location_id, monthly_consumption, d_values={}, context={}):
273
278
# Get the available stock
274
279
# Get the real stock
275
# real_stock = product_obj.get_product_available(cr, uid, [product_id], context={'states': ['done'],
277
# 'location': location_id,
278
# 'compute_child': True,
279
# 'from_date': time.strftime('%Y-%m-%d')})
280
# # Get the picked reservation
281
# ## TODO: To confirm by Magali
280
picked_resa = product_obj.get_product_available(cr, uid, [product_id], context={'states': ['assigned'],
282
'location': location_id,
283
'compute_child': True,
284
'from_date': time.strftime('%Y-%m-%d')})
285
# Get the picked reservation
286
## TODO: To confirm by Magali
282
287
# picked_reservation = 0.00
284
289
# for location in location_obj.search(cr, uid, [('location_id', 'child_of', [location_id])]):
289
294
# for move in move_obj.browse(cr, uid, move_ids):
290
295
# picked_reservation += move.product_qty
292
# available_stock = real_stock.get(product_id) - picked_reservation
294
# # Get the quantity on order
295
# ## TODO : To confirm by Magali
297
available_stock = product.qty_available - picked_resa.get(product.id)
299
#available_stock = real_stock.get(product_id) - picked_reservation
301
# Get the quantity on order
302
## TODO : To confirm by Magali
296
303
# quantity_on_order = 0.00
298
305
# for location in location_obj.search(cr, uid, [('location_id', 'child_of', [location_id])]):
311
324
# Get the expiry quantity
312
325
# Set as comment because expiry quantity will be developed in a future sprint
313
# expiry_quantity = self.get_expiry_qty(cr, uid, product_id, location_id, monthly_consumption, d_values)
314
expiry_quantity = 0.00
326
expiry_quantity = product_obj.get_expiry_qty(cr, uid, product_id, location_id, monthly_consumption, d_values)
327
expiry_quantity = expiry_quantity and available_stock - expiry_quantity or 0.00
328
#expiry_quantity = 0.00
316
330
# Set this part of algorithm as comments because this algorithm seems to be equal to virtual stock
317
# return available_stock + quantity_on_order - safety_stock - (safety_time * monthly_consumption) - expiry_quantity
331
return available_stock + quantity_on_order.get(product.id) - safety_stock - (safety_time * monthly_consumption) - expiry_quantity
319
return product.virtual_available - safety_stock - (safety_time * monthly_consumption) - expiry_quantity
322
def get_expiry_qty(self, cr, uid, product_id, location_id, monthly_consumption, d_values={}, context={}):
324
Compute the expiry quantities
326
INFO : This method is not use on Sprint1 because the algorithm is
329
product_obj = self.pool.get('product.product')
330
stock_obj = self.pool.get('stock.location')
331
batch_obj = self.pool.get('stock.production.lot')
332
move_obj = self.pool.get('stock.move')
336
location_ids = stock_obj.search(cr, uid, [('location_id', 'child_of', location_id)])
337
available_stock = 0.00
339
# Get all batches for this product
340
batch_ids = batch_obj.search(cr, uid, [('product_id', '=', product_id)], offset=0, limit=None, order='life_date')
341
if len(batch_ids) == 1:
342
# Search all moves with this batch number
343
for location in location_ids:
344
context.update({'location_id': location})
345
available_stock += batch_obj.browse(cr, uid, batch_ids, context=context)[0].stock_available
346
expiry_date = batch_obj.browse(cr, uid, batch_ids)[0].life_date or time.strftime('%Y-%m-%d')
347
nb_month = self.get_diff_date(expiry_date)
348
res = available_stock - (nb_month * monthly_consumption)
350
# Get the stock available for the product
351
for location in location_ids:
352
context.update({'location_id': location})
353
for batch in batch_obj.browse(cr, uid, batch_ids, context=context):
354
available_stock += batch.stock_available
359
for batch in batch_obj.browse(cr, uid, batch_ids):
360
nb_month = self.get_diff_date(batch.life_date)
361
if (nb_month - sum_nb_month) > 0:
362
tmp_qty = (nb_month - sum_nb_month) * monthly_consumption
363
res += available_stock - (last_nb_month * monthly_consumption) - tmp_qty
333
# return product.virtual_available - safety_stock - (safety_time * monthly_consumption) - expiry_quantity
369
335
def get_diff_date(self, date):
371
337
Returns the number of month between the date in parameter and today
373
339
date = Parser.DateFromString(date)
340
today = datetime.today()
376
342
# The batch is expired
377
343
if date.year < today.year or (date.year == today.year and date.month < today.month):