[ADD] stock: "Stock Forecast" analysis view

Code courtesy of Jignesh Rathod <jir@odoo.com> and Josse Colpaert
<jco@odoo.com>.
This commit is contained in:
jir
2015-01-21 14:28:55 +01:00
committed by Richard Mathot
parent d653380782
commit 2ad01aa2d1
5 changed files with 173 additions and 1 deletions
+1
View File
@@ -90,6 +90,7 @@ Dashboard / Reports for Warehouse Management will include:
'views/report_stockpicking.xml',
'views/report_stockinventory.xml',
'views/stock.xml',
'report/report_stock_forecast.xml',
],
'test': [
'test/inventory.yml',
+1
View File
@@ -21,3 +21,4 @@
import product_stock
import report_stock
import report_stock_forecast
@@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
from openerp import fields, models
from openerp import tools
class report_stock_forecast(models.Model):
_name = 'report.stock.forecast'
_auto = False
date = fields.Date(string='Date')
product_id = fields.Many2one('product.product', string='Product', readonly=True)
cumulative_quantity = fields.Float(string='Cumulative Quantity', readonly=True)
quantity = fields.Float(readonly=True)
def init(self, cr):
tools.drop_view_if_exists(cr, 'report_stock_forecast')
cr.execute("""CREATE or REPLACE VIEW report_stock_forecast AS (SELECT
max(id) as id,
product_id as product_id,
date as date,
sum(product_qty) AS quantity,
sum(sum(product_qty)) OVER(PARTITION BY product_id ORDER BY date ) AS cumulative_quantity
FROM
(SELECT
max(id) as id,
MAIN.product_id as product_id,
SUB.date as date,
CASE WHEN MAIN.date = SUB.date THEN sum(MAIN.product_qty) ELSE 0 END as product_qty
FROM
(SELECT
max(sq.id) as id,
sq.product_id,
CASE WHEN sm.date < CURRENT_DATE
THEN to_date(to_char(sm.date, 'YYYY/MM/DD'), 'YYYY/MM/DD')
ELSE to_date(to_char(CURRENT_DATE, 'YYYY/MM/DD'), 'YYYY/MM/DD')
END AS date,
SUM(sq.qty) AS product_qty
FROM
(SELECT min(date) AS date FROM stock_move AS sm
LEFT JOIN
stock_location source_location ON sm.location_id = source_location.id
LEFT JOIN
stock_location dest_location ON sm.location_dest_id = dest_location.id
WHERE
sm.state IN ('confirmed','assigned','waiting') AND
(dest_location.usage = 'internal' AND source_location.usage != 'internal')
or (source_location.usage = 'internal' AND dest_location.usage != 'internal')) AS sm,
stock_quant as sq
LEFT JOIN
product_product ON product_product.id = sq.product_id
LEFT JOIN
stock_location location_id ON sq.location_id = location_id.id
WHERE
location_id.usage = 'internal'
GROUP BY date, sq.product_id
UNION ALL
SELECT
max(sm.id) as id,
sm.product_id,
to_date(to_char(sm.date, 'YYYY/MM/DD'), 'YYYY/MM/DD') AS date,
SUM(sm.product_qty) AS product_qty
FROM
stock_move as sm
LEFT JOIN
product_product ON product_product.id = sm.product_id
LEFT JOIN
stock_location dest_location ON sm.location_dest_id = dest_location.id
LEFT JOIN
stock_location source_location ON sm.location_id = source_location.id
WHERE
sm.state IN ('confirmed','assigned','waiting') and
source_location.usage != 'internal' and dest_location.usage = 'internal'
GROUP BY sm.date,sm.product_id
UNION ALL
SELECT
max(sm.id) as id,
sm.product_id,
to_date(to_char(sm.date, 'YYYY/MM/DD'), 'YYYY/MM/DD') AS date,
SUM(-(sm.product_qty)) AS product_qty
FROM
stock_move as sm
LEFT JOIN
product_product ON product_product.id = sm.product_id
LEFT JOIN
stock_location source_location ON sm.location_id = source_location.id
LEFT JOIN
stock_location dest_location ON sm.location_dest_id = dest_location.id
WHERE
sm.state IN ('confirmed','assigned','waiting') and
source_location.usage = 'internal' and dest_location.usage != 'internal'
GROUP BY sm.date,sm.product_id)
as MAIN
LEFT JOIN
(SELECT DISTINCT date
FROM
(
SELECT CURRENT_DATE AS DATE
UNION ALL
SELECT to_date(to_char(sm.date, 'YYYY/MM/DD'), 'YYYY/MM/DD') AS date
FROM stock_move sm
LEFT JOIN
stock_location source_location ON sm.location_id = source_location.id
LEFT JOIN
stock_location dest_location ON sm.location_dest_id = dest_location.id
WHERE
sm.state IN ('confirmed','assigned','waiting') and
(dest_location.usage = 'internal' AND source_location.usage != 'internal')
or (source_location.usage = 'internal' AND dest_location.usage != 'internal')) AS DATE_SEARCH)
SUB ON (SUB.date IS NOT NULL)
GROUP BY MAIN.product_id,SUB.date, MAIN.date
) AS FINAL
GROUP BY product_id,date)""")
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_stock_level_forecast_pivot" model="ir.ui.view">
<field name="name">Stock.forecast.pivot</field>
<field name="model">report.stock.forecast</field>
<field name="arch" type="xml">
<pivot string="Stock Level forecast" disable_linking="True">
<field name="product_id" type="col"/>
<field name="cumulative_quantity" type="measure"/>
<field name="quantity" type="measure"/>
</pivot>
</field>
</record>
<record id="view_stock_level_forecast_graph" model="ir.ui.view">
<field name="name">Stock.forecast.graph</field>
<field name="model">report.stock.forecast</field>
<field name="arch" type="xml">
<graph string="Stock Level forecast" type="pivot">
<field name="product_id" type="col"/>
<field name="cumulative_quantity" type="measure"/>
</graph>
</field>
</record>
<record id="view_stock_level_forecast_filter" model="ir.ui.view">
<field name="name">view.stock.level.forecast.filter</field>
<field name="model">report.stock.forecast</field>
<field name="arch" type="xml">
<search string="Stock Level forecast">
<field name="product_id"/>
<field name="date"/>
<group expand="1" string="Group By">
<filter string="Pivot" name="pivot_by" context="{'pivot_row_groupby': ['date:day'], 'pivot_column_groupby': ['product_id'],'pivot_measures': ['cumulative_quantity','quantity']}"/>
<filter string="Graph" name="graph_by" context="{'graph_groupbys': ['date:day', 'product_id']}"/>
</group>
</search>
</field>
</record>
<record id="action_stock_level_forecast_report" model="ir.actions.act_window">
<field name="name">Stock Level Forecast</field>
<field name="res_model">report.stock.forecast</field>
<field name="view_type">form</field>
<field name="view_mode">pivot,graph</field>
<field name="search_view_id" ref="view_stock_level_forecast_filter"/>
<field name="context">{'search_default_pivot_by':1,'search_default_graph_by':1}</field>
<field name="view_id" ref="view_stock_level_forecast_pivot"/>
</record>
<menuitem action="action_stock_level_forecast_report" id="menu_report_product_forecast" parent="next_id_61" sequence="3" />
</odoo>
+3 -1
View File
@@ -80,4 +80,6 @@ access_product_price_history_stock_manager,prices.history stock manager,product.
access_barcode_nomenclature_stock_user,barcode.nomenclature.stock.user,barcodes.model_barcode_nomenclature,stock.group_stock_user,1,0,0,0
access_barcode_nomenclature_stock_manager,barcode.nomenclature.stock.manager,barcodes.model_barcode_nomenclature,stock.group_stock_manager,1,1,1,1
access_barcode_rule_stock_user,barcode.rule.stock.user,barcodes.model_barcode_rule,stock.group_stock_user,1,0,0,0
access_barcode_rule_stock_manager,barcode.rule.stock.manager,barcodes.model_barcode_rule,stock.group_stock_manager,1,1,1,1
access_barcode_rule_stock_manager,barcode.rule.stock.manager,barcodes.model_barcode_rule,stock.group_stock_manager,1,1,1,1
access_stock_forecast_user,report.stock.forecast.user,model_report_stock_forecast,stock.group_stock_user,1,0,0,0
access_stock_forecast_manager,report.stock.forecast.manager,model_report_stock_forecast,stock.group_stock_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
80 access_barcode_nomenclature_stock_user barcode.nomenclature.stock.user barcodes.model_barcode_nomenclature stock.group_stock_user 1 0 0 0
81 access_barcode_nomenclature_stock_manager barcode.nomenclature.stock.manager barcodes.model_barcode_nomenclature stock.group_stock_manager 1 1 1 1
82 access_barcode_rule_stock_user barcode.rule.stock.user barcodes.model_barcode_rule stock.group_stock_user 1 0 0 0
83 access_barcode_rule_stock_manager barcode.rule.stock.manager barcodes.model_barcode_rule stock.group_stock_manager 1 1 1 1
84 access_stock_forecast_user report.stock.forecast.user model_report_stock_forecast stock.group_stock_user 1 0 0 0
85 access_stock_forecast_manager report.stock.forecast.manager model_report_stock_forecast stock.group_stock_manager 1 1 1 1