From e81252df2084f50082d974767b72ec59e4892e99 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 1 Jun 2023 17:57:40 +0200 Subject: [PATCH 01/23] [ADD] survey_contact_generation: New module TT40985 --- survey_contact_generation/README.rst | 110 +++++ survey_contact_generation/__init__.py | 1 + survey_contact_generation/__manifest__.py | 15 + survey_contact_generation/i18n/es.po | 59 +++ .../i18n/survey_contact_generation.pot | 57 +++ survey_contact_generation/models/__init__.py | 3 + .../models/survey_question.py | 37 ++ .../models/survey_survey.py | 11 + .../models/survey_user_input.py | 42 ++ .../readme/CONFIGURE.rst | 10 + .../readme/CONTRIBUTORS.rst | 4 + .../readme/DESCRIPTION.rst | 1 + survey_contact_generation/readme/USAGE.rst | 3 + .../static/description/icon.png | Bin 0 -> 8322 bytes .../static/description/index.html | 449 ++++++++++++++++++ .../views/survey_question_views.xml | 15 + .../views/survey_survey_views.xml | 14 + 17 files changed, 831 insertions(+) create mode 100644 survey_contact_generation/README.rst create mode 100644 survey_contact_generation/__init__.py create mode 100644 survey_contact_generation/__manifest__.py create mode 100644 survey_contact_generation/i18n/es.po create mode 100644 survey_contact_generation/i18n/survey_contact_generation.pot create mode 100644 survey_contact_generation/models/__init__.py create mode 100644 survey_contact_generation/models/survey_question.py create mode 100644 survey_contact_generation/models/survey_survey.py create mode 100644 survey_contact_generation/models/survey_user_input.py create mode 100644 survey_contact_generation/readme/CONFIGURE.rst create mode 100644 survey_contact_generation/readme/CONTRIBUTORS.rst create mode 100644 survey_contact_generation/readme/DESCRIPTION.rst create mode 100644 survey_contact_generation/readme/USAGE.rst create mode 100644 survey_contact_generation/static/description/icon.png create mode 100644 survey_contact_generation/static/description/index.html create mode 100644 survey_contact_generation/views/survey_question_views.xml create mode 100644 survey_contact_generation/views/survey_survey_views.xml diff --git a/survey_contact_generation/README.rst b/survey_contact_generation/README.rst new file mode 100644 index 00000000..3de33b55 --- /dev/null +++ b/survey_contact_generation/README.rst @@ -0,0 +1,110 @@ +========================== +Survey contacts generation +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:b9b083394402c8f4a1902549fe422a7abd87a9aa0616c9f5c760673cfcb43da7 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fsurvey-lightgray.png?logo=github + :target: https://github.com/OCA/survey/tree/13.0/survey_contact_generation + :alt: OCA/survey +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/survey-13-0/survey-13-0-survey_contact_generation + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/webui/builds.html?repo=OCA/survey&target_branch=13.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to generate new contacts from surveys answers. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure the contact generation: + +#. Go to the configured survey. +#. In the *Contact* section of the *Options* tab, set + *Generate Contact* on, if you want contacts to be + generated from the answers to this survey. +#. In each question associated with a future new contact, + specify the corresponding contact field. To do this, + go to the 'Options' tab, then navigate to the 'Contact' group, + and select the 'Contact field' field. + + + +Usage +===== + +if the survey is properly configured, once it is submited +by an anonomous user, a new contact is create or an +existing one is linked. + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `_ + + * David Vidal + * Ernesto Tejeda + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +.. |maintainer-chienandalu| image:: https://github.com/chienandalu.png?size=40px + :target: https://github.com/chienandalu + :alt: chienandalu + +Current `maintainer `__: + +|maintainer-chienandalu| + +This module is part of the `OCA/survey `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/survey_contact_generation/__init__.py b/survey_contact_generation/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/survey_contact_generation/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/survey_contact_generation/__manifest__.py b/survey_contact_generation/__manifest__.py new file mode 100644 index 00000000..465a9607 --- /dev/null +++ b/survey_contact_generation/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright 2023 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Survey contacts generation", + "summary": "Generate new contacts from surveys", + "version": "13.0.1.0.0", + "development_status": "Beta", + "category": "Marketing/Survey", + "website": "https://github.com/OCA/survey", + "author": "Tecnativa, Odoo Community Association (OCA)", + "maintainers": ["chienandalu"], + "license": "AGPL-3", + "depends": ["survey"], + "data": ["views/survey_question_views.xml", "views/survey_survey_views.xml"], +} diff --git a/survey_contact_generation/i18n/es.po b/survey_contact_generation/i18n/es.po new file mode 100644 index 00000000..3cf14824 --- /dev/null +++ b/survey_contact_generation/i18n/es.po @@ -0,0 +1,59 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * survey_contact_generation +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-06-13 15:49+0000\n" +"PO-Revision-Date: 2023-06-13 17:49+0200\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"X-Generator: Poedit 3.0.1\n" + +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__allowed_field_ids +msgid "Allowed Field" +msgstr "" + +#. module: survey_contact_generation +#: model_terms:ir.ui.view,arch_db:survey_contact_generation.survey_form +#: model_terms:ir.ui.view,arch_db:survey_contact_generation.survey_question_form +msgid "Contact" +msgstr "Contacto" + +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field +msgid "Contact field" +msgstr "Campo de contacto" + +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_survey__generate_contact +msgid "Generate Contact" +msgstr "Generar contacto" + +#. module: survey_contact_generation +#: model:ir.model.fields,help:survey_contact_generation.field_survey_survey__generate_contact +msgid "Generate contacts for anonymous survey users" +msgstr "Generar contacto para encuestas anónimas" + +#. module: survey_contact_generation +#: model:ir.model,name:survey_contact_generation.model_survey_survey +msgid "Survey" +msgstr "Planificación" + +#. module: survey_contact_generation +#: model:ir.model,name:survey_contact_generation.model_survey_question +msgid "Survey Question" +msgstr "Pregunta de la encuesta" + +#. module: survey_contact_generation +#: model:ir.model,name:survey_contact_generation.model_survey_user_input +msgid "Survey User Input" +msgstr "Entrada de usuario de la encuesta" diff --git a/survey_contact_generation/i18n/survey_contact_generation.pot b/survey_contact_generation/i18n/survey_contact_generation.pot new file mode 100644 index 00000000..45379a1f --- /dev/null +++ b/survey_contact_generation/i18n/survey_contact_generation.pot @@ -0,0 +1,57 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * survey_contact_generation +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-06-13 15:49+0000\n" +"PO-Revision-Date: 2023-06-13 15:49+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: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__allowed_field_ids +msgid "Allowed Field" +msgstr "" + +#. module: survey_contact_generation +#: model_terms:ir.ui.view,arch_db:survey_contact_generation.survey_form +#: model_terms:ir.ui.view,arch_db:survey_contact_generation.survey_question_form +msgid "Contact" +msgstr "" + +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field +msgid "Contact field" +msgstr "" + +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_survey__generate_contact +msgid "Generate Contact" +msgstr "" + +#. module: survey_contact_generation +#: model:ir.model.fields,help:survey_contact_generation.field_survey_survey__generate_contact +msgid "Generate contacts for anonymous survey users" +msgstr "" + +#. module: survey_contact_generation +#: model:ir.model,name:survey_contact_generation.model_survey_survey +msgid "Survey" +msgstr "" + +#. module: survey_contact_generation +#: model:ir.model,name:survey_contact_generation.model_survey_question +msgid "Survey Question" +msgstr "" + +#. module: survey_contact_generation +#: model:ir.model,name:survey_contact_generation.model_survey_user_input +msgid "Survey User Input" +msgstr "" diff --git a/survey_contact_generation/models/__init__.py b/survey_contact_generation/models/__init__.py new file mode 100644 index 00000000..93bb3b4a --- /dev/null +++ b/survey_contact_generation/models/__init__.py @@ -0,0 +1,3 @@ +from . import survey_question +from . import survey_survey +from . import survey_user_input diff --git a/survey_contact_generation/models/survey_question.py b/survey_contact_generation/models/survey_question.py new file mode 100644 index 00000000..fad3df40 --- /dev/null +++ b/survey_contact_generation/models/survey_question.py @@ -0,0 +1,37 @@ +# Copyright 2022 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import api, fields, models + + +class SurveyQuestion(models.Model): + _inherit = "survey.question" + + allowed_field_ids = fields.Many2many( + comodel_name="ir.model.fields", compute="_compute_allowed_field_ids", + ) + res_partner_field = fields.Many2one( + string="Contact field", + comodel_name="ir.model.fields", + domain="[('id', 'in', allowed_field_ids)]", + ) + + @api.depends("question_type") + def _compute_allowed_field_ids(self): + type_mapping = { + "textbox": ["char"], + "free_text": ["text"], + "numerical_box": ["integer", "float"], + "date": ["date"], + "datetime": ["datetime"], + } + for record in self: + record.allowed_field_ids = ( + self.env["ir.model.fields"] + .search( + [ + ("model", "=", "res.partner"), + ("ttype", "in", type_mapping.get(record.question_type, [])), + ] + ) + .ids + ) diff --git a/survey_contact_generation/models/survey_survey.py b/survey_contact_generation/models/survey_survey.py new file mode 100644 index 00000000..96321021 --- /dev/null +++ b/survey_contact_generation/models/survey_survey.py @@ -0,0 +1,11 @@ +# Copyright 2023 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class SurveySurvey(models.Model): + _inherit = "survey.survey" + + generate_contact = fields.Boolean( + help="Generate contacts for anonymous survey users", + ) diff --git a/survey_contact_generation/models/survey_user_input.py b/survey_contact_generation/models/survey_user_input.py new file mode 100644 index 00000000..8e33eab5 --- /dev/null +++ b/survey_contact_generation/models/survey_user_input.py @@ -0,0 +1,42 @@ +# Copyright 2022 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import models + + +class SurveyUserInput(models.Model): + _inherit = "survey.user_input" + + def _prepare_partner(self): + self.ensure_one() + return { + line.question_id.res_partner_field.name: line[f"value_{line.answer_type}"] + for line in self.user_input_line_ids.filtered( + lambda r: r.question_id.res_partner_field + ) + } + + def _create_contact_post_process(self): + """After creating the lead send an internal message with the input link""" + self.partner_id.message_post_with_view( + "mail.message_origin_link", + values={"self": self.partner_id, "origin": self.survey_id}, + subtype_id=self.env.ref("mail.mt_note").id, + ) + + def _mark_done(self): + """Generate the contact when the survey is submitted""" + for user_input in self.filtered( + lambda r: r.survey_id.generate_contact and not self.partner_id + ): + vals = user_input._prepare_partner() + partner = False + email = vals.get("email") + if email: + partner = self.env["res.partner"].search( + [("email", "=", email)], limit=1 + ) + if not partner: + partner = self.env["res.partner"].create(vals) + self._create_contact_post_process() + self.write({"partner_id": partner.id, "email": partner.email}) + return super()._mark_done() diff --git a/survey_contact_generation/readme/CONFIGURE.rst b/survey_contact_generation/readme/CONFIGURE.rst new file mode 100644 index 00000000..18966aa7 --- /dev/null +++ b/survey_contact_generation/readme/CONFIGURE.rst @@ -0,0 +1,10 @@ +To configure the contact generation: + +#. Go to the configured survey. +#. In the *Contact* section of the *Options* tab, set + *Generate Contact* on, if you want contacts to be + generated from the answers to this survey. +#. In each question associated with a future new contact, + specify the corresponding contact field. To do this, + go to the 'Options' tab, then navigate to the 'Contact' group, + and select the 'Contact field' field. diff --git a/survey_contact_generation/readme/CONTRIBUTORS.rst b/survey_contact_generation/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..db689930 --- /dev/null +++ b/survey_contact_generation/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* `Tecnativa `_ + + * David Vidal + * Ernesto Tejeda diff --git a/survey_contact_generation/readme/DESCRIPTION.rst b/survey_contact_generation/readme/DESCRIPTION.rst new file mode 100644 index 00000000..ac10b74a --- /dev/null +++ b/survey_contact_generation/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows to generate new contacts from surveys answers. diff --git a/survey_contact_generation/readme/USAGE.rst b/survey_contact_generation/readme/USAGE.rst new file mode 100644 index 00000000..f7c7830c --- /dev/null +++ b/survey_contact_generation/readme/USAGE.rst @@ -0,0 +1,3 @@ +if the survey is properly configured, once it is submited +by an anonomous user, a new contact is create or an +existing one is linked. diff --git a/survey_contact_generation/static/description/icon.png b/survey_contact_generation/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ae0af814c13aaa36da581cafb348ae53540fdb93 GIT binary patch literal 8322 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 M07*qoM6N<$g1NtQl>h($ literal 0 HcmV?d00001 diff --git a/survey_contact_generation/static/description/index.html b/survey_contact_generation/static/description/index.html new file mode 100644 index 00000000..fe775364 --- /dev/null +++ b/survey_contact_generation/static/description/index.html @@ -0,0 +1,449 @@ + + + + + + +Survey contacts generation + + + +
+

