4 Commits

Author SHA1 Message Date
jscampucci
80600395ca [WIP] Test gitea actions
Some checks failed
pre-commit / pre-commit (pull_request) Failing after 5m25s
2025-09-15 15:14:16 +02:00
jscampucci
65171f3fb4 [CLN] global : lint line length corrections 2025-09-15 14:31:21 +02:00
jscampucci
d3b2cdd286 [CLN] global : clean lint errors 2025-09-15 14:13:26 +02:00
jscampucci
174aabfbbb [CLN] global : full pre-commit & ruff lint 2025-09-15 12:58:03 +02:00
74 changed files with 685 additions and 438 deletions

View File

@@ -5,18 +5,18 @@
"version": "16.0.1.0.0", "version": "16.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
"category": "", "category": "",
'summary': 'Generate quotation from event registration', "summary": "Generate quotation from event registration",
'description': """ "description": """
Generate quotation from event registration : Generate quotation from event registration :
""", """,
"depends": ["event_sale"], "depends": ["event_sale"],
"data": [ "data": [
'security/ir.model.access.csv', "security/ir.model.access.csv",
'views/event_registration_views.xml', "views/event_registration_views.xml",
'views/sale_order_views.xml', "views/sale_order_views.xml",
'views/account_move_views.xml', "views/account_move_views.xml",
], ],
"installable": True, "installable": True,
} }

View File

@@ -1,6 +1,7 @@
from odoo import _, api, Command, fields, models from odoo import fields, models
class AccountMove(models.Model): class AccountMove(models.Model):
_inherit = "account.move" _inherit = "account.move"
event_registration_id = fields.Many2one('event.registration', string="Stagiaire") event_registration_id = fields.Many2one("event.registration", string="Stagiaire")

View File

@@ -1,12 +1,17 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command
import logging import logging
from odoo import api, fields, models
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class EventRegistration(models.Model): class EventRegistration(models.Model):
_inherit = "event.registration" _inherit = "event.registration"
financier_ids = fields.One2many('event.registration.financier', 'registration_id', string="Financements") financier_ids = fields.One2many(
"event.registration.financier", "registration_id", string="Financements"
)
def name_get(self): def name_get(self):
result = [] result = []
@@ -20,27 +25,30 @@ class EventRegistration(models.Model):
def _compute_display_name(self): def _compute_display_name(self):
for registration in self: for registration in self:
if registration.partner_id and registration.event_id: if registration.partner_id and registration.event_id:
registration.display_name = f"{registration.partner_id.name} ({registration.event_id.name})" registration.display_name = (
f"{registration.partner_id.name} ({registration.event_id.name})"
)
else: else:
registration.display_name = super(EventRegistration, registration)._compute_display_name() registration.display_name = super(
EventRegistration, registration
)._compute_display_name()
def generate_quotation(self): def generate_quotation(self):
for registration in self: for registration in self:
for financier in registration.financier_ids: for financier in registration.financier_ids:
if not financier.quotation_id: if not financier.quotation_id:
so_values = financier.get_sale_order_values() so_values = financier.get_sale_order_values()
so_values['order_line'] = financier.get_sale_order_line_values() so_values["order_line"] = financier.get_sale_order_line_values()
sale_order = self.env['sale.order'].create(so_values) sale_order = self.env["sale.order"].create(so_values)
financier.quotation_id = sale_order financier.quotation_id = sale_order
else: else:
order_lines = self.env['sale.order.line'].search([ order_lines = self.env["sale.order.line"].search(
('order_id','=',financier.quotation_id.id), [
('product_id','=',financier.get_product_id()), ("order_id", "=", financier.quotation_id.id),
('state', '!=', 'done'), ("product_id", "=", financier.get_product_id()),
]) ("state", "!=", "done"),
]
)
if order_lines: if order_lines:
order_lines[0].price_unit = financier.amount order_lines[0].price_unit = financier.amount
financier.quotation_id.write(financier.get_sale_order_values()) financier.quotation_id.write(financier.get_sale_order_values())

View File

@@ -1,44 +1,52 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command
import logging import logging
from odoo import Command, fields, models
from odoo.exceptions import UserError from odoo.exceptions import UserError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class EventRegistrationFinancier(models.Model): class EventRegistrationFinancier(models.Model):
_name = "event.registration.financier" _name = "event.registration.financier"
_rec_name = 'financier_id' _rec_name = "financier_id"
company_id = fields.Many2one("res.company") company_id = fields.Many2one("res.company")
company_currency_id = fields.Many2one('res.currency', related="company_id.currency_id") company_currency_id = fields.Many2one(
registration_id = fields.Many2one('event.registration') "res.currency", related="company_id.currency_id"
quotation_id = fields.Many2one('sale.order', string="Devis") )
financier_id = fields.Many2one('res.partner', string="Financeur", required=True) registration_id = fields.Many2one("event.registration")
terms = fields.Char('Modalités') quotation_id = fields.Many2one("sale.order", string="Devis")
amount = fields.Monetary('Montant', currency_field="company_currency_id") financier_id = fields.Many2one("res.partner", string="Financeur", required=True)
terms = fields.Char("Modalités")
amount = fields.Monetary("Montant", currency_field="company_currency_id")
state = fields.Selection( state = fields.Selection(
related='quotation_id.state', related="quotation_id.state",
string="Order Status", string="Order Status",
copy=False, store=True, precompute=True) copy=False,
store=True,
precompute=True,
)
def get_product_id(self): def get_product_id(self):
if self.registration_id.event_ticket_id: if self.registration_id.event_ticket_id:
return self.registration_id.event_ticket_id.product_id.id return self.registration_id.event_ticket_id.product_id.id
elif self.registration_id.event_id.event_ticket_ids: elif self.registration_id.event_id.event_ticket_ids:
return self.registration_id.event_id.event_ticket_ids[0].product_id.id return self.registration_id.event_id.event_ticket_ids[0].product_id.id
raise UserError('Un ticket doit être défini dans la session de formation afin de générer le devis') raise UserError(
"Un ticket doit être défini dans la session de formation afin de générer le devis"
)
def get_sale_order_values(self): def get_sale_order_values(self):
return { return {
'event_registration_id':self.registration_id.id, "event_registration_id": self.registration_id.id,
'partner_id':self.financier_id.id, "partner_id": self.financier_id.id,
} }
def get_sale_order_line_values(self): def get_sale_order_line_values(self):
return [Command.create({ return [
"price_unit": self.amount, Command.create(
"product_id": self.get_product_id() {"price_unit": self.amount, "product_id": self.get_product_id()}
})] )
]

View File

