diff --git a/base_import_match/README.rst b/base_import_match/README.rst index c11ff80b..1b9eb96e 100644 --- a/base_import_match/README.rst +++ b/base_import_match/README.rst @@ -1,11 +1,30 @@ -.. 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 - ================= Base Import Match ================= +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--backend-lightgray.png?logo=github + :target: https://github.com/OCA/server-backend/tree/12.0/base_import_match + :alt: OCA/server-backend +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-backend-12-0/server-backend-12-0-base_import_match + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/253/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + By default, when importing data (like CSV import) with the ``base_import`` module, Odoo follows this rule: @@ -53,6 +72,11 @@ By default 2 rules are installed for production instances: In demo instances there are more examples. +**Table of contents** + +.. contents:: + :local: + Configuration ============= @@ -82,11 +106,7 @@ To use this module, you need to: #. Go to any list view. #. Press *Import* and follow the import procedure as usual. -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/149/10.0 - -Known Issues / Roadmap +Known issues / Roadmap ====================== * Add a setting to throw an error when multiple matches are found, instead of @@ -95,31 +115,43 @@ Known Issues / Roadmap 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. +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 `_. + +Do not contact contributors directly about support or help with technical issues. Credits ======= +Authors +~~~~~~~ + +* Grupo ESOC Ingeniería de Servicios +* Tecnativa + Contributors ------------- +~~~~~~~~~~~~ -* Jairo Llopis -* Vicent Cubells +* `Tecnativa `_: + * Jairo Llopis + * Vicent Cubells + * Ernesto Tejeda -Maintainer ----------- +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. .. 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. +This module is part of the `OCA/server-backend `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_import_match/__init__.py b/base_import_match/__init__.py index 197214cd..4724f5f1 100644 --- a/base_import_match/__init__.py +++ b/base_import_match/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis # Copyright 2016 Tecnativa - Vicent Cubells # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/base_import_match/__manifest__.py b/base_import_match/__manifest__.py index a9068280..2cc6afe6 100644 --- a/base_import_match/__manifest__.py +++ b/base_import_match/__manifest__.py @@ -1,15 +1,13 @@ -# -*- coding: utf-8 -*- # Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis # Copyright 2016 Tecnativa - Vicent Cubells # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Base Import Match", "summary": "Try to avoid duplicates before importing", - "version": "10.0.1.0.0", + "version": "12.0.1.0.0", "category": "Tools", "website": "https://tecnativa.com", - "author": "Grupo ESOC Ingeniería de Servicios," - "Tecnativa, " + "author": "Tecnativa, " "Odoo Community Association (OCA)", "license": "AGPL-3", "application": False, diff --git a/base_import_match/data/base_import_match.xml b/base_import_match/data/base_import_match.xml index b2995871..9cc7f91e 100644 --- a/base_import_match/data/base_import_match.xml +++ b/base_import_match/data/base_import_match.xml @@ -11,11 +11,11 @@ - + - + True True @@ -27,7 +27,7 @@ - + diff --git a/base_import_match/demo/base_import_match.xml b/base_import_match/demo/base_import_match.xml index 4e9af7f4..4125a9d0 100644 --- a/base_import_match/demo/base_import_match.xml +++ b/base_import_match/demo/base_import_match.xml @@ -11,15 +11,15 @@ - + - + - + @@ -29,7 +29,7 @@ - + @@ -39,7 +39,7 @@ - + diff --git a/base_import_match/models/__init__.py b/base_import_match/models/__init__.py index 45ac4f35..09759b3a 100644 --- a/base_import_match/models/__init__.py +++ b/base_import_match/models/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis # Copyright 2016 Tecnativa - Vicent Cubells # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/base_import_match/models/base.py b/base_import_match/models/base.py index 62dff40b..55bb21c0 100644 --- a/base_import_match/models/base.py +++ b/base_import_match/models/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Jairo Llopis # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import api, models @@ -20,7 +19,8 @@ class Base(models.AbstractModel): if self.env["base_import.match"]._usable_rules(self._name, fields): newdata = list() # Data conversion to ORM format - import_fields = map(models.fix_import_export_id_paths, fields) + import_fields = list( + map(models.fix_import_export_id_paths, fields)) converted_data = self._convert_records( self._extract_records(import_fields, data)) # Mock Odoo to believe the user is importing the ID field @@ -44,7 +44,10 @@ class Base(models.AbstractModel): match = self.env["base_import.match"]._match_find( self, record, row) # Give a valid XMLID to this row if a match was found - row["id"] = (match._BaseModel__export_xml_id() + # To generate externals IDS. + match.export_data(fields) + ext_id = match.get_external_id() + row["id"] = (ext_id[match.id] if match else row.get("id", u"")) # Store the modified row, in the same order as fields newdata.append(tuple(row[f] for f in clean_fields)) diff --git a/base_import_match/models/base_import.py b/base_import_match/models/base_import.py index 9350ce5a..e07e6cfc 100644 --- a/base_import_match/models/base_import.py +++ b/base_import_match/models/base_import.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis # Copyright 2016 Tecnativa - Vicent Cubells # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -26,6 +25,7 @@ class BaseImportMatch(models.Model): domain=[("transient", "=", False)], help="In this model you will apply the match.") model_name = fields.Char( + string="Model name", related="model_id.model", store=True, index=True) diff --git a/base_import_match/readme/CONFIGURE.rst b/base_import_match/readme/CONFIGURE.rst new file mode 100644 index 00000000..1fd3de06 --- /dev/null +++ b/base_import_match/readme/CONFIGURE.rst @@ -0,0 +1,16 @@ +To configure this module, you need to: + +#. Go to *Settings > Technical > Database Structure > Import Match*. +#. *Create*. +#. Choose a *Model*. +#. Choose the *Fields* that conform a unique key in that model. +#. If the rule must be used only for certain imported values, check + *Conditional* and enter the **exact string** that is going to be imported + in *Imported value*. + + #. Keep in mind that the match here is evaluated as a case sensitive + **text string** always. If you enter e.g. ``True``, it will match that + string, but will not match ``1`` or ``true``. +#. *Save*. + +In that list view, you can sort rules by drag and drop. diff --git a/base_import_match/readme/CONTRIBUTORS.rst b/base_import_match/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..f487f960 --- /dev/null +++ b/base_import_match/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* `Tecnativa `_: + * Jairo Llopis + * Vicent Cubells + * Ernesto Tejeda diff --git a/base_import_match/readme/DESCRIPTION.rst b/base_import_match/readme/DESCRIPTION.rst new file mode 100644 index 00000000..ffaeade9 --- /dev/null +++ b/base_import_match/readme/DESCRIPTION.rst @@ -0,0 +1,46 @@ +By default, when importing data (like CSV import) with the ``base_import`` +module, Odoo follows this rule: + +- If you import the XMLID of a record, make an **update**. +- If you do not, **create** a new record. + +This module allows you to set additional rules to match if a given import is an +update or a new record. + +This is useful when you need to sync heterogeneous databases, and the field you +use to match records in those databases with Odoo's is not the XMLID but the +name, VAT, email, etc. + +After installing this module, the import logic will be changed to: + +- If you import the XMLID of a record, make an **update**. +- If you do not: + + - If there are import match rules for the model you are importing: + + - Discard the rules that require fields you are not importing. + - Traverse the remaining rules one by one in order to find a match in the database. + + - Skip the rule if it requires a special condition that is not + satisfied. + - If one match is found: + + - Stop traversing the rest of valid rules. + - **Update** that record. + - If zero or multiple matches are found: + + - Continue with the next rule. + - If all rules are exhausted and no single match is found: + + - **Create** a new record. + - If there are no match rules for your model: + + - **Create** a new record. + +By default 2 rules are installed for production instances: + +- One rule that will allow you to update companies based on their VAT, when + ``is_company`` is ``True``. +- One rule that will allow you to update users based on their login. + +In demo instances there are more examples. diff --git a/base_import_match/readme/ROADMAP.rst b/base_import_match/readme/ROADMAP.rst new file mode 100644 index 00000000..38f6cf0e --- /dev/null +++ b/base_import_match/readme/ROADMAP.rst @@ -0,0 +1,2 @@ +* Add a setting to throw an error when multiple matches are found, instead of + falling back to creation of new record. diff --git a/base_import_match/readme/USAGE.rst b/base_import_match/readme/USAGE.rst new file mode 100644 index 00000000..7e0d6cdc --- /dev/null +++ b/base_import_match/readme/USAGE.rst @@ -0,0 +1,5 @@ +To use this module, you need to: + +#. Follow steps in **Configuration** section above. +#. Go to any list view. +#. Press *Import* and follow the import procedure as usual. diff --git a/base_import_match/static/description/index.html b/base_import_match/static/description/index.html new file mode 100644 index 00000000..cb3247b0 --- /dev/null +++ b/base_import_match/static/description/index.html @@ -0,0 +1,512 @@ + + + + + + +Base Import Match + + + +
+

