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

Proposed by gpa(OpenERP)
Status: Merged
Merged at revision: 16
Proposed branch: lp:~openbig/bigconsulting/changes_in_stock_minimum_calculator
Merge into: lp:bigconsulting
Diff against target: 994 lines (+413/-439)
14 files modified
stock_minimum_calculator/__init__.py (+3/-1)
stock_minimum_calculator/__terp__.py (+3/-3)
stock_minimum_calculator/stock_minimujm_calculator_wizard.xml (+7/-0)
stock_minimum_calculator/stock_minimum_calculator.py (+0/-58)
stock_minimum_calculator/stock_minimum_calculator_demo.xml (+17/-0)
stock_minimum_calculator/stock_minimum_calculator_sequence.xml (+4/-4)
stock_minimum_calculator/stock_minimum_calculator_view.xml (+2/-74)
stock_minimum_calculator/stock_order_point_calculator.py (+0/-217)
stock_minimum_calculator/stock_order_point_calculator_view.xml (+0/-50)
stock_minimum_calculator/supplier_cost_optimated_leadtimes.py (+89/-0)
stock_minimum_calculator/supplier_cost_optimated_leadtimes_view.xml (+46/-0)
stock_minimum_calculator/wizard/__init__.py (+1/-0)
stock_minimum_calculator/wizard/seasonal_trend_set_view.xml (+0/-32)
stock_minimum_calculator/wizard/stock_order_point_calculator.py (+241/-0)
To merge this branch: bzr merge lp:~openbig/bigconsulting/changes_in_stock_minimum_calculator
Reviewer Review Type Date Requested Status
openbig Pending
Review via email: mp+27589@code.launchpad.net

Description of the change