@@ -1,39 +1,61 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command
import logging import logging
from odoo import fields, models
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class SaleOrder(models.Model): class SaleOrder(models.Model):
_inherit = "sale.order" _inherit = "sale.order"
event_registration_id = fields.Many2one('event.registration', string="Stagiaire") event_registration_id = fields.Many2one("event.registration", string="Stagiaire")
def _prepare_invoice(self): def _prepare_invoice(self):
"""Copy event_registration_id to generated invoice
""" """
res = super(SaleOrder, self)._prepare_invoice() Copy event_registration_id to generated invoice.
"""
res = super()._prepare_invoice()
res["event_registration_id"] = self.event_registration_id.id res["event_registration_id"] = self.event_registration_id.id
return res return res
def linked_to_registration(self): def linked_to_registration(self):
return len(self.env['event.registration.financier'].search([('quotation_id','=',self.id)])) > 0 return (
len(
self.env["event.registration.financier"].search(
[("quotation_id", "=", self.id)]
)
)
> 0
)
def action_confirm(self): def action_confirm(self):
res = super(SaleOrder, self).action_confirm() res = super().action_confirm()
#if sale order is linked to event.registration.financier, don't open wizard # if sale order is linked to event.registration.financier, don't open wizard
if isinstance(res, dict) and res.get('xml_id') == 'event_sale.action_sale_order_event_registration' and self.linked_to_registration(): if (
isinstance(res, dict)
and res.get("xml_id") == "event_sale.action_sale_order_event_registration"
and self.linked_to_registration()
):
return True return True
return res return res
class SaleOrderLine(models.Model): class SaleOrderLine(models.Model):
_inherit = "sale.order.line" _inherit = "sale.order.line"
def _update_registrations(self, confirm=True, cancel_to_draft=False, registration_data=None, mark_as_paid=False): def _update_registrations(
self,
confirm=True,
cancel_to_draft=False,
registration_data=None,
mark_as_paid=False,
):
# bypass _update_registrations if order generated by event registration # bypass _update_registrations if order generated by event registration
if self.order_id.linked_to_registration(): if self.order_id.linked_to_registration():
return return
return super(SaleOrderLine, self)._update_registrations(confirm, cancel_to_draft, registration_data, mark_as_paid) return super()._update_registrations(
confirm, cancel_to_draft, registration_data, mark_as_paid
)

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="view_move_form" model="ir.ui.view"> <record id="view_move_form" model="ir.ui.view">
<field name="name">view.move.form.inherit.event.generate.quotation</field> <field name="name">view.move.form.inherit.event.generate.quotation</field>
@@ -12,7 +12,9 @@
</record> </record>
<record id="view_out_invoice_tree" model="ir.ui.view"> <record id="view_out_invoice_tree" model="ir.ui.view">
<field name="name">view.out.invoice.tree.inherit.event.generate.quotation</field> <field
name="name"
>view.out.invoice.tree.inherit.event.generate.quotation</field>
<field name="model">account.move</field> <field name="model">account.move</field>
<field name="inherit_id" ref="account.view_out_invoice_tree" /> <field name="inherit_id" ref="account.view_out_invoice_tree" />
<field name="arch" type="xml"> <field name="arch" type="xml">

View File

@@ -1,8 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record model="ir.ui.view" id="view_event_registration_form_event_generate_quotation_from_registration"> <record
<field name="name">view.event.registration.form.event.generate.quotation.from.registration</field> model="ir.ui.view"
id="view_event_registration_form_event_generate_quotation_from_registration"
>
<field
name="name"
>view.event.registration.form.event.generate.quotation.from.registration</field>
<field name="model">event.registration</field> <field name="model">event.registration</field>
<field name="inherit_id" ref="event_sale.event_registration_ticket_view_form" /> <field name="inherit_id" ref="event_sale.event_registration_ticket_view_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
@@ -10,14 +15,25 @@
<group name="quotation" string="Financement" colspan="1"> <group name="quotation" string="Financement" colspan="1">
<field name="financier_ids" nolabel="1" colspan="2"> <field name="financier_ids" nolabel="1" colspan="2">
<tree editable="bottom"> <tree editable="bottom">
<field name="state" invisible="1"/> <field name="state" invisible="1" />
<field name="financier_id" attrs="{'readonly': [('state', 'in', ['done', 'cancel'])]}"/> <field
<field name="amount" attrs="{'readonly': [('state', 'in', ['done', 'cancel'])]}" /> name="financier_id"
attrs="{'readonly': [('state', 'in', ['done', 'cancel'])]}"
/>
<field
name="amount"
attrs="{'readonly': [('state', 'in', ['done', 'cancel'])]}"
/>
<field name="terms" /> <field name="terms" />
<field name="quotation_id" readonly="True" /> <field name="quotation_id" readonly="True" />
</tree> </tree>
</field> </field>
<button name="generate_quotation" type="object" string="Créer/adapter les devis" colspan="2" /> <button
name="generate_quotation"
type="object"
string="Créer/adapter les devis"
colspan="2"
/>
</group> </group>
</sheet> </sheet>
</field> </field>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="sale_order_view_form" model="ir.ui.view"> <record id="sale_order_view_form" model="ir.ui.view">
<field name="name">sale.order.form.inherit.event.generate.quotation</field> <field name="name">sale.order.form.inherit.event.generate.quotation</field>

View File

@@ -7,18 +7,15 @@
"version": "16.0.0.0.0", "version": "16.0.0.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
'summary': 'Event mail attachments', "summary": "Event mail attachments",
'description': """ "description": """
Event mail attachments Event mail attachments
---------------------------------------------------- ----------------------------------------------------
""", """,
"category": "", "category": "",
"depends": ["ctl_training_customization"], "depends": ["ctl_training_customization"],
"data": [ "data": ["views/mail_template_views.xml"],
'views/mail_template_views.xml'
],
"installable": True, "installable": True,
} }

View File

@@ -1,14 +1,19 @@
from odoo import _, api, Command, fields, models from odoo import fields, models
from lxml import etree, html
class MailTemplate(models.Model): class MailTemplate(models.Model):
_inherit = "mail.template" _inherit = "mail.template"
event_attachment_name_prefix = fields.Char('Attachment name prefix', help="If there is an attachment in event registration, or in event, with a name that starts with this name, it will be attached to the mail.") event_attachment_name_prefix = fields.Char(
"Attachment name prefix",
help="""
If there is an attachment in event registration, or in event,
with a name that starts with this name, it will be attached to the mail.
""",
)
def generate_email(self, res_ids, fields): def generate_email(self, res_ids, fields):
res = super(MailTemplate, self).generate_email(res_ids, fields) res = super().generate_email(res_ids, fields)
self.ensure_one() self.ensure_one()
multi_mode = True multi_mode = True
@@ -16,35 +21,46 @@ class MailTemplate(models.Model):
res_ids = [res_ids] res_ids = [res_ids]
multi_mode = False multi_mode = False
for lang, (template, template_res_ids) in self._classify_per_lang(res_ids).items(): for _, (template, template_res_ids) in self._classify_per_lang(res_ids).items():
#add reports attached to event.registration or event.event from attachment name # add reports attached to event.registration or event.event from
# attachment name
if template.event_attachment_name_prefix: if template.event_attachment_name_prefix:
for res_id in template_res_ids: for res_id in template_res_ids:
event_registration = self.env['event.registration'].browse(res_id) event_registration = self.env["event.registration"].browse(res_id)
attachments = self.env['ir.attachment'] attachments = self.env["ir.attachment"]
for event_attachment_name_prefix in template.event_attachment_name_prefix.split(","): for (
attachments |= self.env['ir.attachment'].search([ event_attachment_name_prefix
('res_model','=','event.registration'), ) in template.event_attachment_name_prefix.split(","):
('res_id','=',res_id), attachments |= self.env["ir.attachment"].search(
('name','like',event_attachment_name_prefix)]) [
attachments |= self.env['ir.attachment'].search([ ("res_model", "=", "event.registration"),
('res_model','=','event.event'), ("res_id", "=", res_id),
('res_id','=',event_registration.event_id.id), ("name", "like", event_attachment_name_prefix),
('name','like',event_attachment_name_prefix)]) ]
)
attachments |= self.env["ir.attachment"].search(
[
("res_model", "=", "event.event"),
("res_id", "=", event_registration.event_id.id),
("name", "like", event_attachment_name_prefix),
]
)
attachments_res = [(attachment.name, attachment.datas) for attachment in attachments] attachments_res = [
(attachment.name, attachment.datas)
for attachment in attachments
]
if multi_mode: if multi_mode:
if res_id in res: if res_id in res:
if not 'attachments' in res[res_id]: if "attachments" not in res[res_id]:
res[res_id]['attachments'] = attachments_res res[res_id]["attachments"] = attachments_res
else: else:
res[res_id]['attachments'].extend(attachments_res) res[res_id]["attachments"].extend(attachments_res)
else: else:
if not 'attachments' in res: if "attachments" not in res:
res['attachments'] = attachments_res res["attachments"] = attachments_res
else: else:
res['attachments'].extend(attachments_res) res["attachments"].extend(attachments_res)
return res return res

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<data> <data>
<record model="ir.ui.view" id="email_template_form_event_mail_attachment"> <record model="ir.ui.view" id="email_template_form_event_mail_attachment">

