[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:
@@ -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',
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user