changeset 5ea0f19ebaf3 in modules/sale_opportunity:default
details: 
https://hg.tryton.org/modules/sale_opportunity?cmd=changeset&node=5ea0f19ebaf3
description:
        Use Date field for monthly report

        issue11366
        review384861002
diffstat:

 CHANGELOG                                  |   1 +
 opportunity.py                             |  76 ++++++++++++++---------------
 view/opportunity_employee_monthly_tree.xml |   3 +-
 view/opportunity_monthly_graph1.xml        |   2 +-
 view/opportunity_monthly_graph2.xml        |   2 +-
 view/opportunity_monthly_tree.xml          |   3 +-
 6 files changed, 41 insertions(+), 46 deletions(-)

diffs (184 lines):

diff -r 7d74e4665608 -r 5ea0f19ebaf3 CHANGELOG
--- a/CHANGELOG Sun Apr 10 19:11:39 2022 +0200
+++ b/CHANGELOG Mon Apr 11 22:26:17 2022 +0200
@@ -1,3 +1,4 @@
+* Use Date field for monthly report
 * Add support for Python 3.10
 * Remove support for Python 3.6
 
diff -r 7d74e4665608 -r 5ea0f19ebaf3 opportunity.py
--- a/opportunity.py    Sun Apr 10 19:11:39 2022 +0200
+++ b/opportunity.py    Mon Apr 11 22:26:17 2022 +0200
@@ -7,7 +7,7 @@
 from sql import Literal, Null
 from sql.aggregate import Count, Max, Sum
 from sql.conditionals import Case, Coalesce
-from sql.functions import Extract
+from sql.functions import DateTrunc, Extract
 
 from trytond.i18n import gettext
 from trytond.ir.attachment import AttachmentCopyMixin
@@ -699,22 +699,30 @@
     end_date = fields.Date('End Date')
 
 
-class SaleOpportunityMonthly(SaleOpportunityReportMixin, ModelSQL, ModelView):
+class MonthLabelMixin:
+    __slots__ = ()
+
+    month_label = fields.Function(fields.Char("Month"), 'get_month_label')
+
+    @classmethod
+    def order_month_label(cls, tables):
+        table, _ = tables[None]
+        return [table.month]
+
+    def get_month_label(self, name):
+        return self.month.strftime('%Y-%m')
+
+
+class SaleOpportunityMonthly(
+        MonthLabelMixin, SaleOpportunityReportMixin, ModelSQL, ModelView):
     'Sale Opportunity per Month'
     __name__ = 'sale.opportunity_monthly'
-    year = fields.Integer("Year")
-    month = fields.Many2One('ir.calendar.month', "Month")
-    year_month = fields.Function(fields.Char('Year-Month'),
-            'get_year_month')
+    month = fields.Date("Month")
 
     @classmethod
     def __setup__(cls):
         super(SaleOpportunityMonthly, cls).__setup__()
-        cls._order.insert(0, ('year', 'DESC'))
-        cls._order.insert(1, ('month.index', 'DESC'))
-
-    def get_year_month(self, name):
-        return '%s-%s' % (self.year, self.month.index)
+        cls._order.insert(0, ('month', 'DESC'))
 
     @classmethod
     def table_query(cls):
@@ -723,34 +731,28 @@
         month = Month.__table__()
         query = super(SaleOpportunityMonthly, cls).table_query()
         opportunity, = query.from_
-        type_id = cls.id.sql_type().base
-        year_column = Extract('YEAR', opportunity.start_date).as_('year')
-        month_index = Extract('MONTH', opportunity.start_date)
-        query.from_ = opportunity.join(
-            month, condition=month_index == month.index)
+        month_timestamp = DateTrunc('MONTH', opportunity.start_date)
+        id_ = Extract('EPOCH', month_timestamp)
+        month = cls.month.sql_cast(month_timestamp)
         query.columns += (
-            Max(Extract('MONTH', opportunity.start_date)
-                + Extract('YEAR', opportunity.start_date) * 100
-                ).cast(type_id).as_('id'),
-            year_column,
-            month.id.as_('month'))
-        query.group_by = (year_column, month.id, opportunity.company)
+            id_.as_('id'),
+            month.as_('month'),
+            )
+        query.group_by = [id_, month, opportunity.company]
         return query
 
 
 class SaleOpportunityEmployeeMonthly(
-        SaleOpportunityReportMixin, ModelSQL, ModelView):
+        MonthLabelMixin, SaleOpportunityReportMixin, ModelSQL, ModelView):
     'Sale Opportunity per Employee per Month'
     __name__ = 'sale.opportunity_employee_monthly'
