From ef14d698a3c88460472cae52e0ebbbeb95a4e8da Mon Sep 17 00:00:00 2001 From: Mathias Markl Date: Tue, 29 May 2018 19:25:41 +0200 Subject: [PATCH] .. --- muk_attachment_lobject/__manifest__.py | 2 +- .../models/ir_attachment.py | 2 +- muk_converter/__manifest__.py | 2 +- muk_converter/models/store.py | 2 +- muk_converter/wizards/convert.py | 2 +- muk_fields_lobject/__init__.py | 5 +- muk_fields_lobject/__manifest__.py | 6 +- muk_fields_lobject/base/__init__.py | 23 ++ muk_fields_lobject/base/fields.py | 24 +++ muk_fields_lobject/{ => base}/models.py | 16 +- muk_fields_lobject/doc/changelog.rst | 5 + muk_fields_lobject/fields/__init__.py | 23 ++ .../{fields.py => fields/lobject.py} | 204 +++++++++--------- muk_fields_lobject/models/__init__.py | 2 +- .../static/description/index.html | 2 +- muk_fields_lobject/tests/test_lobject.py | 2 +- muk_models_groupby_hour/README.md | 3 - muk_models_groupby_hour/__init__.py | 5 +- muk_models_groupby_hour/__manifest__.py | 15 +- muk_models_groupby_hour/base/__init__.py | 22 ++ muk_models_groupby_hour/{ => base}/models.py | 18 +- muk_models_groupby_hour/doc/changelog.rst | 5 + muk_models_groupby_hour/doc/index.rst | 46 ++++ .../static/description/index.html | 33 ++- muk_models_groupby_hour/tests/__init__.py | 2 - muk_models_groupby_hour/tests/test_groupby.py | 2 - muk_utils/__init__.py | 6 +- muk_utils/__manifest__.py | 3 +- muk_utils/tools/__init__.py | 1 + muk_utils/{ => tools}/http.py | 0 muk_utils/tools/patch.py | 43 ++++ 31 files changed, 366 insertions(+), 160 deletions(-) create mode 100644 muk_fields_lobject/base/__init__.py create mode 100644 muk_fields_lobject/base/fields.py rename muk_fields_lobject/{ => base}/models.py (82%) create mode 100644 muk_fields_lobject/fields/__init__.py rename muk_fields_lobject/{fields.py => fields/lobject.py} (96%) delete mode 100644 muk_models_groupby_hour/README.md create mode 100644 muk_models_groupby_hour/base/__init__.py rename muk_models_groupby_hour/{ => base}/models.py (85%) create mode 100644 muk_models_groupby_hour/doc/index.rst rename muk_utils/{ => tools}/http.py (100%) create mode 100644 muk_utils/tools/patch.py diff --git a/muk_attachment_lobject/__manifest__.py b/muk_attachment_lobject/__manifest__.py index 60f5b5c..2512782 100644 --- a/muk_attachment_lobject/__manifest__.py +++ b/muk_attachment_lobject/__manifest__.py @@ -22,7 +22,7 @@ { "name": "MuK Large Objects Attachment", "summary": """Large Objects Attachment Location""", - "version": '11.0.2.0.0', + "version": '11.0.2.0.1', "category": 'Extra Tools', "license": "AGPL-3", "website": "http://www.mukit.at", diff --git a/muk_attachment_lobject/models/ir_attachment.py b/muk_attachment_lobject/models/ir_attachment.py index c6947fc..9cf2157 100644 --- a/muk_attachment_lobject/models/ir_attachment.py +++ b/muk_attachment_lobject/models/ir_attachment.py @@ -26,7 +26,7 @@ import mimetypes from odoo import api, models, _ from odoo.exceptions import AccessError -from odoo.addons.muk_fields_lobject.fields import LargeObject +from odoo.addons.muk_fields_lobject.fields.lobject import LargeObject _logger = logging.getLogger(__name__) diff --git a/muk_converter/__manifest__.py b/muk_converter/__manifest__.py index 8fde0f1..97683a8 100644 --- a/muk_converter/__manifest__.py +++ b/muk_converter/__manifest__.py @@ -20,7 +20,7 @@ { "name": "MuK Converter", "summary": """Universal Converter""", - "version": '11.0.1.1.3', + "version": '11.0.1.1.4', "category": 'Extra Tools', "license": "AGPL-3", "website": "https://www.mukit.at", diff --git a/muk_converter/models/store.py b/muk_converter/models/store.py index 3e09f91..2c91968 100644 --- a/muk_converter/models/store.py +++ b/muk_converter/models/store.py @@ -21,7 +21,7 @@ import logging from odoo import api, models, fields -from odoo.addons.muk_fields_lobject.fields import LargeObject +from odoo.addons.muk_fields_lobject.fields.lobject import LargeObject _logger = logging.getLogger(__name__) diff --git a/muk_converter/wizards/convert.py b/muk_converter/wizards/convert.py index 937f835..209524f 100644 --- a/muk_converter/wizards/convert.py +++ b/muk_converter/wizards/convert.py @@ -25,7 +25,7 @@ import mimetypes from odoo import _, api, fields, models -from odoo.addons.muk_utils.http import get_response +from odoo.addons.muk_utils.tools.http import get_response from odoo.addons.muk_converter.tools import converter _logger = logging.getLogger(__name__) diff --git a/muk_fields_lobject/__init__.py b/muk_fields_lobject/__init__.py index 41504c8..38678d2 100644 --- a/muk_fields_lobject/__init__.py +++ b/muk_fields_lobject/__init__.py @@ -19,4 +19,7 @@ from . import fields from . import models -from . import controllers \ No newline at end of file +from . import controllers + +def _patch_system(): + from . import base \ No newline at end of file diff --git a/muk_fields_lobject/__manifest__.py b/muk_fields_lobject/__manifest__.py index 2dc06ff..78e233f 100644 --- a/muk_fields_lobject/__manifest__.py +++ b/muk_fields_lobject/__manifest__.py @@ -20,7 +20,7 @@ { "name": "MuK Large Objects", "summary": """PGSQL Large Objects Support""", - "version": '11.0.2.1.0', + "version": '11.0.2.2.0', "category": 'Extra Tools', "license": "AGPL-3", "website": "https://www.mukit.at", @@ -42,8 +42,8 @@ "python": [], "bin": [], }, - "auto_install": True, + "auto_install": False, "application": False, "installable": True, - + "post_load": "_patch_system", } diff --git a/muk_fields_lobject/base/__init__.py b/muk_fields_lobject/base/__init__.py new file mode 100644 index 0000000..94fc962 --- /dev/null +++ b/muk_fields_lobject/base/__init__.py @@ -0,0 +1,23 @@ +################################################################################### +# +# MuK Document Management System +# +# Copyright (C) 2018 MuK IT GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### + +from . import fields +from . import models \ No newline at end of file diff --git a/muk_fields_lobject/base/fields.py b/muk_fields_lobject/base/fields.py new file mode 100644 index 0000000..121ebfb --- /dev/null +++ b/muk_fields_lobject/base/fields.py @@ -0,0 +1,24 @@ +################################################################################### +# +# Copyright (C) 2018 MuK IT GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### + +from odoo import fields + +from odoo.addons.muk_fields_lobject.fields.lobject import LargeObject + +fields.LargeObject = LargeObject \ No newline at end of file diff --git a/muk_fields_lobject/models.py b/muk_fields_lobject/base/models.py similarity index 82% rename from muk_fields_lobject/models.py rename to muk_fields_lobject/base/models.py index fd340db..9f9b583 100644 --- a/muk_fields_lobject/models.py +++ b/muk_fields_lobject/base/models.py @@ -19,13 +19,15 @@ import logging -from odoo import models +from odoo import models, api -_logger = logging.getLogger(__name__) +from odoo.addons.muk_utils.tools import patch -unlink = models.BaseModel.unlink +_logger = logging.getLogger(__name__) -def large_object_unlink(self): +@api.multi +@patch.monkey_patch_model(models.BaseModel) +def unlink(self): oids = [] for name in self._fields: field = self._fields[name] @@ -34,8 +36,6 @@ def large_object_unlink(self): oid = record.with_context({'oid': True})[name] if oid: oids.append(oid) - unlink(self) + unlink.super(self) for oid in oids: - self.env.cr._cnx.lobject(oid, 'rb').unlink() - -models.BaseModel.unlink = large_object_unlink \ No newline at end of file + self.env.cr._cnx.lobject(oid, 'rb').unlink() \ No newline at end of file diff --git a/muk_fields_lobject/doc/changelog.rst b/muk_fields_lobject/doc/changelog.rst index 933b525..8466ee4 100644 --- a/muk_fields_lobject/doc/changelog.rst +++ b/muk_fields_lobject/doc/changelog.rst @@ -1,3 +1,8 @@ +`2.2.0` +------- + +- Monkey Patch Methods + `2.1.0` ------- diff --git a/muk_fields_lobject/fields/__init__.py b/muk_fields_lobject/fields/__init__.py new file mode 100644 index 0000000..0720944 --- /dev/null +++ b/muk_fields_lobject/fields/__init__.py @@ -0,0 +1,23 @@ + ################################################################################### +# +# Copyright (C) 2018 MuK IT GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### + +from . import lobject + +# backward compatibility +from .lobject import LargeObject diff --git a/muk_fields_lobject/fields.py b/muk_fields_lobject/fields/lobject.py similarity index 96% rename from muk_fields_lobject/fields.py rename to muk_fields_lobject/fields/lobject.py index 52ba082..7695570 100644 --- a/muk_fields_lobject/fields.py +++ b/muk_fields_lobject/fields/lobject.py @@ -1,103 +1,101 @@ -################################################################################### -# -# Copyright (C) 2018 MuK IT GmbH -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -################################################################################### - -import base64 -import hashlib -import logging -import binascii -import tempfile - -from odoo import fields -from odoo.tools import human_size - -_logger = logging.getLogger(__name__) - -class LargeObject(fields.Field): - - type = 'lobject' - column_type = ('oid', 'oid') - _slots = { - 'prefetch': False, - 'context_dependent': True, - } - - def convert_to_column(self, value, record, values=None): - oid = record.with_context({'oid': True})[self.name] - if oid: - record.env.cr._cnx.lobject(oid, 'rb').unlink() - if not value: - return None - lobject = record.env.cr._cnx.lobject(0, 'wb') - if isinstance(value, bytes): - try: - if base64.b64encode(base64.b64decode(value)) == value: - lobject.write(base64.b64decode(value)) - else: - lobject.write(value) - except binascii.Error: - lobject.write(value) - elif isinstance(value, str): - lobject.write(base64.b64decode(value.encode('ascii'))) - else: - while True: - chunk = value.read(4096) - if not chunk: - break - lobject.write(chunk) - return lobject.oid - - def convert_to_record(self, value, record): - if value and isinstance(value, int): - lobject = record.env.cr._cnx.lobject(value, 'rb') - if record._context.get('human_size'): - return human_size(lobject.seek(0, 2)) - elif record._context.get('bin_size'): - return lobject.seek(0, 2) - elif record._context.get('oid'): - return lobject.oid - elif record._context.get('base64'): - return base64.b64encode(lobject.read()) - elif record._context.get('stream'): - file = tempfile.TemporaryFile() - while True: - chunk = lobject.read(4096) - if not chunk: - file.seek(0) - return file - file.write(chunk) - elif record._context.get('checksum'): - checksum = hashlib.md5() - while True: - chunk = lobject.read(4096) - if not chunk: - return checksum.hexdigest() - checksum.update(chunk) - else: - return lobject.read() - return value - - def convert_to_export(self, value, record): - if value: - lobject = record.env.cr._cnx.lobject(value, 'rb') - if record._context.get('export_raw_data'): - return lobject.read() - return base64.b64encode(lobject.read()) - return '' - -fields.LargeObject = LargeObject \ No newline at end of file +################################################################################### +# +# Copyright (C) 2018 MuK IT GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### + +import base64 +import hashlib +import logging +import binascii +import tempfile + +from odoo import fields +from odoo.tools import human_size + +_logger = logging.getLogger(__name__) + +class LargeObject(fields.Field): + + type = 'lobject' + column_type = ('oid', 'oid') + _slots = { + 'prefetch': False, + 'context_dependent': True, + } + + def convert_to_column(self, value, record, values=None): + oid = record.with_context({'oid': True})[self.name] + if oid: + record.env.cr._cnx.lobject(oid, 'rb').unlink() + if not value: + return None + lobject = record.env.cr._cnx.lobject(0, 'wb') + if isinstance(value, bytes): + try: + if base64.b64encode(base64.b64decode(value)) == value: + lobject.write(base64.b64decode(value)) + else: + lobject.write(value) + except binascii.Error: + lobject.write(value) + elif isinstance(value, str): + lobject.write(base64.b64decode(value.encode('ascii'))) + else: + while True: + chunk = value.read(4096) + if not chunk: + break + lobject.write(chunk) + return lobject.oid + + def convert_to_record(self, value, record): + if value and isinstance(value, int): + lobject = record.env.cr._cnx.lobject(value, 'rb') + if record._context.get('human_size'): + return human_size(lobject.seek(0, 2)) + elif record._context.get('bin_size'): + return lobject.seek(0, 2) + elif record._context.get('oid'): + return lobject.oid + elif record._context.get('base64'): + return base64.b64encode(lobject.read()) + elif record._context.get('stream'): + file = tempfile.TemporaryFile() + while True: + chunk = lobject.read(4096) + if not chunk: + file.seek(0) + return file + file.write(chunk) + elif record._context.get('checksum'): + checksum = hashlib.md5() + while True: + chunk = lobject.read(4096) + if not chunk: + return checksum.hexdigest() + checksum.update(chunk) + else: + return lobject.read() + return value + + def convert_to_export(self, value, record): + if value: + lobject = record.env.cr._cnx.lobject(value, 'rb') + if record._context.get('export_raw_data'): + return lobject.read() + return base64.b64encode(lobject.read()) + return '' \ No newline at end of file diff --git a/muk_fields_lobject/models/__init__.py b/muk_fields_lobject/models/__init__.py index 961ed22..471635d 100644 --- a/muk_fields_lobject/models/__init__.py +++ b/muk_fields_lobject/models/__init__.py @@ -1,4 +1,4 @@ -################################################################################### + ################################################################################### # # Copyright (C) 2018 MuK IT GmbH # diff --git a/muk_fields_lobject/static/description/index.html b/muk_fields_lobject/static/description/index.html index 22cbf77..46d8ecc 100644 --- a/muk_fields_lobject/static/description/index.html +++ b/muk_fields_lobject/static/description/index.html @@ -55,7 +55,7 @@
 		    	
-from odoo.addons.muk_fields_lobject.fields import LargeObject
+from odoo.addons.muk_fields_lobject.fields.lobject import LargeObject
 
 class LargeObjectModel(models.Model):
 
diff --git a/muk_fields_lobject/tests/test_lobject.py b/muk_fields_lobject/tests/test_lobject.py
index de1e6d7..c500a48 100644
--- a/muk_fields_lobject/tests/test_lobject.py
+++ b/muk_fields_lobject/tests/test_lobject.py
@@ -22,7 +22,7 @@ import logging
 
 from odoo.tests import common
 
-from odoo.addons.muk_fields_lobject.fields import LargeObject
+from odoo.addons.muk_fields_lobject.fields.lobject import LargeObject
 
 _path = os.path.dirname(os.path.dirname(__file__))
 _logger = logging.getLogger(__name__)
diff --git a/muk_models_groupby_hour/README.md b/muk_models_groupby_hour/README.md
deleted file mode 100644
index f0ac741..0000000
--- a/muk_models_groupby_hour/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# MuK Groupby Hour
-
-Allow records to be grouped by hour.
\ No newline at end of file
diff --git a/muk_models_groupby_hour/__init__.py b/muk_models_groupby_hour/__init__.py
index ae4b147..a62c730 100644
--- a/muk_models_groupby_hour/__init__.py
+++ b/muk_models_groupby_hour/__init__.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-
 ###################################################################################
 # 
 #    Copyright (C) 2018 MuK IT GmbH
@@ -19,4 +17,5 @@
 #
 ###################################################################################
 
-from . import models
\ No newline at end of file
+def _patch_system():
+    from . import base
\ No newline at end of file
diff --git a/muk_models_groupby_hour/__manifest__.py b/muk_models_groupby_hour/__manifest__.py
index 5fa2547..ba03db1 100644
--- a/muk_models_groupby_hour/__manifest__.py
+++ b/muk_models_groupby_hour/__manifest__.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-
 ###################################################################################
 # 
 #    Copyright (C) 2018 MuK IT GmbH
@@ -22,10 +20,7 @@
 {
     "name": "MuK Groupby Hour",
     "summary": """Group records by hour""",
-    "description": """ 
-        Allow records to be grouped by hour.
-    """,
-    "version": '11.0.1.0.1',   
+    "version": '11.0.2.0.0',   
     "category": 'Extra Tools',   
     "license": "AGPL-3",
     "website": "http://www.mukit.at",
@@ -34,12 +29,10 @@
         "Mathias Markl ",
     ],
     "depends": [
-        "base",
+        "muk_utils",
     ],
     "data": [
     ],
-    "demo": [
-    ],
     "qweb": [
         "static/src/xml/*.xml",
     ],
@@ -50,8 +43,8 @@
         "python": [],
         "bin": [],
     },
