Browse Source

[ADD] even_question_sale

16.0
RemiFr82 7 months ago
parent
commit
540d8f584e
  1. 147
      .gitignore
  2. 1
      event_question_sale/__init__.py
  3. 41
      event_question_sale/__manifest__.py
  4. 3
      event_question_sale/models/__init__.py
  5. 26
      event_question_sale/models/event_question.py
  6. 12
      event_question_sale/models/event_question_answer.py
  7. 66
      event_question_sale/models/event_question_answer_product.py
  8. 14
      event_question_sale/models/event_registration_answer.py
  9. 47
      event_question_sale/views/event_event.xml

147
.gitignore

@ -1,36 +1,29 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
/.venv
/.pytest_cache
# C extensions
*.so
# Distribution / packaging
.Python
env/
bin/
build/
develop-eggs/
dist/
downloads/
dist_wo_pbr/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
*.eggs
# Installer logs
pip-log.txt
@ -39,122 +32,50 @@ pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.coverage\.*
.coverage\_*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Pycharm
.idea
# Flask stuff:
instance/
.webassets-cache
# Eclipse
.settings
# Scrapy stuff:
.scrapy
# Visual Studio cache/options directory
.vs/
.vscode
# Sphinx documentation
docs/_build/
# OSX Files
.DS_Store
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Django stuff:
*.log
# Spyder project settings
.spyderproject
.spyproject
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Rope project settings
# Rope
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# Sphinx documentation
docs/_build/
# pytype static type analyzer
.pytype/
# Backup files
*~
*.swp
# Cython debug symbols
cython_debug/
# OCA rules
!static/lib/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Auto-generated
ChangeLog
.pre-commit-config-local.yaml

1
event_question_sale/__init__.py

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

41
event_question_sale/__manifest__.py

@ -0,0 +1,41 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
"name": "Event question sale",
"version": "1.0.0",
"summary": """
Set booking order extra products on event question answers.
""",
"description": """
This module extends the functionnalities of event questions and event tickets sale.
On the event questions you can check the box to be able to add on each answer,
zero, one or more extra products (giving price and qty) that will be added to the sale order.
For the questions asked once per registration, you can choose to add the extra products once or for each attendee.
""",
"author": "RemiFr82",
"contributors": "Hike2River",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Events",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"website_event_questions",
"website_event_sale",
],
"data": [],
"assets": {},
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

3
event_question_sale/models/__init__.py

@ -0,0 +1,3 @@
from . import event_question_answer_product
from . import event_question_answer
from . import event_question

26
event_question_sale/models/event_question.py

@ -0,0 +1,26 @@
from odoo import api, fields, models, _
class EventQuestion(models.Model):
_inherit = "event.question"
add_products = fields.Boolean(
string="Add extra products on answers",
help="Checking this box allows",
)
qty_by_attendees = fields.Boolean(
string="Multiply quantity by attendees count",
help="For the questions asked only once per registration.\n"
"If checked, Odoo will add the extra product for each attendee.\n"
"Otherwise, Odoo will add the extra product only once.",
)
@api.onchange("question_type")
def onchange_qtype(self):
if self.question_type != "simple_choice" and self.add_product:
self.add_product = False
@api.onchange("once_per_order")
def onchange_qtype(self):
if not self.once_per_order and self.qty_by_attendees:
self.qty_by_attendees = False

12
event_question_sale/models/event_question_answer.py

@ -0,0 +1,12 @@
from odoo import api, fields, models, _
class EventQuestionAnswer(models.Model):
_inherit = "event.question.answer"
extra_product_ids = fields.One2many(
comodel_name="event.question.answer.product",
inverse_name="answer_id",
string="Extra Products",
help="These producs will be added to the sale order of the booking with the given quantity and price.",
)

66
event_question_sale/models/event_question_answer_product.py

@ -0,0 +1,66 @@
from odoo import api, fields, models, _
class EventQuestionAnswerProduct(models.Model):
_name = "event.question.answer.product"
_rec_name = "product_id"
answer_id = fields.Many2one(
comodel_name="event.question.answer",
string="Answer",
required=True,
ondelete="cascade",
)
product_id = fields.Many2one(
comodel_name="product.product",
string="Product variant",
)
price_unit = fields.Float(
string="Unit price",
digits="Product Price",
)
quantity = fields.Float(
string="Quantity",
digits="Product Unit of Measure",
)
uom_category_id = fields.Many2one(
related="product_id.uom_id.category_id",
depends=["product_id"],
)
uom_id = fields.Many2one(
comodel_name="uom.uom",
string="Unit of Measure",
compute="_compute_uom_id",
store=True,
readonly=False,
precompute=True,
ondelete="restrict",
domain="[('category_id', '=', uom_category_id)]",
)
def name_get(self):
res = []
for eqap in self:
res.append(
(
eqap.id,
_("{} x {} at {}").format(
eqap.quantity,
eqap.product_id.display_name,
eqap.answer_id.question_id.event_id.company_id.currency_id.format(
eqap.price_unit
),
),
)
)
return res
@api.depends("product_id")
def _compute_uom_id(self):
for eqap in self:
product = eqap.product_id
uom = eqap.uom_id
if not product:
eqap.uom_id = False
elif not uom or (product.uom_id.id != uom.id):
eqap.uom_id = product.uom_id

14
event_question_sale/models/event_registration_answer.py

@ -0,0 +1,14 @@
from odoo import api, fields, models, _
class EventRegistrationAnswer(models.Model):
_inherit = "event.registration.answer"
extra_product_ids = fields.One2many(related="value_answer_id.extra_product_ids")
sale_order_line_ids = fields.Many2many(
comodel_name="sale.order.line",
column1="event_answer_id",
column2="sale_order_line_id",
relation="event_answer_sale_order_line_rel",
string="Related sale order lines",
)

47
event_question_sale/views/event_event.xml

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="event_event_view_form_inherit" model="ir.ui.view">
<field name="name">event.event.view.form.inherit</field>
<field name="model">event.event</field>
<field name="inherit_id" ref="website_event_questions.event_event_view_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='once_per_order']/.." position="attributes">
<attribute name="class">o_label_nowrap</attribute>
</xpath>
<field name="once_per_order" position="after">
<field name="add_products" />
<field name="qty_by_attendees" />
</field>
<xpath expr="//field[@name='question_ids']/form//tree" position="attributes">
<attribute name="editable">0</attribute>
</xpath>
<xpath expr="//field[@name='question_ids']/form//tree" position="inside">
<field name="extra_product_ids" widget="one2many" options="{'no_quick_create': 1}"
attrs="{'cdolumn_invisible':[('parent.add_products','!=',True)]}">
<!-- <form>
<group>
<group>
<field name="product_id" />
<field name="price_unit" />
</group>
<group>
<field name="quantity" />
<field name="uom_id" />
<field name="uom_category_id" invisible="1" />
</group>
</group>
</form> -->
<tree editable="bottom">
<field name="product_id" />
<field name="price_unit" />
<field name="quantity" />
<field name="uom_id" />
<field name="uom_category_id" invisible="1" />
</tree>
</field>
</xpath>
</field>
</record>
</odoo>
Loading…
Cancel
Save