View File

@@ -5,18 +5,15 @@
"version": "16.0.0.0.0", "version": "16.0.0.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
'summary': 'Add manual send in event communication', "summary": "Add manual send in event communication",
'description': """ "description": """
Add manual send in event communication Add manual send in event communication
---------------------------------------------------- ----------------------------------------------------
""", """,
"category": "", "category": "",
"depends": ["event"], "depends": ["event"],
"data": [ "data": ["views/event_event_views.xml"],
'views/event_event_views.xml'
],
"installable": True, "installable": True,
} }

View File

@@ -1,27 +1,39 @@
from odoo import _, api, Command, fields, models
from lxml import etree, html
import logging import logging
from odoo.exceptions import MissingError, ValidationError
from odoo import api, fields, models
from odoo.exceptions import MissingError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class EventMail(models.Model): class EventMail(models.Model):
_inherit = "event.mail" _inherit = "event.mail"
notification_type = fields.Selection(selection_add=[('mail_manual', 'Mail (manual)')], ondelete={'mail_manual': 'set default'}) notification_type = fields.Selection(
selection_add=[("mail_manual", "Mail (manual)")],
ondelete={"mail_manual": "set default"},
)
def _selection_template_model_get_mapping(self): def _selection_template_model_get_mapping(self):
return {**super(EventMail, self)._selection_template_model_get_mapping(), 'mail_manual': 'mail.template'} return {
**super()._selection_template_model_get_mapping(),
"mail_manual": "mail.template",
}
@api.depends(
@api.depends('event_id.date_begin', 'event_id.date_end', 'interval_type', 'interval_unit', 'interval_nbr','notification_type') "event_id.date_begin",
"event_id.date_end",
"interval_type",
"interval_unit",
"interval_nbr",
"notification_type",
)
def _compute_scheduled_date(self): def _compute_scheduled_date(self):
res = super(EventMail, self)._compute_scheduled_date() res = super()._compute_scheduled_date()
for scheduler in self: for scheduler in self:
if scheduler.notification_type == 'mail_manual': if scheduler.notification_type == "mail_manual":
scheduler.scheduled_date = '2148-12-31' scheduler.scheduled_date = "2148-12-31"
scheduler.interval_type = 'after_sub' scheduler.interval_type = "after_sub"
return res return res
@@ -31,24 +43,24 @@ class EventMail(models.Model):
class EventMailRegistration(models.Model): class EventMailRegistration(models.Model):
_inherit = 'event.mail.registration' _inherit = "event.mail.registration"
def execute(self): def execute(self):
"""Inherit execute to send mail from schedulers "mail_manual"
""" """
res = super(EventMailRegistration, self).execute() Inherit execute to send mail from schedulers "mail_manual".
"""
res = super().execute()
todo_manual = self.filtered(lambda reg_mail: todo_manual = self.filtered(
not reg_mail.mail_sent and lambda reg_mail: not reg_mail.mail_sent
reg_mail.registration_id.state in ['open', 'done'] and and reg_mail.registration_id.state in ["open", "done"]
reg_mail.scheduler_id.notification_type == 'mail_manual' and reg_mail.scheduler_id.notification_type == "mail_manual"
) )
done = self.browse() done = self.browse()
for reg_mail in todo_manual: for reg_mail in todo_manual:
organizer = reg_mail.scheduler_id.event_id.organizer_id organizer = reg_mail.scheduler_id.event_id.organizer_id
company = self.env.company company = self.env.company
author = self.env.ref('base.user_root').partner_id author = self.env.ref("base.user_root").partner_id
if organizer.email: if organizer.email:
author = organizer author = organizer
elif company.email: elif company.email:
@@ -57,7 +69,7 @@ class EventMailRegistration(models.Model):
author = self.env.user.partner_id author = self.env.user.partner_id
email_values = { email_values = {
'author_id': author.id, "author_id": author.id,
} }
template = None template = None
try: try:
@@ -66,15 +78,20 @@ class EventMailRegistration(models.Model):
pass pass
if not template: if not template:
_logger.warning("Cannot process ticket %s, because Mail Scheduler %s has reference to non-existent template", reg_mail.registration_id, reg_mail.scheduler_id) _logger.warning(
"""
Cannot process ticket %s, because Mail Scheduler %s has
reference to non-existent template
""",
reg_mail.registration_id,
reg_mail.scheduler_id,
)
continue continue
if not template.email_from: if not template.email_from:
email_values['email_from'] = author.email_formatted email_values["email_from"] = author.email_formatted
template.send_mail(reg_mail.registration_id.id, email_values=email_values) template.send_mail(reg_mail.registration_id.id, email_values=email_values)
done |= reg_mail done |= reg_mail
done.write({'mail_sent': True}) done.write({"mail_sent": True})
return res return res

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<data> <data>
<record model="ir.ui.view" id="view_event_form_event_mail_manual"> <record model="ir.ui.view" id="view_event_form_event_mail_manual">
@@ -6,22 +6,41 @@
<field name="inherit_id" ref="event.view_event_form" /> <field name="inherit_id" ref="event.view_event_form" />
<field name="model">event.event</field> <field name="model">event.event</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='event_mail_ids']/tree/field[@name='mail_state']" position="after"> <xpath
expr="//field[@name='event_mail_ids']/tree/field[@name='mail_state']"
position="after"
>
<button <button
name="send" name="send"
type="object" type="object"
icon="fa-bullhorn" icon="fa-bullhorn"
attrs="{'invisible':[('notification_type','!=','mail_manual')]}" attrs="{'invisible':[('notification_type','!=','mail_manual')]}"
confirm="Send mail to all attendees ?" /> confirm="Send mail to all attendees ?"
/>
</xpath> </xpath>
<xpath expr="//field[@name='event_mail_ids']/tree/field[@name='interval_nbr']" position="attributes"> <xpath
<attribute name="attrs">{'readonly':['|',('interval_unit','=','now'),('notification_type','=','mail_manual')]}</attribute> expr="//field[@name='event_mail_ids']/tree/field[@name='interval_nbr']"
position="attributes"
>
<attribute
name="attrs"
>{'readonly':['|',('interval_unit','=','now'),('notification_type','=','mail_manual')]}</attribute>
</xpath> </xpath>
<xpath expr="//field[@name='event_mail_ids']/tree/field[@name='interval_unit']" position="attributes"> <xpath
<attribute name="attrs">{'readonly':[('notification_type','=','mail_manual')]}</attribute> expr="//field[@name='event_mail_ids']/tree/field[@name='interval_unit']"
position="attributes"
>
<attribute
name="attrs"
>{'readonly':[('notification_type','=','mail_manual')]}</attribute>
</xpath> </xpath>
<xpath expr="//field[@name='event_mail_ids']/tree/field[@name='interval_type']" position="attributes"> <xpath
<attribute name="attrs">{'readonly':[('notification_type','=','mail_manual')]}</attribute> expr="//field[@name='event_mail_ids']/tree/field[@name='interval_type']"
position="attributes"
>
<attribute
name="attrs"
>{'readonly':[('notification_type','=','mail_manual')]}</attribute>
</xpath> </xpath>
</field> </field>
</record> </record>