-    "auto_install": True,
+    "auto_install": False,
     "application": False,
     "installable": True,
-    
+    "post_load": "_patch_system",
 }
\ No newline at end of file
diff --git a/muk_models_groupby_hour/base/__init__.py b/muk_models_groupby_hour/base/__init__.py
new file mode 100644
index 0000000..bb5b74e
--- /dev/null
+++ b/muk_models_groupby_hour/base/__init__.py
@@ -0,0 +1,22 @@
+###################################################################################
+# 
+#    MuK Document Management System
+#
+#    Copyright (C) 2018 MuK IT GmbH
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see .
+#
+###################################################################################
+
+from . import models
\ No newline at end of file
diff --git a/muk_models_groupby_hour/models.py b/muk_models_groupby_hour/base/models.py
similarity index 85%
rename from muk_models_groupby_hour/models.py
rename to muk_models_groupby_hour/base/models.py
index cb60626..45c5bc5 100644
--- a/muk_models_groupby_hour/models.py
+++ b/muk_models_groupby_hour/base/models.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-
 ###################################################################################
 # 
 #    Copyright (C) 2018 MuK IT GmbH
@@ -30,11 +28,13 @@ from odoo import _
 from odoo import models, api, fields
 from odoo.tools import ustr, pycompat, human_size
 
