mirror of
https://github.com/OCA/stock-logistics-reporting.git
synced 2025-02-16 17:13:21 +02:00
@@ -0,0 +1 @@
|
||||
../../../../stock_move_delay_report
|
||||
6
setup/stock_move_delay_report/setup.py
Normal file
6
setup/stock_move_delay_report/setup.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['setuptools-odoo'],
|
||||
odoo_addon=True,
|
||||
)
|
||||
0
stock_move_delay_report/README.rst
Normal file
0
stock_move_delay_report/README.rst
Normal file
5
stock_move_delay_report/__init__.py
Normal file
5
stock_move_delay_report/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# Copyright 2023 ForgeFlow S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import models
|
||||
from . import report
|
||||
17
stock_move_delay_report/__manifest__.py
Normal file
17
stock_move_delay_report/__manifest__.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2023 ForgeFlow S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "Stock Move Delay Report",
|
||||
"summary": "Stock Move Delay Report",
|
||||
"version": "13.0.1.0.0",
|
||||
"license": "AGPL-3",
|
||||
"author": "ForgeFlow, Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/stock-logistics-reporting",
|
||||
"depends": ["stock"],
|
||||
"data": [
|
||||
"security/ir.model.access.csv",
|
||||
"security/report_security.xml",
|
||||
"report/delay_report_views.xml",
|
||||
],
|
||||
}
|
||||
4
stock_move_delay_report/models/__init__.py
Normal file
4
stock_move_delay_report/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# Copyright 2023 ForgeFlow S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import stock_move
|
||||
40
stock_move_delay_report/models/stock_move.py
Normal file
40
stock_move_delay_report/models/stock_move.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# Copyright 2023 ForgeFlow S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
date_delay = fields.Float(
|
||||
compute="_compute_date_delay",
|
||||
store=True,
|
||||
help="If the move is done, the difference between "
|
||||
"the scheduled date and the deadline",
|
||||
)
|
||||
|
||||
responsible_id = fields.Many2one(
|
||||
comodel_name="res.partner",
|
||||
compute="_compute_responsible",
|
||||
store=True,
|
||||
help="Partner responsible of completing the move on time.",
|
||||
)
|
||||
|
||||
@api.depends("state")
|
||||
def _compute_date_delay(self):
|
||||
for rec in self:
|
||||
if rec.state == "done" and rec.date_expected:
|
||||
rec.date_delay = (rec.date - rec.date_expected).days
|
||||
elif not rec.date_expected:
|
||||
rec.date_delay = 0
|
||||
else:
|
||||
rec.date_delay = None
|
||||
|
||||
@api.depends("state")
|
||||
def _compute_responsible(self):
|
||||
for rec in self:
|
||||
if rec.picking_id.picking_type_id.code == "incoming":
|
||||
rec.responsible_id = rec.picking_id.partner_id
|
||||
elif rec.picking_id.picking_type_id.code == "outgoing":
|
||||
rec.responsible_id = rec.picking_id.company_id.partner_id
|
||||
2
stock_move_delay_report/readme/CONTRIBUTORS.rst
Normal file
2
stock_move_delay_report/readme/CONTRIBUTORS.rst
Normal file
@@ -0,0 +1,2 @@
|
||||
* `ForgeFlow <https://www.forgeflow.com>`_:
|
||||
* David Jiménez <david.jimenez@forgeflow.com>
|
||||
1
stock_move_delay_report/readme/DESCRIPTION.rst
Normal file
1
stock_move_delay_report/readme/DESCRIPTION.rst
Normal file
@@ -0,0 +1 @@
|
||||
This module adds a report to check the delay from incoming and outgoing moves grouped by Responsible Partner.
|
||||
9
stock_move_delay_report/readme/USAGE.rst
Normal file
9
stock_move_delay_report/readme/USAGE.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
Go to Inventory -> Reporting -> Delay Analysis.
|
||||
|
||||
Here there are 3 views:
|
||||
|
||||
Graph View: Shows the mean delay days of the stock moves for each partner with incoming or outgoing moves.
|
||||
|
||||
Pivot View: Shows the mean delay days of the stock moves for each partner with incoming or outgoing moves. Also shows the % of moves done on time.
|
||||
|
||||
Tree View: Shows all the done moves grouped by the partner responsible (in charge) of the picking.
|
||||
4
stock_move_delay_report/report/__init__.py
Normal file
4
stock_move_delay_report/report/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# Copyright 2023 ForgeFlow S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import delay_report
|
||||
78
stock_move_delay_report/report/delay_report.py
Normal file
78
stock_move_delay_report/report/delay_report.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# Copyright 2023 ForgeFlow S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models, tools
|
||||
|
||||
|
||||
class StockMoveDelayReport(models.Model):
|
||||
_name = "stock.move.delay.report"
|
||||
_description = "Delay Analysis Report"
|
||||
_auto = False
|
||||
|
||||
date = fields.Date("Date Scheduled", readonly=True)
|
||||
move_id = fields.Many2one("stock.move", "Stock Move #", readonly=True)
|
||||
product_id = fields.Many2one("product.product", "Product", readonly=True)
|
||||
reference = fields.Char("Reference", readonly=True)
|
||||
location_src_id = fields.Many2one("stock.location", "From", readonly=True)
|
||||
location_dest_id = fields.Many2one("stock.location", "To", readonly=True)
|
||||
date_delay = fields.Float("Date Delay", group_operator="avg", readonly=True)
|
||||
done_on_time = fields.Float("Done on Time", group_operator="avg", readonly=True)
|
||||
product_uom = fields.Many2one("uom.uom", "Unit of Measure", readonly=True)
|
||||
responsible_id = fields.Many2one("res.partner", "Responsible", readonly=True)
|
||||
company_id = fields.Many2one("res.company", string="Company")
|
||||
|
||||
def _done_on_time(self):
|
||||
return """
|
||||
case when sm.date_delay > 0 then 0.0 else 100.0 end as done_on_time
|
||||
"""
|
||||
|
||||
def _select(self):
|
||||
return """
|
||||
sm.id,
|
||||
sm.date,
|
||||
sm.id AS move_id,
|
||||
sm.product_id,
|
||||
sm.reference,
|
||||
sm.location_id AS location_src_id,
|
||||
sm.location_dest_id,
|
||||
sm.date_delay,
|
||||
%s,
|
||||
sm.product_uom,
|
||||
sm.responsible_id,
|
||||
sm.company_id
|
||||
""" % (
|
||||
self._done_on_time()
|
||||
)
|
||||
|
||||
def _from(self):
|
||||
return """
|
||||
stock_move AS sm
|
||||
"""
|
||||
|
||||
def _where(self):
|
||||
if len(self.env.company) == 1:
|
||||
return """
|
||||
sm.state = 'done' AND sm.responsible_id IS NOT NULL
|
||||
"""
|
||||
else:
|
||||
return """
|
||||
sm.state = 'done' AND sm.responsible_id IS NOT NULL
|
||||
"""
|
||||
|
||||
def _query(self):
|
||||
return """
|
||||
(SELECT %s
|
||||
FROM %s
|
||||
WHERE %s)
|
||||
""" % (
|
||||
self._select(),
|
||||
self._from(),
|
||||
self._where(),
|
||||
)
|
||||
|
||||
def init(self):
|
||||
tools.drop_view_if_exists(self.env.cr, self._table)
|
||||
# pylint: disable=E8103
|
||||
self.env.cr.execute(
|
||||
"""CREATE or REPLACE VIEW %s as (%s)""" % (self._table, self._query())
|
||||
)
|
||||
108
stock_move_delay_report/report/delay_report_views.xml
Normal file
108
stock_move_delay_report/report/delay_report_views.xml
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
|
||||
<record id="stock_move_delay_report_pivot_view" model="ir.ui.view">
|
||||
<field name="name">stock.move.delay.report.pivot</field>
|
||||
<field name="model">stock.move.delay.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Delay Analysis" disable_linking="True">
|
||||
<field name="responsible_id" type="row" />
|
||||
<field name="date_delay" type="measure" string="Mean Days Delay" />
|
||||
<field name="done_on_time" type="measure" />
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_move_delay_report_graph_view" model="ir.ui.view">
|
||||
<field name="name">stock.move.delay.report.graph</field>
|
||||
<field name="model">stock.move.delay.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Delay Analysis" type="line">
|
||||
<field name="responsible_id" type="row" />
|
||||
<field name="date_delay" type="measure" string="Mean Days Delay" />
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_move_delay_report_tree_view" model="ir.ui.view">
|
||||
<field name="name">stock.move.delay.report.tree</field>
|
||||
<field name="model">stock.move.delay.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree create="0">
|
||||
<field name="responsible_id" />
|
||||
<field name="date" />
|
||||
<field name="move_id" />
|
||||
<field name="product_id" />
|
||||
<field name="product_uom" optional="0" />
|
||||
<field name="reference" />
|
||||
<field name="location_src_id" />
|
||||
<field name="location_dest_id" />
|
||||
<field name="date_delay" />
|
||||
<field name="company_id" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_move_delay_report_search_view" model="ir.ui.view">
|
||||
<field name="name">stock.move.delay.report.search</field>
|
||||
<field name="model">stock.move.delay.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field name="responsible_id" />
|
||||
<filter
|
||||
name="group_responsible_id"
|
||||
string="Responsible"
|
||||
icon="terp-partner"
|
||||
context="{'group_by':'responsible_id'}"
|
||||
/>
|
||||
<filter
|
||||
string="Only Products"
|
||||
name="only_products"
|
||||
domain="[('product_id.type', '=', 'product')]"
|
||||
/>
|
||||
<filter
|
||||
string="Only Services"
|
||||
name="only_services"
|
||||
domain="[('product_id.type', '=', 'service')]"
|
||||
/>
|
||||
<filter
|
||||
string="Only Consumable"
|
||||
name="only_consumable"
|
||||
domain="[('product_id.type', '=', 'consu')]"
|
||||
/>
|
||||
<filter
|
||||
string="Date"
|
||||
name="today"
|
||||
date="date"
|
||||
help="Scheduled or processing date"
|
||||
/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_stock_move_delay_report" model="ir.actions.act_window">
|
||||
<field name="name">Delay Analysis</field>
|
||||
<field name="res_model">stock.move.delay.report</field>
|
||||
<field name="view_mode">graph,pivot,tree</field>
|
||||
<field name="search_view_id" ref="stock_move_delay_report_search_view" />
|
||||
<field name="context">{
|
||||
'search_default_group_responsible_id': 1,
|
||||
'search_default_only_products': 1,
|
||||
}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No data yet!
|
||||
</p><p>
|
||||
Complete a new stock move
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
action="action_stock_move_delay_report"
|
||||
id="menu_stock_move_delay_report"
|
||||
parent="stock.menu_warehouse_report"
|
||||
sequence="140"
|
||||
/>
|
||||
|
||||
</odoo>
|
||||
3
stock_move_delay_report/security/ir.model.access.csv
Normal file
3
stock_move_delay_report/security/ir.model.access.csv
Normal file
@@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_stock_move_delay_report_user,stock.move.delay.report.user,model_stock_move_delay_report,base.group_user,1,0,0,0
|
||||
access_stock_move_delay_report_manager,stock.move.delay.report.manager,model_stock_move_delay_report,base.group_system,1,1,1,1
|
||||
|
10
stock_move_delay_report/security/report_security.xml
Normal file
10
stock_move_delay_report/security/report_security.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<odoo>
|
||||
<record model="ir.rule" id="stock_move_delay_report_comp_rule">
|
||||
<field name="name">Stock Move Delay Analysis multi-company</field>
|
||||
<field name="model_id" ref="model_stock_move_delay_report" />
|
||||
<field name="global" eval="True" />
|
||||
<field
|
||||
name="domain_force"
|
||||
>['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user