1 Commits

Author SHA1 Message Date
853ed418bb wip 2025-08-21 12:31:41 +02:00
153 changed files with 2873 additions and 3977 deletions

View File

@@ -1,20 +0,0 @@
# Configuration for known file extensions
[*.{css,js,json,less,md,py,rst,sass,scss,xml,yaml,yml}]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{json,yml,yaml,rst,md}]
indent_size = 2
# Do not configure editor for libs and autogenerated content
[{*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst}]
charset = unset
end_of_line = unset
indent_size = unset
indent_style = unset
insert_final_newline = false
trim_trailing_whitespace = false

View File

@@ -1,188 +0,0 @@
env:
browser: true
es6: true
# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449
parserOptions:
ecmaVersion: 2019
overrides:
- files:
- "**/*.esm.js"
parserOptions:
sourceType: module
# Globals available in Odoo that shouldn't produce errorings
globals:
_: readonly
$: readonly
fuzzy: readonly
jQuery: readonly
moment: readonly
odoo: readonly
openerp: readonly
owl: readonly
luxon: readonly
# Styling is handled by Prettier, so we only need to enable AST rules;
# see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890
rules:
accessor-pairs: warn
array-callback-return: warn
callback-return: warn
capitalized-comments:
- warn
- always
- ignoreConsecutiveComments: true
ignoreInlineComments: true
complexity:
- warn
- 15
constructor-super: warn
dot-notation: warn
eqeqeq: warn
global-require: warn
handle-callback-err: warn
id-blacklist: warn
id-match: warn
init-declarations: error
max-depth: warn
max-nested-callbacks: warn
max-statements-per-line: warn
no-alert: warn
no-array-constructor: warn
no-caller: warn
no-case-declarations: warn
no-class-assign: warn
no-cond-assign: error
no-const-assign: error
no-constant-condition: warn
no-control-regex: warn
no-debugger: error
no-delete-var: warn
no-div-regex: warn
no-dupe-args: error
no-dupe-class-members: error
no-dupe-keys: error
no-duplicate-case: error
no-duplicate-imports: error
no-else-return: warn
no-empty-character-class: warn
no-empty-function: error
no-empty-pattern: error
no-empty: warn
no-eq-null: error
no-eval: error
no-ex-assign: error
no-extend-native: warn
no-extra-bind: warn
no-extra-boolean-cast: warn
no-extra-label: warn
no-fallthrough: warn
no-func-assign: error
no-global-assign: error
no-implicit-coercion:
- warn
- allow: ["~"]
no-implicit-globals: warn
no-implied-eval: warn
no-inline-comments: warn
no-inner-declarations: warn
no-invalid-regexp: warn
no-irregular-whitespace: warn
no-iterator: warn
no-label-var: warn
no-labels: warn
no-lone-blocks: warn
no-lonely-if: error
no-mixed-requires: error
no-multi-str: warn
no-native-reassign: error
no-negated-condition: warn
no-negated-in-lhs: error
no-new-func: warn
no-new-object: warn
no-new-require: warn
no-new-symbol: warn
no-new-wrappers: warn
no-new: warn
no-obj-calls: warn
no-octal-escape: warn
no-octal: warn
no-param-reassign: warn
no-path-concat: warn
no-process-env: warn
no-process-exit: warn
no-proto: warn
no-prototype-builtins: warn
no-redeclare: warn
no-regex-spaces: warn
no-restricted-globals: warn
no-restricted-imports: warn
no-restricted-modules: warn
no-restricted-syntax: warn
no-return-assign: error
no-script-url: warn
no-self-assign: warn
no-self-compare: warn
no-sequences: warn
no-shadow-restricted-names: warn
no-shadow: warn
no-sparse-arrays: warn
no-sync: warn
no-this-before-super: warn
no-throw-literal: warn
no-undef-init: warn
no-undef: error
no-unmodified-loop-condition: warn
no-unneeded-ternary: error
no-unreachable: error
no-unsafe-finally: error
no-unused-expressions: error
no-unused-labels: error
no-unused-vars: error
no-use-before-define: error
no-useless-call: warn
no-useless-computed-key: warn
no-useless-concat: warn
no-useless-constructor: warn
no-useless-escape: warn
no-useless-rename: warn
no-void: warn
no-with: warn
operator-assignment: [error, always]
prefer-const: warn
radix: warn
require-yield: warn
sort-imports: warn
spaced-comment: [error, always]
strict: [error, function]
use-isnan: error
valid-jsdoc:
- warn
- prefer:
arg: param
argument: param
augments: extends
constructor: class
exception: throws
func: function
method: function
prop: property
return: returns
virtual: abstract
yield: yields
preferType:
array: Array
bool: Boolean
boolean: Boolean
number: Number
object: Object
str: String
string: String
requireParamDescription: false
requireReturn: false
requireReturnDescription: false
requireReturnType: false
valid-typeof: warn
yoda: warn

View File

@@ -1,42 +0,0 @@
name: pre-commit
on:
pull_request:
branches:
- "18.0*"
jobs:
pre-commit:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Get python version
run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
# - uses: actions/cache@v4
# with:
# path: ~/.cache/pre-commit
# key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
- name: Install pre-commit
run: pip install pre-commit
- name: Run pre-commit
run: pre-commit run --all-files --show-diff-on-failure --color=always
env:
# Consider valid a PR that changes README fragments but doesn't
# change the README.rst file itself. It's not really a problem
# because the bot will update it anyway after merge. This way, we
# lower the barrier for functional contributors that want to fix the
# readme fragments, while still letting developers get README
# auto-generated (which also helps functionals when using runboat).
# DOCS https://pre-commit.com/#temporarily-disabling-hooks
SKIP: oca-gen-addon-readme
- name: Check that all files generated by pre-commit are in git
run: |
newfiles="$(git ls-files --others --exclude-from=.gitignore)"
if [ "$newfiles" != "" ] ; then
echo "Please check-in the following files:"
echo "$newfiles"
exit 1
fi

View File

@@ -1,150 +0,0 @@
exclude: |
(?x)
# NOT INSTALLABLE ADDONS
# END NOT INSTALLABLE ADDONS
# Files and folders generated by bots, to avoid loops
^setup/|/static/description/index\.html$|
# We don't want to mess with tool-generated files
.svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/|^eslint.config.cjs|^prettier.config.cjs|
# Maybe reactivate this when all README files include prettier ignore tags?
^README\.md$|
# Library files can have extraneous formatting (even minimized)
/static/(src/)?lib/|
# Repos using Sphinx to generate docs don't need prettying
^docs/_templates/.*\.html$|
# Don't bother non-technical authors with formatting issues in docs
readme/.*\.(rst|md)$|
# Ignore build and dist directories in addons
/build/|/dist/|
# Ignore test files in addons
/tests/samples/.*|
# You don't usually want a bot to modify your legal texts
(LICENSE.*|COPYING.*)
default_language_version:
python: python3
node: "16.17.0"
repos:
- repo: local
hooks:
# These files are most likely copier diff rejection junks; if found,
# review them manually, fix the problem (if needed) and remove them
- id: forbidden-files
name: forbidden files
entry: found forbidden files; remove them
language: fail
files: "\\.rej$"
- id: en-po-files
name: en.po files cannot exist
entry: found a en.po file
language: fail
files: '[a-zA-Z0-9_]*/i18n/en\.po$'
- repo: https://github.com/oca/maintainer-tools
rev: f9b919b9868143135a9c9cb03021089cabba8223
hooks:
# update the NOT INSTALLABLE ADDONS section above
- id: oca-update-pre-commit-excluded-addons
- id: oca-fix-manifest-website
entry:
bash -c 'oca-fix-manifest-website "https://git.elabore.coop/elabore/$(basename
$(git rev-parse --show-toplevel))"'
- id: oca-gen-addon-readme
entry:
bash -c 'oca-gen-addon-readme
--addons-dir=.
--branch=$(git symbolic-ref
refs/remotes/origin/HEAD | sed "s@^refs/remotes/origin/@@")
--repo-name=$(basename $(git rev-parse --show-toplevel))
--org-name="Elabore"
--if-source-changed --keep-source-digest'
- repo: https://github.com/OCA/odoo-pre-commit-hooks
rev: v0.1.4
hooks:
- id: oca-checks-odoo-module
- id: oca-checks-po
args:
- --disable=po-pretty-format
- repo: local
hooks:
- id: prettier
name: prettier (with plugin-xml)
entry: prettier
args:
- --write
- --list-different
- --ignore-unknown
types: [text]
files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$
language: node
additional_dependencies:
- "prettier@2.7.1"
- "@prettier/plugin-xml@2.2.0"
- repo: local
hooks:
- id: eslint
name: eslint
entry: eslint
args:
- --color
- --fix
verbose: true
types: [javascript]
language: node
additional_dependencies:
- "eslint@8.24.0"
- "eslint-plugin-jsdoc@"
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
# exclude autogenerated files
exclude: /README\.rst$|\.pot?$
- id: end-of-file-fixer
# exclude autogenerated files
exclude: /README\.rst$|\.pot?$
- id: debug-statements
- id: fix-encoding-pragma
args: ["--remove"]
- id: check-case-conflict
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-merge-conflict
# exclude files where underlines are not distinguishable from merge conflicts
exclude: /README\.rst$|^docs/.*\.rst$
- id: check-symlinks
- id: check-xml
- id: mixed-line-ending
args: ["--fix=lf"]
- repo: https://github.com/PyCQA/docformatter
rev: v1.7.7
hooks:
- id: docformatter
args: [
"--in-place", # modify the files
"--recursive", # run on all the files
"--wrap-summaries",
"88", # max length of 1st line
"--wrap-descriptions",
"88", # max length of other lines
"--pre-summary-newline", # new line before a long summary
"--make-summary-multi-line", # force summary on multilines
]
additional_dependencies: ["tomli"] # if Python <3.11
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.0
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
- repo: https://github.com/OCA/pylint-odoo
rev: v9.1.3
hooks:
- id: pylint_odoo
name: pylint with optional checks
args:
- --rcfile=.pylintrc
- --exit-zero
verbose: true
- id: pylint_odoo
args:
- --rcfile=.pylintrc-mandatory

View File

@@ -1,8 +0,0 @@
# Defaults for all prettier-supported languages.
# Prettier will complete this with settings from .editorconfig file.
bracketSpacing: false
printWidth: 88
proseWrap: always
semi: true
trailingComma: "es5"
xmlWhitespaceSensitivity: "strict"

123
.pylintrc
View File

