Merge lp:~openbig/bigconsulting/order_point_calcultor into lp:bigconsulting

Proposed by gpa(OpenERP)
Status: Superseded
Proposed branch: lp:~openbig/bigconsulting/order_point_calcultor
Merge into: lp:bigconsulting
Diff against target: 432 lines (+247/-129)
2 files modified
stock_minimum_calculator/stock_minimum_calculator_wizard.xml (+1/-1)
stock_minimum_calculator/wizard/stock_order_point_calculator.py (+246/-128)
To merge this branch: bzr merge lp:~openbig/bigconsulting/order_point_calcultor
Reviewer Review Type Date Requested Status
openbig Pending
Review via email: mp+32737@code.launchpad.net

This proposal supersedes a proposal from 2010-08-16.

This proposal has been superseded by a proposal from 2010-08-16.

Description of the change

improvement in order point calculator wizard bug 615927

To post a comment you must log in.
78. By gpa(OpenERP)

improvement

79. By gpa(OpenERP)

optimzation in wizard order point calculator

80. By gpa(OpenERP)

optimization in stock order point wizard

81. By gpa(OpenERP)

optimization in stock order point wizard

82. By gpa(OpenERP)

improvement for automatically increment in scanned quantity and real quantity

83. By gpa(OpenERP)