Survey contacts generation

+ + +

Beta License: AGPL-3 OCA/survey Translate me on Weblate Try me on Runboat

+

This module allows to generate new contacts from surveys answers.

+

Table of contents

+ +
+

Configuration

+

To configure the contact generation:

+
    +
  1. Go to the configured survey.
  2. +
  3. In the Contact section of the Options tab, set +Generate Contact on, if you want contacts to be +generated from the answers to this survey.
  4. +
  5. In each question associated with a future new contact, +specify the corresponding contact field. To do this, +go to the ‘Options’ tab, then navigate to the ‘Contact’ group, +and select the ‘Contact field’ field.
  6. +
+
+
+

Usage

+

if the survey is properly configured, once it is submited +by an anonomous user, a new contact is create or an +existing one is linked.

+
+
+

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 to smash it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Tecnativa
  • +
+
+
+

Contributors

+
    +
  • Tecnativa
      +
    • David Vidal
    • +
    • 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.

+

Current maintainer:

+

chienandalu

+

This module is part of the OCA/survey project on GitHub.

+

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

+
+
+
+ + diff --git a/survey_contact_generation/views/survey_question_views.xml b/survey_contact_generation/views/survey_question_views.xml new file mode 100644 index 00000000..ae2e34c4 --- /dev/null +++ b/survey_contact_generation/views/survey_question_views.xml @@ -0,0 +1,15 @@ + + + + survey.question + + + + + + + + + + + diff --git a/survey_contact_generation/views/survey_survey_views.xml b/survey_contact_generation/views/survey_survey_views.xml new file mode 100644 index 00000000..66eea35f --- /dev/null +++ b/survey_contact_generation/views/survey_survey_views.xml @@ -0,0 +1,14 @@ + + + + survey.survey + + + + + + + + + + From 4e8281182f1bb982740aeb3294b92588ac819ba0 Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 14 Jun 2023 13:59:44 +0200 Subject: [PATCH 02/23] [IMP] survey_contact_generation: Add test coverage --- survey_contact_generation/README.rst | 18 ++--- survey_contact_generation/__manifest__.py | 7 +- .../demo/survey_contact_generation_demo.xml | 48 +++++++++++++ survey_contact_generation/i18n/es.po | 68 ++++++++++++++++++- .../i18n/survey_contact_generation.pot | 64 ++++++++++++++++- .../readme/CONTRIBUTORS.rst | 1 + .../static/description/index.html | 9 ++- .../tests/survey_contact_generation_tour.js | 52 ++++++++++++++ survey_contact_generation/tests/__init__.py | 1 + .../tests/test_survey_contact_generation.py | 38 +++++++++++ survey_contact_generation/views/assets.xml | 15 ++++ 11 files changed, 299 insertions(+), 22 deletions(-) create mode 100644 survey_contact_generation/demo/survey_contact_generation_demo.xml create mode 100644 survey_contact_generation/static/tests/survey_contact_generation_tour.js create mode 100644 survey_contact_generation/tests/__init__.py create mode 100644 survey_contact_generation/tests/test_survey_contact_generation.py create mode 100644 survey_contact_generation/views/assets.xml diff --git a/survey_contact_generation/README.rst b/survey_contact_generation/README.rst index 3de33b55..2ecd7954 100644 --- a/survey_contact_generation/README.rst +++ b/survey_contact_generation/README.rst @@ -2,13 +2,10 @@ Survey contacts generation ========================== -.. - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:b9b083394402c8f4a1902549fe422a7abd87a9aa0616c9f5c760673cfcb43da7 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status @@ -22,11 +19,11 @@ Survey contacts generation .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png :target: https://translation.odoo-community.org/projects/survey-13-0/survey-13-0-survey_contact_generation :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/webui/builds.html?repo=OCA/survey&target_branch=13.0 - :alt: Try me on Runboat +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/200/13.0 + :alt: Try me on Runbot -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| This module allows to generate new contacts from surveys answers. @@ -49,8 +46,6 @@ To configure the contact generation: go to the 'Options' tab, then navigate to the 'Contact' group, and select the 'Contact field' field. - - Usage ===== @@ -63,7 +58,7 @@ 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 to smash it by providing a detailed and welcomed +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. @@ -83,6 +78,7 @@ Contributors * David Vidal * Ernesto Tejeda + * Stefan Ungureanu Maintainers ~~~~~~~~~~~ diff --git a/survey_contact_generation/__manifest__.py b/survey_contact_generation/__manifest__.py index 465a9607..d999cd22 100644 --- a/survey_contact_generation/__manifest__.py +++ b/survey_contact_generation/__manifest__.py @@ -11,5 +11,10 @@ "maintainers": ["chienandalu"], "license": "AGPL-3", "depends": ["survey"], - "data": ["views/survey_question_views.xml", "views/survey_survey_views.xml"], + "data": [ + "views/survey_question_views.xml", + "views/survey_survey_views.xml", + "views/assets.xml", + ], + "demo": ["demo/survey_contact_generation_demo.xml"], } diff --git a/survey_contact_generation/demo/survey_contact_generation_demo.xml b/survey_contact_generation/demo/survey_contact_generation_demo.xml new file mode 100644 index 00000000..800c8f9c --- /dev/null +++ b/survey_contact_generation/demo/survey_contact_generation_demo.xml @@ -0,0 +1,48 @@ + + + + + Contact Creation Survey + 80e5f1e2-1a9d-4c51-8e23-09e93f7fa2c5 + open + public + + + + + + 0 + Name + textbox + + + + + + 1 + Email + textbox + + + + + 2 + Notes + free_text + + + + + 3 + Color + numerical_box + + + + + 4 + Date + date + + + diff --git a/survey_contact_generation/i18n/es.po b/survey_contact_generation/i18n/es.po index 3cf14824..fde335e6 100644 --- a/survey_contact_generation/i18n/es.po +++ b/survey_contact_generation/i18n/es.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-13 15:49+0000\n" -"PO-Revision-Date: 2023-06-13 17:49+0200\n" +"POT-Creation-Date: 2023-06-14 11:55+0000\n" +"PO-Revision-Date: 2023-06-14 13:58+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: es\n" @@ -20,7 +20,13 @@ msgstr "" #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__allowed_field_ids msgid "Allowed Field" -msgstr "" +msgstr "Campo permitido" + +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q3 +#: model:survey.question,title:survey_contact_generation.survey_contact_q3 +msgid "Color" +msgstr "Color" #. module: survey_contact_generation #: model_terms:ir.ui.view,arch_db:survey_contact_generation.survey_form @@ -28,11 +34,28 @@ msgstr "" msgid "Contact" msgstr "Contacto" +#. module: survey_contact_generation +#: model:survey.survey,title:survey_contact_generation.survey_contact_creation +msgid "Contact Creation Survey" +msgstr "Encuesta de creación de contactos" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field msgid "Contact field" msgstr "Campo de contacto" +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q4 +#: model:survey.question,title:survey_contact_generation.survey_contact_q4 +msgid "Date" +msgstr "Fecha" + +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q1 +#: model:survey.question,title:survey_contact_generation.survey_contact_q1 +msgid "Email" +msgstr "Correo electrónico" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_survey__generate_contact msgid "Generate Contact" @@ -43,6 +66,27 @@ msgstr "Generar contacto" msgid "Generate contacts for anonymous survey users" msgstr "Generar contacto para encuestas anónimas" +#. module: survey_contact_generation +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q0 +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q1 +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q2 +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q3 +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q4 +msgid "If other, please specify:" +msgstr "Si es otro, especifíquelo:" + +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q0 +#: model:survey.question,title:survey_contact_generation.survey_contact_q0 +msgid "Name" +msgstr "Nombre" + +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q2 +#: model:survey.question,title:survey_contact_generation.survey_contact_q2 +msgid "Notes" +msgstr "Notas" + #. module: survey_contact_generation #: model:ir.model,name:survey_contact_generation.model_survey_survey msgid "Survey" @@ -57,3 +101,21 @@ msgstr "Pregunta de la encuesta" #: model:ir.model,name:survey_contact_generation.model_survey_user_input msgid "Survey User Input" msgstr "Entrada de usuario de la encuesta" + +#. module: survey_contact_generation +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q0 +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q1 +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q2 +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q3 +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q4 +msgid "The answer you entered is not valid." +msgstr "La respuesta que has introducido no es válida." + +#. module: survey_contact_generation +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q0 +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q1 +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q2 +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q3 +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q4 +msgid "This question requires an answer." +msgstr "Esta pregunta requiere una respuesta." diff --git a/survey_contact_generation/i18n/survey_contact_generation.pot b/survey_contact_generation/i18n/survey_contact_generation.pot index 45379a1f..890cd2c3 100644 --- a/survey_contact_generation/i18n/survey_contact_generation.pot +++ b/survey_contact_generation/i18n/survey_contact_generation.pot @@ -6,8 +6,6 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-13 15:49+0000\n" -"PO-Revision-Date: 2023-06-13 15:49+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -20,17 +18,40 @@ msgstr "" msgid "Allowed Field" msgstr "" +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q3 +#: model:survey.question,title:survey_contact_generation.survey_contact_q3 +msgid "Color" +msgstr "" + #. module: survey_contact_generation #: model_terms:ir.ui.view,arch_db:survey_contact_generation.survey_form #: model_terms:ir.ui.view,arch_db:survey_contact_generation.survey_question_form msgid "Contact" msgstr "" +#. module: survey_contact_generation +#: model:survey.survey,title:survey_contact_generation.survey_contact_creation +msgid "Contact Creation Survey" +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field msgid "Contact field" msgstr "" +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q4 +#: model:survey.question,title:survey_contact_generation.survey_contact_q4 +msgid "Date" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q1 +#: model:survey.question,title:survey_contact_generation.survey_contact_q1 +msgid "Email" +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_survey__generate_contact msgid "Generate Contact" @@ -41,6 +62,27 @@ msgstr "" msgid "Generate contacts for anonymous survey users" msgstr "" +#. module: survey_contact_generation +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q0 +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q1 +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q2 +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q3 +#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q4 +msgid "If other, please specify:" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q0 +#: model:survey.question,title:survey_contact_generation.survey_contact_q0 +msgid "Name" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,question:survey_contact_generation.survey_contact_q2 +#: model:survey.question,title:survey_contact_generation.survey_contact_q2 +msgid "Notes" +msgstr "" + #. module: survey_contact_generation #: model:ir.model,name:survey_contact_generation.model_survey_survey msgid "Survey" @@ -55,3 +97,21 @@ msgstr "" #: model:ir.model,name:survey_contact_generation.model_survey_user_input msgid "Survey User Input" msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q0 +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q1 +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q2 +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q3 +#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q4 +msgid "The answer you entered is not valid." +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q0 +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q1 +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q2 +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q3 +#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q4 +msgid "This question requires an answer." +msgstr "" diff --git a/survey_contact_generation/readme/CONTRIBUTORS.rst b/survey_contact_generation/readme/CONTRIBUTORS.rst index db689930..e3851e7f 100644 --- a/survey_contact_generation/readme/CONTRIBUTORS.rst +++ b/survey_contact_generation/readme/CONTRIBUTORS.rst @@ -2,3 +2,4 @@ * David Vidal * Ernesto Tejeda + * Stefan Ungureanu diff --git a/survey_contact_generation/static/description/index.html b/survey_contact_generation/static/description/index.html index fe775364..3ac2edcf 100644 --- a/survey_contact_generation/static/description/index.html +++ b/survey_contact_generation/static/description/index.html @@ -3,7 +3,7 @@ - + Survey contacts generation -
-

