Merge lp:~icsergio/stock-logistic-warehouse/improve_reordering_rules into lp:stock-logistic-warehouse

Proposed by Sergio Corato
Status: Merged
Merged at revision: 29
Proposed branch: lp:~icsergio/stock-logistic-warehouse/improve_reordering_rules
Merge into: lp:stock-logistic-warehouse
Diff against target: 203 lines (+171/-0)
6 files modified
stock_reord_rule/__init__.py (+22/-0)
stock_reord_rule/__openerp__.py (+51/-0)
stock_reord_rule/cron_data.xml (+15/-0)
stock_reord_rule/security/ir.model.access.csv (+2/-0)
stock_reord_rule/stock_reord_rule.py (+59/-0)
stock_reord_rule/stock_reord_rule_view.xml (+22/-0)
To merge this branch: bzr merge lp:~icsergio/stock-logistic-warehouse/improve_reordering_rules
Reviewer Review Type Date Requested Status
Guewen Baconnier @ Camptocamp code review, no test Approve
Review via email: mp+148960@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

__openerp__.py:
 * The description does not allow to understand what the module does
 * merge init_xml and update_xml in 'data'

l.126
from openerp.osv import orm, fields

l.128,152
inherit from orm.Model

l.150,161
remove the instantiation

l.137,144,147
context propagation is missing

l.138
why do you skip the update when you have 1 product?

l.139
unreadable query: use multiple lines

l.139
the product ids should not be substituted in the str, they must be an argument in cr.execute()

l.146
this is bug prone because you initialized res at l.135 and reuse it for each product.
Just remove the l.146 and do the write as follows:
    self.write(cr, uid, reord_rules_ids, {'product_max_qty': val[1]}, context=context)

l.158
why is 3 casted to int?

l.178-180
Instead of forcing the 'string' in the view, you better have to directly write the correct string in the python ``fields``.

On pep8 [1]
take a look on the pep8 recommandations for the whitespaces [2], 1 space after a comma or a colon (l.144,157,158...)

[1] http://www.python.org/dev/peps/pep-0008/
[2] http://www.python.org/dev/peps/pep-0008/#whitespace-in-expressions-and-statements

review: Needs Fixing (code review, no test)
30. By Sergio Corato

[FIX] Code and description review

Revision history for this message
Sergio Corato (icsergio) wrote :

Thanks a lot, I uploaded the code reviewed with your useful tips.

For
"l.138
why do you skip the update when you have 1 product?"
it's because if there is only a service product it gives a non-blocking error, even not visible by the user (only in console).
If it's admitted, it can be removed (as I did in the last release).

Revision history for this message
Sergio Corato (icsergio) wrote :

Perhaps is better if I check if the product is a service before executing, I'd test this one first.

31. By Sergio Corato

[FIX] Improved SQL query to search only product of type product

32. By Sergio Corato

[IMP] Improved usage description

Revision history for this message
Sergio Corato (icsergio) wrote :

Now it would be ok, for me.

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Looks good to me. Any idea if it works correctly in multi-company?

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

(I ask that because the SQL query bypass the record rules)

Revision history for this message
Sergio Corato (icsergio) wrote :

I've done some tests and it looks ok even in multi-company.

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Nice.

LGTM