View File

@@ -7,16 +7,16 @@
"version": "16.0.1.0.0", "version": "16.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
"category": "", "category": "",
"depends": ["event", "website_event_track"], "depends": ["event", "website_event_track"],
"data": [ "data": [
'security/ir.model.access.csv', "security/ir.model.access.csv",
'views/event_sequence_views.xml', "views/event_sequence_views.xml",
'views/event_track_views.xml', "views/event_track_views.xml",
'views/event_event_views.xml', "views/event_event_views.xml",
'views/event_sequence_menu.xml', "views/event_sequence_menu.xml",
'data/event_sequence_data.xml', "data/event_sequence_data.xml",
], ],
"installable": True, "installable": True,
} }

View File

@@ -18,6 +18,7 @@ msgstr ""
#. module: event_sequence #. module: event_sequence
#: model:ir.model.fields,field_description:event_sequence.field_event_event__current_sequence_id #: model:ir.model.fields,field_description:event_sequence.field_event_event__current_sequence_id
#: model_terms:ir.ui.view,arch_db:event_sequence.view_event_form_event_sequence
msgid "Current sequence" msgid "Current sequence"
msgstr "Séquence en cours" msgstr "Séquence en cours"
@@ -45,12 +46,6 @@ msgstr "Séquence"
msgid "Sequences" msgid "Sequences"
msgstr "Séquences" msgstr "Séquences"
#. module: event_sequence
#: model_terms:ir.ui.view,arch_db:event_sequence.view_event_form_event_sequence
msgid "Current sequence"
msgstr "Séquence en cours"
#. module: event_sequence #. module: event_sequence
#: model_terms:ir.ui.view,arch_db:event_sequence.view_event_track_by_sequence_kanban #: model_terms:ir.ui.view,arch_db:event_sequence.view_event_track_by_sequence_kanban
msgid "hours" msgid "hours"

View File

@@ -1,9 +1,8 @@
from odoo import _, api, Command, fields, models from odoo import fields, models
from lxml import etree, html
from odoo.tools import format_time
class EventEvent(models.Model): class EventEvent(models.Model):
_inherit = "event.event" _inherit = "event.event"
sequence_number = fields.Integer('Number of sequences', default="5") sequence_number = fields.Integer("Number of sequences", default="5")
current_sequence_id = fields.Many2one('event.sequence', 'Current sequence') current_sequence_id = fields.Many2one("event.sequence", "Current sequence")

View File

@@ -5,5 +5,5 @@ from odoo import fields, models
class EventSequence(models.Model): class EventSequence(models.Model):
_name = "event.sequence" _name = "event.sequence"
name = fields.Char("name") name = fields.Char()
sequence = fields.Integer("Sequence") #for sorting sequence = fields.Integer() # for sorting

View File

@@ -1,22 +1,21 @@
from odoo import _, api, Command, fields, models from odoo import api, fields, models
from lxml import etree, html
from odoo.tools import format_time
class EventTrack(models.Model): class EventTrack(models.Model):
_inherit = "event.track" _inherit = "event.track"
sequence_id = fields.Many2one('event.sequence', 'Sequence', group_expand='_read_group_stage_ids') sequence_id = fields.Many2one(
sequence = fields.Integer('Sequence') #for sorting "event.sequence", "Sequence", group_expand="_read_group_stage_ids"
)
sequence = fields.Integer() # for sorting
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):
if vals_list and 'sequence' not in vals_list[0]: if vals_list and "sequence" not in vals_list[0]:
vals_list[0]['sequence'] = 999 vals_list[0]["sequence"] = 999
tracks = super(EventTrack, self).create(vals_list) tracks = super().create(vals_list)
return tracks return tracks
@api.model @api.model
def _read_group_stage_ids(self, stages, domain, order): def _read_group_stage_ids(self, stages, domain, order):
event_id = None event_id = None
@@ -25,8 +24,7 @@ class EventTrack(models.Model):
event_id = d[2] event_id = d[2]
if event_id: if event_id:
event = self.env['event.event'].browse(event_id) event = self.env["event.event"].browse(event_id)
return stages.search([], order="sequence", limit=event.sequence_number) return stages.search([], order="sequence", limit=event.sequence_number)
return stages.search([], order="sequence") return stages.search([], order="sequence")

View File

@@ -10,8 +10,12 @@
<field name="sequence_number" /> <field name="sequence_number" />
</label> </label>
<h1 position="after"> <h1 position="after">
<label for="current_sequence_id" string="Current sequence"/> <label for="current_sequence_id" string="Current sequence" />
<h4><field class="text-break" name="current_sequence_id" style="width:150px;" /></h4> <h4><field
class="text-break"
name="current_sequence_id"
style="width:150px;"
/></h4>
</h1> </h1>
</field> </field>
</record> </record>

View File

@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<menuitem id="event_sequence_menu" <menuitem
id="event_sequence_menu"
name="Sequences" name="Sequences"
action="event_sequence_action" action="event_sequence_action"
parent="event.menu_event_configuration" parent="event.menu_event_configuration"
sequence="31"/> sequence="31"
/>
</odoo> </odoo>

View File

@@ -15,6 +15,6 @@
<field name="name">Sequences</field> <field name="name">Sequences</field>
<field name="res_model">event.sequence</field> <field name="res_model">event.sequence</field>
<field name="view_mode">tree</field> <field name="view_mode">tree</field>
<field name="view_id" ref="view_event_sequence_tree"/> <field name="view_id" ref="view_event_sequence_tree" />
</record> </record>
</odoo> </odoo>