Survey contacts generation

+
+ + +Odoo Community Association + +
+

Survey contacts generation

-

Beta License: AGPL-3 OCA/survey Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/survey Translate me on Weblate Try me on Runboat

This module allows to generate new contacts from surveys answers.

Table of contents

@@ -386,7 +391,7 @@

Survey contacts generation

-

Configuration

+

Configuration

To configure the contact generation:

  1. Go to the configured survey.
  2. @@ -403,12 +408,12 @@

    Configuration

-

Usage

+

Usage

if the survey is properly configured, once it is submited by an anonomous user, a new contact is create or an existing one is linked.

-

Bug Tracker

+

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 to smash it by providing a detailed and welcomed @@ -416,15 +421,15 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Tecnativa
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -451,5 +456,6 @@

Maintainers

+
diff --git a/survey_contact_generation/views/survey_question_views.xml b/survey_contact_generation/views/survey_question_views.xml index f1b88af0..bb0e95c9 100644 --- a/survey_contact_generation/views/survey_question_views.xml +++ b/survey_contact_generation/views/survey_question_views.xml @@ -9,9 +9,9 @@ - + From d4fe800f59749db546896e082683ba038ce8d3e7 Mon Sep 17 00:00:00 2001 From: mymage Date: Tue, 11 Nov 2025 09:44:31 +0000 Subject: [PATCH 20/23] Translated using Weblate (Italian) Currently translated at 100.0% (27 of 27 strings) Translation: survey-17.0/survey-17.0-survey_contact_generation Translate-URL: https://translation.odoo-community.org/projects/survey-17-0/survey-17-0-survey_contact_generation/it/ --- survey_contact_generation/i18n/it.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/survey_contact_generation/i18n/it.po b/survey_contact_generation/i18n/it.po index 756a94d1..bbd58fe5 100644 --- a/survey_contact_generation/i18n/it.po +++ b/survey_contact_generation/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 15.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2024-02-26 07:16+0000\n" +"PO-Revision-Date: 2025-11-11 12:42+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -14,12 +14,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.17\n" +"X-Generator: Weblate 5.10.4\n" #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__allowed_partner_field_domain msgid "Allowed Partner Field Domain" -msgstr "" +msgstr "Dominio campo partner consentito" #. module: survey_contact_generation #: model:survey.question,title:survey_contact_generation.survey_contact_q3 From 41bf20f26850920f2a1e506d8ad137cae02cb56e Mon Sep 17 00:00:00 2001 From: eduezerouali-tecnativa Date: Fri, 10 Jul 2026 17:12:05 +0200 Subject: [PATCH 21/23] [IMP] survey_contact_generation: add posibility to create more than one partner per survey --- survey_contact_generation/README.rst | 33 +++- survey_contact_generation/__manifest__.py | 7 +- .../demo/survey_contact_nesting_demo.xml | 86 ++++++++++ survey_contact_generation/i18n/es.po | 72 ++++++++ survey_contact_generation/i18n/it.po | 72 ++++++++ .../i18n/survey_contact_generation.pot | 72 ++++++++ .../models/survey_question.py | 20 +++ .../models/survey_user_input.py | 115 +++++++++++-- survey_contact_generation/readme/CONFIGURE.md | 28 ++++ .../readme/CONTRIBUTORS.md | 1 + .../static/description/index.html | 71 +++++++- survey_contact_generation/tests/__init__.py | 1 + .../tests/test_survey_contact_nesting.py | 155 ++++++++++++++++++ .../views/survey_question_views.xml | 11 ++ 14 files changed, 728 insertions(+), 16 deletions(-) create mode 100644 survey_contact_generation/demo/survey_contact_nesting_demo.xml create mode 100644 survey_contact_generation/tests/test_survey_contact_nesting.py diff --git a/survey_contact_generation/README.rst b/survey_contact_generation/README.rst index 0ace717a..885b3ee9 100644 --- a/survey_contact_generation/README.rst +++ b/survey_contact_generation/README.rst @@ -11,7 +11,7 @@ Survey contacts generation !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:88258b218ef6c2d962226485f10c68c20b12f1afacd5dd070883960d0b9c5273 + !! source digest: sha256:1cc82509977655cfc45ab7ead533ec21a2b39cc308129b35a4ad8b84cbd07891 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -56,6 +56,36 @@ To configure the contact generation: then navigate to the 'Contact' group, and select the 'Contact field' field. +To generate a hierarchy of contacts out of a single survey: + +1. A question mapped to the *Name* contact field opens a contact of its + own. Any other question fills in a field of the contact opened by its + *Node*. +2. In such a question, set *Node* to the question opening the contact it + hangs from. Leave it empty and its answers will belong to the main + generated contact. +3. Contacts typed as *Contact* share their address with their parent, so + set *Contact address type* to *Other address* in the questions + opening a contact that holds an address of its own. + +For instance, this survey generates a company, two of its workcenters +with their own address, and an employee hanging from each workcenter: + +===================== ============= ============ ============= +Question Contact field Node Address type +===================== ============= ============ ============= +Company name name +Workcenter 1 name Company name Other address +Workcenter 1 street street Workcenter 1 +Workcenter 1 employee name Workcenter 1 +Workcenter 2 name Company name Other address +Workcenter 2 street street Workcenter 2 +Workcenter 2 employee name Workcenter 2 +===================== ============= ============ ============= + +A node whose name goes unanswered generates no contact, and whatever +hangs from it hangs from its own node instead. + Usage ===== @@ -89,6 +119,7 @@ Contributors - Ernesto Tejeda - Stefan Ungureanu - Pilar Vargas + - Eduardo Ezerouali Maintainers ----------- diff --git a/survey_contact_generation/__manifest__.py b/survey_contact_generation/__manifest__.py index de931de2..9ae0f814 100644 --- a/survey_contact_generation/__manifest__.py +++ b/survey_contact_generation/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Survey contacts generation", "summary": "Generate new contacts from surveys", - "version": "17.0.1.0.1", + "version": "17.0.1.1.0", "development_status": "Beta", "category": "Marketing/Survey", "website": "https://github.com/OCA/survey", @@ -15,7 +15,10 @@ "views/survey_question_views.xml", "views/survey_survey_views.xml", ], - "demo": ["demo/survey_contact_generation_demo.xml"], + "demo": [ + "demo/survey_contact_generation_demo.xml", + "demo/survey_contact_nesting_demo.xml", + ], "assets": { "web.assets_tests": [ "/survey_contact_generation/static/tests/survey_contact_generation_tour.esm.js", diff --git a/survey_contact_generation/demo/survey_contact_nesting_demo.xml b/survey_contact_generation/demo/survey_contact_nesting_demo.xml new file mode 100644 index 00000000..d917779e --- /dev/null +++ b/survey_contact_generation/demo/survey_contact_nesting_demo.xml @@ -0,0 +1,86 @@ + + + + + Nested Contact Creation Survey + 6c1b2f84-9a3d-4e77-b0c2-1d5e8a4f7c93 + public + + + + + + 0 + Company name + char_box + + + + + + + 1 + Workcenter 1 + char_box + + + other + + + + 2 + Workcenter 1 street + char_box + + + + + + 3 + Workcenter 1 employee + char_box + + + + + + 4 + Workcenter 1 employee email + char_box + + + + + + + 5 + Workcenter 2 + char_box + + + other + + + + 6 + Workcenter 2 street + char_box + + + + + + 7 + Workcenter 2 employee + char_box + + + + diff --git a/survey_contact_generation/i18n/es.po b/survey_contact_generation/i18n/es.po index 1ef59f6b..59a1ea29 100644 --- a/survey_contact_generation/i18n/es.po +++ b/survey_contact_generation/i18n/es.po @@ -17,6 +17,14 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.17\n" +#. module: survey_contact_generation +#: model:ir.model.fields,help:survey_contact_generation.field_survey_question__res_partner_type +msgid "" +"Address type of the contact this question opens. Contacts share their " +"address with their parent, so a node holding an address of its own needs a " +"different type." +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__allowed_partner_field_domain msgid "Allowed Partner Field Domain" @@ -29,6 +37,7 @@ msgstr "Color" #. module: survey_contact_generation #: model:survey.question,title:survey_contact_generation.survey_contact_q_company_name +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_company msgid "Company name" msgstr "" @@ -44,6 +53,11 @@ msgstr "Contacto" msgid "Contact Creation Survey" msgstr "Encuesta de creación de contactos" +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_type +msgid "Contact address type" +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question_answer__res_partner_field @@ -80,6 +94,11 @@ msgstr "Correo electrónico" msgid "Employees" msgstr "Empleados" +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field_name +msgid "Field Name" +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_survey__generate_contact msgid "Generate Contact" @@ -101,6 +120,16 @@ msgstr "" msgid "Name" msgstr "Nombre" +#. module: survey_contact_generation +#: model:survey.survey,title:survey_contact_generation.survey_contact_nesting +msgid "Nested Contact Creation Survey" +msgstr "" + +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__survey_question_node_id +msgid "Node" +msgstr "" + #. module: survey_contact_generation #: model:survey.question,title:survey_contact_generation.survey_contact_q2 msgid "Notes" @@ -111,6 +140,14 @@ msgstr "Notas" msgid "Prospects" msgstr "Perspectivas" +#. module: survey_contact_generation +#: model:ir.model.fields,help:survey_contact_generation.field_survey_question__survey_question_node_id +msgid "" +"Question opening the contact this one relates to. A question mapped to the " +"name opens a contact of its own, and hangs it from the contact of this node. " +"Any other question fills in a field of the contact this node opened." +msgstr "" + #. module: survey_contact_generation #: model:survey.question.answer,value:survey_contact_generation.survey_contact_q5_sug2 msgid "Romania" @@ -158,6 +195,41 @@ msgstr "Etiquetas" msgid "Vendor" msgstr "Vendedor" +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_1 +msgid "Workcenter 1" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_employee_1 +msgid "Workcenter 1 employee" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_employee_1_email +msgid "Workcenter 1 employee email" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_1_street +msgid "Workcenter 1 street" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_2 +msgid "Workcenter 2" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_employee_2 +msgid "Workcenter 2 employee" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_2_street +msgid "Workcenter 2 street" +msgstr "" + #~ msgid "Allowed Field" #~ msgstr "Campo permitido" diff --git a/survey_contact_generation/i18n/it.po b/survey_contact_generation/i18n/it.po index bbd58fe5..fef1e1d2 100644 --- a/survey_contact_generation/i18n/it.po +++ b/survey_contact_generation/i18n/it.po @@ -16,6 +16,14 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 5.10.4\n" +#. module: survey_contact_generation +#: model:ir.model.fields,help:survey_contact_generation.field_survey_question__res_partner_type +msgid "" +"Address type of the contact this question opens. Contacts share their " +"address with their parent, so a node holding an address of its own needs a " +"different type." +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__allowed_partner_field_domain msgid "Allowed Partner Field Domain" @@ -28,6 +36,7 @@ msgstr "Colore" #. module: survey_contact_generation #: model:survey.question,title:survey_contact_generation.survey_contact_q_company_name +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_company msgid "Company name" msgstr "Nome azienda" @@ -43,6 +52,11 @@ msgstr "Contatto" msgid "Contact Creation Survey" msgstr "Sondaggio creazione contatto" +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_type +msgid "Contact address type" +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question_answer__res_partner_field @@ -79,6 +93,11 @@ msgstr "E-mail" msgid "Employees" msgstr "Dipendenti" +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field_name +msgid "Field Name" +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_survey__generate_contact msgid "Generate Contact" @@ -100,6 +119,16 @@ msgstr "Generazione risposte utente sondaggio" msgid "Name" msgstr "Nome" +#. module: survey_contact_generation +#: model:survey.survey,title:survey_contact_generation.survey_contact_nesting +msgid "Nested Contact Creation Survey" +msgstr "" + +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__survey_question_node_id +msgid "Node" +msgstr "" + #. module: survey_contact_generation #: model:survey.question,title:survey_contact_generation.survey_contact_q2 msgid "Notes" @@ -110,6 +139,14 @@ msgstr "Note" msgid "Prospects" msgstr "Prospettive" +#. module: survey_contact_generation +#: model:ir.model.fields,help:survey_contact_generation.field_survey_question__survey_question_node_id +msgid "" +"Question opening the contact this one relates to. A question mapped to the " +"name opens a contact of its own, and hangs it from the contact of this node. " +"Any other question fills in a field of the contact this node opened." +msgstr "" + #. module: survey_contact_generation #: model:survey.question.answer,value:survey_contact_generation.survey_contact_q5_sug2 msgid "Romania" @@ -159,6 +196,41 @@ msgstr "Etichette" msgid "Vendor" msgstr "Fornitore" +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_1 +msgid "Workcenter 1" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_employee_1 +msgid "Workcenter 1 employee" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_employee_1_email +msgid "Workcenter 1 employee email" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_1_street +msgid "Workcenter 1 street" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_2 +msgid "Workcenter 2" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_employee_2 +msgid "Workcenter 2 employee" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_2_street +msgid "Workcenter 2 street" +msgstr "" + #~ msgid "Allowed Field" #~ msgstr "Campi permessi" diff --git a/survey_contact_generation/i18n/survey_contact_generation.pot b/survey_contact_generation/i18n/survey_contact_generation.pot index 67825618..d664d5da 100644 --- a/survey_contact_generation/i18n/survey_contact_generation.pot +++ b/survey_contact_generation/i18n/survey_contact_generation.pot @@ -13,6 +13,14 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" +#. module: survey_contact_generation +#: model:ir.model.fields,help:survey_contact_generation.field_survey_question__res_partner_type +msgid "" +"Address type of the contact this question opens. Contacts share their " +"address with their parent, so a node holding an address of its own needs a " +"different type." +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__allowed_partner_field_domain msgid "Allowed Partner Field Domain" @@ -25,6 +33,7 @@ msgstr "" #. module: survey_contact_generation #: model:survey.question,title:survey_contact_generation.survey_contact_q_company_name +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_company msgid "Company name" msgstr "" @@ -40,6 +49,11 @@ msgstr "" msgid "Contact Creation Survey" msgstr "" +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_type +msgid "Contact address type" +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question_answer__res_partner_field @@ -76,6 +90,11 @@ msgstr "" msgid "Employees" msgstr "" +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__res_partner_field_name +msgid "Field Name" +msgstr "" + #. module: survey_contact_generation #: model:ir.model.fields,field_description:survey_contact_generation.field_survey_survey__generate_contact msgid "Generate Contact" @@ -97,6 +116,16 @@ msgstr "" msgid "Name" msgstr "" +#. module: survey_contact_generation +#: model:survey.survey,title:survey_contact_generation.survey_contact_nesting +msgid "Nested Contact Creation Survey" +msgstr "" + +#. module: survey_contact_generation +#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question__survey_question_node_id +msgid "Node" +msgstr "" + #. module: survey_contact_generation #: model:survey.question,title:survey_contact_generation.survey_contact_q2 msgid "Notes" @@ -107,6 +136,14 @@ msgstr "" msgid "Prospects" msgstr "" +#. module: survey_contact_generation +#: model:ir.model.fields,help:survey_contact_generation.field_survey_question__survey_question_node_id +msgid "" +"Question opening the contact this one relates to. A question mapped to the " +"name opens a contact of its own, and hangs it from the contact of this node." +" Any other question fills in a field of the contact this node opened." +msgstr "" + #. module: survey_contact_generation #: model:survey.question.answer,value:survey_contact_generation.survey_contact_q5_sug2 msgid "Romania" @@ -153,3 +190,38 @@ msgstr "" #: model:survey.question.answer,value:survey_contact_generation.survey_contact_q6_sug1 msgid "Vendor" msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_1 +msgid "Workcenter 1" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_employee_1 +msgid "Workcenter 1 employee" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_employee_1_email +msgid "Workcenter 1 employee email" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_1_street +msgid "Workcenter 1 street" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_2 +msgid "Workcenter 2" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_employee_2 +msgid "Workcenter 2 employee" +msgstr "" + +#. module: survey_contact_generation +#: model:survey.question,title:survey_contact_generation.survey_nesting_q_workcenter_2_street +msgid "Workcenter 2 street" +msgstr "" diff --git a/survey_contact_generation/models/survey_question.py b/survey_contact_generation/models/survey_question.py index dbe62743..a9475265 100644 --- a/survey_contact_generation/models/survey_question.py +++ b/survey_contact_generation/models/survey_question.py @@ -13,6 +13,26 @@ class SurveyQuestion(models.Model): string="Contact field", comodel_name="ir.model.fields", ) + survey_question_node_id = fields.Many2one( + comodel_name="survey.question", + string="Node", + help="Question opening the contact this one relates to. A question " + "mapped to the name opens a contact of its own, and hangs it from the " + "contact of this node. Any other question fills in a field of the " + "contact this node opened.", + ) + # A many2one is just an id in the view, so we expose its name as a field + # to be able to use it in view modifiers + res_partner_field_name = fields.Char(related="res_partner_field.name") + res_partner_type = fields.Selection( + selection=lambda self: self.env["res.partner"] + ._fields["type"] + ._description_selection(self.env), + string="Contact address type", + help="Address type of the contact this question opens. Contacts share " + "their address with their parent, so a node holding an address of its " + "own needs a different type.", + ) @api.depends("question_type") def _compute_allowed_partner_field_domain(self): diff --git a/survey_contact_generation/models/survey_user_input.py b/survey_contact_generation/models/survey_user_input.py index 58addb9a..4492648f 100644 --- a/survey_contact_generation/models/survey_user_input.py +++ b/survey_contact_generation/models/survey_user_input.py @@ -1,17 +1,97 @@ # Copyright 2022 Tecnativa - David Vidal # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import models +from odoo import fields, models class SurveyUserInput(models.Model): _inherit = "survey.user_input" - def _prepare_partner(self): - """Extract partner values from the answers""" + def _get_partner_nodes(self): + """The questions opening a contact of their own. + + Filling in the name opens a contact, and then `survey_question_node_id` + tells which contact it hangs from. Any other question fills in a field + of the contact its own `survey_question_node_id` opened. A name answered + outside any node belongs to the main generated contact instead. + """ + self.ensure_one() + questions = self.survey_id.question_ids + nodes = questions.survey_question_node_id + return questions.filtered( + lambda x: x.res_partner_field.name == "name" + and (x.survey_question_node_id or x in nodes) + ) + + def _get_partner_groups(self): + """The answers that fill in a contact, grouped by the contact they fill""" self.ensure_one() - elegible_inputs = self.user_input_line_ids.filtered( + nodes = self._get_partner_nodes() + return self.user_input_line_ids.filtered( lambda x: x.question_id.res_partner_field and not x.skipped + ).grouped( + lambda x: x.question_id + if x.question_id in nodes + else x.question_id.survey_question_node_id + ) + + def _get_partner_node_children(self, groups, node): + """The nodes whose contact hangs from the given node's one""" + return [ + child + for child in groups + # A node whose own node answered nothing hangs from the main contact + if child + and ( + child.survey_question_node_id == node + or (not node and child.survey_question_node_id not in groups) + ) + ] + + def _prepare_partner(self): + """Extract the values of the main contact from the answers""" + self.ensure_one() + groups = self._get_partner_groups() + vals = self._prepare_partner_vals( + groups.get(self.env["survey.question"], self.env["survey.user_input.line"]) ) + vals["generating_survey_user_input_id"] = self.id + return vals + + def _create_partner_nodes(self, groups, node, parent): + """Generate the contact of every node hanging from the given one. + + `res.partner` sets `_allow_sudo_commands = False`, so the contacts can't + be nested in the `child_ids` of their parent: the commands would run + back as the survey taker, who isn't allowed to create contacts. Each + contact gets its own `create()` instead, linked through `parent_id`. + + Returns the contacts generated right below the given node. + """ + self.ensure_one() + partners = self.env["res.partner"] + for child in self._get_partner_node_children(groups, node): + vals = self._prepare_partner_vals(groups[child]) + if not vals.get("name"): + # A node whose name went unanswered opens no contact, so + # whatever hangs from it hangs from its own node instead. Its + # remaining answers are dropped: they have no contact to fill. + partners |= self._create_partner_nodes(groups, child, parent) + continue + if parent: + vals["parent_id"] = parent.id + # `contact` children share their address with their parent, so a + # node holding an address of its own needs a different type + if child.res_partner_type: + vals["type"] = child.res_partner_type + partner = self.env["res.partner"].sudo().create(vals) + self._create_contact_post_process(partner) + self._create_partner_nodes(groups, child, partner) + partners |= partner + return partners + + def _prepare_partner_vals(self, elegible_inputs): + """Extract the values of a single contact out of its group of answers""" + self.ensure_one() basic_inputs = elegible_inputs.filtered( lambda x: x.answer_type not in {"suggestion"} and x.question_id.res_partner_field.name not in {"comment", "company_name"} @@ -45,6 +125,7 @@ def _prepare_partner(self): if line[f"value_{line.answer_type}"]: vals["parent_id"] = ( self.env["res.partner"] + .sudo() .create( { "name": line[f"value_{line.answer_type}"], @@ -61,7 +142,6 @@ def _prepare_partner(self): vals[field_name] += line.suggested_answer_id.value else: vals[field_name] = line.suggested_answer_id.value - vals["generating_survey_user_input_id"] = self.id return vals def _create_contact_post_process(self, partner): @@ -82,12 +162,23 @@ def _mark_done(self): lambda r: r.survey_id.generate_contact and not r.partner_id ): vals = user_input._prepare_partner() - partner = False - email = vals.get("email") - if email: - partner = self._get_existing_partner(email) + partner = self.env["res.partner"] + # Every answer may live inside a node, and then there's no main + # contact to generate: the root node contact takes its place + if set(vals) - {"generating_survey_user_input_id"}: + email = vals.get("email") + if email: + partner = user_input._get_existing_partner(email) + if not partner: + partner = self.env["res.partner"].sudo().create(vals) + user_input._create_contact_post_process(partner) + # The node contacts hang from the main one, when there's one + roots = user_input._create_partner_nodes( + user_input._get_partner_groups(), self.env["survey.question"], partner + ) if not partner: - partner = self.env["res.partner"].create(vals) - self._create_contact_post_process(partner) - self.update({"partner_id": partner.id, "email": partner.email}) + partner = fields.first(roots) + partner.sudo().generating_survey_user_input_id = user_input + if partner: + user_input.update({"partner_id": partner.id, "email": partner.email}) return super()._mark_done() diff --git a/survey_contact_generation/readme/CONFIGURE.md b/survey_contact_generation/readme/CONFIGURE.md index b914557e..b3f74f7f 100644 --- a/survey_contact_generation/readme/CONFIGURE.md +++ b/survey_contact_generation/readme/CONFIGURE.md @@ -11,3 +11,31 @@ To configure the contact generation: corresponding contact field. To do this, go to the 'Options' tab, then navigate to the 'Contact' group, and select the 'Contact field' field. + +To generate a hierarchy of contacts out of a single survey: + +1. A question mapped to the *Name* contact field opens a contact of its + own. Any other question fills in a field of the contact opened by its + *Node*. +2. In such a question, set *Node* to the question opening the contact it + hangs from. Leave it empty and its answers will belong to the main + generated contact. +3. Contacts typed as *Contact* share their address with their parent, so + set *Contact address type* to *Other address* in the questions opening + a contact that holds an address of its own. + +For instance, this survey generates a company, two of its workcenters +with their own address, and an employee hanging from each workcenter: + +| Question | Contact field | Node | Address type | +|----------------------|---------------|----------------------|---------------| +| Company name | name | | | +| Workcenter 1 | name | Company name | Other address | +| Workcenter 1 street | street | Workcenter 1 | | +| Workcenter 1 employee| name | Workcenter 1 | | +| Workcenter 2 | name | Company name | Other address | +| Workcenter 2 street | street | Workcenter 2 | | +| Workcenter 2 employee| name | Workcenter 2 | | + +A node whose name goes unanswered generates no contact, and whatever hangs +from it hangs from its own node instead. diff --git a/survey_contact_generation/readme/CONTRIBUTORS.md b/survey_contact_generation/readme/CONTRIBUTORS.md index 946ac052..c6ae6110 100644 --- a/survey_contact_generation/readme/CONTRIBUTORS.md +++ b/survey_contact_generation/readme/CONTRIBUTORS.md @@ -3,3 +3,4 @@ - Ernesto Tejeda - Stefan Ungureanu - Pilar Vargas + - Eduardo Ezerouali diff --git a/survey_contact_generation/static/description/index.html b/survey_contact_generation/static/description/index.html index 3b17ec76..f89f13e9 100644 --- a/survey_contact_generation/static/description/index.html +++ b/survey_contact_generation/static/description/index.html @@ -372,7 +372,7 @@

