diff --git a/muk_utils/LICENSE b/muk_utils/LICENSE new file mode 100644 index 0000000..11e8067 --- /dev/null +++ b/muk_utils/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. diff --git a/muk_utils/README.rst b/muk_utils/README.rst new file mode 100644 index 0000000..8e5cbfc --- /dev/null +++ b/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 `_). + +To install our modules using the package manager make sure +`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 `` + +The module name consists of the Odoo version and the module name, where +underscores are replaced by a dash. + +**Module:** + +``odoo-addon-`` + +**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 `` + +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 `_ +and find a more detailed installation guide on our `website `_. + +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 `_ +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 `` + +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 + +Images +------ + +Some pictures are based on or inspired by the icon set of Font Awesome: + +* `Font Awesome `_ + +Author & Maintainer +------------------- + +This module is maintained by the `MuK IT GmbH `_. + +MuK IT is an Austrian company specialized in customizing and extending Odoo. +We develop custom solutions for your individual needs to help you focus on +your strength and expertise to grow your business. + +If you want to get in touch please contact us via `mail `_ +or visit our `website `_. diff --git a/muk_utils/__init__.py b/muk_utils/__init__.py new file mode 100644 index 0000000..b8ecfdc --- /dev/null +++ b/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 . +################################################################################### + +from . import models, tools diff --git a/muk_utils/__manifest__.py b/muk_utils/__manifest__.py new file mode 100644 index 0000000..18fe880 --- /dev/null +++ b/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 . +################################################################################### + +{ + "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 "], + "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, +} diff --git a/muk_utils/actions/ir_attachment.xml b/muk_utils/actions/ir_attachment.xml new file mode 100644 index 0000000..1fd39a2 --- /dev/null +++ b/muk_utils/actions/ir_attachment.xml @@ -0,0 +1,34 @@ + + + + + + + + Migrate + + + code + records.action_migrate() + + + diff --git a/muk_utils/doc/changelog.rst b/muk_utils/doc/changelog.rst new file mode 100644 index 0000000..fcc9635 --- /dev/null +++ b/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 diff --git a/muk_utils/doc/index.rst b/muk_utils/doc/index.rst new file mode 100644 index 0000000..8e5cbfc --- /dev/null +++ b/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 `_). + +To install our modules using the package manager make sure +`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 `` + +The module name consists of the Odoo version and the module name, where +underscores are replaced by a dash. + +**Module:** + +``odoo-addon-`` + +**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 `` + +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 `_ +and find a more detailed installation guide on our `website `_. + +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 `_ +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 `` + +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 + +Images +------ + +Some pictures are based on or inspired by the icon set of Font Awesome: + +* `Font Awesome `_ + +Author & Maintainer +------------------- + +This module is maintained by the `MuK IT GmbH `_. + +MuK IT is an Austrian company specialized in customizing and extending Odoo. +We develop custom solutions for your individual needs to help you focus on +your strength and expertise to grow your business. + +If you want to get in touch please contact us via `mail `_ +or visit our `website `_. diff --git a/muk_utils/i18n/ar.po b/muk_utils/i18n/ar.po new file mode 100644 index 0000000..20c2caf --- /dev/null +++ b/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 "Save 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 "المستخدمون" diff --git a/muk_utils/i18n/de.po b/muk_utils/i18n/de.po new file mode 100644 index 0000000..cb29f86 --- /dev/null +++ b/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 "Save this page before triggering the migration." +msgstr "SpeichernSie 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" diff --git a/muk_utils/i18n/es.po b/muk_utils/i18n/es.po new file mode 100644 index 0000000..e111f90 --- /dev/null +++ b/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 "Save this page before triggering the migration." +msgstr "Save 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" diff --git a/muk_utils/i18n/fr.po b/muk_utils/i18n/fr.po new file mode 100644 index 0000000..c8cca24 --- /dev/null +++ b/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 "Save this page before triggering the migration." +msgstr "Save 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" diff --git a/muk_utils/i18n/hi.po b/muk_utils/i18n/hi.po new file mode 100644 index 0000000..7c00033 --- /dev/null +++ b/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 "Save 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 "" diff --git a/muk_utils/i18n/muk_utils.pot b/muk_utils/i18n/muk_utils.pot new file mode 100644 index 0000000..1138072 --- /dev/null +++ b/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 "Save 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 "" diff --git a/muk_utils/i18n/nl.po b/muk_utils/i18n/nl.po new file mode 100644 index 0000000..ffdabfc --- /dev/null +++ b/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 "Save this page before triggering the migration." +msgstr "Save 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" diff --git a/muk_utils/i18n/pt.po b/muk_utils/i18n/pt.po new file mode 100644 index 0000000..7d39a89 --- /dev/null +++ b/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 "Save 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" diff --git a/muk_utils/i18n/ru.po b/muk_utils/i18n/ru.po new file mode 100644 index 0000000..b6bded4 --- /dev/null +++ b/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 "Save 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 "Пользователи" diff --git a/muk_utils/models/__init__.py b/muk_utils/models/__init__.py new file mode 100644 index 0000000..bc28605 --- /dev/null +++ b/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 . +################################################################################### + +from . import ( + base, + ir_attachment, + ir_config_parameter, + mixins_groups, + mixins_hierarchy, + res_config_settings, +) diff --git a/muk_utils/models/base.py b/muk_utils/models/base.py new file mode 100644 index 0000000..804ff2f --- /dev/null +++ b/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 . +################################################################################### + +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 (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 (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 (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 (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 + ) diff --git a/muk_utils/models/ir_attachment.py b/muk_utils/models/ir_attachment.py new file mode 100644 index 0000000..d8e734c --- /dev/null +++ b/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 . +################################################################################### + +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() diff --git a/muk_utils/models/ir_config_parameter.py b/muk_utils/models/ir_config_parameter.py new file mode 100644 index 0000000..f606f0d --- /dev/null +++ b/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 . +################################################################################### + +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) diff --git a/muk_utils/models/mixins_groups.py b/muk_utils/models/mixins_groups.py new file mode 100644 index 0000000..0133068 --- /dev/null +++ b/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 . +################################################################################### + +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)}) diff --git a/muk_utils/models/mixins_hierarchy.py b/muk_utils/models/mixins_hierarchy.py new file mode 100644 index 0000000..db96b84 --- /dev/null +++ b/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 . +################################################################################### + +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 diff --git a/muk_utils/models/res_config_settings.py b/muk_utils/models/res_config_settings.py new file mode 100644 index 0000000..54a250a --- /dev/null +++ b/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 . +################################################################################### + +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() diff --git a/muk_utils/static/description/banner.png b/muk_utils/static/description/banner.png new file mode 100644 index 0000000..cf5692b Binary files /dev/null and b/muk_utils/static/description/banner.png differ diff --git a/muk_utils/static/description/icon.png b/muk_utils/static/description/icon.png new file mode 100644 index 0000000..1b124a9 Binary files /dev/null and b/muk_utils/static/description/icon.png differ diff --git a/muk_utils/static/description/icon.svg b/muk_utils/static/description/icon.svg new file mode 100644 index 0000000..45683e2 --- /dev/null +++ b/muk_utils/static/description/icon.svg @@ -0,0 +1 @@ + diff --git a/muk_utils/static/description/index.html b/muk_utils/static/description/index.html new file mode 100644 index 0000000..41933a0 --- /dev/null +++ b/muk_utils/static/description/index.html @@ -0,0 +1,168 @@ +
+
+