Base Import Match

+ + +

Beta License: AGPL-3 OCA/server-backend Translate me on Weblate Try me on Runbot

+

By default, when importing data (like CSV import) with the base_import +module, Odoo follows this rule:

+
    +
  • If you import the XMLID of a record, make an update.
  • +
  • If you do not, create a new record.
  • +
+

This module allows you to set additional rules to match if a given import is an +update or a new record.

+

This is useful when you need to sync heterogeneous databases, and the field you +use to match records in those databases with Odoo’s is not the XMLID but the +name, VAT, email, etc.

+

After installing this module, the import logic will be changed to:

+
    +
  • If you import the XMLID of a record, make an update.
  • +
  • If you do not:
      +
    • If there are import match rules for the model you are importing:
        +
      • Discard the rules that require fields you are not importing.
      • +
      • Traverse the remaining rules one by one in order to find a match in the database.
          +
        • Skip the rule if it requires a special condition that is not +satisfied.
        • +
        • If one match is found:
            +
          • Stop traversing the rest of valid rules.
          • +
          • Update that record.
          • +
          +
        • +
        • If zero or multiple matches are found:
            +
          • Continue with the next rule.
          • +
          +
        • +
        • If all rules are exhausted and no single match is found:
            +
          • Create a new record.
          • +
          +
        • +
        +
      • +
      +
    • +
    • If there are no match rules for your model:
        +
      • Create a new record.
      • +
      +
    • +
    +
  • +
