mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
Merge pull request #346 from Eficent/9.0-imp-stock_cycle_count
[9.0][IMP] stock_cycle_count: Add views and reports
This commit is contained in:
@@ -4,3 +4,4 @@
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import models
|
||||
from . import reports
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"name": "Stock Cycle Count",
|
||||
"summary": "Adds the capability to schedule cycle counts in a "
|
||||
"warehouse through different rules defined by the user",
|
||||
"version": "9.0.1.1.0",
|
||||
"version": "9.0.1.2.0",
|
||||
"author": "Eficent, "
|
||||
"Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/stock-logistics-warehouse",
|
||||
@@ -26,7 +26,10 @@
|
||||
'views/stock_location_view.xml',
|
||||
'data/cycle_count_sequence.xml',
|
||||
'data/cycle_count_ir_cron.xml',
|
||||
'security/ir.model.access.csv'],
|
||||
'reports/stock_location_accuracy_report.xml',
|
||||
'reports/stock_cycle_count_report.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
"license": "AGPL-3",
|
||||
'installable': True,
|
||||
'application': False,
|
||||
|
||||
@@ -12,23 +12,27 @@ PERCENT = 100.0
|
||||
class StockInventory(models.Model):
|
||||
_inherit = 'stock.inventory'
|
||||
|
||||
@api.one
|
||||
@api.multi
|
||||
@api.depends("state", "line_ids")
|
||||
def _compute_inventory_accuracy(self):
|
||||
total_qty = sum(self.line_ids.mapped('theoretical_qty'))
|
||||
abs_discrepancy = sum(self.line_ids.mapped(
|
||||
lambda x: abs(x.discrepancy_qty)))
|
||||
if total_qty:
|
||||
self.inventory_accuracy = PERCENT * (
|
||||
total_qty - abs_discrepancy) / total_qty
|
||||
if not self.line_ids and self.state == 'done':
|
||||
self.inventory_accuracy = 100.0
|
||||
for inv in self:
|
||||
theoretical = sum(inv.line_ids.mapped(
|
||||
lambda x: abs(x.theoretical_qty)))
|
||||
abs_discrepancy = sum(inv.line_ids.mapped(
|
||||
lambda x: abs(x.discrepancy_qty)))
|
||||
if theoretical:
|
||||
inv.inventory_accuracy = max(
|
||||
PERCENT * (theoretical - abs_discrepancy) / theoretical,
|
||||
0.0)
|
||||
if not inv.line_ids and inv.state == 'done':
|
||||
inv.inventory_accuracy = PERCENT
|
||||
|
||||
cycle_count_id = fields.Many2one(
|
||||
comodel_name='stock.cycle.count', string='Stock Cycle Count',
|
||||
ondelete='cascade', readonly=True)
|
||||
inventory_accuracy = fields.Float(string='Accuracy',
|
||||
compute=_compute_inventory_accuracy,
|
||||
digits=(3, 2))
|
||||
inventory_accuracy = fields.Float(
|
||||
string='Accuracy', compute=_compute_inventory_accuracy,
|
||||
digits=(3, 2), store=True, group_operator="avg")
|
||||
|
||||
@api.multi
|
||||
def action_done(self):
|
||||
|
||||
@@ -91,3 +91,14 @@ class StockLocation(models.Model):
|
||||
'state': 'draft'
|
||||
})
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_accuracy_stats(self):
|
||||
self.ensure_one()
|
||||
action = self.env.ref('stock_cycle_count.act_accuracy_stats')
|
||||
result = action.read()[0]
|
||||
result['context'] = {"search_default_location_id": self.id}
|
||||
new_domain = result['domain'][:-1] + \
|
||||
", ('location_id', 'child_of', active_ids)]"
|
||||
result['domain'] = new_domain
|
||||
return result
|
||||
|
||||
4
stock_cycle_count/reports/__init__.py
Normal file
4
stock_cycle_count/reports/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import report_stock_location_accuracy
|
||||
38
stock_cycle_count/reports/report_stock_location_accuracy.py
Normal file
38
stock_cycle_count/reports/report_stock_location_accuracy.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# (http://www.eficent.com)
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from openerp import api, models
|
||||
|
||||
|
||||
class LocationAccuracyReport(models.AbstractModel):
|
||||
_name = "report.stock_location_accuracy"
|
||||
|
||||
@api.model
|
||||
def _get_inventory_domain(self, loc_id, exclude_sublocation=True):
|
||||
return [('location_id', '=', loc_id),
|
||||
('exclude_sublocation', '=', exclude_sublocation),
|
||||
('state', '=', 'done')]
|
||||
|
||||
@api.model
|
||||
def _get_location_data(self, locations):
|
||||
data = dict()
|
||||
inventory_obj = self.env["stock.inventory"]
|
||||
for loc in locations:
|
||||
counts = inventory_obj.search(self._get_inventory_domain(loc.id))
|
||||
data[loc] = counts
|
||||
return data
|
||||
|
||||
@api.multi
|
||||
def render_html(self, data=None):
|
||||
report_obj = self.env["report"]
|
||||
locs = self.env["stock.location"].browse(self._ids)
|
||||
data = self._get_location_data(locs)
|
||||
docargs = {
|
||||
"doc_ids": locs._ids,
|
||||
"docs": locs,
|
||||
"data": data,
|
||||
}
|
||||
return report_obj.render(
|
||||
"stock_cycle_count.stock_location_accuracy", docargs)
|
||||
59
stock_cycle_count/reports/stock_cycle_count_report.xml
Normal file
59
stock_cycle_count/reports/stock_cycle_count_report.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||
|
||||
<odoo>
|
||||
|
||||
<template id="report_cyclecount">
|
||||
<t t-call="report.html_container">
|
||||
<t t-call="report.internal_layout">
|
||||
<div class="page">
|
||||
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Cycle Count #</th>
|
||||
<th>Location</th>
|
||||
<th>Required Date</th>
|
||||
<th>Assigned to</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="sale_tbody">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<tr>
|
||||
<td>
|
||||
<span t-field="doc.name"/>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="doc.location_id"/>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="doc.date_deadline"/>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="doc.responsible_id"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="doc.state"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Report action -->
|
||||
<report
|
||||
id="action_report_stock_cycle_count"
|
||||
model="stock.cycle.count"
|
||||
name="stock_cycle_count.report_cyclecount"
|
||||
string="Cycle Count"
|
||||
report_type="qweb-pdf"
|
||||
groups="stock.group_stock_user"/>
|
||||
|
||||
</odoo>
|
||||
73
stock_cycle_count/reports/stock_location_accuracy_report.xml
Normal file
73
stock_cycle_count/reports/stock_location_accuracy_report.xml
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||
|
||||
<odoo>
|
||||
|
||||
<!-- Templates -->
|
||||
<template id="stock_location_accuracy">
|
||||
<t t-call="report.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<div class="oe_structure"/>
|
||||
<h3>
|
||||
<span>Location:</span>
|
||||
<span t-field="doc.name"/>
|
||||
</h3>
|
||||
|
||||
<div class="row mt32 mb32" id="informations">
|
||||
<div class="col-xs-6">
|
||||
<strong>Complete name:</strong>
|
||||
<p t-field="doc.complete_name"/>
|
||||
</div>
|
||||
<div class="col-xs-3">
|
||||
<strong>Current Accuracy:</strong>
|
||||
<p t-field="doc.loc_accuracy"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Inventory</th>
|
||||
<th class="text-right">Date</th>
|
||||
<th class="text-right">Accuracy</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="sale_tbody">
|
||||
<t t-foreach="data[doc]" t-as="l">
|
||||
<tr>
|
||||
<td>
|
||||
<span t-field="l.name"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.date"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.inventory_accuracy"/>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Report action -->
|
||||
<report
|
||||
id="action_report_stock_location_accuracy"
|
||||
model="stock.location"
|
||||
name="stock_location_accuracy"
|
||||
string="Accuracy report"
|
||||
report_type="qweb-pdf"
|
||||
groups="stock.group_stock_user"/>
|
||||
|
||||
</odoo>
|
||||
@@ -10,6 +10,7 @@
|
||||
<field name="inherit_id" ref="stock.view_inventory_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date" position="after">
|
||||
<field name="location_id"/>
|
||||
<field name="cycle_count_id"/>
|
||||
<field name="inventory_accuracy"/>
|
||||
</field>
|
||||
@@ -31,4 +32,52 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_inventory_filter" model="ir.ui.view">
|
||||
<field name="name">stock.inventory.filter - stock_cycle_count</field>
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="inherit_id" ref="stock.view_inventory_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="company_id" position="after">
|
||||
<field name="location_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_inventory_graph" model="ir.ui.view">
|
||||
<field name="name">stock.inventory.graph</field>
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Inventory accuracy evolution" type="line">
|
||||
<field name="cycle_count_id" type="col"/>
|
||||
<field name="inventory_accuracy" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_inventory_pivot" model="ir.ui.view">
|
||||
<field name="name">stock.inventory.pivot</field>
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Inventory Accuracy">
|
||||
<field name="date" type="col"/>
|
||||
<field name="location_id" type="row"/>
|
||||
<field name="inventory_accuracy" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="act_accuracy_stats">
|
||||
<field name="domain">[('exclude_sublocation', '=', True),
|
||||
('state', '=', 'done')]</field>
|
||||
<field name="name">Accuracy Stats</field>
|
||||
<field name="res_model">stock.inventory</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,tree,form,graph</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_report_accuracy_stats"
|
||||
name="Cycle Count Accuracy"
|
||||
parent="stock.menu_warehouse_report"
|
||||
action="act_accuracy_stats" />
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -4,15 +4,6 @@
|
||||
|
||||
<odoo>
|
||||
|
||||
<record model="ir.actions.act_window" id="act_accuracy_stats">
|
||||
<field name="domain">[('location_id', '=', active_ids),
|
||||
('state', '=', 'done')]</field>
|
||||
<field name="name">Accuracy Stats</field>
|
||||
<field name="res_model">stock.inventory</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<record id="view_location_form" model="ir.ui.view">
|
||||
<field name="name">Location form - cycle count extension</field>
|
||||
<field name="model">stock.location</field>
|
||||
@@ -20,8 +11,9 @@
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button string="Accuracy Stats" class="oe_stat_button"
|
||||
icon="fa-line-chart" name="%(act_accuracy_stats)d"
|
||||
type="action"/>
|
||||
icon="fa-line-chart" name="action_accuracy_stats"
|
||||
context="{'location_id': active_ids}"
|
||||
type="object"/>
|
||||
</xpath>
|
||||
<field name="active" position="after">
|
||||
<field name="zero_confirmation_disabled"/>
|
||||
|
||||
Reference in New Issue
Block a user