View File

@@ -4,51 +4,108 @@
<field name="name">event.track.by.sequence.kanban</field> <field name="name">event.track.by.sequence.kanban</field>
<field name="model">event.track</field> <field name="model">event.track</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<kanban default_order="sequence" group_create="false" default_group_by="sequence_id" quick_create_view="website_event_track.event_track_view_form_quick_create"> <kanban
<field name="color"/> default_order="sequence"
<field name="partner_id"/> group_create="false"
default_group_by="sequence_id"
quick_create_view="website_event_track.event_track_view_form_quick_create"
>
<field name="color" />
<field name="partner_id" />
<field name="sequence_id" options="{'create':false}" /> <field name="sequence_id" options="{'create':false}" />
<field name="stage_id" options='{"group_by_tooltip": {"description": "Description"}}'/> <field
<field name="website_url"/> name="stage_id"
<field name="activity_ids"/> options='{"group_by_tooltip": {"description": "Description"}}'
<field name="activity_state"/> />
<field name="legend_blocked"/> <field name="website_url" />
<field name="legend_normal"/> <field name="activity_ids" />
<field name="legend_done"/> <field name="activity_state" />
<field name="legend_blocked" />
<field name="legend_normal" />
<field name="legend_done" />
<templates> <templates>
<progressbar field="kanban_state" colors='{"done": "success", "blocked": "danger"}'/> <progressbar
field="kanban_state"
colors='{"done": "success", "blocked": "danger"}'
/>
<t t-name="kanban-box"> <t t-name="kanban-box">
<div t-attf-class="{{!selection_mode ? 'oe_kanban_color_' + kanban_getcolor(record.color.raw_value) : ''}} oe_kanban_card oe_kanban_global_click"> <div
<div class="o_dropdown_kanban dropdown" groups="base.group_user"> t-attf-class="{{!selection_mode ? 'oe_kanban_color_' + kanban_getcolor(record.color.raw_value) : ''}} oe_kanban_card oe_kanban_global_click"
>
<div
class="o_dropdown_kanban dropdown"
groups="base.group_user"
>
<a role="button" class="dropdown-toggle o-no-caret btn" data-bs-toggle="dropdown" href="#" aria-label="Dropdown menu" title="Dropdown menu"> <a
<span class="fa fa-ellipsis-v"/> role="button"
class="dropdown-toggle o-no-caret btn"
data-bs-toggle="dropdown"
href="#"
aria-label="Dropdown menu"
title="Dropdown menu"
>
<span class="fa fa-ellipsis-v" />
</a> </a>
<div class="dropdown-menu" role="menu"> <div class="dropdown-menu" role="menu">
<a role="menuitem" t-att-href="record.website_url.value" class="dropdown-item">View Track</a> <a
<t t-if="widget.editable"><a role="menuitem" type="edit" class="dropdown-item">Edit Track</a></t> role="menuitem"
<t t-if="widget.deletable"><a role="menuitem" type="delete" class="dropdown-item">Delete</a></t> t-att-href="record.website_url.value"
<ul class="oe_kanban_colorpicker" data-field="color"/> class="dropdown-item"
>View Track</a>
<t t-if="widget.editable"><a
role="menuitem"
type="edit"
class="dropdown-item"
>Edit Track</a></t>
<t t-if="widget.deletable"><a
role="menuitem"
type="delete"
class="dropdown-item"
>Delete</a></t>
<ul
class="oe_kanban_colorpicker"
data-field="color"
/>
</div> </div>
</div> </div>
<div class="oe_kanban_content"> <div class="oe_kanban_content">
<div class="o_kanban_record_top"> <div class="o_kanban_record_top">
<h4 class="o_kanban_record_title"><field name="name"/></h4> <h4 class="o_kanban_record_title"><field
name="name"
/></h4>
</div> </div>
<div class="o_kanban_record_body"> <div class="o_kanban_record_body">
<t t-if="duration"><field name="duration" widget="float_time"/> hours</t> <t t-if="duration"><field
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/> name="duration"
widget="float_time"
/> hours</t>
<field
name="tag_ids"
widget="many2many_tags"
options="{'color_field': 'color'}"
/>
</div> </div>
<div class="o_kanban_record_bottom"> <div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left"> <div class="oe_kanban_bottom_left">
<field name="priority" widget="priority"/> <field name="priority" widget="priority" />
<field name="activity_ids" widget="kanban_activity"/> <field
name="activity_ids"
widget="kanban_activity"
/>
</div> </div>
<div class="oe_kanban_bottom_right"> <div class="oe_kanban_bottom_right">
<field name="kanban_state" widget="state_selection" groups="base.group_user"/> <field
<img t-att-src="kanban_image('res.partner', 'avatar_128', record.partner_id.raw_value)" name="kanban_state"
t-att-title="record.partner_id.value" t-att-alt="record.partner_id.value" widget="state_selection"
class="oe_kanban_avatar"/> groups="base.group_user"
/>
<img
t-att-src="kanban_image('res.partner', 'avatar_128', record.partner_id.raw_value)"
t-att-title="record.partner_id.value"
t-att-alt="record.partner_id.value"
class="oe_kanban_avatar"
/>
</div> </div>
</div> </div>
</div> </div>
@@ -59,10 +116,19 @@
</field> </field>
</record> </record>
<record model="ir.actions.act_window.view" id="action_event_track_from_event_kanban"> <record
<field name="sequence" eval="1"/> model="ir.actions.act_window.view"
id="action_event_track_from_event_kanban"
>
<field name="sequence" eval="1" />
<field name="view_mode">kanban</field> <field name="view_mode">kanban</field>
<field name="act_window_id" ref="website_event_track.action_event_track_from_event"/> <field
<field name="view_id" ref="event_sequence.view_event_track_by_sequence_kanban"/> name="act_window_id"
ref="website_event_track.action_event_track_from_event"
/>
<field
name="view_id"
ref="event_sequence.view_event_track_by_sequence_kanban"
/>
</record> </record>
</odoo> </odoo>

View File

@@ -5,12 +5,12 @@
"version": "16.0.1.0.0", "version": "16.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
'summary': 'Not usefull anymore for CTL', "summary": "Not usefull anymore for CTL",
"category": "", "category": "",
"depends": ["website_event_track"], "depends": ["website_event_track"],
"data": [ "data": [
'views/event_track_views.xml', "views/event_track_views.xml",
], ],
"installable": True, "installable": True,
} }

View File

@@ -1,2 +1,2 @@
from . import event_track from . import event_track
#from . import event_event # from . import event_event

View File

@@ -6,5 +6,5 @@ class EventTrack(models.Model):
_inherit = "event.track" _inherit = "event.track"
speaker_ids = fields.Many2many( speaker_ids = fields.Many2many(
'res.partner', string="Speakers", domain="[('is_company','=',False)]" "res.partner", string="Speakers", domain="[('is_company','=',False)]"
) )

View File