Survey contacts generation

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:88258b218ef6c2d962226485f10c68c20b12f1afacd5dd070883960d0b9c5273 +!! source digest: sha256:1cc82509977655cfc45ab7ead533ec21a2b39cc308129b35a4ad8b84cbd07891 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/survey Translate me on Weblate Try me on Runboat

This module allows to generate new contacts from surveys answers.

@@ -406,6 +406,74 @@

Configuration

then navigate to the ‘Contact’ group, and select the ‘Contact field’ field. +

To generate a hierarchy of contacts out of a single survey:

+
    +
  1. A question mapped to the Name contact field opens a contact of its +own. Any other question fills in a field of the contact opened by its +Node.
  2. +
  3. In such a question, set Node to the question opening the contact it +hangs from. Leave it empty and its answers will belong to the main +generated contact.
  4. +
  5. Contacts typed as Contact share their address with their parent, so +set Contact address type to Other address in the questions +opening a contact that holds an address of its own.
  6. +
+

For instance, this survey generates a company, two of its workcenters +with their own address, and an employee hanging from each workcenter:

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
QuestionContact fieldNodeAddress type
Company namename  
Workcenter 1nameCompany nameOther address
Workcenter 1 streetstreetWorkcenter 1 
Workcenter 1 employeenameWorkcenter 1 
Workcenter 2nameCompany nameOther address
Workcenter 2 streetstreetWorkcenter 2 
Workcenter 2 employeenameWorkcenter 2 
+

