[MRG] Add module stock_reord_rule to improve the orderpoint rules. It works forecasting the stock needed per product for n days of sales, with the next formula: (( Qty sold in days_stats * (1+forecast_gap)) / days_stats * days_warehouse)

This commit is contained in:
Joel Grand-Guillaume
2013-02-22 15:30:51 +01:00
6 changed files with 171 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Vehicle management for OpenERP
# Copyright (C) 2012 Sergio Corato (<http://www.icstools.it>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import stock_reord_rule

View File

@@ -0,0 +1,51 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Improved reordering rules for OpenERP
# Copyright (C) 2012 Sergio Corato (<http://www.icstools.it>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Improved reordering rules',
'version': '0.2',
'category': 'Tools',
'description': """
This module allows to improve reordering rules of stock module.
It works forecasting the stock needed per product for n days of sales, with the next formula:
(( Qty sold in days_stats * (1+forecast_gap)) / days_stats * days_warehouse)
where:
- days_stats = days on wich calculate sales stats;
- forecast_gap = forecast of increase/decrease on sales (%);
- days_warehouse = days of stock to keep in the warehouse.
Usage:
insert days_stats, forecast_gap and days_warehouse vars in product form
and create a reordering rule for the same product, without inserting nothing (neither maximum or
minimum quantity are required). The cron job will be executed daily and will update the maximum
quantity in the reordering rule (you can force it to start changing the date and hour of
execution).
This module doesn't need purchase module to work, but it's useful with that module.'""",
'author': 'Sergio Corato',
'website': 'http://www.icstools.it',
'depends': ['procurement','sale',],
'demo_xml' : [],
'data': ['stock_reord_rule_view.xml','cron_data.xml',],
'images': [],
'active': False,
'installable': True,
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<record model="ir.cron" id="update_reordering_quantity_cron">
<field name="name">Update quantity for reordering rules</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"></field>
<field eval="'stock.warehouse.orderpoint'" name="model"/>
<field eval="'_qty_orderpoint_days'" name="function"/>
<field eval="'[[],{}]'" name="args"/>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,2 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink

View File

@@ -0,0 +1,59 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Automatic Stock Procurement by days for OpenERP
# Copyright (C) 2012 Sergio Corato (<http://www.icstools.it>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import orm, fields
class stock_warehouse_orderpoint(orm.Model):
_inherit = "stock.warehouse.orderpoint"
def _qty_orderpoint_days(self, cr, uid, ids, context=None):
"""Calculate quantity to create warehouse stock for n days of sales.
(( Qty sold in days_stats * (1+forecast_gap)) / days_stats * days_warehouse)"""
obj_product = self.pool.get('product.product')
product_ids = tuple(obj_product.search(cr, uid, [], context=context))
sql= """SELECT sol.product_id AS product_id,
(sum( product_uos_qty )/pp.days_stats*(1+pp.forecast_gap/100) * pp.days_warehouse)
AS quantity FROM sale_order_line sol JOIN sale_order so ON so.id = sol.order_id
JOIN product_product pp ON pp.id = sol.product_id
JOIN product_template pt ON pt.id = pp.product_tmpl_id
WHERE sol.state in ('done','confirmed') AND pt.type = 'product'
AND sol.product_id IN %s AND date_order > (date(now()) - pp.days_stats)
GROUP BY sol.product_uom, sol.product_id, pp.days_stats, pp.forecast_gap,
pp.days_warehouse;"""
cr.execute(sql, (product_ids,))
sql_res = cr.fetchall()
if sql_res:
for val in sql_res:
if val:
reord_rules_ids = self.search(cr, uid, [('product_id', '=', val[0])], context=context)
if reord_rules_ids:
self.write(cr, uid, reord_rules_ids, {'product_max_qty': val[1]}, context=context)
return True
class product_product(orm.Model):
_inherit = "product.product"
_columns = {
'days_warehouse': fields.integer('Days of needed warehouse stock'),
'days_stats': fields.integer('Days of sale statistics'),
'forecast_gap': fields.float('Expected sales variation (percent +/-)', digits=(6,3)),
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="product_normal_form_view_procurement_by_days" model="ir.ui.view">
<field name="name">product.normal.form_procurement_by_days</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<group name="procurement" position="after">
<group name="Stock Procurement By Days">
<field name="days_warehouse"/>
<field name="days_stats"/>
<field name="forecast_gap"/>
</group>
</group>
</field>
</record>
</data>
</openerp>