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