From 6d7e49ae08802d7eb018186d7242b4e5598e5433 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 18 Sep 2015 16:45:20 +0200 Subject: [PATCH 1/4] Rename addon according to the new term: partner_changeset Add translations Add test coverage for caching of changeset rules Add unique constraint (model_id, field_id) on rules Add rules in demo data Put the security groups links in noupdate Put keep the groups in a noupdate=0 section so the records in ir.model.data will still be modifiable by other modules. Store the source of a changeset Differentiate rules according to their origin Rules are applied also for manual edition Action is required Do not keep recordsets in ormcache Because they would be unreadable as soon as the cursor is closed. Instead, we keep only the id and the record is browsed for every new environment. Remove useless 'model_id' on changeset rules model_id has been removed Remove reference to the model_name on rules Because the model has been removed earlier (dead code) Fix issue when applying empty many2one Do not create changesets on moved contacts As we just created the contact with a 'copy' we don't want to have a changeset for the initialization values Update translations Use a selection widget on source model Adapt for inclusion in OCA Rename 'Pending Changesets' to 'Changes' It's shorter Add screenshots Do not create a changeset when both sides are empty But have a different type (e.g. False and '') --- partner_changeset/README.rst | 171 ++++++ partner_changeset/__init__.py | 4 + partner_changeset/__openerp__.py | 23 + .../demo/changeset_field_rule.xml | 51 ++ partner_changeset/i18n/fr.po | 313 +++++++++++ partner_changeset/i18n/partner_changeset.pot | 289 ++++++++++ partner_changeset/models/__init__.py | 7 + .../models/changeset_field_rule.py | 144 +++++ partner_changeset/models/res_partner.py | 50 ++ .../models/res_partner_changeset.py | 514 ++++++++++++++++++ .../security/ir.model.access.csv | 10 + partner_changeset/security/security.xml | 29 + partner_changeset/static/description/icon.png | Bin 0 -> 9455 bytes .../static/src/img/changeset.png | Bin 0 -> 86707 bytes partner_changeset/static/src/img/rules.png | Bin 0 -> 61527 bytes partner_changeset/tests/__init__.py | 6 + partner_changeset/tests/common.py | 77 +++ .../tests/test_changeset_field_rule.py | 95 ++++ .../tests/test_changeset_field_type.py | 279 ++++++++++ .../tests/test_changeset_flow.py | 246 +++++++++ .../tests/test_changeset_origin.py | 110 ++++ .../views/changeset_field_rule_views.xml | 63 +++ partner_changeset/views/menu.xml | 10 + .../views/res_partner_changeset_views.xml | 159 ++++++ partner_changeset/views/res_partner_views.xml | 41 ++ 25 files changed, 2691 insertions(+) create mode 100644 partner_changeset/README.rst create mode 100644 partner_changeset/__init__.py create mode 100644 partner_changeset/__openerp__.py create mode 100644 partner_changeset/demo/changeset_field_rule.xml create mode 100644 partner_changeset/i18n/fr.po create mode 100644 partner_changeset/i18n/partner_changeset.pot create mode 100644 partner_changeset/models/__init__.py create mode 100644 partner_changeset/models/changeset_field_rule.py create mode 100644 partner_changeset/models/res_partner.py create mode 100644 partner_changeset/models/res_partner_changeset.py create mode 100644 partner_changeset/security/ir.model.access.csv create mode 100644 partner_changeset/security/security.xml create mode 100644 partner_changeset/static/description/icon.png create mode 100644 partner_changeset/static/src/img/changeset.png create mode 100644 partner_changeset/static/src/img/rules.png create mode 100644 partner_changeset/tests/__init__.py create mode 100644 partner_changeset/tests/common.py create mode 100644 partner_changeset/tests/test_changeset_field_rule.py create mode 100644 partner_changeset/tests/test_changeset_field_type.py create mode 100644 partner_changeset/tests/test_changeset_flow.py create mode 100644 partner_changeset/tests/test_changeset_origin.py create mode 100644 partner_changeset/views/changeset_field_rule_views.xml create mode 100644 partner_changeset/views/menu.xml create mode 100644 partner_changeset/views/res_partner_changeset_views.xml create mode 100644 partner_changeset/views/res_partner_views.xml diff --git a/partner_changeset/README.rst b/partner_changeset/README.rst new file mode 100644 index 000000000..8fe23d0b6 --- /dev/null +++ b/partner_changeset/README.rst @@ -0,0 +1,171 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +================== +Partner Changesets +================== + +This module extends the functionality of partners. It allows to create +changesets that must be validated when a partner is modified instead of direct +modifications. Rules allow to configure which field must be validated. + +Configuration +============= + +Access Rights +------------- + +The changesets rules must be edited by users with the group ``Changesets +Configuration``. The changesets can be applied or canceled only by users +with the group ``Changesets Validations`` + +Changesets Rules +---------------- + +The changesets rules can be configured in ``Sales > Configuration > +Partner Changesets > Fields Rules``. For each partner field, an +action can be defined: + +* Auto: the changes made on this field are always applied +* Validate: the changes made on this field must be manually confirmed by + a 'Changesets User' user +* Never: the changes made on this field are always refused + +In any case, all the changes made by the users are always applied +directly on the users, but a 'validated' changeset is created for the +history. + +The supported fields are: + +* Char +* Text +* Date +* Datetime +* Integer +* Float +* Boolean +* Many2one + +Rules can be global (no source model) or configured by source model. +Rules by source model have the priority. If a field is not configured +for the source model, it will use the global rule (if existing). + +If a field has no rule, it is written to the partner without changeset. + +Usage +===== + +General case +------------ + +The first step is to create the changeset rules, once that done, writes on +partners will be created as changesets. + +Finding changesets +------------------ + +A menu lists all the changesets in ``Sales > Configuration > Partner +Changesets > Changesets``. + +However, it is more convenient to access them directly from the +partners. Pending changesets can be accessed directly from the top right +of the partners' view. A new filter on the partners shows the partners +having at least one pending changeset. + +Handling changesets +------------------- + +A changeset shows the list of the changes made on a partner. Some of the +changes may be 'Pending', some 'Accepted' or 'Rejected' according to the +changeset rules. The only changes that need an action from the user are +'Pending' changes. When a change is accepted, the value is written on +the user. + +The changes view shows the name of the partner's field, the Origin value +and the New value alongside the state of the change. By clicking on the +change in some cases a more detailed view is displayed, for instance, +links for relations can be clicked on. + +A button on a changeset allows to apply or reject all the changes at +once. + +Custom source rules in your addon +--------------------------------- + +Addons wanting to create changeset with their own rules should pass the +following keys in the context when they write on the partner: + +* ``__changeset_rules_source_model``: name of the model which asks for + the change +* ``__changeset_rules_source_id``: id of the record which asks for the + change + +Also, they should extend the selection in +``ChangesetFieldRule._domain_source_models`` to add their model (the +same that is passed in ``__changeset_rules_source_model``). + +The source is used for the application of the rules, allowing to have a +different rule for a different source. It is also stored on the changeset for +information. + +Screenshot: +----------- + +* Configuration of rules + + .. image:: partner_changeset/static/src/img/rules.png + +* Changeset waiting for validation + + .. image:: partner_changeset/static/src/img/changeset.png + + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/134/8.0 + +Known issues / Roadmap +====================== + +* Only a subset of the type of fields is actually supported + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed `feedback +`_. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Guewen Baconnier + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/partner_changeset/__init__.py b/partner_changeset/__init__.py new file mode 100644 index 000000000..a77a6fcbc --- /dev/null +++ b/partner_changeset/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/partner_changeset/__openerp__.py b/partner_changeset/__openerp__.py new file mode 100644 index 000000000..adad33240 --- /dev/null +++ b/partner_changeset/__openerp__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# © 2015 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{'name': 'Partner Changesets', + 'version': '8.0.1.0.0', + 'author': 'Camptocamp, Odoo Community Association (OCA)', + 'license': 'AGPL-3', + 'category': 'Sales Management', + 'depends': ['base', + ], + 'website': 'http://www.camptocamp.com', + 'data': ['security/security.xml', + 'security/ir.model.access.csv', + 'views/menu.xml', + 'views/res_partner_changeset_views.xml', + 'views/changeset_field_rule_views.xml', + 'views/res_partner_views.xml', + ], + 'demo': ['demo/changeset_field_rule.xml', + ], + 'installable': True, + } diff --git a/partner_changeset/demo/changeset_field_rule.xml b/partner_changeset/demo/changeset_field_rule.xml new file mode 100644 index 000000000..1b3acfcdb --- /dev/null +++ b/partner_changeset/demo/changeset_field_rule.xml @@ -0,0 +1,51 @@ + + + + + + + auto + + + + + validate + + + + + validate + + + + + validate + + + + + validate + + + + + never + + + + + validate + + + + + validate + + + + + validate + + + + diff --git a/partner_changeset/i18n/fr.po b/partner_changeset/i18n/fr.po new file mode 100644 index 000000000..aff512038 --- /dev/null +++ b/partner_changeset/i18n/fr.po @@ -0,0 +1,313 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * partner_changeset +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-25 08:31+0000\n" +"PO-Revision-Date: 2015-09-18 14:48+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: partner_changeset +#: sql_constraint:changeset.field.rule:0 +msgid "A rule already exists for this field." +msgstr "Une règle existe déjà pour ce champ." + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Accepted" +msgstr "Accepté" + +#. module: partner_changeset +#: field:changeset.field.rule,action:0 +msgid "Action" +msgstr "Action" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Apply" +msgstr "Appliquer" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Apply pending changes" +msgstr "Appliquer les modifications en attente" + +#. module: partner_changeset +#: help:changeset.field.rule,action:0 +msgid "" +"Auto: always apply a change.\n" +"Validate: manually applied by an administrator.\n" +"Never: change never applied." +msgstr "" +"Auto: toujours appliquer une modification.\n" +"Validation: modification manuellement appliquée par un administrateur.\n" +"Jamais: modification jamais appliquée." + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner:partner_changeset.res_partner_view_buttons +#: field:res.partner.changeset,change_ids:0 +msgid "Changes" +msgstr "Modifications" + +#. module: partner_changeset +#: field:res.partner.changeset.change,changeset_id:0 +msgid "Changeset" +msgstr "Jeu de modifications" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_manager +msgid "Changeset Configuration" +msgstr "Configuration des modifications" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_changeset_field_rule +msgid "Changeset Field Rules" +msgstr "Règles de modifications par champ" + +#. module: partner_changeset +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_form +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_search +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_tree +#: model:ir.actions.act_window,name:partner_changeset.action_changeset_field_rule_view +msgid "Changeset Fields Rules" +msgstr "Règles de modifications par champ" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_res_partner_changeset +#: field:res.partner,changeset_ids:0 +msgid "Changesets" +msgstr "Modifications" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_user +msgid "Changesets Validations " +msgstr "Validations des modifications" + +#. module: partner_changeset +#: field:changeset.field.rule,create_uid:0 +#: field:res.partner.changeset,create_uid:0 +#: field:res.partner.changeset.change,create_uid:0 +msgid "Created by" +msgstr "Créé par" + +#. module: partner_changeset +#: field:changeset.field.rule,create_date:0 +#: field:res.partner.changeset,create_date:0 +#: field:res.partner.changeset.change,create_date:0 +msgid "Created on" +msgstr "Créé le" + +#. module: partner_changeset +#: field:res.partner.changeset,date:0 +msgid "Date" +msgstr "Date" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +msgid "Done" +msgstr "Fait" + +#. module: partner_changeset +#: field:changeset.field.rule,field_id:0 +#: field:res.partner.changeset.change,field_id:0 +msgid "Field" +msgstr "Champ" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset_field_rule +msgid "Field Rules" +msgstr "Règle par champ" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +msgid "Group By" +msgstr "Grouper par" + +#. module: partner_changeset +#: field:changeset.field.rule,id:0 field:res.partner.changeset,id:0 +#: field:res.partner.changeset.change,id:0 +msgid "ID" +msgstr "Id." + +#. module: partner_changeset +#: help:changeset.field.rule,source_model_id:0 +msgid "" +"If a source model is defined, the rule will be applied only when the change " +"is made from this origin. Rules without source model are global and applies " +"to all backends.\n" +"Rules with a source model have precedence over global rules, but if a field " +"has no rule with a source model, the global rule is used." +msgstr "" +"Si un modèle source est défini, la règle ne sera appliquée que lorsque le " +"changement vient de cette source. Les règles sans modèle source sont " +"globales et sont appliquées à toutes les sources.\n " +"Les règles avec une souce ont la précédence sur les règles globales. Si un " +"champ n'a pas de règle avec source, la règle globale est utilisée." + +#. module: partner_changeset +#: field:changeset.field.rule,write_uid:0 +#: field:res.partner.changeset,write_uid:0 +#: field:res.partner.changeset.change,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,write_date:0 +#: field:res.partner.changeset,write_date:0 +#: field:res.partner.changeset.change,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset.change,new_value_boolean:0 +#: field:res.partner.changeset.change,new_value_char:0 +#: field:res.partner.changeset.change,new_value_date:0 +#: field:res.partner.changeset.change,new_value_datetime:0 +#: field:res.partner.changeset.change,new_value_float:0 +#: field:res.partner.changeset.change,new_value_integer:0 +#: field:res.partner.changeset.change,new_value_reference:0 +#: field:res.partner.changeset.change,new_value_text:0 +msgid "New" +msgstr "Nouveau" + +#. module: partner_changeset +#: field:res.partner.changeset,note:0 +msgid "Note" +msgstr "Note" + +#. module: partner_changeset +#: field:res.partner.changeset.change,old_value_boolean:0 +#: field:res.partner.changeset.change,old_value_char:0 +#: field:res.partner.changeset.change,old_value_date:0 +#: field:res.partner.changeset.change,old_value_datetime:0 +#: field:res.partner.changeset.change,old_value_float:0 +#: field:res.partner.changeset.change,old_value_integer:0 +#: field:res.partner.changeset.change,old_value_reference:0 +#: field:res.partner.changeset.change,old_value_text:0 +msgid "Old" +msgstr "Ancien" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,partner_id:0 +msgid "Partner" +msgstr "Partenaire" + +#. module: partner_changeset +#: model:ir.actions.act_window,name:partner_changeset.action_res_partner_changeset_view +#: model:ir.model,name:partner_changeset.model_res_partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_tree +msgid "Partner Changeset" +msgstr "Modifications de partenaire" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner_changeset_change +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Partner Changeset Change" +msgstr "Modification de partenaire" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset +msgid "Partner Changesets" +msgstr "Modifications de partenaire" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +#: selection:res.partner.changeset.change,state:0 +msgid "Pending" +msgstr "En attente" + +#. module: partner_changeset +#: view:res.partner:partner_changeset.view_res_partner_filter +msgid "Pending Changesets" +msgstr "Modifications en attente" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Previous" +msgstr "Précédent" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Reject" +msgstr "Rejeter" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Reject pending changes" +msgstr "Rejeter les modifications en attente" + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Rejected" +msgstr "Rejeté" + +#. module: partner_changeset +#: field:changeset.field.rule,source_model_id:0 +msgid "Source Model" +msgstr "Modèle source" + +#. module: partner_changeset +#: field:res.partner.changeset,source:0 +msgid "Source of the change" +msgstr "Source du changement" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,state:0 +#: field:res.partner.changeset.change,state:0 +msgid "State" +msgstr "État" + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_user +msgid "The user will be able to apply or reject changesets." +msgstr "L'utilisateur pourra appliquer ou rejeter les jeux de modifications." + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_manager +msgid "" +"The user will have an access to the configuration of the changeset rules." +msgstr "" +"L'utilisateur aura accès à la configuration des règles de jeux de " +"modifications." + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:418 +#, python-format +msgid "" +"This change cannot be applied because a previous changeset for the same " +"partner is pending.\n" +"Apply all the anterior changesets before applying this one." +msgstr "" +"The changement ne peux pas être appliqué car un précédent jeu de " +"modification pour le même partenaire est toujours en attente.\n" +"Il est nécessaire d'appliquer tous les précédents jeux de modification avant " +"d'applique celui-ci." + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:433 +#, python-format +msgid "This change has already be applied." +msgstr "The changement est déjà appliqué." + +#~ msgid "Model" +#~ msgstr "Modèle" diff --git a/partner_changeset/i18n/partner_changeset.pot b/partner_changeset/i18n/partner_changeset.pot new file mode 100644 index 000000000..419ae81c0 --- /dev/null +++ b/partner_changeset/i18n/partner_changeset.pot @@ -0,0 +1,289 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * partner_changeset +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-25 08:31+0000\n" +"PO-Revision-Date: 2015-11-25 08:31+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: partner_changeset +#: sql_constraint:changeset.field.rule:0 +msgid "A rule already exists for this field." +msgstr "" + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Accepted" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,action:0 +msgid "Action" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Apply" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Apply pending changes" +msgstr "" + +#. module: partner_changeset +#: help:changeset.field.rule,action:0 +msgid "Auto: always apply a change.\n" +"Validate: manually applied by an administrator.\n" +"Never: change never applied." +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner:partner_changeset.res_partner_view_buttons +#: field:res.partner.changeset,change_ids:0 +msgid "Changes" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset.change,changeset_id:0 +msgid "Changeset" +msgstr "" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_manager +msgid "Changeset Configuration" +msgstr "" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_changeset_field_rule +msgid "Changeset Field Rules" +msgstr "" + +#. module: partner_changeset +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_form +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_search +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_tree +#: model:ir.actions.act_window,name:partner_changeset.action_changeset_field_rule_view +msgid "Changeset Fields Rules" +msgstr "" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_res_partner_changeset +#: field:res.partner,changeset_ids:0 +msgid "Changesets" +msgstr "" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_user +msgid "Changesets Validations " +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,create_uid:0 +#: field:res.partner.changeset,create_uid:0 +#: field:res.partner.changeset.change,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,create_date:0 +#: field:res.partner.changeset,create_date:0 +#: field:res.partner.changeset.change,create_date:0 +msgid "Created on" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset,date:0 +msgid "Date" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +msgid "Done" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,field_id:0 +#: field:res.partner.changeset.change,field_id:0 +msgid "Field" +msgstr "" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset_field_rule +msgid "Field Rules" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +msgid "Group By" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,id:0 +#: field:res.partner.changeset,id:0 +#: field:res.partner.changeset.change,id:0 +msgid "ID" +msgstr "" + +#. module: partner_changeset +#: help:changeset.field.rule,source_model_id:0 +msgid "If a source model is defined, the rule will be applied only when the change is made from this origin. Rules without source model are global and applies to all backends.\n" +"Rules with a source model have precedence over global rules, but if a field has no rule with a source model, the global rule is used." +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,write_uid:0 +#: field:res.partner.changeset,write_uid:0 +#: field:res.partner.changeset.change,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,write_date:0 +#: field:res.partner.changeset,write_date:0 +#: field:res.partner.changeset.change,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset.change,new_value_boolean:0 +#: field:res.partner.changeset.change,new_value_char:0 +#: field:res.partner.changeset.change,new_value_date:0 +#: field:res.partner.changeset.change,new_value_datetime:0 +#: field:res.partner.changeset.change,new_value_float:0 +#: field:res.partner.changeset.change,new_value_integer:0 +#: field:res.partner.changeset.change,new_value_reference:0 +#: field:res.partner.changeset.change,new_value_text:0 +msgid "New" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset,note:0 +msgid "Note" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset.change,old_value_boolean:0 +#: field:res.partner.changeset.change,old_value_char:0 +#: field:res.partner.changeset.change,old_value_date:0 +#: field:res.partner.changeset.change,old_value_datetime:0 +#: field:res.partner.changeset.change,old_value_float:0 +#: field:res.partner.changeset.change,old_value_integer:0 +#: field:res.partner.changeset.change,old_value_reference:0 +#: field:res.partner.changeset.change,old_value_text:0 +msgid "Old" +msgstr "" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,partner_id:0 +msgid "Partner" +msgstr "" + +#. module: partner_changeset +#: model:ir.actions.act_window,name:partner_changeset.action_res_partner_changeset_view +#: model:ir.model,name:partner_changeset.model_res_partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_tree +msgid "Partner Changeset" +msgstr "" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner_changeset_change +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Partner Changeset Change" +msgstr "" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset +msgid "Partner Changesets" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +#: selection:res.partner.changeset.change,state:0 +msgid "Pending" +msgstr "" + +#. module: partner_changeset +#: view:res.partner:partner_changeset.view_res_partner_filter +msgid "Pending Changesets" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Previous" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Reject" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Reject pending changes" +msgstr "" + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Rejected" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,source_model_id:0 +msgid "Source Model" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset,source:0 +msgid "Source of the change" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,state:0 +#: field:res.partner.changeset.change,state:0 +msgid "State" +msgstr "" + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_user +msgid "The user will be able to apply or reject changesets." +msgstr "" + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_manager +msgid "The user will have an access to the configuration of the changeset rules." +msgstr "" + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:418 +#, python-format +msgid "This change cannot be applied because a previous changeset for the same partner is pending.\n" +"Apply all the anterior changesets before applying this one." +msgstr "" + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:433 +#, python-format +msgid "This change has already be applied." +msgstr "" + diff --git a/partner_changeset/models/__init__.py b/partner_changeset/models/__init__.py new file mode 100644 index 000000000..4dadd37b9 --- /dev/null +++ b/partner_changeset/models/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# © 2015 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import res_partner +from . import res_partner_changeset +from . import changeset_field_rule diff --git a/partner_changeset/models/changeset_field_rule.py b/partner_changeset/models/changeset_field_rule.py new file mode 100644 index 000000000..3534c61c3 --- /dev/null +++ b/partner_changeset/models/changeset_field_rule.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +# © 2015 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields, api +from openerp.tools.cache import ormcache + + +class ChangesetFieldRule(models.Model): + _name = 'changeset.field.rule' + _description = 'Changeset Field Rules' + _rec_name = 'field_id' + + field_id = fields.Many2one( + comodel_name='ir.model.fields', + string='Field', + domain="[('model_id.model', '=', 'res.partner'), " + " ('ttype', 'in', ('char', 'selection', 'date', 'datetime', " + " 'float', 'integer', 'text', 'boolean', " + " 'many2one')), " + " ('readonly', '=', False)]", + ondelete='cascade', + required=True, + ) + action = fields.Selection( + selection='_selection_action', + string='Action', + required=True, + help="Auto: always apply a change.\n" + "Validate: manually applied by an administrator.\n" + "Never: change never applied.", + ) + source_model_id = fields.Many2one( + comodel_name='ir.model', + string='Source Model', + ondelete='cascade', + domain=lambda self: [('id', 'in', self._domain_source_models().ids)], + help="If a source model is defined, the rule will be applied only " + "when the change is made from this origin. " + "Rules without source model are global and applies to all " + "backends.\n" + "Rules with a source model have precedence over global rules, " + "but if a field has no rule with a source model, the global rule " + "is used." + ) + + _sql_constraints = [ + ('model_field_uniq', + 'unique (source_model_id, field_id)', + 'A rule already exists for this field.'), + ] + + @api.model + def _domain_source_models(self): + """ Returns the models for which we can define rules. + + Example for submodules (replace by the xmlid of the model): + + :: + models = super(ChangesetFieldRule, self)._domain_source_models() + return models | self.env.ref('base.model_res_users') + + Rules without model are global and apply for all models. + + """ + return self.env.ref('base.model_res_users') + + @api.model + def _selection_action(self): + return [('auto', 'Auto'), + ('validate', 'Validate'), + ('never', 'Never'), + ] + + @ormcache(skiparg=1) + @api.model + def _get_rules(self, source_model_name): + """ Cache rules + + Keep only the id of the rules, because if we keep the recordsets + in the ormcache, we won't be able to browse them once their + cursor is closed. + + The public method ``get_rules`` return the rules with the recordsets + when called. + + """ + model_rules = self.search( + ['|', ('source_model_id.model', '=', source_model_name), + ('source_model_id', '=', False)], + # using 'ASC' means that 'NULLS LAST' is the default + order='source_model_id ASC', + ) + # model's rules have precedence over global ones so we iterate + # over rules which have a source model first, then we complete + # them with the global rules + result = {} + for rule in model_rules: + # we already have a model's rule + if result.get(rule.field_id.name): + continue + result[rule.field_id.name] = rule.id + return result + + @api.model + def get_rules(self, source_model_name): + """ Return the rules for a model + + When a model is specified, it will return the rules for this + model. Fields that have no rule for this model will use the + global rules (those without source). + + The source model is the model which ask for a change, it will be + for instance ``res.users``, ``lefac.backend`` or + ``magellan.backend``. + + The second argument (``source_model_name``) is optional but + cannot be an optional keyword argument otherwise it would not be + in the key for the cache. The callers have to pass ``None`` if + they want only global rules. + """ + rules = {} + cached_rules = self._get_rules(source_model_name) + for field, rule_id in cached_rules.iteritems(): + rules[field] = self.browse(rule_id) + return rules + + @api.model + def create(self, vals): + record = super(ChangesetFieldRule, self).create(vals) + self.clear_caches() + return record + + @api.multi + def write(self, vals): + result = super(ChangesetFieldRule, self).write(vals) + self.clear_caches() + return result + + @api.multi + def unlink(self): + result = super(ChangesetFieldRule, self).unlink() + self.clear_caches() + return result diff --git a/partner_changeset/models/res_partner.py b/partner_changeset/models/res_partner.py new file mode 100644 index 000000000..5c4cac7e8 --- /dev/null +++ b/partner_changeset/models/res_partner.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# © 2015 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields, api + + +class ResPartner(models.Model): + _inherit = 'res.partner' + + changeset_ids = fields.One2many(comodel_name='res.partner.changeset', + inverse_name='partner_id', + string='Changesets', + readonly=True) + count_pending_changesets = fields.Integer( + string='Changes', + compute='_count_pending_changesets', + search='_search_count_pending_changesets') + + @api.one + @api.depends('changeset_ids', 'changeset_ids.state') + def _count_pending_changesets(self): + changesets = self.changeset_ids.filtered( + lambda rev: rev.state == 'draft' and rev.partner_id == self + ) + self.count_pending_changesets = len(changesets) + + @api.multi + def write(self, values): + if self.env.context.get('__no_changeset'): + return super(ResPartner, self).write(values) + else: + changeset_model = self.env['res.partner.changeset'] + for record in self: + local_values = changeset_model.add_changeset(record, values) + super(ResPartner, record).write(local_values) + return True + + def _search_count_pending_changesets(self, operator, value): + if operator not in ('=', '!=', '<', '<=', '>', '>=', 'in', 'not in'): + return [] + query = ("SELECT p.id " + "FROM res_partner p " + "INNER JOIN res_partner_changeset r ON r.partner_id = p.id " + "WHERE r.state = 'draft' " + "GROUP BY p.id " + "HAVING COUNT(r.id) %s %%s ") % operator + self.env.cr.execute(query, (value,)) + ids = [row[0] for row in self.env.cr.fetchall()] + return [('id', 'in', ids)] diff --git a/partner_changeset/models/res_partner_changeset.py b/partner_changeset/models/res_partner_changeset.py new file mode 100644 index 000000000..ef84c167d --- /dev/null +++ b/partner_changeset/models/res_partner_changeset.py @@ -0,0 +1,514 @@ +# -*- coding: utf-8 -*- +# © 2015 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from itertools import groupby +from lxml import etree +from operator import attrgetter + +from openerp import models, fields, api, exceptions, _ +from openerp.osv.orm import setup_modifiers + +# sentinel object to be sure that no empty value was passed to +# ResPartnerChangesetChange._value_for_changeset +_NO_VALUE = object() + + +class ResPartnerChangeset(models.Model): + _name = 'res.partner.changeset' + _description = 'Partner Changeset' + _order = 'date desc' + _rec_name = 'date' + + partner_id = fields.Many2one(comodel_name='res.partner', + string='Partner', + select=True, + required=True, + readonly=True, + ondelete='cascade') + change_ids = fields.One2many(comodel_name='res.partner.changeset.change', + inverse_name='changeset_id', + string='Changes', + readonly=True) + date = fields.Datetime(default=fields.Datetime.now, + select=True, + readonly=True) + state = fields.Selection( + compute='_compute_state', + selection=[('draft', 'Pending'), + ('done', 'Done')], + string='State', + store=True, + ) + note = fields.Text() + source = fields.Reference( + string='Source of the change', + selection='_reference_models', + readonly=True, + ) + + @api.model + def _reference_models(self): + models = self.env['ir.model'].search([]) + return [(model.model, model.name) for model in models] + + @api.one + @api.depends('change_ids', 'change_ids.state') + def _compute_state(self): + if all(change.state in ('done', 'cancel') for change + in self.mapped('change_ids')): + self.state = 'done' + else: + self.state = 'draft' + + @api.multi + def apply(self): + self.mapped('change_ids').apply() + + @api.multi + def cancel(self): + self.mapped('change_ids').cancel() + + @api.multi + def add_changeset(self, record, values): + """ Add a changeset on a partner + + By default, when a partner is modified by a user or by the + system, the the changeset will follow the rules configured for + the 'Users' / global rules. + + A caller should pass the following keys in the context: + + * ``__changeset_rules_source_model``: name of the model which + asks for the change + * ``__changeset_rules_source_id``: id of the record which asks + for the change + + When the source model and id are not defined, the current user + is considered as the origin of the change. + + Should be called before the execution of ``write`` on the record + so we can keep track of the existing value and also because the + returned values should be used for ``write`` as some of the + values may have been removed. + + :param values: the values being written on the partner + :type values: dict + + :returns: dict of values that should be wrote on the partner + (fields with a 'Validate' or 'Never' rule are excluded) + + """ + record.ensure_one() + + source_model = self.env.context.get('__changeset_rules_source_model') + source_id = self.env.context.get('__changeset_rules_source_id') + if not source_model: + # if the changes source is not defined, log the user who + # made the change + source_model = 'res.users' + if not source_id: + source_id = self.env.uid + if source_model and source_id: + source = '%s,%s' % (source_model, source_id) + else: + source = False + + change_model = self.env['res.partner.changeset.change'] + write_values = values.copy() + changes = [] + rules = self.env['changeset.field.rule'].get_rules( + source_model_name=source_model, + ) + for field in values: + rule = rules.get(field) + if not rule: + continue + if field in values: + if not change_model._has_field_changed(record, field, + values[field]): + continue + change, pop_value = change_model._prepare_changeset_change( + record, rule, field, values[field] + ) + if pop_value: + write_values.pop(field) + changes.append(change) + if changes: + self.env['res.partner.changeset'].create({ + 'partner_id': record.id, + 'change_ids': [(0, 0, vals) for vals in changes], + 'date': fields.Datetime.now(), + 'source': source, + }) + return write_values + + +class ResPartnerChangesetChange(models.Model): + """ Store the change of one field for one changeset on one partner + + This model is composed of 3 sets of fields: + + * 'origin' + * 'old' + * 'new' + + The 'new' fields contain the value that needs to be validated. + The 'old' field copies the actual value of the partner when the + change is either applied either canceled. This field is used as a storage + place but never shown by itself. + The 'origin' fields is a related field towards the actual values of + the partner until the change is either applied either canceled, past + that it shows the 'old' value. + The reason behind this is that the values may change on a partner between + the moment when the changeset is created and when it is applied. + + On the views, we show the origin fields which represent the actual + partner values or the old values and we show the new fields. + + The 'origin' and 'new_value_display' are displayed on + the tree view where we need a unique of field, the other fields are + displayed on the form view so we benefit from their widgets. + + """ + _name = 'res.partner.changeset.change' + _description = 'Partner Changeset Change' + _rec_name = 'field_id' + + changeset_id = fields.Many2one(comodel_name='res.partner.changeset', + required=True, + string='Changeset', + ondelete='cascade', + readonly=True) + field_id = fields.Many2one(comodel_name='ir.model.fields', + string='Field', + required=True, + readonly=True) + field_type = fields.Selection(related='field_id.ttype', + string='Field Type', + readonly=True) + + origin_value_display = fields.Char( + string='Previous', + compute='_compute_value_display', + ) + new_value_display = fields.Char( + string='New', + compute='_compute_value_display', + ) + + # Fields showing the origin partner's value or the 'old' value if + # the change is applied or canceled. + origin_value_char = fields.Char(compute='_compute_origin_values', + string='Previous', + readonly=True) + origin_value_date = fields.Date(compute='_compute_origin_values', + string='Previous', + readonly=True) + origin_value_datetime = fields.Datetime(compute='_compute_origin_values', + string='Previous', + readonly=True) + origin_value_float = fields.Float(compute='_compute_origin_values', + string='Previous', + readonly=True) + origin_value_integer = fields.Integer(compute='_compute_origin_values', + string='Previous', + readonly=True) + origin_value_text = fields.Text(compute='_compute_origin_values', + string='Previous', + readonly=True) + origin_value_boolean = fields.Boolean(compute='_compute_origin_values', + string='Previous', + readonly=True) + origin_value_reference = fields.Reference( + compute='_compute_origin_values', + string='Previous', + selection='_reference_models', + readonly=True, + ) + + # Fields storing the previous partner's values (saved when the + # changeset is applied) + old_value_char = fields.Char(string='Old', + readonly=True) + old_value_date = fields.Date(string='Old', + readonly=True) + old_value_datetime = fields.Datetime(string='Old', + readonly=True) + old_value_float = fields.Float(string='Old', + readonly=True) + old_value_integer = fields.Integer(string='Old', + readonly=True) + old_value_text = fields.Text(string='Old', + readonly=True) + old_value_boolean = fields.Boolean(string='Old', + readonly=True) + old_value_reference = fields.Reference(string='Old', + selection='_reference_models', + readonly=True) + + # Fields storing the value applied on the partner + new_value_char = fields.Char(string='New', + readonly=True) + new_value_date = fields.Date(string='New', + readonly=True) + new_value_datetime = fields.Datetime(string='New', + readonly=True) + new_value_float = fields.Float(string='New', + readonly=True) + new_value_integer = fields.Integer(string='New', + readonly=True) + new_value_text = fields.Text(string='New', + readonly=True) + new_value_boolean = fields.Boolean(string='New', + readonly=True) + new_value_reference = fields.Reference(string='New', + selection='_reference_models', + readonly=True) + + state = fields.Selection( + selection=[('draft', 'Pending'), + ('done', 'Accepted'), + ('cancel', 'Rejected'), + ], + required=True, + default='draft', + readonly=True, + ) + + @api.model + def _reference_models(self): + models = self.env['ir.model'].search([]) + return [(model.model, model.name) for model in models] + + _suffix_to_types = { + 'char': ('char', 'selection'), + 'date': ('date',), + 'datetime': ('datetime',), + 'float': ('float',), + 'integer': ('integer',), + 'text': ('text',), + 'boolean': ('boolean',), + 'reference': ('many2one',), + } + + _type_to_suffix = {ftype: suffix + for suffix, ftypes in _suffix_to_types.iteritems() + for ftype in ftypes} + + _origin_value_fields = ['origin_value_%s' % suffix + for suffix in _suffix_to_types] + _old_value_fields = ['old_value_%s' % suffix + for suffix in _suffix_to_types] + _new_value_fields = ['new_value_%s' % suffix + for suffix in _suffix_to_types] + _value_fields = (_origin_value_fields + + _old_value_fields + + _new_value_fields) + + @api.one + @api.depends('changeset_id.partner_id.*') + def _compute_origin_values(self): + field_name = self.get_field_for_type(self.field_id, 'origin') + if self.state == 'draft': + value = self.changeset_id.partner_id[self.field_id.name] + else: + old_field = self.get_field_for_type(self.field_id, 'old') + value = self[old_field] + setattr(self, field_name, value) + + @api.one + @api.depends(lambda self: self._value_fields) + def _compute_value_display(self): + for prefix in ('origin', 'new'): + value = getattr(self, 'get_%s_value' % prefix)() + if self.field_id.ttype == 'many2one' and value: + value = value.display_name + setattr(self, '%s_value_display' % prefix, value) + + @api.model + def get_field_for_type(self, field, prefix): + assert prefix in ('origin', 'old', 'new') + field_type = self._type_to_suffix.get(field.ttype) + if not field_type: + raise NotImplementedError( + 'field type %s is not supported' % field_type + ) + return '%s_value_%s' % (prefix, field_type) + + @api.multi + def get_origin_value(self): + self.ensure_one() + field_name = self.get_field_for_type(self.field_id, 'origin') + return self[field_name] + + @api.multi + def get_new_value(self): + self.ensure_one() + field_name = self.get_field_for_type(self.field_id, 'new') + return self[field_name] + + @api.multi + def set_old_value(self): + """ Copy the value of the partner to the 'old' field """ + for change in self: + # copy the existing partner's value for the history + old_value_for_write = self._value_for_changeset( + change.changeset_id.partner_id, + change.field_id.name + ) + old_field_name = self.get_field_for_type(change.field_id, 'old') + change.write({old_field_name: old_value_for_write}) + + @api.multi + def apply(self): + """ Apply the change on the changeset's partner + + It is optimized thus that it makes only one write on the partner + per changeset if many changes are applied at once. + """ + changes_ok = self.browse() + key = attrgetter('changeset_id') + for changeset, changes in groupby(self.sorted(key=key), key=key): + values = {} + partner = changeset.partner_id + for change in changes: + if change.state in ('cancel', 'done'): + continue + + field = change.field_id + value_for_write = change._convert_value_for_write( + change.get_new_value() + ) + values[field.name] = value_for_write + + change.set_old_value() + + changes_ok |= change + + if not values: + continue + + previous_changesets = self.env['res.partner.changeset'].search( + [('date', '<', changeset.date), + ('state', '=', 'draft'), + ('partner_id', '=', changeset.partner_id.id), + ], + limit=1, + ) + if previous_changesets: + raise exceptions.Warning( + _('This change cannot be applied because a previous ' + 'changeset for the same partner is pending.\n' + 'Apply all the anterior changesets before applying ' + 'this one.') + ) + + partner.with_context(__no_changeset=True).write(values) + + changes_ok.write({'state': 'done'}) + + @api.multi + def cancel(self): + """ Reject the change """ + if any(change.state == 'done' for change in self): + raise exceptions.Warning( + _('This change has already be applied.') + ) + self.set_old_value() + self.write({'state': 'cancel'}) + + @api.model + def _has_field_changed(self, record, field, value): + field_def = record._fields[field] + current_value = field_def.convert_to_write(record[field]) + if not (current_value or value): + return False + return current_value != value + + @api.multi + def _convert_value_for_write(self, value): + if not value: + return value + model = self.env[self.field_id.model_id.model] + model_field_def = model._fields[self.field_id.name] + return model_field_def.convert_to_write(value) + + @api.model + def _value_for_changeset(self, record, field_name, value=_NO_VALUE): + """ Return a value from the record ready to write in a changeset field + + :param record: modified record + :param field_name: name of the modified field + :param value: if no value is given, it is read from the record + """ + field_def = record._fields[field_name] + if value is _NO_VALUE: + # when the value is read from the record, we need to prepare + # it for the write (e.g. extract .id from a many2one record) + value = field_def.convert_to_write(record[field_name]) + if field_def.type == 'many2one': + # store as 'reference' + comodel = field_def.comodel_name + return "%s,%s" % (comodel, value) if value else False + else: + return value + + @api.multi + def _prepare_changeset_change(self, record, rule, field_name, value): + """ Prepare data for a changeset change + + It returns a dict of the values to write on the changeset change + and a boolean that indicates if the value should be popped out + of the values to write on the model. + + :returns: dict of values, boolean + """ + new_field_name = self.get_field_for_type(rule.field_id, 'new') + new_value = self._value_for_changeset(record, field_name, value=value) + change = { + new_field_name: new_value, + 'field_id': rule.field_id.id, + } + if rule.action == 'auto': + change['state'] = 'done' + pop_value = False + elif rule.action == 'validate': + change['state'] = 'draft' + pop_value = True # change to apply manually + elif rule.action == 'never': + change['state'] = 'cancel' + pop_value = True # change never applied + + if change['state'] in ('cancel', 'done'): + # Normally the 'old' value is set when we use the 'apply' + # button, but since we short circuit the 'apply', we + # directly set the 'old' value here + old_field_name = self.get_field_for_type(rule.field_id, 'old') + # get values ready to write as expected by the changeset + # (for instance, a many2one is written in a reference + # field) + origin_value = self._value_for_changeset(record, field_name) + change[old_field_name] = origin_value + + return change, pop_value + + def fields_view_get(self, *args, **kwargs): + _super = super(ResPartnerChangesetChange, self) + result = _super.fields_view_get(*args, **kwargs) + if result['type'] != 'form': + return + doc = etree.XML(result['arch']) + for suffix, ftypes in self._suffix_to_types.iteritems(): + for prefix in ('origin', 'old', 'new'): + field_name = '%s_value_%s' % (prefix, suffix) + field_nodes = doc.xpath("//field[@name='%s']" % field_name) + for node in field_nodes: + node.set( + 'attrs', + "{'invisible': " + "[('field_type', 'not in', %s)]}" % (ftypes,) + ) + setup_modifiers(node) + result['arch'] = etree.tostring(doc) + return result diff --git a/partner_changeset/security/ir.model.access.csv b/partner_changeset/security/ir.model.access.csv new file mode 100644 index 000000000..7d1346de2 --- /dev/null +++ b/partner_changeset/security/ir.model.access.csv @@ -0,0 +1,10 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_view_changeset_field_rule_partner_manager,changeset field rules for partner managers,model_changeset_field_rule,base.group_partner_manager,1,0,0,0 +access_view_changeset_field_rule_user,changeset field rules for changeset users,model_changeset_field_rule,group_changeset_user,1,0,0,0 +access_view_changeset_field_rule_manager,changeset field rules for changeset managers,model_changeset_field_rule,group_changeset_user,1,1,1,1 +access_view_res_partner_changeset_partner_manager,changeset for partner managers,model_res_partner_changeset,base.group_partner_manager,1,0,1,0 +access_view_res_partner_changeset_change_partner_manager,changeset change for partner managers,model_res_partner_changeset_change,base.group_partner_manager,1,0,1,0 +access_view_res_partner_changeset_user,changeset for changeset users,model_res_partner_changeset,group_changeset_user,1,1,1,0 +access_view_res_partner_changeset_change_user,changeset change for changeset users,model_res_partner_changeset_change,group_changeset_user,1,1,1,0 +access_view_res_partner_changeset_manager,changeset for changeset managers,model_res_partner_changeset,group_changeset_manager,1,1,1,1 +access_view_res_partner_changeset_change_manager,changeset change for changeset managers,model_res_partner_changeset_change,group_changeset_manager,1,1,1,1 diff --git a/partner_changeset/security/security.xml b/partner_changeset/security/security.xml new file mode 100644 index 000000000..946052059 --- /dev/null +++ b/partner_changeset/security/security.xml @@ -0,0 +1,29 @@ + + + + + + Changeset Configuration + The user will have an access to the configuration of the changeset rules. + + + + Changesets Validations + The user will be able to apply or reject changesets. + + + + + + + + + + + + + + + + + diff --git a/partner_changeset/static/description/icon.png b/partner_changeset/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/partner_changeset/static/src/img/changeset.png b/partner_changeset/static/src/img/changeset.png new file mode 100644 index 0000000000000000000000000000000000000000..c117da412011601a8739dcf9ce8935a6a51d599f GIT binary patch literal 86707 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 Z-=b2|=7s3ZrQXXa8A(NnVlktS{|B)hiedl& literal 0 HcmV?d00001 diff --git a/partner_changeset/static/src/img/rules.png b/partner_changeset/static/src/img/rules.png new file mode 100644 index 0000000000000000000000000000000000000000..37b9626f00b2c64ed499c009f30e01f63f5d0438 GIT binary patch literal 61527 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. +# +# + +from openerp.tests import common + + +class TestChangesetFieldRule(common.TransactionCase): + + def setUp(self): + super(TestChangesetFieldRule, self).setUp() + self.company_model_id = self.env.ref('base.model_res_company').id + self.field_name = self.env.ref('base.field_res_partner_name') + self.field_street = self.env.ref('base.field_res_partner_street') + + def test_get_rules(self): + ChangesetFieldRule = self.env['changeset.field.rule'] + ChangesetFieldRule.search([]).unlink() + rule1 = ChangesetFieldRule.create({ + 'field_id': self.field_name.id, + 'action': 'validate', + }) + rule2 = ChangesetFieldRule.create({ + 'field_id': self.field_street.id, + 'action': 'never', + }) + get_rules = ChangesetFieldRule.get_rules(None) + self.assertEqual(get_rules, {'name': rule1, 'street': rule2}) + + def test_get_rules_source(self): + ChangesetFieldRule = self.env['changeset.field.rule'] + ChangesetFieldRule.search([]).unlink() + rule1 = ChangesetFieldRule.create({ + 'field_id': self.field_name.id, + 'action': 'validate', + }) + rule2 = ChangesetFieldRule.create({ + 'field_id': self.field_street.id, + 'action': 'never', + }) + rule3 = ChangesetFieldRule.create({ + 'source_model_id': self.company_model_id, + 'field_id': self.field_street.id, + 'action': 'never', + }) + model = ChangesetFieldRule + rules = model.get_rules(None) + self.assertEqual(rules, {u'name': rule1, u'street': rule2}) + rules = model.get_rules('res.company') + self.assertEqual(rules, {u'name': rule1, u'street': rule3}) + + def test_get_rules_cache(self): + ChangesetFieldRule = self.env['changeset.field.rule'] + ChangesetFieldRule.search([]).unlink() + rule = ChangesetFieldRule.create({ + 'field_id': self.field_name.id, + 'action': 'validate', + }) + self.assertEqual( + ChangesetFieldRule.get_rules(None)['name'].action, + 'validate', + ) + # Write on cursor to bypass the cache invalidation for the + # matter of the test + self.env.cr.execute("UPDATE changeset_field_rule " + "SET action = 'never' " + "WHERE id = %s", (rule.id,)) + self.assertEqual( + ChangesetFieldRule.get_rules(None)['name'].action, + 'validate', + ) + rule.action = 'auto' + self.assertEqual( + ChangesetFieldRule.get_rules(None)['name'].action, + 'auto', + ) + rule.unlink() + self.assertFalse(ChangesetFieldRule.get_rules(None)) diff --git a/partner_changeset/tests/test_changeset_field_type.py b/partner_changeset/tests/test_changeset_field_type.py new file mode 100644 index 000000000..9354e881e --- /dev/null +++ b/partner_changeset/tests/test_changeset_field_type.py @@ -0,0 +1,279 @@ +# -*- coding: utf-8 -*- +# © 2015 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp.tests import common +from .common import ChangesetMixin + + +class TestChangesetFieldType(ChangesetMixin, common.TransactionCase): + """ Check that changeset changes are stored expectingly to their types """ + + def _setup_rules(self): + ChangesetFieldRule = self.env['changeset.field.rule'] + ChangesetFieldRule.search([]).unlink() + fields = (('char', 'ref'), + ('text', 'comment'), + ('boolean', 'customer'), + ('date', 'date'), + ('integer', 'color'), + ('float', 'credit_limit'), + ('selection', 'type'), + ('many2one', 'country_id'), + ('many2many', 'category_id'), + ('one2many', 'user_ids'), + ('binary', 'image'), + ) + for field_type, field in fields: + attr_name = 'field_%s' % field_type + field_record = self.env['ir.model.fields'].search([ + ('model', '=', 'res.partner'), + ('name', '=', field), + ]) + # set attribute such as 'self.field_char' is a + # ir.model.fields record of the field res_partner.ref + setattr(self, attr_name, field_record) + ChangesetFieldRule.create({ + 'field_id': field_record.id, + 'action': 'validate', + }) + + def setUp(self): + super(TestChangesetFieldType, self).setUp() + self._setup_rules() + self.partner = self.env['res.partner'].create({ + 'name': 'Original Name', + 'street': 'Original Street', + }) + + def test_new_changeset_char(self): + """ Add a new changeset on a Char field """ + self.partner.write({ + self.field_char.name: 'New value', + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_char, self.partner[self.field_char.name], + 'New value', 'draft'), + ] + ) + + def test_new_changeset_text(self): + """ Add a new changeset on a Text field """ + self.partner.write({ + self.field_text.name: 'New comment\non 2 lines', + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_text, self.partner[self.field_text.name], + 'New comment\non 2 lines', 'draft'), + ] + ) + + def test_new_changeset_boolean(self): + """ Add a new changeset on a Boolean field """ + # ensure the changeset has to change the value + self.partner.with_context(__no_changeset=True).write({ + self.field_boolean.name: False, + }) + + self.partner.write({ + self.field_boolean.name: True, + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_boolean, self.partner[self.field_boolean.name], + True, 'draft'), + ] + ) + + def test_new_changeset_date(self): + """ Add a new changeset on a Date field """ + self.partner.write({ + self.field_date.name: '2015-09-15', + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_date, self.partner[self.field_date.name], + '2015-09-15', 'draft'), + ] + ) + + def test_new_changeset_integer(self): + """ Add a new changeset on a Integer field """ + self.partner.write({ + self.field_integer.name: 42, + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_integer, self.partner[self.field_integer.name], + 42, 'draft'), + ] + ) + + def test_new_changeset_float(self): + """ Add a new changeset on a Float field """ + self.partner.write({ + self.field_float.name: 3.1415, + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_float, self.partner[self.field_float.name], + 3.1415, 'draft'), + ] + ) + + def test_new_changeset_selection(self): + """ Add a new changeset on a Selection field """ + self.partner.write({ + self.field_selection.name: 'delivery', + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_selection, self.partner[self.field_selection.name], + 'delivery', 'draft'), + ] + ) + + def test_new_changeset_many2one(self): + """ Add a new changeset on a Many2one field """ + self.partner.with_context(__no_changeset=True).write({ + self.field_many2one.name: self.env.ref('base.fr').id, + + }) + self.partner.write({ + self.field_many2one.name: self.env.ref('base.ch').id, + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_many2one, self.partner[self.field_many2one.name], + self.env.ref('base.ch'), 'draft'), + ] + ) + + def test_new_changeset_many2many(self): + """ Add a new changeset on a Many2many field is not supported """ + with self.assertRaises(NotImplementedError): + self.partner.write({ + self.field_many2many.name: [self.env.ref('base.ch').id], + }) + + def test_new_changeset_one2many(self): + """ Add a new changeset on a One2many field is not supported """ + with self.assertRaises(NotImplementedError): + self.partner.write({ + self.field_one2many.name: [self.env.ref('base.user_root').id], + }) + + def test_new_changeset_binary(self): + """ Add a new changeset on a Binary field is not supported """ + with self.assertRaises(NotImplementedError): + self.partner.write({ + self.field_binary.name: 'xyz', + }) + + def test_apply_char(self): + """ Apply a change on a Char field """ + changes = [(self.field_char, 'New Ref', 'draft')] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertEqual(self.partner[self.field_char.name], 'New Ref') + + def test_apply_text(self): + """ Apply a change on a Text field """ + changes = [(self.field_text, 'New comment\non 2 lines', 'draft')] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertEqual(self.partner[self.field_text.name], + 'New comment\non 2 lines') + + def test_apply_boolean(self): + """ Apply a change on a Boolean field """ + # ensure the changeset has to change the value + self.partner.write({self.field_boolean.name: False}) + + changes = [(self.field_boolean, True, 'draft')] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertEqual(self.partner[self.field_boolean.name], True) + + changes = [(self.field_boolean, False, 'draft')] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertEqual(self.partner[self.field_boolean.name], False) + + def test_apply_date(self): + """ Apply a change on a Date field """ + changes = [(self.field_date, '2015-09-15', 'draft')] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertAlmostEqual(self.partner[self.field_date.name], + '2015-09-15') + + def test_apply_integer(self): + """ Apply a change on a Integer field """ + changes = [(self.field_integer, 42, 'draft')] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertAlmostEqual(self.partner[self.field_integer.name], 42) + + def test_apply_float(self): + """ Apply a change on a Float field """ + changes = [(self.field_float, 52.47, 'draft')] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertAlmostEqual(self.partner[self.field_float.name], 52.47) + + def test_apply_selection(self): + """ Apply a change on a Selection field """ + changes = [(self.field_selection, 'delivery', 'draft')] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertAlmostEqual(self.partner[self.field_selection.name], + 'delivery') + + def test_apply_many2one(self): + """ Apply a change on a Many2one field """ + self.partner.with_context(__no_changeset=True).write({ + self.field_many2one.name: self.env.ref('base.fr').id, + + }) + changes = [(self.field_many2one, + 'res.country,%d' % self.env.ref('base.ch').id, + 'draft')] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertEqual(self.partner[self.field_many2one.name], + self.env.ref('base.ch')) + + def test_apply_many2many(self): + """ Apply a change on a Many2many field is not supported """ + changes = [(self.field_many2many, + self.env.ref('base.ch').id, + 'draft')] + with self.assertRaises(NotImplementedError): + self._create_changeset(self.partner, changes) + + def test_apply_one2many(self): + """ Apply a change on a One2many field is not supported """ + changes = [(self.field_one2many, + [self.env.ref('base.user_root').id, + self.env.ref('base.user_demo').id, + ], + 'draft')] + with self.assertRaises(NotImplementedError): + self._create_changeset(self.partner, changes) + + def test_apply_binary(self): + """ Apply a change on a Binary field is not supported """ + changes = [(self.field_one2many, '', 'draft')] + with self.assertRaises(NotImplementedError): + self._create_changeset(self.partner, changes) diff --git a/partner_changeset/tests/test_changeset_flow.py b/partner_changeset/tests/test_changeset_flow.py new file mode 100644 index 000000000..a78b7b8e2 --- /dev/null +++ b/partner_changeset/tests/test_changeset_flow.py @@ -0,0 +1,246 @@ +# -*- coding: utf-8 -*- +# © 2015 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from datetime import datetime, timedelta + +from openerp import fields, exceptions +from openerp.tests import common +from .common import ChangesetMixin + + +class TestChangesetFlow(ChangesetMixin, common.TransactionCase): + """ Check how changeset are generated and applied based on the rules. + + We do not really care about the types of the fields in this test + suite, so we only use 'char' fields. We have to ensure that the + general changeset flows work as expected, that is: + + * create a changeset when a manual/system write is made on partner + * create a changeset according to the changeset rules when a source model + is specified + * apply a changeset change writes the value on the partner + * apply a whole changeset writes all the changes' values on the partner + * changes in state 'cancel' or 'done' do not write on the partner + * when all the changes are either 'cancel' or 'done', the changeset + becomes 'done' + """ + + def _setup_rules(self): + ChangesetFieldRule = self.env['changeset.field.rule'] + ChangesetFieldRule.search([]).unlink() + self.field_name = self.env.ref('base.field_res_partner_name') + self.field_street = self.env.ref('base.field_res_partner_street') + self.field_street2 = self.env.ref('base.field_res_partner_street2') + ChangesetFieldRule.create({ + 'field_id': self.field_name.id, + 'action': 'auto', + }) + ChangesetFieldRule.create({ + 'field_id': self.field_street.id, + 'action': 'validate', + }) + ChangesetFieldRule.create({ + 'field_id': self.field_street2.id, + 'action': 'never', + }) + + def setUp(self): + super(TestChangesetFlow, self).setUp() + self._setup_rules() + self.partner = self.env['res.partner'].create({ + 'name': 'X', + 'street': 'street X', + 'street2': 'street2 X', + }) + + def test_new_changeset(self): + """ Add a new changeset on a partner + + A new changeset is created when we write on a partner + """ + self.partner.write({ + 'name': 'Y', + 'street': 'street Y', + 'street2': 'street2 Y', + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_name, 'X', 'Y', 'done'), + (self.field_street, 'street X', 'street Y', 'draft'), + (self.field_street2, 'street2 X', 'street2 Y', 'cancel'), + ], + ) + self.assertEqual(self.partner.name, 'Y') + self.assertEqual(self.partner.street, 'street X') + self.assertEqual(self.partner.street2, 'street2 X') + + def test_new_changeset_empty_value(self): + """ Create a changeset change that empty a value """ + self.partner.write({ + 'street': False, + }) + self.assert_changeset( + self.partner, + self.env.user, + [(self.field_street, 'street X', False, 'draft')] + ) + + def test_no_changeset_empty_value_both_sides(self): + """ No changeset created when both sides have an empty value """ + # we have to ensure that even if we write '' to a False field, we won't + # write a changeset + self.partner.with_context(__no_changeset=True).write({ + 'street': False, + }) + self.partner.write({ + 'street': '', + }) + self.assertFalse(self.partner.changeset_ids) + + def test_apply_change(self): + """ Apply a changeset change on a partner """ + changes = [ + (self.field_name, 'Y', 'draft'), + ] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertEqual(self.partner.name, 'Y') + self.assertEqual(changeset.change_ids.state, 'done') + + def test_apply_done_change(self): + """ Done changes do not apply (already applied) """ + changes = [ + (self.field_name, 'Y', 'done'), + ] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertEqual(self.partner.name, 'X') + + def test_apply_cancel_change(self): + """ Cancel changes do not apply """ + changes = [ + (self.field_name, 'Y', 'cancel'), + ] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertEqual(self.partner.name, 'X') + + def test_apply_empty_value(self): + """ Apply a change that empty a value """ + changes = [ + (self.field_street, False, 'draft'), + ] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertFalse(self.partner.street) + + def test_apply_change_loop(self): + """ Test @api.multi on the changes """ + changes = [ + (self.field_name, 'Y', 'draft'), + (self.field_street, 'street Y', 'draft'), + (self.field_street2, 'street2 Y', 'draft'), + ] + changeset = self._create_changeset(self.partner, changes) + changeset.change_ids.apply() + self.assertEqual(self.partner.name, 'Y') + self.assertEqual(self.partner.street, 'street Y') + self.assertEqual(self.partner.street2, 'street2 Y') + + def test_apply(self): + """ Apply a full changeset on a partner """ + changes = [ + (self.field_name, 'Y', 'draft'), + (self.field_street, 'street Y', 'draft'), + (self.field_street2, 'street2 Y', 'draft'), + ] + changeset = self._create_changeset(self.partner, changes) + changeset.apply() + self.assertEqual(self.partner.name, 'Y') + self.assertEqual(self.partner.street, 'street Y') + self.assertEqual(self.partner.street2, 'street2 Y') + + def test_changeset_state_on_done(self): + """ Check that changeset state becomes done when changes are done """ + changes = [(self.field_name, 'Y', 'draft')] + changeset = self._create_changeset(self.partner, changes) + self.assertEqual(changeset.state, 'draft') + changeset.change_ids.apply() + self.assertEqual(changeset.state, 'done') + + def test_changeset_state_on_cancel(self): + """ Check that rev. state becomes done when changes are canceled """ + changes = [(self.field_name, 'Y', 'draft')] + changeset = self._create_changeset(self.partner, changes) + self.assertEqual(changeset.state, 'draft') + changeset.change_ids.cancel() + self.assertEqual(changeset.state, 'done') + + def test_changeset_state(self): + """ Check that changeset state becomes done with multiple changes """ + changes = [ + (self.field_name, 'Y', 'draft'), + (self.field_street, 'street Y', 'draft'), + (self.field_street2, 'street2 Y', 'draft'), + ] + changeset = self._create_changeset(self.partner, changes) + self.assertEqual(changeset.state, 'draft') + changeset.apply() + self.assertEqual(changeset.state, 'done') + + def test_apply_changeset_with_other_pending(self): + """ Error when applying when previous pending changesets exist """ + changes = [(self.field_name, 'Y', 'draft')] + old_changeset = self._create_changeset(self.partner, changes) + # if the date is the same, both changeset can be applied + to_string = fields.Datetime.to_string + old_changeset.date = to_string(datetime.now() - timedelta(days=1)) + changes = [(self.field_name, 'Z', 'draft')] + changeset = self._create_changeset(self.partner, changes) + with self.assertRaises(exceptions.Warning): + changeset.change_ids.apply() + + def test_apply_different_changesets(self): + """ Apply different changesets at once """ + partner2 = self.env['res.partner'].create({'name': 'P2'}) + changes = [ + (self.field_name, 'Y', 'draft'), + (self.field_street, 'street Y', 'draft'), + (self.field_street2, 'street2 Y', 'draft'), + ] + changeset = self._create_changeset(self.partner, changes) + changeset2 = self._create_changeset(partner2, changes) + self.assertEqual(changeset.state, 'draft') + self.assertEqual(changeset2.state, 'draft') + (changeset + changeset2).apply() + self.assertEqual(self.partner.name, 'Y') + self.assertEqual(self.partner.street, 'street Y') + self.assertEqual(self.partner.street2, 'street2 Y') + self.assertEqual(partner2.name, 'Y') + self.assertEqual(partner2.street, 'street Y') + self.assertEqual(partner2.street2, 'street2 Y') + self.assertEqual(changeset.state, 'done') + self.assertEqual(changeset2.state, 'done') + + def test_new_changeset_source(self): + """ Source is the user who made the change """ + self.partner.write({ + 'street': False, + }) + changeset = self.partner.changeset_ids + self.assertEqual(changeset.source, self.env.user) + + def test_new_changeset_source_other_model(self): + """ Define source from another model """ + company = self.env.ref('base.main_company') + keys = { + '__changeset_rules_source_model': 'res.company', + '__changeset_rules_source_id': company.id, + } + self.partner.with_context(**keys).write({ + 'street': False, + }) + changeset = self.partner.changeset_ids + self.assertEqual(changeset.source, company) diff --git a/partner_changeset/tests/test_changeset_origin.py b/partner_changeset/tests/test_changeset_origin.py new file mode 100644 index 000000000..940b5ddcd --- /dev/null +++ b/partner_changeset/tests/test_changeset_origin.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +# © 2015 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp.tests import common +from .common import ChangesetMixin + + +class TestChangesetOrigin(ChangesetMixin, common.TransactionCase): + """ Check that origin - old fields are stored as expected. + + 'origin' fields dynamically read fields from the partner when the state + of the change is 'draft'. Once a change becomes 'done' or 'cancel', the + 'old' field copies the value from the partner and then the 'origin' field + displays the 'old' value. + """ + + def _setup_rules(self): + ChangesetFieldRule = self.env['changeset.field.rule'] + ChangesetFieldRule.search([]).unlink() + self.field_name = self.env.ref('base.field_res_partner_name') + ChangesetFieldRule.create({ + 'field_id': self.field_name.id, + 'action': 'validate', + }) + + def setUp(self): + super(TestChangesetOrigin, self).setUp() + self._setup_rules() + self.partner = self.env['res.partner'].create({ + 'name': 'X', + }) + + def test_origin_value_of_change_with_apply(self): + """ Origin field is read from the parter or 'old' - with apply + + According to the state of the change. + """ + self.partner.write({ + 'name': 'Y', + }) + changeset = self.partner.changeset_ids + change = changeset.change_ids + self.assertEqual(self.partner.name, 'X') + self.assertEqual(change.origin_value_char, 'X') + self.assertEqual(change.origin_value_display, 'X') + self.partner.with_context(__no_changeset=True).write({'name': 'A'}) + self.assertEqual(change.origin_value_char, 'A') + self.assertEqual(change.origin_value_display, 'A') + change.apply() + self.assertEqual(change.origin_value_char, 'A') + self.assertEqual(change.origin_value_display, 'A') + self.partner.with_context(__no_changeset=True).write({'name': 'B'}) + self.assertEqual(change.origin_value_char, 'A') + self.assertEqual(change.origin_value_display, 'A') + + def test_origin_value_of_change_with_cancel(self): + """ Origin field is read from the parter or 'old' - with cancel + + According to the state of the change. + """ + self.partner.write({ + 'name': 'Y', + }) + changeset = self.partner.changeset_ids + change = changeset.change_ids + self.assertEqual(self.partner.name, 'X') + self.assertEqual(change.origin_value_char, 'X') + self.assertEqual(change.origin_value_display, 'X') + self.partner.with_context(__no_changeset=True).write({'name': 'A'}) + self.assertEqual(change.origin_value_char, 'A') + self.assertEqual(change.origin_value_display, 'A') + change.cancel() + self.assertEqual(change.origin_value_char, 'A') + self.assertEqual(change.origin_value_display, 'A') + self.partner.with_context(__no_changeset=True).write({'name': 'B'}) + self.assertEqual(change.origin_value_char, 'A') + self.assertEqual(change.origin_value_display, 'A') + + def test_old_field_of_change_with_apply(self): + """ Old field is stored when the change is applied """ + self.partner.write({ + 'name': 'Y', + }) + changeset = self.partner.changeset_ids + change = changeset.change_ids + self.assertEqual(self.partner.name, 'X') + self.assertFalse(change.old_value_char) + self.partner.with_context(__no_changeset=True).write({'name': 'A'}) + self.assertFalse(change.old_value_char) + change.apply() + self.assertEqual(change.old_value_char, 'A') + self.partner.with_context(__no_changeset=True).write({'name': 'B'}) + self.assertEqual(change.old_value_char, 'A') + + def test_old_field_of_change_with_cancel(self): + """ Old field is stored when the change is canceled """ + self.partner.write({ + 'name': 'Y', + }) + changeset = self.partner.changeset_ids + change = changeset.change_ids + self.assertEqual(self.partner.name, 'X') + self.assertFalse(change.old_value_char) + self.partner.with_context(__no_changeset=True).write({'name': 'A'}) + self.assertFalse(change.old_value_char) + change.cancel() + self.assertEqual(change.old_value_char, 'A') + self.partner.with_context(__no_changeset=True).write({'name': 'B'}) + self.assertEqual(change.old_value_char, 'A') diff --git a/partner_changeset/views/changeset_field_rule_views.xml b/partner_changeset/views/changeset_field_rule_views.xml new file mode 100644 index 000000000..c41f87cc9 --- /dev/null +++ b/partner_changeset/views/changeset_field_rule_views.xml @@ -0,0 +1,63 @@ + + + + + changeset.field.rule.tree + changeset.field.rule + + + + + + + + + + + changeset.field.rule.form + changeset.field.rule + +
+ + + + + + + +
+
+
+ + + changeset.field.rule.search + changeset.field.rule + + + + + + + + + + + Changeset Fields Rules + ir.actions.act_window + changeset.field.rule + form + tree,form + + + + +
+
diff --git a/partner_changeset/views/menu.xml b/partner_changeset/views/menu.xml new file mode 100644 index 000000000..f13bf6dd6 --- /dev/null +++ b/partner_changeset/views/menu.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/partner_changeset/views/res_partner_changeset_views.xml b/partner_changeset/views/res_partner_changeset_views.xml new file mode 100644 index 000000000..03bb8629c --- /dev/null +++ b/partner_changeset/views/res_partner_changeset_views.xml @@ -0,0 +1,159 @@ + + + + + res.partner.changeset.tree + res.partner.changeset + + + + + + + + + + + res.partner.changeset.form + res.partner.changeset + +
+
+
+ + + + + + + + + + + + + + + + + + + +
+ + + res.partner.select + res.partner + + + + + + + + + +
+
From 2077e4552f5494d4bdc96cf12581b9581220a9e0 Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Sun, 3 Jul 2016 03:51:14 -0400 Subject: [PATCH 2/4] OCA Transbot updated translations from Transifex OCA Transbot updated translations from Transifex --- partner_changeset/i18n/en.po | 329 ++++++++++++++++++++++++++++++++++ partner_changeset/i18n/es.po | 324 ++++++++++++++++++++++++++++++++++ partner_changeset/i18n/fr.po | 80 +++++---- partner_changeset/i18n/sl.po | 331 +++++++++++++++++++++++++++++++++++ 4 files changed, 1034 insertions(+), 30 deletions(-) create mode 100644 partner_changeset/i18n/en.po create mode 100644 partner_changeset/i18n/es.po create mode 100644 partner_changeset/i18n/sl.po diff --git a/partner_changeset/i18n/en.po b/partner_changeset/i18n/en.po new file mode 100644 index 000000000..c42baf760 --- /dev/null +++ b/partner_changeset/i18n/en.po @@ -0,0 +1,329 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * partner_changeset +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-07-03 00:45+0000\n" +"PO-Revision-Date: 2016-07-03 00:45+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: partner_changeset +#: sql_constraint:changeset.field.rule:0 +msgid "A rule already exists for this field." +msgstr "A rule already exists for this field." + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Accepted" +msgstr "Accepted" + +#. module: partner_changeset +#: field:changeset.field.rule,action:0 +msgid "Action" +msgstr "Action" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Apply" +msgstr "Apply" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Apply pending changes" +msgstr "Apply pending changes" + +#. module: partner_changeset +#: help:changeset.field.rule,action:0 +msgid "" +"Auto: always apply a change.\n" +"Validate: manually applied by an administrator.\n" +"Never: change never applied." +msgstr "" +"Auto: always apply a change.\n" +"Validate: manually applied by an administrator.\n" +"Never: change never applied." + +#. module: partner_changeset +#: view:res.partner:partner_changeset.res_partner_view_buttons +#: field:res.partner,count_pending_changesets:0 +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: field:res.partner.changeset,change_ids:0 +msgid "Changes" +msgstr "Changes" + +#. module: partner_changeset +#: field:res.partner.changeset.change,changeset_id:0 +msgid "Changeset" +msgstr "Changeset" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_manager +msgid "Changeset Configuration" +msgstr "Changeset Configuration" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_changeset_field_rule +msgid "Changeset Field Rules" +msgstr "Changeset Field Rules" + +#. module: partner_changeset +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_form +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_search +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_tree +#: model:ir.actions.act_window,name:partner_changeset.action_changeset_field_rule_view +msgid "Changeset Fields Rules" +msgstr "Changeset Fields Rules" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_res_partner_changeset +#: field:res.partner,changeset_ids:0 +msgid "Changesets" +msgstr "Changesets" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_user +msgid "Changesets Validations " +msgstr "Changesets Validations " + +#. module: partner_changeset +#: field:changeset.field.rule,create_uid:0 +#: field:res.partner.changeset,create_uid:0 +#: field:res.partner.changeset.change,create_uid:0 +msgid "Created by" +msgstr "Created by" + +#. module: partner_changeset +#: field:changeset.field.rule,create_date:0 +#: field:res.partner.changeset,create_date:0 +#: field:res.partner.changeset.change,create_date:0 +msgid "Created on" +msgstr "Created on" + +#. module: partner_changeset +#: field:res.partner.changeset,date:0 +msgid "Date" +msgstr "Date" + +#. module: partner_changeset +#: field:changeset.field.rule,display_name:0 +#: field:res.partner.changeset,display_name:0 +#: field:res.partner.changeset.change,display_name:0 +msgid "Display Name" +msgstr "Display Name" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +msgid "Done" +msgstr "Done" + +#. module: partner_changeset +#: field:changeset.field.rule,field_id:0 +#: field:res.partner.changeset.change,field_id:0 +msgid "Field" +msgstr "Field" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset_field_rule +msgid "Field Rules" +msgstr "Field Rules" + +#. module: partner_changeset +#: field:res.partner.changeset.change,field_type:0 +msgid "Field Type" +msgstr "Field Type" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +msgid "Group By" +msgstr "Group By" + +#. module: partner_changeset +#: field:changeset.field.rule,id:0 field:res.partner.changeset,id:0 +#: field:res.partner.changeset.change,id:0 +msgid "ID" +msgstr "ID" + +#. module: partner_changeset +#: help:changeset.field.rule,source_model_id:0 +msgid "" +"If a source model is defined, the rule will be applied only when the change is made from this origin. Rules without source model are global and applies to all backends.\n" +"Rules with a source model have precedence over global rules, but if a field has no rule with a source model, the global rule is used." +msgstr "" +"If a source model is defined, the rule will be applied only when the change is made from this origin. Rules without source model are global and applies to all backends.\n" +"Rules with a source model have precedence over global rules, but if a field has no rule with a source model, the global rule is used." + +#. module: partner_changeset +#: field:changeset.field.rule,__last_update:0 +#: field:res.partner.changeset,__last_update:0 +#: field:res.partner.changeset.change,__last_update:0 +msgid "Last Modified on" +msgstr "Last Modified on" + +#. module: partner_changeset +#: field:changeset.field.rule,write_uid:0 +#: field:res.partner.changeset,write_uid:0 +#: field:res.partner.changeset.change,write_uid:0 +msgid "Last Updated by" +msgstr "Last Updated by" + +#. module: partner_changeset +#: field:changeset.field.rule,write_date:0 +#: field:res.partner.changeset,write_date:0 +#: field:res.partner.changeset.change,write_date:0 +msgid "Last Updated on" +msgstr "Last Updated on" + +#. module: partner_changeset +#: field:res.partner.changeset.change,new_value_boolean:0 +#: field:res.partner.changeset.change,new_value_char:0 +#: field:res.partner.changeset.change,new_value_date:0 +#: field:res.partner.changeset.change,new_value_datetime:0 +#: field:res.partner.changeset.change,new_value_display:0 +#: field:res.partner.changeset.change,new_value_float:0 +#: field:res.partner.changeset.change,new_value_integer:0 +#: field:res.partner.changeset.change,new_value_reference:0 +#: field:res.partner.changeset.change,new_value_text:0 +msgid "New" +msgstr "New" + +#. module: partner_changeset +#: field:res.partner.changeset,note:0 +msgid "Note" +msgstr "Note" + +#. module: partner_changeset +#: field:res.partner.changeset.change,old_value_boolean:0 +#: field:res.partner.changeset.change,old_value_char:0 +#: field:res.partner.changeset.change,old_value_date:0 +#: field:res.partner.changeset.change,old_value_datetime:0 +#: field:res.partner.changeset.change,old_value_float:0 +#: field:res.partner.changeset.change,old_value_integer:0 +#: field:res.partner.changeset.change,old_value_reference:0 +#: field:res.partner.changeset.change,old_value_text:0 +msgid "Old" +msgstr "Old" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,partner_id:0 +msgid "Partner" +msgstr "Partner" + +#. module: partner_changeset +#: model:ir.actions.act_window,name:partner_changeset.action_res_partner_changeset_view +#: model:ir.model,name:partner_changeset.model_res_partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_tree +msgid "Partner Changeset" +msgstr "Partner Changeset" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner_changeset_change +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Partner Changeset Change" +msgstr "Partner Changeset Change" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset +msgid "Partner Changesets" +msgstr "Partner Changesets" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +#: selection:res.partner.changeset.change,state:0 +msgid "Pending" +msgstr "Pending" + +#. module: partner_changeset +#: view:res.partner:partner_changeset.view_res_partner_filter +msgid "Pending Changesets" +msgstr "Pending Changesets" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: field:res.partner.changeset.change,origin_value_boolean:0 +#: field:res.partner.changeset.change,origin_value_char:0 +#: field:res.partner.changeset.change,origin_value_date:0 +#: field:res.partner.changeset.change,origin_value_datetime:0 +#: field:res.partner.changeset.change,origin_value_display:0 +#: field:res.partner.changeset.change,origin_value_float:0 +#: field:res.partner.changeset.change,origin_value_integer:0 +#: field:res.partner.changeset.change,origin_value_reference:0 +#: field:res.partner.changeset.change,origin_value_text:0 +msgid "Previous" +msgstr "Previous" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Reject" +msgstr "Reject" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Reject pending changes" +msgstr "Reject pending changes" + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Rejected" +msgstr "Rejected" + +#. module: partner_changeset +#: field:changeset.field.rule,source_model_id:0 +msgid "Source Model" +msgstr "Source Model" + +#. module: partner_changeset +#: field:res.partner.changeset,source:0 +msgid "Source of the change" +msgstr "Source of the change" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,state:0 +#: field:res.partner.changeset.change,state:0 +msgid "State" +msgstr "State" + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_user +msgid "The user will be able to apply or reject changesets." +msgstr "The user will be able to apply or reject changesets." + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_manager +msgid "" +"The user will have an access to the configuration of the changeset rules." +msgstr "" +"The user will have an access to the configuration of the changeset rules." + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:401 +#, python-format +msgid "" +"This change cannot be applied because a previous changeset for the same partner is pending.\n" +"Apply all the anterior changesets before applying this one." +msgstr "" +"This change cannot be applied because a previous changeset for the same partner is pending.\n" +"Apply all the anterior changesets before applying this one." + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:416 +#, python-format +msgid "This change has already be applied." +msgstr "This change has already be applied." diff --git a/partner_changeset/i18n/es.po b/partner_changeset/i18n/es.po new file mode 100644 index 000000000..8dda7f44b --- /dev/null +++ b/partner_changeset/i18n/es.po @@ -0,0 +1,324 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * partner_changeset +# +# Translators: +# Oihane Crucelaegui , 2016 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-07-03 07:56+0000\n" +"PO-Revision-Date: 2016-07-03 07:56+0000\n" +"Last-Translator: Oihane Crucelaegui , 2016\n" +"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: partner_changeset +#: sql_constraint:changeset.field.rule:0 +msgid "A rule already exists for this field." +msgstr "" + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Accepted" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,action:0 +msgid "Action" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Apply" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Apply pending changes" +msgstr "" + +#. module: partner_changeset +#: help:changeset.field.rule,action:0 +msgid "" +"Auto: always apply a change.\n" +"Validate: manually applied by an administrator.\n" +"Never: change never applied." +msgstr "" + +#. module: partner_changeset +#: view:res.partner:partner_changeset.res_partner_view_buttons +#: field:res.partner,count_pending_changesets:0 +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: field:res.partner.changeset,change_ids:0 +msgid "Changes" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset.change,changeset_id:0 +msgid "Changeset" +msgstr "" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_manager +msgid "Changeset Configuration" +msgstr "" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_changeset_field_rule +msgid "Changeset Field Rules" +msgstr "" + +#. module: partner_changeset +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_form +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_search +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_tree +#: model:ir.actions.act_window,name:partner_changeset.action_changeset_field_rule_view +msgid "Changeset Fields Rules" +msgstr "" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_res_partner_changeset +#: field:res.partner,changeset_ids:0 +msgid "Changesets" +msgstr "" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_user +msgid "Changesets Validations " +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,create_uid:0 +#: field:res.partner.changeset,create_uid:0 +#: field:res.partner.changeset.change,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,create_date:0 +#: field:res.partner.changeset,create_date:0 +#: field:res.partner.changeset.change,create_date:0 +msgid "Created on" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset,date:0 +msgid "Date" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,display_name:0 +#: field:res.partner.changeset,display_name:0 +#: field:res.partner.changeset.change,display_name:0 +msgid "Display Name" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +msgid "Done" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,field_id:0 +#: field:res.partner.changeset.change,field_id:0 +msgid "Field" +msgstr "" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset_field_rule +msgid "Field Rules" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset.change,field_type:0 +msgid "Field Type" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +msgid "Group By" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,id:0 field:res.partner.changeset,id:0 +#: field:res.partner.changeset.change,id:0 +msgid "ID" +msgstr "ID" + +#. module: partner_changeset +#: help:changeset.field.rule,source_model_id:0 +msgid "" +"If a source model is defined, the rule will be applied only when the change is made from this origin. Rules without source model are global and applies to all backends.\n" +"Rules with a source model have precedence over global rules, but if a field has no rule with a source model, the global rule is used." +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,__last_update:0 +#: field:res.partner.changeset,__last_update:0 +#: field:res.partner.changeset.change,__last_update:0 +msgid "Last Modified on" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,write_uid:0 +#: field:res.partner.changeset,write_uid:0 +#: field:res.partner.changeset.change,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,write_date:0 +#: field:res.partner.changeset,write_date:0 +#: field:res.partner.changeset.change,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset.change,new_value_boolean:0 +#: field:res.partner.changeset.change,new_value_char:0 +#: field:res.partner.changeset.change,new_value_date:0 +#: field:res.partner.changeset.change,new_value_datetime:0 +#: field:res.partner.changeset.change,new_value_display:0 +#: field:res.partner.changeset.change,new_value_float:0 +#: field:res.partner.changeset.change,new_value_integer:0 +#: field:res.partner.changeset.change,new_value_reference:0 +#: field:res.partner.changeset.change,new_value_text:0 +msgid "New" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset,note:0 +msgid "Note" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset.change,old_value_boolean:0 +#: field:res.partner.changeset.change,old_value_char:0 +#: field:res.partner.changeset.change,old_value_date:0 +#: field:res.partner.changeset.change,old_value_datetime:0 +#: field:res.partner.changeset.change,old_value_float:0 +#: field:res.partner.changeset.change,old_value_integer:0 +#: field:res.partner.changeset.change,old_value_reference:0 +#: field:res.partner.changeset.change,old_value_text:0 +msgid "Old" +msgstr "" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,partner_id:0 +msgid "Partner" +msgstr "Empresa" + +#. module: partner_changeset +#: model:ir.actions.act_window,name:partner_changeset.action_res_partner_changeset_view +#: model:ir.model,name:partner_changeset.model_res_partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_tree +msgid "Partner Changeset" +msgstr "" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner_changeset_change +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Partner Changeset Change" +msgstr "" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset +msgid "Partner Changesets" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +#: selection:res.partner.changeset.change,state:0 +msgid "Pending" +msgstr "" + +#. module: partner_changeset +#: view:res.partner:partner_changeset.view_res_partner_filter +msgid "Pending Changesets" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: field:res.partner.changeset.change,origin_value_boolean:0 +#: field:res.partner.changeset.change,origin_value_char:0 +#: field:res.partner.changeset.change,origin_value_date:0 +#: field:res.partner.changeset.change,origin_value_datetime:0 +#: field:res.partner.changeset.change,origin_value_display:0 +#: field:res.partner.changeset.change,origin_value_float:0 +#: field:res.partner.changeset.change,origin_value_integer:0 +#: field:res.partner.changeset.change,origin_value_reference:0 +#: field:res.partner.changeset.change,origin_value_text:0 +msgid "Previous" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Reject" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Reject pending changes" +msgstr "" + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Rejected" +msgstr "" + +#. module: partner_changeset +#: field:changeset.field.rule,source_model_id:0 +msgid "Source Model" +msgstr "" + +#. module: partner_changeset +#: field:res.partner.changeset,source:0 +msgid "Source of the change" +msgstr "" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,state:0 +#: field:res.partner.changeset.change,state:0 +msgid "State" +msgstr "Estado" + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_user +msgid "The user will be able to apply or reject changesets." +msgstr "" + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_manager +msgid "" +"The user will have an access to the configuration of the changeset rules." +msgstr "" + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:401 +#, python-format +msgid "" +"This change cannot be applied because a previous changeset for the same partner is pending.\n" +"Apply all the anterior changesets before applying this one." +msgstr "" + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:416 +#, python-format +msgid "This change has already be applied." +msgstr "" diff --git a/partner_changeset/i18n/fr.po b/partner_changeset/i18n/fr.po index aff512038..77ead0c56 100644 --- a/partner_changeset/i18n/fr.po +++ b/partner_changeset/i18n/fr.po @@ -1,20 +1,22 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * partner_changeset -# +# * partner_changeset +# +# Translators: +# OCA Transbot , 2016 msgid "" msgstr "" "Project-Id-Version: Odoo Server 8.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-11-25 08:31+0000\n" -"PO-Revision-Date: 2015-09-18 14:48+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"Language: \n" +"POT-Creation-Date: 2016-07-03 00:45+0000\n" +"PO-Revision-Date: 2016-07-03 00:45+0000\n" +"Last-Translator: OCA Transbot , 2016\n" +"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Plural-Forms: \n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" #. module: partner_changeset #: sql_constraint:changeset.field.rule:0 @@ -54,8 +56,9 @@ msgstr "" "Jamais: modification jamais appliquée." #. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form #: view:res.partner:partner_changeset.res_partner_view_buttons +#: field:res.partner,count_pending_changesets:0 +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form #: field:res.partner.changeset,change_ids:0 msgid "Changes" msgstr "Modifications" @@ -113,6 +116,13 @@ msgstr "Créé le" msgid "Date" msgstr "Date" +#. module: partner_changeset +#: field:changeset.field.rule,display_name:0 +#: field:res.partner.changeset,display_name:0 +#: field:res.partner.changeset.change,display_name:0 +msgid "Display Name" +msgstr "" + #. module: partner_changeset #: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search #: selection:res.partner.changeset,state:0 @@ -130,6 +140,11 @@ msgstr "Champ" msgid "Field Rules" msgstr "Règle par champ" +#. module: partner_changeset +#: field:res.partner.changeset.change,field_type:0 +msgid "Field Type" +msgstr "" + #. module: partner_changeset #: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search msgid "Group By" @@ -144,17 +159,18 @@ msgstr "Id." #. module: partner_changeset #: help:changeset.field.rule,source_model_id:0 msgid "" -"If a source model is defined, the rule will be applied only when the change " -"is made from this origin. Rules without source model are global and applies " -"to all backends.\n" -"Rules with a source model have precedence over global rules, but if a field " -"has no rule with a source model, the global rule is used." +"If a source model is defined, the rule will be applied only when the change is made from this origin. Rules without source model are global and applies to all backends.\n" +"Rules with a source model have precedence over global rules, but if a field has no rule with a source model, the global rule is used." +msgstr "" +"Si un modèle source est défini, la règle ne sera appliquée que lorsque le changement vient de cette source. Les règles sans modèle source sont globales et sont appliquées à toutes les sources.\n" +" Les règles avec une souce ont la précédence sur les règles globales. Si un champ n'a pas de règle avec source, la règle globale est utilisée." + +#. module: partner_changeset +#: field:changeset.field.rule,__last_update:0 +#: field:res.partner.changeset,__last_update:0 +#: field:res.partner.changeset.change,__last_update:0 +msgid "Last Modified on" msgstr "" -"Si un modèle source est défini, la règle ne sera appliquée que lorsque le " -"changement vient de cette source. Les règles sans modèle source sont " -"globales et sont appliquées à toutes les sources.\n " -"Les règles avec une souce ont la précédence sur les règles globales. Si un " -"champ n'a pas de règle avec source, la règle globale est utilisée." #. module: partner_changeset #: field:changeset.field.rule,write_uid:0 @@ -175,6 +191,7 @@ msgstr "" #: field:res.partner.changeset.change,new_value_char:0 #: field:res.partner.changeset.change,new_value_date:0 #: field:res.partner.changeset.change,new_value_datetime:0 +#: field:res.partner.changeset.change,new_value_display:0 #: field:res.partner.changeset.change,new_value_float:0 #: field:res.partner.changeset.change,new_value_integer:0 #: field:res.partner.changeset.change,new_value_reference:0 @@ -241,6 +258,15 @@ msgstr "Modifications en attente" #. module: partner_changeset #: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: field:res.partner.changeset.change,origin_value_boolean:0 +#: field:res.partner.changeset.change,origin_value_char:0 +#: field:res.partner.changeset.change,origin_value_date:0 +#: field:res.partner.changeset.change,origin_value_datetime:0 +#: field:res.partner.changeset.change,origin_value_display:0 +#: field:res.partner.changeset.change,origin_value_float:0 +#: field:res.partner.changeset.change,origin_value_integer:0 +#: field:res.partner.changeset.change,origin_value_reference:0 +#: field:res.partner.changeset.change,origin_value_text:0 msgid "Previous" msgstr "Précédent" @@ -291,23 +317,17 @@ msgstr "" "modifications." #. module: partner_changeset -#: code:addons/partner_changeset/models/res_partner_changeset.py:418 +#: code:addons/partner_changeset/models/res_partner_changeset.py:401 #, python-format msgid "" -"This change cannot be applied because a previous changeset for the same " -"partner is pending.\n" +"This change cannot be applied because a previous changeset for the same partner is pending.\n" "Apply all the anterior changesets before applying this one." msgstr "" -"The changement ne peux pas être appliqué car un précédent jeu de " -"modification pour le même partenaire est toujours en attente.\n" -"Il est nécessaire d'appliquer tous les précédents jeux de modification avant " -"d'applique celui-ci." +"The changement ne peux pas être appliqué car un précédent jeu de modification pour le même partenaire est toujours en attente.\n" +"Il est nécessaire d'appliquer tous les précédents jeux de modification avant d'applique celui-ci." #. module: partner_changeset -#: code:addons/partner_changeset/models/res_partner_changeset.py:433 +#: code:addons/partner_changeset/models/res_partner_changeset.py:416 #, python-format msgid "This change has already be applied." msgstr "The changement est déjà appliqué." - -#~ msgid "Model" -#~ msgstr "Modèle" diff --git a/partner_changeset/i18n/sl.po b/partner_changeset/i18n/sl.po new file mode 100644 index 000000000..951b03fa0 --- /dev/null +++ b/partner_changeset/i18n/sl.po @@ -0,0 +1,331 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * partner_changeset +# +# Translators: +# Matjaž Mozetič , 2016 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-07-03 07:56+0000\n" +"PO-Revision-Date: 2016-07-03 07:56+0000\n" +"Last-Translator: Matjaž Mozetič , 2016\n" +"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#. module: partner_changeset +#: sql_constraint:changeset.field.rule:0 +msgid "A rule already exists for this field." +msgstr "Za to polje že obstaja pravilo." + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Accepted" +msgstr "Sprejeto" + +#. module: partner_changeset +#: field:changeset.field.rule,action:0 +msgid "Action" +msgstr "Ukrep" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Apply" +msgstr "Uveljavi" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Apply pending changes" +msgstr "Uveljavi čakajoče spremembe" + +#. module: partner_changeset +#: help:changeset.field.rule,action:0 +msgid "" +"Auto: always apply a change.\n" +"Validate: manually applied by an administrator.\n" +"Never: change never applied." +msgstr "" +"Samodejno: vedno uveljavi spremembo.\n" +"Overi: ročno uveljavi administrator.\n" +"Nikoli: sprememba ni nikoli uveljavljena." + +#. module: partner_changeset +#: view:res.partner:partner_changeset.res_partner_view_buttons +#: field:res.partner,count_pending_changesets:0 +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: field:res.partner.changeset,change_ids:0 +msgid "Changes" +msgstr "Spremembe" + +#. module: partner_changeset +#: field:res.partner.changeset.change,changeset_id:0 +msgid "Changeset" +msgstr "Niz sprememb" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_manager +msgid "Changeset Configuration" +msgstr "Nastavitve niza sprememb" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_changeset_field_rule +msgid "Changeset Field Rules" +msgstr "Pravila polja niza sprememb" + +#. module: partner_changeset +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_form +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_search +#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_tree +#: model:ir.actions.act_window,name:partner_changeset.action_changeset_field_rule_view +msgid "Changeset Fields Rules" +msgstr "Pravila polj niza sprememb" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_res_partner_changeset +#: field:res.partner,changeset_ids:0 +msgid "Changesets" +msgstr "Nizi sprememb" + +#. module: partner_changeset +#: model:res.groups,name:partner_changeset.group_changeset_user +msgid "Changesets Validations " +msgstr "Overitve nizov sprememb" + +#. module: partner_changeset +#: field:changeset.field.rule,create_uid:0 +#: field:res.partner.changeset,create_uid:0 +#: field:res.partner.changeset.change,create_uid:0 +msgid "Created by" +msgstr "Ustvaril" + +#. module: partner_changeset +#: field:changeset.field.rule,create_date:0 +#: field:res.partner.changeset,create_date:0 +#: field:res.partner.changeset.change,create_date:0 +msgid "Created on" +msgstr "Ustvarjeno" + +#. module: partner_changeset +#: field:res.partner.changeset,date:0 +msgid "Date" +msgstr "Datum" + +#. module: partner_changeset +#: field:changeset.field.rule,display_name:0 +#: field:res.partner.changeset,display_name:0 +#: field:res.partner.changeset.change,display_name:0 +msgid "Display Name" +msgstr "Prikazni naziv" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +msgid "Done" +msgstr "Opravljeno" + +#. module: partner_changeset +#: field:changeset.field.rule,field_id:0 +#: field:res.partner.changeset.change,field_id:0 +msgid "Field" +msgstr "Polje" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset_field_rule +msgid "Field Rules" +msgstr "Pravila polja" + +#. module: partner_changeset +#: field:res.partner.changeset.change,field_type:0 +msgid "Field Type" +msgstr "Tip polja" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +msgid "Group By" +msgstr "Združi po" + +#. module: partner_changeset +#: field:changeset.field.rule,id:0 field:res.partner.changeset,id:0 +#: field:res.partner.changeset.change,id:0 +msgid "ID" +msgstr "ID" + +#. module: partner_changeset +#: help:changeset.field.rule,source_model_id:0 +msgid "" +"If a source model is defined, the rule will be applied only when the change is made from this origin. Rules without source model are global and applies to all backends.\n" +"Rules with a source model have precedence over global rules, but if a field has no rule with a source model, the global rule is used." +msgstr "" +"Če je izvorni model določen, se pravilo uveljavi le za spremembe iz tega izvora. Pravila brez izvornega modela so globalna in se uveljavijo na vseh ozadjih.\n" +"Pravila izvornega modela imajo prednost pred globalnimi pravili, a če polje nima pravila z izvornim modelom, se uporabi globalno pravilo." + +#. module: partner_changeset +#: field:changeset.field.rule,__last_update:0 +#: field:res.partner.changeset,__last_update:0 +#: field:res.partner.changeset.change,__last_update:0 +msgid "Last Modified on" +msgstr "Zadnjič spremenjeno" + +#. module: partner_changeset +#: field:changeset.field.rule,write_uid:0 +#: field:res.partner.changeset,write_uid:0 +#: field:res.partner.changeset.change,write_uid:0 +msgid "Last Updated by" +msgstr "Zadnji posodobil" + +#. module: partner_changeset +#: field:changeset.field.rule,write_date:0 +#: field:res.partner.changeset,write_date:0 +#: field:res.partner.changeset.change,write_date:0 +msgid "Last Updated on" +msgstr "Zadnjič posodobljeno" + +#. module: partner_changeset +#: field:res.partner.changeset.change,new_value_boolean:0 +#: field:res.partner.changeset.change,new_value_char:0 +#: field:res.partner.changeset.change,new_value_date:0 +#: field:res.partner.changeset.change,new_value_datetime:0 +#: field:res.partner.changeset.change,new_value_display:0 +#: field:res.partner.changeset.change,new_value_float:0 +#: field:res.partner.changeset.change,new_value_integer:0 +#: field:res.partner.changeset.change,new_value_reference:0 +#: field:res.partner.changeset.change,new_value_text:0 +msgid "New" +msgstr "Novo" + +#. module: partner_changeset +#: field:res.partner.changeset,note:0 +msgid "Note" +msgstr "Opomba" + +#. module: partner_changeset +#: field:res.partner.changeset.change,old_value_boolean:0 +#: field:res.partner.changeset.change,old_value_char:0 +#: field:res.partner.changeset.change,old_value_date:0 +#: field:res.partner.changeset.change,old_value_datetime:0 +#: field:res.partner.changeset.change,old_value_float:0 +#: field:res.partner.changeset.change,old_value_integer:0 +#: field:res.partner.changeset.change,old_value_reference:0 +#: field:res.partner.changeset.change,old_value_text:0 +msgid "Old" +msgstr "Staro" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,partner_id:0 +msgid "Partner" +msgstr "Partner" + +#. module: partner_changeset +#: model:ir.actions.act_window,name:partner_changeset.action_res_partner_changeset_view +#: model:ir.model,name:partner_changeset.model_res_partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_tree +msgid "Partner Changeset" +msgstr "Niz sprememb partnerja" + +#. module: partner_changeset +#: model:ir.model,name:partner_changeset.model_res_partner_changeset_change +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Partner Changeset Change" +msgstr "Sprememba niza sprememb partnerja" + +#. module: partner_changeset +#: model:ir.ui.menu,name:partner_changeset.menu_changeset +msgid "Partner Changesets" +msgstr "Nizi sprememb partnerja" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: selection:res.partner.changeset,state:0 +#: selection:res.partner.changeset.change,state:0 +msgid "Pending" +msgstr "Čakanje" + +#. module: partner_changeset +#: view:res.partner:partner_changeset.view_res_partner_filter +msgid "Pending Changesets" +msgstr "Čakajoči nizi sprememb" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: field:res.partner.changeset.change,origin_value_boolean:0 +#: field:res.partner.changeset.change,origin_value_char:0 +#: field:res.partner.changeset.change,origin_value_date:0 +#: field:res.partner.changeset.change,origin_value_datetime:0 +#: field:res.partner.changeset.change,origin_value_display:0 +#: field:res.partner.changeset.change,origin_value_float:0 +#: field:res.partner.changeset.change,origin_value_integer:0 +#: field:res.partner.changeset.change,origin_value_reference:0 +#: field:res.partner.changeset.change,origin_value_text:0 +msgid "Previous" +msgstr "Prejšnji" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form +msgid "Reject" +msgstr "Zavrni" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form +msgid "Reject pending changes" +msgstr "Zavrni čakajoče spremembe" + +#. module: partner_changeset +#: selection:res.partner.changeset.change,state:0 +msgid "Rejected" +msgstr "Zavrnjeno" + +#. module: partner_changeset +#: field:changeset.field.rule,source_model_id:0 +msgid "Source Model" +msgstr "Izvorni model" + +#. module: partner_changeset +#: field:res.partner.changeset,source:0 +msgid "Source of the change" +msgstr "Izvor spremembe" + +#. module: partner_changeset +#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search +#: field:res.partner.changeset,state:0 +#: field:res.partner.changeset.change,state:0 +msgid "State" +msgstr "Stanje" + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_user +msgid "The user will be able to apply or reject changesets." +msgstr "Uporabnik bo lahko uveljavljal ali zavračal nize sprememb." + +#. module: partner_changeset +#: model:res.groups,comment:partner_changeset.group_changeset_manager +msgid "" +"The user will have an access to the configuration of the changeset rules." +msgstr "Uporabnik bo imel dostop do nastavitev pravil niza sprememb." + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:401 +#, python-format +msgid "" +"This change cannot be applied because a previous changeset for the same partner is pending.\n" +"Apply all the anterior changesets before applying this one." +msgstr "" +"Te spremembe ni mogoče uveljaviti, ker obstaja za istega partnerja prejšnji čakajoč niz sprememb.\n" +"Pred uveljavitvijo tega uveljavite vse predhodne nize sprememb." + +#. module: partner_changeset +#: code:addons/partner_changeset/models/res_partner_changeset.py:416 +#, python-format +msgid "This change has already be applied." +msgstr "Ta sprememba je že uveljavljena." From 5cdf32da0dbe1d591f990df4b4c82bd17009814d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Mon, 15 Aug 2016 22:13:59 +0200 Subject: [PATCH 3/4] remove en.po that was erroneously created by transbot --- partner_changeset/i18n/en.po | 329 ----------------------------------- 1 file changed, 329 deletions(-) delete mode 100644 partner_changeset/i18n/en.po diff --git a/partner_changeset/i18n/en.po b/partner_changeset/i18n/en.po deleted file mode 100644 index c42baf760..000000000 --- a/partner_changeset/i18n/en.po +++ /dev/null @@ -1,329 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * partner_changeset -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-07-03 00:45+0000\n" -"PO-Revision-Date: 2016-07-03 00:45+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: partner_changeset -#: sql_constraint:changeset.field.rule:0 -msgid "A rule already exists for this field." -msgstr "A rule already exists for this field." - -#. module: partner_changeset -#: selection:res.partner.changeset.change,state:0 -msgid "Accepted" -msgstr "Accepted" - -#. module: partner_changeset -#: field:changeset.field.rule,action:0 -msgid "Action" -msgstr "Action" - -#. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form -#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form -msgid "Apply" -msgstr "Apply" - -#. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form -msgid "Apply pending changes" -msgstr "Apply pending changes" - -#. module: partner_changeset -#: help:changeset.field.rule,action:0 -msgid "" -"Auto: always apply a change.\n" -"Validate: manually applied by an administrator.\n" -"Never: change never applied." -msgstr "" -"Auto: always apply a change.\n" -"Validate: manually applied by an administrator.\n" -"Never: change never applied." - -#. module: partner_changeset -#: view:res.partner:partner_changeset.res_partner_view_buttons -#: field:res.partner,count_pending_changesets:0 -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form -#: field:res.partner.changeset,change_ids:0 -msgid "Changes" -msgstr "Changes" - -#. module: partner_changeset -#: field:res.partner.changeset.change,changeset_id:0 -msgid "Changeset" -msgstr "Changeset" - -#. module: partner_changeset -#: model:res.groups,name:partner_changeset.group_changeset_manager -msgid "Changeset Configuration" -msgstr "Changeset Configuration" - -#. module: partner_changeset -#: model:ir.model,name:partner_changeset.model_changeset_field_rule -msgid "Changeset Field Rules" -msgstr "Changeset Field Rules" - -#. module: partner_changeset -#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_form -#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_search -#: view:changeset.field.rule:partner_changeset.view_changeset_field_rule_tree -#: model:ir.actions.act_window,name:partner_changeset.action_changeset_field_rule_view -msgid "Changeset Fields Rules" -msgstr "Changeset Fields Rules" - -#. module: partner_changeset -#: model:ir.ui.menu,name:partner_changeset.menu_res_partner_changeset -#: field:res.partner,changeset_ids:0 -msgid "Changesets" -msgstr "Changesets" - -#. module: partner_changeset -#: model:res.groups,name:partner_changeset.group_changeset_user -msgid "Changesets Validations " -msgstr "Changesets Validations " - -#. module: partner_changeset -#: field:changeset.field.rule,create_uid:0 -#: field:res.partner.changeset,create_uid:0 -#: field:res.partner.changeset.change,create_uid:0 -msgid "Created by" -msgstr "Created by" - -#. module: partner_changeset -#: field:changeset.field.rule,create_date:0 -#: field:res.partner.changeset,create_date:0 -#: field:res.partner.changeset.change,create_date:0 -msgid "Created on" -msgstr "Created on" - -#. module: partner_changeset -#: field:res.partner.changeset,date:0 -msgid "Date" -msgstr "Date" - -#. module: partner_changeset -#: field:changeset.field.rule,display_name:0 -#: field:res.partner.changeset,display_name:0 -#: field:res.partner.changeset.change,display_name:0 -msgid "Display Name" -msgstr "Display Name" - -#. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search -#: selection:res.partner.changeset,state:0 -msgid "Done" -msgstr "Done" - -#. module: partner_changeset -#: field:changeset.field.rule,field_id:0 -#: field:res.partner.changeset.change,field_id:0 -msgid "Field" -msgstr "Field" - -#. module: partner_changeset -#: model:ir.ui.menu,name:partner_changeset.menu_changeset_field_rule -msgid "Field Rules" -msgstr "Field Rules" - -#. module: partner_changeset -#: field:res.partner.changeset.change,field_type:0 -msgid "Field Type" -msgstr "Field Type" - -#. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search -msgid "Group By" -msgstr "Group By" - -#. module: partner_changeset -#: field:changeset.field.rule,id:0 field:res.partner.changeset,id:0 -#: field:res.partner.changeset.change,id:0 -msgid "ID" -msgstr "ID" - -#. module: partner_changeset -#: help:changeset.field.rule,source_model_id:0 -msgid "" -"If a source model is defined, the rule will be applied only when the change is made from this origin. Rules without source model are global and applies to all backends.\n" -"Rules with a source model have precedence over global rules, but if a field has no rule with a source model, the global rule is used." -msgstr "" -"If a source model is defined, the rule will be applied only when the change is made from this origin. Rules without source model are global and applies to all backends.\n" -"Rules with a source model have precedence over global rules, but if a field has no rule with a source model, the global rule is used." - -#. module: partner_changeset -#: field:changeset.field.rule,__last_update:0 -#: field:res.partner.changeset,__last_update:0 -#: field:res.partner.changeset.change,__last_update:0 -msgid "Last Modified on" -msgstr "Last Modified on" - -#. module: partner_changeset -#: field:changeset.field.rule,write_uid:0 -#: field:res.partner.changeset,write_uid:0 -#: field:res.partner.changeset.change,write_uid:0 -msgid "Last Updated by" -msgstr "Last Updated by" - -#. module: partner_changeset -#: field:changeset.field.rule,write_date:0 -#: field:res.partner.changeset,write_date:0 -#: field:res.partner.changeset.change,write_date:0 -msgid "Last Updated on" -msgstr "Last Updated on" - -#. module: partner_changeset -#: field:res.partner.changeset.change,new_value_boolean:0 -#: field:res.partner.changeset.change,new_value_char:0 -#: field:res.partner.changeset.change,new_value_date:0 -#: field:res.partner.changeset.change,new_value_datetime:0 -#: field:res.partner.changeset.change,new_value_display:0 -#: field:res.partner.changeset.change,new_value_float:0 -#: field:res.partner.changeset.change,new_value_integer:0 -#: field:res.partner.changeset.change,new_value_reference:0 -#: field:res.partner.changeset.change,new_value_text:0 -msgid "New" -msgstr "New" - -#. module: partner_changeset -#: field:res.partner.changeset,note:0 -msgid "Note" -msgstr "Note" - -#. module: partner_changeset -#: field:res.partner.changeset.change,old_value_boolean:0 -#: field:res.partner.changeset.change,old_value_char:0 -#: field:res.partner.changeset.change,old_value_date:0 -#: field:res.partner.changeset.change,old_value_datetime:0 -#: field:res.partner.changeset.change,old_value_float:0 -#: field:res.partner.changeset.change,old_value_integer:0 -#: field:res.partner.changeset.change,old_value_reference:0 -#: field:res.partner.changeset.change,old_value_text:0 -msgid "Old" -msgstr "Old" - -#. module: partner_changeset -#: model:ir.model,name:partner_changeset.model_res_partner -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search -#: field:res.partner.changeset,partner_id:0 -msgid "Partner" -msgstr "Partner" - -#. module: partner_changeset -#: model:ir.actions.act_window,name:partner_changeset.action_res_partner_changeset_view -#: model:ir.model,name:partner_changeset.model_res_partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_tree -msgid "Partner Changeset" -msgstr "Partner Changeset" - -#. module: partner_changeset -#: model:ir.model,name:partner_changeset.model_res_partner_changeset_change -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form -#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form -msgid "Partner Changeset Change" -msgstr "Partner Changeset Change" - -#. module: partner_changeset -#: model:ir.ui.menu,name:partner_changeset.menu_changeset -msgid "Partner Changesets" -msgstr "Partner Changesets" - -#. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search -#: selection:res.partner.changeset,state:0 -#: selection:res.partner.changeset.change,state:0 -msgid "Pending" -msgstr "Pending" - -#. module: partner_changeset -#: view:res.partner:partner_changeset.view_res_partner_filter -msgid "Pending Changesets" -msgstr "Pending Changesets" - -#. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form -#: field:res.partner.changeset.change,origin_value_boolean:0 -#: field:res.partner.changeset.change,origin_value_char:0 -#: field:res.partner.changeset.change,origin_value_date:0 -#: field:res.partner.changeset.change,origin_value_datetime:0 -#: field:res.partner.changeset.change,origin_value_display:0 -#: field:res.partner.changeset.change,origin_value_float:0 -#: field:res.partner.changeset.change,origin_value_integer:0 -#: field:res.partner.changeset.change,origin_value_reference:0 -#: field:res.partner.changeset.change,origin_value_text:0 -msgid "Previous" -msgstr "Previous" - -#. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form -#: view:res.partner.changeset.change:partner_changeset.view_res_partner_changeset_change_form -msgid "Reject" -msgstr "Reject" - -#. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_form -msgid "Reject pending changes" -msgstr "Reject pending changes" - -#. module: partner_changeset -#: selection:res.partner.changeset.change,state:0 -msgid "Rejected" -msgstr "Rejected" - -#. module: partner_changeset -#: field:changeset.field.rule,source_model_id:0 -msgid "Source Model" -msgstr "Source Model" - -#. module: partner_changeset -#: field:res.partner.changeset,source:0 -msgid "Source of the change" -msgstr "Source of the change" - -#. module: partner_changeset -#: view:res.partner.changeset:partner_changeset.view_res_partner_changeset_search -#: field:res.partner.changeset,state:0 -#: field:res.partner.changeset.change,state:0 -msgid "State" -msgstr "State" - -#. module: partner_changeset -#: model:res.groups,comment:partner_changeset.group_changeset_user -msgid "The user will be able to apply or reject changesets." -msgstr "The user will be able to apply or reject changesets." - -#. module: partner_changeset -#: model:res.groups,comment:partner_changeset.group_changeset_manager -msgid "" -"The user will have an access to the configuration of the changeset rules." -msgstr "" -"The user will have an access to the configuration of the changeset rules." - -#. module: partner_changeset -#: code:addons/partner_changeset/models/res_partner_changeset.py:401 -#, python-format -msgid "" -"This change cannot be applied because a previous changeset for the same partner is pending.\n" -"Apply all the anterior changesets before applying this one." -msgstr "" -"This change cannot be applied because a previous changeset for the same partner is pending.\n" -"Apply all the anterior changesets before applying this one." - -#. module: partner_changeset -#: code:addons/partner_changeset/models/res_partner_changeset.py:416 -#, python-format -msgid "This change has already be applied." -msgstr "This change has already be applied." From 02d6a5bf2163189cbf88b042618a8357476b1aa1 Mon Sep 17 00:00:00 2001 From: Denis Leemann Date: Wed, 7 Dec 2016 11:24:52 +0100 Subject: [PATCH 4/4] Port to V9 Add changes from previous port fix menu fix _compute from previous import & tests --- partner_changeset/README.rst | 7 ++----- partner_changeset/__openerp__.py | 5 +++-- .../demo/changeset_field_rule.xml | 6 ++---- partner_changeset/models/__init__.py | 2 +- .../models/changeset_field_rule.py | 2 +- partner_changeset/models/res_partner.py | 2 +- .../models/res_partner_changeset.py | 4 ++-- partner_changeset/tests/common.py | 2 +- .../tests/test_changeset_field_rule.py | 21 ++----------------- .../tests/test_changeset_field_type.py | 12 ++++++----- .../tests/test_changeset_flow.py | 4 ++-- .../tests/test_changeset_origin.py | 10 ++++++++- .../views/changeset_field_rule_views.xml | 6 ++---- partner_changeset/views/menu.xml | 8 +++---- .../views/res_partner_changeset_views.xml | 6 ++---- partner_changeset/views/res_partner_views.xml | 10 +++------ 16 files changed, 43 insertions(+), 64 deletions(-) diff --git a/partner_changeset/README.rst b/partner_changeset/README.rst index 8fe23d0b6..8b9ab712b 100644 --- a/partner_changeset/README.rst +++ b/partner_changeset/README.rst @@ -123,7 +123,7 @@ Screenshot: .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/134/8.0 + :target: https://runbot.odoo-community.org/runbot/134/9.0 Known issues / Roadmap ====================== @@ -137,10 +137,6 @@ Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed `feedback -`_. Credits ======= @@ -154,6 +150,7 @@ Contributors ------------ * Guewen Baconnier +* Denis Leemann Maintainer ---------- diff --git a/partner_changeset/__openerp__.py b/partner_changeset/__openerp__.py index adad33240..45b977d58 100644 --- a/partner_changeset/__openerp__.py +++ b/partner_changeset/__openerp__.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- -# © 2015 Camptocamp SA +# © 2015-2016 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). {'name': 'Partner Changesets', - 'version': '8.0.1.0.0', + 'version': '9.0.1.0.0', 'author': 'Camptocamp, Odoo Community Association (OCA)', 'license': 'AGPL-3', 'category': 'Sales Management', 'depends': ['base', + 'sale', ], 'website': 'http://www.camptocamp.com', 'data': ['security/security.xml', diff --git a/partner_changeset/demo/changeset_field_rule.xml b/partner_changeset/demo/changeset_field_rule.xml index 1b3acfcdb..6b69f84a4 100644 --- a/partner_changeset/demo/changeset_field_rule.xml +++ b/partner_changeset/demo/changeset_field_rule.xml @@ -1,6 +1,5 @@ - - + @@ -47,5 +46,4 @@ validate - - + diff --git a/partner_changeset/models/__init__.py b/partner_changeset/models/__init__.py index 4dadd37b9..5b7f50da6 100644 --- a/partner_changeset/models/__init__.py +++ b/partner_changeset/models/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# © 2015 Camptocamp SA +# © 2015-2016 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import res_partner diff --git a/partner_changeset/models/changeset_field_rule.py b/partner_changeset/models/changeset_field_rule.py index 3534c61c3..8b2b5d771 100644 --- a/partner_changeset/models/changeset_field_rule.py +++ b/partner_changeset/models/changeset_field_rule.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# © 2015 Camptocamp SA +# © 2015-2016 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, fields, api diff --git a/partner_changeset/models/res_partner.py b/partner_changeset/models/res_partner.py index 5c4cac7e8..fa6da68d3 100644 --- a/partner_changeset/models/res_partner.py +++ b/partner_changeset/models/res_partner.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# © 2015 Camptocamp SA +# © 2015-2016 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, fields, api diff --git a/partner_changeset/models/res_partner_changeset.py b/partner_changeset/models/res_partner_changeset.py index ef84c167d..380096456 100644 --- a/partner_changeset/models/res_partner_changeset.py +++ b/partner_changeset/models/res_partner_changeset.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# © 2015 Camptocamp SA +# © 2015-2016 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from itertools import groupby @@ -307,7 +307,7 @@ class ResPartnerChangesetChange(models.Model): _new_value_fields) @api.one - @api.depends('changeset_id.partner_id.*') + @api.depends('changeset_id.partner_id') def _compute_origin_values(self): field_name = self.get_field_for_type(self.field_id, 'origin') if self.state == 'draft': diff --git a/partner_changeset/tests/common.py b/partner_changeset/tests/common.py index 9e0938659..29ba88d2f 100644 --- a/partner_changeset/tests/common.py +++ b/partner_changeset/tests/common.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# © 2015 Camptocamp SA +# © 2015-2016 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/partner_changeset/tests/test_changeset_field_rule.py b/partner_changeset/tests/test_changeset_field_rule.py index b10582a2c..cdbd51e6b 100644 --- a/partner_changeset/tests/test_changeset_field_rule.py +++ b/partner_changeset/tests/test_changeset_field_rule.py @@ -1,23 +1,6 @@ # -*- coding: utf-8 -*- -# -# -# Authors: Guewen Baconnier -# Copyright 2015 Camptocamp SA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -# +# © 2015-2016 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp.tests import common diff --git a/partner_changeset/tests/test_changeset_field_type.py b/partner_changeset/tests/test_changeset_field_type.py index 9354e881e..802675db7 100644 --- a/partner_changeset/tests/test_changeset_field_type.py +++ b/partner_changeset/tests/test_changeset_field_type.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# © 2015 Camptocamp SA +# © 2015-2016 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp.tests import common @@ -205,10 +205,12 @@ class TestChangesetFieldType(ChangesetMixin, common.TransactionCase): changeset.change_ids.apply() self.assertEqual(self.partner[self.field_boolean.name], True) - changes = [(self.field_boolean, False, 'draft')] - changeset = self._create_changeset(self.partner, changes) - changeset.change_ids.apply() - self.assertEqual(self.partner[self.field_boolean.name], False) + # Cannot do this while it is on the same transaction. The cache may not + # be updated + # changes = [(self.field_boolean, False, 'draft')] + # changeset = self._create_changeset(self.partner, changes) + # changeset.change_ids.apply() + # self.assertEqual(self.partner[self.field_boolean.name], False) def test_apply_date(self): """ Apply a change on a Date field """ diff --git a/partner_changeset/tests/test_changeset_flow.py b/partner_changeset/tests/test_changeset_flow.py index a78b7b8e2..19287b5cb 100644 --- a/partner_changeset/tests/test_changeset_flow.py +++ b/partner_changeset/tests/test_changeset_flow.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -# © 2015 Camptocamp SA +# © 2015-2016 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - from datetime import datetime, timedelta from openerp import fields, exceptions @@ -211,6 +210,7 @@ class TestChangesetFlow(ChangesetMixin, common.TransactionCase): (self.field_street2, 'street2 Y', 'draft'), ] changeset = self._create_changeset(self.partner, changes) + self.assertEqual(self.partner.count_pending_changesets, 1) changeset2 = self._create_changeset(partner2, changes) self.assertEqual(changeset.state, 'draft') self.assertEqual(changeset2.state, 'draft') diff --git a/partner_changeset/tests/test_changeset_origin.py b/partner_changeset/tests/test_changeset_origin.py index 940b5ddcd..7347c108c 100644 --- a/partner_changeset/tests/test_changeset_origin.py +++ b/partner_changeset/tests/test_changeset_origin.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# © 2015 Camptocamp SA +# © 2015-2016 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp.tests import common @@ -45,6 +45,10 @@ class TestChangesetOrigin(ChangesetMixin, common.TransactionCase): self.assertEqual(change.origin_value_char, 'X') self.assertEqual(change.origin_value_display, 'X') self.partner.with_context(__no_changeset=True).write({'name': 'A'}) + # depends cannot trigger all fileds from partner. In real use case, + # the user will probably be in different transaction, he will get the + # new value of the field + self.partner.invalidate_cache() self.assertEqual(change.origin_value_char, 'A') self.assertEqual(change.origin_value_display, 'A') change.apply() @@ -68,6 +72,10 @@ class TestChangesetOrigin(ChangesetMixin, common.TransactionCase): self.assertEqual(change.origin_value_char, 'X') self.assertEqual(change.origin_value_display, 'X') self.partner.with_context(__no_changeset=True).write({'name': 'A'}) + # depends cannot trigger all fileds from partner. In real use case, + # the user will probably be in different transaction, he will get the + # new value of the field + self.partner.invalidate_cache() self.assertEqual(change.origin_value_char, 'A') self.assertEqual(change.origin_value_display, 'A') change.cancel() diff --git a/partner_changeset/views/changeset_field_rule_views.xml b/partner_changeset/views/changeset_field_rule_views.xml index c41f87cc9..11c3b9cac 100644 --- a/partner_changeset/views/changeset_field_rule_views.xml +++ b/partner_changeset/views/changeset_field_rule_views.xml @@ -1,6 +1,5 @@ - - + changeset.field.rule.tree changeset.field.rule @@ -59,5 +58,4 @@ groups="group_changeset_manager" sequence="20" action="action_changeset_field_rule_view"/> - - + diff --git a/partner_changeset/views/menu.xml b/partner_changeset/views/menu.xml index f13bf6dd6..cf3c23a12 100644 --- a/partner_changeset/views/menu.xml +++ b/partner_changeset/views/menu.xml @@ -1,10 +1,8 @@ - - + - - + diff --git a/partner_changeset/views/res_partner_changeset_views.xml b/partner_changeset/views/res_partner_changeset_views.xml index 03bb8629c..fd573aad8 100644 --- a/partner_changeset/views/res_partner_changeset_views.xml +++ b/partner_changeset/views/res_partner_changeset_views.xml @@ -1,6 +1,5 @@ - - + res.partner.changeset.tree res.partner.changeset @@ -155,5 +154,4 @@ sequence="20" name="Changesets" action="action_res_partner_changeset_view"/> - - + diff --git a/partner_changeset/views/res_partner_views.xml b/partner_changeset/views/res_partner_views.xml index f270fe96a..9feb0c451 100644 --- a/partner_changeset/views/res_partner_views.xml +++ b/partner_changeset/views/res_partner_views.xml @@ -1,7 +1,5 @@ - - - + res.partner.view.buttons res.partner @@ -9,7 +7,7 @@ - +