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