@@ -1,123 +0,0 @@
[MASTER]
load-plugins=pylint_odoo
score=n
[ODOOLINT]
readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst"
manifest-required-authors=Elabore
manifest-required-keys=license
manifest-deprecated-keys=description,active
license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3
valid-odoo-versions=18.0
[MESSAGES CONTROL]
disable=all
# This .pylintrc contains optional AND mandatory checks and is meant to be
# loaded in an IDE to have it check everything, in the hope this will make
# optional checks more visible to contributors who otherwise never look at a
# green travis to see optional checks that failed.
# .pylintrc-mandatory containing only mandatory checks is used the pre-commit
# config as a blocking check.
enable=anomalous-backslash-in-string,
api-one-deprecated,
api-one-multi-together,
assignment-from-none,
attribute-deprecated,
class-camelcase,
dangerous-default-value,
dangerous-view-replace-wo-priority,
development-status-allowed,
duplicate-id-csv,
duplicate-key,
duplicate-xml-fields,
duplicate-xml-record-id,
eval-referenced,
eval-used,
incoherent-interpreter-exec-perm,
license-allowed,
manifest-author-string,
manifest-deprecated-key,
manifest-required-author,
manifest-required-key,
manifest-version-format,
method-compute,
method-inverse,
method-required-super,
method-search,
openerp-exception-warning,
pointless-statement,
pointless-string-statement,
print-used,
redundant-keyword-arg,
redundant-modulename-xml,
reimported,
relative-import,
return-in-init,
rst-syntax-error,
sql-injection,
too-few-format-args,
translation-field,
translation-required,
unreachable,
use-vim-comment,
wrong-tabs-instead-of-spaces,
xml-syntax-error,
attribute-string-redundant,
character-not-valid-in-resource-link,
consider-merging-classes-inherited,
context-overridden,
create-user-wo-reset-password,
dangerous-filter-wo-user,
dangerous-qweb-replace-wo-priority,
deprecated-data-xml-node,
deprecated-openerp-xml-node,
duplicate-po-message-definition,
except-pass,
file-not-used,
invalid-commit,
manifest-maintainers-list,
missing-newline-extrafiles,
missing-readme,
missing-return,
odoo-addons-relative-import,
old-api7-method-defined,
po-msgstr-variables,
po-syntax-error,
renamed-field-parameter,
resource-not-exist,
str-format-used,
test-folder-imported,
translation-contains-variable,
translation-positional-used,
unnecessary-utf8-coding-comment,
website-manifest-key-not-valid-uri,
xml-attribute-translatable,
xml-deprecated-qweb-directive,
xml-deprecated-tree-attribute,
external-request-timeout,
# messages that do not cause the lint step to fail
consider-merging-classes-inherited,
create-user-wo-reset-password,
dangerous-filter-wo-user,
deprecated-module,
file-not-used,
invalid-commit,
missing-manifest-dependency,
missing-newline-extrafiles,
missing-readme,
no-utf8-coding-comment,
odoo-addons-relative-import,
old-api7-method-defined,
redefined-builtin,
too-complex,
unnecessary-utf8-coding-comment
[REPORTS]
msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
output-format=colorized
reports=no

View File

@@ -1,98 +0,0 @@
[MASTER]
load-plugins=pylint_odoo
score=n
[ODOOLINT]
readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst"
manifest-required-authors=Elabore
manifest-required-keys=license
manifest-deprecated-keys=description,active
license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3
valid-odoo-versions=18.0
[MESSAGES CONTROL]
disable=all
enable=anomalous-backslash-in-string,
api-one-deprecated,
api-one-multi-together,
assignment-from-none,
attribute-deprecated,
class-camelcase,
dangerous-default-value,
dangerous-view-replace-wo-priority,
development-status-allowed,
duplicate-id-csv,
duplicate-key,
duplicate-xml-fields,
duplicate-xml-record-id,
eval-referenced,
eval-used,
incoherent-interpreter-exec-perm,
license-allowed,
manifest-author-string,
manifest-deprecated-key,
manifest-required-author,
manifest-required-key,
manifest-version-format,
method-compute,
method-inverse,
method-required-super,
method-search,
openerp-exception-warning,
pointless-statement,
pointless-string-statement,
print-used,
redundant-keyword-arg,
redundant-modulename-xml,
reimported,
relative-import,
return-in-init,
rst-syntax-error,
sql-injection,
too-few-format-args,
translation-field,
translation-required,
unreachable,
use-vim-comment,
wrong-tabs-instead-of-spaces,
xml-syntax-error,
attribute-string-redundant,
character-not-valid-in-resource-link,
consider-merging-classes-inherited,
context-overridden,
create-user-wo-reset-password,
dangerous-filter-wo-user,
dangerous-qweb-replace-wo-priority,
deprecated-data-xml-node,
deprecated-openerp-xml-node,
duplicate-po-message-definition,
except-pass,
file-not-used,
invalid-commit,
manifest-maintainers-list,
missing-newline-extrafiles,
missing-readme,
missing-return,
odoo-addons-relative-import,
old-api7-method-defined,
po-msgstr-variables,
po-syntax-error,
renamed-field-parameter,
resource-not-exist,
str-format-used,
test-folder-imported,
translation-contains-variable,
translation-positional-used,
unnecessary-utf8-coding-comment,
website-manifest-key-not-valid-uri,
xml-attribute-translatable,
xml-deprecated-qweb-directive,
xml-deprecated-tree-attribute,
external-request-timeout
[REPORTS]
msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
output-format=colorized
reports=no

View File

@@ -1,31 +0,0 @@
target-version = "py310"
fix = true
[lint]
extend-select = [
"B",
"C90",
"E501", # line too long (default 88)
"I", # isort
"UP", # pyupgrade
]
extend-safe-fixes = ["UP008"]
exclude = ["setup/*"]
[format]
exclude = ["setup/*"]
[lint.per-file-ignores]
"__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py
"__manifest__.py" = ["B018"] # useless expression
[lint.isort]
section-order = ["future", "standard-library", "third-party", "odoo", "odoo-addons", "first-party", "local-folder"]
[lint.isort.sections]
"odoo" = ["odoo"]
"odoo-addons" = ["odoo.addons"]
[lint.mccabe]
max-complexity = 16

View File

