Open reporting per product from reporting per product category
issue10489 review358211002
This commit is contained in:
1 parent
b2397091db
commit
4de662e12e
9 files changed
+113
-100
No files matched your search
+3
-3
@@ -39,9 +39,9 @@ def register():
|
||||
sale_reporting.CustomerTimeseries,
|
||||
sale_reporting.Product,
|
||||
sale_reporting.ProductTimeseries,
|
||||
sale_reporting.Category,
|
||||
sale_reporting.CategoryTimeseries,
|
||||
sale_reporting.CategoryTree,
|
||||
sale_reporting.ProductCategory,
|
||||
sale_reporting.ProductCategoryTimeseries,
|
||||
sale_reporting.ProductCategoryTree,
|
||||
sale_reporting.Country,
|
||||
sale_reporting.CountryTimeseries,
|
||||
sale_reporting.Subdivision,
|
||||
|
||||
+29
-26
@@ -376,7 +376,7 @@ class ProductTimeseries(ProductMixin, AbstractTimeseries, ModelView):
|
||||
__name__ = 'sale.reporting.product.time_series'
|
||||
|
||||
|
||||
class CategoryMixin(object):
|
||||
class ProductCategoryMixin(object):
|
||||
__slots__ = ()
|
||||
category = fields.Many2One(
|
||||
'product.category', "Category",
|
||||
@@ -390,7 +390,7 @@ class CategoryMixin(object):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
TemplateCategory = pool.get('product.template-product.category.all')
|
||||
from_item, tables, withs = super(CategoryMixin, cls)._joins()
|
||||
from_item, tables, withs = super()._joins()
|
||||
if 'line.product' not in tables:
|
||||
product = Product.__table__()
|
||||
tables['line.product'] = product
|
||||
@@ -409,7 +409,7 @@ class CategoryMixin(object):
|
||||
@classmethod
|
||||
def _columns(cls, tables, withs):
|
||||
template_category = tables['line.product.template_category']
|
||||
return super(CategoryMixin, cls)._columns(tables, withs) + [
|
||||
return super()._columns(tables, withs) + [
|
||||
template_category.category.as_('category')]
|
||||
|
||||
@classmethod
|
||||
@@ -428,13 +428,12 @@ class CategoryMixin(object):
|
||||
@classmethod
|
||||
def _group_by(cls, tables, withs):
|
||||
template_category = tables['line.product.template_category']
|
||||
return super(CategoryMixin, cls)._group_by(tables, withs) + [
|
||||
template_category.category]
|
||||
return super()._group_by(tables, withs) + [template_category.category]
|
||||
|
||||
@classmethod
|
||||
def _where(cls, tables, withs):
|
||||
template_category = tables['line.product.template_category']
|
||||
where = super(CategoryMixin, cls)._where(tables, withs)
|
||||
where = super()._where(tables, withs)
|
||||
where &= template_category.category != Null
|
||||
return where
|
||||
|
||||
@@ -442,12 +441,13 @@ class CategoryMixin(object):
|
||||
return self.category.rec_name if self.category else None
|
||||
|
||||
|
||||
class Category(CategoryMixin, Abstract, ModelView):
|
||||
"Sale Reporting per Category"
|
||||
__name__ = 'sale.reporting.category'
|
||||
class ProductCategory(ProductCategoryMixin, Abstract, ModelView):
|
||||
"Sale Reporting per Product Category"
|
||||
__name__ = 'sale.reporting.product.category'
|
||||
|
||||
time_series = fields.One2Many(
|
||||
'sale.reporting.category.time_series', 'category', "Time Series")
|
||||
'sale.reporting.product.category.time_series', 'category',
|
||||
"Time Series")
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
@@ -460,19 +460,20 @@ class Category(CategoryMixin, Abstract, ModelView):
|
||||
return template_category.category
|
||||
|
||||
|
||||
class CategoryTimeseries(CategoryMixin, AbstractTimeseries, ModelView):
|
||||
"Sale Reporting per Category"
|
||||
__name__ = 'sale.reporting.category.time_series'
|
||||
class ProductCategoryTimeseries(
|
||||
ProductCategoryMixin, AbstractTimeseries, ModelView):
|
||||
"Sale Reporting per Product Category"
|
||||
__name__ = 'sale.reporting.product.category.time_series'
|
||||
|
||||
|
||||
class CategoryTree(ModelSQL, ModelView):
|
||||
"Sale Reporting per Category"
|
||||
__name__ = 'sale.reporting.category.tree'
|
||||
class ProductCategoryTree(ModelSQL, ModelView):
|
||||
"Sale Reporting per Product Category"
|
||||
__name__ = 'sale.reporting.product.category.tree'
|
||||
|
||||
name = fields.Function(fields.Char("Name"), 'get_name')
|
||||
parent = fields.Many2One('sale.reporting.category.tree', "Parent")
|
||||
parent = fields.Many2One('sale.reporting.product.category.tree', "Parent")
|
||||
children = fields.One2Many(
|
||||
'sale.reporting.category.tree', 'parent', "Children")
|
||||
'sale.reporting.product.category.tree', 'parent', "Children")
|
||||
revenue = fields.Function(
|
||||
fields.Numeric("Revenue", digits=(16, Eval('currency_digits', 2)),
|
||||
depends=['currency_digits']), 'get_total')
|
||||
@@ -517,9 +518,9 @@ class CategoryTree(ModelSQL, ModelView):
|
||||
@classmethod
|
||||
def get_total(cls, categories, names):
|
||||
pool = Pool()
|
||||
ReportingCategory = pool.get('sale.reporting.category')
|
||||
ReportingProductCategory = pool.get('sale.reporting.product.category')
|
||||
table = cls.__table__()
|
||||
reporting_category = ReportingCategory.__table__()
|
||||
reporting_product_category = ReportingProductCategory.__table__()
|
||||
cursor = Transaction().connection.cursor()
|
||||
|
||||
categories = cls.search([
|
||||
@@ -527,24 +528,26 @@ class CategoryTree(ModelSQL, ModelView):
|
||||
])
|
||||
ids = [c.id for c in categories]
|
||||
parents = {}
|
||||
reporting_categories = []
|
||||
reporting_product_categories = []
|
||||
for sub_ids in grouped_slice(ids):
|
||||
sub_ids = list(sub_ids)
|
||||
where = reduce_ids(table.id, sub_ids)
|
||||
cursor.execute(*table.select(table.id, table.parent, where=where))
|
||||
parents.update(cursor)
|
||||
|
||||
where = reduce_ids(reporting_category.id, sub_ids)
|
||||
where = reduce_ids(reporting_product_category.id, sub_ids)
|
||||
cursor.execute(
|
||||
*reporting_category.select(reporting_category.id, where=where))
|
||||
reporting_categories.extend(r for r, in cursor)
|
||||
*reporting_product_category.select(
|
||||
reporting_product_category.id, where=where))
|
||||
reporting_product_categories.extend(r for r, in cursor)
|
||||
|
||||
result = {}
|
||||
reporting_categories = ReportingCategory.browse(reporting_categories)
|
||||
reporting_product_categories = ReportingProductCategory.browse(
|
||||
reporting_product_categories)
|
||||
for name in names:
|
||||
values = dict.fromkeys(ids, 0)
|
||||
values.update(
|
||||
(c.id, getattr(c, name)) for c in reporting_categories)
|
||||
(c.id, getattr(c, name)) for c in reporting_product_categories)
|
||||
result[name] = cls._sum_tree(categories, values, parents)
|
||||
return result
|
||||
|
||||
|
||||
+73
-64
@@ -197,6 +197,10 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="name">Sales per Product</field>
|
||||
<field name="res_model">sale.reporting.product</field>
|
||||
<field name="context_model">sale.reporting.context</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="If(Eval('active_model') == 'sale.reporting.product.category.tree', [('product', 'where', [('categories_all', 'child_of', Eval('active_ids', []), 'parent')])], [])"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_product_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
@@ -218,6 +222,11 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="model" eval="'ir.ui.menu,%s' % ref('menu_reporting_sale')"/>
|
||||
<field name="action" ref="act_reporting_product"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_product_keyword2">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">sale.reporting.product.category.tree,-1</field>
|
||||
<field name="action" ref="act_reporting_product"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_product_companies">
|
||||
<field name="name">User in companies</field>
|
||||
@@ -323,79 +332,79 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- Category -->
|
||||
<!-- Product Category -->
|
||||
|
||||
<record model="ir.ui.view" id="reporting_category_view_tree">
|
||||
<field name="model">sale.reporting.category.tree</field>
|
||||
<record model="ir.ui.view" id="reporting_product_category_view_tree">
|
||||
<field name="model">sale.reporting.product.category.tree</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="field_childs">children</field>
|
||||
<field name="name">sale_reporting_category_tree</field>
|
||||
<field name="name">sale_reporting_product_category_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_category_tree">
|
||||
<field name="name">Sales per Category</field>
|
||||
<field name="res_model">sale.reporting.category.tree</field>
|
||||
<record model="ir.action.act_window" id="act_reporting_product_category_tree">
|
||||
<field name="name">Sales per Product Category</field>
|
||||
<field name="res_model">sale.reporting.product.category.tree</field>
|
||||
<field name="context_model">sale.reporting.context</field>
|
||||
<field name="domain" eval="[('parent', '=', None)]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_category_tree_view1">
|
||||
<record model="ir.action.act_window.view" id="act_reporting_product_category_tree_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_category_view_tree"/>
|
||||
<field name="act_window" ref="act_reporting_category_tree"/>
|
||||
<field name="view" ref="reporting_product_category_view_tree"/>
|
||||
<field name="act_window" ref="act_reporting_product_category_tree"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_category_tree_keyword1">
|
||||
<record model="ir.action.keyword" id="act_reporting_product_category_tree_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model" eval="'ir.ui.menu,%s' % ref('menu_reporting_sale')"/>
|
||||
<field name="action" ref="act_reporting_category_tree"/>
|
||||
<field name="action" ref="act_reporting_product_category_tree"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_category_view_list">
|
||||
<field name="model">sale.reporting.category</field>
|
||||
<record model="ir.ui.view" id="reporting_product_category_view_list">
|
||||
<field name="model">sale.reporting.product.category</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">sale_reporting_category_list</field>
|
||||
<field name="name">sale_reporting_product_category_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_category">
|
||||
<field name="name">Sales per Category</field>
|
||||
<field name="res_model">sale.reporting.category</field>
|
||||
<record model="ir.action.act_window" id="act_reporting_product_category">
|
||||
<field name="name">Sales per Product Category</field>
|
||||
<field name="res_model">sale.reporting.product.category</field>
|
||||
<field name="context_model">sale.reporting.context</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('category', 'child_of', Eval('active_ids', []), 'parent')]"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_category_view1">
|
||||
<record model="ir.action.act_window.view" id="act_reporting_product_category_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_category_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_category"/>
|
||||
<field name="view" ref="reporting_product_category_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_product_category"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_category_keyword1">
|
||||
<record model="ir.action.keyword" id="act_reporting_product_category_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">sale.reporting.category.tree,-1</field>
|
||||
<field name="action" ref="act_reporting_category"/>
|
||||
<field name="model">sale.reporting.product.category.tree,-1</field>
|
||||
<field name="action" ref="act_reporting_product_category"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_category_companies">
|
||||
<record model="ir.rule.group" id="rule_group_reporting_product_category_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.category')]"/>
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.product.category')]"/>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_category_companies">
|
||||
<record model="ir.rule" id="rule_reporting_product_category_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_category_companies"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_product_category_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_category">
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.category')]"/>
|
||||
<record model="ir.model.access" id="access_reporting_product_category">
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.product.category')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_category_sale">
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.category')]"/>
|
||||
<record model="ir.model.access" id="access_reporting_product_category_sale">
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.product.category')]"/>
|
||||
<field name="group" ref="group_sale"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
@@ -403,27 +412,27 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_category_time_series_view_list">
|
||||
<field name="model">sale.reporting.category.time_series</field>
|
||||
<record model="ir.ui.view" id="reporting_product_category_time_series_view_list">
|
||||
<field name="model">sale.reporting.product.category.time_series</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">sale_reporting_category_time_series_list</field>
|
||||
<field name="name">sale_reporting_product_category_time_series_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_category_time_series_view_graph_revenue">
|
||||
<field name="model">sale.reporting.category.time_series</field>
|
||||
<record model="ir.ui.view" id="reporting_product_category_time_series_view_graph_revenue">
|
||||
<field name="model">sale.reporting.product.category.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">sale_reporting_category_time_series_graph_revenue</field>
|
||||
<field name="name">sale_reporting_product_category_time_series_graph_revenue</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_category_time_series_view_graph_number">
|
||||
<field name="model">sale.reporting.category.time_series</field>
|
||||
<record model="ir.ui.view" id="reporting_product_category_time_series_view_graph_number">
|
||||
<field name="model">sale.reporting.product.category.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">sale_reporting_category_time_series_graph_number</field>
|
||||
<field name="name">sale_reporting_product_category_time_series_graph_number</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_category_time_series">
|
||||
<field name="name">Sales per Category</field>
|
||||
<field name="res_model">sale.reporting.category.time_series</field>
|
||||
<record model="ir.action.act_window" id="act_reporting_product_category_time_series">
|
||||
<field name="name">Sales per Product Category</field>
|
||||
<field name="res_model">sale.reporting.product.category.time_series</field>
|
||||
<field name="context_model">sale.reporting.context</field>
|
||||
<field
|
||||
name="domain"
|
||||
@@ -431,48 +440,48 @@ this repository contains the full copyright notices and license terms. -->
|
||||
pyson="1"/>
|
||||
<field name="order" eval="[('date', 'DESC')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_category_time_series_list_view1">
|
||||
<record model="ir.action.act_window.view" id="act_reporting_product_category_time_series_list_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_category_time_series_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_category_time_series"/>
|
||||
<field name="view" ref="reporting_product_category_time_series_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_product_category_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_category_time_series_list_view2">
|
||||
<record model="ir.action.act_window.view" id="act_reporting_product_category_time_series_list_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_category_time_series_view_graph_revenue"/>
|
||||
<field name="act_window" ref="act_reporting_category_time_series"/>
|
||||
<field name="view" ref="reporting_product_category_time_series_view_graph_revenue"/>
|
||||
<field name="act_window" ref="act_reporting_product_category_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_category_time_series_list_view3">
|
||||
<record model="ir.action.act_window.view" id="act_reporting_product_category_time_series_list_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_category_time_series_view_graph_number"/>
|
||||
<field name="act_window" ref="act_reporting_category_time_series"/>
|
||||
<field name="view" ref="reporting_product_category_time_series_view_graph_number"/>
|
||||
<field name="act_window" ref="act_reporting_product_category_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_category_time_series_list_keyword1">
|
||||
<record model="ir.action.keyword" id="act_reporting_product_category_time_series_list_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">sale.reporting.category,-1</field>
|
||||
<field name="action" ref="act_reporting_category_time_series"/>
|
||||
<field name="model">sale.reporting.product.category,-1</field>
|
||||
<field name="action" ref="act_reporting_product_category_time_series"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_category_time_series_companies">
|
||||
<record model="ir.rule.group" id="rule_group_reporting_product_category_time_series_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.category.time_series')]"/>
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.product.category.time_series')]"/>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_category_time_series_companies">
|
||||
<record model="ir.rule" id="rule_reporting_product_category_time_series_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_category_time_series_companies"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_product_category_time_series_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_category_time_series">
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.category.time_series')]"/>
|
||||
<record model="ir.model.access" id="access_reporting_product_category_time_series">
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.product.category.time_series')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_category_time_series_sale">
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.category.time_series')]"/>
|
||||
<record model="ir.model.access" id="access_reporting_product_category_time_series_sale">
|
||||
<field name="model" search="[('model', '=', 'sale.reporting.product.category.time_series')]"/>
|
||||
<field name="group" ref="group_sale"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
|
||||
@@ -183,15 +183,16 @@ Check sale reporting per product::
|
||||
... (product1.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))])
|
||||
True
|
||||
|
||||
Check sale reporting per categories::
|
||||
Check sale reporting per product categories::
|
||||
|
||||
>>> Category = Model.get('sale.reporting.category')
|
||||
>>> CategoryTimeseries = Model.get('sale.reporting.category.time_series')
|
||||
>>> CategoryTree = Model.get('sale.reporting.category.tree')
|
||||
>>> ProductCategory = Model.get('sale.reporting.product.category')
|
||||
>>> ProductCategoryTimeseries = Model.get(
|
||||
... 'sale.reporting.product.category.time_series')
|
||||
>>> ProductCategoryTree = Model.get('sale.reporting.product.category.tree')
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = Category.find([])
|
||||
... time_series = CategoryTimeseries.find([])
|
||||
... tree = CategoryTree.find([])
|
||||
... reports = ProductCategory.find([])
|
||||
... time_series = ProductCategoryTimeseries.find([])
|
||||
... tree = ProductCategoryTree.find([])
|
||||
>>> len(reports)
|
||||
4
|
||||
>>> with config.set_context(context=context):
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user