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 _
30 class crm_case_log(osv.osv):
31 _inherit = 'crm.case.log'
32 _description = 'crm.case.log'
33 def create(self, cr, uid, vals, *args, **kwargs):
34 if not 'name' in vals:
35 vals['name']='Historize'
36 return super(osv.osv,self).create(cr, uid, vals, *args, **kwargs)
38 'user_id': lambda self,cr,uid,context: uid,
42 class event_type(osv.osv):
44 _description= 'Event type'
46 'name': fields.char('Event type', size=64, required=True),
52 _description = 'Event'
53 _inherits = {'crm.case.section': 'section_id'}
56 def copy(self, cr, uid, id, default=None, context=None):
57 return super(event, self).copy(cr, uid,id, default={'code': self.pool.get('ir.sequence').get(cr, uid, 'event.event'),'state':'draft'})
59 def button_draft(self, cr, uid, ids, context={}):
60 return self.write(cr, uid, ids, {'state':'draft'})
62 def button_cancel(self, cr, uid, ids, context={}):
63 return self.write(cr, uid, ids, {'state':'cancel'})
65 def button_done(self, cr, uid, ids, context={}):
66 return self.write(cr, uid, ids, {'state':'done'})
68 def button_confirm(self, cr, uid, ids, context={}):
69 for eve in self.browse(cr, uid, ids):
70 if eve.mail_auto_confirm:
71 #send reminder that will confirm the event for all the people that were already confirmed
72 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id','=',eve.id),('state','not in',['draft','cancel'])])
74 self.pool.get('event.registration').mail_user_confirm(cr, uid, reg_ids)
75 return self.write(cr, uid, ids, {'state':'confirm'})
77 def _get_register(self, cr, uid, ids, name, args, context=None):
79 for event in self.browse(cr, uid, ids, context):
80 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')"""
81 cr.execute(query,(event.section_id.id,))
84 res[event.id] = res2[0]
89 def _get_prospect(self, cr, uid, ids, name, args, context=None):
91 for event in self.browse(cr, uid, ids, context):
92 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'"""
93 cr.execute(query,(event.section_id.id,))
96 res[event.id] = res2[0]
101 def write(self, cr, uid, ids,vals, *args, **kwargs):
102 res = super(event,self).write(cr, uid, ids,vals, *args, **kwargs)
103 if 'date_begin' in vals and vals['date_begin']:
104 for eve in self.browse(cr, uid, ids):
105 #change the deadlines of the registration linked to this event
106 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id','=',eve.id)])
108 self.pool.get('event.registration').write(cr, uid, reg_ids, {'date_deadline':vals['date_begin']})
110 #change the description of the registration linked to this event
111 if 'mail_auto_confirm' in vals:
112 if vals['mail_auto_confirm']:
113 if 'mail_confirm' not in vals:
114 for eve in self.browse(cr, uid, ids):
115 vals['mail_confirm'] = eve.mail_confirm
117 vals['mail_confirm']=False
118 if 'mail_confirm' in vals:
119 for eve in self.browse(cr, uid, ids):
120 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id','=',eve.id)])
122 self.pool.get('event.registration').write(cr, uid, reg_ids, {'description':vals['mail_confirm']})
126 'type': fields.many2one('event.type', 'Type'),
127 'section_id': fields.many2one('crm.case.section', 'Case section', required=True),
128 'register_max': fields.integer('Maximum Registrations'),
129 'register_min': fields.integer('Minimum Registrations'),
130 'register_current': fields.function(_get_register, method=True, string='Confirmed Registrations'),
131 'register_prospect': fields.function(_get_prospect, method=True, string='Unconfirmed Registrations'),
132 'date_begin': fields.datetime('Beginning date', required=True),
133 'date_end': fields.datetime('Ending date', required=True),
134 'state': fields.selection([('draft','Draft'),('confirm','Confirmed'),('done','Done'),('cancel','Cancelled')], 'State', readonly=True, required=True,
135 help='If event is created, the state is \'Draft\'.\n If event is confirmed for the particular dates the state is set to \'Confirmed\'.\
136 \nIf the event is over, the state is set to \'Done\'.\n If event is cancelled the state is set to \'Cancelled\'.'),
137 'mail_auto_registr':fields.boolean('Mail Auto Register',help='Check this box if you want to use the automatic mailing for new registration'),
138 'mail_auto_confirm':fields.boolean('Mail Auto Confirm',help='Check this box if you want ot use the automatic confirmation emailing or the reminder'),
139 'mail_registr':fields.text('Registration Email',help='This email will be sent when someone subscribes to the event.'),
140 '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."),
141 'product_id':fields.many2one('product.product','Product', required=True),
145 'state': lambda *args: 'draft',
146 'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'event.event'),
147 'user_id': lambda self,cr,uid,ctx: uid,
152 class event_registration(osv.osv):
154 def _history(self, cr, uid,ids,keyword, history=False, email=False, context={}):
155 for case in self.browse(cr, uid, ids):
161 'canal_id': case.canal_id.id,
163 'case_id': case.case_id.id
165 obj = self.pool.get('crm.case.log')
166 obj.create(cr, uid, data, context)
169 def button_reg_close(self, cr, uid, ids, *args):
170 self.write(cr, uid, ids, {'state':'done',})
171 self._history(cr, uid, ids, 'Done', history=True)
174 def button_reg_cancel(self, cr, uid, ids, *args):
175 self.write(cr, uid, ids, {'state':'cancel',})
176 self._history(cr, uid, ids, 'Cancel', history=True)
179 def create(self, cr, uid, *args, **argv):
180 event = self.pool.get('event.event').browse(cr, uid, args[0]['event_id'], None)
181 args[0]['section_id']= event.section_id.id
182 args[0]['date_deadline']= event.date_begin
183 args[0]['description']= event.mail_confirm
184 res = super(event_registration, self).create(cr, uid, *args, **argv)
185 self._history(cr, uid,[res], 'Created', history=True)
188 def write(self, cr, uid, *args, **argv):
189 if 'event_id' in args[1]:
190 event = self.pool.get('event.event').browse(cr, uid, args[1]['event_id'], None)
191 args[1]['section_id']= event.section_id.id
192 args[1]['date_deadline']= event.date_begin
193 args[1]['description']= event.mail_confirm
194 return super(event_registration, self).write(cr, uid, *args, **argv)
196 def mail_user_confirm(self,cr,uid,ids):
197 reg_ids=self.browse(cr,uid,ids)
198 for reg_id in reg_ids:
199 src = reg_id.event_id.reply_to or False
200 dest = [reg_id.email_from]
202 dest += [reg_id.email_cc]
204 tools.email_send(src, dest,'Auto Confirmation: '+'['+str(reg_id.id)+']'+' '+reg_id.name, reg_id.event_id.mail_confirm, openobject_id = str(reg_id.case_id.id))
206 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'))
209 def mail_user(self,cr,uid,ids):
210 reg_ids=self.browse(cr,uid,ids)
211 for reg_id in reg_ids:
212 src = reg_id.event_id.reply_to or False
213 dest = [reg_id.email_from]
215 dest += [reg_id.email_cc]
216 if reg_id.event_id.mail_auto_confirm or reg_id.event_id.mail_auto_registr:
218 if reg_id.event_id.state in ['draft', 'fixed', 'open','confirm','running'] and reg_id.event_id.mail_auto_registr:
219 tools.email_send(src, dest,'Auto Registration: '+'['+str(reg_id.id)+']'+' '+reg_id.name, reg_id.event_id.mail_registr, openobject_id = str(reg_id.case_id.id))
220 if (reg_id.event_id.state in ['confirm','running']) and reg_id.event_id.mail_auto_confirm:
221 tools.email_send(src, dest,'Auto Confirmation: '+'['+str(reg_id.id)+']'+' '+reg_id.name, reg_id.event_id.mail_confirm, openobject_id = str(reg_id.case_id.id))
223 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'))
226 def _create_invoice_lines(self, cr, uid, ids, vals):
227 return self.pool.get('account.invoice.line').create(cr, uid,vals )
229 _name= 'event.registration'
230 _description = 'Event Registration'
231 _inherits = {'crm.case': 'case_id'}
233 'case_id':fields.many2one('crm.case','Case'),
234 'nb_register': fields.integer('Number of Registration', readonly=True, states={'draft':[('readonly',False)]}),
235 'event_id':fields.many2one('event.event', 'Event Related', required=True),
236 "partner_invoice_id":fields.many2one('res.partner', 'Partner Invoiced'),
237 "contact_id":fields.many2one('res.partner.contact', 'Partner Contact'), #TODO: filter only the contacts that have a function into the selected partner_id
238 "unit_price": fields.float('Unit Price'),
239 "badge_title":fields.char('Badge Title',size=128),
240 "badge_name":fields.char('Badge Name',size=128),
241 "badge_partner":fields.char('Badge Partner',size=128),
242 "invoice_label":fields.char("Label Invoice",size=128,required=True),
243 "tobe_invoiced":fields.boolean("To be Invoiced"),
244 "invoice_id":fields.many2one("account.invoice","Invoice"),
245 'date_closed': fields.datetime('Closed', readonly=True),
246 'ref' : fields.reference('Reference', selection=crm._links_get, size=128),
247 'ref2' : fields.reference('Reference 2', selection=crm._links_get, size=128),
248 'categ_id': fields.many2one('crm.case.categ','Category', domain="[('section_id','=',section_id)]"),
249 'canal_id': fields.many2one('res.partner.canal', 'Channel',help="The channels represent the different communication modes available with the customer." \
250 " With each commercial opportunity, you can indicate the canall which is this opportunity source."),
251 'som': fields.many2one('res.partner.som', 'State of Mind', help="The minds states allow to define a value scale which represents" \
252 "the partner mentality in relation to our services.The scale has" \
253 "to be created with a factor for each level from 0 (Very dissatisfied) to 10 (Extremely satisfied)."),
257 'nb_register': lambda *a: 1,
258 'tobe_invoiced' : lambda *a: True,
259 'name': lambda *a: 'Registration',
260 'state': lambda *b: 'draft'
263 def onchange_badge_name(self, cr, uid, ids, badge_name):
267 data['name'] = 'Registration: ' + badge_name
268 return {'value':data}
270 def onchange_contact_id(self, cr, uid, ids, contact, partner):
274 contact_id = self.pool.get('res.partner.contact').browse(cr, uid, contact)
275 data['badge_name'] = contact_id.name
276 data['badge_title'] = contact_id.title
278 partner_addresses = self.pool.get('res.partner.address').search(cr, uid, [('partner_id','=',partner)])
279 job_ids = self.pool.get('res.partner.job').search(cr, uid, [('contact_id','=',contact),('address_id','in',partner_addresses)])
281 data['email_from'] = self.pool.get('res.partner.job').browse(cr, uid, job_ids[0]).email
282 d = self.onchange_badge_name(cr, uid, ids,data['badge_name'])
283 data.update(d['value'])
285 return {'value':data}
287 def onchange_event(self, cr, uid, ids, event_id, partner_invoice_id):
290 return {'value':{'unit_price' : False ,'invoice_label' : False }}
291 data_event = self.pool.get('event.event').browse(cr,uid,event_id)
292 if data_event.product_id:
293 if not partner_invoice_id:
294 unit_price=self.pool.get('product.product').price_get(cr, uid, [data_event.product_id.id],context=context)[data_event.product_id.id]
295 return {'value':{'unit_price' : unit_price , 'invoice_label' : data_event.product_id.name}}
296 data_partner = self.pool.get('res.partner').browse(cr,uid,partner_invoice_id)
297 context.update({'partner_id':data_partner})
298 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]
299 return {'value':{'unit_price' :unit_price , 'invoice_label' : data_event.product_id.name}}
300 return {'value':{'unit_price' : False,'invoice_label' : False}}
303 def onchange_partner_id(self, cr, uid, ids, part, event_id, email=False):
305 data['badge_partner'] = data['contact_id'] = data['partner_invoice_id'] = data['email_from'] = data['badge_title'] = data['badge_name'] = False
307 return {'value':data}
308 data['partner_invoice_id']=part
309 # this calls onchange_partner_invoice_id
310 d = self.onchange_partner_invoice_id(cr, uid, ids, event_id,part)
311 # this updates the dictionary
312 data.update(d['value'])
313 addr = self.pool.get('res.partner').address_get(cr, uid, [part])
315 if addr.has_key('default'):
316 job_ids = self.pool.get('res.partner.job').search(cr, uid, [('address_id','=',addr['default'])])
318 data['contact_id'] = self.pool.get('res.partner.job').browse(cr, uid, job_ids[0]).contact_id.id
319 d = self.onchange_contact_id(cr, uid, ids, data['contact_id'],part)
320 data.update(d['value'])
321 partner_data = self.pool.get('res.partner').browse(cr, uid, part)
322 data['badge_partner'] = partner_data.name
323 return {'value':data}
325 def onchange_partner_invoice_id(self, cr, uid, ids, event_id, partner_invoice_id):
328 data['unit_price']=False
330 return {'value':data}
331 data_event = self.pool.get('event.event').browse(cr,uid,event_id)
333 if data_event.product_id:
334 if not partner_invoice_id:
335 data['unit_price']=self.pool.get('product.product').price_get(cr, uid, [data_event.product_id.id],context=context)[data_event.product_id.id]
336 return {'value':data}
337 data_partner = self.pool.get('res.partner').browse(cr,uid,partner_invoice_id)
338 context.update({'partner_id':data_partner})
339 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]
340 return {'value':data}
341 return {'value':data}
343 def onchange_categ_id(self, cr, uid, ids, categ, context={}):
346 cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
347 return {'value':{'probability':cat}}
349 def _map_ids(self,method,cr, uid, ids, *args, **argv):
350 case_data = self.browse(cr,uid,ids)
352 for case in case_data:
354 new_ids.append(case.case_id.id)
355 return getattr(self.pool.get('crm.case'),method)(cr, uid, new_ids, *args, **argv)
358 def case_close(self,cr, uid, ids, *args, **argv):
359 return self._map_ids('case_close',cr,uid,ids,*args,**argv)
360 def case_escalate(self,cr, uid, ids, *args, **argv):
361 return self._map_ids('case_escalate',cr,uid,ids,*args,**argv)
362 def case_open(self,cr, uid, ids, *args, **argv):
363 return self._map_ids('case_open',cr,uid,ids,*args,**argv)
364 def case_cancel(self,cr, uid, ids, *args, **argv):
365 return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
366 def case_pending(self,cr, uid, ids, *args, **argv):
367 return self._map_ids('case_pending',cr,uid,ids,*args,**argv)
368 def case_reset(self,cr, uid, ids, *args, **argv):
369 return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
370 def case_log(self,cr, uid, ids, *args, **argv):
371 return self._map_ids('case_log',cr,uid,ids,*args,**argv)
372 def case_log_reply(self,cr, uid, ids, *args, **argv):
373 return self._map_ids('case_log_reply',cr,uid,ids,*args,**argv)
374 def add_reply(self,cr, uid, ids, *args, **argv):
375 return self._map_ids('add_reply',cr,uid,ids,*args,**argv)
376 def remind_partner(self,cr, uid, ids, *args, **argv):
377 return self._map_ids('remind_partner',cr,uid,ids,*args,**argv)
378 def remind_user(self,cr, uid, ids, *args, **argv):
379 return self._map_ids('remind_user',cr,uid,ids,*args,**argv)
386 class report_event_registration(osv.osv):
387 _name = "report.event.registration"
388 _description = "Events on registrations"
391 'name': fields.char('Event',size=20),
392 'date_begin': fields.datetime('Beginning date', required=True),
393 'date_end': fields.datetime('Ending date', required=True),
394 'draft_state': fields.integer('Draft Registration',size=20),
395 'confirm_state': fields.integer('Confirm Registration',size=20),
396 'register_max': fields.integer('Maximum Registrations'),
400 create or replace view report_event_registration as (
404 e.date_begin as date_begin,
405 e.date_end as date_end,
406 (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,
407 (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,
408 e.register_max as register_max
410 event_event e,crm_case_section c
415 report_event_registration()
417 class report_event_type_registration(osv.osv):
418 _name = "report.event.type.registration"
419 _description = "Event type on registration"
422 'name': fields.char('Event Type',size=20),
423 'nbevent':fields.integer('Number Of Events'),
424 'draft_state': fields.integer('Draft Registrations',size=20),
425 'confirm_state': fields.integer('Confirm Registrations',size=20),
429 create or replace view report_event_type_registration as (
433 (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 ,
434 (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,
435 count(t.id) as nbevent
439 crm_case_section c1 on (e.section_id=c1.id)
441 event_type t on (e.type=t.id)
446 report_event_type_registration()
449 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: