From 96fb5d41d9b532be490a6d0c76759c09cd347b0a Mon Sep 17 00:00:00 2001 From: Shivam Dudhat Date: Mon, 31 Aug 2015 17:56:20 +0530 Subject: [PATCH] [MIG] event_sale : migration to new api --- addons/event_sale/__openerp__.py | 1 - addons/event_sale/data/event_demo.xml | 10 +- addons/event_sale/data/event_sale_data.xml | 4 +- addons/event_sale/models/event.py | 163 ++++++++---------- addons/event_sale/models/product.py | 36 ++-- addons/event_sale/models/sale_order.py | 77 ++++----- addons/event_sale/views/event_views.xml | 32 ++-- addons/event_sale/views/product_views.xml | 13 +- addons/event_sale/views/sale_order_views.xml | 19 +- .../wizard/event_edit_registration.py | 17 +- .../wizard/event_edit_registration.xml | 7 +- 11 files changed, 168 insertions(+), 211 deletions(-) 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 {} - - - +