-_logger = logging.getLogger(__name__)
-
-_read_group_process_groupby = models.BaseModel._read_group_process_groupby
+from odoo.addons.muk_utils.tools import patch
 
-def _read_group_process_groupby_hour(self, gb, query):
+_logger = logging.getLogger(__name__)
+        
+@api.model   
+@patch.monkey_patch_model(models.BaseModel)
+def _read_group_process_groupby(self, gb, query):
     split = gb.split(':')
     field_type = self._fields[split[0]].type
     gb_function = split[1] if len(split) == 2 else None
@@ -56,8 +56,4 @@ def _read_group_process_groupby_hour(self, gb, query):
             'tz_convert': tz_convert,
             'qualified_field': qualified_field
         }
-    return _read_group_process_groupby(self, gb, query)
-    
-     
-    
-models.BaseModel._read_group_process_groupby = _read_group_process_groupby_hour
\ No newline at end of file
+    return _read_group_process_groupby.super(self, gb, query)
\ No newline at end of file
diff --git a/muk_models_groupby_hour/doc/changelog.rst b/muk_models_groupby_hour/doc/changelog.rst
index 9ee2b48..f2ae21c 100644
--- a/muk_models_groupby_hour/doc/changelog.rst
+++ b/muk_models_groupby_hour/doc/changelog.rst
@@ -1,3 +1,8 @@
+`2.0.0`
+-------
+
+- Migrated to Python 3
+
 `1.0.0`
 -------
 
