1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # Copyright (c) 2007 TINY SPRL. (http://tiny.be) All Rights Reserved.
7 # WARNING: This program as such is intended to be used by professional
8 # programmers who take the whole responsability of assessing all potential
9 # consequences resulting from its eventual inadequacies and bugs
10 # End users who are looking for a ready-to-use solution with commercial
11 # garantees and support are strongly adviced to contract a Free Software
14 # This program is Free Software; you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License
16 # as published by the Free Software Foundation; either version 2
17 # of the License, or (at your option) any later version.
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 ##############################################################################
30 from osv import fields, osv
36 class crm_case_log(osv.osv):
37 _inherit = 'crm.case.log'
38 _description = 'crm.case.log'
39 def create(self, cr, uid, vals, *args, **kwargs):
40 if not 'name' in vals:
41 vals['name']='Historize'
42 return super(osv.osv,self).create(cr, uid, vals, *args, **kwargs)
44 'user_id': lambda self,cr,uid,context: uid,
48 class one2many_mod_task(fields.one2many):
49 def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
58 query = "select project_id from event_event where id = %i" %id
60 project_ids = [ x[0] for x in cr.fetchall()]
61 ids2 = obj.pool.get(self._obj).search(cr, user, [(self._fields_id,'in',project_ids),('state','<>','done')], limit=self._limit)
62 for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
63 res[id].append( r['id'] )
66 class event_type(osv.osv):
68 _description= 'Event type'
70 'name': fields.char('Event type', size=64, required=True),
76 _description = 'Event'
77 _inherits = {'crm.case.section': 'section_id'}
80 def copy(self, cr, uid, id, default=None, context=None):
81 return super(event, self).copy(cr, uid,id, default={'code': self.pool.get('ir.sequence').get(cr, uid, 'event.event'),'state':'draft'})
83 def button_draft(self, cr, uid, ids, context={}):
84 return self.write(cr, uid, ids, {'state':'draft'})
86 def button_cancel(self, cr, uid, ids, context={}):
87 return self.write(cr, uid, ids, {'state':'cancel'})
89 def button_done(self, cr, uid, ids, context={}):
90 return self.write(cr, uid, ids, {'state':'done'})
92 def button_confirm(self, cr, uid, ids, context={}):
93 for eve in self.browse(cr, uid, ids):
94 if eve.mail_auto_confirm:
95 #send reminder that will confirm the event for all the people that were already confirmed
96 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id','=',eve.id),('state','not in',['draft','cancel'])])
98 self.pool.get('event.registration').mail_user_confirm(cr, uid, reg_ids)
99 return self.write(cr, uid, ids, {'state':'confirm'})
101 def _get_register(self, cr, uid, ids, name, args, context=None):
103 for event in self.browse(cr, uid, ids, context):
104 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
108 res[event.id] = res2[0]
113 def _get_prospect(self, cr, uid, ids, name, args, context=None):
115 for event in self.browse(cr, uid, ids, context):
116 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
120 res[event.id] = res2[0]
125 def write(self, cr, uid, ids,vals, *args, **kwargs):
126 res = super(event,self).write(cr, uid, ids,vals, *args, **kwargs)
127 if 'date_begin' in vals and vals['date_begin']:
128 for eve in self.browse(cr, uid, ids):
129 #change the deadlines of the registration linked to this event
130 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id','=',eve.id)])
132 self.pool.get('event.registration').write(cr, uid, reg_ids, {'date_deadline':vals['date_begin']})
133 #change the date of the project
135 self.pool.get('project.project').write(cr, uid, [eve.project_id.id], {'date_end':eve.date_begin})
137 #change the description of the registration linked to this event
138 if 'mail_auto_confirm' in vals:
139 if vals['mail_auto_confirm']:
140 if 'mail_confirm' not in vals:
141 for eve in self.browse(cr, uid, ids):
142 vals['mail_confirm'] = eve.mail_confirm
144 vals['mail_confirm']=False
145 if 'mail_confirm' in vals:
146 for eve in self.browse(cr, uid, ids):
147 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id','=',eve.id)])
149 self.pool.get('event.registration').write(cr, uid, reg_ids, {'description':vals['mail_confirm']})
153 'type': fields.many2one('event.type', 'Type'),
154 'section_id': fields.many2one('crm.case.section', 'Case section', required=True),
155 'register_max': fields.integer('Maximum Registrations'),
156 'register_min': fields.integer('Minimum Registrations'),
157 'register_current': fields.function(_get_register, method=True, string='Confirmed Registrations'),
158 'register_prospect': fields.function(_get_prospect, method=True, string='Unconfirmed Registrations'),
159 'project_id': fields.many2one('project.project', 'Project', readonly=True),
160 'task_ids': one2many_mod_task('project.task', 'project_id', "Project tasks", readonly=True, domain="[('state','<>', 'done')]"),
161 'date_begin': fields.datetime('Beginning date', required=True),
162 'date_end': fields.datetime('Ending date', required=True),
163 'state': fields.selection([('draft','Draft'),('confirm','Confirmed'),('done','Done'),('cancel','Canceled')], 'Status', readonly=True, required=True),
164 'mail_auto_registr':fields.boolean('Mail Auto Register',help='Check this box if you want to use the automatic mailing for new registration'),
165 'mail_auto_confirm':fields.boolean('Mail Auto Confirm',help='Check this box if you want ot use the automatic confirmation emailing or the reminder'),
166 'mail_registr':fields.text('Registration Email',help='This email will be sent when someone subscribes to the event.'),
167 '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."),
168 'budget_id':fields.many2one('account.budget.post','Budget'),
169 'product_id':fields.many2one('product.product','Product', required=True),
172 'state': lambda *args: 'draft',
173 'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'event.event'),
174 'user_id': lambda self,cr,uid,ctx: uid,
178 class event_registration(osv.osv):
180 def _history(self, cr, uid,ids,keyword, history=False, email=False, context={}):
185 'canal_id': case.canal_id.id,
187 'case_id': case.case_id.id
189 obj = self.pool.get('crm.case.log')
190 obj.create(cr, uid, data, context)
193 def button_reg_close(self, cr, uid, ids, *args):
194 self.write(cr, uid, ids, {'state':'done',})
195 cases = self.browse(cr, uid, ids)
196 self._history(cr, uid, cases, 'Done', history=True)
199 def button_reg_cancel(self, cr, uid, ids, *args):
200 self.write(cr, uid, ids, {'state':'cancel',})
201 cases = self.browse(cr, uid, ids)
202 self._history(cr, uid, cases, 'Cancel', history=True)
205 def create(self, cr, uid, *args, **argv):
206 event = self.pool.get('event.event').browse(cr, uid, args[0]['event_id'], None)
207 args[0]['section_id']= event.section_id.id
208 args[0]['date_deadline']= event.date_begin
209 args[0]['description']= event.mail_confirm
210 res = super(event_registration, self).create(cr, uid, *args, **argv)
211 self._history(cr, uid,self.browse(cr, uid, [res]), 'Created', history=True)
214 def write(self, cr, uid, *args, **argv):
215 if 'event_id' in args[1]:
216 event = self.pool.get('event.event').browse(cr, uid, args[1]['event_id'], None)
217 args[1]['section_id']= event.section_id.id
218 args[1]['date_deadline']= event.date_begin
219 args[1]['description']= event.mail_confirm
220 return super(event_registration, self).write(cr, uid, *args, **argv)
222 def mail_user_confirm(self,cr,uid,ids):
223 reg_ids=self.browse(cr,uid,ids)
224 for reg_id in reg_ids:
225 src = reg_id.event_id.reply_to or False
226 dest = [reg_id.email_from]
228 dest += [reg_id.email_cc]
230 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))
232 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'))
235 def mail_user(self,cr,uid,ids):
236 reg_ids=self.browse(cr,uid,ids)
237 for reg_id in reg_ids:
238 src = reg_id.event_id.reply_to or False
239 dest = [reg_id.email_from]
241 dest += [reg_id.email_cc]
242 if reg_id.event_id.mail_auto_confirm or reg_id.event_id.mail_auto_registr:
244 if reg_id.event_id.state in ['draft', 'fixed', 'open','confirm','running'] and reg_id.event_id.mail_auto_registr:
245 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))
246 if (reg_id.event_id.state in ['confirm','running']) and reg_id.event_id.mail_auto_confirm:
247 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))
249 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'))
252 _name= 'event.registration'
253 _description = 'Event Registration'
254 _inherits = {'crm.case': 'case_id'}
256 'case_id':fields.many2one('crm.case','Case'),
257 'nb_register': fields.integer('Number of Registration', readonly=True, states={'draft':[('readonly',False)]}),
258 'event_id':fields.many2one('event.event', 'Event Related', required=True),
259 "partner_invoice_id":fields.many2one('res.partner', 'Partner Invoiced'),
260 "contact_id":fields.many2one('res.partner.contact', 'Partner Contact'), #TODO: filter only the contacts that have a function into the selected partner_id
261 "unit_price": fields.float('Unit Price'),
262 "badge_title":fields.char('Badge Title',size=128),
263 "badge_name":fields.char('Badge Name',size=128),
264 "badge_partner":fields.char('Badge Partner',size=128),
265 "invoice_label":fields.char("Label Invoice",size=128,required=True),
266 "tobe_invoiced":fields.boolean("To be Invoiced"),
267 "invoice_id":fields.many2one("account.invoice","Invoice"),
270 'nb_register': lambda *a: 1,
271 'tobe_invoiced' : lambda *a: True,
272 'name': lambda *a: 'Registration'
275 def onchange_badge_name(self, cr, uid, ids, badge_name):
279 data['name'] = 'Registration: ' + badge_name
280 return {'value':data}
282 def onchange_contact_id(self, cr, uid, ids, contact, partner):
286 contact_id = self.pool.get('res.partner.contact').browse(cr, uid, contact)
287 data['badge_name'] = contact_id.name
288 data['badge_title'] = contact_id.title
290 partner_addresses = self.pool.get('res.partner.address').search(cr, uid, [('partner_id','=',partner)])
291 job_id = self.pool.get('res.partner.job').search(cr, uid, [('contact_id','=',contact),('address_id','in',partner_addresses)])[0]
292 data['email_from'] = self.pool.get('res.partner.job').browse(cr, uid, job_id).email
293 d = self.onchange_badge_name(cr, uid, ids,data['badge_name'])
294 data.update(d['value'])
296 return {'value':data}
298 def onchange_event(self, cr, uid, ids, event_id, partner_invoice_id):
301 return {'value':{'unit_price' : False ,'invoice_label' : False }}
302 data_event = self.pool.get('event.event').browse(cr,uid,event_id)
303 if data_event.product_id:
304 if not partner_invoice_id:
305 unit_price=self.pool.get('product.product').price_get(cr, uid, [data_event.product_id.id],context=context)[data_event.product_id.id]
306 return {'value':{'unit_price' : unit_price , 'invoice_label' : data_event.product_id.name}}
307 data_partner = self.pool.get('res.partner').browse(cr,uid,partner_invoice_id)
308 context.update({'partner_id':data_partner})
309 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]
310 return {'value':{'unit_price' :unit_price , 'invoice_label' : data_event.product_id.name}}
311 return {'value':{'unit_price' : False,'invoice_label' : False}}
314 def onchange_partner_id(self, cr, uid, ids, part, event_id, email=False):
316 data['badge_partner'] = data['contact_id'] = data['partner_invoice_id'] = data['email_from'] = data['badge_title'] = data['badge_name'] = False
318 return {'value':data}
319 data['partner_invoice_id']=part
320 # this calls onchange_partner_invoice_id
321 d = self.onchange_partner_invoice_id(cr, uid, ids, event_id,part)
322 # this updates the dictionary
323 data.update(d['value'])
324 addr = self.pool.get('res.partner').address_get(cr, uid, [part])
326 if addr.has_key('default'):
327 job_ids = self.pool.get('res.partner.job').search(cr, uid, [('address_id','=',addr['default'])])
329 data['contact_id'] = self.pool.get('res.partner.job').browse(cr, uid, job_ids[0]).contact_id.id
330 d = self.onchange_contact_id(cr, uid, ids, data['contact_id'],part)
331 data.update(d['value'])
332 partner_data = self.pool.get('res.partner').browse(cr, uid, part)
333 data['badge_partner'] = partner_data.name
334 return {'value':data}
336 def onchange_partner_invoice_id(self, cr, uid, ids, event_id, partner_invoice_id):
339 data['unit_price']=False
341 return {'value':data}
342 data_event = self.pool.get('event.event').browse(cr,uid,event_id)
344 if data_event.product_id:
345 if not partner_invoice_id:
346 data['unit_price']=self.pool.get('product.product').price_get(cr, uid, [data_event.product_id.id],context=context)[data_event.product_id.id]
347 return {'value':data}
348 data_partner = self.pool.get('res.partner').browse(cr,uid,partner_invoice_id)
349 context.update({'partner_id':data_partner})
350 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]
351 return {'value':data}
352 return {'value':data}
354 def onchange_categ_id(self, cr, uid, ids, categ, context={}):
357 cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
358 return {'value':{'probability':cat}}
360 def _map_ids(self,method,cr, uid, ids, *args, **argv):
361 case_data = self.browse(cr,uid,ids)
363 for case in case_data:
364 new_ids.append(case.case_id.id)
365 return getattr(self.pool.get('crm.case'),method)(cr, uid, new_ids, *args, **argv)
368 def case_close(self,cr, uid, ids, *args, **argv):
369 return self._map_ids('case_close',cr,uid,ids,*args,**argv)
370 def case_escalate(self,cr, uid, ids, *args, **argv):
371 return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
372 def case_open(self,cr, uid, ids, *args, **argv):
373 return self._map_ids('case_open',cr,uid,ids,*args,**argv)
374 def case_cancel(self,cr, uid, ids, *args, **argv):
375 return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
376 def case_pending(self,cr, uid, ids, *args, **argv):
377 return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
378 def case_reset(self,cr, uid, ids, *args, **argv):
379 return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
380 def case_log(self,cr, uid, ids, *args, **argv):
381 return self._map_ids('case_log',cr,uid,ids,*args,**argv)
382 def case_log_reply(self,cr, uid, ids, *args, **argv):
383 return self._map_ids('case_log_reply',cr,uid,ids,*args,**argv)
384 def add_reply(self,cr, uid, ids, *args, **argv):
385 return self._map_ids('add_reply',cr,uid,ids,*args,**argv)
386 def remind_partner(self,cr, uid, ids, *args, **argv):
387 return self._map_ids('remind_partner',cr,uid,ids,*args,**argv)
388 def remind_user(self,cr, uid, ids, *args, **argv):
389 return self._map_ids('remind_user',cr,uid,ids,*args,**argv)
396 class report_event_registration(osv.osv):
397 _name = "report.event.registration"
398 _description = "Events on registrations"
401 'name': fields.char('Event',size=20),
402 'date_begin': fields.datetime('Beginning date', required=True),
403 'date_end': fields.datetime('Ending date', required=True),
404 'draft_state': fields.integer('Draft Registration',size=20),
405 'confirm_state': fields.integer('Confirm Registration',size=20),
406 'register_max': fields.integer('Maximum Registrations'),
410 create or replace view report_event_registration as (
414 e.date_begin as date_begin,
415 e.date_end as date_end,
416 (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,
417 (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,
418 e.register_max as register_max
420 event_event e,crm_case_section c
425 report_event_registration()
427 class report_event_type_registration(osv.osv):
428 _name = "report.event.type.registration"
429 _description = "Event type on registration"
432 'name': fields.char('Event Type',size=20),
433 'nbevent':fields.integer('Number Of Events'),
434 'draft_state': fields.integer('Draft Registrations',size=20),
435 'confirm_state': fields.integer('Confirm Registrations',size=20),
439 create or replace view report_event_type_registration as (
443 (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 ,
444 (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,
445 count(t.id) as nbevent
449 crm_case_section c1 on (e.section_id=c1.id)
451 event_type t on (e.type=t.id)
456 report_event_type_registration()
459 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: