diff --git a/addons/event_sale/__openerp__.py b/addons/event_sale/__openerp__.py
index 802a0714b42..fc546f6f271 100644
--- a/addons/event_sale/__openerp__.py
+++ b/addons/event_sale/__openerp__.py
@@ -29,7 +29,6 @@ this event.
'wizard/event_edit_registration.xml',
],
'demo': ['data/event_demo.xml'],
- 'test': ['test/confirm.yml'],
'installable': True,
'auto_install': True
}
diff --git a/addons/event_sale/data/event_demo.xml b/addons/event_sale/data/event_demo.xml
index 459ec7b6493..50344152a31 100644
--- a/addons/event_sale/data/event_demo.xml
+++ b/addons/event_sale/data/event_demo.xml
@@ -1,7 +1,5 @@
-
-
-
-
+
+
Open Days in Los Angeles
True
@@ -219,6 +217,4 @@
]]>
-
-
-
+
diff --git a/addons/event_sale/data/event_sale_data.xml b/addons/event_sale/data/event_sale_data.xml
index 38e1f2434fb..9cd470bc89c 100644
--- a/addons/event_sale/data/event_sale_data.xml
+++ b/addons/event_sale/data/event_sale_data.xml
@@ -1,5 +1,5 @@
-
+
@@ -19,7 +19,7 @@
-
+
diff --git a/addons/event_sale/models/event.py b/addons/event_sale/models/event.py
index c54bde9eb24..e2e2f931d9f 100644
--- a/addons/event_sale/models/event.py
+++ b/addons/event_sale/models/event.py
@@ -1,100 +1,76 @@
# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from openerp import models, fields, api, _
-import openerp.addons.decimal_precision as dp
-from openerp.exceptions import ValidationError
-from openerp.osv import fields as old_fields
+from odoo import api, fields, models, _
+from odoo.exceptions import ValidationError
+
+import odoo.addons.decimal_precision as dp
-class event_event(models.Model):
+class Event(models.Model):
+
_inherit = 'event.event'
- event_ticket_ids = fields.One2many(
- 'event.event.ticket', 'event_id', string='Event Ticket',
- default=lambda rec: rec._default_tickets(), copy=True)
-
- @api.model
def _default_tickets(self):
- try:
- product = self.env.ref('event_sale.product_product_event')
- return [{
- 'name': _('Subscription'),
- 'product_id': product.id,
- 'price': 0,
- }]
- except ValueError:
+ product = self.env.ref('event_sale.product_product_event', raise_if_not_found=False)
+ if not product:
return self.env['event.event.ticket']
+ return [{
+ 'name': _('Subscription'),
+ 'product_id': product.id,
+ 'price': 0,
+ }]
+
+ event_ticket_ids = fields.One2many('event.event.ticket', 'event_id', string='Event Ticket',
+ default=lambda self: self._default_tickets(), copy=True)
-class event_ticket(models.Model):
+class EventTicket(models.Model):
+
_name = 'event.event.ticket'
_description = 'Event Ticket'
- name = fields.Char('Name', required=True, translate=True)
- event_id = fields.Many2one('event.event', "Event", required=True, ondelete='cascade')
- product_id = fields.Many2one(
- 'product.product', 'Product',
- required=True, domain=[("event_type_id", "!=", False)],
- default=lambda self: self._default_product_id())
- registration_ids = fields.One2many('event.registration', 'event_ticket_id', 'Registrations')
- price = fields.Float('Price', digits=dp.get_precision('Product Price'))
- deadline = fields.Date("Sales End")
- is_expired = fields.Boolean('Is Expired', compute='_is_expired')
-
- @api.model
def _default_product_id(self):
- try:
- product = self.env['ir.model.data'].get_object('event_sale', 'product_product_event')
- return product.id
- except ValueError:
- return False
+ return self.env.ref('event_sale.product_product_event', raise_if_not_found=False)
- @api.one
- @api.depends('deadline')
- def _is_expired(self):
- if self.deadline:
- current_date = fields.Date.context_today(self.with_context({'tz': self.event_id.date_tz}))
- self.is_expired = self.deadline < current_date
- else:
- self.is_expired = False
-
- # FIXME non-stored fields wont ends up in _columns (and thus _all_columns), which forbid them
- # to be used in qweb views. Waiting a fix, we create an old function field directly.
- """
- price_reduce = fields.Float("Price Reduce", compute="_get_price_reduce", store=False,
- digits=dp.get_precision('Product Price'))
- @api.one
- @api.depends('price', 'product_id.lst_price', 'product_id.price')
- def _get_price_reduce(self):
- product = self.product_id
- discount = product.lst_price and (product.lst_price - product.price) / product.lst_price or 0.0
- self.price_reduce = (1.0 - discount) * self.price
- """
- def _get_price_reduce(self, cr, uid, ids, field_name, arg, context=None):
- res = dict.fromkeys(ids, 0.0)
- for ticket in self.browse(cr, uid, ids, context=context):
- product = ticket.product_id
- discount = product.lst_price and (product.lst_price - product.price) / product.lst_price or 0.0
- res[ticket.id] = (1.0 - discount) * ticket.price
- return res
-
- _columns = {
- 'price_reduce': old_fields.function(_get_price_reduce, type='float', string='Price Reduce',
- digits_compute=dp.get_precision('Product Price')),
- }
+ name = fields.Char(string='Name', required=True, translate=True)
+ event_id = fields.Many2one('event.event', string="Event", required=True, ondelete='cascade')
+ product_id = fields.Many2one('product.product', string='Product',
+ required=True, domain=[("event_type_id", "!=", False)],
+ default=_default_product_id)
+ registration_ids = fields.One2many('event.registration', 'event_ticket_id', string='Registrations')
+ price = fields.Float(string='Price', digits=dp.get_precision('Product Price'))
+ deadline = fields.Date(string="Sales End")
+ is_expired = fields.Boolean(string='Is Expired', compute='_compute_is_expired')
+ price_reduce = fields.Float(string="Price Reduce", compute="_compute_price_reduce", digits=dp.get_precision('Product Price'))
# seats fields
- seats_availability = fields.Selection(
- [('limited', 'Limited'), ('unlimited', 'Unlimited')],
- 'Available Seat', required=True, store=True, compute='_compute_seats', default="limited")
- seats_max = fields.Integer('Maximum Available Seats',
- help="Define the number of available tickets. If you have too much registrations you will "
- "not be able to sell tickets anymore. Set 0 to ignore this rule set as unlimited.")
+ seats_availability = fields.Selection([('limited', 'Limited'), ('unlimited', 'Unlimited')],
+ string='Available Seat', required=True, store=True, compute='_compute_seats', default="limited")
+ seats_max = fields.Integer(string='Maximum Available Seats',
+ help="Define the number of available tickets. If you have too much registrations you will "
+ "not be able to sell tickets anymore. Set 0 to ignore this rule set as unlimited.")
seats_reserved = fields.Integer(string='Reserved Seats', compute='_compute_seats', store=True)
seats_available = fields.Integer(string='Available Seats', compute='_compute_seats', store=True)
seats_unconfirmed = fields.Integer(string='Unconfirmed Seat Reservations', compute='_compute_seats', store=True)
seats_used = fields.Integer(compute='_compute_seats', store=True)
+ @api.multi
+ def _compute_is_expired(self):
+ for record in self:
+ if record.deadline:
+ current_date = fields.Date.context_today(record.with_context({'tz': record.event_id.date_tz}))
+ record.is_expired = record.deadline < current_date
+ else:
+ record.is_expired = False
+
+ @api.multi
+ def _compute_price_reduce(self):
+ for record in self:
+ product = record.product_id
+ discount = product.lst_price and (product.lst_price - product.price) / product.lst_price or 0.0
+ record.price_reduce = (1.0 - discount) * record.price
+
@api.multi
@api.depends('seats_max', 'registration_ids.state')
def _compute_seats(self):
@@ -115,8 +91,8 @@ class event_ticket(models.Model):
WHERE event_ticket_id IN %s AND state IN ('draft', 'open', 'done')
GROUP BY event_ticket_id, state
"""
- self._cr.execute(query, (tuple(self.ids),))
- for event_ticket_id, state, num in self._cr.fetchall():
+ self.env.cr.execute(query, (tuple(self.ids),))
+ for event_ticket_id, state, num in self.env.cr.fetchall():
ticket = self.browse(event_ticket_id)
ticket[state_field[state]] += num
# compute seats_available
@@ -124,37 +100,38 @@ class event_ticket(models.Model):
if ticket.seats_max > 0:
ticket.seats_available = ticket.seats_max - (ticket.seats_reserved + ticket.seats_used)
- @api.one
+ @api.multi
@api.constrains('registration_ids', 'seats_max')
def _check_seats_limit(self):
- if self.seats_max and self.seats_available < 0:
- raise ValidationError(_('No more available seats for the ticket'))
+ for record in self:
+ if record.seats_max and record.seats_available < 0:
+ raise ValidationError(_('No more available seats for the ticket'))
@api.onchange('product_id')
- def onchange_product_id(self):
- price = self.product_id.list_price if self.product_id else 0
- return {'value': {'price': price}}
+ def _onchange_product_id(self):
+ self.price = self.product_id.list_price or 0
-class event_registration(models.Model):
+class EventRegistration(models.Model):
_inherit = 'event.registration'
- event_ticket_id = fields.Many2one('event.event.ticket', 'Event Ticket')
+ event_ticket_id = fields.Many2one('event.event.ticket', string='Event Ticket')
# in addition to origin generic fields, add real relational fields to correctly
# handle attendees linked to sale orders and their lines
# TDE FIXME: maybe add an onchange on sale_order_id + origin
- sale_order_id = fields.Many2one('sale.order', 'Source Sale Order', ondelete='cascade')
- sale_order_line_id = fields.Many2one('sale.order.line', 'Sale Order Line', ondelete='cascade')
+ sale_order_id = fields.Many2one('sale.order', string='Source Sale Order', ondelete='cascade')
+ sale_order_line_id = fields.Many2one('sale.order.line', string='Sale Order Line', ondelete='cascade')
- @api.one
+ @api.multi
@api.constrains('event_ticket_id', 'state')
def _check_ticket_seats_limit(self):
- if self.event_ticket_id.seats_max and self.event_ticket_id.seats_available < 0:
- raise ValidationError(_('No more available seats for this ticket'))
+ for record in self:
+ if record.event_ticket_id.seats_max and record.event_ticket_id.seats_available < 0:
+ raise ValidationError(_('No more available seats for this ticket'))
@api.multi
def _check_auto_confirmation(self):
- res = super(event_registration, self)._check_auto_confirmation()
+ res = super(EventRegistration, self)._check_auto_confirmation()
if res:
orders = self.env['sale.order'].search([('state', '=', 'draft'), ('id', 'in', self.mapped('sale_order_id').ids)], limit=1)
if orders:
@@ -163,7 +140,7 @@ class event_registration(models.Model):
@api.model
def create(self, vals):
- res = super(event_registration, self).create(vals)
+ res = super(EventRegistration, self).create(vals)
if res.origin or res.sale_order_id:
message = _("The registration has been created for event %(event_name)s%(ticket)s from sale order %(order)s") % ({
'event_name': '%s' % res.event_id.name,
@@ -178,7 +155,7 @@ class event_registration(models.Model):
line_id = registration.get('sale_order_line_id')
if line_id:
registration.setdefault('partner_id', line_id.order_id.partner_id)
- att_data = super(event_registration, self)._prepare_attendee_values(registration)
+ att_data = super(EventRegistration, self)._prepare_attendee_values(registration)
if line_id:
att_data.update({
'event_id': line_id.event_id.id,
diff --git a/addons/event_sale/models/product.py b/addons/event_sale/models/product.py
index 476425081e7..f98bd9be21a 100644
--- a/addons/event_sale/models/product.py
+++ b/addons/event_sale/models/product.py
@@ -1,29 +1,29 @@
# -*- coding: utf-8 -*-
-from openerp.osv import fields, osv
+from odoo import api, fields, models
-class product_template(osv.osv):
+class ProductTemplate(models.Model):
_inherit = 'product.template'
- _columns = {
- 'event_ok': fields.boolean('Event Subscription', help='Determine if a product needs to create automatically an event registration at the confirmation of a sales order line.'),
- 'event_type_id': fields.many2one('event.type', 'Type of Event', help='Select event types so when we use this product in sales order lines, it will filter events of this type only.'),
- }
- def onchange_event_ok(self, cr, uid, ids, type, event_ok, context=None):
- if event_ok:
- return {'value': {'type': 'service'}}
- return {}
+ event_ok = fields.Boolean(string='Event Subscription', help='Determine if a product needs '
+ 'to create automatically an event registration at the confirmation of a sales order line.')
+ event_type_id = fields.Many2one('event.type', string='Type of Event', help='Select event types '
+ 'so when we use this product in sales order lines, it will filter events of this type only.')
+
+ @api.onchange('event_ok')
+ def _onchange_event_ok(self):
+ if self.event_ok:
+ self.type = 'service'
-class product(osv.osv):
+class Product(models.Model):
_inherit = 'product.product'
- _columns = {
- 'event_ticket_ids': fields.one2many('event.event.ticket', 'product_id', 'Event Tickets'),
- }
- def onchange_event_ok(self, cr, uid, ids, type, event_ok, context=None):
+ event_ticket_ids = fields.One2many('event.event.ticket', 'product_id', string='Event Tickets')
+
+ @api.onchange('event_ok')
+ def _onchange_event_ok(self):
""" Redirection, inheritance mechanism hides the method on the model """
- if event_ok:
- return {'value': {'type': 'service'}}
- return {}
+ if self.event_ok:
+ self.type = 'service'
diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py
index 8c2b8bc0c3f..7b4032882f0 100644
--- a/addons/event_sale/models/sale_order.py
+++ b/addons/event_sale/models/sale_order.py
@@ -1,53 +1,48 @@
# -*- coding: utf-8 -*-
-from openerp import api
-from openerp.osv import fields, osv
+from odoo import api, fields, models
-class sale_order(osv.osv):
+class SaleOrder(models.Model):
_inherit = "sale.order"
- def action_confirm(self, cr, uid, ids, context=None):
- res = super(sale_order, self).action_confirm(cr, uid, ids, context=context)
- for order in self.browse(cr, uid, ids, context=context):
- redirect_to_event_registration, so_id = any(line.event_id for line in order.order_line), order.id
- order.order_line._update_registrations(confirm=True)
- if redirect_to_event_registration:
- event_ctx = dict(context, default_sale_order_id=so_id)
- return self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'event_sale', 'action_sale_order_event_registration', event_ctx)
- else:
- return res
+ @api.multi
+ def action_confirm(self):
+ self.ensure_one()
+ res = super(SaleOrder, self).action_confirm()
+ self.order_line._update_registrations(confirm=True)
+ if any(self.order_line.filtered(lambda line: line.event_id)):
+ return self.env['ir.actions.act_window'].with_context(default_sale_order_id=self.id).for_xml_id('event_sale', 'action_sale_order_event_registration')
+ return res
-class sale_order_line(osv.osv):
+class SaleOrderLine(models.Model):
+
_inherit = 'sale.order.line'
- _columns = {
- 'event_id': fields.many2one(
- 'event.event', 'Event',
- help="Choose an event and it will automatically create a registration for this event."),
- 'event_ticket_id': fields.many2one(
- 'event.event.ticket', 'Event Ticket',
- help="Choose an event ticket and it will automatically create a registration for this event ticket."),
- # those 2 fields are used for dynamic domains and filled by onchange
- # TDE: really necessary ? ...
- 'event_type_id': fields.related('product_id', 'event_type_id', type='many2one', relation="event.type", string="Event Type", readonly=True),
- 'event_ok': fields.related('product_id', 'event_ok', string='event_ok', type='boolean', readonly=True),
- }
- def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None):
- res = super(sale_order_line, self)._prepare_order_line_invoice_line(cr, uid, line, account_id=account_id, context=context)
- if line.event_id:
- event = self.pool['event.event'].read(cr, uid, line.event_id.id, ['name'], context=context)
- res['name'] = '%s: %s' % (res.get('name', ''), event['name'])
+ 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.")
+ # those 2 fields are used for dynamic domains and filled by onchange
+ # TDE: really necessary ? ..
+ event_type_id = fields.Many2one(related='product_id.event_type_id', string="Event Type")
+ event_ok = fields.Boolean(related='product_id.event_ok')
+
+ @api.multi
+ def _prepare_invoice_line(self, qty):
+ self.ensure_one()
+ res = super(SaleOrderLine, self)._prepare_invoice_line(qty)
+ if self.event_id:
+ res['name'] = '%s: %s' % (res.get('name', ''), self.event_id.name)
return res
@api.onchange('product_id')
- def product_id_change_event(self):
+ def _onchange_product_id_event(self):
+ values = {'event_type_id': False, 'event_ok': False}
if self.product_id.event_ok:
- values = dict(event_type_id=self.product_id.event_type_id.id,
- event_ok=self.product_id.event_ok)
- else:
- values = dict(event_type_id=False, event_ok=False)
+ values['event_type_id'] = self.product_id.event_type_id.id
+ values['event_ok'] = self.product_id.event_ok
self.update(values)
@api.multi
@@ -58,7 +53,7 @@ class sale_order_line(osv.osv):
and create new one for missing one. """
Registration = self.env['event.registration']
registrations = Registration.search([('sale_order_line_id', 'in', self.ids)])
- for so_line in [l for l in self if l.event_id]:
+ 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 != 'open').confirm_registration()
@@ -71,10 +66,10 @@ class sale_order_line(osv.osv):
registration = registration_data.pop()
# TDE CHECK: auto confirmation
registration['sale_order_line_id'] = so_line
- self.env['event.registration'].with_context(registration_force_draft=True).create(
+ Registration.with_context(registration_force_draft=True).create(
Registration._prepare_attendee_values(registration))
return True
- def onchange_event_ticket_id(self, cr, uid, ids, event_ticket_id=False, context=None):
- price = event_ticket_id and self.pool["event.event.ticket"].browse(cr, uid, event_ticket_id, context=context).price or False
- return {'value': {'price_unit': price}}
+ @api.onchange('event_ticket_id')
+ def _onchange_event_ticket_id(self):
+ self.price_unit = self.event_ticket_id.price
diff --git a/addons/event_sale/views/event_views.xml b/addons/event_sale/views/event_views.xml
index ef7e2cedbdc..64e2ec9caa4 100644
--- a/addons/event_sale/views/event_views.xml
+++ b/addons/event_sale/views/event_views.xml
@@ -1,9 +1,7 @@
-
-
-
-
-
- event.registration.ticket.search
+
+
+
+ event.registration.search.inherit
event.registration
@@ -13,8 +11,8 @@
-
- event.registration.ticket.tree
+
+ event.registration.tree.inherit
event.registration
@@ -25,8 +23,8 @@
-
- event.registration.ticket.form
+
+ event.registration.form.inherit
event.registration
@@ -42,13 +40,12 @@
-
-
- view_event_form_inherit_tichet
+
+
+ event.form.inherit
event.event
-
@@ -72,11 +69,10 @@
-
-
+
event.event.ticket.form
event.event.ticket
@@ -106,5 +102,5 @@
-
-
+
+
diff --git a/addons/event_sale/views/product_views.xml b/addons/event_sale/views/product_views.xml
index dcb548560e0..ddaed028280 100644
--- a/addons/event_sale/views/product_views.xml
+++ b/addons/event_sale/views/product_views.xml
@@ -1,13 +1,13 @@
-
-
-
-
+
+
+
+ product.template.form.inherit
product.template
@@ -16,5 +16,4 @@
-
-
+
diff --git a/addons/event_sale/views/sale_order_views.xml b/addons/event_sale/views/sale_order_views.xml
index 4950c5597de..c4278ae45e3 100644
--- a/addons/event_sale/views/sale_order_views.xml
+++ b/addons/event_sale/views/sale_order_views.xml
@@ -1,15 +1,13 @@
-
-
-
-
- event.sale.order
+
+
+
+ sale.order.form.inherit
sale.order
-
+
@@ -19,10 +17,9 @@
-
+
-
-
-
+
+
diff --git a/addons/event_sale/wizard/event_edit_registration.py b/addons/event_sale/wizard/event_edit_registration.py
index 989737405b8..3554dc668f8 100644
--- a/addons/event_sale/wizard/event_edit_registration.py
+++ b/addons/event_sale/wizard/event_edit_registration.py
@@ -46,13 +46,13 @@ class SaleOrderEventRegistration(models.TransientModel):
@api.multi
def action_make_registration(self):
- Registration = self.env['event.registration']
- for wizard in self:
- for wiz_registration in wizard.event_registration_ids:
- if wiz_registration.registration_id:
- wiz_registration.registration_id.write(wiz_registration.get_registration_data()[0])
- else:
- Registration.create(wiz_registration.get_registration_data()[0])
+ self.ensure_one()
+ for registration_line in self.event_registration_ids:
+ values = registration_line.get_registration_data()
+ if registration_line.registration_id:
+ registration_line.registration_id.write(values)
+ else:
+ self.env['event.registration'].create(values)
return {'type': 'ir.actions.act_window_close'}
@@ -69,8 +69,9 @@ class RegistrationEditorLine(models.TransientModel):
phone = fields.Char(string='Phone')
name = fields.Char(string='Name', select=True)
- @api.one
+ @api.multi
def get_registration_data(self):
+ self.ensure_one()
return {
'event_id': self.event_id.id,
'event_ticket_id': self.event_ticket_id.id,
diff --git a/addons/event_sale/wizard/event_edit_registration.xml b/addons/event_sale/wizard/event_edit_registration.xml
index bec8334a2e5..801d64d45f4 100644
--- a/addons/event_sale/wizard/event_edit_registration.xml
+++ b/addons/event_sale/wizard/event_edit_registration.xml
@@ -1,6 +1,5 @@
-
-
+
registration.editor.form
@@ -37,6 +36,4 @@
new
{}
-
-
-
+