diff --git a/muk_models_groupby_hour/doc/index.rst b/muk_models_groupby_hour/doc/index.rst
new file mode 100644
index 0000000..5d2e39e
--- /dev/null
+++ b/muk_models_groupby_hour/doc/index.rst
@@ -0,0 +1,46 @@
+================
+MuK Groupby Hour
+================
+
+Technical module to provide some utility features to enable group by hour. This
+module has no direct effect on the running system.
+
+Installation
+============
+
+To install this module, you need to:
+
+Download the module and add it to your Odoo addons folder. Afterward, log on to
+your Odoo server and go to the Apps menu. Trigger the debug modus and update the
+list by clicking on the "Update Apps List" link. Now install the module by
+clicking on the install button.
+
+Configuration
+=============
+
+No additional configuration is needed to use this module.
+
+Usage
+=============
+
+This module has no direct visible effect on the system. It provide utility features.
+
+Credits
+=======
+
+Contributors
+------------
+
+* Mathias Markl 
+
+Author & Maintainer
+-------------------
+
+This module is maintained by the `MuK IT GmbH `_.
+
+MuK IT is an Austrian company specialized in customizing and extending Odoo.
+We develop custom solutions for your individual needs to help you focus on
+your strength and expertise to grow your business.
+
+If you want to get in touch please contact us via mail
+(sale@mukit.at) or visit our website (https://mukit.at).
diff --git a/muk_models_groupby_hour/static/description/index.html b/muk_models_groupby_hour/static/description/index.html
index f7a9b4b..94ec278 100644
--- a/muk_models_groupby_hour/static/description/index.html
+++ b/muk_models_groupby_hour/static/description/index.html
@@ -9,7 +9,7 @@
 
 
-
+

Overview

@@ -37,14 +37,45 @@ def sales_per_hour(self):
+
+

Demo

+
+
+
User:
+
+
+
apps
+
+
+
Password:
+
+
+
demo
+
+
+ +
+

Help and Support

+
Feel free to + contact us, if you need any help with your Odoo integration or addiontal + features.
. +# +################################################################################### + +import logging + +from odoo import api + +_logger = logging.getLogger(__name__) + +def monkey_patch(cls): + def decorate(func): + name = func.__name__ + func.super = getattr(cls, name, None) + setattr(cls, name, func) + return func + return decorate + +def monkey_patch_model(cls): + def decorate(func): + name = func.__name__ + super = getattr(cls, name, None) + func.super = super + wrapped = api.guess(api.propagate(name, func)) + wrapped.super = super + setattr(cls, name, wrapped) + return func + return decorate