MuK Utils

+

Utility Features

+

+ MuK IT GmbH - www.mukit.at +

+
+
+ +
+
+
+

Overview

+

+ 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. +

+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+
+ +
+

Help and Support

+
+ Feel free to contact us, if you need any help with your Odoo integration or + addiontal features. +
+ + +
diff --git a/muk_utils/static/description/logo.png b/muk_utils/static/description/logo.png new file mode 100644 index 0000000..9427ce3 Binary files /dev/null and b/muk_utils/static/description/logo.png differ diff --git a/muk_utils/static/description/preview.png b/muk_utils/static/description/preview.png new file mode 100644 index 0000000..1deb1cc Binary files /dev/null and b/muk_utils/static/description/preview.png differ diff --git a/muk_utils/static/description/service_customization.png b/muk_utils/static/description/service_customization.png new file mode 100644 index 0000000..3eac664 Binary files /dev/null and b/muk_utils/static/description/service_customization.png differ diff --git a/muk_utils/static/description/service_development.png b/muk_utils/static/description/service_development.png new file mode 100644 index 0000000..580d460 Binary files /dev/null and b/muk_utils/static/description/service_development.png differ diff --git a/muk_utils/static/description/service_implementation.png b/muk_utils/static/description/service_implementation.png new file mode 100644 index 0000000..d64b66b Binary files /dev/null and b/muk_utils/static/description/service_implementation.png differ diff --git a/muk_utils/static/description/service_integration.png b/muk_utils/static/description/service_integration.png new file mode 100644 index 0000000..76c5e80 Binary files /dev/null and b/muk_utils/static/description/service_integration.png differ diff --git a/muk_utils/static/description/service_support.png b/muk_utils/static/description/service_support.png new file mode 100644 index 0000000..4c530fa Binary files /dev/null and b/muk_utils/static/description/service_support.png differ diff --git a/muk_utils/tests/__init__.py b/muk_utils/tests/__init__.py new file mode 100644 index 0000000..14e21de --- /dev/null +++ b/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 . +################################################################################### + +from . import ( + test_attachment_migration, + test_file_tools, + test_http_tools, + test_json_tools, + test_search_childs, + test_search_parents, + test_security_helper, +) diff --git a/muk_utils/tests/test_attachment_migration.py b/muk_utils/tests/test_attachment_migration.py new file mode 100644 index 0000000..d986905 --- /dev/null +++ b/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 . +################################################################################### + +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() diff --git a/muk_utils/tests/test_file_tools.py b/muk_utils/tests/test_file_tools.py new file mode 100644 index 0000000..40c12d1 --- /dev/null +++ b/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 . +################################################################################### + +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 diff --git a/muk_utils/tests/test_http_tools.py b/muk_utils/tests/test_http_tools.py new file mode 100644 index 0000000..4d7d4b9 --- /dev/null +++ b/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 . +################################################################################### + +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")) diff --git a/muk_utils/tests/test_json_tools.py b/muk_utils/tests/test_json_tools.py new file mode 100644 index 0000000..2ac6262 --- /dev/null +++ b/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 . +################################################################################### + +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) diff --git a/muk_utils/tests/test_search_childs.py b/muk_utils/tests/test_search_childs.py new file mode 100644 index 0000000..4e8d971 --- /dev/null +++ b/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 . +################################################################################### + +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) diff --git a/muk_utils/tests/test_search_parents.py b/muk_utils/tests/test_search_parents.py new file mode 100644 index 0000000..9068a47 --- /dev/null +++ b/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 . +################################################################################### + +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) diff --git a/muk_utils/tests/test_security_helper.py b/muk_utils/tests/test_security_helper.py new file mode 100644 index 0000000..07ffa8b --- /dev/null +++ b/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 . +################################################################################### + +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) diff --git a/muk_utils/tools/__init__.py b/muk_utils/tools/__init__.py new file mode 100644 index 0000000..3f12832 --- /dev/null +++ b/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 . +################################################################################### + +from . import file, http, json, patch, security diff --git a/muk_utils/tools/file.py b/muk_utils/tools/file.py new file mode 100644 index 0000000..a7376ef --- /dev/null +++ b/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 . +################################################################################### + +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) diff --git a/muk_utils/tools/http.py b/muk_utils/tools/http.py new file mode 100644 index 0000000..ffbbb8c --- /dev/null +++ b/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 . +################################################################################### + +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]) diff --git a/muk_utils/tools/json.py b/muk_utils/tools/json.py new file mode 100644 index 0000000..1d810d3 --- /dev/null +++ b/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 . +################################################################################### + +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) diff --git a/muk_utils/tools/patch.py b/muk_utils/tools/patch.py new file mode 100644 index 0000000..ee02c03 --- /dev/null +++ b/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 . +################################################################################### + + +def monkey_patch(cls): + def decorate(func): + name = func.__name__ + func.super = getattr(cls, name, None) + setattr(cls, name, func) + return func + + return decorate diff --git a/muk_utils/tools/security.py b/muk_utils/tools/security.py new file mode 100644 index 0000000..e382ade --- /dev/null +++ b/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 . +################################################################################### + +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)) diff --git a/muk_utils/tools/utils.py b/muk_utils/tools/utils.py new file mode 100644 index 0000000..22cd82f --- /dev/null +++ b/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 . +################################################################################### + + +def uniquify_list(seq): + seen = set() + return [val for val in seq if val not in seen and not seen.add(val)] diff --git a/muk_utils/views/ir_attachment.xml b/muk_utils/views/ir_attachment.xml new file mode 100644 index 0000000..47bb25d --- /dev/null +++ b/muk_utils/views/ir_attachment.xml @@ -0,0 +1,70 @@ + + + + + + + + ir_attachment.search + ir.attachment + + + + + + + + + + + + + + + + + + ir_attachment.tree + ir.attachment + + + + + + + + + + ir_attachment.form + ir.attachment + + + + + + + + + + + + diff --git a/muk_utils/views/mixins_groups.xml b/muk_utils/views/mixins_groups.xml new file mode 100644 index 0000000..2978ab5 --- /dev/null +++ b/muk_utils/views/mixins_groups.xml @@ -0,0 +1,110 @@ + + + + + + + + muk_utils_mixins_groups.search + muk_utils.mixins.groups + + + + + + + + + muk_utils_mixins_groups.tree + muk_utils.mixins.groups + + + + + + + + + + muk_utils_mixins_groups.form + muk_utils.mixins.groups + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +
diff --git a/muk_utils/views/res_config_settings.xml b/muk_utils/views/res_config_settings.xml new file mode 100644 index 0000000..35c8442 --- /dev/null +++ b/muk_utils/views/res_config_settings.xml @@ -0,0 +1,56 @@ + + + + + + + + res.config.settings.view.form + res.config.settings + + +
+

Storage

+
+
+
+
+
+
+
+
+
+
+ +