review: Approve (code review, no test)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'stock_reord_rule'
2=== added file 'stock_reord_rule/__init__.py'
3--- stock_reord_rule/__init__.py 1970-01-01 00:00:00 +0000
4+++ stock_reord_rule/__init__.py 2013-02-19 21:36:22 +0000
5@@ -0,0 +1,22 @@
6+# -*- encoding: utf-8 -*-
7+##############################################################################
8+#
9+# Vehicle management for OpenERP
10+# Copyright (C) 2012 Sergio Corato (<http://www.icstools.it>)
11+#
12+# This program is free software: you can redistribute it and/or modify
13+# it under the terms of the GNU Affero General Public License as
14+# published by the Free Software Foundation, either version 3 of the
15+# License, or (at your option) any later version.
16+#
17+# This program is distributed in the hope that it will be useful,
18+# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+# GNU Affero General Public License for more details.
21+#
22+# You should have received a copy of the GNU Affero General Public License
23+# along with this program. If not, see <http://www.gnu.org/licenses/>.
24+#
25+##############################################################################
26+
27+import stock_reord_rule
28
29=== added file 'stock_reord_rule/__openerp__.py'
30--- stock_reord_rule/__openerp__.py 1970-01-01 00:00:00 +0000
31+++ stock_reord_rule/__openerp__.py 2013-02-19 21:36:22 +0000
32@@ -0,0 +1,51 @@
33+# -*- encoding: utf-8 -*-
34+##############################################################################
35+#
36+# Improved reordering rules for OpenERP
37+# Copyright (C) 2012 Sergio Corato (<http://www.icstools.it>)
38+#
39+# This program is free software: you can redistribute it and/or modify
40+# it under the terms of the GNU Affero General Public License as
41+# published by the Free Software Foundation, either version 3 of the
42+# License, or (at your option) any later version.
43+#
44+# This program is distributed in the hope that it will be useful,
45+# but WITHOUT ANY WARRANTY; without even the implied warranty of
46+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47+# GNU Affero General Public License for more details.
48+#
49+# You should have received a copy of the GNU Affero General Public License
50+# along with this program. If not, see <http://www.gnu.org/licenses/>.
51+#
52+##############################################################################
53+
54+{
55+ 'name': 'Improved reordering rules',
56+ 'version': '0.2',
57+ 'category': 'Tools',
58+ 'description': """
59+ This module allows to improve reordering rules of stock module.
60+
61+ It works forecasting the stock needed per product for n days of sales, with the next formula:
62+ (( Qty sold in days_stats * (1+forecast_gap)) / days_stats * days_warehouse)
63+ where:
64+ - days_stats = days on wich calculate sales stats;
65+ - forecast_gap = forecast of increase/decrease on sales (%);
66+ - days_warehouse = days of stock to keep in the warehouse.
67+
68+ Usage:
69+ insert days_stats, forecast_gap and days_warehouse vars in product form
70+ and create a reordering rule for the same product, without inserting nothing (neither maximum or
71+ minimum quantity are required). The cron job will be executed daily and will update the maximum
72+ quantity in the reordering rule (you can force it to start changing the date and hour of
73+ execution).
74+ This module doesn't need purchase module to work, but it's useful with that module.'""",
75+ 'author': 'Sergio Corato',
76+ 'website': 'http://www.icstools.it',
77+ 'depends': ['procurement','sale',],
78+ 'demo_xml' : [],
79+ 'data': ['stock_reord_rule_view.xml','cron_data.xml',],
80+ 'images': [],
81+ 'active': False,
82+ 'installable': True,
83+}
84
85=== added file 'stock_reord_rule/cron_data.xml'
86--- stock_reord_rule/cron_data.xml 1970-01-01 00:00:00 +0000
87+++ stock_reord_rule/cron_data.xml 2013-02-19 21:36:22 +0000
88@@ -0,0 +1,15 @@
89+<?xml version="1.0"?>
90+<openerp>
91+ <data noupdate="1">
92+ <record model="ir.cron" id="update_reordering_quantity_cron">
93+ <field name="name">Update quantity for reordering rules</field>
94+ <field name="interval_number">1</field>
95+ <field name="interval_type">days</field>
96+ <field name="numbercall">-1</field>
97+ <field name="doall" eval="False"></field>
98+ <field eval="'stock.warehouse.orderpoint'" name="model"/>
99+ <field eval="'_qty_orderpoint_days'" name="function"/>
100+ <field eval="'[[],{}]'" name="args"/>
101+ </record>
102+ </data>
103+</openerp>
104
105=== added directory 'stock_reord_rule/i18n'
106=== added directory 'stock_reord_rule/security'
107=== added file 'stock_reord_rule/security/ir.model.access.csv'
108--- stock_reord_rule/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
109+++ stock_reord_rule/security/ir.model.access.csv 2013-02-19 21:36:22 +0000
110@@ -0,0 +1,2 @@
111+"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
112+
113
114=== added file 'stock_reord_rule/stock_reord_rule.py'
115--- stock_reord_rule/stock_reord_rule.py 1970-01-01 00:00:00 +0000
116+++ stock_reord_rule/stock_reord_rule.py 2013-02-19 21:36:22 +0000
117@@ -0,0 +1,59 @@
118+# -*- encoding: utf-8 -*-
119+##############################################################################
120+#
121+# Automatic Stock Procurement by days for OpenERP
122+# Copyright (C) 2012 Sergio Corato (<http://www.icstools.it>)
123+#
124+# This program is free software: you can redistribute it and/or modify
125+# it under the terms of the GNU Affero General Public License as
126+# published by the Free Software Foundation, either version 3 of the
127+# License, or (at your option) any later version.
128+#
129+# This program is distributed in the hope that it will be useful,
130+# but WITHOUT ANY WARRANTY; without even the implied warranty of
131+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
132+# GNU Affero General Public License for more details.
133+#
134+# You should have received a copy of the GNU Affero General Public License
135+# along with this program. If not, see <http://www.gnu.org/licenses/>.
136+#
137+##############################################################################
138+
139+from openerp.osv import orm, fields
140+
141+class stock_warehouse_orderpoint(orm.Model):
142+ _inherit = "stock.warehouse.orderpoint"
143+
144+ def _qty_orderpoint_days(self, cr, uid, ids, context=None):
145+ """Calculate quantity to create warehouse stock for n days of sales.
146+ (( Qty sold in days_stats * (1+forecast_gap)) / days_stats * days_warehouse)"""
147+
148+ obj_product = self.pool.get('product.product')
149+ product_ids = tuple(obj_product.search(cr, uid, [], context=context))
150+ sql= """SELECT sol.product_id AS product_id,
151+ (sum( product_uos_qty )/pp.days_stats*(1+pp.forecast_gap/100) * pp.days_warehouse)
152+ AS quantity FROM sale_order_line sol JOIN sale_order so ON so.id = sol.order_id
153+ JOIN product_product pp ON pp.id = sol.product_id
154+ JOIN product_template pt ON pt.id = pp.product_tmpl_id
155+ WHERE sol.state in ('done','confirmed') AND pt.type = 'product'
156+ AND sol.product_id IN %s AND date_order > (date(now()) - pp.days_stats)
157+ GROUP BY sol.product_uom, sol.product_id, pp.days_stats, pp.forecast_gap,
158+ pp.days_warehouse;"""
159+ cr.execute(sql, (product_ids,))
160+ sql_res = cr.fetchall()
161+ if sql_res:
162+ for val in sql_res:
163+ if val:
164+ reord_rules_ids = self.search(cr, uid, [('product_id', '=', val[0])], context=context)
165+ if reord_rules_ids:
166+ self.write(cr, uid, reord_rules_ids, {'product_max_qty': val[1]}, context=context)
167+ return True
168+
169+class product_product(orm.Model):
170+ _inherit = "product.product"
171+
172+ _columns = {
173+ 'days_warehouse': fields.integer('Days of needed warehouse stock'),
174+ 'days_stats': fields.integer('Days of sale statistics'),
175+ 'forecast_gap': fields.float('Expected sales variation (percent +/-)', digits=(6,3)),
176+ }
177
178=== added file 'stock_reord_rule/stock_reord_rule_view.xml'
179--- stock_reord_rule/stock_reord_rule_view.xml 1970-01-01 00:00:00 +0000
180+++ stock_reord_rule/stock_reord_rule_view.xml 2013-02-19 21:36:22 +0000
181@@ -0,0 +1,22 @@
182+<?xml version="1.0" encoding="utf-8"?>
183+<openerp>
184+ <data>
185+
186+ <record id="product_normal_form_view_procurement_by_days" model="ir.ui.view">
187+ <field name="name">product.normal.form_procurement_by_days</field>
188+ <field name="model">product.product</field>
189+ <field name="inherit_id" ref="product.product_normal_form_view"/>
190+ <field name="arch" type="xml">
191+ <group name="procurement" position="after">
192+ <group name="Stock Procurement By Days">
193+ <field name="days_warehouse"/>
194+ <field name="days_stats"/>
195+ <field name="forecast_gap"/>
196+ </group>
197+ </group>
198+ </field>
199+ </record>
200+
201+ </data>
202+</openerp>
203+

Subscribers

People subscribed via source and target branches