A node whose name goes unanswered generates no contact, and whatever +hangs from it hangs from its own node instead.

Usage

@@ -436,6 +504,7 @@

Contributors

  • Ernesto Tejeda
  • Stefan Ungureanu
  • Pilar Vargas
  • +
  • Eduardo Ezerouali
  • diff --git a/survey_contact_generation/tests/__init__.py b/survey_contact_generation/tests/__init__.py index d4c56fbb..a8a77a9f 100644 --- a/survey_contact_generation/tests/__init__.py +++ b/survey_contact_generation/tests/__init__.py @@ -1 +1,2 @@ from . import test_survey_contact_generation +from . import test_survey_contact_nesting diff --git a/survey_contact_generation/tests/test_survey_contact_nesting.py b/survey_contact_generation/tests/test_survey_contact_nesting.py new file mode 100644 index 00000000..46246912 --- /dev/null +++ b/survey_contact_generation/tests/test_survey_contact_nesting.py @@ -0,0 +1,155 @@ +# Copyright 2026 Tecnativa - Eduardo Ezerouali +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo.tests import TransactionCase, tagged + + +@tagged("post_install", "-at_install") +class TestSurveyContactNesting(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.survey = cls.env.ref("survey_contact_generation.survey_contact_nesting") + cls.q_company = cls.env.ref( + "survey_contact_generation.survey_nesting_q_company" + ) + cls.q_workcenter_1 = cls.env.ref( + "survey_contact_generation.survey_nesting_q_workcenter_1" + ) + cls.q_workcenter_1_street = cls.env.ref( + "survey_contact_generation.survey_nesting_q_workcenter_1_street" + ) + cls.q_employee_1 = cls.env.ref( + "survey_contact_generation.survey_nesting_q_employee_1" + ) + cls.q_employee_1_email = cls.env.ref( + "survey_contact_generation.survey_nesting_q_employee_1_email" + ) + cls.q_workcenter_2 = cls.env.ref( + "survey_contact_generation.survey_nesting_q_workcenter_2" + ) + cls.q_workcenter_2_street = cls.env.ref( + "survey_contact_generation.survey_nesting_q_workcenter_2_street" + ) + cls.q_employee_2 = cls.env.ref( + "survey_contact_generation.survey_nesting_q_employee_2" + ) + + def _answer(self, user_input, answers): + """Answer the given `{question: value}` map with char box lines""" + for question, value in answers.items(): + self.env["survey.user_input.line"].create( + { + "user_input_id": user_input.id, + "question_id": question.id, + "skipped": not value, + "answer_type": "char_box" if value else False, + "value_char_box": value, + } + ) + + def _submit(self, answers=None): + """Answer the whole survey, overriding the given answers, and submit it""" + user_input = self.env["survey.user_input"].create({"survey_id": self.survey.id}) + default_answers = { + self.q_company: "ACME", + self.q_workcenter_1: "Workcenter North", + self.q_workcenter_1_street: "1 North Street", + self.q_employee_1: "Alice", + self.q_employee_1_email: "alice@example.com", + self.q_workcenter_2: "Workcenter South", + self.q_workcenter_2_street: "2 South Street", + self.q_employee_2: "Bob", + } + default_answers.update(answers or {}) + self._answer(user_input, default_answers) + user_input._mark_done() + return user_input + + def _get_contact(self, user_input, name): + return self.env["res.partner"].search( + [("id", "child_of", user_input.partner_id.id), ("name", "=", name)] + ) + + def test_groups_open_one_contact_per_name_question(self): + """A name question opens a contact, any other one fills the node's contact""" + user_input = self.env["survey.user_input"].create({"survey_id": self.survey.id}) + self._answer( + user_input, + { + self.q_company: "ACME", + self.q_workcenter_1: "Workcenter North", + self.q_workcenter_1_street: "1 North Street", + self.q_employee_1: "Alice", + }, + ) + groups = user_input._get_partner_groups() + self.assertEqual( + {key.title for key in groups}, + {"Company name", "Workcenter 1", "Workcenter 1 employee"}, + ) + # The street doesn't open a contact: it fills in the workcenter's one + self.assertEqual( + groups[self.q_workcenter_1].question_id, + self.q_workcenter_1 + self.q_workcenter_1_street, + ) + + def test_contact_hierarchy(self): + """Every node generates a contact hanging from the contact of its node""" + user_input = self._submit() + company = user_input.partner_id + self.assertEqual(company.name, "ACME") + self.assertFalse(company.parent_id) + self.assertEqual(company.generating_survey_user_input_id, user_input) + north = self._get_contact(user_input, "Workcenter North") + south = self._get_contact(user_input, "Workcenter South") + self.assertEqual(north.parent_id, company) + self.assertEqual(south.parent_id, company) + self.assertEqual(self._get_contact(user_input, "Alice").parent_id, north) + self.assertEqual(self._get_contact(user_input, "Bob").parent_id, south) + + def test_sibling_nodes_do_not_share_their_answers(self): + """Contacts hanging from the same node don't overwrite each other""" + user_input = self._submit() + self.assertEqual( + self._get_contact(user_input, "Workcenter North").street, "1 North Street" + ) + self.assertEqual( + self._get_contact(user_input, "Workcenter South").street, "2 South Street" + ) + self.assertEqual( + self._get_contact(user_input, "Alice").email, "alice@example.com" + ) + self.assertFalse(self._get_contact(user_input, "Bob").email) + + def test_address_type_isolates_the_address(self): + """A node typed as an address doesn't share it with its parent's family""" + user_input = self._submit() + north = self._get_contact(user_input, "Workcenter North") + self.assertEqual(north.type, "other") + # A `contact` child still shares the address of its own node + self.assertEqual(self._get_contact(user_input, "Alice").type, "contact") + self.assertEqual(self._get_contact(user_input, "Alice").street, north.street) + + def test_skipped_node_hands_its_children_over(self): + """A node whose name went unanswered generates no contact""" + user_input = self._submit({self.q_workcenter_1: False}) + company = user_input.partner_id + self.assertFalse(self._get_contact(user_input, "Workcenter North")) + # Alice hangs from the company now, as her own node generated nothing + self.assertEqual(self._get_contact(user_input, "Alice").parent_id, company) + # A nameless contact holding the orphan street is not generated either + contacts = self.env["res.partner"].search([("id", "child_of", company.id)]) + self.assertFalse(contacts.filtered(lambda x: not x.name)) + self.assertFalse(contacts.filtered(lambda x: x.street == "1 North Street")) + + def test_root_node_contact_is_the_generated_one(self): + """With every answer inside a node there's no main contact to generate""" + user_input = self._submit() + # The root node contact takes the place of the main one + self.assertEqual(user_input.partner_id.name, "ACME") + self.assertEqual( + self.env["res.partner"].search_count( + [("generating_survey_user_input_id", "=", user_input.id)] + ), + 1, + ) diff --git a/survey_contact_generation/views/survey_question_views.xml b/survey_contact_generation/views/survey_question_views.xml index bb0e95c9..e85c0c32 100644 --- a/survey_contact_generation/views/survey_question_views.xml +++ b/survey_contact_generation/views/survey_question_views.xml @@ -11,6 +11,17 @@ options="{'no_create': True, 'no_open': True}" domain="allowed_partner_field_domain" /> + + + From 5a7372fddd7857c9ec51f0fbcbb8cbef47c77525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adasat=20Torres=20de=20Le=C3=B3n?= Date: Tue, 11 Aug 2026 09:35:38 +0100 Subject: [PATCH 22/23] [IMP] survey_contact_generation: pre-commit auto fixes --- .../demo/survey_contact_generation_demo.xml | 2 +- .../demo/survey_contact_nesting_demo.xml | 6 +++--- survey_contact_generation/models/survey_question.py | 6 +++--- survey_contact_generation/models/survey_user_input.py | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/survey_contact_generation/demo/survey_contact_generation_demo.xml b/survey_contact_generation/demo/survey_contact_generation_demo.xml index b01dd4fe..f67b608e 100644 --- a/survey_contact_generation/demo/survey_contact_generation_demo.xml +++ b/survey_contact_generation/demo/survey_contact_generation_demo.xml @@ -1,6 +1,6 @@ - + Contact Creation Survey 80e5f1e2-1a9d-4c51-8e23-09e93f7fa2c5 diff --git a/survey_contact_generation/demo/survey_contact_nesting_demo.xml b/survey_contact_generation/demo/survey_contact_nesting_demo.xml index d917779e..e65a980b 100644 --- a/survey_contact_generation/demo/survey_contact_nesting_demo.xml +++ b/survey_contact_generation/demo/survey_contact_nesting_demo.xml @@ -1,6 +1,6 @@ - + 1 @@ -57,7 +57,7 @@ - + 5 diff --git a/survey_contact_generation/models/survey_question.py b/survey_contact_generation/models/survey_question.py index a9475265..9abcd638 100644 --- a/survey_contact_generation/models/survey_question.py +++ b/survey_contact_generation/models/survey_question.py @@ -73,9 +73,9 @@ def default_get(self, fields): return result res = self.env[partner_field.relation].search([], limit=1) if res: - result[ - "res_partner_field_resource_ref" - ] = f"{partner_field.relation},{res.id}" + result["res_partner_field_resource_ref"] = ( + f"{partner_field.relation},{res.id}" + ) return result @api.model diff --git a/survey_contact_generation/models/survey_user_input.py b/survey_contact_generation/models/survey_user_input.py index 4492648f..bc857b8a 100644 --- a/survey_contact_generation/models/survey_user_input.py +++ b/survey_contact_generation/models/survey_user_input.py @@ -103,9 +103,9 @@ def _prepare_partner_vals(self, elegible_inputs): for line in elegible_inputs - basic_inputs: field_name = line.question_id.res_partner_field.name if line.question_id.res_partner_field.ttype == "many2one": - vals[ - field_name - ] = line.suggested_answer_id.res_partner_field_resource_ref.id + vals[field_name] = ( + line.suggested_answer_id.res_partner_field_resource_ref.id + ) elif line.question_id.res_partner_field.ttype == "many2many": vals.setdefault(field_name, []) vals[field_name] += [ From 3acadf58590eb42affcbb01842d274b33897ac5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adasat=20Torres=20de=20Le=C3=B3n?= Date: Tue, 11 Aug 2026 11:01:06 +0100 Subject: [PATCH 23/23] [MIG] survey_contact_generation: Migration to version 19.0 --- survey_contact_generation/README.rst | 11 +- survey_contact_generation/__manifest__.py | 2 +- .../demo/survey_contact_generation_demo.xml | 8 - .../models/survey_user_input.py | 4 +- .../readme/CONTRIBUTORS.md | 1 + .../static/description/index.html | 9 +- .../survey_contact_generation_tour.esm.js | 58 ++++--- .../tests/test_survey_contact_generation.py | 156 +++++++++++++++++- .../tests/test_survey_contact_nesting.py | 120 +++++++++++--- 9 files changed, 295 insertions(+), 74 deletions(-) diff --git a/survey_contact_generation/README.rst b/survey_contact_generation/README.rst index 885b3ee9..127381bf 100644 --- a/survey_contact_generation/README.rst +++ b/survey_contact_generation/README.rst @@ -21,13 +21,13 @@ Survey contacts generation :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsurvey-lightgray.png?logo=github - :target: https://github.com/OCA/survey/tree/17.0/survey_contact_generation + :target: https://github.com/OCA/survey/tree/19.0/survey_contact_generation :alt: OCA/survey .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/survey-17-0/survey-17-0-survey_contact_generation + :target: https://translation.odoo-community.org/projects/survey-19-0/survey-19-0-survey_contact_generation :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/survey&target_branch=17.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/survey&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -98,7 +98,7 @@ 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 to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -120,6 +120,7 @@ Contributors - Stefan Ungureanu - Pilar Vargas - Eduardo Ezerouali + - Adasat Torres Maintainers ----------- @@ -142,6 +143,6 @@ Current `maintainer `__: |maintainer-pilarvargas-tecnativa| -This module is part of the `OCA/survey `_ project on GitHub. +This module is part of the `OCA/survey `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/survey_contact_generation/__manifest__.py b/survey_contact_generation/__manifest__.py index 9ae0f814..aee473cc 100644 --- a/survey_contact_generation/__manifest__.py +++ b/survey_contact_generation/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Survey contacts generation", "summary": "Generate new contacts from surveys", - "version": "17.0.1.1.0", + "version": "19.0.1.0.0", "development_status": "Beta", "category": "Marketing/Survey", "website": "https://github.com/OCA/survey", diff --git a/survey_contact_generation/demo/survey_contact_generation_demo.xml b/survey_contact_generation/demo/survey_contact_generation_demo.xml index f67b608e..34c73394 100644 --- a/survey_contact_generation/demo/survey_contact_generation_demo.xml +++ b/survey_contact_generation/demo/survey_contact_generation_demo.xml @@ -3,7 +3,6 @@ Contact Creation Survey - 80e5f1e2-1a9d-4c51-8e23-09e93f7fa2c5 public @@ -46,13 +45,6 @@ numerical_box - - - 4 - Date - date - - 4 diff --git a/survey_contact_generation/models/survey_user_input.py b/survey_contact_generation/models/survey_user_input.py index bc857b8a..5119d40e 100644 --- a/survey_contact_generation/models/survey_user_input.py +++ b/survey_contact_generation/models/survey_user_input.py @@ -1,6 +1,6 @@ # Copyright 2022 Tecnativa - David Vidal # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import fields, models +from odoo import models class SurveyUserInput(models.Model): @@ -177,7 +177,7 @@ def _mark_done(self): user_input._get_partner_groups(), self.env["survey.question"], partner ) if not partner: - partner = fields.first(roots) + partner = next(iter(roots)) if len(roots) > 1 else roots partner.sudo().generating_survey_user_input_id = user_input if partner: user_input.update({"partner_id": partner.id, "email": partner.email}) diff --git a/survey_contact_generation/readme/CONTRIBUTORS.md b/survey_contact_generation/readme/CONTRIBUTORS.md index c6ae6110..41e7f47b 100644 --- a/survey_contact_generation/readme/CONTRIBUTORS.md +++ b/survey_contact_generation/readme/CONTRIBUTORS.md @@ -4,3 +4,4 @@ - Stefan Ungureanu - Pilar Vargas - Eduardo Ezerouali + - Adasat Torres diff --git a/survey_contact_generation/static/description/index.html b/survey_contact_generation/static/description/index.html index f89f13e9..637befb9 100644 --- a/survey_contact_generation/static/description/index.html +++ b/survey_contact_generation/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Survey contacts generation