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 _
31 class event_type(osv.osv):
33 _description= 'Event type'
35 'name': fields.char('Event type', size=64, required=True),
41 _description = 'Event'
42 _inherits = {'crm.case.section': 'section_id'}
45 def copy(self, cr, uid, id, default=None, context=None):
46 return super(event, self).copy(cr, uid, id, default={'code': self.pool.get('ir.sequence').get(cr, uid, 'event.event'), 'state': 'draft'})
48 def button_draft(self, cr, uid, ids, context={}):
49 return self.write(cr, uid, ids, {'state': 'draft'})
51 def button_cancel(self, cr, uid, ids, context={}):
52 return self.write(cr, uid, ids, {'state': 'cancel'})
54 def button_done(self, cr, uid, ids, context={}):
55 return self.write(cr, uid, ids, {'state': 'done'})
57 def button_confirm(self, cr, uid, ids, context={}):
58 for eve in self.browse(cr, uid, ids):
59 if eve.mail_auto_confirm:
60 #send reminder that will confirm the event for all the people that were already confirmed
61 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id', '=', eve.id), ('state', 'not in', ['draft', 'cancel'])])
63 self.pool.get('event.registration').mail_user_confirm(cr, uid, reg_ids)
64 return self.write(cr, uid, ids, {'state': 'confirm'})
66 def _get_register(self, cr, uid, ids, name, args, context=None):
68 for event in self.browse(cr, uid, ids, context):
71 if name[0] == 'register_current':
73 query = """SELECT sum(r.nb_register)
74 from event_registration r
75 where state=%s and event_id=%s"""
77 cr.execute(query, (state, event.id, ))
80 res[event.id][name[0]] = res2[0]
82 res[event.id][name[0]] = 0
85 def write(self, cr, uid, ids, vals, *args, **kwargs):
86 res = super(event, self).write(cr, uid, ids, vals, *args, **kwargs)
87 if 'date_begin' in vals and vals['date_begin']:
88 for eve in self.browse(cr, uid, ids):
89 #change the deadlines of the registration linked to this event
90 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id', '=', eve.id)])
92 self.pool.get('event.registration').write(cr, uid, reg_ids, {'date_deadline': vals['date_begin']})
94 #change the description of the registration linked to this event
95 if 'mail_auto_confirm' in vals:
96 if vals['mail_auto_confirm']:
97 if 'mail_confirm' not in vals:
98 for eve in self.browse(cr, uid, ids):
99 vals['mail_confirm'] = eve.mail_confirm
101 vals['mail_confirm']=False
102 if 'mail_confirm' in vals:
103 for eve in self.browse(cr, uid, ids):
104 reg_ids = self.pool.get('event.registration').search(cr, uid, [('event_id', '=', eve.id)])
106 self.pool.get('event.registration').write(cr, uid, reg_ids, {'description': vals['mail_confirm']})
110 'type': fields.many2one('event.type', 'Type'),
111 'section_id': fields.many2one('crm.case.section', 'Case section', required=True),
112 'register_max': fields.integer('Maximum Registrations'),
113 'register_min': fields.integer('Minimum Registrations'),
114 'register_current': fields.function(_get_register, method=True, string='Confirmed Registrations', multi='register_current'),
115 'register_prospect': fields.function(_get_register, method=True, string='Unconfirmed Registrations', multi='register_prospect'),
116 'date_begin': fields.datetime('Beginning date', required=True),
117 'date_end': fields.datetime('Ending date', required=True),
118 'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, required=True,
119 help='If event is created, the state is \'Draft\'.\n If event is confirmed for the particular dates the state is set to \'Confirmed\'.\
120 \nIf the event is over, the state is set to \'Done\'.\n If event is cancelled the state is set to \'Cancelled\'.'),
121 'mail_auto_registr': fields.boolean('Mail Auto Register', help='Check this box if you want to use the automatic mailing for new registration'),
122 'mail_auto_confirm': fields.boolean('Mail Auto Confirm', help='Check this box if you want ot use the automatic confirmation emailing or the reminder'),
123 'mail_registr': fields.text('Registration Email', help='This email will be sent when someone subscribes to the event.'),
124 '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."),
125 'product_id': fields.many2one('product.product', 'Product', required=True),
129 'state': lambda *args: 'draft',
130 'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'event.event'),
131 'user_id': lambda self, cr, uid, ctx: uid,
136 class event_registration(osv.osv):
138 def check_confirm(self, cr, uid, ids, context):
139 mod_obj = self.pool.get('ir.model.data')
140 current_registration = self.browse(cr, uid, [ids[0]])[0]
141 total_confirmed = current_registration.event_id.register_current + current_registration.nb_register
142 if total_confirmed <= current_registration.event_id.register_max or current_registration.event_id.register_max == 0:
143 self.write(cr, uid, [ids[0]], {'state': 'open'}, context=context)
144 self._history(cr, uid, [ids[0]], 'Open', history=True)
145 self.mail_user(cr, uid, [ids[0]])
148 model_data_ids = mod_obj.search(cr, uid, [('model', '=', 'ir.ui.view'), ('name', '=', 'view_event_confirm_registration')], context=context)
149 resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
150 context.update({'reg_id': ids[0]})
152 'name': _('Confirm Registration'),
155 'view_mode': 'tree,form',
156 'res_model': 'event.confirm.registration',
157 'views': [(resource_id, 'form')],
158 'type': 'ir.actions.act_window',
163 def _history(self, cr, uid, ids, keyword, history=False, email=False, context={}):
164 for case in self.browse(cr, uid, ids):
168 'canal_id': case.canal_id.id,
171 obj = self.pool.get('mailgate.message')
172 obj.create(cr, uid, data, context=context)
175 def button_reg_close(self, cr, uid, ids, *args):
176 self.write(cr, uid, ids, {'state': 'done', })
177 self._history(cr, uid, ids, 'Done', history=True)
180 def button_reg_cancel(self, cr, uid, ids, *args):
181 self.write(cr, uid, ids, {'state': 'cancel', })
182 self._history(cr, uid, ids, 'Cancel', history=True)
185 def create(self, cr, uid, *args, **argv):
186 event = self.pool.get('event.event').browse(cr, uid, args[0]['event_id'], None)
187 args[0]['section_id']= event.section_id.id
188 args[0]['date_deadline']= event.date_begin
189 args[0]['description']= event.mail_confirm
190 res = super(event_registration, self).create(cr, uid, *args, **argv)
191 self._history(cr, uid, [res], 'Created', history=True)
194 def write(self, cr, uid, *args, **argv):
195 if 'event_id' in args[1]:
196 event = self.pool.get('event.event').browse(cr, uid, args[1]['event_id'], None)
197 args[1]['section_id']= event.section_id.id
198 args[1]['date_deadline']= event.date_begin
199 args[1]['description']= event.mail_confirm
200 return super(event_registration, self).write(cr, uid, *args, **argv)
202 def mail_user_confirm(self, cr, uid, ids):
203 reg_ids = self.browse(cr, uid, ids)
204 for reg_id in reg_ids:
205 src = reg_id.event_id.reply_to or False
207 if reg_id.email_from:
208 dest += [reg_id.email_from]
210 dest += [reg_id.email_cc]
212 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.id))
214 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'))
217 def mail_user(self, cr, uid, ids):
218 reg_ids = self.browse(cr, uid, ids)
219 for reg_id in reg_ids:
220 src = reg_id.event_id.reply_to or False
222 if reg_id.email_from:
223 dest += [reg_id.email_from]
225 dest += [reg_id.email_cc]
226 if reg_id.event_id.mail_auto_confirm or reg_id.event_id.mail_auto_registr:
228 if reg_id.event_id.state in ['draft', 'fixed', 'open', 'confirm', 'running'] and reg_id.event_id.mail_auto_registr:
229 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.id))
230 if (reg_id.event_id.state in ['confirm', 'running']) and reg_id.event_id.mail_auto_confirm:
231 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.id))
233 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'))
236 def _create_invoice_lines(self, cr, uid, ids, vals):
237 return self.pool.get('account.invoice.line').create(cr, uid, vals)
239 _name= 'event.registration'
240 _description = 'Event Registration'
241 _inherit = 'crm.meeting'
244 'email_cc': fields.text('Watchers Emails', size=252 , help="These \
245 people will receive a copy of the future communication between partner \
246 and users by email"),
247 'nb_register': fields.integer('Number of Registration', readonly=True, states={'draft': [('readonly', False)]}),
248 'event_id': fields.many2one('event.event', 'Event Related', required=True),
249 "partner_invoice_id": fields.many2one('res.partner', 'Partner Invoiced'),
250 "contact_id": fields.many2one('res.partner.contact', 'Partner Contact'), #TODO: filter only the contacts that have a function into the selected partner_id
251 "unit_price": fields.float('Unit Price'),
252 "badge_title": fields.char('Badge Title', size=128),
253 "badge_name": fields.char('Badge Name', size=128),
254 "badge_partner": fields.char('Badge Partner', size=128),
255 "invoice_label": fields.char("Label Invoice", size=128, required=True),
256 "tobe_invoiced": fields.boolean("To be Invoiced"),
257 "invoice_id": fields.many2one("account.invoice", "Invoice"),
258 'date_closed': fields.datetime('Closed', readonly=True),
259 'ref': fields.reference('Reference', selection=crm._links_get, size=128),
260 'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
261 'canal_id': fields.many2one('res.partner.canal', 'Channel', help="The channels represent the different communication modes available with the customer." \
262 " With each commercial opportunity, you can indicate the canall which is this opportunity source."),
263 'som': fields.many2one('res.partner.som', 'State of Mind', help="The minds states allow to define a value scale which represents" \
264 "the partner mentality in relation to our services.The scale has" \
265 "to be created with a factor for each level from 0 (Very dissatisfied) to 10 (Extremely satisfied)."),
269 'nb_register': lambda *a: 1,
270 'tobe_invoiced': lambda *a: True,
271 'name': lambda *a: 'Registration',
274 def onchange_badge_name(self, cr, uid, ids, badge_name):
278 data['name'] = 'Registration: ' + badge_name
279 return {'value': data}
281 def onchange_contact_id(self, cr, uid, ids, contact, partner):
285 contact_id = self.pool.get('res.partner.contact').browse(cr, uid, contact)
286 data['badge_name'] = contact_id.name
287 data['badge_title'] = contact_id.title
289 partner_addresses = self.pool.get('res.partner.address').search(cr, uid, [('partner_id', '=', partner)])
290 job_ids = self.pool.get('res.partner.job').search(cr, uid, [('contact_id', '=', contact), ('address_id', 'in', partner_addresses)])
292 data['email_from'] = self.pool.get('res.partner.job').browse(cr, uid, job_ids[0]).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}}
364 class report_event_registration(osv.osv):
365 _name = "report.event.registration"
366 _description = "Events on registrations"
369 'name': fields.char('Event', size=20),
370 'date_begin': fields.datetime('Beginning date', required=True),
371 'date_end': fields.datetime('Ending date', required=True),
372 'draft_state': fields.integer('Draft Registration', size=20),
373 'confirm_state': fields.integer('Confirm Registration', size=20),
374 'register_max': fields.integer('Maximum Registrations'),
378 create or replace view report_event_registration as (
382 e.date_begin as date_begin,
383 e.date_end as date_end,
384 (SELECT sum(c.nb_register) FROM event_registration c WHERE c.section_id=e.section_id and state in ('draft')) as draft_state,
385 (SELECT sum(c.nb_register) FROM event_registration c WHERE c.section_id=e.section_id and state in ('open')) as confirm_state,
386 e.register_max as register_max
388 event_event e,crm_case_section c
393 report_event_registration()
395 class report_event_type_registration(osv.osv):
396 _name = "report.event.type.registration"
397 _description = "Event type on registration"
400 'name': fields.char('Event Type', size=20),
401 'nbevent': fields.integer('Number Of Events'),
402 'draft_state': fields.integer('Draft Registrations', size=20),
403 'confirm_state': fields.integer('Confirm Registrations', size=20),
409 create or replace view report_event_type_registration as (
413 (select sum(c.nb_register) from event_registration c, event_event e where c.section_id=e.section_id and c.state='draft' and e.type=t.id ) as draft_state ,
414 (select sum(c.nb_register) from event_registration c, event_event e where c.section_id=e.section_id and c.state='open' and e.type=t.id ) as confirm_state,
415 count(t.id) as nbevent
419 crm_case_section c1 on (e.section_id=c1.id)
421 event_type t on (e.type=t.id)
426 report_event_type_registration()
429 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: