From 0b42e36da3fba78fd2ea9da3ada6e80dc2be39cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 3 Oct 2014 10:23:05 +0200 Subject: [PATCH] [CLEAN] event_sale: lint / cleaned module, migrated event models to the new API. --- addons/event_sale/__init__.py | 21 +- addons/event_sale/__openerp__.py | 29 +-- addons/event_sale/event_demo.xml | 6 +- addons/event_sale/event_sale.py | 242 ------------------ addons/event_sale/models/__init__.py | 5 + addons/event_sale/models/event.py | 129 ++++++++++ addons/event_sale/models/product.py | 29 +++ addons/event_sale/models/sale_order.py | 69 +++++ .../{event_sale_view.xml => views/event.xml} | 40 +-- addons/event_sale/views/product.xml | 20 ++ addons/event_sale/views/sale_order.xml | 24 ++ 11 files changed, 287 insertions(+), 327 deletions(-) delete mode 100644 addons/event_sale/event_sale.py create mode 100644 addons/event_sale/models/__init__.py create mode 100644 addons/event_sale/models/event.py create mode 100644 addons/event_sale/models/product.py create mode 100644 addons/event_sale/models/sale_order.py rename addons/event_sale/{event_sale_view.xml => views/event.xml} (64%) create mode 100644 addons/event_sale/views/product.xml create mode 100644 addons/event_sale/views/sale_order.xml diff --git a/addons/event_sale/__init__.py b/addons/event_sale/__init__.py index 726d2d5c09d..c7b5ac7e1f2 100644 --- a/addons/event_sale/__init__.py +++ b/addons/event_sale/__init__.py @@ -1,22 +1,3 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## -import event_sale +import models diff --git a/addons/event_sale/__openerp__.py b/addons/event_sale/__openerp__.py index 6691ad217bd..d2300d05a17 100644 --- a/addons/event_sale/__openerp__.py +++ b/addons/event_sale/__openerp__.py @@ -1,30 +1,10 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - { 'name': 'Events Sales', - 'version': '0.1', + 'version': '1.1', 'category': 'Tools', - 'website' : 'https://www.odoo.com/page/events', + 'website': 'https://www.odoo.com/page/events', 'description': """ Creating registration with sale orders. ======================================= @@ -41,7 +21,9 @@ this event. 'author': 'OpenERP SA', 'depends': ['event', 'sale_crm'], 'data': [ - 'event_sale_view.xml', + 'views/event.xml', + 'views/product.xml', + 'views/sale_order.xml', 'event_sale_data.xml', 'event_sale_report.xml', 'views/report_registrationbadge.xml', @@ -52,4 +34,3 @@ this event. 'installable': True, 'auto_install': True } -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/event_sale/event_demo.xml b/addons/event_sale/event_demo.xml index 8a55172cd85..9d0ed231897 100644 --- a/addons/event_sale/event_demo.xml +++ b/addons/event_sale/event_demo.xml @@ -12,7 +12,7 @@ 1000.0 - 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 + @@ -25,7 +25,7 @@ 1000.0 - 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 + @@ -38,7 +38,7 @@ 1000.0 - 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 + diff --git a/addons/event_sale/event_sale.py b/addons/event_sale/event_sale.py deleted file mode 100644 index 2d947be63e0..00000000000 --- a/addons/event_sale/event_sale.py +++ /dev/null @@ -1,242 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp import api -from openerp.fields import Integer, One2many, Html -from openerp.osv import fields, osv -from openerp.tools.translate import _ - -class product_template(osv.osv): - _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 {} - -class product(osv.osv): - _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): - # cannot directly forward to product.template as the ids are theoretically different - if event_ok: - return {'value': {'type': 'service'}} - return {} - - -class sale_order_line(osv.osv): - _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 - 'event_type_id': fields.related('product_id','event_type_id', type='many2one', relation="event.type", string="Event Type"), - 'event_ok': fields.related('product_id', 'event_ok', string='event_ok', type='boolean'), - } - - def product_id_change(self, cr, uid, ids, - pricelist, - product, - qty=0, - uom=False, - qty_uos=0, - uos=False, - name='', - partner_id=False, - lang=False, - update_tax=True, - date_order=False, - packaging=False, - fiscal_position=False, - flag=False, context=None): - """ - check product if event type - """ - res = super(sale_order_line,self).product_id_change(cr, uid, ids, pricelist, product, qty=qty, uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id, lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context) - if product: - product_res = self.pool.get('product.product').browse(cr, uid, product, context=context) - if product_res.event_ok: - res['value'].update(event_type_id=product_res.event_type_id.id, - event_ok=product_res.event_ok) - else: - res['value'].update(event_type_id=False, - event_ok=False) - return res - - def button_confirm(self, cr, uid, ids, context=None): - ''' - create registration with sales order - ''' - context = dict(context or {}) - registration_obj = self.pool.get('event.registration') - for order_line in self.browse(cr, uid, ids, context=context): - if order_line.event_id: - dic = { - 'name': order_line.order_id.partner_invoice_id.name, - 'partner_id': order_line.order_id.partner_id.id, - 'nb_register': int(order_line.product_uom_qty), - 'email': order_line.order_id.partner_id.email, - 'phone': order_line.order_id.partner_id.phone, - 'origin': order_line.order_id.name, - 'event_id': order_line.event_id.id, - 'event_ticket_id': order_line.event_ticket_id and order_line.event_ticket_id.id or None, - } - - if order_line.event_ticket_id: - message = _("The registration has been created for event %s with the ticket %s from the Sale Order %s. ") % (order_line.event_id.name, order_line.event_ticket_id.name, order_line.order_id.name) - else: - message = _("The registration has been created for event %s from the Sale Order %s. ") % (order_line.event_id.name, order_line.order_id.name) - - context.update({'mail_create_nolog': True}) - registration_id = registration_obj.create(cr, uid, dic, context=context) - registration_obj.message_post(cr, uid, [registration_id], body=message, context=context) - return super(sale_order_line, self).button_confirm(cr, uid, ids, context=context) - - def onchange_event_ticket_id(self, cr, uid, ids, event_ticket_id=False, context=None): - price = event_ticket_id and self.pool.get("event.event.ticket").browse(cr, uid, event_ticket_id, context=context).price or False - return {'value': {'price_unit': price}} - - -class event_event(osv.osv): - _inherit = 'event.event' - - event_ticket_ids = One2many('event.event.ticket', 'event_id', string='Event Ticket', - default=lambda rec: rec._default_tickets()) - seats_max = Integer(string='Maximum Available Seats', - help="The maximum registration level is equal to the sum of the maximum registration of event ticket. " + - "If you have too much registrations you are not able to confirm your event. (0 to ignore this rule )", - store=True, readonly=True, compute='_compute_seats_max') - - badge_back = Html('Badge Back', translate=True, states={'done': [('readonly', True)]}) - badge_innerleft = Html('Badge Innner Left', translate=True, states={'done': [('readonly', True)]}) - badge_innerright = Html('Badge Inner Right', translate=True, states={'done': [('readonly', 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: - return self.env['event.event.ticket'] - - @api.one - @api.depends('event_ticket_ids.seats_max') - def _compute_seats_max(self): - self.seats_max = sum(ticket.seats_max for ticket in self.event_ticket_ids) - -class event_ticket(osv.osv): - _name = 'event.event.ticket' - - def _get_seats(self, cr, uid, ids, fields, args, context=None): - """Get reserved, available, reserved but unconfirmed and used seats for each event tickets. - @return: Dictionary of function field values. - """ - res = dict([(id, {}) for id in ids]) - for ticket in self.browse(cr, uid, ids, context=context): - res[ticket.id]['seats_reserved'] = sum(reg.nb_register for reg in ticket.registration_ids if reg.state == "open") - res[ticket.id]['seats_used'] = sum(reg.nb_register for reg in ticket.registration_ids if reg.state == "done") - res[ticket.id]['seats_unconfirmed'] = sum(reg.nb_register for reg in ticket.registration_ids if reg.state == "draft") - res[ticket.id]['seats_available'] = ticket.seats_max - \ - (res[ticket.id]['seats_reserved'] + res[ticket.id]['seats_used']) \ - if ticket.seats_max > 0 else None - return res - - def _is_expired(self, cr, uid, ids, field_name, args, context=None): - # FIXME: A ticket is considered expired when the deadline is passed. The deadline should - # be considered in the timezone of the event, not the timezone of the user! - # Until we add a TZ on the event we'll use the context's current date, more accurate - # than using UTC all the time. - current_date = fields.date.context_today(self, cr, uid, context=context) - return {ticket.id: ticket.deadline and ticket.deadline < current_date - for ticket in self.browse(cr, uid, ids, context=context)} - - - _columns = { - '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)]), - 'registration_ids': fields.one2many('event.registration', 'event_ticket_id', 'Registrations'), - 'deadline': fields.date("Sales End"), - 'is_expired': fields.function(_is_expired, type='boolean', string='Is Expired'), - 'price': fields.float('Price'), - 'seats_max': fields.integer('Maximum Available Seats', oldname='register_max', help="You can for each event define a maximum registration level. If you have too much registrations you are not able to confirm your event. (put 0 to ignore this rule )"), - 'seats_reserved': fields.function(_get_seats, string='Reserved Seats', type='integer', multi='seats_reserved'), - 'seats_available': fields.function(_get_seats, string='Available Seats', type='integer', multi='seats_reserved'), - 'seats_unconfirmed': fields.function(_get_seats, string='Unconfirmed Seat Reservations', type='integer', multi='seats_reserved'), - 'seats_used': fields.function(_get_seats, string='Number of Participations', type='integer', multi='seats_reserved'), - } - - def _default_product_id(self, cr, uid, context={}): - imd = self.pool.get('ir.model.data') - try: - product = imd.get_object(cr, uid, 'event_sale', 'product_product_event') - except ValueError: - return False - return product.id - - _defaults = { - 'product_id': _default_product_id - } - - def _check_seats_limit(self, cr, uid, ids, context=None): - for ticket in self.browse(cr, uid, ids, context=context): - if ticket.seats_max and ticket.seats_available < 0: - return False - return True - - _constraints = [ - (_check_seats_limit, 'No more available tickets.', ['registration_ids','seats_max']), - ] - - def onchange_product_id(self, cr, uid, ids, product_id=False, context=None): - price = self.pool.get("product.product").browse(cr, uid, product_id).list_price if product_id else 0 - return {'value': {'price': price}} - - -class event_registration(osv.osv): - """Event Registration""" - _inherit= 'event.registration' - _columns = { - 'event_ticket_id': fields.many2one('event.event.ticket', 'Event Ticket'), - } - - def _check_ticket_seats_limit(self, cr, uid, ids, context=None): - for registration in self.browse(cr, uid, ids, context=context): - if registration.event_ticket_id.seats_max and registration.event_ticket_id.seats_available < 0: - return False - return True - - _constraints = [ - (_check_ticket_seats_limit, 'No more available tickets.', ['event_ticket_id','nb_register','state']), - ] diff --git a/addons/event_sale/models/__init__.py b/addons/event_sale/models/__init__.py new file mode 100644 index 00000000000..988d9523f9b --- /dev/null +++ b/addons/event_sale/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +import sale_order +import product +import event diff --git a/addons/event_sale/models/event.py b/addons/event_sale/models/event.py new file mode 100644 index 00000000000..8fc46f5e22b --- /dev/null +++ b/addons/event_sale/models/event.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- + +from openerp import models, fields, api, _ +from openerp.exceptions import Warning + + +class event_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()) + seats_max = fields.Integer( + string='Maximum Available Seats', + help="The maximum registration level is equal to the sum of the maximum registration of event ticket. " + + "If you have too much registrations you are not able to confirm your event. (0 to ignore this rule )", + store=True, readonly=True, compute='_compute_seats_max') + + badge_back = fields.Html('Badge Back', translate=True, states={'done': [('readonly', True)]}) + badge_innerleft = fields.Html('Badge Innner Left', translate=True, states={'done': [('readonly', True)]}) + badge_innerright = fields.Html('Badge Inner Right', translate=True, states={'done': [('readonly', 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: + return self.env['event.event.ticket'] + + @api.one + @api.depends('event_ticket_ids.seats_max') + def _compute_seats_max(self): + self.seats_max = sum(ticket.seats_max for ticket in self.event_ticket_ids) + + +class event_ticket(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') + deadline = fields.Date("Sales End") + is_expired = fields.Boolean('Is Expired', compute='_is_expired', store=True) + + @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 + + @api.one + @api.depends('deadline') + def _is_expired(self): + # FIXME: A ticket is considered expired when the deadline is passed. The deadline should + # be considered in the timezone of the event, not the timezone of the user! + # Until we add a TZ on the event we'll use the context's current date, more accurate + # than using UTC all the time. + current_date = fields.Date.context_today(self.with_context({'tz': self.event_id.date_tz})) + self.is_expired = self.deadline < current_date + + seats_max = fields.Integer('Maximum Available Seats', help="You can for each event define a maximum registration level. If you have too much registrations you are not able to confirm your event. (put 0 to ignore this rule )") + 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 + @api.depends('seats_max', 'registration_ids.state', 'registration_ids.nb_register') + def _compute_seats(self): + """ Determine reserved, available, reserved but unconfirmed and used seats. """ + # initialize fields to 0 + for ticket in self: + ticket.seats_unconfirmed = ticket.seats_reserved = ticket.seats_used = ticket.seats_available = 0 + # aggregate registrations by ticket and by state + if self.ids: + state_field = { + 'draft': 'seats_unconfirmed', + 'open': 'seats_reserved', + 'done': 'seats_used', + } + query = """ SELECT event_ticket_id, state, sum(nb_register) + FROM event_registration + 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(): + ticket = self.browse(event_ticket_id) + ticket[state_field[state]] += num + # compute seats_available + for ticket in self: + if ticket.seats_max > 0: + ticket.seats_available = ticket.seats_max - (ticket.seats_reserved + ticket.seats_used) + + @api.one + @api.constrains('registration_ids', 'seats_max') + def _check_seats_limit(self): + if self.seats_max and self.seats_available < 0: + raise Warning('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}} + + +class event_registration(models.Model): + _inherit = 'event.registration' + + event_ticket_id = fields.Many2one('event.event.ticket', 'Event Ticket') + + @api.one + @api.constrains('event_ticket_id', 'nb_register', 'state') + def _check_ticket_seats_limit(self): + if self.event_ticket_id.seats_max and self.event_ticket_id.seats_available < 0: + raise Warning('No more available seats for this ticket') diff --git a/addons/event_sale/models/product.py b/addons/event_sale/models/product.py new file mode 100644 index 00000000000..476425081e7 --- /dev/null +++ b/addons/event_sale/models/product.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +from openerp.osv import fields, osv + + +class product_template(osv.osv): + _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 {} + + +class product(osv.osv): + _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): + """ Redirection, inheritance mechanism hides the method on the model """ + if event_ok: + return {'value': {'type': 'service'}} + return {} diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py new file mode 100644 index 00000000000..6705f00160a --- /dev/null +++ b/addons/event_sale/models/sale_order.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +from openerp.osv import fields, osv +from openerp.tools.translate import _ + + +class sale_order_line(osv.osv): + _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"), + 'event_ok': fields.related('product_id', 'event_ok', string='event_ok', type='boolean'), + } + + def product_id_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False, + qty_uos=0, uos=False, name='', partner_id=False, lang=False, + update_tax=True, date_order=False, packaging=False, + fiscal_position=False, flag=False, context=None): + """ check product if event type """ + res = super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty=qty, uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id, lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context) + if product: + product_res = self.pool.get('product.product').browse(cr, uid, product, context=context) + if product_res.event_ok: + res['value'].update(event_type_id=product_res.event_type_id.id, + event_ok=product_res.event_ok) + else: + res['value'].update(event_type_id=False, + event_ok=False) + return res + + def button_confirm(self, cr, uid, ids, context=None): + ''' + create registration with sales order + ''' + context = dict(context or {}) + registration_obj = self.pool.get('event.registration') + for order_line in self.browse(cr, uid, ids, context=context): + if order_line.event_id: + dic = { + 'name': order_line.order_id.partner_invoice_id.name, + 'partner_id': order_line.order_id.partner_id.id, + 'nb_register': int(order_line.product_uom_qty), + 'email': order_line.order_id.partner_id.email, + 'phone': order_line.order_id.partner_id.phone, + 'origin': order_line.order_id.name, + 'event_id': order_line.event_id.id, + 'event_ticket_id': order_line.event_ticket_id and order_line.event_ticket_id.id or None, + } + + if order_line.event_ticket_id: + message = _("The registration has been created for event %s with the ticket %s from the Sale Order %s. ") % (order_line.event_id.name, order_line.event_ticket_id.name, order_line.order_id.name) + else: + message = _("The registration has been created for event %s from the Sale Order %s. ") % (order_line.event_id.name, order_line.order_id.name) + + context.update({'mail_create_nolog': True}) + registration_id = registration_obj.create(cr, uid, dic, context=context) + registration_obj.message_post(cr, uid, [registration_id], body=message, context=context) + return super(sale_order_line, self).button_confirm(cr, uid, ids, context=context) + + 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}} diff --git a/addons/event_sale/event_sale_view.xml b/addons/event_sale/views/event.xml similarity index 64% rename from addons/event_sale/event_sale_view.xml rename to addons/event_sale/views/event.xml index 9c4f265ef4d..dd4c4393bbc 100644 --- a/addons/event_sale/event_sale_view.xml +++ b/addons/event_sale/views/event.xml @@ -2,22 +2,6 @@ - - product.template - - -
-
- -
-
- - - - -
- event.registration.ticket.search event.registration @@ -50,26 +34,6 @@
- - - event.sale.order - sale.order - - - - - - - - - - - - - - - view_event_form @@ -82,7 +46,7 @@ - + @@ -108,7 +72,7 @@ - + diff --git a/addons/event_sale/views/product.xml b/addons/event_sale/views/product.xml new file mode 100644 index 00000000000..dcb548560e0 --- /dev/null +++ b/addons/event_sale/views/product.xml @@ -0,0 +1,20 @@ + + + + + product.template + + +
+
+ +
+
+ + + + +
+
+
diff --git a/addons/event_sale/views/sale_order.xml b/addons/event_sale/views/sale_order.xml new file mode 100644 index 00000000000..a85691c0f55 --- /dev/null +++ b/addons/event_sale/views/sale_order.xml @@ -0,0 +1,24 @@ + + + + + event.sale.order + sale.order + + + + + + + + + + + + + + + + +