1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
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.
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.
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/>.
20 ##############################################################################
22 from osv import fields, osv
27 from tools.translate import _
29 class crm_case_log(osv.osv):
30 _inherit = 'crm.case.log'
31 _description = 'crm.case.log'
32 def create(self, cr, uid, vals, *args, **kwargs):
33 if not 'name' in vals:
34 vals['name']='Historize'
35 return super(osv.osv,self).create(cr, uid, vals, *args, **kwargs)
37 'user_id': lambda self,cr,uid,context: uid,
41 class event_type(osv.osv):
43 _description= 'Event type'
45 'name': fields.char('Event type', size=64, required=True),
51 _description = 'Event'
52 _inherits = {'crm.case.section': 'section_id'}
55 def copy(self, cr, uid, id, default=None, context=None):
56 return super(event, self).copy(cr, uid,id, default={'code': self.pool.get('ir.sequence').get(cr, uid, 'event.event'),'state':'draft'})
58 def button_draft(self, cr, uid, ids, context={}):
59 return self.write(cr, uid, ids, {'state':'draft'})
61 def button_cancel(self, cr, uid, ids, context={}):
62 return self.write(cr, uid, ids, {'state':'cancel'})
64 def button_done(self, cr, uid, ids, context={}):
65 return self.write(cr, uid, ids, {'state':'done'})
67 def button_confirm(self, cr, uid, ids, context={}):
68 for eve in self.browse(cr, uid, ids):
69 if eve.mail_auto_confirm:
70 #send reminder that will confirm the event for all the people that were already confirmed
71 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id','=',eve.id),('state','not in',['draft','cancel'])])
73 self.pool.get('event.registration').mail_user_confirm(cr, uid, reg_ids)
74 return self.write(cr, uid, ids, {'state':'confirm'})
76 def _get_register(self, cr, uid, ids, name, args, context=None):
78 for event in self.browse(cr, uid, ids, context):
79 query = """select sum(nb_register) from crm_case c left join crm_case_section s on (c.section_id=s.id) right join event_event e on (e.section_id=s.id) right join event_registration r on (r.case_id=c.id) where e.section_id = %s and c.state in ('open','done')""" % event.section_id.id
83 res[event.id] = res2[0]
88 def _get_prospect(self, cr, uid, ids, name, args, context=None):
90 for event in self.browse(cr, uid, ids, context):
91 query = """select sum(nb_register) from crm_case c left join crm_case_section s on (c.section_id=s.id) right join event_event e on (e.section_id=s.id) right join event_registration r on (r.case_id=c.id) where e.section_id = %s and c.state = 'draft'""" % event.section_id.id
95 res[event.id] = res2[0]
100 def write(self, cr, uid, ids,vals, *args, **kwargs):
101 res = super(event,self).write(cr, uid, ids,vals, *args, **kwargs)
102 if 'date_begin' in vals and vals['date_begin']:
103 for eve in self.browse(cr, uid, ids):
104 #change the deadlines of the registration linked to this event
105 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id','=',eve.id)])
107 self.pool.get('event.registration').write(cr, uid, reg_ids, {'date_deadline':vals['date_begin']})
109 #change the description of the registration linked to this event
110 if 'mail_auto_confirm' in vals:
111 if vals['mail_auto_confirm']:
112 if 'mail_confirm' not in vals:
113 for eve in self.browse(cr, uid, ids):
114 vals['mail_confirm'] = eve.mail_confirm
116 vals['mail_confirm']=False
117 if 'mail_confirm' in vals:
118 for eve in self.browse(cr, uid, ids):
119 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id','=',eve.id)])
121 self.pool.get('event.registration').write(cr, uid, reg_ids, {'description':vals['mail_confirm']})
125 'type': fields.many2one('event.type', 'Type'),
126 'section_id': fields.many2one('crm.case.section', 'Case section', required=True),
127 'register_max': fields.integer('Maximum Registrations'),
128 'register_min': fields.integer('Minimum Registrations'),
129 'register_current': fields.function(_get_register, method=True, string='Confirmed Registrations'),
130 'register_prospect': fields.function(_get_prospect, method=True, string='Unconfirmed Registrations'),
131 'date_begin': fields.datetime('Beginning date', required=True),
132 'date_end': fields.datetime('Ending date', required=True),
133 'state': fields.selection([('draft','Draft'),('confirm','Confirmed'),('done','Done'),('cancel','Cancelled')], 'State', readonly=True, required=True,
134 help='If event is created, the state is \'Draft\'.\n If event is confirmed for the particular dates the state is set to \'Confirmed\'.\
135 \nIf the event is over, the state is set to \'Done\'.\n If event is cancelled the state is set to \'Cancelled\'.'),
136 'mail_auto_registr':fields.boolean('Mail Auto Register',help='Check this box if you want to use the automatic mailing for new registration'),
137 'mail_auto_confirm':fields.boolean('Mail Auto Confirm',help='Check this box if you want ot use the automatic confirmation emailing or the reminder'),
138 'mail_registr':fields.text('Registration Email',help='This email will be sent when someone subscribes to the event.'),
139 'mail_confirm': fields.text('Confirmation Email', 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."),
140 'product_id':fields.many2one('product.product','Product', required=True),
144 'state': lambda *args: 'draft',
145 'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'event.event'),
146 'user_id': lambda self,cr,uid,ctx: uid,
151 class event_registration(osv.osv):
153 def _history(self, cr, uid,ids,keyword, history=False, email=False, context={}):
154 for case in self.browse(cr, uid, ids):
160 'canal_id': case.canal_id.id,
162 'case_id': case.case_id.id
164 obj = self.pool.get('crm.case.log')
165 obj.create(cr, uid, data, context)
168 def button_reg_close(self, cr, uid, ids, *args):
169 self.write(cr, uid, ids, {'state':'done',})
170 self._history(cr, uid, ids, 'Done', history=True)
173 def button_reg_cancel(self, cr, uid, ids, *args):
174 self.write(cr, uid, ids, {'state':'cancel',})
175 self._history(cr, uid, ids, 'Cancel', history=True)
178 def create(self, cr, uid, *args, **argv):
179 event = self.pool.get('event.event').browse(cr, uid, args[0]['event_id'], None)
180 args[0]['section_id']= event.section_id.id
181 args[0]['date_deadline']= event.date_begin
182 args[0]['description']= event.mail_confirm
183 res = super(event_registration, self).create(cr, uid, *args, **argv)
184 self._history(cr, uid,[res], 'Created', history=True)
187 def write(self, cr, uid, *args, **argv):
188 if 'event_id' in args[1]:
189 event = self.pool.get('event.event').browse(cr, uid, args[1]['event_id'], None)
190 args[1]['section_id']= event.section_id.id
191 args[1]['date_deadline']= event.date_begin
192 args[1]['description']= event.mail_confirm
193 return super(event_registration, self).write(cr, uid, *args, **argv)
195 def mail_user_confirm(self,cr,uid,ids):
196 reg_ids=self.browse(cr,uid,ids)
197 for reg_id in reg_ids:
198 src = reg_id.event_id.reply_to or False
199 dest = [reg_id.email_from]
201 dest += [reg_id.email_cc]
203 tools.email_send(src, dest,'Auto Confirmation: '+'['+str(reg_id.id)+']'+' '+reg_id.name, reg_id.event_id.mail_confirm, tinycrm = str(reg_id.case_id.id))
205 raise osv.except_osv(_('Error!'), _('You must define a reply-to address in order to mail the participant. You can do this in the Mailing tab of your event. Note that this is also the place where you can configure your event to not send emails automaticly while registering'))
208 def mail_user(self,cr,uid,ids):
209 reg_ids=self.browse(cr,uid,ids)
210 for reg_id in reg_ids:
211 src = reg_id.event_id.reply_to or False
212 dest = [reg_id.email_from]
214 dest += [reg_id.email_cc]
215 if reg_id.event_id.mail_auto_confirm or reg_id.event_id.mail_auto_registr:
217 if reg_id.event_id.state in ['draft', 'fixed', 'open','confirm','running'] and reg_id.event_id.mail_auto_registr:
218 tools.email_send(src, dest,'Auto Registration: '+'['+str(reg_id.id)+']'+' '+reg_id.name, reg_id.event_id.mail_registr, tinycrm = str(reg_id.case_id.id))
219 if (reg_id.event_id.state in ['confirm','running']) and reg_id.event_id.mail_auto_confirm:
220 tools.email_send(src, dest,'Auto Confirmation: '+'['+str(reg_id.id)+']'+' '+reg_id.name, reg_id.event_id.mail_confirm, tinycrm = str(reg_id.case_id.id))
222 raise osv.except_osv(_('Error!'), _('You must define a reply-to address in order to mail the participant. You can do this in the Mailing tab of your event. Note that this is also the place where you can configure your event to not send emails automaticly while registering'))
225 def _create_invoice_lines(self, cr, uid, ids, vals):
226 return self.pool.get('account.invoice.line').create(cr, uid,vals )
228 _name= 'event.registration'
229 _description = 'Event Registration'
230 _inherits = {'crm.case': 'case_id'}
232 'case_id':fields.many2one('crm.case','Case'),
233 'nb_register': fields.integer('Number of Registration', readonly=True, states={'draft':[('readonly',False)]}),
234 'event_id':fields.many2one('event.event', 'Event Related', required=True),
235 "partner_invoice_id":fields.many2one('res.partner', 'Partner Invoiced'),
236 "contact_id":fields.many2one('res.partner.contact', 'Partner Contact'), #TODO: filter only the contacts that have a function into the selected partner_id
237 "unit_price": fields.float('Unit Price'),
238 "badge_title":fields.char('Badge Title',size=128),
239 "badge_name":fields.char('Badge Name',size=128),
240 "badge_partner":fields.char('Badge Partner',size=128),
241 "invoice_label":fields.char("Label Invoice",size=128,required=True),
242 "tobe_invoiced":fields.boolean("To be Invoiced"),
243 "invoice_id":fields.many2one("account.invoice","Invoice"),
246 'nb_register': lambda *a: 1,
247 'tobe_invoiced' : lambda *a: True,
248 'name': lambda *a: 'Registration',
249 'state': lambda *b: 'draft'
252 def onchange_badge_name(self, cr, uid, ids, badge_name):
256 data['name'] = 'Registration: ' + badge_name
257 return {'value':data}
259 def onchange_contact_id(self, cr, uid, ids, contact, partner):
263 contact_id = self.pool.get('res.partner.contact').browse(cr, uid, contact)
264 data['badge_name'] = contact_id.name
265 data['badge_title'] = contact_id.title
267 partner_addresses = self.pool.get('res.partner.address').search(cr, uid, [('partner_id','=',partner)])
268 job_ids = self.pool.get('res.partner.job').search(cr, uid, [('contact_id','=',contact),('address_id','in',partner_addresses)])
270 data['email_from'] = self.pool.get('res.partner.job').browse(cr, uid, job_ids[0]).email
271 d = self.onchange_badge_name(cr, uid, ids,data['badge_name'])
272 data.update(d['value'])
274 return {'value':data}
276 def onchange_event(self, cr, uid, ids, event_id, partner_invoice_id):
279 return {'value':{'unit_price' : False ,'invoice_label' : False }}
280 data_event = self.pool.get('event.event').browse(cr,uid,event_id)
281 if data_event.product_id:
282 if not partner_invoice_id:
283 unit_price=self.pool.get('product.product').price_get(cr, uid, [data_event.product_id.id],context=context)[data_event.product_id.id]
284 return {'value':{'unit_price' : unit_price , 'invoice_label' : data_event.product_id.name}}
285 data_partner = self.pool.get('res.partner').browse(cr,uid,partner_invoice_id)
286 context.update({'partner_id':data_partner})
287 unit_price = self.pool.get('product.product')._product_price(cr, uid, [data_event.product_id.id], False, False, {'pricelist':data_partner.property_product_pricelist.id})[data_event.product_id.id]
288 return {'value':{'unit_price' :unit_price , 'invoice_label' : data_event.product_id.name}}
289 return {'value':{'unit_price' : False,'invoice_label' : False}}
292 def onchange_partner_id(self, cr, uid, ids, part, event_id, email=False):
294 data['badge_partner'] = data['contact_id'] = data['partner_invoice_id'] = data['email_from'] = data['badge_title'] = data['badge_name'] = False
296 return {'value':data}
297 data['partner_invoice_id']=part
298 # this calls onchange_partner_invoice_id
299 d = self.onchange_partner_invoice_id(cr, uid, ids, event_id,part)
300 # this updates the dictionary
301 data.update(d['value'])
302 addr = self.pool.get('res.partner').address_get(cr, uid, [part])
304 if addr.has_key('default'):
305 job_ids = self.pool.get('res.partner.job').search(cr, uid, [('address_id','=',addr['default'])])
307 data['contact_id'] = self.pool.get('res.partner.job').browse(cr, uid, job_ids[0]).contact_id.id
308 d = self.onchange_contact_id(cr, uid, ids, data['contact_id'],part)
309 data.update(d['value'])
310 partner_data = self.pool.get('res.partner').browse(cr, uid, part)
311 data['badge_partner'] = partner_data.name
312 return {'value':data}
314 def onchange_partner_invoice_id(self, cr, uid, ids, event_id, partner_invoice_id):
317 data['unit_price']=False
319 return {'value':data}
320 data_event = self.pool.get('event.event').browse(cr,uid,event_id)
322 if data_event.product_id:
323 if not partner_invoice_id:
324 data['unit_price']=self.pool.get('product.product').price_get(cr, uid, [data_event.product_id.id],context=context)[data_event.product_id.id]
325 return {'value':data}
326 data_partner = self.pool.get('res.partner').browse(cr,uid,partner_invoice_id)
327 context.update({'partner_id':data_partner})
328 data['unit_price'] = self.pool.get('product.product')._product_price(cr, uid, [data_event.product_id.id], False, False, {'pricelist':data_partner.property_product_pricelist.id})[data_event.product_id.id]
329 return {'value':data}
330 return {'value':data}
332 def onchange_categ_id(self, cr, uid, ids, categ, context={}):
335 cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
336 return {'value':{'probability':cat}}
338 def _map_ids(self,method,cr, uid, ids, *args, **argv):
339 case_data = self.browse(cr,uid,ids)
341 for case in case_data:
343 new_ids.append(case.case_id.id)
344 return getattr(self.pool.get('crm.case'),method)(cr, uid, new_ids, *args, **argv)
347 def case_close(self,cr, uid, ids, *args, **argv):
348 return self._map_ids('case_close',cr,uid,ids,*args,**argv)
349 def case_escalate(self,cr, uid, ids, *args, **argv):
350 return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
351 def case_open(self,cr, uid, ids, *args, **argv):
352 return self._map_ids('case_open',cr,uid,ids,*args,**argv)
353 def case_cancel(self,cr, uid, ids, *args, **argv):
354 return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
355 def case_pending(self,cr, uid, ids, *args, **argv):
356 return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
357 def case_reset(self,cr, uid, ids, *args, **argv):
358 return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
359 def case_log(self,cr, uid, ids, *args, **argv):
360 return self._map_ids('case_log',cr,uid,ids,*args,**argv)
361 def case_log_reply(self,cr, uid, ids, *args, **argv):
362 return self._map_ids('case_log_reply',cr,uid,ids,*args,**argv)
363 def add_reply(self,cr, uid, ids, *args, **argv):
364 return self._map_ids('add_reply',cr,uid,ids,*args,**argv)
365 def remind_partner(self,cr, uid, ids, *args, **argv):
366 return self._map_ids('remind_partner',cr,uid,ids,*args,**argv)
367 def remind_user(self,cr, uid, ids, *args, **argv):
368 return self._map_ids('remind_user',cr,uid,ids,*args,**argv)
375 class report_event_registration(osv.osv):
376 _name = "report.event.registration"
377 _description = "Events on registrations"
380 'name': fields.char('Event',size=20),
381 'date_begin': fields.datetime('Beginning date', required=True),
382 'date_end': fields.datetime('Ending date', required=True),
383 'draft_state': fields.integer('Draft Registration',size=20),
384 'confirm_state': fields.integer('Confirm Registration',size=20),
385 'register_max': fields.integer('Maximum Registrations'),
389 create or replace view report_event_registration as (
393 e.date_begin as date_begin,
394 e.date_end as date_end,
395 (SELECT sum(nb_register) FROM event_registration x , crm_case c WHERE x.case_id=c.id and c.section_id=e.section_id and state in ('draft')) as draft_state,
396 (SELECT sum(nb_register) FROM event_registration x , crm_case c WHERE x.case_id=c.id and c.section_id=e.section_id and state in ('open')) as confirm_state,
397 e.register_max as register_max
399 event_event e,crm_case_section c
404 report_event_registration()
406 class report_event_type_registration(osv.osv):
407 _name = "report.event.type.registration"
408 _description = "Event type on registration"
411 'name': fields.char('Event Type',size=20),
412 'nbevent':fields.integer('Number Of Events'),
413 'draft_state': fields.integer('Draft Registrations',size=20),
414 'confirm_state': fields.integer('Confirm Registrations',size=20),
418 create or replace view report_event_type_registration as (
422 (select sum(nb_register) from event_registration r , crm_case c , event_event e where c.section_id=e.section_id and r.case_id=c.id and c.state='draft' and e.type=t.id ) as draft_state ,
423 (select sum(nb_register) from event_registration r , crm_case c , event_event e where c.section_id=e.section_id and r.case_id=c.id and c.state='open' and e.type=t.id ) as confirm_state,
424 count(t.id) as nbevent
428 crm_case_section c1 on (e.section_id=c1.id)
430 event_type t on (e.type=t.id)
435 report_event_type_registration()
438 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: