[FIX] Fixed in advance search when search on 'None of the following condition must...
[odoo/odoo.git] / addons / event / event.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 import time
23
24 from crm import crm
25 from osv import fields, osv
26 from tools.translate import _
27 import decimal_precision as dp
28 from crm import wizard
29
30
31 wizard.mail_compose_message.SUPPORTED_MODELS.append('event.registration')
32
33 class event_type(osv.osv):
34     """ Event Type """
35     _name = 'event.type'
36     _description = __doc__
37     _columns = {
38         'name': fields.char('Event type', size=64, required=True),
39     }
40
41 event_type()
42
43 class event_event(osv.osv):
44     """Event"""
45     _name = 'event.event'
46     _description = __doc__
47     _order = 'date_begin'
48
49     def copy(self, cr, uid, id, default=None, context=None):
50         """ Copy record of Given id
51         @param id: Id of Event record.
52         @param context: A standard dictionary for contextual values
53         """
54         if not default:
55             default = {}
56         default.update({
57             'state': 'draft',
58             'registration_ids': False,
59         })
60         return super(event_event, self).copy(cr, uid, id, default=default, context=context)
61
62     def onchange_product(self, cr, uid, ids, product_id=False):
63         """This function returns value of  product's unit price based on product id.
64         @param self: The object pointer
65         @param cr: the current row, from the database cursor,
66         @param uid: the current user’s ID for security checks,
67         @param ids: List of Event IDs
68         @param product_id: Product's id
69         """
70         if not product_id:
71             return {'value': {'unit_price': False}}
72         else:
73            unit_price=self.pool.get('product.product').price_get(cr, uid, [product_id])[product_id]
74            return {'value': {'unit_price': unit_price}}
75
76     def button_draft(self, cr, uid, ids, context=None):
77         return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
78
79     def button_cancel(self, cr, uid, ids, context=None):
80         return self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
81
82     def button_done(self, cr, uid, ids, context=None):
83         if type(ids) in (int, long,):
84             ids = [ids]
85         return self.write(cr, uid, ids, {'state': 'done'}, context=context)
86
87     def do_confirm(self, cr, uid, ids, context=None):
88         """ Confirm Event and send confirmation email to all register peoples
89         """
90         register_pool = self.pool.get('event.registration')
91         for event in self.browse(cr, uid, ids, context=context):
92             if event.mail_auto_confirm:
93                 #send reminder that will confirm the event for all the people that were already confirmed
94                 reg_ids = register_pool.search(cr, uid, [
95                                ('event_id', '=', event.id),
96                                ('state', 'not in', ['draft', 'cancel'])], context=context)
97                 register_pool.mail_user_confirm(cr, uid, reg_ids)
98
99         return self.write(cr, uid, ids, {'state': 'confirm'}, context=context)
100
101     def button_confirm(self, cr, uid, ids, context=None):
102         """This Function Confirm Event.
103         @param ids: List of Event IDs
104         @param context: A standard dictionary for contextual values
105         @return: True
106         """
107         if context is None:
108             context = {}
109         res = False
110         if type(ids) in (int, long,):
111             ids = [ids]
112         data_pool = self.pool.get('ir.model.data')
113         unconfirmed_ids = []
114         for event in self.browse(cr, uid, ids, context=context):
115             total_confirmed = event.register_current
116             if total_confirmed >= event.register_min or event.register_max == 0:
117                 res = self.do_confirm(cr, uid, [event.id], context=context)
118             else:
119                 unconfirmed_ids.append(event.id)
120         if unconfirmed_ids:
121             view_id = data_pool.get_object_reference(cr, uid, 'event', 'view_event_confirm')
122             view_id = view_id and view_id[1] or False
123             context['event_ids'] = unconfirmed_ids
124             return {
125                 'name': _('Confirm Event'),
126                 'context': context,
127                 'view_type': 'form',
128                 'view_mode': 'tree,form',
129                 'res_model': 'event.confirm',
130                 'views': [(view_id, 'form')],
131                 'type': 'ir.actions.act_window',
132                 'target': 'new',
133                 'context': context,
134                 'nodestroy': True
135             }
136         return res
137
138     def _get_register(self, cr, uid, ids, fields, args, context=None):
139         """Get Confirm or uncofirm register value.
140         @param ids: List of Event registration type's id
141         @param fields: List of function fields(register_current and register_prospect).
142         @param context: A standard dictionary for contextual values
143         @return: Dictionary of function fields value.
144         """
145         register_pool = self.pool.get('event.registration')
146         res = {}
147         for event in self.browse(cr, uid, ids, context=context):
148             res[event.id] = {}
149             for field in fields:
150                 res[event.id][field] = False
151             state = []
152             if 'register_current' in fields:
153                 state += ['open', 'done']
154             if 'register_prospect' in fields:
155                 state.append('draft')
156
157             reg_ids = register_pool.search(cr, uid, [
158                         ('event_id', '=', event.id),
159                        ('state', 'in', state)], context=context)
160
161             number = 0.0
162             if reg_ids:
163                 cr.execute('SELECT SUM(nb_register) FROM event_registration WHERE id IN %s', (tuple(reg_ids),))
164                 number = cr.fetchone()
165
166             if 'register_current' in fields:
167                 res[event.id]['register_current'] = number and number[0] or 0.0
168             if 'register_prospect' in fields:
169                 res[event.id]['register_prospect'] = number and number[0] or 0.0
170         return res
171
172     def write(self, cr, uid, ids, vals, context=None):
173         """
174         Writes values in one or several fields.
175         @param ids: List of Event registration type's IDs
176         @param vals: dictionary with values to update.
177         @return: True
178         """
179         register_pool = self.pool.get('event.registration')
180         res = super(event_event, self).write(cr, uid, ids, vals, context=context)
181         if vals.get('date_begin', False) or vals.get('mail_auto_confirm', False) or vals.get('mail_confirm', False):
182             for event in self.browse(cr, uid, ids, context=context):
183                 #change the deadlines of the registration linked to this event
184                 register_values = {}
185                 if vals.get('date_begin', False):
186                     register_values['date_deadline'] = vals['date_begin']
187
188                 #change the description of the registration linked to this event
189                 if vals.get('mail_auto_confirm', False):
190                     if vals['mail_auto_confirm']:
191                         if 'mail_confirm' not in vals:
192                             vals['mail_confirm'] = event.mail_confirm
193                     else:
194                         vals['mail_confirm'] = False
195                 if 'mail_confirm' in vals:
196                     register_values['description'] = vals['mail_confirm']
197
198                 if register_values:
199                     reg_ids = register_pool.search(cr, uid, [('event_id', '=', event.id)], context=context)
200                     register_pool.write(cr, uid, reg_ids, register_values, context=context)
201         return res
202
203     _columns = {
204         'name': fields.char('Summary', size=64, required=True, translate=True, readonly=False, states={'done': [('readonly', True)]}),
205         'user_id': fields.many2one('res.users', 'Responsible User', readonly=False, states={'done': [('readonly', True)]}),
206         'parent_id': fields.many2one('event.event', 'Parent Event', readonly=False, states={'done': [('readonly', True)]}),
207         'section_id': fields.many2one('crm.case.section', 'Sale Team', readonly=False, states={'done': [('readonly', True)]}),
208         'child_ids': fields.one2many('event.event', 'parent_id', 'Child Events', readonly=False, states={'done': [('readonly', True)]}),
209         'reply_to': fields.char('Reply-To', size=64, readonly=False, states={'done': [('readonly', True)]}, help="The email address put in the 'Reply-To' of all emails sent by OpenERP"),
210         'type': fields.many2one('event.type', 'Type', help="Type of Event like Seminar, Exhibition, Conference, Training.", readonly=False, states={'done': [('readonly', True)]}),
211         'register_max': fields.integer('Maximum Registrations', help="Provide Maximum Number of Registrations", readonly=True, states={'draft': [('readonly', False)]}),
212         'register_min': fields.integer('Minimum Registrations', help="Provide Minimum Number of Registrations", readonly=True, states={'draft': [('readonly', False)]}),
213         'register_current': fields.function(_get_register, string='Confirmed Registrations', multi='register_current',
214             help="Total of Open and Done Registrations"),
215         'register_prospect': fields.function(_get_register, string='Unconfirmed Registrations', multi='register_prospect',
216             help="Total of Prospect Registrations"),
217         'registration_ids': fields.one2many('event.registration', 'event_id', 'Registrations', readonly=False, states={'done': [('readonly', True)]}),
218         'date_begin': fields.datetime('Beginning date', required=True, help="Beginning Date of Event", readonly=True, states={'draft': [('readonly', False)]}),
219         'date_end': fields.datetime('Closing date', required=True, help="Closing Date of Event", readonly=True, states={'draft': [('readonly', False)]}),
220         'state': fields.selection([
221             ('draft', 'Draft'),
222             ('confirm', 'Confirmed'),
223             ('done', 'Done'),
224             ('cancel', 'Cancelled')],
225             'State', readonly=True, required=True,
226             help='If event is created, the state is \'Draft\'.If event is confirmed for the particular dates the state is set to \'Confirmed\'. If the event is over, the state is set to \'Done\'.If event is cancelled the state is set to \'Cancelled\'.'),
227         'mail_auto_registr': fields.boolean('Mail Auto Register', readonly=False, states={'done': [('readonly', True)]}, help='Check this box if you want to use automatic emailing for new registration.'),
228         'mail_auto_confirm': fields.boolean('Mail Auto Confirm', readonly=False, states={'done': [('readonly', True)]}, help='Check this box if you want to use automatic confirmation emailing or reminder.'),
229         'mail_registr': fields.text('Registration Email', readonly=False, states={'done': [('readonly', True)]}, help='This email will be sent when someone subscribes to the event.'),
230         'mail_confirm': fields.text('Confirmation Email', readonly=False, states={'done': [('readonly', True)]}, help="This email will be sent when the event gets confirmed or when someone subscribes to a confirmed event. This is also the email sent to remind someone about the event."),
231         'product_id': fields.many2one('product.product', 'Product', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="The invoices of this event registration will be created with this Product. Thus it allows you to set the default label and the accounting info you want by default on these invoices."),
232         'note': fields.text('Notes', help="Description or Summary of Event", readonly=False, states={'done': [('readonly', True)]}),
233         'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', readonly=True, states={'draft': [('readonly', False)]}, help="Pricelist version for current event."),
234         'unit_price': fields.related('product_id', 'list_price', type='float', string='Registration Cost', readonly=True, states={'draft':[('readonly',False)]}, help="This will be the default price used as registration cost when invoicing this event. Note that you can specify a specific amount for each registration.", digits_compute=dp.get_precision('Sale Price')),
235         'main_speaker_id': fields.many2one('res.partner','Main Speaker', readonly=False, states={'done': [('readonly', True)]}, help="Speaker who will be giving speech at the event."),
236         'speaker_ids': fields.many2many('res.partner', 'event_speaker_rel', 'speaker_id', 'partner_id', 'Other Speakers', readonly=False, states={'done': [('readonly', True)]}),
237         'address_id': fields.many2one('res.partner.address','Location Address', readonly=False, states={'done': [('readonly', True)]}),
238         'speaker_confirmed': fields.boolean('Speaker Confirmed', readonly=False, states={'done': [('readonly', True)]}),
239         'country_id': fields.related('address_id', 'country_id',
240                     type='many2one', relation='res.country', string='Country', readonly=False, states={'done': [('readonly', True)]}),
241         'language': fields.char('Language',size=64, readonly=False, states={'done': [('readonly', True)]}),
242         'note': fields.text('Description', readonly=False, states={'done': [('readonly', True)]}),
243         'company_id': fields.many2one('res.company', 'Company', required=False, change_default=True, readonly=False, states={'done': [('readonly', True)]}),
244     }
245
246     _defaults = {
247         'state': 'draft',
248         'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'event.event', context=c),
249         'user_id': lambda obj, cr, uid, context: uid,
250     }
251
252     def _check_recursion(self, cr, uid, ids, context=None):
253         return super(event_event, self)._check_recursion(cr, uid, ids, context=context)
254
255     def _check_closing_date(self, cr, uid, ids, context=None):
256         for event in self.browse(cr, uid, ids, context=context):
257             if event.date_end < event.date_begin:
258                 return False
259         return True
260
261     _constraints = [
262         (_check_recursion, 'Error ! You cannot create recursive event.', ['parent_id']),
263         (_check_closing_date, 'Error ! Closing Date cannot be set before Beginning Date.', ['date_end']),
264     ]
265
266     def do_team_change(self, cr, uid, ids, team_id, context=None):
267         """
268         On Change Callback: when team change, this is call.
269         on this function, take value of reply_to from selected team.
270         """
271         if not team_id:
272             return {}
273         team_pool = self.pool.get('crm.case.section')
274         res = {}
275         team = team_pool.browse(cr, uid, team_id, context=context)
276         if team.reply_to:
277             res = {'value': {'reply_to': team.reply_to}}
278         return res
279
280 event_event()
281
282 class event_registration(osv.osv):
283     """Event Registration"""
284     _name= 'event.registration'
285     _description = __doc__
286     _inherit = 'mail.thread'
287
288     def _amount_line(self, cr, uid, ids, field_name, arg, context=None):
289         cur_obj = self.pool.get('res.currency')
290         res = {}
291         for line in self.browse(cr, uid, ids, context=context):
292             price = line.unit_price * line.nb_register
293             pricelist = line.event_id.pricelist_id or line.partner_invoice_id.property_product_pricelist
294             cur = pricelist and pricelist.currency_id or False
295             res[line.id] = cur and cur_obj.round(cr, uid, cur, price) or price
296         return res
297
298     _columns = {
299         'id': fields.integer('ID'),
300         'name': fields.char('Summary', size=124,  readonly=True, states={'draft': [('readonly', False)]}),
301         'email_cc': fields.text('CC', size=252, readonly=False, states={'done': [('readonly', True)]}, help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"),
302         'nb_register': fields.integer('Quantity', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Number of Registrations or Tickets"),
303         'event_id': fields.many2one('event.event', 'Event', required=True, readonly=True, states={'draft': [('readonly', False)]}),
304         'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
305         "partner_invoice_id": fields.many2one('res.partner', 'Partner Invoiced', readonly=True, states={'draft': [('readonly', False)]}),
306         "contact_id": fields.many2one('res.partner.address', 'Partner Contact', readonly=False, states={'done': [('readonly', True)]}), #TODO: filter only the contacts that have a function into the selected partner_id
307         "unit_price": fields.float('Unit Price', required=True, digits_compute=dp.get_precision('Sale Price'), readonly=True, states={'draft': [('readonly', False)]}),
308         'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute=dp.get_precision('Sale Price'), store=True),
309         "badge_ids": fields.one2many('event.registration.badge', 'registration_id', 'Badges', readonly=False, states={'done': [('readonly', True)]}),
310         "event_product": fields.char("Invoice Name", size=128, readonly=True, states={'draft': [('readonly', False)]}),
311         "tobe_invoiced": fields.boolean("To be Invoiced", readonly=True, states={'draft': [('readonly', False)]}),
312         "invoice_id": fields.many2one("account.invoice", "Invoice", readonly=True),
313         'date_closed': fields.datetime('Closed', readonly=True),
314         'ref': fields.reference('Reference', selection=crm._links_get, size=128),
315         'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
316         'email_from': fields.char('Email', size=128, states={'done': [('readonly', True)]}, help="These people will receive email."),
317         'create_date': fields.datetime('Creation Date', readonly=True),
318         'write_date': fields.datetime('Write Date', readonly=True),
319         'description': fields.text('Description', states={'done': [('readonly', True)]}),
320         'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
321         'log_ids': fields.one2many('mail.message', 'res_id', 'Logs', domain=[('email_from', '=', False),('model','=',_name)]),
322         'date_deadline': fields.related('event_id','date_end', type='datetime', string="End Date", readonly=True),
323         'date': fields.related('event_id', 'date_begin', type='datetime', string="Start Date", readonly=True),
324         'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}),
325         'active': fields.boolean('Active'),
326         'section_id': fields.related('event_id', 'section_id', type='many2one', relation='crm.case.section', string='Sale Team', store=True, readonly=True),
327         'company_id': fields.related('event_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True, states={'draft':[('readonly',False)]}),
328         'state': fields.selection([('open', 'Confirmed'),
329                                     ('draft', 'Unconfirmed'),
330                                     ('cancel', 'Cancelled'),
331                                     ('done', 'Done')], 'State', \
332                                     size=16, readonly=True)
333     }
334     _defaults = {
335         'nb_register': 1,
336         'tobe_invoiced':  True,
337         'state': 'draft',
338         'active': 1,
339         'user_id': lambda self, cr, uid, ctx: uid,
340     }
341
342     def _make_invoice(self, cr, uid, reg, lines, context=None):
343         """ Create Invoice from Invoice lines
344         @param reg: Model of Event Registration
345         @param lines: Ids of Invoice lines
346         """
347         if context is None:
348             context = {}
349         inv_pool = self.pool.get('account.invoice')
350         val_invoice = inv_pool.onchange_partner_id(cr, uid, [], 'out_invoice', reg.partner_invoice_id.id, False, False)
351         val_invoice['value'].update({'partner_id': reg.partner_invoice_id.id})
352         val_invoice['value'].update({
353                 'origin': reg.event_product,
354                 'reference': False,
355                 'invoice_line': [(6, 0, lines)],
356                 'comment': "",
357                 'date_invoice': context.get('date_inv', False)
358             })
359         inv_id = inv_pool.create(cr, uid, val_invoice['value'], context=context)
360         inv_pool.button_compute(cr, uid, [inv_id])
361         self.message_append(cr, uid, [reg], _('Invoiced'))
362         return inv_id
363
364     def copy(self, cr, uid, id, default=None, context=None):
365         """ Copy record of Given id
366         @param id: Id of Registration record.
367         @param context: A standard dictionary for contextual values
368         """
369         if not default:
370             default = {}
371         default.update({
372             'invoice_id': False,
373         })
374         return super(event_registration, self).copy(cr, uid, id, default=default, context=context)
375
376     def action_invoice_create(self, cr, uid, ids, grouped=False, date_inv = False, context=None):
377         """ Action of Create Invoice """
378         res = False
379         invoices = {}
380         tax_ids=[]
381         new_invoice_ids = []
382         inv_lines_pool = self.pool.get('account.invoice.line')
383         inv_pool = self.pool.get('account.invoice')
384         product_pool = self.pool.get('product.product')
385         contact_pool = self.pool.get('res.partner.address')
386         if context is None:
387             context = {}
388         # If date was specified, use it as date invoiced, usefull when invoices are generated this month and put the
389         # last day of the last month as invoice date
390         if date_inv:
391             context['date_inv'] = date_inv
392
393         for reg in self.browse(cr, uid, ids, context=context):
394             val_invoice = inv_pool.onchange_partner_id(cr, uid, [], 'out_invoice', reg.partner_invoice_id.id, False, False)
395             val_invoice['value'].update({'partner_id': reg.partner_invoice_id.id})
396             partner_address_id = val_invoice['value']['address_invoice_id']
397             if not partner_address_id:
398                raise osv.except_osv(_('Error !'),
399                         _("Registered partner doesn't have an address to make the invoice."))
400
401             value = inv_lines_pool.product_id_change(cr, uid, [], reg.event_id.product_id.id, uom =False, partner_id=reg.partner_invoice_id.id, fposition_id=reg.partner_invoice_id.property_account_position.id)
402             product = product_pool.browse(cr, uid, reg.event_id.product_id.id, context=context)
403             for tax in product.taxes_id:
404                 tax_ids.append(tax.id)
405             vals = value['value']
406             c_name = reg.contact_id and ('-' + contact_pool.name_get(cr, uid, [reg.contact_id.id])[0][1]) or ''
407             vals.update({
408                 'name': reg.event_product + '-' + c_name,
409                 'price_unit': reg.unit_price,
410                 'quantity': reg.nb_register,
411                 'product_id':reg.event_id.product_id.id,
412                 'invoice_line_tax_id': [(6, 0, tax_ids)],
413             })
414             inv_line_ids = self._create_invoice_lines(cr, uid, [reg.id], vals)
415             invoices.setdefault(reg.partner_id.id, []).append((reg, inv_line_ids))
416         for val in invoices.values():
417             res = False
418             if grouped:
419                 res = self._make_invoice(cr, uid, val[0][0], [v for k, v in val], context=context)
420
421                 for k, v in val:
422                     self.do_close(cr, uid, [k.id], context={'invoice_id': res})
423
424             else:
425                for k, v in val:
426                    res = self._make_invoice(cr, uid, k, [v], context=context)
427                    self.do_close(cr, uid, [k.id], context={'invoice_id': res})
428             if res: new_invoice_ids.append(res)
429         return new_invoice_ids
430
431     def do_open(self, cr, uid, ids, context=None):
432         """ Open Registration
433         """
434         res = self.write(cr, uid, ids, {'state': 'open'}, context=context)
435         self.mail_user(cr, uid, ids)
436         self.message_append(cr, uid, ids, _('Open'))
437         return res
438
439     def do_close(self, cr, uid, ids, context=None):
440         """ Close Registration
441         """
442         if context is None:
443             context = {}
444         invoice_id = context.get('invoice_id', False)
445         values = {'state': 'done', 'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')}
446         msg = _('Done')
447         if invoice_id:
448             values['invoice_id'] = invoice_id
449         res = self.write(cr, uid, ids, values)
450         self.message_append(cr, uid, ids, msg)
451         return res
452     
453     # event uses add_note wizard from crm, which expects case_* methods
454     def case_open(self, cr, uid, ids, context=None):
455         self.do_open(cr, uid, ids, context)
456     
457     # event uses add_note wizard from crm, which expects case_* methods
458     def case_close(self, cr, uid, ids, context=None):
459         self.do_close(cr, uid, ids, context)
460     
461     # event uses add_note wizard from crm, which expects case_* methods
462     def case_cancel(self, cr, uid, ids, context=None):
463         """ Cancel Registration
464         """
465         self.message_append(cr, uid, ids, _('Cancel'))
466         return self.write(cr, uid, ids, {'state': 'cancel'})
467     
468     # event uses add_note wizard from crm, which expects case_* methods
469     def case_reset(self, cr, uid, ids, context=None):
470         pass
471     
472     # event uses add_note wizard from crm, which expects case_* methods
473     def case_pending(self, cr, uid, ids, context=None):
474         pass
475     
476     def check_confirm(self, cr, uid, ids, context=None):
477         """This Function Open Event Registration and send email to user.
478         @param ids: List of Event registration's IDs
479         @param context: A standard dictionary for contextual values
480         @return: True
481         """
482         if type(ids) in (int, long,):
483             ids = [ids]
484         data_pool = self.pool.get('ir.model.data')
485         unconfirmed_ids = []
486         if context is None:
487             context = {}
488         for registration in self.browse(cr, uid, ids, context=context):
489             total_confirmed = registration.event_id.register_current + registration.nb_register
490             if total_confirmed <= registration.event_id.register_max or registration.event_id.register_max == 0:
491                 self.do_open(cr, uid, [registration.id], context=context)
492             else:
493                 unconfirmed_ids.append(registration.id)
494         if unconfirmed_ids:
495             view_id = data_pool.get_object_reference(cr, uid, 'event', 'view_event_confirm_registration')
496             view_id = view_id and view_id[1] or False
497             context['registration_ids'] = unconfirmed_ids
498             return {
499                 'name': _('Confirm Registration'),
500                 'context': context,
501                 'view_type': 'form',
502                 'view_mode': 'tree,form',
503                 'res_model': 'event.confirm.registration',
504                 'views': [(view_id, 'form')],
505                 'type': 'ir.actions.act_window',
506                 'target': 'new',
507                 'context': context,
508                 'nodestroy': True
509             }
510         return True
511
512     def button_reg_close(self, cr, uid, ids, context=None):
513         """This Function Close Event Registration.
514         """
515         data_pool = self.pool.get('ir.model.data')
516         unclosed_ids = []
517         for registration in self.browse(cr, uid, ids, context=context):
518             if registration.tobe_invoiced and not registration.invoice_id:
519                 unclosed_ids.append(registration.id)
520             else:
521                 self.do_close(cr, uid, [registration.id], context=context)
522         if unclosed_ids:
523             view_id = data_pool.get_object_reference(cr, uid, 'event', 'view_event_make_invoice')
524             view_id = view_id and view_id[1] or False
525             context['active_ids'] = unclosed_ids
526             return {
527                 'name': _('Close Registration'),
528                 'context': context,
529                 'view_type': 'form',
530                 'view_mode': 'tree,form',
531                 'res_model': 'event.make.invoice',
532                 'views': [(view_id, 'form')],
533                 'type': 'ir.actions.act_window',
534                 'target': 'new',
535                 'context': context,
536                 'nodestroy': True
537             }
538         return True
539
540     def button_reg_cancel(self, cr, uid, ids, context=None, *args):
541         return self.case_cancel(cr, uid, ids)
542
543     def mail_user(self, cr, uid, ids, confirm=False, context=None):
544         """
545         Send email to user
546         """
547         mail_message = self.pool.get('mail.message')
548         for registration in self.browse(cr, uid, ids, context=context):
549             src = registration.event_id.reply_to or False
550             email_to = []
551             email_cc = []
552             if registration.email_from:
553                 email_to = [registration.email_from]
554             if registration.email_cc:
555                 email_cc += [registration.email_cc]
556             if not (email_to or email_cc):
557                 continue
558             subject = ""
559             body = ""
560             if confirm:
561                 subject = _('Auto Confirmation: [%s] %s') %(registration.id, registration.name)
562                 body = registration.event_id.mail_confirm
563             elif registration.event_id.mail_auto_confirm or registration.event_id.mail_auto_registr:
564                 if registration.event_id.state in ['draft', 'fixed', 'open', 'confirm', 'running'] and registration.event_id.mail_auto_registr:
565                     subject = _('Auto Registration: [%s] %s') %(registration.id, registration.name)
566                     body = registration.event_id.mail_registr
567                 if (registration.event_id.state in ['confirm', 'running']) and registration.event_id.mail_auto_confirm:
568                     subject = _('Auto Confirmation: [%s] %s') %(registration.id, registration.name)
569                     body = registration.event_id.mail_confirm
570             if subject or body:
571                 mail_message.schedule_with_attach(cr, uid, src, email_to, subject, body, model='event.registration', email_cc=email_cc, res_id=registration.id)
572
573         return True
574
575     def mail_user_confirm(self, cr, uid, ids, context=None):
576         """
577         Send email to user
578         """
579         return self.mail_user(cr, uid, ids, confirm=True, context=context)
580
581     def _create_invoice_lines(self, cr, uid, ids, vals):
582         """ Create account Invoice line for Registration Id.
583         """
584         return self.pool.get('account.invoice.line').create(cr, uid, vals)
585
586     def onchange_contact_id(self, cr, uid, ids, contact, partner):
587
588         """This function returns value of Badge Name, Badge Title based on Partner contact.
589         @param self: The object pointer
590         @param cr: the current row, from the database cursor,
591         @param uid: the current user’s ID for security checks,
592         @param ids: List of Registration IDs
593         @param contact: Patner Contact IDS
594         @param partner: Partner IDS
595         """
596         data ={}
597         if not contact:
598             return data
599         addr_obj = self.pool.get('res.partner.address')
600         data['email_from'] = addr_obj.browse(cr, uid, contact).email
601         return {'value': data}
602
603     def onchange_event(self, cr, uid, ids, event_id, partner_invoice_id):
604         """This function returns value of Product Name, Unit Price based on Event.
605         @param self: The object pointer
606         @param cr: the current row, from the database cursor,
607         @param uid: the current user’s ID for security checks,
608         @param ids: List of Registration IDs
609         @param event_id: Event ID
610         @param partner_invoice_id: Partner Invoice ID
611         """
612         context = {}
613         if not event_id:
614             return {'value': {'unit_price': False, 'event_product': False}}
615
616         event_obj = self.pool.get('event.event')
617         prod_obj = self.pool.get('product.product')
618         res_obj = self.pool.get('res.partner')
619
620         data_event =  event_obj.browse(cr, uid, event_id)
621         res = {'value': {'unit_price': False,
622                          'event_product': False,
623                          'user_id': False,
624                          'date': data_event.date_begin,
625                          'date_deadline': data_event.date_end,
626                          'description': data_event.note,
627                          'name': data_event.name,
628                          'section_id': data_event.section_id and data_event.section_id.id or False,
629                         }}
630         if data_event.user_id.id:
631             res['value'].update({'user_id': data_event.user_id.id})
632         if data_event.product_id:
633             pricelist_id = data_event.pricelist_id and data_event.pricelist_id.id or False
634             if partner_invoice_id:
635                 partner = res_obj.browse(cr, uid, partner_invoice_id, context=context)
636                 pricelist_id = pricelist_id or partner.property_product_pricelist.id
637             unit_price = prod_obj._product_price(cr, uid, [data_event.product_id.id], False, False, {'pricelist': pricelist_id})[data_event.product_id.id]
638             if not unit_price:
639                 unit_price = data_event.unit_price
640             res['value'].update({'unit_price': unit_price, 'event_product': data_event.product_id.name})
641         return res
642
643     def onchange_partner_id(self, cr, uid, ids, part, event_id, email=False):
644         """This function returns value of Patner Invoice id, Unit Price, badget title based on partner and Event.
645         @param self: The object pointer
646         @param cr: the current row, from the database cursor,
647         @param uid: the current user’s ID for security checks,
648         @param ids: List of Registration IDs
649         @param event_id: Event ID
650         @param partner_invoice_id: Partner Invoice ID
651         """
652         res_obj = self.pool.get('res.partner')
653
654         data = {}
655         data['contact_id'], data['partner_invoice_id'], data['email_from'] = (False, False, False)
656         if not part:
657             return {'value': data}
658         data['partner_invoice_id'] = part
659         # this calls onchange_partner_invoice_id
660         d = self.onchange_partner_invoice_id(cr, uid, ids, event_id, part)
661         # this updates the dictionary
662         data.update(d['value'])
663         addr = res_obj.address_get(cr, uid, [part]).get('default', False)
664         if addr:
665             d = self.onchange_contact_id(cr, uid, ids, addr, part)
666             data.update(d['value'])
667         return {'value': data}
668
669     def onchange_partner_invoice_id(self, cr, uid, ids, event_id, partner_invoice_id):
670         """This function returns value of Product unit Price based on Invoiced partner.
671         @param self: The object pointer
672         @param cr: the current row, from the database cursor,
673         @param uid: the current user’s ID for security checks,
674         @param ids: List of Registration IDs
675         @param event_id: Event ID
676         @param partner_invoice_id: Partner Invoice ID
677         """
678         data = {}
679         context = {}
680         event_obj = self.pool.get('event.event')
681         prod_obj = self.pool.get('product.product')
682         res_obj = self.pool.get('res.partner')
683
684         data['unit_price']=False
685         if not event_id:
686             return {'value': data}
687         data_event =  event_obj.browse(cr, uid, event_id, context=context)
688         if data_event.product_id:
689             data['event_product'] = data_event.product_id.name
690             pricelist_id = data_event.pricelist_id and data_event.pricelist_id.id or False
691             if partner_invoice_id:
692                 partner = res_obj.browse(cr, uid, partner_invoice_id, context=context)
693                 pricelist_id = pricelist_id or partner.property_product_pricelist.id
694             unit_price = prod_obj._product_price(cr, uid, [data_event.product_id.id], False, False, {'pricelist': pricelist_id})[data_event.product_id.id]
695             if not unit_price:
696                 unit_price = data_event.unit_price
697             data['unit_price'] = unit_price
698         return {'value': data}
699
700 event_registration()
701
702 class event_registration_badge(osv.osv):
703     _name = 'event.registration.badge'
704     _description = __doc__
705     _columns = {
706         "registration_id": fields.many2one('event.registration', 'Registration', required=True),
707         "title": fields.char('Title', size=128),
708         "name": fields.char('Name', size=128, required=True),
709         "address_id": fields.many2one('res.partner.address', 'Address'),
710     }
711
712 event_registration_badge()
713
714 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: