[CLEAN] event_sale: lint / cleaned module, migrated event models to the new API.
authorThibault Delavallée <tde@openerp.com>
Fri, 3 Oct 2014 08:23:05 +0000 (10:23 +0200)
committerThibault Delavallée <tde@openerp.com>
Fri, 3 Oct 2014 13:07:45 +0000 (15:07 +0200)
12 files changed:
addons/event_sale/__init__.py
addons/event_sale/__openerp__.py
addons/event_sale/event_demo.xml
addons/event_sale/event_sale.py [deleted file]
addons/event_sale/event_sale_view.xml [deleted file]
addons/event_sale/models/__init__.py [new file with mode: 0644]
addons/event_sale/models/event.py [new file with mode: 0644]
addons/event_sale/models/product.py [new file with mode: 0644]
addons/event_sale/models/sale_order.py [new file with mode: 0644]
addons/event_sale/views/event.xml [new file with mode: 0644]
addons/event_sale/views/product.xml [new file with mode: 0644]
addons/event_sale/views/sale_order.xml [new file with mode: 0644]

index 726d2d5..c7b5ac7 100644 (file)
@@ -1,22 +1,3 @@
 # -*- coding: utf-8 -*-
-##############################################################################
-#
-#    OpenERP, Open Source Management Solution
-#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
-#
-#    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 <http://www.gnu.org/licenses/>.
-#
-##############################################################################
 
-import event_sale
+import models
index 6691ad2..d2300d0 100644 (file)
@@ -1,30 +1,10 @@
 # -*- coding: utf-8 -*-
