[MERGE] event(_sale/_track): improve sponsors and attendees integration
Purpose
=======
Improve the sponsors and attendees integration in event. Focus on :
* sponsor management: transform it into a real business document allowing
to communicate with sponsors) ;
* attendee management: improve views, ease searching / updating them in
batch;
Specifications
==============
Sponsors
--------
Move all the views related to sponsor and sponsor type to their own file to
clean module organization.
Add integration with mailgateway and activities through mail.thread and
mail.activity.mixin inheritance.
Improve sponsor views: add a real form view and add a small kanban view
displaying some partner / sponsor information.
Attendees
---------
In order to allow state management in batch, state field is made editable in
multi edit mode of registrations. That way event managers are able to work in
batch. It required to move some code currently called in custom action-called
methods directly in write. It makes sense to consider that some required code
is called by writing on state field instead of depending on calling the right
method. Indeed there is not much "business" code to move: calling mail
schedulers on confirmation, and putting the closing date when closing.
Event and registration tree views are improved, some fields are now editable
in multi edit mode.
When a user register on a event from website, it will create a sale order and
a partner (the customer of the SO). Set automatically the partner of the
registration to the partner of the sale order.
Other
-----
This merge include a fix in mass mailing (default domain propagation) and
web (void values display for phone widget). See sub commits for more details.
Task ID 2119333
PR #40949
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -61,9 +61,21 @@ class EventRegistration(models.Model):
|
||||
def create(self, vals):
|
||||
registration = super(EventRegistration, self).create(vals)
|
||||
if registration._check_auto_confirmation():
|
||||
registration.sudo().confirm_registration()
|
||||
registration.sudo().action_confirm()
|
||||
return registration
|
||||
|
||||
def write(self, vals):
|
||||
ret = super(EventRegistration, self).write(vals)
|
||||
|
||||
if vals.get('state') == 'open':
|
||||
# auto-trigger after_sub (on subscribe) mail schedulers, if needed
|
||||
onsubscribe_schedulers = self.mapped('event_id.event_mail_ids').filtered(lambda s: s.interval_type == 'after_sub')
|
||||
onsubscribe_schedulers.execute()
|
||||
elif vals.get('state') == 'done' and 'date_closed' not in vals:
|
||||
vals['date_closed'] = fields.Datetime.now()
|
||||
|
||||
return ret
|
||||
|
||||
@api.model
|
||||
def _prepare_attendee_values(self, registration):
|
||||
""" Method preparing the values to create new attendees based on a
|
||||
@@ -83,23 +95,38 @@ class EventRegistration(models.Model):
|
||||
data.update({key: value for key, value in registration.items() if key in self._fields})
|
||||
return data
|
||||
|
||||
def do_draft(self):
|
||||
def name_get(self):
|
||||
""" Custom name_get implementation to better differentiate registrations
|
||||
linked to a given partner but with different name (one partner buying
|
||||
several registrations)
|
||||
|
||||
* name, partner_id has no name -> take name
|
||||
* partner_id has name, name void or same -> take partner name
|
||||
* both have name: partner + name
|
||||
"""
|
||||
ret_list = []
|
||||
for registration in self:
|
||||
if registration.partner_id.name:
|
||||
if registration.name and registration.name != registration.partner_id.name:
|
||||
name = '%s, %s' % (registration.partner_id.name, registration.name)
|
||||
else:
|
||||
name = registration.partner_id.name
|
||||
else:
|
||||
name = registration.name
|
||||
ret_list.append((registration.id, name))
|
||||
return ret_list
|
||||
|
||||
def action_set_draft(self):
|
||||
self.write({'state': 'draft'})
|
||||
|
||||
def confirm_registration(self):
|
||||
def action_confirm(self):
|
||||
self.write({'state': 'open'})
|
||||
|
||||
# auto-trigger after_sub (on subscribe) mail schedulers, if needed
|
||||
onsubscribe_schedulers = self.event_id.event_mail_ids.filtered(
|
||||
lambda s: s.interval_type == 'after_sub')
|
||||
onsubscribe_schedulers.execute()
|
||||
|
||||
def button_reg_close(self):
|
||||
def action_set_done(self):
|
||||
""" Close Registration """
|
||||
for registration in self:
|
||||
registration.write({'state': 'done', 'date_closed': fields.Datetime.now()})
|
||||
self.write({'state': 'done'})
|
||||
|
||||
def button_reg_cancel(self):
|
||||
def action_cancel(self):
|
||||
self.write({'state': 'cancel'})
|
||||
|
||||
@api.onchange('partner_id')
|
||||
|
||||
@@ -47,10 +47,10 @@ class TestEventFlow(TestEventCommon):
|
||||
})
|
||||
|
||||
# EventUser validates registrations
|
||||
test_reg1.button_reg_close()
|
||||
test_reg1.action_set_done()
|
||||
self.assertEqual(test_reg1.state, 'done', 'Event: wrong state of attended registration')
|
||||
self.assertEqual(test_event.seats_used, 1, 'Event: incorrect number of attendees after closing registration')
|
||||
test_reg2.button_reg_close()
|
||||
test_reg2.action_set_done()
|
||||
self.assertEqual(test_reg1.state, 'done', 'Event: wrong state of attended registration')
|
||||
self.assertEqual(test_event.seats_used, 2, 'Event: incorrect number of attendees after closing registration')
|
||||
|
||||
|
||||
@@ -291,18 +291,21 @@
|
||||
<field name="name">event.event.tree</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Events" decoration-bf="message_needaction==True" decoration-danger="(seats_min and seats_min>seats_reserved) or (seats_max and seats_max<seats_reserved)">
|
||||
<tree string="Events"
|
||||
decoration-bf="message_needaction==True"
|
||||
decoration-danger="(seats_min and seats_min>seats_reserved) or (seats_max and seats_max<seats_reserved)"
|
||||
multi_edit="1">
|
||||
<field name="name"/>
|
||||
<field name="event_type_id"/>
|
||||
<field name="date_begin"/>
|
||||
<field name="date_end"/>
|
||||
<field name="seats_reserved" sum="Total"/>
|
||||
<field name="seats_min"/>
|
||||
<field name="seats_max" invisible="1"/>
|
||||
<field name="user_id"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="activity_exception_decoration" widget="activity_exception"/>
|
||||
<field name="event_type_id" readonly="1"/>
|
||||
<field name="date_begin" readonly="1"/>
|
||||
<field name="date_end" readonly="1"/>
|
||||
<field name="seats_reserved" sum="Total" readonly="1"/>
|
||||
<field name="seats_min" readonly="1"/>
|
||||
<field name="seats_max" invisible="1" readonly="1"/>
|
||||
<field name="user_id" readonly="1"/>
|
||||
<field name="message_needaction" invisible="1" readonly="1"/>
|
||||
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
|
||||
<field name="activity_exception_decoration" widget="activity_exception" readonly="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -485,18 +488,20 @@
|
||||
<field name="name">event.registration.tree</field>
|
||||
<field name="model">event.registration</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Registration" decoration-bf="message_needaction==True">
|
||||
<field name="create_date"/>
|
||||
<tree string="Registration" decoration-bf="message_needaction==True" multi_edit="1">
|
||||
<field name="create_date" optional="hide"/>
|
||||
<field name="date_open" optional="hide"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="name"/>
|
||||
<field name="email"/>
|
||||
<field name="email" optional="hide"/>
|
||||
<field name="event_id" />
|
||||
<field name="state"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="origin" optional="hide"/>
|
||||
<field name="state" readonly="0"/>
|
||||
<field name="company_id" groups="base.group_multi_company" optional="hide"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<button name="confirm_registration" string="Confirm Registration" states="draft" type="object" icon="fa-check text-success"/>
|
||||
<button name="button_reg_close" string="Attended the Event" states="open" type="object" icon="fa-level-down text-success"/>
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object" icon="fa-times-circle text-danger"/>
|
||||
<button name="action_confirm" string="Confirm Registration" states="draft" type="object" icon="fa-check text-success"/>
|
||||
<button name="action_set_done" string="Attended the Event" states="open" type="object" icon="fa-level-down text-success"/>
|
||||
<button name="action_cancel" string="Cancel Registration" states="draft,open" type="object" icon="fa-times-circle text-danger"/>
|
||||
<field name="activity_exception_decoration" widget="activity_exception"/>
|
||||
</tree>
|
||||
</field>
|
||||
@@ -509,10 +514,10 @@
|
||||
<form string="Event Registration">
|
||||
<header>
|
||||
<button name="action_send_badge_email" string="Send by Email" type="object" states="open,done" class="oe_highlight"/>
|
||||
<button name="confirm_registration" string="Confirm" states="draft" type="object" class="oe_highlight"/>
|
||||
<button name="button_reg_close" string="Attended" states="open" type="object" class="oe_highlight"/>
|
||||
<button string="Set To Unconfirmed" name="do_draft" states="cancel,done" type="object" />
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object"/>
|
||||
<button name="action_confirm" string="Confirm" states="draft" type="object" class="oe_highlight"/>
|
||||
<button name="action_set_done" string="Attended" states="open" type="object" class="oe_highlight"/>
|
||||
<button name="action_set_draft" string="Set To Unconfirmed" states="cancel,done" type="object" />
|
||||
<button name="action_cancel" string="Cancel Registration" states="draft,open" type="object"/>
|
||||
<field name="state" nolabel="1" colspan="2" widget="statusbar" statusbar_visible="draft,open,done"/>
|
||||
</header>
|
||||
<sheet string="Registration">
|
||||
@@ -552,30 +557,22 @@
|
||||
<field name="email"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_global_click">
|
||||
<div class="oe_kanban_details">
|
||||
<div class="oe_kanban_card oe_kanban_global_click">
|
||||
<div class="float-right">
|
||||
<a class="btn btn-sm btn-success" string="Confirm Registration" name="action_confirm" type="object" states="draft" role="button">
|
||||
<i class="fa fa-check" role="img" aria-label="Confirm button" title="Confirm Registration"/>
|
||||
</a>
|
||||
<a class="btn btn-sm btn-success" string="Attended the Event" name="action_close" type="object" states="open" role="button">
|
||||
<i class="fa fa-level-down" role="img" aria-label="Attended button" title="Attended the Event"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="oe_kanban_content">
|
||||
<div class="o_kanban_record_top">
|
||||
<div class="o_kanban_record_headings">
|
||||
<strong class="o_kanban_record_title">
|
||||
<field name="name"/>
|
||||
</strong>
|
||||
</div>
|
||||
<div class="float-right">
|
||||
<a class="btn btn-sm btn-success" string="Confirm Registration" name="confirm_registration" type="object" states="draft" role="button">
|
||||
<i class="fa fa-check" role="img" aria-label="Confirm button" title="Confirm Registration"/>
|
||||
</a>
|
||||
<a class="btn btn-sm btn-success" string="Attended the Event" name="button_reg_close" type="object" states="open" role="button">
|
||||
<i class="fa fa-level-down" role="img" aria-label="Attended button" title="Attended the Event"/>
|
||||
</a>
|
||||
<a class="btn btn-sm btn-danger" string="Cancel Registration" name="button_reg_cancel" type="object" states="draft,open" role="button">
|
||||
<i class="fa fa-times" role="img" aria-label="Cancel button" title="Cancel Registration"/>
|
||||
</a>
|
||||
</div>
|
||||
<b class="o_kanban_record_title"><field name="display_name"/></b>
|
||||
</div>
|
||||
<div class="o_kanban_record_body">
|
||||
<field name="event_id"/>
|
||||
</div>
|
||||
<ul>
|
||||
<li><field name="partner_id"/></li>
|
||||
<li><field name="email"/></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -6,6 +6,16 @@ from odoo import api, fields, models
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = "sale.order"
|
||||
|
||||
def write(self, vals):
|
||||
""" Synchronize partner from SO to registrations. This is done notably
|
||||
in website_sale controller shop/address that updates customer, but not
|
||||
only. """
|
||||
result = super(SaleOrder, self).write(vals)
|
||||
if vals.get('partner_id'):
|
||||
registrations_toupdate = self.env['event.registration'].search([('sale_order_id', 'in', self.ids)])
|
||||
registrations_toupdate.write({'partner_id': vals['partner_id']})
|
||||
return result
|
||||
|
||||
def _action_confirm(self):
|
||||
res = super(SaleOrder, self)._action_confirm()
|
||||
for so in self:
|
||||
@@ -27,10 +37,12 @@ class SaleOrderLine(models.Model):
|
||||
|
||||
_inherit = 'sale.order.line'
|
||||
|
||||
event_id = fields.Many2one('event.event', string='Event',
|
||||
help="Choose an event and it will automatically create a registration for this event.")
|
||||
event_ticket_id = fields.Many2one('event.event.ticket', string='Event Ticket', help="Choose "
|
||||
"an event ticket and it will automatically create a registration for this event ticket.")
|
||||
event_id = fields.Many2one(
|
||||
'event.event', string='Event',
|
||||
help="Choose an event and it will automatically create a registration for this event.")
|
||||
event_ticket_id = fields.Many2one(
|
||||
'event.event.ticket', string='Event Ticket',
|
||||
help="Choose an event ticket and it will automatically create a registration for this event ticket.")
|
||||
event_ok = fields.Boolean(related='product_id.event_ok', readonly=True)
|
||||
|
||||
def _update_registrations(self, confirm=True, cancel_to_draft=False, registration_data=None):
|
||||
@@ -43,9 +55,9 @@ class SaleOrderLine(models.Model):
|
||||
for so_line in self.filtered('event_id'):
|
||||
existing_registrations = registrations.filtered(lambda self: self.sale_order_line_id.id == so_line.id)
|
||||
if confirm:
|
||||
existing_registrations.filtered(lambda self: self.state not in ['open', 'cancel']).confirm_registration()
|
||||
existing_registrations.filtered(lambda self: self.state not in ['open', 'cancel']).action_confirm()
|
||||
if cancel_to_draft:
|
||||
existing_registrations.filtered(lambda self: self.state == 'cancel').do_draft()
|
||||
existing_registrations.filtered(lambda self: self.state == 'cancel').action_set_draft()
|
||||
|
||||
for count in range(int(so_line.product_uom_qty) - len(existing_registrations)):
|
||||
registration = {}
|
||||
|
||||
@@ -23,6 +23,18 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_registration_view_kanban" model="ir.ui.view">
|
||||
<field name="name">event.registration.kanban.inherit</field>
|
||||
<field name="model">event.registration</field>
|
||||
<field name="inherit_id" ref="event.event_registration_view_kanban"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='event_id']" position="after">
|
||||
<br/>
|
||||
<field name="event_ticket_id"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_event_registration_ticket_form" model="ir.ui.view">
|
||||
<field name="name">event.registration.form.inherit</field>
|
||||
<field name="model">event.registration</field>
|
||||
|
||||
@@ -581,9 +581,19 @@ class MassMailing(models.Model):
|
||||
# ------------------------------------------------------
|
||||
|
||||
def _get_default_mailing_domain(self):
|
||||
mailing_domain = []
|
||||
default_mailing_domain = self.default_get(['mailing_domain']).get('mailing_domain')
|
||||
if self.mailing_model_name == 'mailing.list' and self.contact_list_ids:
|
||||
mailing_domain = [('list_ids', 'in', self.contact_list_ids.ids)]
|
||||
elif default_mailing_domain:
|
||||
default_mailing_domain = literal_eval(default_mailing_domain) if isinstance(default_mailing_domain, str) else default_mailing_domain
|
||||
try:
|
||||
self.env[self.mailing_model_real].search(default_mailing_domain, limit=1)
|
||||
except:
|
||||
mailing_domain = []
|
||||
else:
|
||||
mailing_domain = default_mailing_domain
|
||||
else:
|
||||
mailing_domain = []
|
||||
|
||||
if self.mailing_type == 'mail' and 'is_blacklisted' in self.env[self.mailing_model_name]._fields:
|
||||
mailing_domain = expression.AND([[('is_blacklisted', '=', False)], mailing_domain])
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
from ast import literal_eval
|
||||
|
||||
from odoo.addons.mass_mailing.tests.common import TestMassMailCommon
|
||||
from odoo.tests.common import users
|
||||
from odoo.tools import mute_logger
|
||||
from odoo.tests.common import users, Form
|
||||
|
||||
|
||||
class TestMassMailValues(TestMassMailCommon):
|
||||
@@ -71,3 +70,15 @@ class TestMassMailValues(TestMassMailCommon):
|
||||
'mailing_model_id': self.env['ir.model']._get('res.partner').id,
|
||||
})
|
||||
self.assertEqual(literal_eval(mailing.mailing_domain), [('email', 'ilike', 'test.example.com')])
|
||||
|
||||
@users('user_marketing')
|
||||
def test_mailing_computed_fields_form(self):
|
||||
mailing_form = Form(self.env['mailing.mailing'].with_context(
|
||||
default_mailing_domain="[('email', 'ilike', 'test.example.com')]",
|
||||
default_mailing_model_id=self.env['ir.model']._get('res.partner').id,
|
||||
))
|
||||
self.assertEqual(
|
||||
literal_eval(mailing_form.mailing_domain),
|
||||
['&', ('is_blacklisted', '=', False), ('email', 'ilike', 'test.example.com')]
|
||||
)
|
||||
self.assertEqual(mailing_form.mailing_model_real, 'res.partner')
|
||||
|
||||
@@ -79,7 +79,7 @@ Phone.include({
|
||||
*/
|
||||
_renderReadonly: function () {
|
||||
var def = this._super.apply(this, arguments);
|
||||
if (this.enableSMS) {
|
||||
if (this.enableSMS && this.value) {
|
||||
var $composerButton = $('<a>', {
|
||||
title: _t('Send SMS Text Message'),
|
||||
href: '',
|
||||
|
||||
@@ -18,6 +18,15 @@ QUnit.module('fields', {
|
||||
message: "",
|
||||
}]
|
||||
},
|
||||
visitor: {
|
||||
fields: {
|
||||
mobile: {string: "mobile", type: "text"},
|
||||
},
|
||||
records: [{
|
||||
id: 1,
|
||||
mobile: "+32494444444",
|
||||
}]
|
||||
},
|
||||
};
|
||||
}
|
||||
}, function () {
|
||||
@@ -32,6 +41,7 @@ QUnit.module('fields', {
|
||||
data: this.data,
|
||||
arch: '<form><sheet><field name="message" widget="sms_widget"/></sheet></form>',
|
||||
});
|
||||
|
||||
assert.containsOnce(form, '.o_sms_count', "Should have a sms counter");
|
||||
assert.strictEqual(form.$('.o_sms_count').text(), '0 characters, fits in 0 SMS (GSM7) ',
|
||||
'Should be "0 characters, fits in 0 SMS (GSM7) " by default');
|
||||
@@ -70,5 +80,39 @@ QUnit.module('fields', {
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('Sms widgets with non-empty initial value', async function (assert) {
|
||||
assert.expect(1);
|
||||
var form = await createView({
|
||||
View: FormView,
|
||||
model: 'visitor',
|
||||
data: this.data,
|
||||
arch: `<form><sheet><field name="mobile" widget="sms_widget"/></sheet></form>`,
|
||||
res_id: 1,
|
||||
res_ids: [1],
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_field_text').text(), '+32494444444',
|
||||
'Should have the initial value');
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('Sms widgets with empty initial value', async function (assert) {
|
||||
assert.expect(1);
|
||||
var form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: `<form><sheet><field name="message" widget="sms_widget"/></sheet></form>`,
|
||||
res_id: 1,
|
||||
res_ids: [1],
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_field_text').text(), '',
|
||||
'Should have the empty initial value');
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1465,9 +1465,13 @@ var FieldEmail = InputField.extend({
|
||||
* @private
|
||||
*/
|
||||
_renderReadonly: function () {
|
||||
this.$el.text(this.value)
|
||||
.addClass('o_form_uri o_text_overflow')
|
||||
.attr('href', this.prefix + ':' + this.value);
|
||||
if (this.value) {
|
||||
this.$el.text(this.value)
|
||||
.addClass('o_form_uri o_text_overflow')
|
||||
.attr('href', this.prefix + ':' + this.value);
|
||||
} else {
|
||||
this.$el.text('');
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -31,6 +31,7 @@ QUnit.module('basic_fields', {
|
||||
display_name: {string: "Displayed name", type: "char", searchable: true},
|
||||
foo: {string: "Foo", type: "char", default: "My little Foo Value", searchable: true, trim: true},
|
||||
bar: {string: "Bar", type: "boolean", default: true, searchable: true},
|
||||
empty_string: {string: "Empty string", type: "char", default: false, searchable: true, trim: true},
|
||||
txt: {string: "txt", type: "text", default: "My little txt Value\nHo-ho-hoooo Merry Christmas"},
|
||||
int_field: {string: "int_field", type: "integer", sortable: true, searchable: true},
|
||||
qux: {string: "Qux", type: "float", digits: [16,1], searchable: true},
|
||||
@@ -996,6 +997,30 @@ QUnit.module('basic_fields', {
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('email field with empty value', async function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
var form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partners">' +
|
||||
'<sheet>' +
|
||||
'<group>' +
|
||||
'<field name="empty_string" widget="email"/>' +
|
||||
'</group>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
});
|
||||
|
||||
var $mailtoLink = form.$('a.o_form_uri.o_field_widget.o_text_overflow');
|
||||
assert.strictEqual($mailtoLink.text(), '',
|
||||
"the value should be displayed properly");
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
|
||||
QUnit.module('FieldChar');
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ class SaleOrder(models.Model):
|
||||
('sale_order_id', 'in', self.ids), # To avoid break on multi record set
|
||||
('event_ticket_id', '=', ticket.id),
|
||||
], offset=new_qty, limit=(old_qty - new_qty), order='create_date asc')
|
||||
attendees.button_reg_cancel()
|
||||
attendees.action_cancel()
|
||||
# adding attendees
|
||||
elif ticket and new_qty > old_qty:
|
||||
line = OrderLine.browse(values['line_id'])
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
'data/event_track_data.xml',
|
||||
'views/event_track_templates.xml',
|
||||
'views/event_track_views.xml',
|
||||
'views/event_sponsor_views.xml',
|
||||
'views/event_views.xml',
|
||||
],
|
||||
'demo': [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import fields, models, _
|
||||
|
||||
|
||||
class SponsorType(models.Model):
|
||||
@@ -16,11 +16,29 @@ class SponsorType(models.Model):
|
||||
class Sponsor(models.Model):
|
||||
_name = "event.sponsor"
|
||||
_description = 'Event Sponsor'
|
||||
_order = "sequence"
|
||||
_order = "sequence, sponsor_type_id"
|
||||
_rec_name = 'partner_name'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
|
||||
event_id = fields.Many2one('event.event', 'Event', required=True)
|
||||
sponsor_type_id = fields.Many2one('event.sponsor.type', 'Sponsoring Type', required=True)
|
||||
partner_id = fields.Many2one('res.partner', 'Sponsor/Customer', required=True)
|
||||
partner_name = fields.Char('Name', related='partner_id.name')
|
||||
partner_email = fields.Char('Email', related='partner_id.email')
|
||||
partner_phone = fields.Char('Phone', related='partner_id.phone')
|
||||
partner_mobile = fields.Char('Mobile', related='partner_id.mobile')
|
||||
url = fields.Char('Sponsor Website')
|
||||
sequence = fields.Integer('Sequence', store=True, related='sponsor_type_id.sequence', readonly=False)
|
||||
image_128 = fields.Image(string="Logo", related='partner_id.image_128', store=True, readonly=False)
|
||||
sequence = fields.Integer('Sequence')
|
||||
image_128 = fields.Image(
|
||||
string="Logo", related='partner_id.image_128', store=True, readonly=False)
|
||||
|
||||
def _message_get_suggested_recipients(self):
|
||||
recipients = super(Sponsor, self)._message_get_suggested_recipients()
|
||||
for sponsor in self:
|
||||
if sponsor.partner_id:
|
||||
sponsor._message_add_suggested_recipient(
|
||||
recipients,
|
||||
partner=sponsor.partner_id,
|
||||
reason=_('Sponsor')
|
||||
)
|
||||
return recipients
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<!-- EVENTS/CONFIGURATION/EVENT Sponsor Types -->
|
||||
<record id="event_sponsor_type_view_form" model="ir.ui.view">
|
||||
<field name="name">Sponsor Types</field>
|
||||
<field name="model">event.sponsor.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Event Sponsor Types">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="sequence" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_type_view_tree" model="ir.ui.view">
|
||||
<field name="name">Sponsor Types</field>
|
||||
<field name="model">event.sponsor.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom" string="Event Sponsor Type">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_type_action" model="ir.actions.act_window">
|
||||
<field name="name">Sponsor Types</field>
|
||||
<field name="res_model">event.sponsor.type</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="event_sponsor_type_action" groups="base.group_no_one" id="menu_event_sponsor_type" parent="event.menu_event_configuration"/>
|
||||
|
||||
<record id="event_sponsor_view_search" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.search</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Event Sponsors">
|
||||
<field name="partner_id"/>
|
||||
<field name="event_id"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_view_form" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.view.form</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<field name="image_128" widget="image" class="oe_avatar"/>
|
||||
<h1><field name="partner_id"/></h1>
|
||||
<group>
|
||||
<group>
|
||||
<field name="event_id"/>
|
||||
<field name="partner_email" widget="email"/>
|
||||
<field name="url" widget="url"/>
|
||||
<field name="sequence" groups="base.group_no_one"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="sponsor_type_id"/>
|
||||
<field name="partner_phone" widget="phone" options="{'enable_sms': True}"/>
|
||||
<field name="partner_mobile" widget="phone" options="{'enable_sms': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
|
||||
<field name="activity_ids" widget="mail_activity"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_view_tree" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.view.tree</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="url"/>
|
||||
<field name="sponsor_type_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_view_kanban" model="ir.ui.view">
|
||||
<field name="name">event.sponsor.view.kanban</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<field name="id"/>
|
||||
<field name="url"/>
|
||||
<field name="partner_email"/>
|
||||
<field name="sponsor_type_id"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_global_click overflow-hidden">
|
||||
<div class="row my-auto">
|
||||
<img t-att-src="kanban_image('event.sponsor', 'image_128', record.id.raw_value)" alt="Sponsor image" class="col-4"/>
|
||||
<div class="col-8">
|
||||
<h1 class="o_kanban_record_title"><field name="partner_id"/></h1>
|
||||
<div>Level: <field name="sponsor_type_id"/></div>
|
||||
<span class="o_text_overflow" t-esc="record.partner_email.value"/>
|
||||
<span class="o_text_overflow" t-esc="record.url.value"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_action_from_event" model="ir.actions.act_window">
|
||||
<field name="name">Event Sponsors</field>
|
||||
<field name="res_model">event.sponsor</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="context">{'search_default_event_id': active_id, 'default_event_id': active_id}</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -263,75 +263,6 @@
|
||||
action="action_event_track_location"
|
||||
parent="event.menu_event_configuration"/>
|
||||
|
||||
<!-- EVENTS/CONFIGURATION/EVENT Sponsor Types -->
|
||||
<record model="ir.ui.view" id="view_event_sponsor_type_form">
|
||||
<field name="name">Sponsor Types</field>
|
||||
<field name="model">event.sponsor.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Event Sponsor Types">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="sequence"/>
|
||||
<field name="name"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_sponsor_type_tree">
|
||||
<field name="name">Sponsor Types</field>
|
||||
<field name="model">event.sponsor.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Event Sponsor Type" editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_event_sponsor_type">
|
||||
<field name="name">Sponsor Types</field>
|
||||
<field name="res_model">event.sponsor.type</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_event_sponsor_type"
|
||||
action="action_event_sponsor_type"
|
||||
parent="event.menu_event_configuration"
|
||||
groups="base.group_no_one"/>
|
||||
|
||||
<!-- EVENT.SPONSOR VIEWS -->
|
||||
<record model="ir.ui.view" id="view_event_sponsor_tree">
|
||||
<field name="name">event.sponsor.tree</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom">
|
||||
<field name="partner_id"/>
|
||||
<field name="url"/>
|
||||
<field name="sponsor_type_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_sponsor_search">
|
||||
<field name="name">event.sponsor.search</field>
|
||||
<field name="model">event.sponsor</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Event Sponsors">
|
||||
<field name="partner_id"/>
|
||||
<field name="event_id"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_event_sponsor_from_event">
|
||||
<field name="name">Event Tracks</field>
|
||||
<field name="res_model">event.sponsor</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_event_id': active_id, 'default_event_id': active_id}</field>
|
||||
</record>
|
||||
|
||||
<!-- EVENTS/CONFIGURATION/EVENT Tags -->
|
||||
<record model="ir.ui.view" id="view_event_track_tag_form">
|
||||
<field name="name">Track Tags</field>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
context="{'default_date': date_begin}">
|
||||
<field name="track_count" string="Tracks" widget="statinfo"/>
|
||||
</button>
|
||||
<button name="%(action_event_sponsor_from_event)d"
|
||||
<button name="%(event_sponsor_action_from_event)d"
|
||||
type="action"
|
||||
class="oe_stat_button"
|
||||
icon="fa-users">
|
||||
|
||||
@@ -702,6 +702,7 @@ class WebsiteSale(http.Controller):
|
||||
elif mode[1] == 'shipping':
|
||||
order.partner_shipping_id = partner_id
|
||||
|
||||
# TDE FIXME: don't ever do this
|
||||
order.message_partner_ids = [(4, partner_id), (3, request.website.partner_id.id)]
|
||||
if not errors:
|
||||
return request.redirect(kw.get('callback') or '/shop/confirm_order')
|
||||
|
||||
Reference in New Issue
Block a user