Added change as new specification

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'stock_minimum_calculator/__init__.py'
2--- stock_minimum_calculator/__init__.py 2010-06-09 14:36:04 +0000
3+++ stock_minimum_calculator/__init__.py 2010-06-15 07:09:25 +0000
4@@ -21,6 +21,8 @@
5 ##############################################################################
6
7 import stock_minimum_calculator
8+import stock_order_point_calculator
9+import supplier_cost_optimated_leadtimes
10 import wizard
11-import stock_order_point_calculator
12+
13 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
14\ No newline at end of file
15
16=== modified file 'stock_minimum_calculator/__terp__.py'
17--- stock_minimum_calculator/__terp__.py 2010-06-11 07:42:16 +0000
18+++ stock_minimum_calculator/__terp__.py 2010-06-15 07:09:25 +0000
19@@ -30,11 +30,11 @@
20 we have proper re-order quentity for each products.
21 """,
22 "depends": ['stock','mrp'],
23- "demo_xml": [],
24+ "demo_xml": ["stock_minimum_calculator_demo.xml"],
25 "update_xml": ['stock_minimum_calculator_view.xml',
26 "stock_minimujm_calculator_wizard.xml",
27- "stock_order_point_calculator_view.xml",
28- "stock_minimum_calculator_sequence.xml"
29+ "stock_minimum_calculator_sequence.xml",
30+ "supplier_cost_optimated_leadtimes_view.xml",
31 ],
32 "license": "GPL-3",
33 "active": False,
34
35=== modified file 'stock_minimum_calculator/stock_minimujm_calculator_wizard.xml'
36--- stock_minimum_calculator/stock_minimujm_calculator_wizard.xml 2010-06-09 14:36:04 +0000
37+++ stock_minimum_calculator/stock_minimujm_calculator_wizard.xml 2010-06-15 07:09:25 +0000
38@@ -7,5 +7,12 @@
39 name="set_seasonal.trend"
40 menu="True"
41 id="id_set_seasonal_trend"/>
42+ <wizard
43+ string="Order Point Cacluator"
44+ model="product.product"
45+ name="orderpoint.calculator"
46+ menu="True"
47+ id="id_order_point_cacluator"/>
48+
49 </data>
50 </openerp>
51
52=== modified file 'stock_minimum_calculator/stock_minimum_calculator.py'
53--- stock_minimum_calculator/stock_minimum_calculator.py 2010-06-11 06:02:15 +0000
54+++ stock_minimum_calculator/stock_minimum_calculator.py 2010-06-15 07:09:25 +0000
55@@ -36,7 +36,6 @@
56 }
57 stock_holding_rate()
58
59-
60 class supplier_product(osv.osv):
61 _name = 'supplier.product'
62 _rec_name = 'partner_id'
63@@ -48,63 +47,6 @@
64
65 supplier_product()
66
67-class res_partner(osv.osv):
68- _inherit = "res.partner"
69- _columns = {
70- 'stock_holding_rate_id':fields.many2one("stock.holding.rate",'Holding Rate'),
71- }
72-res_partner()
73-
74-
75-class supplier_cost_opti_lead_time(osv.osv):
76- _name = "supplier.cost.opti.lead.time"
77- _columns = {
78- 'supp_cost_id':fields.char("ID",size=64, required=True),
79- 'name':fields.char("Name of the rule",size=64, required=True),
80- 'partner_id': fields.many2one('res.partner', 'Suplier'),
81- 'date_start': fields.date('Date', required=True),
82- 'active': fields.boolean('Active'),
83- 'yrl_purchase_rev':fields.float("YRL Purchase Revenue",required=True),
84- 'economic_no_order':fields.float("Economic Number of orders",readonly=True),
85- 'cost_per_del':fields.float("Cost Per Delivery",required=True),
86- 'economic_lead_time':fields.float("Economic Lead Time",readonly=True),
87- 'stock_holding_rate_id':fields.many2one("stock.holding.rate",'Holding Rate',required=True),
88- 'staus': fields.selection([
89- ('draft','Draft'),
90- ('valid','Valid'),
91- ('cancel','Cancel'),
92- ],'Status',readonly=True),
93- }
94- _defaults = {
95- 'date_start': lambda *a: time.strftime('%Y-%m-%d'),
96- }
97-
98- def action_compute(self, cr, uid, ids, context={}):
99- for id in ids:
100- cost_op = self.browse(cr, uid,id,context=context)
101- economic_numer_orders = (cost_op.yrl_purchase_rev * cost_op.stock_holding_rate_id.stock_hold_rate)/ (2*cost_op.cost_per_del)
102- economic_lead_time = 360 / economic_numer_orders
103- self.write(cr, uid, [id],{'economic_lead_time':economic_lead_time,'economic_no_order':economic_numer_orders})
104- return True
105-
106- def action_cancel(self, cr, uid, ids, context={}):
107- for o in self.browse(cr, uid, ids):
108- self.write(cr, uid, [o.id], {'staus': 'cancel'})
109- return True
110-
111- def action_validate(self, cr, uid, ids, context={}):
112- for o in self.browse(cr, uid, ids):
113- already_id = self_obj.search(cr, uid, [('partner_id','=',o.partner_id.id),('id', 'not in', ids),('staus','=','valid')])
114- if already_id:
115- old_partner_id = self.browse(cr, uid, already_id[0])
116- if o.partner_id.id == old_partner_id.partner_id.id:
117- raise osv.except_osv(_('Error !'),
118- _('You can not this partner becasue this partner aleready with valid entry'))
119- self.write(cr, uid, [o.id], {'staus': 'valid'})
120- return True
121-
122-supplier_cost_opti_lead_time()
123-
124 class product_seasonal(osv.osv):
125 _name = 'product.seasonal'
126 _columns = {
127
128=== added file 'stock_minimum_calculator/stock_minimum_calculator_demo.xml'
129--- stock_minimum_calculator/stock_minimum_calculator_demo.xml 1970-01-01 00:00:00 +0000
130+++ stock_minimum_calculator/stock_minimum_calculator_demo.xml 2010-06-15 07:09:25 +0000
131@@ -0,0 +1,17 @@
132+<?xml version="1.0" encoding="utf-8"?>
133+<openerp>
134+ <data noupdate="1">
135+
136+ <record id="product_seasonal_id1" model="product.seasonal">
137+ <field name="name">Normal Seasonal</field>
138+ <field name="code">main</field>
139+ <field name="seasonal_factor">1.0</field>
140+ </record>
141+ <record id="product_seasonal_id2" model="product.seasonal">
142+ <field name="name">Christmas Seasonal</field>
143+ <field name="code">christmas</field>
144+ <field name="seasonal_factor">1.12</field>
145+ </record>
146+
147+ </data>
148+</openerp>
149
150=== modified file 'stock_minimum_calculator/stock_minimum_calculator_sequence.xml'
151--- stock_minimum_calculator/stock_minimum_calculator_sequence.xml 2010-06-11 07:42:16 +0000
152+++ stock_minimum_calculator/stock_minimum_calculator_sequence.xml 2010-06-15 07:09:25 +0000
153@@ -3,12 +3,12 @@
154 <data noupdate="1">
155 <!-- Sequences for stock.orderpoint.step2 -->
156 <record id="sequence_stock_op_point" model="ir.sequence.type">
157- <field name="name">Stock orderpoint step2</field>
158- <field name="code">stock.orderpoint.step2</field>
159+ <field name="name">Stock orderpoint Calculator</field>
160+ <field name="code">stock.orderpoint.calculator</field>
161 </record>
162 <record id="sequence_stock_op" model="ir.sequence">
163- <field name="name">Stock orderpoint step2</field>
164- <field name="code">stock.orderpoint.step2</field>
165+ <field name="name">stock orderpoint Calculator</field>
166+ <field name="code">stock.orderpoint.calculator</field>
167 <field name="prefix">OP/</field>
168 <field name="padding">5</field>
169 <field name="number_increment">1</field>
170
171=== modified file 'stock_minimum_calculator/stock_minimum_calculator_view.xml'
172--- stock_minimum_calculator/stock_minimum_calculator_view.xml 2010-06-10 06:28:31 +0000
173+++ stock_minimum_calculator/stock_minimum_calculator_view.xml 2010-06-15 07:09:25 +0000
174@@ -2,7 +2,7 @@
175 <openerp>
176 <data>
177
178- <record id="stock_holding_rate_tree_view" model="ir.ui.view">
179+ <record id="stock_holding_rate_tree_view" model="ir.ui.view">
180 <field name="name">stock.holding.rate.tree</field>
181 <field name="model">stock.holding.rate</field>
182 <field name="type">tree</field>
183@@ -52,69 +52,8 @@
184 <field name="view_type">form</field>
185 <field name="view_id" ref="stock_holding_rate_tree_view"/>
186 </record>
187+
188 <menuitem action="stock_holding_rate_tree_view_normal_action" id="menu_stock_holding_rate" parent="stock.menu_stock_configuration"/>
189-
190- <record id="supplier_cost_opti_lead_time_tree_view" model="ir.ui.view">
191- <field name="name">supplier.cost.opti.lead.time.tree</field>
192- <field name="model">supplier.cost.opti.lead.time</field>
193- <field name="type">tree</field>
194- <field name="arch" type="xml">
195- <tree string="Supplier Cost Optimated Lead Times">
196- <field name="supp_cost_id"/>
197- <field name="name"/>
198- <field name="partner_id"/>
199- <field name="date_start"/>
200- <field name="yrl_purchase_rev"/>
201- <field name="economic_no_order"/>
202- <field name="cost_per_del"/>
203- <field name="economic_lead_time"/>
204- <field name="stock_holding_rate_id"/>
205- <field name="staus"/>
206- </tree>
207- </field>
208- </record>
209-
210- <record id="supplier_cost_opti_lead_time_form_view" model="ir.ui.view">
211- <field name="name">supplier.cost.opti.lead.time.form</field>
212- <field name="model">supplier.cost.opti.lead.time</field>
213- <field name="type">form</field>
214- <field name="arch" type="xml">
215- <form string="Supplier Cost Optimated Lead Times">
216- <group colspan="6" col="6">
217- <field name="name"/>
218- <field name="supp_cost_id"/>
219- <field name="active"/>
220- <field name="partner_id"/>
221- <field name="date_start"/>
222- </group>
223- <group colspan="2" col="2">
224- <separator colspan="4" string="Automatic Declaration"/>
225- <field name="yrl_purchase_rev"/>
226- <field name="cost_per_del"/>
227- <field name="stock_holding_rate_id"/>
228- </group>
229- <group colspan="2" col="2">
230- <separator colspan="4" string="Economic Number of orders"/>
231- <field name="economic_no_order"/>
232- <field name="economic_lead_time"/>
233- <button name="action_compute" string="Calculate Lead Time" type="object"/>
234- </group>
235- <field name="staus"/>
236- <button name="action_cancel" string="Cancel" type="object"/>
237- <button name="action_validate" string="Valid" type="object"/>
238- </form>
239- </field>
240- </record>
241- <record id="supplier_cost_opti_lead_time_normal_action" model="ir.actions.act_window">
242- <field name="name">Supplier Cost Optimated Lead Times</field>
243- <field name="type">ir.actions.act_window</field>
244- <field name="res_model">supplier.cost.opti.lead.time</field>
245- <field name="view_type">form</field>
246- <field name="view_id" ref="supplier_cost_opti_lead_time_tree_view"/>
247- </record>
248- <menuitem action="supplier_cost_opti_lead_time_normal_action" id="menu_supplier_cost_opti_lead_time" parent="stock.menu_stock_configuration"/>
249-
250-
251
252 <record id="product_seasonal_tree_view" model="ir.ui.view">
253 <field name="name">product.seasonal.tree</field>
254@@ -150,17 +89,6 @@
255 </record>
256 <menuitem action="product_seasonal_normal_action" id="menu_product_seasonal" parent="stock.menu_stock_configuration"/>
257
258- <record model="ir.ui.view" id="view_supplier_holding_rate_form1">
259- <field name="name">res.partner.form</field>
260- <field name="model">res.partner</field>
261- <field name="inherit_id" ref="stock.view_partner_property_form"/>
262- <field name="type">form</field>
263- <field name="arch" type="xml">
264- <field name="property_stock_supplier" position="after">
265- <field name="stock_holding_rate_id" />
266- </field>
267- </field>
268- </record>
269 <record model="ir.ui.view" id="view_supplier_holding_rate_form">
270 <field name="name">product.product.form</field>
271 <field name="model">product.product</field>
272
273=== removed file 'stock_minimum_calculator/stock_order_point_calculator.py'
274--- stock_minimum_calculator/stock_order_point_calculator.py 2010-06-11 07:42:16 +0000
275+++ stock_minimum_calculator/stock_order_point_calculator.py 1970-01-01 00:00:00 +0000
276@@ -1,217 +0,0 @@
277-# -*- coding: utf-8 -*-
278-##############################################################################
279-#
280-# OpenERP, Open Source Management Solution
281-# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
282-#
283-# This program is free software: you can redistribute it and/or modify
284-# it under the terms of the GNU Affero General Public License as
285-# published by the Free Software Foundation, either version 3 of the
286-# License, or (at your option) any later version.
287-#
288-# This program is distributed in the hope that it will be useful,
289-# but WITHOUT ANY WARRANTY; without even the implied warranty of
290-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
291-# GNU Affero General Public License for more details.
292-#
293-# You should have received a copy of the GNU Affero General Public License
294-# along with this program. If not, see <http://www.gnu.org/licenses/>.
295-#
296-##############################################################################
297-from osv import fields, osv
298-import time
299-from tools.translate import _
300-
301-class stock_orderpoint_step1(osv.osv_memory):
302-
303- _name="stock.orderpoint.step1"
304- _columns = {
305- 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse',required=True),
306- 'deactive': fields.boolean('Deactive Existing Rules'),
307- 'delactive': fields.boolean('Delete Exiting Rules(for this warehosue)'),
308- }
309-
310- def _de_next(self, cr, uid, ids, context=None):
311-
312- mod_obj = self.pool.get('ir.model.data')
313- product_obj = self.pool.get('product.product')
314- min_rule_obj = self.pool.get('stock.warehouse.orderpoint')
315- form = self.read(cr, uid, ids, [])[0]
316-
317- stock_rule_ids = min_rule_obj.search(cr,uid,[('warehouse_id','=',form['warehouse_id'])])
318-
319- if form['deactive']:
320- for stock_rule_id in min_rule_obj.browse(cr, uid, stock_rule_ids, context=context):
321- min_rule_obj.write(cr, uid, [stock_rule_id.id], {'active':False}, context=context)
322-
323- elif form['delactive']:
324- for stock_rule_id in min_rule_obj.browse(cr, uid, stock_rule_ids, context=context):
325- min_rule_obj.unlink(cr, uid, [stock_rule_id.id],context=context)
326-
327-
328- model_data_ids = mod_obj.search(cr, uid,[('model','=','ir.ui.view'),('name','=','view_stock_orderpoint_step2')], context=context)
329- resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
330- return {
331- 'name': _('Stock Orderpoint Step2'),
332- 'context': context,
333- 'view_type': 'form',
334- 'view_mode': 'form',
335- 'res_model': 'stock.orderpoint.step2',
336- 'views': [(resource_id,'form')],
337- 'type': 'ir.actions.act_window',
338- 'target': 'new',
339- }
340-stock_orderpoint_step1()
341-
342-
343-class stock_orderpoint_step2(osv.osv_memory):
344-
345- _name="stock.orderpoint.step2"
346- _columns = {
347- 'min_qty_calculation': fields.selection([('optimal_stock_coverage', 'Optimal Stock Coverage'),
348- ('normal_stock_coverage', 'Normal Stock Coverage'),
349- ], 'Method Calculation Minimum Qty',required=True),
350- 'max_qty_calculation': fields.selection([('optimal_stock_coverage', 'Optimal Stock Coverage'),
351- ('normal_stock_coverage', 'Normal Stock Coverage'),
352- ], 'Method Calculation Maximum Qty',required=True),
353- }
354- _defaults = {
355- 'min_qty_calculation': lambda *a: 'optimal_stock_coverage',
356- 'max_qty_calculation': lambda *a: 'optimal_stock_coverage',
357- }
358-
359- def _next_calculate(self, cr, uid, ids, context=None):
360-
361- purchase_obj = self.pool.get('purchase.order')
362- sale_obj = self.pool.get('sale.order')
363- product_obj = self.pool.get('product.product')
364- supp_obj = self.pool.get("product.supplierinfo")
365- supp_cost_opt_obj = self.pool.get("supplier.cost.opti.lead.time")
366- wizard_obj = self.pool.get("stock.orderpoint.step1")
367- min_rule_obj = self.pool.get('stock.warehouse.orderpoint')
368- order_period_obj = self.pool.get("stock.warehosue.orderpoint.period")
369-
370- form = self.read(cr, uid, ids, [])[0]
371-
372- purchase_ids = purchase_obj.search(cr,uid,[])
373- start_pur_id = min(purchase_ids)
374- last_pur_id = max(purchase_ids)
375-
376- ############# Calculation of purchase Quantity upto today
377- purchase_qty = 0.0
378- if purchase_ids:
379- for pur_id in purchase_ids:
380- purchase_data = purchase_obj.browse(cr,uid,pur_id)
381- for line in purchase_data.order_line:
382- purchase_qty += line.product_qty
383-
384-
385- ##### Calculation of sale order Quantity of open orders
386- sale_qty = 0.0
387- sale_ids = self.pool.get('sale.order').search(cr, uid, [('state','in',['manual','progress'])])
388- if sale_ids:
389- for sale_id in sale_ids:
390- sale_data = self.pool.get('sale.order').browse(cr,uid,sale_id)
391- for line in sale_data.order_line:
392- sale_qty += line.product_uom_qty
393-
394-
395- ##################calculation of date difference between first and last purchase order
396- first_purchase_date = purchase_obj.browse(cr,uid,start_pur_id).date_order
397- last_purchase_date = purchase_obj.browse(cr,uid,last_pur_id).date_order
398- first_date = time.mktime(time.strptime(first_purchase_date,'%Y-%m-%d'))
399- last_date = time.mktime(time.strptime(last_purchase_date,'%Y-%m-%d'))
400- diff_day = (last_date-first_date)/(3600*24)
401-
402- ##### Calculation of purchase lead time
403- purchase_lead_time = 0.0
404- company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id
405- purchase_lead_time = company.po_lead
406-
407- ##### Calculation of supplier lead time
408- product_id = product_obj.browse(cr, uid, context['id'], context)
409- supplier_lead_time = 0.0
410- if product_id:
411- for supp in product_id.seller_ids:
412- sup = supp_obj.browse(cr, uid, supp.id, context)
413- supplier_lead_time = sup.delay
414-
415-
416- ##### Calculation of average_daily_consumption
417- average_daily_consumption = 0.0
418- if purchase_ids and diff_day > 0.0:
419- average_daily_consumption = (sale_qty + purchase_qty )/diff_day
420- else:
421- plan_consume = product_id.plan_avg_consume
422- average_daily_consumption = plan_consume
423- ######### calculation of safety stock
424- safety_stock = purchase_qty / len(purchase_ids)
425-
426- ### calculation of Economic lead time (days)
427- cost_op_id = supp_cost_opt_obj.search(cr, uid, [('partner_id','=',sup.name.id)])
428- economic_lead_days = 0.0
429- economic_numer_orders = 0.0
430- economic_lead_time = 0.0
431- if cost_op_id:
432- cost_op = supp_cost_opt_obj.browse(cr, uid,cost_op_id[0])
433- economic_numer_orders = cost_op.economic_no_order
434- economic_lead_time = cost_op.economic_lead_time
435- economic_lead_days = economic_lead_time * 30 #Economic leaddays: field economic leadtime from supplier.leadtimes * 30
436-
437- ### Calculation of the percentage of this days period
438- future_seasonal_fac = 0.0
439- periods = self.pool.get('account.period').find(cr, uid)
440- for period in periods:
441- trend_id = order_period_obj.search(cr, uid, [('period_id','=',period)])
442- if trend_id:
443- per = order_period_obj.browse(cr, uid,trend_id[0]).percentage
444- future_seasonal_fac = economic_lead_days + purchase_lead_time / per
445-
446- #### Calculation of seasonal Factor
447-
448- #??????seasonal factor = percentage of product.seasonaltrend for future period of follwing date:
449- #today + economic lead days + purchase lead time / "percentage of this days period"
450- seasonal_fac = 0.0
451- seasonal_fac = product_id.seasonal_id.seasonal_factor
452-
453-
454- ### Calculation for minimum quantity
455- optimal_stock_coverage = 0.0
456- normal_stock_coverage = 0.0
457- if form['min_qty_calculation'] == 'optimal_stock_coverage':
458- optimal_stock_coverage = average_daily_consumption * seasonal_fac * (economic_lead_days + purchase_lead_time) / safety_stock
459- else:
460- normal_stock_coverage = average_daily_consumption * (supplier_lead_time + purchase_lead_time)/safety_stock
461-
462-
463- ### Calculation for maximum quantity
464- optimal_stock_coverage_max = 0.0
465- normal_stock_coverage_max = 0.0
466- if form['max_qty_calculation'] == 'optimal_stock_coverage':
467- optimal_stock_coverage_max = (average_daily_consumption * seasonal_fac * (economic_lead_days + purchase_lead_time))
468- else:
469- normal_stock_coverage_max = average_daily_consumption * (supplier_lead_time + purchase_lead_time)
470-
471- ids = wizard_obj.search(cr, uid, [])
472-
473- wizz_id = wizard_obj.browse(cr, uid, ids[0])
474- max1 = 'max'
475- name = self.pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint.step2')
476-
477- self.pool.get('stock.warehouse.orderpoint').create(cr, uid, {
478- 'name': name,
479- 'active': True,
480- 'warehouse_id': wizz_id.warehouse_id.id,
481- 'location_id': product_id.property_stock_inventory.id,
482- 'product_id': context['id'],
483- 'product_min_qty': optimal_stock_coverage or normal_stock_coverage,
484- 'product_max_qty': optimal_stock_coverage_max or normal_stock_coverage_max,
485- 'qty_multiple':1,
486- 'product_uom':product_id.uom_id.id,
487- 'logic':'max'
488- } )
489- return {}
490-
491-stock_orderpoint_step2()
492-
493-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
494\ No newline at end of file
495
496=== removed file 'stock_minimum_calculator/stock_order_point_calculator_view.xml'
497--- stock_minimum_calculator/stock_order_point_calculator_view.xml 2010-06-09 14:36:04 +0000
498+++ stock_minimum_calculator/stock_order_point_calculator_view.xml 1970-01-01 00:00:00 +0000
499@@ -1,50 +0,0 @@
500-<?xml version="1.0" encoding="utf-8"?>
501-<openerp>
502- <data>
503- <record id="view_account_invoice_pay" model="ir.ui.view">
504- <field name="name">stock.orderpoint.step1.form</field>
505- <field name="model">stock.orderpoint.step1</field>
506- <field name="type">form</field>
507- <field name="arch" type="xml">
508- <form string="Wizard Order Point Calculator Step1 - Choose Warehouse and Updating Settings">
509- <group colspan="4" >
510- <field name="warehouse_id"/>
511- <field name="deactive"/>
512- <field name="delactive"/>
513- </group>
514- <group colspan="4" col="6">
515- <label string ="" colspan="2"/>
516- <button icon="gtk-cancel" special="cancel" string="Cancel"/>
517- <button icon="gtk-execute" string="Next Step" name="_de_next" type="object"/>
518- </group>
519- </form>
520- </field>
521- </record>
522-
523- <act_window name="Orderpoint Calculator"
524- res_model="stock.orderpoint.step1"
525- src_model="product.product"
526- view_mode="form"
527- target="new"
528- context="{'id': active_id}"
529- id="action_view_stock_orderpoint_step1"/>
530-
531- <record id="view_stock_orderpoint_step2" model="ir.ui.view">
532- <field name="name">stock.orderpoint.step2.form</field>
533- <field name="model">stock.orderpoint.step2</field>
534- <field name="type">form</field>
535- <field name="arch" type="xml">
536- <form string="Wizard Order Point Calculator Step2 - Choose Method">
537- <field name="min_qty_calculation"/>
538- <field name="max_qty_calculation" />
539- <group colspan="4" col="6">
540- <button icon="gtk-cancel" special="cancel" string="Cancel"/>
541- <button icon="gtk-execute" string="Next Step" name="_next_calculate" type="object"/>
542- </group>
543- </form>
544- </field>
545- </record>
546-
547-
548- </data>
549-</openerp>
550\ No newline at end of file
551
552=== added file 'stock_minimum_calculator/supplier_cost_optimated_leadtimes.py'
553--- stock_minimum_calculator/supplier_cost_optimated_leadtimes.py 1970-01-01 00:00:00 +0000
554+++ stock_minimum_calculator/supplier_cost_optimated_leadtimes.py 2010-06-15 07:09:25 +0000
555@@ -0,0 +1,89 @@
556+# -*- coding: utf-8 -*-
557+##############################################################################
558+#
559+# OpenERP, Open Source Management Solution
560+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
561+#
562+# This program is free software: you can redistribute it and/or modify
563+# it under the terms of the GNU Affero General Public License as
564+# published by the Free Software Foundation, either version 3 of the
565+# License, or (at your option) any later version.
566+#
567+# This program is distributed in the hope that it will be useful,
568+# but WITHOUT ANY WARRANTY; without even the implied warranty of
569+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
570+# GNU Affero General Public License for more details.
571+#
572+# You should have received a copy of the GNU Affero General Public License
573+# along with this program. If not, see <http://www.gnu.org/licenses/>.
574+#
575+##############################################################################
576+from osv import fields, osv
577+import time
578+from tools.translate import _
579+from mx import DateTime
580+
581+class supplier_cost_optimated_leadtimes(osv.osv_memory):
582+
583+ _name="supplier.cost.optimated.leadtimes"
584+ _columns = {
585+ 'partner_id': fields.many2one('res.partner', 'Suplier'),
586+ 'account_purchase_rev': fields.many2one('account.analytic.account', 'Acc. Purchase Revenues', required=True),
587+ 'account_cost_pre_del': fields.many2one('account.analytic.account', 'Acc. Delivery Cost'),
588+ 'date_start': fields.date('From Period', required=True),
589+ 'date_stop': fields.date('To Period', required=True),
590+ 'purchase_rev':fields.float("Purchase Revenue",readonly=True,),
591+ 'economic_no_order':fields.float("Economic Number of orders",readonly=True),
592+ 'cost_per_del':fields.float("Cost Per Delivery",readonly=True),
593+ 'economic_lead_time':fields.float("Economic Lead Time", readonly=True),
594+ 'stock_holding_rate_id':fields.many2one("stock.holding.rate",'Holding Rate',required=True),
595+ }
596+
597+ def _compute(self, cr, uid, ids, context=None):
598+
599+ form = self.read(cr, uid, ids, [], context=context)[0]
600+
601+ analytic_account_obj = self.pool.get('account.analytic.account')
602+ analytic_line_obj = self.pool.get('account.analytic.line')
603+ stock_hold_rate_obj = self.pool.get("stock.holding.rate")
604+
605+ date_start = form['date_start']
606+ date_stop = form['date_stop']
607+
608+ pur_balance = 0.0
609+ pur_analytic_id = form['account_purchase_rev']
610+
611+ pur_analytic_line_id = analytic_line_obj.search(cr,uid,[('account_id','=',pur_analytic_id), ('date','>=',date_start),('date','<=',date_stop)])
612+
613+ if pur_analytic_line_id:
614+ for pur_analytic_id in pur_analytic_line_id:
615+ pur_analytic_amount = analytic_line_obj.browse(cr, uid, pur_analytic_id, context)
616+ balance = pur_analytic_amount.amount
617+ pur_balance += balance
618+
619+
620+ cost_del_analytic_id = form['account_cost_pre_del']
621+ cost_balance = 0.0
622+
623+ cost_del_analytic_line_id = analytic_line_obj.search(cr,uid,[('account_id','=',cost_del_analytic_id), ('date','>=',date_start),('date','<=',date_stop)])
624+
625+ if cost_del_analytic_line_id:
626+ for cost_analytic_id in cost_del_analytic_line_id:
627+ cost_analytic_amount = analytic_line_obj.browse(cr, uid, cost_analytic_id, context)
628+ balance = cost_analytic_amount.amount
629+ cost_balance += balance
630+
631+ stock_hold_id = stock_hold_rate_obj.browse(cr, uid, form['stock_holding_rate_id'])
632+ stock_hold_rate = stock_hold_id.stock_hold_rate
633+
634+ if pur_balance and cost_balance:
635+ for id in ids:
636+ economic_numer_orders = (pur_balance * stock_hold_rate)/ (2 * cost_balance)
637+ economic_lead_time = 360 / economic_numer_orders
638+ self.write(cr, uid, [id],{'cost_per_del':cost_balance,'purchase_rev':pur_balance, 'economic_no_order':economic_numer_orders,'economic_lead_time':economic_lead_time})
639+
640+ return True
641+
642+supplier_cost_optimated_leadtimes()
643+
644+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
645\ No newline at end of file
646
647=== added file 'stock_minimum_calculator/supplier_cost_optimated_leadtimes_view.xml'
648--- stock_minimum_calculator/supplier_cost_optimated_leadtimes_view.xml 1970-01-01 00:00:00 +0000
649+++ stock_minimum_calculator/supplier_cost_optimated_leadtimes_view.xml 2010-06-15 07:09:25 +0000
650@@ -0,0 +1,46 @@
651+<?xml version="1.0" encoding="utf-8"?>
652+<openerp>
653+ <data>
654+ <record id="view_supplier_cost_optimated_leadtimes" model="ir.ui.view">
655+ <field name="name">supplier.cost.optimated.leadtimes.form</field>
656+ <field name="model">supplier.cost.optimated.leadtimes</field>
657+ <field name="type">form</field>
658+ <field name="arch" type="xml">
659+ <form string="Wizard to Calculate Cost Optimized Lead Times">
660+ <group colspan="4" >
661+ <field name="partner_id"/>
662+ <field name="stock_holding_rate_id"/>
663+ <field name="date_start"/>
664+ <field name="account_purchase_rev"/>
665+ <field name="date_stop"/>
666+ <field name="account_cost_pre_del"/>
667+ <separator colspan="4" string="Result of Calculation"/>
668+ <field name="purchase_rev"/>
669+ <field name="economic_no_order"/>
670+ <field name="cost_per_del"/>
671+ <field name="economic_lead_time"/>
672+ </group>
673+
674+ <group colspan="4" col="4">
675+ <button icon="gtk-cancel" special="cancel" string="Cancel"/>
676+ <button icon="gtk-execute" string="Calculate Lead Time" name="_compute" type="object"/>
677+ </group>
678+ </form>
679+ </field>
680+ </record>
681+
682+ <record id="action_supplier_cost_optimated_leadtimes" model="ir.actions.act_window">
683+ <field name="name">Supplier Cost Optimated Leadtimes</field>
684+ <field name="type">ir.actions.act_window</field>
685+ <field name="res_model">supplier.cost.optimated.leadtimes</field>
686+ <field name="view_type">form</field>
687+ <field name="view_mode">form</field>
688+ <field name="view_id" ref="view_supplier_cost_optimated_leadtimes"/>
689+ <field name="target">new</field>
690+ </record>
691+ <menuitem action="action_supplier_cost_optimated_leadtimes"
692+ id="menu_action_supplier_cost_optimated_leadtimesy"
693+ parent="stock.next_id_61"/>
694+
695+ </data>
696+</openerp>
697\ No newline at end of file
698
699=== modified file 'stock_minimum_calculator/wizard/__init__.py'
700--- stock_minimum_calculator/wizard/__init__.py 2010-06-09 14:36:04 +0000
701+++ stock_minimum_calculator/wizard/__init__.py 2010-06-15 07:09:25 +0000
702@@ -21,6 +21,7 @@
703 ##############################################################################
704
705 import seasonal_trend_set
706+import stock_order_point_calculator
707
708 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
709
710
711=== removed file 'stock_minimum_calculator/wizard/seasonal_trend_set_view.xml'
712--- stock_minimum_calculator/wizard/seasonal_trend_set_view.xml 2010-06-09 14:36:04 +0000
713+++ stock_minimum_calculator/wizard/seasonal_trend_set_view.xml 1970-01-01 00:00:00 +0000
714@@ -1,32 +0,0 @@
715-<?xml version="1.0" encoding="utf-8"?>
716-<openerp>
717- <data>
718-
719- <record id="view_stock_order_rule" model="ir.ui.view">
720- <field name="name">product.seasonal.trend.form</field>
721- <field name="model">product.seasonal.trend</field>
722- <field name="type">form</field>
723- <field name="arch" type="xml">
724- <form string="Set Seasonal Trend">
725- <field name="trend_seasonal_id" />
726- <field name="active" />
727- <group colspan="4" col="6">
728- <button icon="gtk-cancel" special="cancel" string="Cancel"/>
729- <button icon="gtk-execute" string="OK" name="_set_seasonal" type="object"/>
730- </group>
731- </form>
732- </field>
733- </record>
734-
735- <act_window
736- res_model = "product.seasonal.trend"
737- src_model = "product.product"
738- view_type = "form"
739- view_mode = "form"
740- name= "Set Seasonal Trend"
741- target="new"
742- context="{'id': active_id}"
743- id="action_product_seasonal_trend"/>
744-
745- </data>
746-</openerp>
747\ No newline at end of file
748
749=== added file 'stock_minimum_calculator/wizard/stock_order_point_calculator.py'
750--- stock_minimum_calculator/wizard/stock_order_point_calculator.py 1970-01-01 00:00:00 +0000
751+++ stock_minimum_calculator/wizard/stock_order_point_calculator.py 2010-06-15 07:09:25 +0000
752@@ -0,0 +1,241 @@
753+# -*- coding: utf-8 -*-
754+##############################################################################
755+#
756+# OpenERP, Open Source Management Solution
757+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
758+#
759+# This program is free software: you can redistribute it and/or modify
760+# it under the terms of the GNU Affero General Public License as
761+# published by the Free Software Foundation, either version 3 of the
762+# License, or (at your option) any later version.
763+#
764+# This program is distributed in the hope that it will be useful,
765+# but WITHOUT ANY WARRANTY; without even the implied warranty of
766+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
767+# GNU Affero General Public License for more details.
768+#
769+# You should have received a copy of the GNU Affero General Public License
770+# along with this program. If not, see <http://www.gnu.org/licenses/>.
771+#
772+##############################################################################
773+
774+import wizard
775+import pooler
776+import time
777+from tools.translate import _
778+import mx.DateTime
779+from mx.DateTime import RelativeDateTime, now, DateTime, localtime
780+
781+orderpoint_calculator_form = """<?xml version="1.0"?>
782+<form string="Order Point Calculator ">
783+ <field name="warehouse_id"/>
784+ <field name="location_id"/>
785+ <field name="seasonal_id"/>
786+ <field name="delactive"/>
787+ <field name="method_qty_calculation" colspan="4"/>
788+ <group attrs="{'invisible':[('method_qty_calculation','=','his_cons_without_product')]}" colspan="4">
789+ <separator string="Configuration of Base Consumptions Periods" colspan="4"/>
790+ <field name="date_start"/>
791+ <field name="date_stop"/>
792+ </group>
793+</form>"""
794+
795+orderpoint_calculator_fields = {
796+ 'warehouse_id': {
797+ 'string': 'Warehouse',
798+ 'type': 'many2one',
799+ 'relation': 'stock.warehouse',
800+ 'required': True
801+ },
802+
803+ 'delactive': {
804+ 'string':'Delete Exiting Rules(for this warehosue)',
805+ 'type':'boolean'
806+ },
807+
808+ 'location_id': {
809+ 'string': 'Location',
810+ 'type': 'many2one',
811+ 'relation': 'stock.location',
812+ 'required': True
813+ },
814+
815+ 'seasonal_id': {
816+ 'string': 'Season of Consumption',
817+ 'type': 'many2one',
818+ 'relation': 'product.seasonal',
819+ 'required': True
820+ },
821+
822+ 'date_start': {
823+ 'string':'From Date',
824+ 'type':'date'
825+ },
826+
827+ 'date_stop': {
828+ 'string':'To Date',
829+ 'type':'date',
830+ 'default': lambda *a: time.strftime('%Y-%m-%d')
831+ },
832+
833+ 'method_qty_calculation':{
834+ 'string':"Method Calculation",
835+ 'type':'selection',
836+ 'selection':[('his_cons_with_product', 'Calculate with historical consumptions of products'),
837+ ('his_cons_without_product', 'Calculate with Out historical consumptions of product'),
838+ ('hist_cons_and_open_sale', 'Calculate with historical consumptions of product and Open sales orders'),
839+ ],'required': True,
840+ 'default': lambda *a:'his_cons_with_product'
841+ },
842+ }
843+
844+def _get_default(obj, cr, uid, data, context=None):
845+ pool = pooler.get_pool(cr.dbname)
846+
847+ warehouse_id = pool.get('stock.warehouse').search(cr, uid, [])[0]
848+ location_id = pool.get('stock.location').search(cr, uid, [('name','=','Stock')])[0]
849+
850+ date = now().strftime('%Y-%m-%d')
851+ date = mx.DateTime.strptime(date, '%Y-%m-%d') - RelativeDateTime(months=3)
852+ date = date.strftime('%Y-%m-%d')
853+
854+ return {'warehouse_id': warehouse_id, 'location_id':location_id,'date_start':date}
855+
856+def _do_calculate(self, cr, uid, data, context):
857+
858+ pool = pooler.get_pool(cr.dbname)
859+
860+ purchase_obj = pool.get('purchase.order')
861+ sale_obj = pool.get('sale.order')
862+ product_obj = pool.get('product.product')
863+ supp_obj = pool.get('product.supplierinfo')
864+ supp_cost_opt_obj = pool.get('supplier.cost.opti.lead.time')
865+ min_rule_obj = pool.get('stock.warehouse.orderpoint')
866+
867+ stock_rule_ids = min_rule_obj.search(cr,uid,[('warehouse_id','=',data['form']['warehouse_id'])])
868+ if data['form']['delactive']:
869+ for stock_rule_id in min_rule_obj.browse(cr, uid, stock_rule_ids, context=context):
870+ min_rule_obj.unlink(cr, uid, [stock_rule_id.id],context=context)
871+
872+ ##### Calculation of purchase lead time
873+ purchase_lead_time = 0.0
874+ company = pool.get('res.users').browse(cr, uid, uid, context).company_id
875+ purchase_lead_time = company.po_lead
876+
877+ ##### Calculation of supplier lead time
878+
879+ for id in data['ids']:
880+ product_id = product_obj.browse(cr, uid, id, context)
881+ supplier_lead_time = 0.0
882+ if product_id:
883+ for supp in product_id.seller_ids:
884+ sup = supp_obj.browse(cr, uid, supp.id, context)
885+ supplier_lead_time = sup.delay
886+
887+ ###### Calculation of average_daily_consumption
888+ date_start = data['form']['date_start']
889+ date_stop = data['form']['date_stop']
890+ average_daily_consumption = 0.0
891+ consum_qty = 0.0
892+ sale_ids = sale_obj.search(cr,uid,[('date_order','>=',date_start),('date_order','<=',date_stop)])
893+ if sale_ids:
894+ for sid in sale_ids:
895+ sale_data = sale_obj.browse(cr,uid,sid)
896+ for line in sale_data.order_line:
897+ consum_qty += line.product_uom_qty
898+
899+ ##################calculation of date difference between first and last sale order
900+ sale_ids = sale_obj.search(cr,uid,[])
901+ if sale_ids:
902+ start_sale_id = min(sale_ids)
903+ last_sale_id = max(sale_ids)
904+ first_sale_date = sale_obj.browse(cr,uid,start_sale_id).date_order
905+ last_sale_date = sale_obj.browse(cr,uid,last_sale_id).date_order
906+ first_date = time.mktime(time.strptime(first_sale_date,'%Y-%m-%d'))
907+ last_date = time.mktime(time.strptime(last_sale_date,'%Y-%m-%d'))
908+ diff_day = (last_date-first_date)/(3600*24)
909+ if diff_day > 0:
910+ average_daily_consumption = consum_qty / diff_day
911+
912+ ###### Calculation of plan_average_daily_consumption
913+ plan_average_daily_consumption = 0.0
914+ if product_id.plan_avg_consume:
915+ plan_average_daily_consumption = product_id.plan_avg_consume
916+
917+ ########## calculation historical consumption of products and open sales orders“
918+ ### total sale qty with open state
919+
920+ sale_qty = 0.0
921+ sale_ids = sale_obj.search(cr, uid, [('state','in',['manual','progress'])])
922+ if sale_ids:
923+ for sale_id in sale_ids:
924+ sale_data = sale_obj.browse(cr,uid,sale_id)
925+ for line in sale_data.order_line:
926+ sale_qty += line.product_uom_qty
927+
928+ ###################
929+ purchase_ids = purchase_obj.search(cr,uid,[])
930+ if purchase_ids:
931+ start_pur_id = min(purchase_ids)
932+ last_pur_id = max(purchase_ids)
933+
934+ ##################calculation of date difference between first and last purchase order
935+ first_purchase_date = purchase_obj.browse(cr,uid,start_pur_id).date_order
936+ last_purchase_date = purchase_obj.browse(cr,uid,last_pur_id).date_order
937+ first_date = time.mktime(time.strptime(first_purchase_date,'%Y-%m-%d'))
938+ last_date = time.mktime(time.strptime(last_purchase_date,'%Y-%m-%d'))
939+ pur_diff_day = (last_date-first_date)/(3600*24)
940+
941+ product_max_qty = 0.0
942+ product_min_qty = 0.0
943+
944+ if data['form']['method_qty_calculation'] == 'his_cons_with_product':
945+ product_min_qty = average_daily_consumption * (supplier_lead_time + purchase_lead_time)
946+ product_max_qty = 2 * product_min_qty
947+
948+ elif data['form']['method_qty_calculation'] == 'his_cons_without_product':
949+ product_min_qty = plan_average_daily_consumption * (supplier_lead_time + purchase_lead_time)
950+ product_max_qty = 2 * product_min_qty
951+
952+ else:
953+ product_min_qty = (average_daily_consumption + sale_qty) / pur_diff_day * (supplier_lead_time + purchase_lead_time)
954+ product_max_qty = 2 * product_min_qty
955+
956+ max1 = 'max'
957+ name = pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint.calculator')
958+ pool.get('stock.warehouse.orderpoint').create(cr, uid, {
959+ 'name': name,
960+ 'active': True,
961+ 'warehouse_id': data['form']['warehouse_id'],
962+ 'location_id': product_id.property_stock_inventory.id,
963+ 'product_id': id,
964+ 'product_min_qty': product_min_qty,
965+ 'product_max_qty': product_max_qty,
966+ 'qty_multiple':1,
967+ 'product_uom':product_id.uom_id.id,
968+ 'logic':'max'
969+ } )
970+
971+ return {}
972+
973+class orderpoint_calculator(wizard.interface):
974+ states = {
975+ 'init' : {
976+ 'actions' : [_get_default],
977+ 'result' : {'type' : 'form',
978+ 'arch' : orderpoint_calculator_form,
979+ 'fields' : orderpoint_calculator_fields,
980+ 'state' : [('end', 'Cancel'),('calculation', 'Calculation') ]}
981+ },
982+ 'calculation' : {
983+ 'actions' : [],
984+ 'result' : {'type' : 'action',
985+ 'action' : _do_calculate,
986+ 'state' : 'end'}
987+ }
988+ }
989+orderpoint_calculator("orderpoint.calculator")
990+
991+
992+
993+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
994\ No newline at end of file

Subscribers

People subscribed via source and target branches