-##############################################################################
-#
-#    OpenERP, Open Source Management Solution
-#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
-#
-#    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 <http://www.gnu.org/licenses/>.
-#
-##############################################################################
-
 
 {
     '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:
index 8a55172..9d0ed23 100644 (file)
@@ -12,7 +12,7 @@
         <field name="standard_price">1000.0</field>
         <field name="uom_id" ref="product.product_uom_unit"/>
         <field name="uom_po_id" ref="product.product_uom_unit"/>
-        <field name="image">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</field>
+        <field name="image" type="base64" file="event_sale/static/img/event_product-image.jpg"/>
     </record>
 
     <record id="event_1_product" model="product.product">
@@ -25,7 +25,7 @@
         <field name="standard_price">1000.0</field>
         <field name="uom_id" ref="product.product_uom_unit"/>
         <field name="uom_po_id" ref="product.product_uom_unit"/>
-        <field name="image">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</field>
+        <field name="image" type="base64" file="event_sale/static/img/event_product-image.jpg"/>
     </record>
 
     <record id="event_2_product" model="product.product">
@@ -38,7 +38,7 @@
         <field name="standard_price">1000.0</field>
         <field name="uom_id" ref="product.product_uom_unit"/>
         <field name="uom_po_id" ref="product.product_uom_unit"/>
-        <field name="image">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</field>
+        <field name="image" type="base64" file="event_sale/static/img/event_product-image.jpg"/>
     </record>
 
     <record id="event.event_3" model="event.event">
diff --git a/addons/event_sale/event_sale.py b/addons/event_sale/event_sale.py
deleted file mode 100644 (file)
index 2d947be..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-#    OpenERP, Open Source Management Solution
-#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
-#
-#    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 <http://www.gnu.org/licenses/>.
-#
-##############################################################################
-
-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 <i>%s</i> with the ticket <i>%s</i> 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 <i>%s</i> 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/event_sale_view.xml b/addons/event_sale/event_sale_view.xml
deleted file mode 100644 (file)
index 9c4f265..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0"?>
-<openerp>
-    <data>
-
-        <record model="ir.ui.view" id="event_sale_product_template_form">
-             <field name="model">product.template</field>
-             <field name="inherit_id" ref="product.product_template_form_view" />
-             <field name="arch" type="xml">
-                <div name="options" position="inside">
-                    <div>
-                        <field name="event_ok" on_change="onchange_event_ok(type, event_ok, context)"/>
-                        <label for="event_ok"/>
-                    </div>
-                </div>
-                <field name='type' position="after">
-                    <field name="event_type_id" attrs="{'invisible': [('event_ok', '=', False)]}"/>
-                </field>
-             </field>
-        </record>
-
-        <record model="ir.ui.view" id="view_event_registration_ticket_search">
-            <field name="name">event.registration.ticket.search</field>
-            <field name="model">event.registration</field>
-            <field name="inherit_id" ref="event.view_registration_search" />
-            <field name="arch" type="xml">
-                <filter name="group_event" position="after">
-                    <filter string="Ticket Type" domain="[]" context="{'group_by':'event_ticket_id'}"/>
-                </filter>
-            </field>
-        </record>
-
-        <record model="ir.ui.view" id="view_event_registration_ticket_tree">
-            <field name="name">event.registration.ticket.tree</field>
-            <field name="model">event.registration</field>
-            <field name="inherit_id" ref="event.view_event_registration_tree" />
-            <field name="arch" type="xml">
-                <field name="event_id" position="after">
-                    <field name="event_ticket_id"/>
-                </field>
-            </field>
-        </record>
-
-        <record model="ir.ui.view" id="view_event_registration_ticket_form">
-            <field name="name">event.registration.ticket.form</field>
-            <field name="model">event.registration</field>
-            <field name="inherit_id" ref="event.view_event_registration_form" />
-            <field name="arch" type="xml">
-                <field name="user_id" position="after">
-                    <field name="event_ticket_id" domain="[('event_id', '=', event_id)]"/>
-                </field>
-            </field>
-        </record>
-
-        <record model="ir.ui.view" id="event_order_line">
-             <field name="name">event.sale.order</field>
-             <field name="model">sale.order</field>
-             <field name="inherit_id" ref="sale.view_order_form" />
-             <field name="arch" type="xml">
-                <xpath expr="//field[@name='product_id']" position="after">
-                    <field name="event_id" domain="['|', ('type','=', False),('type', '=', event_type_id)]" attrs="{'invisible': [('event_ok', '=', False)],'required': [('event_ok', '!=', False)]}"/>
-                    <field name="event_ticket_id" domain="[('event_id', '=', event_id), ('seats_available', '>', 0)]" attrs="{'invisible': [('event_id', '=', False)]}"
-                        on_change="onchange_event_ticket_id(event_ticket_id, context)"/>
-                    <field name="event_type_id" invisible="1"/>
-                    <field name="event_ok" invisible="1"/>
-                </xpath>
-             </field>
-        </record>
-        
-        <!-- the presence of 'event user' makes the order lines non-editable -->
-        <record id="sale.view_order_form_editable_list" model="ir.ui.view">
-            <field name="groups_id" eval="[(4, ref('event.group_event_user'))]"/>
-        </record>        
-        
-        <record id="view_event_form" model="ir.ui.view">
-            <field name="name">view_event_form</field>
-            <field name="model">event.event</field>
-            <field name="inherit_id" ref="event.view_event_form"/>
-            <field name="arch" type="xml">
-                <data>
-                    <xpath expr="//notebook" position="inside">
-                        <page string="Ticket Types">
-                            <field name="event_ticket_ids" context="{'default_name': name}">
-                                <tree string="Payments" editable="bottom">
-                                    <field name="name"/>
-                                    <field name="product_id" on_change='onchange_product_id(product_id)'/>
-                                    <field name="deadline"/>
-                                    <field name="price"/>
-                                    <field name="seats_max"/>
-                                    <field name="seats_reserved"/>
-                                    <field name="seats_unconfirmed"/>
-                                </tree>
-                            </field>
-                        </page>
-                    </xpath>
-               </data>
-            </field>
-        </record>
-
-        <!-- Edit badge report form -->
-        <record id="view_event_form" model="ir.ui.view">
-            <field name="name">view_event_form</field>
-            <field name="model">event.event</field>
-            <field name="inherit_id" ref="event.view_event_form"/>
-            <field name="arch" type="xml">
-                <data>
-                    <xpath expr="//notebook" position="inside">
-                        <page string="Ticket Types">
-                            <field name="event_ticket_ids" context="{'default_name': name}">
-                                <tree string="Payments" editable="bottom">
-                                    <field name="name"/>
-                                    <field name="product_id" on_change='onchange_product_id(product_id)'/>
-                                    <field name="deadline"/>
-                                    <field name="price"/>
-                                    <field name="seats_max"/>
-                                    <field name="seats_reserved"/>
-                                    <field name="seats_unconfirmed"/>
-                                </tree>
-                            </field>
-                        </page>
-                    </xpath>
-               </data>
-            </field>
-        </record>
-    </data>
-</openerp>
diff --git a/addons/event_sale/models/__init__.py b/addons/event_sale/models/__init__.py
new file mode 100644 (file)
index 0000000..988d952
--- /dev/null
@@ -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 (file)
index 0000000..8fc46f5
--- /dev/null
@@ -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 (file)
index 0000000..4764250
--- /dev/null
@@ -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 (file)
index 0000000..6705f00
--- /dev/null
@@ -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 <i>%s</i> with the ticket <i>%s</i> 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 <i>%s</i> 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/views/event.xml b/addons/event_sale/views/event.xml
new file mode 100644 (file)
index 0000000..dd4c439
--- /dev/null
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<openerp>
+    <data>
+
+        <record model="ir.ui.view" id="view_event_registration_ticket_search">
+            <field name="name">event.registration.ticket.search</field>
+            <field name="model">event.registration</field>
+            <field name="inherit_id" ref="event.view_registration_search" />
+            <field name="arch" type="xml">
+                <filter name="group_event" position="after">
+                    <filter string="Ticket Type" domain="[]" context="{'group_by':'event_ticket_id'}"/>
+                </filter>
+            </field>
+        </record>
+
+        <record model="ir.ui.view" id="view_event_registration_ticket_tree">
+            <field name="name">event.registration.ticket.tree</field>
+            <field name="model">event.registration</field>
+            <field name="inherit_id" ref="event.view_event_registration_tree" />
+            <field name="arch" type="xml">
+                <field name="event_id" position="after">
+                    <field name="event_ticket_id"/>
+                </field>
+            </field>
+        </record>
+
+        <record model="ir.ui.view" id="view_event_registration_ticket_form">
+            <field name="name">event.registration.ticket.form</field>
+            <field name="model">event.registration</field>
+            <field name="inherit_id" ref="event.view_event_registration_form" />
+            <field name="arch" type="xml">
+                <field name="user_id" position="after">
+                    <field name="event_ticket_id" domain="[('event_id', '=', event_id)]"/>
+                </field>
+            </field>
+        </record>
+        
+        <record id="view_event_form" model="ir.ui.view">
+            <field name="name">view_event_form</field>
+            <field name="model">event.event</field>
+            <field name="inherit_id" ref="event.view_event_form"/>
+            <field name="arch" type="xml">
+                <data>
+                    <xpath expr="//notebook" position="inside">
+                        <page string="Ticket Types">
+                            <field name="event_ticket_ids" context="{'default_name': name}">
+                                <tree string="Payments" editable="bottom">
+                                    <field name="name"/>
+                                    <field name="product_id"/>
+                                    <field name="deadline"/>
+                                    <field name="price"/>
+                                    <field name="seats_max"/>
+                                    <field name="seats_reserved"/>
+                                    <field name="seats_unconfirmed"/>
+                                </tree>
+                            </field>
+                        </page>
+                    </xpath>
+               </data>
+            </field>
+        </record>
+
+        <!-- Edit badge report form -->
+        <record id="view_event_form" model="ir.ui.view">
+            <field name="name">view_event_form</field>
+            <field name="model">event.event</field>
+            <field name="inherit_id" ref="event.view_event_form"/>
+            <field name="arch" type="xml">
+                <data>
+                    <xpath expr="//notebook" position="inside">
+                        <page string="Ticket Types">
+                            <field name="event_ticket_ids" context="{'default_name': name}">
+                                <tree string="Payments" editable="bottom">
+                                    <field name="name"/>
+                                    <field name="product_id"/>
+                                    <field name="deadline"/>
+                                    <field name="price"/>
+                                    <field name="seats_max"/>
+                                    <field name="seats_reserved"/>
+                                    <field name="seats_unconfirmed"/>
+                                </tree>
+                            </field>
+                        </page>
+                    </xpath>
+               </data>
+            </field>
+        </record>
+    </data>
+</openerp>
diff --git a/addons/event_sale/views/product.xml b/addons/event_sale/views/product.xml
new file mode 100644 (file)
index 0000000..dcb5485
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<openerp>
+    <data>
+        <record model="ir.ui.view" id="event_sale_product_template_form">
+             <field name="model">product.template</field>
+             <field name="inherit_id" ref="product.product_template_form_view" />
+             <field name="arch" type="xml">
+                <div name="options" position="inside">
+                    <div>
+                        <field name="event_ok" on_change="onchange_event_ok(type, event_ok, context)"/>
+                        <label for="event_ok"/>
+                    </div>
+                </div>
+                <field name='type' position="after">
+                    <field name="event_type_id" attrs="{'invisible': [('event_ok', '=', False)]}"/>
+                </field>
+             </field>
+        </record>
+    </data>
+</openerp>
diff --git a/addons/event_sale/views/sale_order.xml b/addons/event_sale/views/sale_order.xml
new file mode 100644 (file)
index 0000000..a85691c
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<openerp>
+    <data>
+        <record model="ir.ui.view" id="event_order_line">
+             <field name="name">event.sale.order</field>
+             <field name="model">sale.order</field>
+             <field name="inherit_id" ref="sale.view_order_form" />
+             <field name="arch" type="xml">
+                <xpath expr="//field[@name='product_id']" position="after">
+                    <field name="event_id" domain="['|', ('type','=', False),('type', '=', event_type_id)]" attrs="{'invisible': [('event_ok', '=', False)],'required': [('event_ok', '!=', False)]}"/>
+                    <field name="event_ticket_id" domain="[('event_id', '=', event_id), ('seats_available', '>', 0)]" attrs="{'invisible': [('event_id', '=', False)]}"
+                        on_change="onchange_event_ticket_id(event_ticket_id, context)"/>
+                    <field name="event_type_id" invisible="1"/>
+                    <field name="event_ok" invisible="1"/>
+                </xpath>
+             </field>
+        </record>
+        
+        <!-- the presence of 'event user' makes the order lines non-editable -->
+        <record id="sale.view_order_form_editable_list" model="ir.ui.view">
+            <field name="groups_id" eval="[(4, ref('event.group_event_user'))]"/>
+        </record>        
+    </data>
+</openerp>