@@ -13,7 +13,7 @@ Add fields used by several survey addons
* Implementation of theses fields should be in another module
""",
"version": "18.0.1.0.0",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Elabore",
"website": "https://www.elabore.coop",

View File

@@ -1,54 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * survey_base
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-02-17 14:44+0000\n"
"PO-Revision-Date: 2026-02-17 14:44+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_base
#: model:ir.model.fields,field_description:survey_base.field_survey_user_input_line__value_file
msgid "File"
msgstr "Fichier"
#. module: survey_base
#: model:ir.model.fields,field_description:survey_base.field_survey_user_input_line__value_file_fname
msgid "File Name"
msgstr "Nom du fichier"
#. module: survey_base
#: model:ir.model.fields,field_description:survey_base.field_survey_question_answer__record_reference
#: model:ir.model.fields,field_description:survey_base.field_survey_user_input_line__record_reference
msgid "Record"
msgstr "Enregistrement"
#. module: survey_base
#: model:ir.model.fields,field_description:survey_base.field_survey_question_answer__record_reference_model
#: model:ir.model.fields,field_description:survey_base.field_survey_user_input_line__record_reference_model
msgid "Record Model"
msgstr "Modèle de l'enregistrement"
#. module: survey_base
#: model:ir.model.fields,field_description:survey_base.field_survey_question_answer__smart_search
#: model:ir.model.fields,field_description:survey_base.field_survey_user_input_line__smart_search
msgid "Smart Search"
msgstr "Recherche intelligente"
#. module: survey_base
#: model:ir.model,name:survey_base.model_survey_question_answer
msgid "Survey Label"
msgstr "Étiquette du sondage"
#. module: survey_base
#: model:ir.model,name:survey_base.model_survey_user_input_line
msgid "Survey User Input Line"
msgstr "Ligne d'entrée pour l'utilisateur du sondage"

View File

@@ -21,7 +21,7 @@ class SurveyUserInputLine(models.Model):
#record reference fields
record_reference = fields.Many2oneReference(model_field="record_reference_model", string="Record")
record_reference_model = fields.Char('Record Model')
record_reference_model = fields.Char('Record model')
"""set record_reference when saving survey_user_input line
"""

View File

@@ -0,0 +1,109 @@
==========================
Survey contacts generation
==========================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:0a298d1600a5f93ffe77357631c7e799e78b23b84c362b126720e36655dd5227
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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/15.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-15-0/survey-15-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=15.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 <https://github.com/OCA/survey/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 <https://github.com/OCA/survey/issues/new?body=module:%20survey_contact_generation%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Tecnativa
Contributors
~~~~~~~~~~~~
* `Tecnativa <https://www.tecnativa.com>`_
* David Vidal
* Ernesto Tejeda
* Stefan Ungureanu
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 <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-chienandalu|
This module is part of the `OCA/survey <https://github.com/OCA/survey/tree/15.0/survey_contact_generation>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,25 @@
# 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": "16.0.1.0.0",
"development_status": "Beta",
"category": "Marketing/Survey",
"website": "https://github.com/OCA/survey",
"author": "Tecnativa, Odoo Community Association (OCA)",
"maintainers": ["clement_thomas"],
"license": "AGPL-3",
"depends": ["survey","partner_firstname"],
"data": [
'security/ir.model.access.csv',
"views/survey_question_views.xml",
"views/survey_survey_views.xml",
],
"demo": ["demo/survey_contact_generation_demo.xml"],
"assets": {
"web.assets_tests": [
"/survey_contact_generation/static/tests/survey_contact_generation_tour.js",
],
},
}

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Survey-->
<record model="survey.survey" id="survey_contact_creation">
<field name="title">Contact Creation Survey</field>
<field name="access_token">80e5f1e2-1a9d-4c51-8e23-09e93f7fa2c5</field>
<field name="access_mode">public</field>
<field name="users_can_go_back" eval="True" />
<field name="generate_contact" eval="True" />
</record>
<record model="survey.question" id="survey_contact_q0">
<field name="survey_id" ref="survey_contact_creation" />
<field name="sequence">0</field>
<field name="title">Name</field>
<field name="question_type">char_box</field>
<field name="constr_mandatory" eval="True" />
<field name="res_partner_field" ref="base.field_res_partner__name" />
</record>
<record model="survey.question" id="survey_contact_q1">
<field name="survey_id" ref="survey_contact_creation" />
<field name="sequence">1</field>
<field name="title">Email</field>
<field name="question_type">char_box</field>
<field name="res_partner_field" ref="base.field_res_partner__email" />
</record>
<record model="survey.question" id="survey_contact_q2">
<field name="survey_id" ref="survey_contact_creation" />
<field name="sequence">2</field>
<field name="title">Notes</field>
<field name="question_type">text_box</field>
<field name="res_partner_field" ref="base.field_res_partner__comment" />
</record>
<record model="survey.question" id="survey_contact_q3">
<field name="survey_id" ref="survey_contact_creation" />
<field name="sequence">3</field>
<field name="title">Color</field>
<field name="question_type">numerical_box</field>
<field name="res_partner_field" ref="base.field_res_partner__color" />
</record>
<record model="survey.question" id="survey_contact_q4">
<field name="survey_id" ref="survey_contact_creation" />
<field name="sequence">4</field>
<field name="title">Date</field>
<field name="question_type">date</field>
<field name="res_partner_field" ref="base.field_res_partner__date" />
</record>
<record model="survey.question" id="survey_contact_q5">
<field name="survey_id" ref="survey_contact_creation" />
<field name="sequence">4</field>
<field name="title">Country</field>
<field name="question_type">simple_choice</field>
<field name="res_partner_field" ref="base.field_res_partner__country_id" />
</record>
<record model="survey.question.answer" id="survey_contact_q5_sug1">
<field name="question_id" ref="survey_contact_q5" />
<field name="sequence">1</field>
<field name="value">Spain</field>
<field name="res_partner_field_resource_ref" ref="base.es" />
</record>
<record model="survey.question.answer" id="survey_contact_q5_sug2">
<field name="question_id" ref="survey_contact_q5" />
<field name="sequence">2</field>
<field name="value">Romania</field>
<field name="res_partner_field_resource_ref" ref="base.ro" />
</record>
<record model="survey.question" id="survey_contact_q6">
<field name="survey_id" ref="survey_contact_creation" />
<field name="sequence">4</field>
<field name="title">Tags</field>
<field name="question_type">multiple_choice</field>
<field name="res_partner_field" ref="base.field_res_partner__category_id" />
</record>
<record model="survey.question.answer" id="survey_contact_q6_sug1">
<field name="question_id" ref="survey_contact_q6" />
<field name="sequence">1</field>
<field name="value">Vendor</field>
<field
name="res_partner_field_resource_ref"
ref="base.res_partner_category_0"
/>
</record>
<record model="survey.question.answer" id="survey_contact_q6_sug2">
<field name="question_id" ref="survey_contact_q6" />
<field name="sequence">2</field>
<field name="value">Prospects</field>
<field
name="res_partner_field_resource_ref"
ref="base.res_partner_category_2"
/>
</record>
<record model="survey.question.answer" id="survey_contact_q6_sug3">
<field name="question_id" ref="survey_contact_q6" />
<field name="sequence">3</field>
<field name="value">Employees</field>
<field
name="res_partner_field_resource_ref"
ref="base.res_partner_category_3"
/>
</record>
</odoo>

View File

@@ -0,0 +1,168 @@
# 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-14 11:55+0000\n"
"PO-Revision-Date: 2023-06-14 13:58+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 "Campo permitido"
#. module: survey_contact_generation
#: 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
#: model_terms:ir.ui.view,arch_db:survey_contact_generation.survey_question_form
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
#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question_answer__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_question_answer__res_partner_field_resource_ref
msgid "Contact field value"
msgstr ""
#. module: survey_contact_generation
#: model:survey.question,title:survey_contact_generation.survey_contact_q5
msgid "Country"
msgstr ""
#. module: survey_contact_generation
#: model:survey.question,title:survey_contact_generation.survey_contact_q4
msgid "Date"
msgstr "Fecha"
#. module: survey_contact_generation
#: model:survey.question,title:survey_contact_generation.survey_contact_q1
msgid "Email"
msgstr "Correo electrónico"
#. module: survey_contact_generation
#: model:survey.question.answer,value:survey_contact_generation.survey_contact_q6_sug3
msgid "Employees"
msgstr ""
#. 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: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
#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q5
#: model:survey.question,comments_message:survey_contact_generation.survey_contact_q6
msgid "If other, please specify:"
msgstr "Si es otro, especifíquelo:"
#. module: survey_contact_generation
#: model:survey.question,title:survey_contact_generation.survey_contact_q0
msgid "Name"
msgstr "Nombre"
#. module: survey_contact_generation
#: model:survey.question,title:survey_contact_generation.survey_contact_q2
msgid "Notes"
msgstr "Notas"
#. module: survey_contact_generation
#: model:survey.question.answer,value:survey_contact_generation.survey_contact_q6_sug2
msgid "Prospects"
msgstr ""
#. module: survey_contact_generation
#: model:survey.question.answer,value:survey_contact_generation.survey_contact_q5_sug2
msgid "Romania"
msgstr ""
#. module: survey_contact_generation
#: model:survey.question.answer,value:survey_contact_generation.survey_contact_q5_sug1
msgid "Spain"
msgstr ""
#. 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_answer
msgid "Survey Label"
msgstr ""
#. 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"
#. module: survey_contact_generation
#: model:survey.question,title:survey_contact_generation.survey_contact_q6
msgid "Tags"
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
#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q5
#: model:survey.question,validation_error_msg:survey_contact_generation.survey_contact_q6
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
#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q5
#: model:survey.question,constr_error_msg:survey_contact_generation.survey_contact_q6
msgid "This question requires an answer."
msgstr "Esta pregunta requiere una respuesta."
#. module: survey_contact_generation
#: model:survey.question.answer,value:survey_contact_generation.survey_contact_q6_sug1
msgid "Vendor"
msgstr ""

View File

@@ -0,0 +1,64 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * survey_contact_generation
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-19 14:33+0000\n"
"PO-Revision-Date: 2023-09-19 14:33+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 "Champs autorisés"
#. 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
#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question_answer__res_partner_field
msgid "Contact field"
msgstr "Champ contact"
#. module: survey_contact_generation
#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_question_answer__res_partner_field_resource_ref
msgid "Contact field value"
msgstr "Valeur du champ contact"
#. module: survey_contact_generation
#: model:ir.model.fields,field_description:survey_contact_generation.field_survey_survey__generate_contact
msgid "Generate Contact"
msgstr "Générer un contact"
#. 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 "Générer des contacts pour les questionnaires anonymes"
#. module: survey_contact_generation
#: model:ir.model,name:survey_contact_generation.model_survey_question_answer
msgid "Survey Label"
msgstr "Étiquette du questionnaire"
#. module: survey_contact_generation
#: model:ir.model,name:survey_contact_generation.model_survey_question
msgid "Survey Question"
msgstr "Question du questionnaire"
#. module: survey_contact_generation
#: model:ir.model,name:survey_contact_generation.model_survey_user_input
msgid "Survey User Input"
msgstr "Entrée utilisateur du questionnaire"

View File

@@ -1,3 +1,3 @@
from . import survey_question
from . import survey_survey
from . import survey_user_input
from . import survey_user_input_line

View File

@@ -0,0 +1,81 @@
# Copyright 2022 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
type_mapping = {
"char_box": ["char", "text"],
"text_box": ["html"],
"numerical_box": ["integer", "float", "html", "char"],
"date": ["date", "text", "char"],
"datetime": ["datetime", "html", "char"],
"simple_choice": ["many2one", "html", "char"],
"multiple_choice": ["many2many", "html", "char"],
}
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):
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
)
class SurveyQuestionAnswer(models.Model):
_inherit = "survey.question.answer"
@api.model
def default_get(self, fields):
result = super().default_get(fields)
if (
not result.get("res_partner_field")
or "res_partner_field_resource_ref" not in fields
):
return result
partner_field = self.env["ir.model.fields"].browse(result["res_partner_field"])
# Otherwise we'll just use the value (char, text)
if partner_field.ttype not in {"many2one", "many2many"}:
return result
res = self.env[partner_field.relation].search([], limit=1)
if res:
result["res_partner_field_resource_ref"] = "%s,%s" % (
partner_field.relation,
res.id,
)
return result
@api.model
def _selection_res_partner_field_resource_ref(self):
return [(model.model, model.name) for model in self.env["ir.model"].search([])]
res_partner_field = fields.Many2one(related="question_id.res_partner_field")
res_partner_field_resource_ref = fields.Reference(
string="Contact field value",
selection="_selection_res_partner_field_resource_ref",
)
@api.onchange("res_partner_field_resource_ref")
def _onchange_res_partner_field_resource_ref(self):
"""Set the default value as the product name, although we can change it"""
if self.res_partner_field_resource_ref:
self.value = self.res_partner_field_resource_ref.display_name or ""

View File

@@ -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",
)

View File

@@ -0,0 +1,94 @@
# 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):
"""Extract partner values from the answers"""
self.ensure_one()
elegible_inputs = self.user_input_line_ids.filtered(
lambda x: x.question_id.res_partner_field and not x.skipped
)
basic_inputs = elegible_inputs.filtered(
lambda x: x.answer_type not in {"suggestion"}
and x.question_id.res_partner_field.name != "comment"
and not (x.question_id.comments_allowed and x.question_id.comment_count_as_answer and x.question_id.res_partner_field.ttype in ("many2one","many2many")) #exclude comments answer in case of many2one or many2many reference
)
vals = {
line.question_id.res_partner_field.name: line[f"value_{line.answer_type}"]
for line in basic_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
elif line.question_id.res_partner_field.ttype == "many2many":
vals.setdefault(field_name, [])
if line.suggested_answer_id: # exclude "comment" answer
vals[field_name] += [
(4, line.suggested_answer_id.res_partner_field_resource_ref.id)
]
# We'll use the comment field to add any other infos
elif field_name == "comment":
vals.setdefault("comment", "")
value = (
line.suggested_answer_id.value
if line.answer_type == "suggestion"
else line[f"value_{line.answer_type}"]
)
vals["comment"] += f"\n{line.question_id.title}: {value}"
else:
if line.question_id.question_type == "multiple_choice":
if not vals.get(field_name):
vals[field_name] = line.suggested_answer_id.value
else:
vals[field_name] += line.suggested_answer_id.value
else:
vals[field_name] = line.suggested_answer_id.value
return vals
def _create_contact_post_process(self, partner):
"""After creating the lead send an internal message with the input link"""
partner.message_post_with_view(
"mail.message_origin_link",
values={"self": partner, "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 #uncomment to avoid contact generation several times
):
vals = user_input._prepare_partner()
partner = False
email = vals.get("email")
firstname = vals.get("firstname")
lastname = vals.get("lastname")
# check doublon only if email send
if not email:
continue
#search if partner exists with same email, firstname and lastname depending on submitted data
doublon_domain = []
if email:
doublon_domain.append(("email", "ilike", email))
if firstname:
doublon_domain.append(("firstname", "ilike", firstname))
if lastname:
doublon_domain.append(("lastname", "ilike", lastname))
if doublon_domain:
partner = self.env["res.partner"].search(doublon_domain, limit=1)
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})
return super()._mark_done()

View File

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

View File

@@ -0,0 +1,5 @@
* `Tecnativa <https://www.tecnativa.com>`_
* David Vidal
* Ernesto Tejeda
* Stefan Ungureanu

View File

@@ -0,0 +1 @@
This module allows to generate new contacts from surveys answers.

View File

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

View File

@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_ir_model_fields_survey_user,ir.model.fields.survey.user,base.model_ir_model_fields,survey.group_survey_user,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_ir_model_fields_survey_user ir.model.fields.survey.user base.model_ir_model_fields survey.group_survey_user 1 0 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<title>Survey contacts generation</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
@@ -275,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -301,7 +301,7 @@ span.option {
span.pre {
white-space: pre }
span.problematic, pre.problematic {
span.problematic {
color: red }
span.section-subtitle {
@@ -360,105 +360,89 @@ ul.auto-toc {
</style>
</head>
<body>
<div class="document">
<div class="document" id="survey-contacts-generation">
<h1 class="title">Survey contacts generation</h1>
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="survey-xlsx-expand-multiple-choice">
<h1>Survey XLSX - Expand Multiple Choice</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:2ec53fabb2863ebd536f204a7cb4fa4833a634a5711a9e325ed64f50a4c3c4b6
!! source digest: sha256:0a298d1600a5f93ffe77357631c7e799e78b23b84c362b126720e36655dd5227
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/elabore-coop/survey-tools/tree/18.0/survey_xlsx_expand_multiple_choice"><img alt="elabore-coop/survey-tools" src="https://img.shields.io/badge/github-elabore--coop%2Fsurvey--tools-lightgray.png?logo=github" /></a></p>
<p>This module improves the <strong>Survey Results XLSX export</strong> provided by
<tt class="docutils literal">survey_xlsx</tt> for questions that can hold several answers.</p>
<p>By default such questions are exported as a single column containing every
selected value joined together, which is hard to analyse in a spreadsheet.
This module splits them into dedicated columns:</p>
<ul class="simple">
<li><strong>Multiple choice</strong> questions (<em>multiple answers allowed</em>): one column per
possible answer, with <tt class="docutils literal">Oui</tt> / <tt class="docutils literal">Non</tt> as value.</li>
<li><strong>Matrix</strong> questions: one column per matrix row, with the selected option
as value.</li>
</ul>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p>This module relies on report extension hooks that are <strong>not part of the
standard</strong> <tt class="docutils literal">survey_xlsx</tt> yet. They are introduced by this pull request:</p>
<p><a class="reference external" href="https://github.com/elabore-coop/survey/pull/1">https://github.com/elabore-coop/survey/pull/1</a></p>
<p class="last">You must run a <tt class="docutils literal">survey_xlsx</tt> that includes these hooks (the PR branch,
until it is merged upstream). Installed against a plain <tt class="docutils literal">survey_xlsx</tt>,
this module installs without error but the export <strong>silently falls back</strong>
to the default one-column-per-question behaviour.</p>
</div>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/survey/tree/15.0/survey_contact_generation"><img alt="OCA/survey" src="https://img.shields.io/badge/github-OCA%2Fsurvey-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/survey-15-0/survey-15-0-survey_contact_generation"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/survey&amp;target_branch=15.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows to generate new contacts from surveys answers.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
<p>Export the results of a survey as usual:</p>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<p>To configure the contact generation:</p>
<ol class="arabic simple">
<li>Go to <em>Surveys</em> and open a survey.</li>
<li>Print the <em>Survey Results XLSX</em> report.</li>
<li>Go to the configured survey.</li>
<li>In the <em>Contact</em> section of the <em>Options</em> tab, set
<em>Generate Contact</em> on, if you want contacts to be
generated from the answers to this survey.</li>
<li>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.</li>
</ol>
<p>In the generated spreadsheet:</p>
<ul class="simple">
<li>A multiple choice question <tt class="docutils literal">Favorite colors</tt> with options <em>Red</em>, <em>Green</em>
and <em>Blue</em> produces three columns <tt class="docutils literal">Favorite colors / Red</tt>,
<tt class="docutils literal">Favorite colors / Green</tt> and <tt class="docutils literal">Favorite colors / Blue</tt>, each containing
<tt class="docutils literal">Oui</tt> or <tt class="docutils literal">Non</tt>.</li>
<li>A matrix question <tt class="docutils literal">Satisfaction</tt> with rows <em>Dashboards</em> and <em>Customer
relationship</em> produces two columns <tt class="docutils literal">Satisfaction / Dashboards</tt> and
<tt class="docutils literal">Satisfaction / Customer relationship</tt>, each containing the selected
option (e.g. <em>Not satisfied at all</em>).</li>
</ul>
<p>Other question types keep their standard single-column export.</p>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<p>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.</p>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/elabore-coop/survey-tools/issues">GitHub Issues</a>.
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/survey/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/elabore-coop/survey-tools/issues/new?body=module:%20survey_xlsx_expand_multiple_choice%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<a class="reference external" href="https://github.com/OCA/survey/issues/new?body=module:%20survey_contact_generation%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-3">Credits</a></h2>
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-4">Authors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Elabore</li>
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-5">Contributors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.elabore.coop">Elabore</a><ul>
<li>Quentin Mondot</li>
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a><ul>
<li>David Vidal</li>
<li>Ernesto Tejeda</li>
<li>Stefan Ungureanu</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h3>
<p>This module is part of the <a class="reference external" href="https://github.com/elabore-coop/survey-tools/tree/18.0/survey_xlsx_expand_multiple_choice">elabore-coop/survey-tools</a> project on GitHub.</p>
<p>You are welcome to contribute.</p>
</div>
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/chienandalu"><img alt="chienandalu" src="https://github.com/chienandalu.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/survey/tree/15.0/survey_contact_generation">OCA/survey</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>

View File

@@ -0,0 +1,82 @@
odoo.define("survey.tour_test_survey_contact_generation", function (require) {
"use strict";
const tour = require("web_tour.tour");
tour.register(
"test_survey_contact_generation",
{
test: true,
url: "/survey/start/80e5f1e2-1a9d-4c51-8e23-09e93f7fa2c5",
},
[
{
content: "Click on Start",
trigger: "button.btn:contains('Start Survey')",
},
{
content: "Name",
trigger: "div.js_question-wrapper:contains('Name') input",
run: "text My Name",
},
{
content: "Email",
trigger: "div.js_question-wrapper:contains('Email') input",
run: "text survey_contact_generation@test.com",
},
{
content: "Notes",
trigger: "div.js_question-wrapper:contains('Notes') textarea",
run: "text This is a test note",
},
{
content: "Color",
trigger: "div.js_question-wrapper:contains('Color') input",
run: "text 1",
},
{
content: "Date",
trigger: "div.js_question-wrapper:contains('Date') input",
run: "text 01/01/2023",
},
{
content: "Country",
trigger:
"div.js_question-wrapper:contains('Country') label:contains('Romania') i",
run: function () {
$(
"div.js_question-wrapper:contains('Country') label:contains('Romania') i"
).prop("checked", true);
},
},
{
content: "Tags",
trigger:
"div.js_question-wrapper:contains('Tags') label:contains('Prospects') i",
run: function () {
$(
"div.js_question-wrapper:contains('Tags') label:contains('Prospects') i"
).prop("checked", true);
},
},
{
content: "Tags",
trigger:
"div.js_question-wrapper:contains('Tags') label:contains('Vendor') i",
run: function () {
$(
"div.js_question-wrapper:contains('Tags') label:contains('Vendor') i"
).prop("checked", true);
},
},
{
content: "Click Submit",
trigger: "button[value='finish']",
},
{
content: "Thank you",
trigger: "h1:contains('Thank you!')",
},
]
);
});

View File

@@ -0,0 +1 @@
from . import test_survey_contact_generation

View File

@@ -0,0 +1,31 @@
# Copyright 2023 Tecnativa - David Vidal
# Copyright 2023 Tecnativa - Stefan Ungureanu
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo.tests import HttpCase, tagged
from odoo.addons.survey.tests.common import SurveyCase
@tagged("-at_install", "post_install")
class SurveyContactGenerationCase(SurveyCase, HttpCase):
def setUp(self):
"""We run the tour in the setup so we can share the tests case with other
modules"""
super().setUp()
self.survey = self.env.ref("survey_contact_generation.survey_contact_creation")
initial_user_inputs = self.survey.user_input_ids
# Run the survey as a portal user and get the generated quotation
self.start_tour(
f"/survey/start/{self.survey.access_token}",
"test_survey_contact_generation",
)
self.user_input = self.survey.user_input_ids - initial_user_inputs
@tagged("-at_install", "post_install")
class SurveyContactGenerationTests(SurveyContactGenerationCase):
def test_contact_generation(self):
partner = self.env["res.partner"].search(
[("email", "=", "survey_contact_generation@test.com")]
)
self.assertEqual(partner, self.user_input.partner_id)

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="survey_question_form" model="ir.ui.view">
<field name="model">survey.question</field>
<field name="inherit_id" ref="survey.survey_question_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='comments_allowed']/.." position="after">
<group name="contact" string="Contact">
<field name="res_partner_field" widget="selection" />
<field name="allowed_field_ids" invisible="1" />
</group>
</xpath>
<xpath expr="//field[@name='suggested_answer_ids']" position="attributes">
<attribute
name="context"
>{'default_question_id': active_id, 'default_res_partner_field': res_partner_field}</attribute>
</xpath>
<xpath
expr="//field[@name='suggested_answer_ids']//field[@name='value']"
position="after"
>
<field name="res_partner_field" invisible="1" />
<field
name="res_partner_field_resource_ref"
readonly="False"
options="{'hide_model': True, 'no_create': True, 'no_edit': True, 'no_open': True}"
attrs="{'column_invisible': [('parent.res_partner_field', '=', False)]}"
/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="survey_form" model="ir.ui.view">
<field name="model">survey.survey</field>
<field name="inherit_id" ref="survey.survey_survey_view_form" />
<field name="arch" type="xml">
<group name="options" position="inside">
<group name="contact_options" string="Contact">
<field name="generate_contact" />
</group>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,105 @@
=======================
Survey leads generation
=======================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:72ceb1068020aaec4baba6df86a6b1b024793db57bdfc2cec8374da9cac8d031
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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/15.0/survey_crm_generation
:alt: OCA/survey
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/survey-15-0/survey-15-0-survey_crm_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=15.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows to generate leads/opportunities from surveys.
**Table of contents**
.. contents::
:local:
Configuration
=============
To configure the leads/opportunities generation:
#. Go to the configured survey.
#. In the *CRM* section of the *Options* tab, set *Generate leads* on.
#. Optionally you can set default tags for the generated leads.
#. You can set the crm team to assign the leads to.
The questions marked to be shown in the lead description will be shown there.
Usage
=====
Once the surveys are submited a lead/opportunity (depending on the default options for
the company) will be generated with a link to the answers.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/survey/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 <https://github.com/OCA/survey/issues/new?body=module:%20survey_crm_generation%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Tecnativa
Contributors
~~~~~~~~~~~~
* `Tecnativa <https://www.tecnativa.com>`_
* David Vidal
* Stefan ungureanu
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 <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-chienandalu|
This module is part of the `OCA/survey <https://github.com/OCA/survey/tree/15.0/survey_crm_generation>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,26 @@
# Copyright 2023 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Survey leads generation",
"summary": "Generate CRM leads/opportunities from surveys",
"version": "16.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", "crm"],
"data": [
"views/survey_survey_views.xml",
"views/survey_question_views.xml",
"views/survey_user_input_views.xml",
"views/crm_lead_views.xml",
],
"demo": ["demo/survey_crm_demo.xml"],
"assets": {
"web.assets_tests": [
"/survey_crm_generation/static/tests/survey_crm_generation_tour.js",
],
},
}

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record model="crm.tag" id="tag_survey_leads">
<field name="name">Survey Leads</field>
</record>
<record model="crm.tag" id="tag_oca_partnership">
<field name="name">OCA Partnership</field>
</record>
<!-- Sales Team -->
<record model="crm.team" id="oca_partnership_leads">
<field name="name">OCA Partnership</field>
</record>
<!-- Survey -->
<record model="survey.survey" id="become_partner">
<field name="title">Become OCA Partner</field>
<field name="description">Be part of the Odoo Community!</field>
<field name="access_token">08b4db21-66cc-4c69-a712-cc364c54902c</field>
<field name="access_mode">public</field>
<field name="generate_leads" eval="True" />
<field name="crm_team_id" ref="oca_partnership_leads" />
<field
name="crm_tag_ids"
eval="[(6,0,[ref('survey_crm_generation.tag_oca_partnership'), ref('survey_crm_generation.tag_survey_leads')])]"
/>
<field name="users_can_go_back" eval="True" />
</record>
<record model="survey.question" id="survey_oca_q0">
<field name="survey_id" ref="become_partner" />
<field name="sequence">0</field>
<field name="title">E-mail address</field>
<field name="question_type">text_box</field>
<field name="show_in_lead_description" eval="True" />
<field name="constr_mandatory" eval="True" />
</record>
<record model="survey.question" id="survey_oca_q1">
<field name="survey_id" ref="become_partner" />
<field name="sequence">1</field>
<field name="title">Your company name?</field>
<field name="question_type">text_box</field>
<field name="show_in_lead_description" eval="True" />
<field name="constr_mandatory" eval="True" />
</record>
<record model="survey.question" id="survey_oca_q3">
<field name="survey_id" ref="become_partner" />
<field name="sequence">2</field>
<field name="title">And your name?</field>
<field name="question_type">text_box</field>
<field name="show_in_lead_description" eval="True" />
<field name="constr_mandatory" eval="True" />
</record>
</odoo>

View File

@@ -0,0 +1,137 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * survey_crm_generation
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-06-01 09:49+0000\n"
"PO-Revision-Date: 2023-06-01 12:07+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0.1\n"
#. module: survey_crm_generation
#: model:survey.question,title:survey_crm_generation.survey_oca_q3
msgid "And your name?"
msgstr "¿Y tu nombre? "
#. module: survey_crm_generation
#: model:survey.survey,description:survey_crm_generation.become_partner
msgid "Be part of the Odoo Community!"
msgstr "¡Se parte de la comunidad de Odoo!"
#. module: survey_crm_generation
#: model:survey.survey,title:survey_crm_generation.become_partner
msgid "Become OCA Partner"
msgstr "Conviértete en miembro OCA"
#. module: survey_crm_generation
#: model_terms:ir.ui.view,arch_db:survey_crm_generation.survey_form
#: model_terms:ir.ui.view,arch_db:survey_crm_generation.survey_question_form
msgid "CRM"
msgstr "CRM"
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_survey__crm_tag_ids
msgid "Crm Tag"
msgstr "Etiqueta CRM"
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_survey__crm_team_id
msgid "Crm Team"
msgstr "Equipo CRM"
#. module: survey_crm_generation
#: model:survey.question,title:survey_crm_generation.survey_oca_q0
msgid "E-mail address"
msgstr "Dirección de correo electrónico"
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_survey__generate_leads
msgid "Generate Leads"
msgstr "Generación de iniciativa"
#. module: survey_crm_generation
#: model:ir.model.fields,help:survey_crm_generation.field_survey_survey__generate_leads
msgid "Generate leads/opportunities linked to the generated quotations"
msgstr "Generar iniciativas/oportunidades vinculadas a las ofertas generadas"
#. module: survey_crm_generation
#: model:survey.question,comments_message:survey_crm_generation.survey_oca_q0
#: model:survey.question,comments_message:survey_crm_generation.survey_oca_q1
#: model:survey.question,comments_message:survey_crm_generation.survey_oca_q3
msgid "If other, please specify:"
msgstr "Si es otro, especifíquelo:"
#. module: survey_crm_generation
#: model:ir.model,name:survey_crm_generation.model_crm_lead
msgid "Lead/Opportunity"
msgstr "Iniciativa/Oportunidad"
#. module: survey_crm_generation
#: model:crm.tag,name:survey_crm_generation.tag_oca_partnership
#: model:crm.team,name:survey_crm_generation.oca_partnership_leads
msgid "OCA Partnership"
msgstr "Asociación OCA"
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_user_input__opportunity_id
msgid "Opportunity"
msgstr "Oportunidad"
#. module: survey_crm_generation
#: model:ir.model.fields,help:survey_crm_generation.field_survey_survey__crm_tag_ids
msgid "Set the default crm tags in the generated leads/opportunities"
msgstr "Establecer las etiquetas crm por defecto en las iniciativas/oportunidades generadas"
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_question__show_in_lead_description
msgid "Show In Lead Description"
msgstr "Mostrar en la descripción de la iniciativa"
#. module: survey_crm_generation
#: model:ir.model,name:survey_crm_generation.model_survey_survey
msgid "Survey"
msgstr "Encuesta"
#. module: survey_crm_generation
#: model:crm.tag,name:survey_crm_generation.tag_survey_leads
msgid "Survey Leads"
msgstr "Encuesta de la iniciativa"
#. module: survey_crm_generation
#: model:ir.model,name:survey_crm_generation.model_survey_question
msgid "Survey Question"
msgstr "Pregunta de la encuesta"
#. module: survey_crm_generation
#: model:ir.model,name:survey_crm_generation.model_survey_user_input
#: model:ir.model.fields,field_description:survey_crm_generation.field_crm_lead__survey_user_input_id
msgid "Survey User Input"
msgstr "Respuestas de los usuarios"
#. module: survey_crm_generation
#: model:survey.question,validation_error_msg:survey_crm_generation.survey_oca_q0
#: model:survey.question,validation_error_msg:survey_crm_generation.survey_oca_q1
#: model:survey.question,validation_error_msg:survey_crm_generation.survey_oca_q3
msgid "The answer you entered is not valid."
msgstr "La respuesta que has introducido no es válida."
#. module: survey_crm_generation
#: model:survey.question,constr_error_msg:survey_crm_generation.survey_oca_q0
#: model:survey.question,constr_error_msg:survey_crm_generation.survey_oca_q1
#: model:survey.question,constr_error_msg:survey_crm_generation.survey_oca_q3
msgid "This question requires an answer."
msgstr "Esta pregunta requiere una respuesta."
#. module: survey_crm_generation
#: model:survey.question,title:survey_crm_generation.survey_oca_q1
msgid "Your company name?"
msgstr "¿El nombre de su empresa?"

View File

@@ -0,0 +1,85 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * survey_crm_generation
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-10-24 08:50+0000\n"
"PO-Revision-Date: 2023-10-24 08:50+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_crm_generation
#: model_terms:ir.ui.view,arch_db:survey_crm_generation.survey_form
#: model_terms:ir.ui.view,arch_db:survey_crm_generation.survey_question_form
msgid "CRM"
msgstr ""
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_survey__crm_tag_ids
msgid "Crm Tag"
msgstr "Étiquette CRM"
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_survey__crm_team_id
msgid "Crm Team"
msgstr "Équipe commerciale"
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_survey__generate_leads
msgid "Generate Leads"
msgstr "Générer des pistes"
#. module: survey_crm_generation
#: model:ir.model.fields,help:survey_crm_generation.field_survey_survey__generate_leads
msgid "Generate leads/opportunities linked to the generated quotations"
msgstr "Générer des pistes / opportunités liées aux devis"
#. module: survey_crm_generation
#: model:ir.model,name:survey_crm_generation.model_crm_lead
msgid "Lead/Opportunity"
msgstr "Piste/Opportunité"
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_user_input__opportunity_id
msgid "Opportunity"
msgstr "Opportunité"
#. module: survey_crm_generation
#: model:ir.model.fields,help:survey_crm_generation.field_survey_survey__crm_tag_ids
msgid "Set the default crm tags in the generated leads/opportunities"
msgstr "Attribuer les étiquettes par défault dans les pistes générées"
#. module: survey_crm_generation
#: model:ir.model.fields,field_description:survey_crm_generation.field_survey_question__show_in_lead_description
msgid "Show In Lead Description"
msgstr "Montrer dans la description de la piste CRM"
#. module: survey_crm_generation
#: model:ir.model,name:survey_crm_generation.model_survey_survey
msgid "Survey"
msgstr "Questionnaire"
#. module: survey_crm_generation
#: model:ir.model,name:survey_crm_generation.model_survey_question
msgid "Survey Question"
msgstr "Question du questionnaire"
#. module: survey_crm_generation
#: model:ir.model,name:survey_crm_generation.model_survey_user_input
#: model:ir.model.fields,field_description:survey_crm_generation.field_crm_lead__survey_user_input_id
msgid "Survey User Input"
msgstr "Entrée utilisateur du questionnaire"
#. module: survey_crm_generation
#. odoo-python
#: code:addons/survey_crm_generation/models/survey_user_input.py:0
#, python-format
msgid "Survey answers: "
msgstr "Réponses au questionnaire : "

View File

@@ -0,0 +1,4 @@
from . import crm_lead
from . import survey_question
from . import survey_survey
from . import survey_user_input

View File

@@ -0,0 +1,9 @@
# Copyright 2023 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class CrmLead(models.Model):
_inherit = "crm.lead"
survey_user_input_id = fields.Many2one(comodel_name="survey.user_input")

View File

@@ -0,0 +1,9 @@
# Copyright 2022 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class SurveyQuestion(models.Model):
_inherit = "survey.question"
show_in_lead_description = fields.Boolean()

View File

@@ -0,0 +1,16 @@
# 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_leads = fields.Boolean(
help="Generate leads/opportunities linked to the generated quotations",
)
crm_tag_ids = fields.Many2many(
comodel_name="crm.tag",
help="Set the default crm tags in the generated leads/opportunities",
)
crm_team_id = fields.Many2one(comodel_name="crm.team")

View File

@@ -0,0 +1,77 @@
# Copyright 2022 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, _
class SurveyUserInput(models.Model):
_inherit = "survey.user_input"
opportunity_id = fields.Many2one(comodel_name="crm.lead")
def _prepare_opportunity(self):
return {
"name": self.survey_id.title,
"tag_ids": [(6, 0, self.survey_id.crm_tag_ids.ids)],
"partner_id": self.partner_id.id,
"user_id": self.survey_id.crm_team_id.user_id.id,
"team_id": self.survey_id.crm_team_id.id,
"company_id": self.create_uid.company_id.id,
"survey_user_input_id": self.id,
"description": self._prepare_lead_description(),
"type": "lead"
}
def _prepare_lead_description(self):
"""We can have surveys without partner. It's handy to have some relevant info
in the description although the answers are linked themselves.
:return str: description for the lead
"""
relevant_answers = self.user_input_line_ids.filtered(
lambda x: not x.skipped and x.question_id.show_in_lead_description
)
li = ''
for answer in relevant_answers:
li += '<li>'
if answer.answer_type == "suggestion":
answer_value = answer.suggested_answer_id
else:
answer_value = answer[f'value_{answer.answer_type}']
#case of value Models
if isinstance(answer_value,models.Model):
# case of Multi Models
if len(answer_value._ids) > 1:
ul2 = f'{answer.question_id.title}: <ul>'
for answer_value_object in answer_value:
ul2 += '<li>'+f"{answer_value_object.display_name}"+'</li>'
ul2 += '</ul>'
li += ul2
# case of One Models
else:
li += f"{answer.question_id.title}: {answer_value.display_name}"
else:
# case of string value
li += f"{answer.question_id.title}: {answer_value}"
li += '</li>'
description = '<u>'+_('Survey answers: ')+"</u><ul>"+li+"</ul>"
return description
def _create_opportunity_post_process(self):
"""After creating the lead send an internal message with the input link"""
self.opportunity_id.message_post_with_view(
"mail.message_origin_link",
values={"self": self.opportunity_id, "origin": self},
subtype_id=self.env.ref("mail.mt_note").id,
)
def _mark_done(self):
"""Generate the opportunity when the survey is submitted"""
res = super()._mark_done()
if not self.survey_id.generate_leads:
return res
vals = self._prepare_opportunity()
self.opportunity_id = self.env["crm.lead"].sudo().create(vals)
self._create_opportunity_post_process()
return res

View File

@@ -0,0 +1,8 @@
To configure the leads/opportunities generation:
#. Go to the configured survey.
#. In the *CRM* section of the *Options* tab, set *Generate leads* on.
#. Optionally you can set default tags for the generated leads.
#. You can set the crm team to assign the leads to.
The questions marked to be shown in the lead description will be shown there.

View File

@@ -0,0 +1,4 @@
* `Tecnativa <https://www.tecnativa.com>`_
* David Vidal
* Stefan ungureanu

View File

@@ -0,0 +1 @@
This module allows to generate leads/opportunities from surveys.

View File

@@ -0,0 +1,2 @@
Once the surveys are submited a lead/opportunity (depending on the default options for
the company) will be generated with a link to the answers.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<title>Survey leads generation</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
@@ -275,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -301,7 +301,7 @@ span.option {
span.pre {
white-space: pre }
span.problematic, pre.problematic {
span.problematic {
color: red }
span.section-subtitle {
@@ -360,81 +360,84 @@ ul.auto-toc {
</style>
</head>
<body>
<div class="document">
<div class="document" id="survey-leads-generation">
<h1 class="title">Survey leads generation</h1>
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="survey-xlsx-extra-fields-bridge">
<h1>Survey XLSX - Extra Fields Bridge</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8baa47af03e5b4b4e70ca6db224a5ac3e73aa66f287c42053a9a8f631efd10c2
!! source digest: sha256:72ceb1068020aaec4baba6df86a6b1b024793db57bdfc2cec8374da9cac8d031
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/elabore-coop/survey-tools/tree/18.0/survey_xlsx_extra_fields"><img alt="elabore-coop/survey-tools" src="https://img.shields.io/badge/github-elabore--coop%2Fsurvey--tools-lightgray.png?logo=github" /></a></p>
<p>This is a <strong>bridge module</strong> between <tt class="docutils literal">survey_xlsx_expand_multiple_choice</tt>
and <tt class="docutils literal">survey_extra_fields</tt>.</p>
<p><tt class="docutils literal">survey_extra_fields</tt> adds a <em>File</em> question type, whose answers are
uploaded attachments that cannot be represented in a spreadsheet cell. This
module excludes those <em>File</em> questions from the <strong>Survey Results XLSX
export</strong>: they get no column at all, instead of an unusable one.</p>
<p>It installs automatically (<tt class="docutils literal">auto_install</tt>) as soon as both
<tt class="docutils literal">survey_xlsx_expand_multiple_choice</tt> and <tt class="docutils literal">survey_extra_fields</tt> are
installed, and is uninstalled when either of them is removed. There is
nothing to configure.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p>The exclusion is implemented through the report extension hooks provided
by <tt class="docutils literal">survey_xlsx_expand_multiple_choice</tt>, which itself relies on hooks
added to <tt class="docutils literal">survey_xlsx</tt> by this pull request:</p>
<p><a class="reference external" href="https://github.com/elabore-coop/survey/pull/1">https://github.com/elabore-coop/survey/pull/1</a></p>
<p class="last">Without those hooks, <em>File</em> questions are not filtered out of the export.</p>
</div>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/survey/tree/15.0/survey_crm_generation"><img alt="OCA/survey" src="https://img.shields.io/badge/github-OCA%2Fsurvey-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/survey-15-0/survey-15-0-survey_crm_generation"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/survey&amp;target_branch=15.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows to generate leads/opportunities from surveys.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-5">Maintainers</a></li>
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<p>To configure the leads/opportunities generation:</p>
<ol class="arabic simple">
<li>Go to the configured survey.</li>
<li>In the <em>CRM</em> section of the <em>Options</em> tab, set <em>Generate leads</em> on.</li>
<li>Optionally you can set default tags for the generated leads.</li>
<li>You can set the crm team to assign the leads to.</li>
</ol>
<p>The questions marked to be shown in the lead description will be shown there.</p>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<p>Once the surveys are submited a lead/opportunity (depending on the default options for
the company) will be generated with a link to the answers.</p>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/elabore-coop/survey-tools/issues">GitHub Issues</a>.
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/survey/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/elabore-coop/survey-tools/issues/new?body=module:%20survey_xlsx_extra_fields%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<a class="reference external" href="https://github.com/OCA/survey/issues/new?body=module:%20survey_crm_generation%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-2">Credits</a></h2>
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-3">Authors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Elabore</li>
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-4">Contributors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.elabore.coop">Elabore</a><ul>
<li>Quentin Mondot</li>
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a><ul>
<li>David Vidal</li>
<li>Stefan ungureanu</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-5">Maintainers</a></h3>
<p>This module is part of the <a class="reference external" href="https://github.com/elabore-coop/survey-tools/tree/18.0/survey_xlsx_extra_fields">elabore-coop/survey-tools</a> project on GitHub.</p>
<p>You are welcome to contribute.</p>
</div>
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/chienandalu"><img alt="chienandalu" src="https://github.com/chienandalu.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/survey/tree/15.0/survey_crm_generation">OCA/survey</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>

View File

@@ -0,0 +1,48 @@
odoo.define(
"survey_crm_generation.tour_test_survey_crm_generation",
function (require) {
"use strict";
const tour = require("web_tour.tour");
tour.register(
"test_survey_crm_generation",
{
test: true,
url: "/survey/start/08b4db21-66cc-4c69-a712-cc364c54902c",
},
[
{
content: "Start Survey",
trigger: "button.btn:contains('Start Survey')",
},
{
content: "E-mail address",
trigger:
"div.js_question-wrapper:contains('E-mail address') textarea",
run: "text test@test.com",
},
{
content: "Your company name?",
trigger:
"div.js_question-wrapper:contains('Your company name?') textarea",
run: "text Tecnativa",
},
{
content: "And your name?",
trigger:
"div.js_question-wrapper:contains('And your name?') textarea",
run: "text Tecnativa",
},
{
content: "Click Submit",
trigger: "button[value='finish']",
},
{
content: "Thank you",
trigger: "h1:contains('Thank you!')",
},
]
);
}
);

View File

@@ -0,0 +1 @@
from . import test_survey_crm_sale_generation

View File

@@ -0,0 +1,49 @@
# Copyright 2023 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from markupsafe import Markup
from odoo.tests import HttpCase, tagged
from odoo.addons.survey.tests.common import SurveyCase
@tagged("-at_install", "post_install")
class SurveyCrmGenerationCase(SurveyCase, HttpCase):
def setUp(self):
"""We run the tour in the setup so we can share the tests case with other
modules"""
super().setUp()
self.oca_leads = self.env.ref("survey_crm_generation.oca_partnership_leads")
self.survey = self.env.ref("survey_crm_generation.become_partner")
initial_user_inputs = self.survey.user_input_ids
# Run the survey as a portal user and get the generated quotation
self.start_tour(
f"/survey/start/{self.survey.access_token}",
"test_survey_crm_generation",
login="portal",
)
self.user_input = self.survey.user_input_ids - initial_user_inputs
self.generated_lead = self.user_input.opportunity_id
@tagged("-at_install", "post_install")
class SurveyCrmGenerationTests(SurveyCrmGenerationCase):
def test_lead_generation(self):
self.assertFalse(self.generated_lead.stage_id.is_won)
self.assertEqual(self.generated_lead.team_id, self.oca_leads)
self.assertEqual(
self.generated_lead.tag_ids,
(
self.env.ref("survey_crm_generation.tag_oca_partnership")
+ self.env.ref("survey_crm_generation.tag_survey_leads")
),
)
expected_lead_description = Markup(
"<p>E-mail address: test@test.com\n"
"Your company name?: Tecnativa\n"
"And your name?: Tecnativa</p>"
)
self.assertEqual(
self.generated_lead.description,
expected_lead_description,
)

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="crm_lead_view_form" model="ir.ui.view">
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_lead_view_form" />
<field name="arch" type="xml">
<field name="tag_ids" position="after">
<field
string="Created from survey"
name="survey_user_input_id"
attrs="{'invisible': [('survey_user_input_id', '=', False)]}"
readonly="1"
/>
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="survey_question_form" model="ir.ui.view">
<field name="model">survey.question</field>
<field name="inherit_id" ref="survey.survey_question_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='comments_allowed']/.." position="after">
<group name="crm" string="CRM">
<field
name="show_in_lead_description"
attrs="{'invisible': [('question_type', 'in', ['matrix'])]}"
/>
</group>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="survey_form" model="ir.ui.view">
<field name="model">survey.survey</field>
<field name="inherit_id" ref="survey.survey_survey_view_form" />
<field name="arch" type="xml">
<group name="options" position="inside">
<group name="crm_options" string="CRM">
<field name="generate_leads" />
<field
name="crm_team_id"
attrs="{'invisible': [('generate_leads', '=', False)]}"
/>
<field
name="crm_tag_ids"
widget="many2many_tags"
attrs="{'invisible': [('generate_leads', '=', False)]}"
/>
</group>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record model="ir.ui.view" id="survey_user_input_view_form">
<field name="model">survey.user_input</field>
<field name="inherit_id" ref="survey.survey_user_input_view_form" />
<field name="arch" type="xml">
<field name="partner_id" position="before">
<field
name="opportunity_id"
attrs="{'invisible': [('opportunity_id', '=', False)]}"
/>
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,25 @@
# Copyright 2016-2020 Akretion France (<https://www.akretion.com>)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Survey lead generation attachment",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Elabore",
'summary': 'Link Attachments from Surveys to generated leads',
'description': """
Link Attachments from Surveys to generated leads
----------------------------------------------------
* Create new attachments on lead creation, based on attached file of survey answer (survey.user_input.line)
""",
"website": "https://www.elabore.coop",
"category": "",
"depends": ["survey_base","survey_crm_generation"],
"data": [
],
"installable": True,
"auto_install":True
}

View File

@@ -0,0 +1 @@
from . import survey_user_input

View File

@@ -0,0 +1,32 @@
import logging
import textwrap
import uuid
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo.tools import float_is_zero
_logger = logging.getLogger(__name__)
class SurveyUserInput(models.Model):
_inherit = 'survey.user_input'
def _mark_done(self):
"""Copy attachments to crm lead"""
res = super()._mark_done()
for user_input in self:
if user_input.survey_id.generate_leads and user_input.opportunity_id:
for user_input_line in user_input.user_input_line_ids:
if user_input_line.value_file:
self.env['ir.attachment'].create({
'res_model':'crm.lead',
'res_id':user_input.opportunity_id.id,
'name': user_input_line.value_file_fname,
'datas': user_input_line.value_file,
'type': 'binary'
})
return res

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,26 @@
# Copyright 2016-2020 Akretion France (<https://www.akretion.com>)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Survey Crm Generation Training",
'summary': 'Customize lead creation from survey according to trainings',
'description': """
Customize lead creation from survey according to trainings
----------------------------------------------------
* add event type in crm.lead
* Copy event type selected in survey answer, to created lead
""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Elabore",
"website": "https://www.elabore.coop",
"category": "",
"depends": ["event","survey_crm_generation","survey_event_registration_generation","survey_event_base"],
"data": [
"views/crm_lead_views.xml",
],
"installable": True,
"auto_install":True
}