changes in first condition of date

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'stock_minimum_calculator/stock_minimum_calculator_wizard.xml'
2--- stock_minimum_calculator/stock_minimum_calculator_wizard.xml 2010-07-27 09:27:59 +0000
3+++ stock_minimum_calculator/stock_minimum_calculator_wizard.xml 2010-08-16 09:23:39 +0000
4@@ -9,7 +9,7 @@
5 id="id_set_seasonal_trend"/>
6 <wizard
7 string="Order Point Cacluator"
8- model="product.product"
9+ model="res.partner"
10 name="orderpoint.calculator"
11 menu="True"
12 id="id_order_point_cacluator"/>
13
14=== modified file 'stock_minimum_calculator/wizard/stock_order_point_calculator.py'
15--- stock_minimum_calculator/wizard/stock_order_point_calculator.py 2010-08-04 13:12:02 +0000
16+++ stock_minimum_calculator/wizard/stock_order_point_calculator.py 2010-08-16 09:23:39 +0000
17@@ -34,13 +34,9 @@
18 <field name="warehouse_id"/>
19 <field name="location_id"/>
20 <field name="seasonal_id"/>
21+ <field name="max_qty_factor"/>
22 <field name="delactive"/>
23 <field name="method_qty_calculation" colspan="4"/>
24- <group attrs="{'invisible':[('method_qty_calculation','=','his_cons_without_product')]}" colspan="4">
25- <separator string="Configuration of Base Consumptions Periods" colspan="4"/>
26- <field name="date_start"/>
27- <field name="date_stop"/>
28- </group>
29 </form>"""
30
31 orderpoint_calculator_fields = {
32@@ -70,24 +66,19 @@
33 'required': True,
34 'help':'Use this field as index. Reference index is Main Season with 1.00. If you want to change the orderpoint rules you are able to define new season with a seasonal index. This index should reference to 1.00. For example if you expect - 10% consumption for autumn season in comparition to main season enter 0.90.'
35 },
36-
37- 'date_start': {
38- 'string':'From Date',
39- 'type':'date'
40- },
41-
42- 'date_stop': {
43- 'string':'To Date',
44- 'type':'date',
45- 'default': lambda *a: time.strftime('%Y-%m-%d')
46+
47+ 'max_qty_factor': {
48+ 'string':'Max. Qty. Factor',
49+ 'type':'float',
50+ 'required': True
51 },
52
53 'method_qty_calculation':{
54 'string':"Method Calculation",
55 'type':'selection',
56- 'selection':[('his_cons_with_product', 'Calculate with historical consumptions of products'),
57+ 'selection':[('his_cons_with_product', 'Calculate with planning values'),
58 ('his_cons_without_product', 'Calculate with Out historical consumptions of product'),
59- ('hist_cons_and_open_sale', 'Calculate with historical consumptions of product and Open sales orders'),
60+ ('hist_cons_and_open_sale', 'Calculate with historical values'),
61 ],'required': True,
62 'default': lambda *a:'his_cons_with_product'
63 },
64@@ -120,12 +111,18 @@
65 pool = pooler.get_pool(cr.dbname)
66
67 purchase_obj = pool.get('purchase.order')
68+ purchase_order_line_obj = pool.get('purchase.order.line')
69 sale_obj = pool.get('sale.order')
70+ sale_line_obj = pool.get("sale.order.line")
71 product_obj = pool.get('product.product')
72 supp_obj = pool.get('product.supplierinfo')
73 supp_cost_opt_obj = pool.get('supplier.cost.opti.lead.time')
74 min_rule_obj = pool.get('stock.warehouse.orderpoint')
75 seasonal_obj = pool.get('product.seasonal')
76+ stock_move_obj = pool.get('stock.move')
77+ account_invoice_obj = pool.get('account.invoice')
78+ account_invoice_line_obj = pool.get('account.invoice.line')
79+
80 ##### Calculation of purchase lead time
81 purchase_lead_time = 0.0
82 company = pool.get('res.users').browse(cr, uid, uid, context).company_id
83@@ -135,117 +132,238 @@
84 seasonal_id = data['form']['seasonal_id']
85 seasonal_data = seasonal_obj.browse(cr, uid, seasonal_id)
86 seasonal_factor = seasonal_data.seasonal_factor
87-
88- ##### Calculation of supplier lead time
89-
90- for id in data['ids']:
91- product_id = product_obj.browse(cr, uid, id, context)
92- supplier_lead_time = 0.0
93- if product_id:
94- for supp in product_id.seller_ids:
95- sup = supp_obj.browse(cr, uid, supp.id, context)
96- supplier_lead_time = sup.delay
97-
98- ###### Calculation of average_daily_consumption
99- date_start = data['form']['date_start']
100- date_stop = data['form']['date_stop']
101- average_daily_consumption = 0.0
102- sale_line_obj = pool.get("sale.order.line")
103- consum_qty = 0.0
104- sale_ids = sale_obj.search(cr,uid,[('date_order','>=',date_start),('date_order','<=',date_stop)])
105- if sale_ids:
106- for sid in sale_ids:
107- sale_line_id = sale_line_obj.search(cr,uid,[('order_id','=',sid),('product_id','=',product_id.id)])
108- for line_id in sale_line_id:
109- sale_line_data= sale_line_obj.browse(cr,uid,line_id)
110- consum_qty += sale_line_data.product_uom_qty
111- ###here consume quantity is total of selected product
112- ##################calculation of date difference between first and last sale order
113- sale_ids = sale_obj.search(cr,uid,[('date_order','>=',date_start),('date_order','<=',date_stop)], order='date_order asc')
114- if sale_ids:
115- start_sale_id = sale_ids[0]
116- last_sale_id = sale_ids[-1]
117- first_sale_date = sale_obj.browse(cr,uid,start_sale_id).date_order
118- last_sale_date = sale_obj.browse(cr,uid,last_sale_id).date_order
119- first_date = time.mktime(time.strptime(first_sale_date,'%Y-%m-%d'))
120- last_date = time.mktime(time.strptime(last_sale_date,'%Y-%m-%d'))
121- diff_day = (last_date-first_date)/(3600*24)
122- if diff_day > 0:
123- average_daily_consumption = consum_qty / diff_day
124- ###### Calculation of plan_average_daily_consumption
125- plan_average_daily_consumption = 0.0
126- if product_id.plan_avg_consume:
127- plan_average_daily_consumption = product_id.plan_avg_consume
128-
129- ####### get location #####
130- location_id = data['form']['location_id']
131-
132- ########## calculation historical consumption of products and open sales orders“
133- ### total sale qty with open state
134-
135- sale_qty = 0.0
136- open_sale_ids = sale_obj.search(cr, uid, [('state','in',['manual','progress'])])
137- if sale_ids:
138- for sale_id in open_sale_ids:
139- sale_open_line_ids= sale_line_obj.search(cr,uid,[('order_id','=',sale_id),('product_id','=',product_id.id)])
140- for open_line_id in sale_open_line_ids:
141- sale_line_data= sale_line_obj.browse(cr,uid,open_line_id)
142- sale_qty += sale_line_data.product_uom_qty
143- ###################
144- purchase_ids = purchase_obj.search(cr,uid,[])
145- if purchase_ids:
146- start_pur_id = min(purchase_ids)
147- last_pur_id = max(purchase_ids)
148-
149- ##################calculation of date difference between first and last purchase order
150- first_purchase_date = purchase_obj.browse(cr,uid,start_pur_id).date_order
151- last_purchase_date = purchase_obj.browse(cr,uid,last_pur_id).date_order
152- first_date = time.mktime(time.strptime(first_purchase_date,'%Y-%m-%d'))
153- last_date = time.mktime(time.strptime(last_purchase_date,'%Y-%m-%d'))
154- pur_diff_day = (last_date-first_date)/(3600*24)
155- product_max_qty = 0.0
156- product_min_qty = 0.0
157-
158- if data['form']['method_qty_calculation'] == 'his_cons_with_product':
159- product_min_qty = int(math.ceil(average_daily_consumption * (supplier_lead_time + purchase_lead_time) * seasonal_factor))
160- product_max_qty = 2 * product_min_qty
161-
162- elif data['form']['method_qty_calculation'] == 'his_cons_without_product':
163- product_min_qty = int(math.ceil(plan_average_daily_consumption * (supplier_lead_time + purchase_lead_time) * seasonal_factor))
164- product_max_qty = 2 * product_min_qty
165-
166- else:
167- try:
168- product_min_qty = int(math.ceil((consum_qty + sale_qty) / pur_diff_day * (supplier_lead_time + purchase_lead_time) * seasonal_factor))
169- except Exception,e:
170- product_min_qty = 0.0
171- product_max_qty = 2 * product_min_qty
172-
173- if data['form']['delactive']:
174- stock_rule_ids = min_rule_obj.search(cr,uid,[('warehouse_id','=',data['form']['warehouse_id']),('product_id','=',product_id.id)])
175- for stock_rule_id in stock_rule_ids:
176- min_rule_obj.unlink(cr, uid, [stock_rule_id],context=context)
177-
178- mini_stock_rule_id = min_rule_obj.search(cr,uid,[('warehouse_id','=',data['form']['warehouse_id']),('product_id','=',product_id.id)])
179- if mini_stock_rule_id:
180- for stock_rule_id in mini_stock_rule_id:
181- min_rule_obj.write(cr, uid, [stock_rule_id],{'product_min_qty':product_min_qty,'product_max_qty':product_max_qty,},context=context)
182- else:
183- name = pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint.calculator')
184- pool.get('stock.warehouse.orderpoint').create(cr, uid, {
185- 'name': name,
186- 'active': True,
187- 'warehouse_id': data['form']['warehouse_id'],
188- 'location_id': location_id,
189- 'product_id': id,
190- 'product_min_qty': product_min_qty,
191- 'product_max_qty': product_max_qty,
192- 'qty_multiple':1,
193- 'product_uom':product_id.uom_id.id,
194- 'logic':'max'
195- } )
196-
197-
198+
199+ # max_qty_factor factor
200+ max_qty_factor = data['form']['max_qty_factor']
201+
202+ # 1. Calculation of the date date start in one year later than current date
203+ from_date = (datetime.now() - relativedelta(months=12)).strftime('%Y-%m-%d %H:%M:%S')
204+ to_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
205+
206+ # 2.1 first find the all the product which fullfill the criteria of the 2.1
207+ product_ids = product_obj.search(cr,uid,[('active','=',True),('type','=','product'),
208+ ('procure_method','=','make_to_stock'),
209+ ('supply_method','=','buy'),
210+ ('purchase_ok','=',True),
211+ ('state','not in',['end','obsolete']),
212+ ])
213+ ####### get location #####
214+ location_id = data['form']['location_id']
215+ ###########
216+
217+ #2. Second point find the products for the perticular suppliers
218+ for partner_id in data['ids']:
219+ filter_products = []
220+ for product_id in product_ids:
221+ product_data = product_obj.browse(cr, uid, product_id, context=context)
222+ for seller_id in product_data.seller_ids:
223+ if seller_id.name.id == partner_id:
224+ filter_products.append(product_id)
225+
226+ #3. Calculation of the first stock input date as first input
227+ for filter_product_id in filter_products:
228+ product_data = pool.get('product.product').browse(cr, uid, filter_product_id, context=context)
229+ supplier_lead_time = 0.0
230+
231+ # supplier_lead_time of the supplier delay
232+ for seller_id in product_data.seller_ids:
233+ if seller_id.name.id == partner_id:
234+ supplier_lead_time = seller_id.delay
235+
236+ stock_move_ids = stock_move_obj.search(cr, uid, [('product_id','=',filter_product_id)])
237+
238+ average_daily_consumption = 0.0
239+ first_stock_move_ids = []
240+
241+ # Take the first input date of the stock move where stock move of incoming picking or stock move not have any picking
242+
243+ for first_stock_id in stock_move_ids:
244+ first_data = stock_move_obj.browse(cr, uid, first_stock_id, context=context)
245+
246+ if first_data.picking_id:
247+ if first_data.picking_id.type == 'in':
248+ first_stock_move_ids.append(first_stock_id)
249+ else:
250+ first_stock_move_ids.append(first_stock_id)
251+
252+ if first_stock_move_ids:
253+ first_stock_move_id = first_stock_move_ids[0]
254+ first_input = stock_move_obj.browse(cr, uid, first_stock_move_id, context=context).date_planned
255+
256+ # Case 1 if first input is less than from date
257+
258+ if first_input < from_date:
259+ # calculation of consumption of product from_date to to_date , where state is done
260+ consum_qty = 0.0
261+ sale_ids = sale_obj.search(cr,uid,[('date_order','>=',from_date),('date_order','<=',to_date), ('state','=','done')])
262+ if sale_ids:
263+ for sid in sale_ids:
264+ sale_line_id = sale_line_obj.search(cr,uid,[('order_id','=',sid),('product_id','=',filter_product_id)])
265+ for line_id in sale_line_id:
266+ sale_line_data= sale_line_obj.browse(cr, uid, line_id, context=context).product_uom_qty
267+ consum_qty += sale_line_data
268+
269+ # Calculation of the refund quantities of the prduct from the refund invoice
270+ refund_qty = 0.0
271+ refund_invoice_ids = account_invoice_obj.search(cr,uid,[('type','in',['out_refund','in_refund']),('date_invoice','>=',from_date),('date_invoice','<=',to_date)])
272+ for refund_id in refund_invoice_ids:
273+ invoie_line_ids = account_invoice_line_obj.search(cr,uid,[('invoice_id','=',refund_id),('product_id','=',filter_product_id)])
274+ for invoice_line_id in invoie_line_ids:
275+ inovice_line_data = account_invoice_line_obj.browse(cr, uid, invoice_line_id, context=context).quantity
276+ refund_qty += inovice_line_data
277+
278+ # calculation of open sale orders
279+ open_sale_qty = 0.0
280+ open_sale_ids = sale_obj.search(cr, uid, [('state','in',['manual','progress'])])
281+ if open_sale_ids:
282+ for sale_id in open_sale_ids:
283+ sale_open_line_ids= sale_line_obj.search(cr,uid,[('order_id','=',sale_id),('product_id','=',filter_product_id)])
284+ for open_line_id in sale_open_line_ids:
285+ sale_line_data= sale_line_obj.browse(cr,uid,open_line_id)
286+ open_sale_qty += sale_line_data.product_uom_qty
287+
288+ # Calculation of open purchase orders
289+ open_purchase_qty = 0.0
290+ open_purchase_ids = purchase_obj.search(cr,uid,[('state','=','approved')])
291+ if open_purchase_ids:
292+ for purchase_id in open_purchase_ids:
293+ open_purchase_line_ids= purchase_order_line_obj.search(cr,uid,[('order_id','=',purchase_id),('product_id','=',filter_product_id)])
294+ for open_pur_id in open_purchase_line_ids:
295+ purchase_line_data = purchase_order_line_obj.browse(cr, uid, open_pur_id, context=context)
296+ open_purchase_qty += purchase_line_data.product_qty
297+
298+ # Date difference between from_date and to_date
299+ first_date = time.mktime(time.strptime(from_date,'%Y-%m-%d %H:%M:%S'))
300+ last_date = time.mktime(time.strptime(to_date,'%Y-%m-%d %H:%M:%S'))
301+ pur_diff_day = (last_date-first_date)/(3600*24)
302+ ### calculation of average_daily_consumption
303+ if pur_diff_day > 0:
304+ average_daily_consumption = (consum_qty - refund_qty + open_sale_qty - open_purchase_qty) / pur_diff_day
305+
306+ elif from_date < first_input and first_input < to_date:
307+ first_date = first_input
308+ # calculation of consumption of product from_date to to_date , where sale order state is done
309+ sale_line_obj = pool.get("sale.order.line")
310+ consum_qty = 0.0
311+ sale_ids = sale_obj.search(cr,uid,[('date_order','>=',first_date),('date_order','<=',to_date),('state','=','done')])
312+ if sale_ids:
313+ for sid in sale_ids:
314+ sale_line_id = sale_line_obj.search(cr,uid,[('order_id','=',sid),('product_id','=',filter_product_id)])
315+ for line_id in sale_line_id:
316+ sale_line_data= sale_line_obj.browse(cr, uid, line_id, context=context).product_uom_qty
317+ consum_qty += sale_line_data
318+
319+ # Calculation of the refund quantities of the prduct from the refund invoice
320+ refund_qty = 0.0
321+ refund_invoice_ids = account_invoice_obj.search(cr,uid,[('type','in',['out_refund','in_refund']),('date_invoice','>=',first_date),('date_invoice','<=',to_date)])
322+ for refund_id in refund_invoice_ids:
323+ invoie_line_ids = account_invoice_line_obj.search(cr,uid,[('invoice_id','=',refund_id),('product_id','=',filter_product_id)])
324+ for invoice_line_id in invoie_line_ids:
325+ inovice_line_data = account_invoice_line_obj.browse(cr, uid, invoice_line_id, context=context).quantity
326+ refund_qty += inovice_line_data
327+
328+ # calculation of open sale orders where state is open
329+ open_sale_qty = 0.0
330+ open_sale_ids = sale_obj.search(cr, uid, [('state','in',['manual','progress'])])
331+ if open_sale_ids:
332+ for sale_id in open_sale_ids:
333+ sale_open_line_ids= sale_line_obj.search(cr,uid,[('order_id','=',sale_id),('product_id','=',filter_product_id)])
334+ for open_line_id in sale_open_line_ids:
335+ sale_line_data= sale_line_obj.browse(cr,uid,open_line_id)
336+ open_sale_qty += sale_line_data.product_uom_qty
337+
338+ # Calculation of open purchase orders, where state is open
339+ open_purchase_qty = 0.0
340+ open_purchase_ids = purchase_obj.search(cr,uid,[('state','=','approved')])
341+ if open_purchase_ids:
342+ for purchase_id in open_purchase_ids:
343+ open_purchase_line_ids= purchase_order_line_obj.search(cr,uid,[('order_id','=',purchase_id),('product_id','=',filter_product_id)])
344+ for open_pur_id in open_purchase_line_ids:
345+ purchase_line_data = purchase_order_line_obj.browse(cr, uid, open_pur_id, context=context)
346+ open_purchase_qty += purchase_line_data.product_qty
347+
348+ # Date difference between from_date and to_date
349+ first_date = time.mktime(time.strptime(first_date,'%Y-%m-%d %H:%M:%S'))
350+ last_date = time.mktime(time.strptime(to_date,'%Y-%m-%d %H:%M:%S'))
351+ pur_diff_day = (last_date-first_date)/(3600*24)
352+
353+ if pur_diff_day>0:
354+ ### calculation of average_daily_consumption
355+ average_daily_consumption = (consum_qty - refund_qty + open_sale_qty - open_purchase_qty) / pur_diff_day
356+ else:
357+ open_sale_qty = 0.0
358+ open_sale_ids = sale_obj.search(cr, uid, [('state','in',['manual','progress'])])
359+ if open_sale_ids:
360+ for sale_id in open_sale_ids:
361+ sale_open_line_ids= sale_line_obj.search(cr,uid,[('order_id','=',sale_id),('product_id','=',filter_product_id)])
362+ for open_line_id in sale_open_line_ids:
363+ sale_line_data= sale_line_obj.browse(cr,uid,open_line_id)
364+ open_sale_qty += sale_line_data.product_uom_qty
365+
366+ open_purchase_qty = 0.0
367+ open_purchase_ids = purchase_obj.search(cr,uid,[('state','=','approved')])
368+ if open_purchase_ids:
369+ for purchase_id in open_purchase_ids:
370+ open_purchase_line_ids= purchase_order_line_obj.search(cr,uid,[('order_id','=',purchase_id),('product_id','=',filter_product_id)])
371+ for open_pur_id in open_purchase_line_ids:
372+ purchase_line_data = purchase_order_line_obj.browse(cr, uid, open_pur_id, context=context)
373+ open_purchase_qty += purchase_line_data.product_qty
374+
375+ # calculation of first open purchase date
376+ first_open_purchase_order = min(open_purchase_ids)
377+ fst_open_pur_date = purchase_obj. browse(cr, uid, first_open_purchase_order, context=context).date_order
378+
379+ # Days difference between to date and first purchase date
380+ pur_to_date = time.mktime(time.strptime(to_date,'%Y-%m-%d %H:%M:%S'))
381+ pur_open_date = time.mktime(time.strptime(fst_open_pur_date,'%Y-%m-%d'))
382+ pur_diff_day = (pur_to_date-pur_open_date)/(3600*24)
383+
384+ if pur_diff_day>0:
385+ average_daily_consumption = (open_sale_qty - open_purchase_qty)/pur_diff_day
386+
387+ ###### Calculation of plan_average_daily_consumption
388+ plan_average_daily_consumption = 0.0
389+ plan_average_daily_consumption = product_data.plan_avg_consume
390+
391+ if data['form']['method_qty_calculation'] == 'his_cons_with_product':
392+ product_min_qty = int(math.ceil(average_daily_consumption * (supplier_lead_time + purchase_lead_time) * seasonal_factor))
393+ product_max_qty = max_qty_factor * product_min_qty
394+
395+ elif data['form']['method_qty_calculation'] == 'his_cons_without_product':
396+ product_min_qty = int(math.ceil(plan_average_daily_consumption * (supplier_lead_time + purchase_lead_time) * seasonal_factor))
397+ product_max_qty = max_qty_factor * product_min_qty
398+
399+ else:
400+ try:
401+ product_min_qty = int(math.ceil((consum_qty + open_sale_qty) / pur_diff_day * (supplier_lead_time + purchase_lead_time) * seasonal_factor))
402+ except Exception,e:
403+ product_min_qty = 0.0
404+ product_max_qty = max_qty_factor * product_min_qty
405+
406+ if data['form']['delactive']:
407+ stock_rule_ids = min_rule_obj.search(cr,uid,[('warehouse_id','=',data['form']['warehouse_id']),('product_id','=',filter_product_id)])
408+ for stock_rule_id in stock_rule_ids:
409+ min_rule_obj.unlink(cr, uid, [stock_rule_id],context=context)
410+
411+ mini_stock_rule_id = min_rule_obj.search(cr,uid,[('warehouse_id','=',data['form']['warehouse_id']),('product_id','=',filter_product_id)])
412+ if mini_stock_rule_id:
413+ for stock_rule_id in mini_stock_rule_id:
414+ min_rule_obj.write(cr, uid, [stock_rule_id],{'product_min_qty':product_min_qty,'product_max_qty':product_max_qty,},context=context)
415+ else:
416+ name = pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint.calculator')
417+ pool.get('stock.warehouse.orderpoint').create(cr, uid, {
418+ 'name': name,
419+ 'active': True,
420+ 'warehouse_id': data['form']['warehouse_id'],
421+ 'location_id': location_id,
422+ 'product_id': filter_product_id,
423+ 'product_min_qty': product_min_qty,
424+ 'product_max_qty': product_max_qty,
425+ 'qty_multiple':1,
426+ 'product_uom':product_data.uom_id.id,
427+ 'logic':'price',
428+ } )
429+
430 return {}
431
432 def _get_message(self, cr, uid, data, context):

Subscribers

People subscribed via source and target branches