@@ -5,19 +5,17 @@
"version": "16.0.1.0.0", "version": "16.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
"category": "", "category": "",
'summary': 'Replace date of event track with list of calendar events', "summary": "Replace date of event track with list of calendar events",
'description': """ "description": """
Replace date of event track with list of calendar events Replace date of event track with list of calendar events
---------------------------------------------------- ----------------------------------------------------
* Create calendar events on event track form * Create calendar events on event track form
* Sync calendar event attendees with event track registration * Sync calendar event attendees with event track registration
""", """,
"depends": ["website_event_track","calendar"], "depends": ["website_event_track", "calendar"],
"data": [ "data": ["views/event_track_views.xml"],
"views/event_track_views.xml"
],
"installable": True, "installable": True,
} }

View File

@@ -1,18 +1,16 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command from odoo import api, fields, models
class CalendarEvent(models.Model): class CalendarEvent(models.Model):
_inherit = 'calendar.event' _inherit = "calendar.event"
event_track_id = fields.Many2one('event.track', "Event track") event_track_id = fields.Many2one("event.track", "Event track")
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):
res = super(CalendarEvent,self).create(vals_list) res = super().create(vals_list)
for event in res: for event in res:
if event.event_track_id: if event.event_track_id:
event.event_track_id.sync_calendar_event() event.event_track_id.sync_calendar_event()
return res return res

View File

@@ -1,8 +1,11 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command
import logging import logging
from odoo import models
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class EventEvent(models.Model): class EventEvent(models.Model):
_inherit = "event.event" _inherit = "event.event"

View File

@@ -1,13 +1,16 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command
import logging import logging
from odoo import api, models
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class EventRegistration(models.Model): class EventRegistration(models.Model):
_inherit = "event.registration" _inherit = "event.registration"
def write(self, vals): def write(self, vals):
res = super(EventRegistration,self).write(vals) res = super().write(vals)
for registration in self: for registration in self:
for track in registration.event_id.track_ids: for track in registration.event_id.track_ids:
track.sync_calendar_event() track.sync_calendar_event()
@@ -15,7 +18,7 @@ class EventRegistration(models.Model):
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):
res = super(EventRegistration, self).create(vals_list) res = super().create(vals_list)
for registration in res: for registration in res:
for track in registration.event_id.track_ids: for track in registration.event_id.track_ids:
track.sync_calendar_event() track.sync_calendar_event()

View File

@@ -1,41 +1,49 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command
from datetime import timedelta
import logging import logging
from odoo import Command, api, fields, models
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class EventTrack(models.Model): class EventTrack(models.Model):
_inherit = "event.track" _inherit = "event.track"
calendar_event_ids = fields.One2many('calendar.event', 'event_track_id', 'Time slot', copy=True) calendar_event_ids = fields.One2many(
"calendar.event", "event_track_id", "Time slot", copy=True
)
date = fields.Datetime(compute="_compute_date") date = fields.Datetime(compute="_compute_date")
def _compute_date(self): def _compute_date(self):
"""Date become a field computed from first calendar event date """
Date become a field computed from first calendar event date.
""" """
for event_track in self: for event_track in self:
if event_track.calendar_event_ids: if event_track.calendar_event_ids:
event_track.date = event_track.calendar_event_ids.sorted(key=lambda r: r.start)[0].start event_track.date = event_track.calendar_event_ids.sorted(
key=lambda r: r.start
)[0].start
else: else:
event_track.date = None event_track.date = None
def get_calendar_event_values(self): def get_calendar_event_values(self):
"""return default values of calendar events """
Return default values of calendar events.
""" """
return { return {
# due to google calendar unexpected notifications, for the moment we disable attendees of calendar event # due to google calendar unexpected notifications, for the moment we
# disable attendees of calendar event
# uncomment following line to re-enable # uncomment following line to re-enable
#'partner_ids':[Command.set(self.get_calendar_event_partner_value())], #'partner_ids':[Command.set(self.get_calendar_event_partner_value())],
'partner_ids':[Command.set([])], "partner_ids": [Command.set([])],
'location':self.location_id.name if self.location_id else '', "location": self.location_id.name if self.location_id else "",
#'user_id':self.user_id.id, #'user_id':self.user_id.id,
'privacy':"confidential" "privacy": "confidential",
} }
def get_calendar_event_partner_value(self): def get_calendar_event_partner_value(self):
"""Compute list of partner ids for calendar event """
Compute list of partner ids for calendar event.
""" """
# compute list of attendees # compute list of attendees
partner_ids = [] partner_ids = []
@@ -45,40 +53,46 @@ class EventTrack(models.Model):
partner_ids.append(self.partner_id.id) partner_ids.append(self.partner_id.id)
# add event registration attendees # add event registration attendees
partner_ids.extend([registration.partner_id.id for registration in self.event_id.registration_ids if registration.partner_id]) partner_ids.extend(
[
registration.partner_id.id
for registration in self.event_id.registration_ids
if registration.partner_id
]
)
return partner_ids return partner_ids
def sync_calendar_event(self): def sync_calendar_event(self):
"""synchronize calendar event values with event track data """
Synchronize calendar event values with event track data.
""" """
_logger.warning("sync_calendar_event...") _logger.warning("sync_calendar_event...")
for track in self: for track in self:
track.calendar_event_ids.with_context(no_mail_to_attendees=True).write(track.get_calendar_event_values()) track.calendar_event_ids.with_context(no_mail_to_attendees=True).write(
track.get_calendar_event_values()
)
_logger.warning("sync_calendar_event done !") _logger.warning("sync_calendar_event done !")
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):
""" """
after creation of event track synchronise calendar event values After creation of event track synchronise calendar event values.
""" """
res = super(EventTrack, self).create(vals_list) res = super().create(vals_list)
res.sync_calendar_event() res.sync_calendar_event()
return res return res
def write(self, vals): def write(self, vals):
""" """
after modification of event track synchronise calendar event values After modification of event track synchronise calendar event values.
""" """
res = super().write(vals) res = super().write(vals)
self.sync_calendar_event() self.sync_calendar_event()
return res return res
def unlink(self): def unlink(self):
for track in self: for track in self:
for calendar_event in track.calendar_event_ids: for calendar_event in track.calendar_event_ids:
calendar_event.unlink() calendar_event.unlink()
return super(EventTrack, self).unlink() return super().unlink()

View File

@@ -11,7 +11,11 @@
<!-- <field name="date" position="replace" /> --> <!-- <field name="date" position="replace" /> -->
<page name="speaker" position="before"> <page name="speaker" position="before">
<page name="calendar_events" string="Plages horaires"> <page name="calendar_events" string="Plages horaires">
<field name="calendar_event_ids" context="{'default_name':name}" colspan="2"> <field
name="calendar_event_ids"
context="{'default_name':name}"
colspan="2"
>
<tree default_order="start,stop" editable="bottom"> <tree default_order="start,stop" editable="bottom">
<field name="name" string="Name" invisible="1" /> <field name="name" string="Name" invisible="1" />
<field name="start" string="From" /> <field name="start" string="From" />

View File