-    year = fields.Integer("Year")
-    month = fields.Many2One('ir.calendar.month', "Month")
+    month = fields.Date("Month")
     employee = fields.Many2One('company.employee', 'Employee')
 
     @classmethod
     def __setup__(cls):
         super(SaleOpportunityEmployeeMonthly, cls).__setup__()
-        cls._order.insert(0, ('year', 'DESC'))
-        cls._order.insert(1, ('month.index', 'DESC'))
+        cls._order.insert(1, ('month', 'DESC'))
         cls._order.insert(2, ('employee', 'ASC'))
 
     @classmethod
@@ -760,20 +762,14 @@
         month = Month.__table__()
         query = super(SaleOpportunityEmployeeMonthly, cls).table_query()
         opportunity, = query.from_
-        type_id = cls.id.sql_type().base
-        year_column = Extract('YEAR', opportunity.start_date).as_('year')
-        month_index = Extract('MONTH', opportunity.start_date)
-        query.from_ = opportunity.join(
-            month, condition=month_index == month.index)
+        month_timestamp = DateTrunc('MONTH', opportunity.start_date)
+        id_ = Extract('EPOCH', month_timestamp)
+        month = cls.month.sql_cast(month_timestamp)
         query.columns += (
-            Max(Extract('MONTH', opportunity.start_date)
-                + Extract('YEAR', opportunity.start_date) * 100
-                + Coalesce(opportunity.employee, 0) * 1000000
-                ).cast(type_id).as_('id'),
-            year_column,
-            month.id.as_('month'),
+            id_.as_('id'),
+            month.as_('month'),
             opportunity.employee,
             )
-        query.group_by = (year_column, month.id,
-            opportunity.employee, opportunity.company)
+        query.group_by = [
+            id_, month, opportunity.employee, opportunity.company]
         return query
diff -r 7d74e4665608 -r 5ea0f19ebaf3 view/opportunity_employee_monthly_tree.xml
--- a/view/opportunity_employee_monthly_tree.xml        Sun Apr 10 19:11:39 
2022 +0200
+++ b/view/opportunity_employee_monthly_tree.xml        Mon Apr 11 22:26:17 
2022 +0200
@@ -2,8 +2,7 @@
 <!-- This file is part of Tryton.  The COPYRIGHT file at the top level of
 this repository contains the full copyright notices and license terms. -->
 <tree>
-    <field name="year" grouping="0"/>
-    <field name="month" widget="selection"/>
+    <field name="month"/>
     <field name="employee" expand="1"/>
     <field name="number" optional="1"/>
     <field name="converted" optional="1"/>
diff -r 7d74e4665608 -r 5ea0f19ebaf3 view/opportunity_monthly_graph1.xml
--- a/view/opportunity_monthly_graph1.xml       Sun Apr 10 19:11:39 2022 +0200
+++ b/view/opportunity_monthly_graph1.xml       Mon Apr 11 22:26:17 2022 +0200
@@ -3,7 +3,7 @@
 this repository contains the full copyright notices and license terms. -->
 <graph>
     <x>
-        <field name="year_month"/>
+        <field name="month_label"/>
     </x>
     <y>
         <field name="number"/>
diff -r 7d74e4665608 -r 5ea0f19ebaf3 view/opportunity_monthly_graph2.xml
--- a/view/opportunity_monthly_graph2.xml       Sun Apr 10 19:11:39 2022 +0200
+++ b/view/opportunity_monthly_graph2.xml       Mon Apr 11 22:26:17 2022 +0200
@@ -3,7 +3,7 @@
 this repository contains the full copyright notices and license terms. -->
 <graph>
     <x>
-        <field name="year_month"/>
+        <field name="month_label"/>
     </x>
     <y>
         <field name="amount"/>
diff -r 7d74e4665608 -r 5ea0f19ebaf3 view/opportunity_monthly_tree.xml
--- a/view/opportunity_monthly_tree.xml Sun Apr 10 19:11:39 2022 +0200
+++ b/view/opportunity_monthly_tree.xml Mon Apr 11 22:26:17 2022 +0200
@@ -2,8 +2,7 @@
 <!-- This file is part of Tryton.  The COPYRIGHT file at the top level of
 this repository contains the full copyright notices and license terms. -->
 <tree>
-    <field name="year" grouping="0"/>
-    <field name="month" widget="selection"/>
+    <field name="month"/>
     <field name="number" optional="1"/>
     <field name="converted" optional="1"/>
     <field name="won" optional="0"/>

Reply via email to