+

By default 2 rules are installed for production instances:

+
    +
  • One rule that will allow you to update companies based on their VAT, when +is_company is True.
  • +
  • One rule that will allow you to update users based on their login.
  • +
+

In demo instances there are more examples.

+

Table of contents

+ +
+

Configuration

+

To configure this module, you need to:

+
    +
  1. Go to Settings > Technical > Database Structure > Import Match.
  2. +
  3. Create.
  4. +
  5. Choose a Model.
  6. +
  7. Choose the Fields that conform a unique key in that model.
  8. +
  9. If the rule must be used only for certain imported values, check +Conditional and enter the exact string that is going to be imported +in Imported value.
      +
    1. Keep in mind that the match here is evaluated as a case sensitive +text string always. If you enter e.g. True, it will match that +string, but will not match 1 or true.
    2. +
    +
  10. +
  11. Save.
  12. +
+

In that list view, you can sort rules by drag and drop.

+
+
+

Usage

+

To use this module, you need to:

+
    +
  1. Follow steps in Configuration section above.
  2. +
  3. Go to any list view.
  4. +
  5. Press Import and follow the import procedure as usual.
  6. +
+
+
+

Known issues / Roadmap

+
    +
  • Add a setting to throw an error when multiple matches are found, instead of +falling back to creation of new record.
  • +
+
+
+

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.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Grupo ESOC Ingeniería de Servicios
  • +
  • Tecnativa
  • +
+
+
+

Contributors

+
    +
  • Tecnativa: +* Jairo Llopis +* Vicent Cubells +* Ernesto Tejeda
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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.

+