@@ -7,13 +7,11 @@
"version": "16.0.1.0.0", "version": "16.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
"category": "", "category": "",
'summary': 'Speaker management in calendar events of event tracks', "summary": "Speaker management in calendar events of event tracks",
"depends": ["event_track_calendar_event"], "depends": ["event_track_calendar_event"],
"data": [ "data": ["views/event_track_views.xml"],
"views/event_track_views.xml"
],
"installable": True, "installable": True,
"auto_install":True "auto_install": True,
} }

View File

@@ -1,10 +1,15 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command from odoo import fields, models
class CalendarEvent(models.Model): class CalendarEvent(models.Model):
_inherit = 'calendar.event' _inherit = "calendar.event"
speaker_ids = fields.Many2many( speaker_ids = fields.Many2many(
'res.partner', "calendar_event_speaker_rel", "calendar_event_id", "speaker_id", string="Intervenants", domain="[('is_company','=',False)]" "res.partner",
"calendar_event_speaker_rel",
"calendar_event_id",
"speaker_id",
string="Intervenants",
domain="[('is_company','=',False)]",
) )

View File

@@ -1,28 +1,28 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command from odoo import fields, models
class EventTrack(models.Model): class EventTrack(models.Model):
_inherit = "event.track" _inherit = "event.track"
speaker_ids = fields.Many2many( speaker_ids = fields.Many2many(
'res.partner', string="Intervenants", compute="compute_speaker_ids" "res.partner", string="Intervenants", compute="_compute_speaker_ids"
) )
def compute_speaker_ids(self): def _compute_speaker_ids(self):
"""set speaker_ids as concat of all speakers of all events""" """
Set speaker_ids as concat of all speakers of all events.
"""
for track in self: for track in self:
speaker_ids = set() speaker_ids = set()
for event in track.calendar_event_ids: for event in track.calendar_event_ids:
speaker_ids.update(event.speaker_ids.ids) speaker_ids.update(event.speaker_ids.ids)
track.speaker_ids = list(speaker_ids) track.speaker_ids = list(speaker_ids)
def get_calendar_event_partner_value(self): def get_calendar_event_partner_value(self):
"""Add speaker ids to calendar event partners
""" """
res = super(EventTrack, self).get_calendar_event_partner_value() Add speaker ids to calendar event partners.
"""
res = super().get_calendar_event_partner_value()
res.extend(self.speaker_ids.ids) res.extend(self.speaker_ids.ids)
return res return res

View File

@@ -1,12 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record model="ir.ui.view" id="view_event_track_form_event_track_calendar_event_event_speaker"> <record
<field name="name">event.track.form.event.track.calendar.event.event.speaker</field> model="ir.ui.view"
<field name="inherit_id" ref="event_track_calendar_event.view_event_track_form_event_track_calendar_event" /> id="view_event_track_form_event_track_calendar_event_event_speaker"
>
<field
name="name"
>event.track.form.event.track.calendar.event.event.speaker</field>
<field
name="inherit_id"
ref="event_track_calendar_event.view_event_track_form_event_track_calendar_event"
/>
<field name="model">event.track</field> <field name="model">event.track</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='calendar_event_ids']/tree/field[@name='description']" position="after"> <xpath
<field name="speaker_ids" widget="many2many_tags"/> expr="//field[@name='calendar_event_ids']/tree/field[@name='description']"
position="after"
>
<field name="speaker_ids" widget="many2many_tags" />
</xpath> </xpath>
<!-- <xpath expr="//field[@name='calendar_event_ids']/form//field[@name='description']" position="after"> <!-- <xpath expr="//field[@name='calendar_event_ids']/form//field[@name='description']" position="after">

View File

@@ -7,23 +7,21 @@
"version": "16.0.1.0.0", "version": "16.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
"category": "", "category": "",
'summary': 'Link event tracks locations to calendar event', "summary": "Link event tracks locations to calendar event",
'description': """ "description": """
Link event tracks locations to calendar event Link event tracks locations to calendar event
---------------------------------------------------- ----------------------------------------------------
* Add Partner field on event track location * Add Partner field on event track location
* Add partner "location" to calendar event * Add partner "location" to calendar event
* Update calendar event if event track location change (or partner in event track location) * Update calendar event if event track location change
(or partner in event track location)
* Alert if location is used * Alert if location is used
""", """,
"depends": ["website_event_track","calendar"], "depends": ["website_event_track", "calendar"],
"data": [ "data": ["views/event_track_location_views.xml", "views/event_track_views.xml"],
'views/event_track_location_views.xml',
'views/event_track_views.xml'
],
"installable": True, "installable": True,
} }

View File

@@ -1,17 +1,19 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command, _ from odoo import api, fields, models
from datetime import timedelta
from odoo.tools import format_date from odoo.tools import format_date
class EventTrack(models.Model): class EventTrack(models.Model):
_inherit = "event.track" _inherit = "event.track"
location_already_in_use = fields.Boolean(
"Location already in use", compute="_compute_location_already_in_use"
)
location_already_in_use_message = fields.Text(
compute="_compute_location_already_in_use"
)
location_already_in_use = fields.Boolean('Location already in use', compute='_compute_location_already_in_use') @api.depends("date", "duration", "location_id")
location_already_in_use_message = fields.Text(compute='_compute_location_already_in_use')
@api.depends('date', 'duration', 'location_id')
def _compute_location_already_in_use(self): def _compute_location_already_in_use(self):
for track in self: for track in self:
location_already_in_use = False location_already_in_use = False
@@ -21,40 +23,59 @@ class EventTrack(models.Model):
for calendar_event in track.calendar_event_ids: for calendar_event in track.calendar_event_ids:
if track.location_id and calendar_event.start: if track.location_id and calendar_event.start:
# search if other calendar event exists for same day on
# same location
search_other_calendar_events = [
("event_track_id.location_id", "=", track.location_id.id),
("start", ">=", calendar_event.start.replace(hour=0, minute=0)),
(
"start",
"<=",
calendar_event.start.replace(hour=23, minute=59),
),
]
#search if other calendar event exists for same day on same location # search only on other event tracks
search_other_calendar_events = [('event_track_id.location_id','=',track.location_id.id),('start','>=',calendar_event.start.replace(hour=0,minute=0)),('start','<=',calendar_event.start.replace(hour=23,minute=59))]
#search only on other event tracks
if track.id or track.id.origin: if track.id or track.id.origin:
search_other_calendar_events.append(('event_track_id','!=',track.id or track.id.origin)) search_other_calendar_events.append(
("event_track_id", "!=", track.id or track.id.origin)
)
#search calendar events not already founded # search calendar events not already founded
if already_found_other_calendar_event_ids: if already_found_other_calendar_event_ids:
search_other_calendar_events.append(('id','not in',already_found_other_calendar_event_ids)) search_other_calendar_events.append(
("id", "not in", already_found_other_calendar_event_ids)
)
other_calendar_events = self.env["calendar.event"].search(search_other_calendar_events) other_calendar_events = self.env["calendar.event"].search(
already_found_other_calendar_event_ids.extend(other_calendar_events.ids) search_other_calendar_events
)
already_found_other_calendar_event_ids.extend(
other_calendar_events.ids
)
if other_calendar_events: if other_calendar_events:
location_already_in_use = True location_already_in_use = True
for other_calendar_event in other_calendar_events: for other_calendar_event in other_calendar_events:
location_already_in_use_message += other_calendar_event.event_track_id.event_id.name+" - "+\ location_already_in_use_message += (
other_calendar_event.event_track_id.name+\ other_calendar_event.event_track_id.event_id.name
" ("+format_date(self.env, other_calendar_event.start)+")"+"\n" + " - "
+ other_calendar_event.event_track_id.name
+ " ("
+ format_date(self.env, other_calendar_event.start)
+ ")"
+ "\n"
)
track.location_already_in_use = location_already_in_use track.location_already_in_use = location_already_in_use
track.location_already_in_use_message = location_already_in_use_message track.location_already_in_use_message = location_already_in_use_message
def get_calendar_event_partner_value(self): def get_calendar_event_partner_value(self):
"""Add event track location partner to list of partner ids """
Add event track location partner to list of partner ids.
""" """
res = super(EventTrack, self).get_calendar_event_partner_value() res = super().get_calendar_event_partner_value()
if self.location_id and self.location_id.partner_id: if self.location_id and self.location_id.partner_id:
res.append(self.location_id.partner_id.id) res.append(self.location_id.partner_id.id)
return res return res

