Browse Source

publish muk_utils - 13.0

pull/31/head
MuK IT GmbH 5 years ago
parent
commit
003d07a530
  1. 165
      muk_utils/LICENSE
  2. 112
      muk_utils/README.rst
  3. 22
      muk_utils/__init__.py
  4. 42
      muk_utils/__manifest__.py
  5. 34
      muk_utils/actions/ir_attachment.xml
  6. 34
      muk_utils/doc/changelog.rst
  7. 112
      muk_utils/doc/index.rst
  8. 210
      muk_utils/i18n/ar.po
  9. 210
      muk_utils/i18n/de.po
  10. 210
      muk_utils/i18n/es.po
  11. 210
      muk_utils/i18n/fr.po
  12. 210
      muk_utils/i18n/hi.po
  13. 210
      muk_utils/i18n/muk_utils.pot
  14. 210
      muk_utils/i18n/nl.po
  15. 210
      muk_utils/i18n/pt.po
  16. 210
      muk_utils/i18n/ru.po
  17. 29
      muk_utils/models/__init__.py
  18. 210
      muk_utils/models/base.py
  19. 101
      muk_utils/models/ir_attachment.py
  20. 32
      muk_utils/models/ir_config_parameter.py
  21. 142
      muk_utils/models/mixins_groups.py
  22. 183
      muk_utils/models/mixins_hierarchy.py
  23. 55
      muk_utils/models/res_config_settings.py
  24. BIN
      muk_utils/static/description/banner.png
  25. BIN
      muk_utils/static/description/icon.png
  26. 1
      muk_utils/static/description/icon.svg
  27. 168
      muk_utils/static/description/index.html
  28. BIN
      muk_utils/static/description/logo.png
  29. BIN
      muk_utils/static/description/preview.png
  30. BIN
      muk_utils/static/description/service_customization.png
  31. BIN
      muk_utils/static/description/service_development.png
  32. BIN
      muk_utils/static/description/service_implementation.png
  33. BIN
      muk_utils/static/description/service_integration.png
  34. BIN
      muk_utils/static/description/service_support.png
  35. 30
      muk_utils/tests/__init__.py
  36. 69
      muk_utils/tests/test_attachment_migration.py
  37. 80
      muk_utils/tests/test_file_tools.py
  38. 35
      muk_utils/tests/test_http_tools.py
  39. 34
      muk_utils/tests/test_json_tools.py
  40. 60
      muk_utils/tests/test_search_childs.py
  41. 112
      muk_utils/tests/test_search_parents.py
  42. 50
      muk_utils/tests/test_security_helper.py
  43. 22
      muk_utils/tools/__init__.py
  44. 97
      muk_utils/tools/file.py
  45. 46
      muk_utils/tools/http.py
  46. 44
      muk_utils/tools/json.py
  47. 30
      muk_utils/tools/patch.py
  48. 30
      muk_utils/tools/security.py
  49. 25
      muk_utils/tools/utils.py
  50. 70
      muk_utils/views/ir_attachment.xml
  51. 110
      muk_utils/views/mixins_groups.xml
  52. 56
      muk_utils/views/res_config_settings.xml

165
muk_utils/LICENSE

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

112
muk_utils/README.rst