View File

@@ -0,0 +1,53 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * survey_crm_generation_training
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-04 10:52+0000\n"
"PO-Revision-Date: 2024-12-04 10:52+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_crm_generation_training
#: model_terms:ir.ui.view,arch_db:survey_crm_generation_training.crm_lead_view_for_crm_generation_training
msgid ""
"<span class=\"o_stat_value\">\n"
" Responses\n"
" </span>"
msgstr ""
"<span class=\"o_stat_value\">\n"
" Réponses\n"
" </span>"
#. module: survey_crm_generation_training
#: model_terms:ir.ui.view,arch_db:survey_crm_generation_training.view_crm_case_leads_filter_survey_crm_generation_training
#: model_terms:ir.ui.view,arch_db:survey_crm_generation_training.view_crm_case_opportunities_filter_survey_crm_generation_training
msgid "Event type"
msgstr "Formation(s)"
#. module: survey_crm_generation_training
#: model:ir.model.fields,field_description:survey_crm_generation_training.field_crm_lead__event_type_ids
msgid "Formation"
msgstr ""
#. module: survey_crm_generation_training
#: model:ir.model,name:survey_crm_generation_training.model_crm_lead
msgid "Lead/Opportunity"
msgstr "Piste/Opportunité"
#. module: survey_crm_generation_training
#: model:ir.model,name:survey_crm_generation_training.model_survey_user_input
msgid "Survey User Input for custom matrix"
msgstr "Entrée des utilisateurs de l'enquête pour la matrice personnalisée"
#. module: survey_crm_generation_training
#: model_terms:ir.ui.view,arch_db:survey_crm_generation_training.crm_lead_view_for_crm_generation_training
msgid "View survey answer that created this lead"
msgstr "Voir les réponses aux questionnaire qui ont créé cette piste"