View File

@@ -1,17 +1,22 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api from odoo import fields, models
class EventTrackLocation(models.Model): class EventTrackLocation(models.Model):
_inherit = 'event.track.location' _inherit = "event.track.location"
partner_id = fields.Many2one('res.partner', 'Address', domain="[('is_company','=',True)]") partner_id = fields.Many2one(
"res.partner", "Address", domain="[('is_company','=',True)]"
)
def write(self, vals): def write(self, vals):
"""update calendar events related to event tracks if partner change
""" """
res = super(EventTrackLocation, self).write(vals) Update calendar events related to event tracks if partner change.
if 'partner_id' in vals: """
event_tracks = self.env['event.track'].search([('location_id','in',self.ids)]) res = super().write(vals)
if "partner_id" in vals:
event_tracks = self.env["event.track"].search(
[("location_id", "in", self.ids)]
)
event_tracks.sync_calendar_event() event_tracks.sync_calendar_event()
return res return res

View File

@@ -1,9 +1,14 @@
<?xml version="1.0"?> <?xml version="1.0" ?>
<odoo> <odoo>
<!-- EVENTS/CONFIGURATION/EVENT locations --> <!-- EVENTS/CONFIGURATION/EVENT locations -->
<record model="ir.ui.view" id="view_event_location_form_inherit_event_track_location_calendar"> <record
<field name="name">Event Locations inherit for event track location calendar</field> model="ir.ui.view"
id="view_event_location_form_inherit_event_track_location_calendar"
>
<field
name="name"
>Event Locations inherit for event track location calendar</field>
<field name="model">event.track.location</field> <field name="model">event.track.location</field>
<field name="inherit_id" ref="website_event_track.view_event_location_form" /> <field name="inherit_id" ref="website_event_track.view_event_location_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
@@ -13,7 +18,10 @@
</field> </field>
</record> </record>
<record model="ir.ui.view" id="view_event_location_tree_inherit_event_track_location_calendar"> <record
model="ir.ui.view"
id="view_event_location_tree_inherit_event_track_location_calendar"
>
<field name="name">Event Location</field> <field name="name">Event Location</field>
<field name="model">event.track.location</field> <field name="model">event.track.location</field>
<field name="inherit_id" ref="website_event_track.view_event_location_tree" /> <field name="inherit_id" ref="website_event_track.view_event_location_tree" />

View File

@@ -1,14 +1,25 @@
<?xml version="1.0"?> <?xml version="1.0" ?>
<odoo> <odoo>
<record model="ir.ui.view" id="view_event_track_form_inherit_event_track_location_calendar"> <record
<field name="name">event.track.form inherit for event track location calendar</field> model="ir.ui.view"
id="view_event_track_form_inherit_event_track_location_calendar"
>
<field
name="name"
>event.track.form inherit for event track location calendar</field>
<field name="model">event.track</field> <field name="model">event.track</field>
<field name="inherit_id" ref="website_event_track.view_event_track_form" /> <field name="inherit_id" ref="website_event_track.view_event_track_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//header" position="after"> <xpath expr="//header" position="after">
<field name="location_already_in_use" invisible="1" /> <field name="location_already_in_use" invisible="1" />
<div attrs="{'invisible':[('location_already_in_use','=',False)]}" class="alert alert-warning mb-0" role="alert"> <div
<strong>Location already in use for this date !</strong><field name="location_already_in_use_message" /> attrs="{'invisible':[('location_already_in_use','=',False)]}"
class="alert alert-warning mb-0"
role="alert"
>
<strong>Location already in use for this date !</strong><field
name="location_already_in_use_message"
/>
</div> </div>
</xpath> </xpath>
</field> </field>

View File

@@ -7,15 +7,13 @@
"version": "16.0.1.0.0", "version": "16.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
"category": "", "category": "",
'summary': 'Copy website event tracks when copy event', "summary": "Copy website event tracks when copy event",
'description': """Copy website event tracks when copy event "description": """Copy website event tracks when copy event
""", """,
"depends": ["website_event_track"], "depends": ["website_event_track"],
"data": [ "data": [],
],
"installable": True, "installable": True,
} }

View File

@@ -1,9 +1,12 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command
import logging import logging
from odoo import fields, models
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class EventEvent(models.Model): class EventEvent(models.Model):
_inherit = "event.event" _inherit = "event.event"
track_ids = fields.One2many(copy=True) #enable copy for event tracks track_ids = fields.One2many(copy=True) # enable copy for event tracks

View File

@@ -1,12 +1,14 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, Command
from datetime import timedelta
import logging import logging
from odoo import fields, models
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class EventTrack(models.Model): class EventTrack(models.Model):
_inherit = "event.track" _inherit = "event.track"
event_id = fields.Many2one(ondelete='cascade') #delete event tracks when delete event event_id = fields.Many2one(
ondelete="cascade"
) # delete event tracks when delete event

View File

View File

@@ -7,11 +7,11 @@
"version": "16.0.1.0.0", "version": "16.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Elabore", "author": "Elabore",
"website": "https://www.elabore.coop", "website": "https://github.com/elabore-coop/event-tools",
"category": "", "category": "",
"depends": ["event"], "depends": ["event"],
"data": [ "data": [
'views/event_type_views.xml', "views/event_type_views.xml",
], ],
"installable": True, "installable": True,
} }

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="event_type_form_view" model="ir.ui.view"> <record id="event_type_form_view" model="ir.ui.view">
<field name="name">event.type.form</field> <field name="name">event.type.form</field>
<field name="model">event.type</field> <field name="model">event.type</field>
<field eval="7" name="priority"/> <field eval="7" name="priority" />
<field name="inherit_id" ref="event.view_event_type_form"/> <field name="inherit_id" ref="event.view_event_type_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<div name="event_type_title" position="before"> <div name="event_type_title" position="before">
<div name="button_box" class="oe_button_box" /> <div name="button_box" class="oe_button_box" />