2012-02-07 14:10:34 +00:00
# -*- 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/>.
#
##############################################################################
2014-04-28 09:44:49 +00:00
from openerp . addons . event . event import event_event as Event
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
from openerp . tools . translate import _
2012-02-27 17:10:43 +00:00
2014-01-30 17:24:22 +00:00
class product_template ( osv . osv ) :
2013-11-15 16:08:28 +00:00
_inherit = ' product.template '
2012-02-27 17:10:43 +00:00
_columns = {
2012-12-21 16:48:08 +00:00
' 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. ' ) ,
2012-02-07 14:10:34 +00:00
}
2012-02-28 10:59:06 +00:00
2013-08-07 11:28:12 +00:00
def onchange_event_ok ( self , cr , uid , ids , type , event_ok , context = None ) :
2014-01-30 17:24:22 +00:00
if event_ok :
return { ' value ' : { ' type ' : ' service ' } }
return { }
class product ( osv . osv ) :
_inherit = ' product.product '
2014-05-02 14:01:52 +00:00
_columns = {
' event_ticket_ids ' : fields . one2many ( ' event.event.ticket ' , ' product_id ' , ' Event Tickets ' ) ,
}
2014-01-30 17:24:22 +00:00
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 { }
2012-02-28 10:59:06 +00:00
2012-02-08 13:20:40 +00:00
class sale_order_line ( osv . osv ) :
2012-02-27 17:10:43 +00:00
_inherit = ' sale.order.line '
_columns = {
2013-08-07 11:28:12 +00:00
' 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. " ) ,
2012-02-28 11:59:04 +00:00
#those 2 fields are used for dynamic domains and filled by onchange
2012-11-12 09:21:25 +00:00
' event_type_id ' : fields . related ( ' product_id ' , ' event_type_id ' , type = ' many2one ' , relation = " event.type " , string = " Event Type " ) ,
2012-10-17 12:38:14 +00:00
' event_ok ' : fields . related ( ' product_id ' , ' event_ok ' , string = ' event_ok ' , type = ' boolean ' ) ,
2012-02-08 13:20:40 +00:00
}
2012-02-09 08:39:58 +00:00
2012-02-10 13:11:21 +00:00
def product_id_change ( self , cr , uid , ids ,
pricelist ,
2013-09-02 10:46:46 +00:00
product ,
qty = 0 ,
2012-02-10 13:11:21 +00:00
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 ) :
2012-02-09 14:22:54 +00:00
"""
2012-02-27 17:10:43 +00:00
check product if event type
2012-02-09 14:22:54 +00:00
"""
2012-02-27 17:10:43 +00:00
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 )
2012-02-09 08:39:58 +00:00
if product :
2012-02-27 17:10:43 +00:00
product_res = self . pool . get ( ' product.product ' ) . browse ( cr , uid , product , context = context )
2012-02-28 16:38:23 +00:00
if product_res . event_ok :
2012-02-27 17:10:43 +00:00
res [ ' value ' ] . update ( { ' event_type_id ' : product_res . event_type_id . id , ' event_ok ' : product_res . event_ok } )
2012-02-10 13:11:21 +00:00
return res
2012-02-08 13:20:40 +00:00
2012-02-27 17:10:43 +00:00
def button_confirm ( self , cr , uid , ids , context = None ) :
2012-02-09 14:22:54 +00:00
'''
2012-12-21 16:48:08 +00:00
create registration with sales order
2012-02-09 14:22:54 +00:00
'''
2012-12-03 09:34:41 +00:00
if context is None :
context = { }
2012-02-27 17:10:43 +00:00
registration_obj = self . pool . get ( ' event.registration ' )
for order_line in self . browse ( cr , uid , ids , context = context ) :
2013-08-07 13:45:47 +00:00
if order_line . event_id :
2012-02-10 13:11:21 +00:00
dic = {
2012-02-27 17:10:43 +00:00
' 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 ,
2012-02-28 16:38:23 +00:00
' event_id ' : order_line . event_id . id ,
2013-08-07 11:28:12 +00:00
' event_ticket_id ' : order_line . event_ticket_id and order_line . event_ticket_id . id or None ,
2012-02-10 13:11:21 +00:00
}
2013-08-07 11:28:12 +00:00
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 )
2013-05-30 15:06:21 +00:00
context . update ( { ' mail_create_nolog ' : True } )
2012-02-27 17:10:43 +00:00
registration_id = registration_obj . create ( cr , uid , dic , context = context )
2013-05-17 04:58:59 +00:00
registration_obj . message_post ( cr , uid , [ registration_id ] , body = message , context = context )
2012-02-27 17:10:43 +00:00
return super ( sale_order_line , self ) . button_confirm ( cr , uid , ids , context = context )
2013-08-07 11:28:12 +00:00
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 } }
2013-08-07 13:45:47 +00:00
class event_event ( osv . osv ) :
2013-08-07 11:28:12 +00:00
_inherit = ' event.event '
2014-01-27 13:58:28 +00:00
def _get_seats_max ( self , cr , uid , ids , field_name , arg , context = None ) :
2013-08-07 11:28:12 +00:00
result = dict . fromkeys ( ids , 0 )
for rec in self . browse ( cr , uid , ids , context = context ) :
2014-01-27 13:58:28 +00:00
result [ rec . id ] = sum ( [ ticket . seats_max for ticket in rec . event_ticket_ids ] )
2013-08-07 11:28:12 +00:00
return result
2013-11-26 16:14:24 +00:00
def _get_tickets ( self , cr , uid , context = { } ) :
try :
2014-01-27 13:58:28 +00:00
product = self . pool . get ( ' ir.model.data ' ) . get_object ( cr , uid , ' event_sale ' , ' product_product_event ' )
return [ {
' name ' : _ ( ' Subscription ' ) ,
' product_id ' : product . id ,
' price ' : 0 ,
} ]
2013-11-26 16:14:24 +00:00
except ValueError :
2014-01-27 13:58:28 +00:00
pass
return [ ]
2013-11-26 16:14:24 +00:00
2014-04-28 09:44:49 +00:00
def _get_ticket_events ( self , cr , uid , ids , context = None ) :
2014-04-29 10:50:20 +00:00
# `self` is the event.event.ticket model when called by ORM!
2014-04-28 09:44:49 +00:00
return list ( set ( ticket . event_id . id
for ticket in self . browse ( cr , uid , ids , context ) ) )
2014-04-29 10:50:20 +00:00
# proxy method, can't import parent method directly as unbound_method: it would receive
# an invalid `self` <event_registration> when called by ORM
def _events_from_registrations ( self , cr , uid , ids , context = None ) :
# `self` is the event.registration model when called by ORM
return self . pool [ ' event.event ' ] . _get_events_from_registrations ( cr , uid , ids , context = context )
2013-08-07 11:28:12 +00:00
_columns = {
' event_ticket_ids ' : fields . one2many ( ' event.event.ticket ' , " event_id " , " Event Ticket " ) ,
2014-01-27 13:58:28 +00:00
' seats_max ' : fields . function ( _get_seats_max ,
string = ' Maximum Avalaible Seats ' ,
2013-08-07 11:28:12 +00:00
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 ) " ,
2014-01-27 13:58:28 +00:00
type = ' integer ' ,
2014-04-28 09:44:49 +00:00
readonly = True ) ,
' seats_available ' : fields . function ( Event . _get_seats , oldname = ' register_avail ' , string = ' Available Seats ' ,
type = ' integer ' , multi = ' seats_reserved ' ,
store = {
2014-04-29 10:50:20 +00:00
' event.registration ' : ( _events_from_registrations , [ ' state ' ] , 10 ) ,
2014-04-28 09:44:49 +00:00
' event.event ' : ( lambda self , cr , uid , ids , c = { } : ids ,
[ ' seats_max ' , ' registration_ids ' ] , 20 ) ,
' event.event.ticket ' : ( _get_ticket_events , [ ' seats_max ' ] , 10 ) ,
} ) ,
2013-08-07 11:28:12 +00:00
}
2013-11-26 16:14:24 +00:00
_defaults = {
' event_ticket_ids ' : _get_tickets
}
2013-08-07 11:28:12 +00:00
class event_ticket ( osv . osv ) :
_name = ' event.event.ticket '
2014-01-27 13:58:28 +00:00
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 .
2013-08-07 11:28:12 +00:00
"""
2014-01-28 11:31:01 +00:00
res = dict ( [ ( id , { } ) for id in ids ] )
2014-01-27 13:58:28 +00:00
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
2013-08-07 11:28:12 +00:00
return res
2014-04-22 12:31:53 +00:00
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 ) }
2013-08-07 11:28:12 +00:00
_columns = {
2014-04-14 12:32:31 +00:00
' name ' : fields . char ( ' Name ' , size = 64 , required = True , translate = True ) ,
2013-09-28 20:41:05 +00:00
' event_id ' : fields . many2one ( ' event.event ' , " Event " , required = True , ondelete = ' cascade ' ) ,
2013-08-07 11:28:12 +00:00
' 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 " ) ,
2014-04-22 12:31:53 +00:00
' is_expired ' : fields . function ( _is_expired , type = ' boolean ' , string = ' Is Expired ' ) ,
2013-08-07 11:28:12 +00:00
' price ' : fields . float ( ' Price ' ) ,
2014-01-27 13:58:28 +00:00
' seats_max ' : fields . integer ( ' Maximum Avalaible 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 ' ) ,
2013-08-07 11:28:12 +00:00
}
2014-01-23 16:37:46 +00:00
2013-11-26 16:14:24 +00:00
def _default_product_id ( self , cr , uid , context = { } ) :
2014-01-23 16:37:46 +00:00
imd = self . pool . get ( ' ir.model.data ' )
2013-11-26 16:14:24 +00:00
try :
2014-01-23 16:37:46 +00:00
product = imd . get_object ( cr , uid , ' event_sale ' , ' product_product_event ' )
2013-11-26 16:14:24 +00:00
except ValueError :
return False
2014-01-23 16:37:46 +00:00
return product . id
2013-11-26 16:14:24 +00:00
_defaults = {
' product_id ' : _default_product_id
}
2014-01-27 13:58:28 +00:00
def _check_seats_limit ( self , cr , uid , ids , context = None ) :
2013-08-07 13:45:47 +00:00
for ticket in self . browse ( cr , uid , ids , context = context ) :
2014-01-27 13:58:28 +00:00
if ticket . seats_max and ticket . seats_available < 0 :
return False
2013-08-07 13:45:47 +00:00
return True
2014-01-27 13:58:28 +00:00
_constraints = [
( _check_seats_limit , ' No more available tickets. ' , [ ' registration_ids ' , ' seats_max ' ] ) ,
]
2013-08-07 11:28:12 +00:00
def onchange_product_id ( self , cr , uid , ids , product_id = False , context = None ) :
return { ' value ' : { ' price ' : self . pool . get ( " product.product " ) . browse ( cr , uid , product_id ) . list_price or 0 } }
class event_registration ( osv . osv ) :
""" Event Registration """
_inherit = ' event.registration '
_columns = {
' event_ticket_id ' : fields . many2one ( ' event.event.ticket ' , ' Event Ticket ' ) ,
}
2013-08-07 13:45:47 +00:00
2014-01-27 13:58:28 +00:00
def _check_ticket_seats_limit ( self , cr , uid , ids , context = None ) :
2013-08-07 13:45:47 +00:00
for registration in self . browse ( cr , uid , ids , context = context ) :
2014-01-28 09:20:37 +00:00
if registration . event_ticket_id . seats_max and registration . event_ticket_id . seats_available < 0 :
2014-01-27 13:58:28 +00:00
return False
return True
_constraints = [
( _check_ticket_seats_limit , ' No more available tickets. ' , [ ' event_ticket_id ' , ' nb_register ' , ' state ' ] ) ,
2014-04-14 12:32:31 +00:00
]