View File

@@ -0,0 +1,2 @@
from . import crm_lead
from . import survey_user_input

View File

@@ -0,0 +1,23 @@
# Copyright 2023 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class CrmLead(models.Model):
_inherit = "crm.lead"
event_type_ids = fields.Many2many('event.type', string='Formation')
def action_view_survey_user_input_id(self):
form_view_id = self.env.ref('survey.survey_user_input_view_form').id
if self.survey_user_input_id:
action = self.env["ir.actions.actions"]._for_xml_id("survey.action_survey_user_input")
action['res_id'] = self.survey_user_input_id.id
action['domain'] = [('id', '=', self.survey_user_input_id.id)]
action['view_type'] = 'form'
action['view_mode'] = 'form'
action['binding_view_types'] = 'form'
action['view_id'] = form_view_id
action['views'] = [(form_view_id, 'form')]
return action

View File

@@ -0,0 +1,22 @@
# Copyright 2022 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, _, Command
class SurveyUserInput(models.Model):
_inherit = "survey.user_input"
def _prepare_opportunity(self):
res = super(SurveyUserInput, self)._prepare_opportunity()
#if answer (survey_user_input) contains event_type_ids, copy it in lead.
res["event_type_ids"] = [Command.set(self.event_type_ids.ids)]
# use survey responsible as seller instead of manager of sale department
if self.survey_id.user_id:
res["user_id"] = self.survey_id.user_id.id
return res

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_crm_case_opportunities_filter_survey_crm_generation_training" model="ir.ui.view">
<field name="name">crm.lead.search.opportunity.crm.generation.training"</field>
<field name="inherit_id" ref="crm.view_crm_case_opportunities_filter" />
<field name="model">crm.lead</field>
<field name="arch" type="xml">
<filter name="salesperson" position="before">
<filter string="Event type" name="event_type" context="{'group_by':'event_type_ids'}" />
</filter>
<field name="tag_ids" position="before">
<field name="event_type_ids" />
</field>
</field>
</record>
<record id="view_crm_case_leads_filter_survey_crm_generation_training" model="ir.ui.view">
<field name="name">crm.lead.search.leads.crm.generation.training"</field>
<field name="inherit_id" ref="crm.view_crm_case_leads_filter" />
<field name="model">crm.lead</field>
<field name="arch" type="xml">
<filter name="salesperson" position="before">
<filter string="Event type" name="event_type" context="{'group_by':'event_type_ids'}" />
</filter>
<field name="tag_ids" position="before">
<field name="event_type_ids" />
</field>
</field>
</record>
<record id="crm_lead_view_for_crm_generation_training" model="ir.ui.view">
<field name="model">crm.lead</field>
<field name="name">crm.lead.crm.generation.training</field>
<field name="inherit_id" ref="crm.crm_lead_view_form" />
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button class="oe_stat_button"
name="action_view_survey_user_input_id"
type="object"
icon="fa-wpforms"
help="View survey answer that created this lead"
attrs="{'invisible': [('survey_user_input_id', '=', False)]}"
>
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
Responses
</span>
</div>
</button>
</div>
<group name="lead_priority" position="after">
<group>
<field
name="event_type_ids"
widget="many2many_tags"
/>
</group>
</group>
</field>
</record>
<!-- CRM OPPORTUNITIES TREE VIEW -->
<record id="crm_case_tree_view_oppor_survey_crm_generation_training" model="ir.ui.view">
<field name="name">crm.lead.tree.opportunity.survey.crm.generation.training</field>
<field name="model">crm.lead</field>
<field name="priority">1</field>
<field name="inherit_id" ref="crm.crm_case_tree_view_oppor" />
<field name="arch" type="xml">
<field name="name" position="after">
<field name="event_type_ids" widget="many2many_tags" />
</field>
</field>
</record>
<!-- CRM OPPORTUNITIES TREE VIEW -->
<record id="crm_case_tree_view_leads_survey_crm_generation_training" model="ir.ui.view">
<field name="name">crm.case.tree.view.leads.survey.crm.generation.training</field>
<field name="model">crm.lead</field>
<field name="priority">1</field>
<field name="inherit_id" ref="crm.crm_case_tree_view_leads" />
<field name="arch" type="xml">
<field name="name" position="after">
<field name="event_type_ids" widget="many2many_tags" />
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,23 @@
# Copyright 2016-2020 Akretion France (<https://www.akretion.com>)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Survey event base",
'summary': 'Add field to reference events and product events in servey answers (survey.user_input)',
'description': """
Add field to reference events and product events in servey answers (survey.user_input)
----------------------------------------------------
*
""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Elabore",
"website": "https://www.elabore.coop",
"category": "",
"depends": ["event","survey_base"],
"data": [
],
"installable": True,
}

View File

@@ -0,0 +1 @@
from . import survey_user_input

View File

@@ -0,0 +1,61 @@
import logging
import textwrap
import uuid
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo.tools import float_is_zero
_logger = logging.getLogger(__name__)
class SurveyUserInput(models.Model):
_inherit = 'survey.user_input'
events_ids = fields.Many2many('event.event', string='Events', compute="compute_events_ids", search="search_events_ids") #related events
event_type_ids = fields.Many2many('event.type', string='Formations', compute="compute_event_type_ids", search="search_event_type_ids") #related event products
def search_events_ids(self, operator, value):
user_input_ids = set()
user_input_lines = self.env['survey.user_input.line'].search([('record_reference_model','=','event.event'),('record_reference','=', value)])
for user_input_line in user_input_lines:
user_input_ids.add(user_input_line.user_input_id.id)
return [('id',operator,list(user_input_ids))]
@api.depends('user_input_line_ids')
def compute_events_ids(self):
"""get all answers of type "event.event"
"""
for user_input in self:
event_ids = []
for user_input in self:
for user_input_line in user_input.user_input_line_ids:
if user_input_line.record_reference_model == 'event.event':
event_ids.append(user_input_line.record_reference)
user_input.events_ids = event_ids
def search_event_type_ids(self, operator, value):
user_input_ids = set()
user_input_lines = self.env['survey.user_input.line'].search([('record_reference_model','=','event.type'),('record_reference','=', value)])
for user_input_line in user_input_lines:
user_input_ids.add(user_input_line.user_input_id.id)
return [('id',operator,list(user_input_ids))]
@api.depends('user_input_line_ids')
def compute_event_type_ids(self):
"""get all answers of type "event.type"
"""
for user_input in self:
event_type_ids = []
for user_input in self:
for user_input_line in user_input.user_input_line_ids:
if user_input_line.record_reference_model == 'event.type':
event_type_ids.append(user_input_line.record_reference)
user_input.event_type_ids = event_type_ids

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,19 @@
# Copyright 2016-2020 Akretion France (<https://www.akretion.com>)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Survey event registration generation",
"version": "16.0.0.0.0",
"license": "AGPL-3",
"author": "Elabore",
"website": "https://www.elabore.coop",
"category": "",
"depends": ["survey", "survey_base"],
"data": [
'security/ir.model.access.csv',
'views/survey_question_views.xml',
'views/survey_survey_views.xml',
],
"installable": True,
}

View File

@@ -0,0 +1,3 @@
from . import survey_user_input
from . import survey_survey
from . import survey_question

View File

@@ -0,0 +1,38 @@
from email.policy import default
from odoo import models, fields, api
class SurveyQuestion(models.Model):
_inherit = 'survey.question'
event_registration_allowed_field_ids = fields.Many2many(
comodel_name="ir.model.fields",
compute="_compute_event_registration_allowed_field_ids",
) #fields of event registration, proposed in question, to associate answer to good event registration field, during event registration creation
event_registration_field = fields.Many2one(
string="Event registration field",
comodel_name="ir.model.fields",
domain="[('id', 'in', event_registration_allowed_field_ids)]",
) #field of event registration selected, used in event registration creation
@api.depends("question_type")
def _compute_event_registration_allowed_field_ids(self):
"""propose all event registration fields corresponding to selected question type
"""
type_mapping = {
"char_box": ["char", "text"],
"text_box": ["html"],
"numerical_box": ["integer", "float", "html", "char"],
"date": ["date", "text", "char"],
"datetime": ["datetime", "html", "char"],
"simple_choice": ["many2one", "html", "char"],
"multiple_choice": ["many2many", "html", "char"],
}
for record in self:
search_domain = [
("model", "=", "event.registration"),
("ttype", "in", type_mapping.get(record.question_type, [])),
]
record.event_registration_allowed_field_ids = self.env["ir.model.fields"].search(search_domain).ids

View File

@@ -0,0 +1,12 @@
# 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_registration = fields.Boolean(
help="Generate event registration for selected event",
)

View File

@@ -0,0 +1,82 @@
import logging
import textwrap
import uuid
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo.tools import float_is_zero
_logger = logging.getLogger(__name__)
class SurveyUserInput(models.Model):
_inherit = 'survey.user_input'
registration_id = fields.Many2one('event.registration', 'Event registration') #registration created automaticaly on survey post
def _prepare_registration(self):
"""Extract registration values from the answers"""
elegible_inputs = self.user_input_line_ids.filtered(
lambda x: x.question_id.event_registration_field and not x.skipped
)
vals = {}
for line in elegible_inputs:
if line.question_id.event_registration_field.ttype == 'many2one':
vals[line.question_id.event_registration_field.name] = line.suggested_answer_id.record_reference
else:
vals[line.question_id.event_registration_field.name] = line[f"value_{line.answer_type}"]
return vals
def _create_registration_post_process(self, registration):
"""After creating the event registration send an internal message with the input link"""
registration.message_post_with_view(
"mail.message_origin_link",
values={"self": registration, "origin": self},
subtype_id=self.env.ref("mail.mt_note").id,
)
def _mark_done(self):
"""Generate registration when the survey is submitted"""
for user_input in self.filtered(
lambda r: r.survey_id.generate_registration and not self.registration_id
):
vals = user_input._prepare_registration()
# check doublon : if old draft registration already exists : update it
email = vals.get('email')
event_id = vals.get('event_id')
old_registration = False
if email and event_id:
old_registration = self.env["event.registration"].search([('email','=',email),('event_id','=',event_id)])
if old_registration:
old_registration = old_registration[0]
if old_registration.state == 'draft':
registration = old_registration
registration.write(vals)
registration.message_post_with_view(
"mail.message_origin_link",
values={"edit":True, "self": registration, "origin": user_input},
subtype_id=self.env.ref("mail.mt_note").id,
)
if not old_registration:
registration = self.env["event.registration"].create(vals)
self._create_registration_post_process(registration)
self.update({"registration_id": registration.id})
res = super()._mark_done()
# after all, set partner id of registration as the partner of user input
for user_input in self:
if user_input.registration_id and user_input.partner_id:
user_input.registration_id.partner_id = user_input.partner_id
return res

View File

@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_ir_model_fields_survey_user,ir.model.fields.survey.user,base.model_ir_model_fields,survey.group_survey_user,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_ir_model_fields_survey_user ir.model.fields.survey.user base.model_ir_model_fields survey.group_survey_user 1 0 0 0

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Survey question form -->
<record id="survey_question_form" model="ir.ui.view">
<field name="model">survey.question</field>
<field name="inherit_id" ref="survey.survey_question_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='comments_allowed']/.." position="after">
<group name="event_registration" string="Event registration">
<!-- event registration field, filtered by event_registration_allowed_field_ids (invisible) -->
<field name="event_registration_field" widget="selection" />
<field name="event_registration_allowed_field_ids" invisible="1" />
</group>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Survey form -->
<record id="survey_form" model="ir.ui.view">
<field name="model">survey.survey</field>
<field name="inherit_id" ref="survey.survey_survey_view_form" />
<field name="arch" type="xml">
<group name="options" position="inside">
<group name="event_registration_options" string="Events registrations">
<!-- Possibility to generate event registration -->
<field name="generate_registration" />
</group>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,25 @@
# Copyright 2016-2020 Akretion France (<https://www.akretion.com>)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Survey event generation attachment",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Elabore",
"website": "https://www.elabore.coop",
"category": "",
'summary': 'Link Attachments from Surveys to generated event registration',
'description': """
Link Attachments from Surveys to generated event registration
----------------------------------------------------
* Create new attachments on event registration creation, based on attached file of survey answer (survey.user_input.line)
""",
"depends": ["survey_base","survey_event_registration_generation"],
"data": [
],
"installable": True,
"auto_install":True
}

View File

@@ -0,0 +1 @@
from . import survey_user_input

View File

@@ -0,0 +1,32 @@
import logging
import textwrap
import uuid
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo.tools import float_is_zero
_logger = logging.getLogger(__name__)
class SurveyUserInput(models.Model):
_inherit = 'survey.user_input'
def _mark_done(self):
"""Copy attachments to event registration"""
res = super()._mark_done()
for user_input in self:
if user_input.survey_id.generate_registration and user_input.registration_id:
for user_input_line in user_input.user_input_line_ids:
if user_input_line.value_file:
self.env['ir.attachment'].create({
'res_model':'event.registration',
'res_id':user_input.registration_id.id,
'name': user_input_line.value_file_fname,
'datas': user_input_line.value_file,
'type': 'binary'
})
return res

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,18 @@
# Copyright 2016-2020 Akretion France (<https://www.akretion.com>)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Survey event speaker generation",
"version": "16.0.0.0.0",
"license": "AGPL-3",
"author": "Elabore",
"website": "https://www.elabore.coop",
"category": "",
"depends": ["survey", "survey_event_base", "event_speaker"],
"data": [
'views/mail_templates_chatter.xml',
'views/survey_survey_views.xml',
],
"installable": True,
}

View File

@@ -0,0 +1,56 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * survey_event_speaker_generation
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-19 14:42+0000\n"
"PO-Revision-Date: 2023-09-19 14:42+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_event_speaker_generation
#: model_terms:ir.ui.view,arch_db:survey_event_speaker_generation.survey_form
msgid "Events speakers"
msgstr "Intervenants d'événements"
#. module: survey_event_speaker_generation
#: model:ir.model.fields,field_description:survey_event_speaker_generation.field_survey_user_input__speaker_id
msgid "Event speaker"
msgstr "Intervenants"
#. module: survey_event_speaker_generation
#: model:ir.model.fields,field_description:survey_event_speaker_generation.field_survey_survey__generate_speaker
msgid "Generate Speaker"
msgstr "Générer un intervenant"
#. module: survey_event_speaker_generation
#: model:ir.model.fields,help:survey_event_speaker_generation.field_survey_survey__generate_speaker
msgid "Generate speaker for selected event"
msgstr "Générer un intervenant pour l'événement selectionné"
#. module: survey_event_speaker_generation
#: model:ir.model,name:survey_event_speaker_generation.model_survey_survey
msgid "Survey"
msgstr "Questionnaire"
#. module: survey_event_speaker_generation
#: model:ir.model,name:survey_event_speaker_generation.model_survey_user_input
msgid "Survey User Input"
msgstr "Entrée utilisateur du questionnaire"
#. module: survey_event_speaker_generation
#: model_terms:ir.ui.view,arch_db:survey_event_speaker_generation.message_event_speaker_assigned
msgid "from survey answers"
msgstr "depuis la réponse au questionnaire"
#. module: survey_event_speaker_generation
#: model_terms:ir.ui.view,arch_db:survey_event_speaker_generation.message_event_speaker_assigned
msgid "has been assigned to"
msgstr "a été assigné à"

View File

@@ -0,0 +1,2 @@
from . import survey_user_input
from . import survey_survey

View File

@@ -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_speaker = fields.Boolean(
help="Generate speaker for selected event",
) #Field to check if user wants to generate a speaker on survey submit

View File

@@ -0,0 +1,41 @@
import logging
import textwrap
import uuid
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _, Command
from odoo.exceptions import ValidationError
from odoo.tools import float_is_zero
_logger = logging.getLogger(__name__)
class SurveyUserInput(models.Model):
_inherit = 'survey.user_input'
speaker_id = fields.Many2one('res.partner', 'Event speaker') #created partner when submit survey
def _create_speaker_post_process(self, speaker):
for event in self.events_ids:
"""Add message to chatter to note speaker creation and association with event"""
speaker.message_post_with_view(
"survey_event_speaker_generation.message_event_speaker_assigned",
values={"speaker": speaker, "user_input": self, "event":event},
subtype_id=self.env.ref("mail.mt_note").id,
)
def _mark_done(self):
"""Attach partner as speaker of event"""
res = super()._mark_done()
for user_input in self.filtered(lambda r: r.survey_id.generate_speaker and not r.speaker_id and r.partner_id):
user_input.update({"speaker_id": user_input.partner_id.id})
for event in user_input.events_ids:
for track in event.track_ids:
track.speaker_ids = [Command.link(user_input.speaker_id.id)]
user_input._create_speaker_post_process(user_input.speaker_id)
return res

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Message notification in res.partner chatter -->
<template id="message_event_speaker_assigned">
<div style="margin: 0px; padding: 0px; font-size: 13px;">
<a href="#" t-att-data-oe-model="speaker._name" t-att-data-oe-id="speaker.id">
<t t-esc="speaker.name" />
</a>
has been assigned as speaker to
<a href="#" t-att-data-oe-model="event._name" t-att-data-oe-id="event.id">
<t t-esc="event.display_name" />
</a>
from survey answers
<a href="#" t-att-data-oe-model="user_input._name" t-att-data-oe-id="user_input.id">
<t t-esc="user_input.display_name" />
</a>
</div>
</template>
</data>
</odoo>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Survey form -->
<record id="survey_form" model="ir.ui.view">
<field name="model">survey.survey</field>
<field name="inherit_id" ref="survey.survey_survey_view_form" />
<field name="arch" type="xml">
<group name="options" position="inside">
<group name="event_speaker_options" string="Events speakers">
<field name="generate_speaker" />
</group>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,24 @@
# Copyright 2016-2020 Akretion France (<https://www.akretion.com>)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Survey event visibility",
"version": "16.0.0.0.0",
"license": "AGPL-3",
"author": "Elabore",
'summary': 'Add visibility field in event stage',
'description': """
Add visibility information in product and events
----------------------------------------------------
The product and event visibility is computed from event stage visibility.
""",
"website": "https://www.elabore.coop",
"category": "",
"depends": ["survey"],
"data": [
'views/event_stage_views.xml',
],
"installable": True,
}

View File

@@ -0,0 +1,3 @@
from . import event_stage
from . import event_event
from . import product_product

View File

@@ -0,0 +1,28 @@
from odoo import models, fields, api
class EventEvent(models.Model):
_inherit = 'event.event'
visible_in_survey = fields.Boolean('Visible in survey', related='stage_id.visible_in_survey', readonly=True,
help="""Events in step configured as 'visible in survey'.""")
def get_events_from_event_products(self, product_ids=None, only_visible_in_survey=False):
"""Search events in stage filtered by product present in ticket..
Args:
product_ids (list[product.product ids], optional): to filter only events with tickets using product in this list. Defaults to None.
Returns:
event.event: Events
"""
event_search = []
if product_ids:
event_tickets = self.env['event.event.ticket'].search([('product_id','in',product_ids)])
event_search.append(('event_ticket_ids','in',event_tickets.ids))
if only_visible_in_survey:
event_search.append(('visible_in_survey','=',True))
return self.env['event.event'].search(event_search)

View File

@@ -0,0 +1,7 @@
from odoo import models, fields, api
class EventStage(models.Model):
_inherit = 'event.stage'
visible_in_survey = fields.Boolean('Visible in surveys') #if checked, only events on this stage are visible in surveys

View File

@@ -0,0 +1,23 @@
from odoo import models, fields, api
class ProductProduct(models.Model):
_inherit = 'product.product'
visible_in_survey = fields.Boolean('Visible in survey', compute='_compute_visible_in_survey', readonly=True,
help="""Events in step configured as 'visible in survey'.""")
def _compute_visible_in_survey(self):
#get all events in step 'visible in survey'
product_ids = set()
events = self.env['event.event'].search([('visible_in_survey','=',True)])
for event in events:
for ticket in event.event_ticket_ids:
product_ids.add(ticket.product_id.id)
for event_product in self:
if event_product.id in product_ids:
event_product.visible_in_survey = True
else:
event_product.visible_in_survey = False

View File

@@ -0,0 +1,31 @@
<?xml version="1.0"?>
<odoo>
<data>
<!-- Event stage view form -->
<!-- * Add field visible_in_survey -->
<record id="event_stage_view_form_survey_event_registration_generation" model="ir.ui.view">
<field name="name">event.stage.view.form.survey.event.registration.generation</field>
<field name="model">event.stage</field>
<field name="inherit_id" ref="event.event_stage_view_form" />
<field name="arch" type="xml">
<field name="pipe_end" position="after">
<field name="visible_in_survey" />
</field>
</field>
</record>
<!-- Event stage view tree -->
<!-- * Add field visible_in_survey -->
<record id="event_stage_view_tree_survey_event_registration_generation" model="ir.ui.view">
<field name="name">event.stage.view.tree.survey.event.registration.generation</field>
<field name="model">event.stage</field>
<field name="inherit_id" ref="event.event_stage_view_tree" />
<field name="arch" type="xml">
<field name="name" position="after">
<field name="visible_in_survey" />
</field>
</field>
</record>
</data>
</odoo>

Some files were not shown because too many files have changed in this diff Show More