@ -0,0 +1,112 @@
=========
MuK Utils
=========
Technical module to provide some utility features and libraries that can be used
in other applications. 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 mode and update the
list by clicking on the "Update Apps List" link. Now install the module by
clicking on the install button.
Another way to install this module is via the package management for Python
(`PyPI <https://pypi.org/project/pip/>`_).
To install our modules using the package manager make sure
`odoo-autodiscover <https://pypi.org/project/odoo-autodiscover/>`_ is installed
correctly. Then open a console and install the module by entering the following
command:
``pip install --extra-index-url https://nexus.mukit.at/repository/odoo/simple <module>``
The module name consists of the Odoo version and the module name, where
underscores are replaced by a dash.
**Module:**
``odoo<version>-addon-<module_name>``
**Example:**
``sudo -H pip3 install --extra-index-url https://nexus.mukit.at/repository/odoo/simple odoo13-addon-muk-utils``
Once the installation has been successfully completed, the app is already in the
correct folder. Log on to your Odoo server and go to the Apps menu. Trigger the
debug mode and update the list by clicking on the "Update Apps List" link. Now
install the module by clicking on the install button.
The biggest advantage of this variant is that you can now also update the app
using the "pip" command. To do this, enter the following command in your console:
``pip install --upgrade --extra-index-url https://nexus.mukit.at/repository/odoo/simple <module>``
When the process is finished, restart your server and update the application in
Odoo. The steps are the same as for the installation only the button has changed
from "Install" to "Upgrade".
You can also view available Apps directly in our `repository <https://nexus.mukit.at/#browse/browse:odoo>`_
and find a more detailed installation guide on our `website <https://mukit.at/page/open-source>`_.
For modules licensed under a proprietary license, you will receive the access data after you purchased
the module. If the purchase were made at the Odoo store please contact our `support <support@mukit.at>`_
with a confirmation of the purchase to receive the corresponding access data.
Upgrade
============
To upgrade this module, you need to:
Download the module and add it to your Odoo addons folder. Restart the server
and log on to your Odoo server. Select the Apps menu and upgrade the module by
clicking on the upgrade button.
If you installed the module using the "pip" command, you can also update the
module in the same way. Just type the following command into the console:
``pip install --upgrade --extra-index-url https://nexus.mukit.at/repository/odoo/simple <module>``
When the process is finished, restart your server and update the application in
Odoo, just like you would normally.
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.
Credit
======
Contributors
------------
* Mathias Markl <mathias.markl@mukit.at>
Images
------
Some pictures are based on or inspired by the icon set of Font Awesome:
* `Font Awesome <https://fontawesome.com>`_
Author & Maintainer
-------------------
This module is maintained by the `MuK IT GmbH <https://www.mukit.at/>`_.
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>`_.

22
muk_utils/__init__.py

@ -0,0 +1,22 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
from . import models, tools

42
muk_utils/__manifest__.py

@ -0,0 +1,42 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
{
"name": "MuK Utils",
"summary": """Utility Features""",
"version": "13.0.1.0.0",
"category": "Extra Tools",
"license": "LGPL-3",
"author": "MuK IT",
"website": "https://www.mukit.at",
"contributors": ["Mathias Markl <mathias.markl@mukit.at>"],
"depends": ["base_setup"],
"data": [
"actions/ir_attachment.xml",
"views/ir_attachment.xml",
"views/mixins_groups.xml",
"views/res_config_settings.xml",
],
"images": ["static/description/banner.png"],
"application": False,
"installable": True,
"auto_install": False,
}

34
muk_utils/actions/ir_attachment.xml

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017-2019 MuK IT GmbH.
This file is part of MuK Utils
(see https://mukit.at).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<odoo>
<record id="action_attachment_migrate" model="ir.actions.server">
<field name="name">Migrate</field>
<field name="model_id" ref="base.model_ir_attachment" />
<field name="binding_model_id" ref="base.model_ir_attachment" />
<field name="state">code</field>
<field name="code">records.action_migrate()</field>
</record>
</odoo>

34
muk_utils/doc/changelog.rst

@ -0,0 +1,34 @@
`1.6.0`
-------
- Override Attachment to make it more extendable
`1.5.0`
-------
- Storage Migration Action
`1.4.0`
-------
- Added Hierarchy Mixin
`1.3.0`
-------
- Added SCSS Editor
`1.2.0`
-------
- Added Group Mixin
`1.1.0`
-------
- Added Storage Settings
`1.0.0`
-------
- Init Version

112
muk_utils/doc/index.rst

@ -0,0 +1,112 @@
=========
MuK Utils
=========
Technical module to provide some utility features and libraries that can be used
in other applications. 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 mode and update the
list by clicking on the "Update Apps List" link. Now install the module by
clicking on the install button.
Another way to install this module is via the package management for Python
(`PyPI <https://pypi.org/project/pip/>`_).
To install our modules using the package manager make sure
`odoo-autodiscover <https://pypi.org/project/odoo-autodiscover/>`_ is installed
correctly. Then open a console and install the module by entering the following
command:
``pip install --extra-index-url https://nexus.mukit.at/repository/odoo/simple <module>``
The module name consists of the Odoo version and the module name, where
underscores are replaced by a dash.
**Module:**
``odoo<version>-addon-<module_name>``
**Example:**
``sudo -H pip3 install --extra-index-url https://nexus.mukit.at/repository/odoo/simple odoo13-addon-muk-utils``
Once the installation has been successfully completed, the app is already in the
correct folder. Log on to your Odoo server and go to the Apps menu. Trigger the
debug mode and update the list by clicking on the "Update Apps List" link. Now
install the module by clicking on the install button.
The biggest advantage of this variant is that you can now also update the app
using the "pip" command. To do this, enter the following command in your console:
``pip install --upgrade --extra-index-url https://nexus.mukit.at/repository/odoo/simple <module>``
When the process is finished, restart your server and update the application in
Odoo. The steps are the same as for the installation only the button has changed
from "Install" to "Upgrade".
You can also view available Apps directly in our `repository <https://nexus.mukit.at/#browse/browse:odoo>`_
and find a more detailed installation guide on our `website <https://mukit.at/page/open-source>`_.
For modules licensed under a proprietary license, you will receive the access data after you purchased
the module. If the purchase were made at the Odoo store please contact our `support <support@mukit.at>`_
with a confirmation of the purchase to receive the corresponding access data.
Upgrade
============
To upgrade this module, you need to:
Download the module and add it to your Odoo addons folder. Restart the server
and log on to your Odoo server. Select the Apps menu and upgrade the module by
clicking on the upgrade button.
If you installed the module using the "pip" command, you can also update the
module in the same way. Just type the following command into the console:
``pip install --upgrade --extra-index-url https://nexus.mukit.at/repository/odoo/simple <module>``
When the process is finished, restart your server and update the application in
Odoo, just like you would normally.
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.
Credit
======
Contributors
------------
* Mathias Markl <mathias.markl@mukit.at>
Images
------
Some pictures are based on or inspired by the icon set of Font Awesome:
* `Font Awesome <https://fontawesome.com>`_
Author & Maintainer
-------------------
This module is maintained by the `MuK IT GmbH <https://www.mukit.at/>`_.
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>`_.

210
muk_utils/i18n/ar.po

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * muk_utils
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0-20190522\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-13 09:39+0000\n"
"PO-Revision-Date: 2019-07-13 09:39+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "<strong>Save</strong> this page before triggering the migration."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "All Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Field"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Model"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_attachment
msgid "Attachment"
msgstr "مرفق"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Attachment storage location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,help:muk_utils.field_res_config_settings__attachment_location
msgid "Attachment storage location."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attachments"
msgstr "المُرفقات"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_base
msgid "Base"
msgstr "الأساس"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__child_groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Child Groups"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_res_config_settings
msgid "Config Settings"
msgstr "ضبط الإعدادات"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__display_name
msgid "Display Name"
msgstr "اسم العرض"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__explicit_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Explicit Users"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Field Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Force Storage Migration"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Group"
msgstr "المجموعة"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_groups
msgid "Group Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__name
msgid "Group Name"
msgstr "اسم المجموعة"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__users
msgid "Group Users"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_tree
msgid "Groups"
msgstr "المجموعات"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_hierarchy
msgid "Hierarchy Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__id
msgid "ID"
msgstr "المعرف"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor____last_update
msgid "Last Modified on"
msgstr "آخر تعديل في"
#. module: muk_utils
#: model:ir.actions.server,name:muk_utils.action_attachment_migrate
msgid "Migrate"
msgstr ""
#. module: muk_utils
#: code:addons/muk_utils/models/ir_attachment.py:87
#, python-format
msgid "Only administrators can execute this action."
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_group
msgid "Parent Group"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_path
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path
msgid "Parent Path"
msgstr "المسار الأصلي"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_json
msgid "Path Json"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_names
msgid "Path Names"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_scss_editor
msgid "Scss Editor"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_form
msgid "Storage"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location
msgid "Storage Location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location_changed
msgid "Storage Location Changed"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_config_parameter
msgid "System Parameter"
msgstr "باراميتر النظام"
#. module: muk_utils
#: sql_constraint:muk_utils.mixins.groups:0
msgid "The name of the group must be unique!"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__count_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Users"
msgstr "المستخدمون"

210
muk_utils/i18n/de.po

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * muk_utils
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0-20190522\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-13 09:39+0000\n"
"PO-Revision-Date: 2019-07-13 09:39+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "<strong>Save</strong> this page before triggering the migration."
msgstr "<strong>Speichern</strong>Sie diese Seite, bevor Sie die Migration auslösen."
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "All Data"
msgstr "Alle Daten"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Field"
msgstr "Dokumenten Feld"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Model"
msgstr "Dokumenten Model"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_attachment
msgid "Attachment"
msgstr "Dateianhang"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Attachment storage location"
msgstr "Speicherort des Attachments"
#. module: muk_utils
#: model:ir.model.fields,help:muk_utils.field_res_config_settings__attachment_location
msgid "Attachment storage location."
msgstr "Speicherort des Attachments."
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attachments"
msgstr "Dateianhänge"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_base
msgid "Base"
msgstr "Basis"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__child_groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Child Groups"
msgstr "Untergruppen"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_res_config_settings
msgid "Config Settings"
msgstr "Konfiguration "
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__display_name
msgid "Display Name"
msgstr "Anzeigename"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__explicit_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Explicit Users"
msgstr "Explizite Benutzer"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Field Data"
msgstr "Felddaten"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Force Storage Migration"
msgstr "Speichermigration erzwingen"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Group"
msgstr "Gruppe"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_groups
msgid "Group Mixin"
msgstr "Gruppen Mixin"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__name
msgid "Group Name"
msgstr "Gruppenname"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__users
msgid "Group Users"
msgstr "Gruppenbenutzer"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_tree
msgid "Groups"
msgstr "Gruppen"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_hierarchy
msgid "Hierarchy Mixin"
msgstr "Hierarchie Mixin"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__id
msgid "ID"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor____last_update
msgid "Last Modified on"
msgstr "Zuletzt geändert am"
#. module: muk_utils
#: model:ir.actions.server,name:muk_utils.action_attachment_migrate
msgid "Migrate"
msgstr "Migrieren"
#. module: muk_utils
#: code:addons/muk_utils/models/ir_attachment.py:87
#, python-format
msgid "Only administrators can execute this action."
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_group
msgid "Parent Group"
msgstr "Übergeordnete Gruppe"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_path
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path
msgid "Parent Path"
msgstr "Übergeordneter Pfad"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_json
msgid "Path Json"
msgstr "Json Pfad"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_names
msgid "Path Names"
msgstr "Pfadnamen"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_scss_editor
msgid "Scss Editor"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_form
msgid "Storage"
msgstr "Speicher"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location
msgid "Storage Location"
msgstr "Speicherort"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location_changed
msgid "Storage Location Changed"
msgstr "Speicherort geändert"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_config_parameter
msgid "System Parameter"
msgstr "Systemparameter"
#. module: muk_utils
#: sql_constraint:muk_utils.mixins.groups:0
msgid "The name of the group must be unique!"
msgstr "Der Name der Gruppe muss einzigartig sein!"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__count_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Users"
msgstr "Benutzer"

210
muk_utils/i18n/es.po

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * muk_utils
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0-20190522\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-13 09:39+0000\n"
"PO-Revision-Date: 2019-07-13 09:39+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "<strong>Save</strong> this page before triggering the migration."
msgstr "<strong>Save</strong> esta página antes de iniciar la migración."
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "All Data"
msgstr "Todos los datos"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Field"
msgstr "Campo de documento adjunto"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Model"
msgstr "Modelo de documento adjunto"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_attachment
msgid "Attachment"
msgstr "Adjunto"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Attachment storage location"
msgstr "Almacén de anexos"
#. module: muk_utils
#: model:ir.model.fields,help:muk_utils.field_res_config_settings__attachment_location
msgid "Attachment storage location."
msgstr "Almacén de archivos adjuntos."
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attachments"
msgstr "Adjuntos"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_base
msgid "Base"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__child_groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Child Groups"
msgstr "Grupos de niños"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_res_config_settings
msgid "Config Settings"
msgstr "Opciones de Configuración"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__display_name
msgid "Display Name"
msgstr "Nombre mostrado"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__explicit_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Explicit Users"
msgstr "Usuarios Explícitos"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Field Data"
msgstr "Datos de campo"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Force Storage Migration"
msgstr "Migración de almacenamiento forzado"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Group"
msgstr "Grupo"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_groups
msgid "Group Mixin"
msgstr "Mezcla de Grupo"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__name
msgid "Group Name"
msgstr "Nombre del grupo"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__users
msgid "Group Users"
msgstr "Usuarios del grupo"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_tree
msgid "Groups"
msgstr "Grupos"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_hierarchy
msgid "Hierarchy Mixin"
msgstr "Mezcla de jerarquías"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__id
msgid "ID"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor____last_update
msgid "Last Modified on"
msgstr "Última modificación en"
#. module: muk_utils
#: model:ir.actions.server,name:muk_utils.action_attachment_migrate
msgid "Migrate"
msgstr "Migrar"
#. module: muk_utils
#: code:addons/muk_utils/models/ir_attachment.py:87
#, python-format
msgid "Only administrators can execute this action."
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_group
msgid "Parent Group"
msgstr "Grupo de padres"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_path
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path
msgid "Parent Path"
msgstr "Trayectoria de los padres"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_json
msgid "Path Json"
msgstr "Camino Json"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_names
msgid "Path Names"
msgstr "Nombres de senderos"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_scss_editor
msgid "Scss Editor"
msgstr "Editor de Scss"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_form
msgid "Storage"
msgstr "Almacenamiento"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location
msgid "Storage Location"
msgstr "Almacén"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location_changed
msgid "Storage Location Changed"
msgstr "Almacén modificado"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_config_parameter
msgid "System Parameter"
msgstr "Parámetros del sistema"
#. module: muk_utils
#: sql_constraint:muk_utils.mixins.groups:0
msgid "The name of the group must be unique!"
msgstr "El nombre del grupo debe ser único!"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__count_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Users"
msgstr "Usuarios"

210
muk_utils/i18n/fr.po

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * muk_utils
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0-20190522\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-13 09:40+0000\n"
"PO-Revision-Date: 2019-07-13 09:40+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "<strong>Save</strong> this page before triggering the migration."
msgstr "<strong>Save</strong> cette page avant de déclencher la migration."
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "All Data"
msgstr "Toutes les données"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Field"
msgstr "Champ du document joint"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Model"
msgstr "Modèle de document joint"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_attachment
msgid "Attachment"
msgstr "Pièce jointe"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Attachment storage location"
msgstr "Pièce jointe"
#. module: muk_utils
#: model:ir.model.fields,help:muk_utils.field_res_config_settings__attachment_location
msgid "Attachment storage location."
msgstr "Emplacement de stockage des pièces jointes"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attachments"
msgstr "Pièces jointes"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_base
msgid "Base"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__child_groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Child Groups"
msgstr "Base"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_res_config_settings
msgid "Config Settings"
msgstr "Paramètres de config"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__explicit_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Explicit Users"
msgstr "Nom d'affichage"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Field Data"
msgstr "Utilisateurs explicites"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Force Storage Migration"
msgstr "Données de terrain"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Group"
msgstr "Groupe"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_groups
msgid "Group Mixin"
msgstr "Groupe"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__name
msgid "Group Name"
msgstr "Nom du groupe"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__users
msgid "Group Users"
msgstr "Nom du groupe"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_tree
msgid "Groups"
msgstr "Groupes"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_hierarchy
msgid "Hierarchy Mixin"
msgstr "Groupes"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__id
msgid "ID"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: muk_utils
#: model:ir.actions.server,name:muk_utils.action_attachment_migrate
msgid "Migrate"
msgstr "Dernière modification le"
#. module: muk_utils
#: code:addons/muk_utils/models/ir_attachment.py:87
#, python-format
msgid "Only administrators can execute this action."
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_group
msgid "Parent Group"
msgstr "Seuls les administrateurs peuvent exécuter cette action."
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_path
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path
msgid "Parent Path"
msgstr "Chemin parent"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_json
msgid "Path Json"
msgstr "Cheminement des parents"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_names
msgid "Path Names"
msgstr "Sentier Json"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_scss_editor
msgid "Scss Editor"
msgstr "Noms des chemins"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_form
msgid "Storage"
msgstr "Editeur Scss"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location
msgid "Storage Location"
msgstr "Stockage"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location_changed
msgid "Storage Location Changed"
msgstr "Emplacement de stockage"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_config_parameter
msgid "System Parameter"
msgstr "Paramètres du système"
#. module: muk_utils
#: sql_constraint:muk_utils.mixins.groups:0
msgid "The name of the group must be unique!"
msgstr "Changement de magasin"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__count_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Users"
msgstr "Utilisateurs"

210
muk_utils/i18n/hi.po

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * muk_utils
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0-20190522\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-13 09:40+0000\n"
"PO-Revision-Date: 2019-07-13 09:40+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "<strong>Save</strong> this page before triggering the migration."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "All Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Field"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Model"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_attachment
msgid "Attachment"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Attachment storage location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,help:muk_utils.field_res_config_settings__attachment_location
msgid "Attachment storage location."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attachments"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_base
msgid "Base"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__child_groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Child Groups"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__display_name
msgid "Display Name"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__explicit_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Explicit Users"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Field Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Force Storage Migration"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Group"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_groups
msgid "Group Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__name
msgid "Group Name"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__users
msgid "Group Users"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_tree
msgid "Groups"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_hierarchy
msgid "Hierarchy Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__id
msgid "ID"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor____last_update
msgid "Last Modified on"
msgstr ""
#. module: muk_utils
#: model:ir.actions.server,name:muk_utils.action_attachment_migrate
msgid "Migrate"
msgstr ""
#. module: muk_utils
#: code:addons/muk_utils/models/ir_attachment.py:87
#, python-format
msgid "Only administrators can execute this action."
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_group
msgid "Parent Group"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_path
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path
msgid "Parent Path"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_json
msgid "Path Json"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_names
msgid "Path Names"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_scss_editor
msgid "Scss Editor"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_form
msgid "Storage"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location
msgid "Storage Location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location_changed
msgid "Storage Location Changed"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_config_parameter
msgid "System Parameter"
msgstr ""
#. module: muk_utils
#: sql_constraint:muk_utils.mixins.groups:0
msgid "The name of the group must be unique!"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__count_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Users"
msgstr ""

210
muk_utils/i18n/muk_utils.pot

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * muk_utils
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0-20190522\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-13 09:39+0000\n"
"PO-Revision-Date: 2019-07-13 09:39+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "<strong>Save</strong> this page before triggering the migration."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "All Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Field"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Model"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_attachment
msgid "Attachment"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Attachment storage location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,help:muk_utils.field_res_config_settings__attachment_location
msgid "Attachment storage location."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attachments"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_base
msgid "Base"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__child_groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Child Groups"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__display_name
msgid "Display Name"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__explicit_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Explicit Users"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Field Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Force Storage Migration"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Group"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_groups
msgid "Group Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__name
msgid "Group Name"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__users
msgid "Group Users"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_tree
msgid "Groups"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_hierarchy
msgid "Hierarchy Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__id
msgid "ID"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor____last_update
msgid "Last Modified on"
msgstr ""
#. module: muk_utils
#: model:ir.actions.server,name:muk_utils.action_attachment_migrate
msgid "Migrate"
msgstr ""
#. module: muk_utils
#: code:addons/muk_utils/models/ir_attachment.py:87
#, python-format
msgid "Only administrators can execute this action."
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_group
msgid "Parent Group"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_path
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path
msgid "Parent Path"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_json
msgid "Path Json"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_names
msgid "Path Names"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_scss_editor
msgid "Scss Editor"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_form
msgid "Storage"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location
msgid "Storage Location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location_changed
msgid "Storage Location Changed"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_config_parameter
msgid "System Parameter"
msgstr ""
#. module: muk_utils
#: sql_constraint:muk_utils.mixins.groups:0
msgid "The name of the group must be unique!"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__count_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Users"
msgstr ""

210
muk_utils/i18n/nl.po

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * muk_utils
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0-20190522\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-13 09:40+0000\n"
"PO-Revision-Date: 2019-07-13 09:40+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "<strong>Save</strong> this page before triggering the migration."
msgstr "<strong>Save</strong> deze pagina vooraleer de migratie te starten."
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "All Data"
msgstr "Alle gegevens"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Field"
msgstr "Bijgevoegd documentveld"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Model"
msgstr "Bijgevoegd documentmodel"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_attachment
msgid "Attachment"
msgstr "Bijlage"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Attachment storage location"
msgstr "Opslaglocatie voor hulpstukken"
#. module: muk_utils
#: model:ir.model.fields,help:muk_utils.field_res_config_settings__attachment_location
msgid "Attachment storage location."
msgstr "Opslagplaats voor bevestigingsmateriaal."
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attachments"
msgstr "Bijlagen"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_base
msgid "Base"
msgstr "Basis"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__child_groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Child Groups"
msgstr "Kind groepen"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_res_config_settings
msgid "Config Settings"
msgstr "Configuratie instellingen"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__display_name
msgid "Display Name"
msgstr "Weergavenaam"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__explicit_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Explicit Users"
msgstr "Expliciete gebruikers"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Field Data"
msgstr "Veldgegevens"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Force Storage Migration"
msgstr "Krachtenopslag migratie"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Group"
msgstr "Groep"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_groups
msgid "Group Mixin"
msgstr "Groepsmixer"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__name
msgid "Group Name"
msgstr "Groepsnaam"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__users
msgid "Group Users"
msgstr "Groep gebruikers"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_tree
msgid "Groups"
msgstr "Groepen"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_hierarchy
msgid "Hierarchy Mixin"
msgstr "Hiërarchie Mixin"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__id
msgid "ID"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor____last_update
msgid "Last Modified on"
msgstr "Laatst gewijzigd op"
#. module: muk_utils
#: model:ir.actions.server,name:muk_utils.action_attachment_migrate
msgid "Migrate"
msgstr "Migreren"
#. module: muk_utils
#: code:addons/muk_utils/models/ir_attachment.py:87
#, python-format
msgid "Only administrators can execute this action."
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_group
msgid "Parent Group"
msgstr "Moedergroep"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_path
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path
msgid "Parent Path"
msgstr "Bovenliggend pad"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_json
msgid "Path Json"
msgstr "Pad Json"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_names
msgid "Path Names"
msgstr "Padnamen"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_scss_editor
msgid "Scss Editor"
msgstr "Scss-editor"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_form
msgid "Storage"
msgstr "Opslag"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location
msgid "Storage Location"
msgstr "Opslaglocatie"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location_changed
msgid "Storage Location Changed"
msgstr "Opslaglocatie veranderd"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_config_parameter
msgid "System Parameter"
msgstr "Systeem parameter"
#. module: muk_utils
#: sql_constraint:muk_utils.mixins.groups:0
msgid "The name of the group must be unique!"
msgstr "De naam van de groep moet uniek zijn!"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__count_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Users"
msgstr "Gebruikers"

210
muk_utils/i18n/pt.po

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * muk_utils
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0-20190522\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-13 09:40+0000\n"
"PO-Revision-Date: 2019-07-13 09:40+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "<strong>Save</strong> this page before triggering the migration."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "All Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Field"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Model"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_attachment
msgid "Attachment"
msgstr "Anexo"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Attachment storage location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,help:muk_utils.field_res_config_settings__attachment_location
msgid "Attachment storage location."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attachments"
msgstr "Anexos"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_base
msgid "Base"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__child_groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Child Groups"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_res_config_settings
msgid "Config Settings"
msgstr "config configurações"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__display_name
msgid "Display Name"
msgstr "Nome a Exibir"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__explicit_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Explicit Users"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Field Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Force Storage Migration"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Group"
msgstr "Grupo"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_groups
msgid "Group Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__name
msgid "Group Name"
msgstr "Nome do Grupo"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__users
msgid "Group Users"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_tree
msgid "Groups"
msgstr "Grupos"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_hierarchy
msgid "Hierarchy Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__id
msgid "ID"
msgstr "Id."
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor____last_update
msgid "Last Modified on"
msgstr "Última Modificação em"
#. module: muk_utils
#: model:ir.actions.server,name:muk_utils.action_attachment_migrate
msgid "Migrate"
msgstr ""
#. module: muk_utils
#: code:addons/muk_utils/models/ir_attachment.py:87
#, python-format
msgid "Only administrators can execute this action."
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_group
msgid "Parent Group"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_path
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path
msgid "Parent Path"
msgstr "Caminho ascendente "
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_json
msgid "Path Json"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_names
msgid "Path Names"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_scss_editor
msgid "Scss Editor"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_form
msgid "Storage"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location
msgid "Storage Location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location_changed
msgid "Storage Location Changed"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_config_parameter
msgid "System Parameter"
msgstr ""
#. module: muk_utils
#: sql_constraint:muk_utils.mixins.groups:0
msgid "The name of the group must be unique!"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__count_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Users"
msgstr "Utilizadores"

210
muk_utils/i18n/ru.po

@ -0,0 +1,210 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * muk_utils
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0-20190522\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-13 09:40+0000\n"
"PO-Revision-Date: 2019-07-13 09:40+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "<strong>Save</strong> this page before triggering the migration."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "All Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Field"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attached Document Model"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_attachment
msgid "Attachment"
msgstr "Приложение"
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Attachment storage location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,help:muk_utils.field_res_config_settings__attachment_location
msgid "Attachment storage location."
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Attachments"
msgstr "Вложения"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_base
msgid "Base"
msgstr "Базовый"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__child_groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Child Groups"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_res_config_settings
msgid "Config Settings"
msgstr "Настройки конфигурации"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__display_name
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__display_name
msgid "Display Name"
msgstr "Отображаемое Имя"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__explicit_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Explicit Users"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_search
msgid "Field Data"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
msgid "Force Storage Migration"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Group"
msgstr "Группа"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_groups
msgid "Group Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__name
msgid "Group Name"
msgstr "Наименование Группы"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__users
msgid "Group Users"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__groups
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_tree
msgid "Groups"
msgstr "Группы"
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_mixins_hierarchy
msgid "Hierarchy Mixin"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__id
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor__id
msgid "ID"
msgstr "Номер"
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy____last_update
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_scss_editor____last_update
msgid "Last Modified on"
msgstr "Последнее изменение"
#. module: muk_utils
#: model:ir.actions.server,name:muk_utils.action_attachment_migrate
msgid "Migrate"
msgstr ""
#. module: muk_utils
#: code:addons/muk_utils/models/ir_attachment.py:87
#, python-format
msgid "Only administrators can execute this action."
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_group
msgid "Parent Group"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__parent_path
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path
msgid "Parent Path"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_json
msgid "Path Json"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_hierarchy__parent_path_names
msgid "Path Names"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_muk_utils_scss_editor
msgid "Scss Editor"
msgstr ""
#. module: muk_utils
#: model_terms:ir.ui.view,arch_db:muk_utils.res_config_settings_view_form
#: model_terms:ir.ui.view,arch_db:muk_utils.view_attachment_form
msgid "Storage"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location
msgid "Storage Location"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_res_config_settings__attachment_location_changed
msgid "Storage Location Changed"
msgstr ""
#. module: muk_utils
#: model:ir.model,name:muk_utils.model_ir_config_parameter
msgid "System Parameter"
msgstr ""
#. module: muk_utils
#: sql_constraint:muk_utils.mixins.groups:0
msgid "The name of the group must be unique!"
msgstr ""
#. module: muk_utils
#: model:ir.model.fields,field_description:muk_utils.field_muk_utils_mixins_groups__count_users
#: model_terms:ir.ui.view,arch_db:muk_utils.view_mixins_groups_form
msgid "Users"
msgstr "Пользователи"

29
muk_utils/models/__init__.py

@ -0,0 +1,29 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
from . import (
base,
ir_attachment,
ir_config_parameter,
mixins_groups,
mixins_hierarchy,
res_config_settings,
)

210
muk_utils/models/base.py

@ -0,0 +1,210 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import logging
from odoo import api, models
from odoo.addons.muk_utils.tools import utils
from odoo.osv import expression
_logger = logging.getLogger(__name__)
class Base(models.AbstractModel):
_inherit = "base"
# ----------------------------------------------------------
# Helper Methods
# ----------------------------------------------------------
@api.model
def _check_parent_field(self):
if self._parent_name not in self._fields:
raise TypeError(
"The parent ({}) field does not exist.".format(self._parent_name)
)
@api.model
def _build_search_childs_domain(self, parent_id, domain=[]):
self._check_parent_field()
parent_domain = [[self._parent_name, "=", parent_id]]
return expression.AND([parent_domain, domain]) if domain else parent_domain
@api.model
def _check_context_bin_size(self, field):
return any(
key in self.env.context for key in ["bin_size", "bin_size_{}".format(field)]
)
# ----------------------------------------------------------
# Security
# ----------------------------------------------------------
def _filter_access(self, operation, in_memory=True):
if self.check_access_rights(operation, False):
if in_memory:
return self._filter_access_rules_python(operation)
else:
return self._filter_access_rules(operation)
return self.env[self._name]
def _filter_access_ids(self, operation, in_memory=True):
return self._filter_access(operation, in_memory=in_memory).ids
def check_access(self, operation, raise_exception=False):
""" Verifies that the operation given by ``operation`` is allowed for
the current user according to the access level.
:param operation: one of ``read``, ``create``, ``write``, ``unlink``
:raise AccessError: * if current level of access do not permit this operation.
:return: True if the operation is allowed
"""
try:
access_right = self.check_access_rights(operation, raise_exception)
access_rule = self.check_access_rule(operation) is None
return access_right and access_rule
except AccessError:
if raise_exception:
raise
return False
# ----------------------------------------------------------
# Hierarchy Methods
# ----------------------------------------------------------
@api.model
def search_parents(self, domain=[], offset=0, limit=None, order=None, count=False):
""" This method finds the top level elements of the hierarchy for a given search query.
:param domain: a search domain <reference/orm/domains> (default: empty list)
:param order: a string to define the sort order of the query (default: none)
:returns: the top level elements for the given search query
"""
res = self._search_parents(
domain=domain, offset=offset, limit=limit, order=order, count=count
)
return res if count else self.browse(res)
@api.model
def search_read_parents(
self, domain=[], fields=None, offset=0, limit=None, order=None
):
""" This method finds the top level elements of the hierarchy for a given search query.
:param domain: a search domain <reference/orm/domains> (default: empty list)
:param fields: a list of fields to read (default: all fields of the model)
:param order: a string to define the sort order of the query (default: none)
:returns: the top level elements for the given search query
"""
records = self.search_parents(
domain=domain, offset=offset, limit=limit, order=order
)
if not records:
return []
if fields and fields == ["id"]:
return [{"id": record.id} for record in records]
result = records.read(fields)
if len(result) <= 1:
return result
index = {vals["id"]: vals for vals in result}
return [index[record.id] for record in records if record.id in index]
@api.model
def _search_parents(self, domain=[], offset=0, limit=None, order=None, count=False):
self._check_parent_field()
self.check_access_rights("read")
if expression.is_false(self, domain):
return 0 if count else []
self._flush_search(domain, fields=[self._parent_name], order=order)
query = self._where_calc(domain)
self._apply_ir_rules(query, "read")
from_clause, where_clause, where_clause_arguments = query.get_sql()
parent_where = where_clause and (" WHERE {}".format(where_clause)) or ""
parent_query = (
'SELECT "{}".id FROM '.format(self._table) + from_clause + parent_where
)
no_parent_clause = '"{table}"."{field}" IS NULL'.format(
table=self._table, field=self._parent_name
)
no_access_clause = '"{table}"."{field}" NOT IN ({query})'.format(
table=self._table, field=self._parent_name, query=parent_query
)
parent_clause = "({} OR {})".format(no_parent_clause, no_access_clause)
order_by = self._generate_order_by(order, query)
from_clause, where_clause, where_clause_params = query.get_sql()
where_str = (
where_clause
and (" WHERE {} AND {}".format(where_clause, parent_clause))
or (" WHERE {}".format(parent_clause))
)
if count:
query_str = "SELECT count(1) FROM " + from_clause + where_str
self.env.cr.execute(query_str, where_clause_params + where_clause_arguments)
return self.env.cr.fetchone()[0]
limit_str = limit and " limit %d" % limit or ""
offset_str = offset and " offset %d" % offset or ""
query_str = (
'SELECT "{}".id FROM '.format(self._table)
+ from_clause
+ where_str
+ order_by
+ limit_str
+ offset_str
)
self.env.cr.execute(query_str, where_clause_params + where_clause_arguments)
return utils.uniquify_list([x[0] for x in self.env.cr.fetchall()])
@api.model
def search_childs(
self, parent_id, domain=[], offset=0, limit=None, order=None, count=False
):
""" This method finds the direct child elements of the parent record for a given search query.
:param parent_id: the integer representing the ID of the parent record
:param domain: a search domain <reference/orm/domains> (default: empty list)
:param offset: the number of results to ignore (default: none)
:param limit: maximum number of records to return (default: all)
:param order: a string to define the sort order of the query (default: none)
:param count: counts and returns the number of matching records (default: False)
:returns: the top level elements for the given search query
"""
domain = self._build_search_childs_domain(parent_id, domain=domain)
return self.search(domain, offset=offset, limit=limit, order=order, count=count)
@api.model
def search_read_childs(
self, parent_id, domain=[], fields=None, offset=0, limit=None, order=None
):
""" This method finds the direct child elements of the parent record for a given search query.
:param parent_id: the integer representing the ID of the parent record
:param domain: a search domain <reference/orm/domains> (default: empty list)
:param fields: a list of fields to read (default: all fields of the model)
:param offset: the number of results to ignore (default: none)
:param limit: maximum number of records to return (default: all)
:param order: a string to define the sort order of the query (default: none)
:returns: the top level elements for the given search query
"""
domain = self._build_search_childs_domain(parent_id, domain=domain)
return self.search_read(
domain=domain, fields=fields, offset=offset, limit=limit, order=order
)

101
muk_utils/models/ir_attachment.py

@ -0,0 +1,101 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import logging
from odoo import _, api, models
from odoo.exceptions import AccessError
from odoo.osv import expression
_logger = logging.getLogger(__name__)
class IrAttachment(models.Model):
_inherit = "ir.attachment"
# ----------------------------------------------------------
# Helper
# ----------------------------------------------------------
@api.model
def _get_storage_domain(self, storage):
return {
"db": [("db_datas", "=", False)],
"file": [("store_fname", "=", False)],
}[storage]
# ----------------------------------------------------------
# Actions
# ----------------------------------------------------------
def action_migrate(self):
self.migrate()
# ----------------------------------------------------------
# Functions
# ----------------------------------------------------------
@api.model
def storage_locations(self):
return ["db", "file"]
@api.model
def force_storage(self):
"""Force all attachments to be stored in the currently configured storage"""
if not self.env.user._is_admin():
raise AccessError(_("Only administrators can execute this action."))
self.search(
expression.AND(
[
self._get_storage_domain(self._storage()),
[
"&",
"|",
("res_field", "=", False),
("res_field", "!=", False),
("type", "=", "binary"),
],
]
)
).migrate(batch_size=100)
return True
def migrate(self, batch_size=None):
commit_on_batch = bool(batch_size)
attachments_to_migrate = len(self)
batch_size = batch_size or len(self) or 1
storage_location = self._storage().upper()
for index, attachment in enumerate(self, start=1):
_logger.info(
"Migrate Attachment {index} of {total} to {storage}".format(
**{
"index": index,
"total": attachments_to_migrate,
"storage": storage_location,
}
)
)
attachment.write(
{"datas": attachment.datas, "mimetype": attachment.mimetype}
)
if commit_on_batch and not index % batch_size:
self.env.cr.commit()

32
muk_utils/models/ir_config_parameter.py

@ -0,0 +1,32 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
from odoo import api, models
class IrConfigParameter(models.Model):
_inherit = "ir.config_parameter"
@api.model
def set_params(self, params):
for key, value in params.items():
self.set_param(key, value)

142
muk_utils/models/mixins_groups.py

@ -0,0 +1,142 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
from odoo import api, fields, models
class Groups(models.AbstractModel):
_name = "muk_utils.mixins.groups"
_description = "Group Mixin"
_parent_store = True
_parent_name = "parent_group"
# ----------------------------------------------------------
# Database
# ----------------------------------------------------------
name = fields.Char(string="Group Name", required=True, translate=True)
parent_path = fields.Char(string="Parent Path", index=True)
count_users = fields.Integer(compute="_compute_users", string="Users", store=True)
@api.model
def _add_magic_fields(self):
super(Groups, self)._add_magic_fields()
def add(name, field):
if name not in self._fields:
self._add_field(name, field)
add(
"parent_group",
fields.Many2one(
_module=self._module,
comodel_name=self._name,
string="Parent Group",
ondelete="cascade",
auto_join=True,
index=True,
automatic=True,
),
)
add(
"child_groups",
fields.One2many(
_module=self._module,
comodel_name=self._name,
inverse_name="parent_group",
string="Child Groups",
automatic=True,
),
)
add(
"groups",
fields.Many2many(
_module=self._module,
comodel_name="res.groups",
relation="{}_groups_rel".format(self._table),
column1="gid",
column2="rid",
string="Groups",
automatic=True,
),
)
add(
"explicit_users",
fields.Many2many(
_module=self._module,
comodel_name="res.users",
relation="{}_explicit_users_rel".format(self._table),
column1="gid",
column2="uid",
string="Explicit Users",
automatic=True,
),
)
add(
"users",
fields.Many2many(
_module=self._module,
comodel_name="res.users",
relation="{}_users_rel".format(self._table),
column1="gid",
column2="uid",
string="Group Users",
compute="_compute_users",
store=True,
automatic=True,
),
)
_sql_constraints = [
("name_uniq", "unique (name)", "The name of the group must be unique!")
]
# ----------------------------------------------------------
# Functions
# ----------------------------------------------------------
@api.model
def default_get(self, fields_list):
res = super(Groups, self).default_get(fields_list)
if not self.env.context.get("groups_no_autojoin"):
if "explicit_users" in res and res["explicit_users"]:
res["explicit_users"] = res["explicit_users"] + [self.env.uid]
else:
res["explicit_users"] = [self.env.uid]
return res
# ----------------------------------------------------------
# Read, View
# ----------------------------------------------------------
@api.depends(
"parent_group", "parent_group.users", "groups", "groups.users", "explicit_users"
)
def _compute_users(self):
for record in self:
users = record.mapped("groups.users")
users |= record.mapped("explicit_users")
users |= record.mapped("parent_group.users")
record.update({"users": users, "count_users": len(users)})

183
muk_utils/models/mixins_hierarchy.py

@ -0,0 +1,183 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import functools
import json
import operator
from odoo import api, fields, models
from odoo.osv import expression
class Hierarchy(models.AbstractModel):
_name = "muk_utils.mixins.hierarchy"
_description = "Hierarchy Mixin"
_parent_store = True
_parent_path_sudo = False
_parent_path_store = False
_name_path_context = "show_path"
# ----------------------------------------------------------
# Database
# ----------------------------------------------------------
parent_path = fields.Char(string="Parent Path", index=True)
@api.model
def _add_magic_fields(self):
super(Hierarchy, self)._add_magic_fields()
def add(name, field):
if name not in self._fields:
self._add_field(name, field)
path_names_search = None
if not self._parent_path_store:
path_names_search = "_search_parent_path_names"
add(
"parent_path_names",
fields.Char(
_module=self._module,
compute="_compute_parent_paths",
compute_sudo=self._parent_path_sudo,
store=self._parent_path_store,
search=path_names_search,
string="Path Names",
readonly=True,
automatic=True,
),
)
add(
"parent_path_json",
fields.Text(
_module=self._module,
compute="_compute_parent_paths",
compute_sudo=self._parent_path_sudo,
store=self._parent_path_store,
string="Path Json",
readonly=True,
automatic=True,
),
)
# ----------------------------------------------------------
# Helper
# ----------------------------------------------------------
@api.model
def _get_depends_parent_paths(self):
depends = ["parent_path"]
if self._rec_name:
depends += [self._rec_name]
elif "name" in self._fields:
depends += ["name"]
elif "x_name" in self._fields:
depends += ["x_name"]
return depends
# ----------------------------------------------------------
# Search
# ----------------------------------------------------------
@api.model
def _search_parent_path_names(self, operator, operand):
domain = []
for value in operand.split("/"):
args = [(self._rec_name_fallback(), operator, value)]
domain = expression.OR([args, domain]) if domain else args
return domain if domain else [(self._rec_name_fallback(), operator, "")]
# ----------------------------------------------------------
# Read, View
# ----------------------------------------------------------
@api.depends(lambda self: self._get_depends_parent_paths())
def _compute_parent_paths(self):
records = self.filtered("parent_path")
records_without_parent_path = self - records
paths = [list(map(int, rec.parent_path.split("/")[:-1])) for rec in records]
ids = paths and set(functools.reduce(operator.concat, paths)) or []
model_without_path = self.with_context(**{self._name_path_context: False})
filtered_records = model_without_path.browse(ids)._filter_access("read")
data = dict(filtered_records.name_get())
for record in records:
path_names = [""]
path_json = []
for id in reversed(list(map(int, record.parent_path.split("/")[:-1]))):
if id not in data:
break
path_names.append(data[id])
path_json.append({"model": record._name, "name": data[id], "id": id})
path_names.reverse()
path_json.reverse()
record.update(
{
"parent_path_names": "/".join(path_names),
"parent_path_json": json.dumps(path_json),
}
)
records_without_parent_path.update(
{"parent_path_names": False, "parent_path_json": False}
)
@api.model
def _name_search(
self, name="", args=None, operator="ilike", limit=100, name_get_uid=None
):
domain = list(args or [])
if not (name == "" and operator == "ilike"):
if "/" in name:
domain += [("parent_path_names", operator, name)]
else:
domain += [(self._rec_name, operator, name)]
records = self.browse(
self._search(domain, limit=limit, access_rights_uid=name_get_uid)
)
return models.lazy_name_get(records.with_user(name_get_uid or self.env.uid))
def name_get(self):
if self.env.context.get(self._name_path_context):
res = []
for record in self:
names = record.parent_path_names
if not names:
res.append(super(Hierarchy, record).name_get()[0])
elif not len(names) > 50:
res.append((record.id, names))
else:
res.append((record.id, ".." + names[-48:]))
return res
return super(Hierarchy, self).name_get()
# ----------------------------------------------------------
# Create, Update, Delete
# ----------------------------------------------------------
def write(self, vals):
res = super(Hierarchy, self).write(vals)
if self._parent_path_store and self._rec_name_fallback() in vals:
domain = [("id", "child_of", self.ids)]
records = self.sudo().search(domain)
records.modified(["parent_path"])
return res

55
muk_utils/models/res_config_settings.py

@ -0,0 +1,55 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
# ----------------------------------------------------------
# Selections
# ----------------------------------------------------------
def _attachment_location_selection(self):
locations = self.env["ir.attachment"].storage_locations()
return list(map(lambda location: (location, location.upper()), locations))
# ----------------------------------------------------------
# Database
# ----------------------------------------------------------
attachment_location = fields.Selection(
selection=lambda self: self._attachment_location_selection(),
config_parameter="ir_attachment.location",
string="Storage Location",
help="Attachment storage location.",
required=True,
default="file",
)
# ----------------------------------------------------------
# Actions
# ----------------------------------------------------------
def action_attachment_force_storage(self):
self.env["ir.attachment"].force_storage()

BIN
muk_utils/static/description/banner.png

After

Width: 880  |  Height: 440  |  Size: 49 KiB

BIN
muk_utils/static/description/icon.png

After

Width: 250  |  Height: 250  |  Size: 20 KiB

1
muk_utils/static/description/icon.svg
File diff suppressed because it is too large
View File

168
muk_utils/static/description/index.html

@ -0,0 +1,168 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">MuK Utils</h2>
<h3 class="oe_slogan">Utility Features</h3>
<h4 class="oe_slogan" style="font-size: 23px;">
MuK IT GmbH - www.mukit.at
</h4>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="text-justify" style="max-width: 84%; margin: 16px 8%;">
<h3 class="oe_slogan">Overview</h3>
<p class="oe_mt32">
Technical module to provide some utility features. The module is mainly
used as a dependency by other modules and to provide a collection of
common libraries. It has no direct visible effect on the system.
</p>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<h3 class="oe_slogan">Our Services</h3>
<div
style="display: flex; padding-top: 20px; justify-content: space-between;"
>
<div style="flex-basis: 18%;">
<a href="https://mukit.at/r/MQ5" target="_blank">
<div
style="width: 75px; height: 75px; border-radius: 100%; margin: auto;"
>
<img
src="service_implementation.png"
style="width: 100%; border-radius: 100%;"
/>
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 14px; color: #000 !important; margin-top: 5px; opacity: 1 !important; line-height: 17px;"
>
Odoo <br />Implementation
</h3>
</a>
</div>
<div style="flex-basis: 18%;">
<a href="https://mukit.at/r/u7c" target="_blank">
<div
style="width: 75px; height: 75px; border-radius: 100%; margin: auto;"
>
<img
src="service_integration.png"
style="width: 100%; border-radius: 100%;"
/>
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 14px; color: #000 !important; margin-top: 5px; opacity: 1 !important; line-height: 17px;"
>
Odoo <br />Integration
</h3>
</a>
</div>
<div style="flex-basis: 18%;">
<a href="https://mukit.at/r/xDJ" target="_blank">
<div
style="width: 75px; height: 75px; border-radius: 100%; margin: auto;"
>
<img
src="service_customization.png"
style="width: 100%; border-radius: 100%;"
/>
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 14px; color: #000 !important; margin-top: 5px; opacity: 1 !important; line-height: 17px;"
>
Odoo <br />Customization
</h3>
</a>
</div>
<div style="flex-basis: 18%;">
<a href=" https://mukit.at/r/J3A" target="_blank">
<div
style="width: 75px; height: 75px; border-radius: 100%; margin: auto;"
>
<img
src="service_development.png"
style="width: 100%; border-radius: 100%;"
/>
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 14px; color: #000 !important; margin-top: 5px; opacity: 1 !important; line-height: 17px;"
>
Odoo <br />Development
</h3>
</a>
</div>
<div style="flex-basis: 18%;">
<a href=" https://mukit.at/r/R1v" target="_blank">
<div
style="width: 75px; height: 75px; border-radius: 100%; margin: auto;"
>
<img
src="service_support.png"
style="width: 100%; border-radius: 100%;"
/>
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 14px; color: #000 !important; margin-top: 5px; opacity: 1 !important; line-height: 17px;"
>
Odoo <br />Support
</h3>
</a>
</div>
</div>
</div>
</section>
<section class="oe_container" style="padding: 32px 0;">
<div class="oe_row oe_spaced" style="margin: auto;">
<div class="oe_demo oe_picture oe_screenshot">
<a href="https://mukit.at/r/SgN" target="_blank">
<img src="preview.png" />
</a>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<h3 class="oe_slogan">Help and Support</h3>
<h5 class="oe_slogan" style="font-size: 20px;">
Feel free to contact us, if you need any help with your Odoo integration or
addiontal features.
</h5>
<div class="oe_slogan">
<a
class="btn btn-primary btn-lg mt8"
href="https://mukit.at"
target="_blank"
>
<i class="fa fa-globe"></i> Website
</a>
<a
class="btn btn-primary btn-lg mt8"
href="https://mukit.at/page/contactus"
target="_blank"
>
<i class="fa fa-envelope"></i> Contact Us
</a>
<a
class="btn btn-primary btn-lg mt8"
href="https://github.com/muk-it"
target="_blank"
>
<i class="fa fa-github"></i> Issues
</a>
</div>
<img
src="logo.png"
style="width: 200px; margin-bottom: 20px; display: block;"
class="mx-auto center-block"
/>
</section>

BIN
muk_utils/static/description/logo.png

After

Width: 500  |  Height: 500  |  Size: 37 KiB

BIN
muk_utils/static/description/preview.png

After

Width: 1000  |  Height: 200  |  Size: 32 KiB

BIN
muk_utils/static/description/service_customization.png

After

Width: 250  |  Height: 250  |  Size: 27 KiB

BIN
muk_utils/static/description/service_development.png

After

Width: 250  |  Height: 250  |  Size: 28 KiB

BIN
muk_utils/static/description/service_implementation.png

After

Width: 250  |  Height: 250  |  Size: 26 KiB

BIN
muk_utils/static/description/service_integration.png

After

Width: 250  |  Height: 250  |  Size: 24 KiB

BIN
muk_utils/static/description/service_support.png

After

Width: 250  |  Height: 250  |  Size: 24 KiB

30
muk_utils/tests/__init__.py

@ -0,0 +1,30 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
from . import (
test_attachment_migration,
test_file_tools,
test_http_tools,
test_json_tools,
test_search_childs,
test_search_parents,
test_security_helper,
)

69
muk_utils/tests/test_attachment_migration.py

@ -0,0 +1,69 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import logging
from odoo.osv import expression
from odoo.tests import common
_logger = logging.getLogger(__name__)
class MigrationTestCase(common.TransactionCase):
def setUp(self):
super(MigrationTestCase, self).setUp()
self.model = self.env["ir.attachment"]
self.params = self.env["ir.config_parameter"].sudo()
self.location = self.params.get_param("ir_attachment.location")
if self.location == "file":
self.params.set_param("ir_attachment.location", "db")
else:
self.params.set_param("ir_attachment.location", "file")
def tearDown(self):
self.params.set_param("ir_attachment.location", self.location)
super(MigrationTestCase, self).tearDown()
def test_storage_domain(self):
self.assertEqual(
self.model._get_storage_domain("db"), [("db_datas", "=", False)]
)
self.assertEqual(
self.model._get_storage_domain("file"), [("store_fname", "=", False)]
)
def test_force_storage_domain(self):
force_storage_domain = expression.AND(
[
self.model._get_storage_domain("db"),
[
"&",
"|",
("res_field", "=", False),
("res_field", "!=", False),
("type", "=", "binary"),
],
]
)
self.assertFalse(expression.is_false(self.model, force_storage_domain))
def test_migration(self):
self.model.search([("type", "=", "binary")], limit=25).migrate()

80
muk_utils/tests/test_file_tools.py

@ -0,0 +1,80 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import logging
import os
import shutil
import tempfile
from odoo.addons.muk_utils.tools import file
from odoo.tests import common
_logger = logging.getLogger(__name__)
class FileTestCase(common.TransactionCase):
def test_check_name(self):
self.assertTrue(file.check_name("Test"))
self.assertFalse(file.check_name("T/est"))
def test_compute_name(self):
self.assertEqual(file.compute_name("Test", 1, False), "Test(1)")
self.assertEqual(file.compute_name("Test.png", 1, True), "Test(1).png")
def test_unique_name(self):
self.assertEqual(file.unique_name("Test", ["A", "B"]), "Test")
self.assertEqual(file.unique_name("Test", ["Test"]), "Test(1)")
def test_unique_files(self):
files = file.unique_files(
[("Test.png", b"\xff data"), ("Test.png", b"\xff data")]
)
self.assertEqual(
files, [("Test.png", b"\xff data"), ("Test(1).png", b"\xff data")]
)
def test_guess_extension(self):
self.assertEqual(file.guess_extension(filename="Test.png"), "png")
self.assertEqual(file.guess_extension(mimetype="image/png"), "png")
def test_ensure_path_directories(self):
tmp_dir = tempfile.mkdtemp()
try:
path = os.path.join(tmp_dir, "Test/Test/")
file.ensure_path_directories(path)
self.assertTrue(os.path.exists(path))
finally:
shutil.rmtree(tmp_dir)
return True
def test_remove_empty_directories(self):
tmp_dir = tempfile.mkdtemp()
try:
dir = os.path.join(tmp_dir, "Test/")
path = os.path.join(dir, "Test/")
os.makedirs(path)
open(os.path.join(dir, "F"), "ab").close()
file.remove_empty_directories(path)
self.assertFalse(os.path.exists(path))
self.assertTrue(os.path.exists(dir))
finally:
shutil.rmtree(tmp_dir)
return True

35
muk_utils/tests/test_http_tools.py

@ -0,0 +1,35 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import base64
import logging
from odoo.addons.muk_utils.tools import http
from odoo.tests import common
_logger = logging.getLogger(__name__)
class HttpTestCase(common.TransactionCase):
def test_decode_http_basic_authentication(self):
credentials = base64.b64encode(b"username:password").decode("ascii")
res = http.decode_http_basic_authentication("Basic {}".format(credentials))
self.assertEqual(res, ("username", "password"))

34
muk_utils/tests/test_json_tools.py

@ -0,0 +1,34 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import json
import logging
from odoo.addons.muk_utils.tools.json import RecordEncoder
from odoo.tests import common
_logger = logging.getLogger(__name__)
class JsonTestCase(common.TransactionCase):
def test_json_dumps(self):
record = self.env["ir.attachment"].search_read([], limit=1)
json.dumps(record, sort_keys=True, indent=4, cls=RecordEncoder)

60
muk_utils/tests/test_search_childs.py

@ -0,0 +1,60 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import logging
from odoo.tests import common
_logger = logging.getLogger(__name__)
class SearchChildsTestCase(common.TransactionCase):
def setUp(self):
super(SearchChildsTestCase, self).setUp()
self.model = self.env["res.partner.category"]
self.parent = self.model.create(
{"parent_id": False, "name": "Parent", "active": True}
)
self.child = self.model.create(
{"parent_id": self.parent.id, "name": "Child", "active": True}
)
self.child_parent = self.model.create(
{"parent_id": self.parent.id, "name": "Child Parent", "active": True}
)
self.child_parent_child = self.model.create(
{
"parent_id": self.child_parent.id,
"name": "Child Parent Child",
"active": True,
}
)
def tearDown(self):
super(SearchChildsTestCase, self).tearDown()
def test_search_childs(self):
childs = self.model.search_childs(self.parent.id)
self.assertEqual(set(childs.ids), {self.child.id, self.child_parent.id})
def test_search_read_childs(self):
childs = self.model.search_childs(self.parent.id)
childs_names = self.model.search_read_childs(self.parent.id, fields=["name"])
self.assertEqual(childs.read(["name"]), childs_names)

112
muk_utils/tests/test_search_parents.py

@ -0,0 +1,112 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import logging
from odoo.tests import common
_logger = logging.getLogger(__name__)
class SearchParentTestCase(common.TransactionCase):
def setUp(self):
super(SearchParentTestCase, self).setUp()
self.model = self.env["res.partner.category"]
self.parent = self.model.create(
{"parent_id": False, "name": "Parent", "active": True}
)
self.child = self.model.create(
{"parent_id": self.parent.id, "name": "Child", "active": True}
)
self.child_parent = self.model.create(
{"parent_id": self.parent.id, "name": "Child Parent", "active": True}
)
self.child_parent_child = self.model.create(
{
"parent_id": self.child_parent.id,
"name": "Child Parent Child",
"active": True,
}
)
self.ids = [
self.parent.id,
self.child.id,
self.child_parent.id,
self.child_parent_child.id,
]
self.domain = [("id", "in", self.ids)]
def tearDown(self):
super(SearchParentTestCase, self).tearDown()
def _evaluate_parent_result(self, parents, records):
for parent in parents:
self.assertTrue(
not parent.parent_id or parent.parent_id.id not in records.ids
)
def test_search_parents(self):
records = self.model.search([])
parents = self.model.search_parents([])
self._evaluate_parent_result(parents, records)
def test_search_parents_domain(self):
records = self.model.search([("id", "!=", 1)])
parents = self.model.search_parents([("id", "!=", 1)])
self._evaluate_parent_result(parents, records)
def test_search_parents_domain(self):
records = self.model.search([("id", "!=", 1)])
parents = self.model.search_parents([("id", "!=", 1)])
self._evaluate_parent_result(parents, records)
def test_search_parents_args(self):
records = self.model.search([], offset=1, limit=1, order="name desc")
parents = self.model.search_parents(offset=1, limit=1, order="name desc")
self._evaluate_parent_result(parents, records)
def test_search_parents_count(self):
parents = self.model.search_parents(self.domain, count=False)
parent_count = self.model.search_parents(self.domain, count=True)
self.assertTrue(len(parents) == parent_count)
def test_search_parents_access_rights(self):
model = self.model.with_user(self.browse_ref("base.user_admin"))
parents = model.search_parents(self.domain)
self._evaluate_parent_result(parents, model.browse(self.ids))
self.assertTrue(len(parents) == 1 and parents.id == self.parent.id)
access_rule = self.env["ir.rule"].create(
{
"model_id": self.browse_ref("base.model_res_partner_category").id,
"domain_force": [("id", "!=", self.parent.id)],
"name": "Restrict Access",
}
)
records = model.search(self.domain)
parents = model.search_parents(self.domain)
self._evaluate_parent_result(parents, records)
self.assertTrue(set(parents.ids) == {self.child.id, self.child_parent.id})
def test_search_read_parents(self):
parents = self.model.search_parents([])
read_names = parents.read(["name"])
search_names = self.model.search_read_parents([], ["name"])
self.assertTrue(read_names == search_names)

50
muk_utils/tests/test_security_helper.py

@ -0,0 +1,50 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import logging
from odoo.tests import common
_logger = logging.getLogger(__name__)
class SecurityTestCase(common.TransactionCase):
def setUp(self):
super(SecurityTestCase, self).setUp()
self.model = self.env["res.partner"].with_user(
self.browse_ref("base.user_admin")
)
self.record_ids = self.model.search([], limit=25).ids
def tearDown(self):
super(SecurityTestCase, self).tearDown()
def test_check_access(self):
self.model.browse(self.record_ids).check_access("read")
self.model.browse(self.record_ids).check_access("create")
self.model.browse(self.record_ids).check_access("write")
self.model.browse(self.record_ids).check_access("unlink")
def test_filter_access(self):
self.model.browse(self.record_ids)._filter_access("read", in_memory=True)
self.model.browse(self.record_ids)._filter_access("read", in_memory=False)
self.model.browse(self.record_ids)._filter_access_ids("read", in_memory=True)
self.model.browse(self.record_ids)._filter_access_ids("read", in_memory=False)

22
muk_utils/tools/__init__.py

@ -0,0 +1,22 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
from . import file, http, json, patch, security

97
muk_utils/tools/file.py

@ -0,0 +1,97 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import mimetypes
import os
import shutil
import tempfile
from odoo.tools.mimetypes import guess_mimetype
def check_name(name):
tmp_dir = tempfile.mkdtemp()
try:
open(os.path.join(tmp_dir, name), "a").close()
except IOError:
return False
finally:
shutil.rmtree(tmp_dir)
return True
def compute_name(name, suffix, escape_suffix):
if escape_suffix:
name, extension = os.path.splitext(name)
return "{}({}){}".format(name, suffix, extension)
else:
return "{}({})".format(name, suffix)
def unique_name(name, names, escape_suffix=False):
if not name in names:
return name
else:
suffix = 1
name = compute_name(name, suffix, escape_suffix)
while name in names:
suffix += 1
name = compute_name(name, suffix, escape_suffix)
return name
def unique_files(files):
ufiles = []
unames = []
for file in files:
uname = unique_name(file[0], unames, escape_suffix=True)
ufiles.append((uname, file[1]))
unames.append(uname)
return ufiles
def guess_extension(filename=None, mimetype=None, binary=None):
extension = filename and os.path.splitext(filename)[1][1:].strip().lower()
if not extension and mimetype:
extension = mimetypes.guess_extension(mimetype)[1:].strip().lower()
if not extension and binary:
mimetype = guess_mimetype(binary, default="")
extension = mimetypes.guess_extension(mimetype)[1:].strip().lower()
return extension
def ensure_path_directories(path):
directory_path = os.path.dirname(path)
if not os.path.exists(directory_path):
os.makedirs(directory_path)
def remove_empty_directories(path):
if not os.path.isdir(path):
return
entries = os.listdir(path)
if len(entries) > 0:
for entry in entries:
subpath = os.path.join(path, entry)
if os.path.isdir(subpath):
self._remove_empty_directories(subpath)
else:
os.rmdir(path)

46
muk_utils/tools/http.py

@ -0,0 +1,46 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import base64
import urllib
from werkzeug.datastructures import CombinedMultiDict
def decode_http_basic_authentication_value(value):
try:
username, password = base64.b64decode(value).decode().split(":", 1)
return urllib.parse.unquote(username), urllib.parse.unquote(password)
except:
return None, None
def decode_http_basic_authentication(encoded_header):
header_values = encoded_header.strip().split(" ")
if len(header_values) == 1:
return decode_http_basic_authentication_value(header_values[0])
if len(header_values) == 2 and header_values[0].strip().lower() == "basic":
return decode_http_basic_authentication_value(header_values[1])
return None, None
def request_params(httprequest):
return CombinedMultiDict([httprequest.args, httprequest.form, httprequest.files])

44
muk_utils/tools/json.py

@ -0,0 +1,44 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import datetime
import json
from odoo import fields, models
from odoo.tools import ustr
class ResponseEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.date):
if isinstance(obj, datetime.datetime):
return fields.Datetime.to_string(obj)
return fields.Date.to_string(obj)
if isinstance(obj, (bytes, bytearray)):
return obj.decode()
return ustr(obj)
class RecordEncoder(ResponseEncoder):
def default(self, obj):
if isinstance(obj, models.BaseModel):
return obj.name_get()
return ResponseEncoder.default(self, obj)

30
muk_utils/tools/patch.py

@ -0,0 +1,30 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
def monkey_patch(cls):
def decorate(func):
name = func.__name__
func.super = getattr(cls, name, None)
setattr(cls, name, func)
return func
return decorate

30
muk_utils/tools/security.py

@ -0,0 +1,30 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
import random
import string
UNICODE_ASCII_CHARACTERS = string.ascii_letters + string.digits
def generate_token(length=30, chars=UNICODE_ASCII_CHARACTERS):
generator = random.SystemRandom()
return "".join(generator.choice(chars) for index in range(length))

25
muk_utils/tools/utils.py

@ -0,0 +1,25 @@
###################################################################################
#
# Copyright (c) 2017-2019 MuK IT GmbH.
#
# This file is part of MuK Utils
# (see https://mukit.at).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
def uniquify_list(seq):
seen = set()
return [val for val in seq if val not in seen and not seen.add(val)]

70
muk_utils/views/ir_attachment.xml

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017-2019 MuK IT GmbH.
This file is part of MuK Utils
(see https://mukit.at).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<odoo>
<record id="view_attachment_search" model="ir.ui.view">
<field name="name">ir_attachment.search</field>
<field name="model">ir.attachment</field>
<field name="inherit_id" ref="base.view_attachment_search"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='url_filter']" position="before">
<separator/>
<filter name="all" string="All Data" domain="['|',('res_field', '=', False),('res_field', '!=', False)]"/>
<filter name="set_res_field" string="Field Data" domain="[('res_field', '!=', False)]"/>
<filter name="no_res_field" string="Attachments" domain="[('res_field', '=', False)]"/>
<separator/>
</xpath>
<xpath expr="//group//filter[last()]" position="before">
<filter name="group_res_model" string="Attached Document Model" context="{'group_by': 'res_model'}" />
<filter name="group_res_field" string="Attached Document Field" context="{'group_by': 'res_field'}" />
</xpath>
</field>
</record>
<record id="view_attachment_tree" model="ir.ui.view">
<field name="name">ir_attachment.tree</field>
<field name="model">ir.attachment</field>
<field name="inherit_id" ref="base.view_attachment_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="after">
<field name="mimetype" />
</xpath>
</field>
</record>
<record id="view_attachment_form" model="ir.ui.view">
<field name="name">ir_attachment.form</field>
<field name="model">ir.attachment</field>
<field name="inherit_id" ref="base.view_attachment_form"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='description_group']" position="before">
<group string="Storage" name="storage" groups="base.group_no_one">
<field name="db_datas" readonly="1" attrs="{'invisible':[('db_datas','=',False)]}"/>
<field name="store_fname" readonly="1" attrs="{'invisible':[('store_fname','=',False)]}"/>
</group>
</xpath>
</field>
</record>
</odoo>

110
muk_utils/views/mixins_groups.xml

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017-2019 MuK IT GmbH.
This file is part of MuK Utils
(see https://mukit.at).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<odoo>
<record id="view_mixins_groups_search" model="ir.ui.view">
<field name="name">muk_utils_mixins_groups.search</field>
<field name="model">muk_utils.mixins.groups</field>
<field name="arch" type="xml">
<search string="Groups">
<field name="name"/>
</search>
</field>
</record>
<record id="view_mixins_groups_tree" model="ir.ui.view">
<field name="name">muk_utils_mixins_groups.tree</field>
<field name="model">muk_utils.mixins.groups</field>
<field name="arch" type="xml">
<tree string="Groups">
<field name="name" />
<field name="count_users" />
</tree>
</field>
</record>
<record id="view_mixins_groups_form" model="ir.ui.view">
<field name="name">muk_utils_mixins_groups.form</field>
<field name="model">muk_utils.mixins.groups</field>
<field name="arch" type="xml">
<form string="Group">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" />
<h1>
<field name="name" />
</h1>
</div>
<group name="group" string="Group">
<group>
<field name="parent_group" />
</group>
<group>
<field name="count_users" />
</group>
</group>
<notebook>
<page name="users" string="Users">
<field name="users">
<tree string="Users">
<field name="name" />
<field name="login" />
<field name="lang" />
<field name="login_date" />
</tree>
</field>
</page>
<page name="groups" string="Groups">
<field name="groups">
<tree string="Groups">
<field name="name" />
<field name="comment" />
</tree>
</field>
</page>
<page name="extra_users" string="Explicit Users">
<field name="explicit_users">
<tree string="Explicit Users">
<field name="name" />
<field name="login" />
<field name="lang" />
<field name="login_date" />
</tree>
</field>
</page>
<page name="childs" string="Child Groups">
<field name="child_groups">
<tree string="Groups">
<field name="name" />
<field name="count_users" />
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
</odoo>

56
muk_utils/views/res_config_settings.xml

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017-2019 MuK IT GmbH.
This file is part of MuK Utils
(see https://mukit.at).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
<field name="arch" type="xml">
<div name="integration" position="after">
<h2>Storage</h2>
<div class="row mt16 o_settings_container" name="storage">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"></div>
<div class="o_setting_right_pane">
<label for="attachment_location"/>
<div class="text-muted">
Attachment storage location
</div>
<div class="mt8">
<field name="attachment_location" class="o_light_label"/>
</div>
<div class="mt8">
<button name="attachment_force_storage"
string="Force Storage Migration"
type="object" icon="fa-refresh"/>
</div>
</div>
</div>
</div>
</div>
</field>
</record>
</odoo>
Loading…
Cancel
Save