This module is part of the OCA/server-backend project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/base_import_match/tests/__init__.py b/base_import_match/tests/__init__.py index 1d8b5f1b..ff1f96e7 100644 --- a/base_import_match/tests/__init__.py +++ b/base_import_match/tests/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis # Copyright 2016 Tecnativa - Vicent Cubells # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/base_import_match/tests/import_data/res_partner_email.csv b/base_import_match/tests/import_data/res_partner_email.csv index 983b9113..c4564a51 100644 --- a/base_import_match/tests/import_data/res_partner_email.csv +++ b/base_import_match/tests/import_data/res_partner_email.csv @@ -1,2 +1,2 @@ email,name -michel.fletcher@agrolait.example.com,Michel Fletcher Changed +floyd.steward34@example.com,Floyd Steward Changed diff --git a/base_import_match/tests/import_data/res_partner_name.csv b/base_import_match/tests/import_data/res_partner_name.csv index c1a10959..82327b9c 100644 --- a/base_import_match/tests/import_data/res_partner_name.csv +++ b/base_import_match/tests/import_data/res_partner_name.csv @@ -1,2 +1,2 @@ function,name -Function Changed,Michel Fletcher +Function Changed,Floyd Steward diff --git a/base_import_match/tests/import_data/res_partner_parent_name_is_company.csv b/base_import_match/tests/import_data/res_partner_parent_name_is_company.csv index 2d433d94..8487e0b9 100644 --- a/base_import_match/tests/import_data/res_partner_parent_name_is_company.csv +++ b/base_import_match/tests/import_data/res_partner_parent_name_is_company.csv @@ -1,2 +1,2 @@ name,is_company,parent_id/id,email -Michel Fletcher,False,base.res_partner_2,changed@agrolait.example.com +Floyd Steward,False,base.res_partner_2,floyd.steward34.changed@example.com diff --git a/base_import_match/tests/import_data/res_partner_vat.csv b/base_import_match/tests/import_data/res_partner_vat.csv index acc3188c..a4b25ad2 100644 --- a/base_import_match/tests/import_data/res_partner_vat.csv +++ b/base_import_match/tests/import_data/res_partner_vat.csv @@ -1,2 +1,2 @@ name,vat,is_company -Agrolait Changed,BE0477472701,True +Deco Addict Changed,BE0477472701,True diff --git a/base_import_match/tests/test_import.py b/base_import_match/tests/test_import.py index b7d977fa..e266084d 100644 --- a/base_import_match/tests/test_import.py +++ b/base_import_match/tests/test_import.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis # Copyright 2016 Tecnativa - Vicent Cubells # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -28,34 +27,34 @@ class ImportCase(TransactionCase): def test_res_partner_vat(self): """Change name based on VAT.""" - agrolait = self.env.ref("base.res_partner_2") - agrolait.vat = "BE0477472701" + deco_addict = self.env.ref("base.res_partner_2") + deco_addict.vat = "BE0477472701" record = self._base_import_record("res.partner", "res_partner_vat") - record.do(["name", "vat", "is_company"], OPTIONS) - agrolait.env.invalidate_all() - self.assertEqual(agrolait.name, "Agrolait Changed") + record.do(["name", "vat", "is_company"], [], OPTIONS) + deco_addict.env.cache.invalidate() + self.assertEqual(deco_addict.name, "Deco Addict Changed") def test_res_partner_parent_name_is_company(self): """Change email based on parent_id, name and is_company.""" record = self._base_import_record( "res.partner", "res_partner_parent_name_is_company") - record.do(["name", "is_company", "parent_id/id", "email"], OPTIONS) + record.do(["name", "is_company", "parent_id/id", "email"], [], OPTIONS) self.assertEqual( self.env.ref("base.res_partner_address_4").email, - "changed@agrolait.example.com") + "floyd.steward34.changed@example.com") def test_res_partner_email(self): """Change name based on email.""" record = self._base_import_record("res.partner", "res_partner_email") - record.do(["email", "name"], OPTIONS) + record.do(["email", "name"], [], OPTIONS) self.assertEqual( self.env.ref("base.res_partner_address_4").name, - "Michel Fletcher Changed") + "Floyd Steward Changed") def test_res_partner_name(self): """Change function based on name.""" record = self._base_import_record("res.partner", "res_partner_name") - record.do(["function", "name"], OPTIONS) + record.do(["function", "name"], [], OPTIONS) self.assertEqual( self.env.ref("base.res_partner_address_4").function, "Function Changed") @@ -63,7 +62,7 @@ class ImportCase(TransactionCase): def test_res_users_login(self): """Change name based on login.""" record = self._base_import_record("res.users", "res_users_login") - record.do(["login", "name"], OPTIONS) + record.do(["login", "name"], [], OPTIONS) self.assertEqual( self.env.ref("base.user_demo").name, "Demo User Changed") diff --git a/base_import_match/views/base_import_match_view.xml b/base_import_match/views/base_import_match_view.xml index 11c9e824..88cb9b35 100644 --- a/base_import_match/views/base_import_match_view.xml +++ b/base_import_match/views/base_import_match_view.xml @@ -62,7 +62,7 @@ - + diff --git a/base_user_role/__manifest__.py b/base_user_role/__manifest__.py index 2d2173d1..591615e2 100644 --- a/base_user_role/__manifest__.py +++ b/base_user_role/__manifest__.py @@ -8,7 +8,7 @@ 'author': 'ABF OSIELL, Odoo Community Association (OCA)', 'license': 'AGPL-3', 'maintainers': ['ABF OSIELL', 'jcdrubay'], - 'website': 'http://www.osiell.com', + 'website': 'https://github.com/OCA/server-backend', 'depends': [ 'base', ],