2009-12-18 13:44:31 +00:00
# -*- coding: utf-8 -*-
2009-12-04 08:25:52 +00:00
##############################################################################
2010-03-25 12:07:00 +00:00
#
2009-12-04 08:25:52 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2009-12-04 08:25:52 +00:00
#
# This program is free software: you can redistribute it and/or modify
2009-12-18 13:44:31 +00:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2009-12-04 08:25:52 +00:00
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2009-12-18 13:44:31 +00:00
# GNU Affero General Public License for more details.
2009-12-04 08:25:52 +00:00
#
2009-12-18 13:44:31 +00:00
# You should have received a copy of the GNU Affero General Public License
2010-03-25 12:07:00 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2009-12-04 08:25:52 +00:00
#
##############################################################################
2010-03-25 12:07:00 +00:00
2011-01-19 08:08:26 +00:00
from datetime import datetime , timedelta , date
2009-12-16 14:16:20 +00:00
from dateutil import parser
2010-02-11 14:08:46 +00:00
from dateutil import rrule
2011-03-31 12:40:25 +00:00
from dateutil . relativedelta import relativedelta
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
from openerp . tools . translate import _
2010-02-01 13:38:58 +00:00
import pytz
2009-12-14 11:07:43 +00:00
import re
2010-02-01 11:28:02 +00:00
import time
2013-11-08 16:05:49 +00:00
from openerp import tools
2013-01-30 15:55:01 +00:00
import openerp . service . report
2013-11-06 16:47:00 +00:00
def get_recurrent_dates ( rrulestring , startdate , exdate = None , tz = None , exrule = None , context = None ) :
""" Get recurrent dates based on Rule string considering exdate and start date.
All input dates and output dates are in UTC . Dates are infered
thanks to rules in the ` ` tz ` ` timezone if given , else it ' ll be in
the current local timezone as specified in the context .
@param rrulestring : rulestring ( ie : ' FREQ=DAILY;INTERVAL=1;COUNT=3 ' )
@param exdate : string of dates separated by commas ( ie : ' 20130506220000Z,20130507220000Z ' )
@param startdate : string start date for computing recurrent dates
@param tz : pytz timezone for computing recurrent dates
@param exrule : string exrule
2012-10-05 17:10:55 +00:00
@return : list of Recurrent dates
2013-11-06 16:47:00 +00:00
2010-03-18 11:30:31 +00:00
"""
2013-11-06 16:47:00 +00:00
exdate = exdate . split ( ' , ' ) if exdate else [ ]
startdate = pytz . UTC . localize (
datetime . strptime ( startdate , " % Y- % m- %d % H: % M: % S " ) )
2010-03-02 05:28:50 +00:00
def todate ( date ) :
2010-03-03 12:59:53 +00:00
val = parser . parse ( ' ' . join ( ( re . compile ( ' \ d ' ) ) . findall ( date ) ) )
2013-11-06 16:47:00 +00:00
## Dates are localized to saved timezone if any, else defaulted to
## current timezone. WARNING: these last event dates are considered as
## "floating" dates.
if not val . tzinfo :
val = pytz . UTC . localize ( val )
return val . astimezone ( timezone )
## Note that we haven't any context tz info when called by the server, so
## we'll default to UTC which could induce one-day errors in date
## calculation.
timezone = pytz . timezone ( tz or context . get ( ' tz ' ) or ' UTC ' )
2012-08-06 16:28:17 +00:00
2010-02-11 14:08:46 +00:00
if not startdate :
startdate = datetime . now ( )
2012-08-06 16:28:17 +00:00
2013-11-06 16:47:00 +00:00
## Convert the start date to saved timezone (or context tz) as it'll
## define the correct hour/day asked by the user to repeat for recurrence.
startdate = startdate . astimezone ( timezone )
2010-07-02 13:30:13 +00:00
rset1 = rrule . rrulestr ( str ( rrulestring ) , dtstart = startdate , forceset = True )
2010-02-11 14:08:46 +00:00
for date in exdate :
datetime_obj = todate ( date )
rset1 . _exdate . append ( datetime_obj )
2012-08-06 16:28:17 +00:00
2010-04-30 12:39:39 +00:00
if exrule :
rset1 . exrule ( rrule . rrulestr ( str ( exrule ) , dtstart = startdate ) )
2010-07-02 13:30:13 +00:00
2013-11-06 16:47:00 +00:00
return [ d . astimezone ( pytz . UTC ) for d in rset1 ]
2010-02-11 12:37:41 +00:00
def base_calendar_id2real_id ( base_calendar_id = None , with_date = False ) :
2010-03-18 11:30:31 +00:00
"""
2012-10-05 17:10:55 +00:00
Convert a " virtual/recurring event id " ( type string ) into a real event id ( type int ) .
E . g . virtual / recurring event id is 4 - 20091201100000 , so it will return 4.
@param base_calendar_id : id of calendar
@param with_date : if a value is passed to this param it will return dates based on value of withdate + base_calendar_id
@return : real event id
2010-03-18 11:30:31 +00:00
"""
2010-02-11 12:37:41 +00:00
if base_calendar_id and isinstance ( base_calendar_id , ( str , unicode ) ) :
res = base_calendar_id . split ( ' - ' )
2010-04-05 10:37:31 +00:00
2010-02-11 12:37:41 +00:00
if len ( res ) > = 2 :
real_id = res [ 0 ]
if with_date :
real_date = time . strftime ( " % Y- % m- %d % H: % M: % S " , \
time . strptime ( res [ 1 ] , " % Y % m %d % H % M % S " ) )
start = datetime . strptime ( real_date , " % Y- % m- %d % H: % M: % S " )
end = start + timedelta ( hours = with_date )
return ( int ( real_id ) , real_date , end . strftime ( " % Y- % m- %d % H: % M: % S " ) )
return int ( real_id )
2010-04-05 10:37:31 +00:00
2010-02-11 12:37:41 +00:00
return base_calendar_id and int ( base_calendar_id ) or base_calendar_id
2010-01-21 09:09:21 +00:00
2012-12-11 15:56:27 +00:00
def get_real_ids ( ids ) :
if isinstance ( ids , ( str , int , long ) ) :
return base_calendar_id2real_id ( ids )
if isinstance ( ids , ( list , tuple ) ) :
res = [ ]
for id in ids :
res . append ( base_calendar_id2real_id ( id ) )
return res
2010-02-11 12:37:41 +00:00
def real_id2base_calendar_id ( real_id , recurrent_date ) :
2010-03-18 11:30:31 +00:00
"""
2012-10-05 17:10:55 +00:00
Convert a real event id ( type int ) into a " virtual/recurring event id " ( type string ) .
E . g . real event id is 1 and recurrent_date is set to 01 - 12 - 2009 10 : 00 : 00 , so
it will return 1 - 20091201100000.
@param real_id : real event id
@param recurrent_date : real event recurrent date
@return : string containing the real id and the recurrent date
2010-03-18 11:30:31 +00:00
"""
2010-02-11 12:37:41 +00:00
if real_id and recurrent_date :
recurrent_date = time . strftime ( " % Y % m %d % H % M % S " , \
2010-04-06 07:28:49 +00:00
time . strptime ( recurrent_date , " % Y- % m- %d % H: % M: % S " ) )
2010-02-11 12:37:41 +00:00
return ' %d - %s ' % ( real_id , recurrent_date )
return real_id
2010-01-12 12:06:53 +00:00
2010-02-11 12:37:41 +00:00
class calendar_attendee ( osv . osv ) :
2010-03-18 11:30:31 +00:00
"""
Calendar Attendee Information
"""
2010-02-11 12:37:41 +00:00
_name = ' calendar.attendee '
_description = ' Attendee information '
_rec_name = ' cutype '
__attribute__ = { }
def _get_address ( self , name = None , email = None ) :
2010-03-18 11:30:31 +00:00
"""
2012-10-05 17:10:55 +00:00
Gives email information in ical CAL - ADDRESS type format .
@param name : name for CAL - ADDRESS value
@param email : email address for CAL - ADDRESS value
2010-03-18 11:30:31 +00:00
"""
2010-02-11 12:37:41 +00:00
if name and email :
name + = ' : '
return ( name or ' ' ) + ( email and ( ' MAILTO: ' + email ) or ' ' )
2010-11-19 13:48:01 +00:00
def _compute_data ( self , cr , uid , ids , name , arg , context = None ) :
2010-03-18 11:30:31 +00:00
"""
2012-10-05 17:10:55 +00:00
Compute data on function fields for attendee values .
@param ids : list of calendar attendee ' s IDs
@param name : name of field
@return : dictionary of form { id : { ' field Name ' : value ' }}
2010-03-18 11:30:31 +00:00
"""
2010-02-11 12:37:41 +00:00
name = name [ 0 ]
result = { }
for attdata in self . browse ( cr , uid , ids , context = context ) :
id = attdata . id
result [ id ] = { }
2013-11-08 16:05:49 +00:00
2010-02-11 12:37:41 +00:00
if name == ' cn ' :
2013-11-08 16:05:49 +00:00
if attdata . partner_id :
2012-03-05 09:30:39 +00:00
result [ id ] [ name ] = attdata . partner_id . name or False
2010-02-11 12:37:41 +00:00
else :
2010-05-13 11:37:59 +00:00
result [ id ] [ name ] = attdata . email or ' '
2013-11-08 16:05:49 +00:00
2010-02-11 12:37:41 +00:00
if name == ' event_date ' :
if attdata . ref :
2010-03-17 14:11:30 +00:00
result [ id ] [ name ] = attdata . ref . date
2010-02-11 12:37:41 +00:00
else :
result [ id ] [ name ] = False
2013-11-08 16:05:49 +00:00
2010-02-11 12:37:41 +00:00
if name == ' event_end_date ' :
if attdata . ref :
2010-03-18 11:30:31 +00:00
result [ id ] [ name ] = attdata . ref . date_deadline
2010-02-11 12:37:41 +00:00
else :
result [ id ] [ name ] = False
2010-05-14 10:14:26 +00:00
2010-02-11 12:37:41 +00:00
return result
2010-01-22 13:55:53 +00:00
2010-01-21 15:05:53 +00:00
_columns = {
2013-11-08 16:05:49 +00:00
' cutype ' : fields . selection ( [ ( ' individual ' , ' Individual ' ) , ( ' group ' , ' Group ' ) , ( ' resource ' , ' Resource ' ) , ( ' room ' , ' Room ' ) , ( ' unknown ' , ' Unknown ' ) ] , ' Invite Type ' , help = " Specify the type of Invitation " ) ,
' state ' : fields . selection ( [ ( ' needs-action ' , ' Needs Action ' ) , ( ' tentative ' , ' Uncertain ' ) , ( ' declined ' , ' Declined ' ) , ( ' accepted ' , ' Accepted ' ) ] , ' Status ' , readonly = True , help = " Status of the attendee ' s participation " ) ,
' rsvp ' : fields . boolean ( ' Required Reply? ' , help = " Indicats whether the favor of a reply is requested " ) ,
' cn ' : fields . function ( _compute_data , string = ' Common name ' , type = " char " , size = 124 , multi = ' cn ' , store = True ) ,
' dir ' : fields . char ( ' URI Reference ' , size = 124 , help = " Reference to the URI that points to the directory information corresponding to the attendee. " ) ,
2012-03-05 09:30:39 +00:00
' partner_id ' : fields . many2one ( ' res.partner ' , ' Contact ' ) ,
2010-04-29 13:50:23 +00:00
' email ' : fields . char ( ' Email ' , size = 124 , help = " Email of Invited Person " ) ,
2013-11-08 16:05:49 +00:00
' event_date ' : fields . function ( _compute_data , string = ' Event Date ' , type = " datetime " , multi = ' event_date ' ) ,
' event_end_date ' : fields . function ( _compute_data , string = ' Event End Date ' , type = " datetime " , multi = ' event_end_date ' ) ,
2010-04-29 13:50:23 +00:00
' availability ' : fields . selection ( [ ( ' free ' , ' Free ' ) , ( ' busy ' , ' Busy ' ) ] , ' Free/Busy ' , readonly = " True " ) ,
2013-11-08 16:05:49 +00:00
' access_token ' : fields . char ( ' Invitation Token ' , size = 256 ) ,
' ref ' : fields . many2one ( ' crm.meeting ' , ' Meeting linked ' ) ,
2013-08-02 08:56:07 +00:00
2011-03-09 10:59:59 +00:00
}
2010-02-11 12:37:41 +00:00
_defaults = {
2010-07-02 07:34:06 +00:00
' state ' : ' needs-action ' ,
2010-07-09 13:35:29 +00:00
' rsvp ' : True ,
' cutype ' : ' individual ' ,
2010-01-21 15:05:53 +00:00
}
2010-07-13 11:17:53 +00:00
2010-06-24 12:55:03 +00:00
def copy ( self , cr , uid , id , default = None , context = None ) :
2011-09-18 13:53:10 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( ' You cannot duplicate a calendar attendee. ' ) )
2012-11-30 06:00:20 +00:00
def onchange_partner_id ( self , cr , uid , ids , partner_id , context = None ) :
"""
Make entry on email and availbility on change of partner_id field .
@param partner_id : changed value of partner id
@return : dictionary of values which put value in email and availability fields
"""
if not partner_id :
return { ' value ' : { ' email ' : ' ' } }
partner = self . pool . get ( ' res.partner ' ) . browse ( cr , uid , partner_id , context = context )
return { ' value ' : { ' email ' : partner . email } }
2010-04-30 12:39:39 +00:00
def get_ics_file ( self , cr , uid , event_obj , context = None ) :
"""
2012-10-05 17:10:55 +00:00
Returns iCalendar file for the event invitation .
@param self : the object pointer
@param cr : the current row , from the database cursor
@param uid : the current user ' s id for security checks
@param event_obj : event object ( browse record )
@param context : a standard dictionary for contextual values
2010-04-30 12:39:39 +00:00
@return : . ics file content
"""
res = None
def ics_datetime ( idate , short = False ) :
2010-09-20 11:49:32 +00:00
if idate :
2012-12-28 09:42:36 +00:00
#returns the datetime as UTC, because it is stored as it in the database
return datetime . strptime ( idate , ' % Y- % m- %d % H: % M: % S ' ) . replace ( tzinfo = pytz . timezone ( ' UTC ' ) )
return False
2010-04-30 12:39:39 +00:00
try :
2010-09-03 13:15:30 +00:00
# FIXME: why isn't this in CalDAV?
2010-04-30 12:39:39 +00:00
import vobject
except ImportError :
return res
cal = vobject . iCalendar ( )
2010-07-13 11:17:53 +00:00
event = cal . add ( ' vevent ' )
2010-12-31 12:18:35 +00:00
if not event_obj . date_deadline or not event_obj . date :
2012-08-07 11:34:14 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " First you have to specify the date of the invitation. " ) )
2010-04-30 12:39:39 +00:00
event . add ( ' created ' ) . value = ics_datetime ( time . strftime ( ' % Y- % m- %d % H: % M: % S ' ) )
event . add ( ' dtstart ' ) . value = ics_datetime ( event_obj . date )
event . add ( ' dtend ' ) . value = ics_datetime ( event_obj . date_deadline )
event . add ( ' summary ' ) . value = event_obj . name
if event_obj . description :
event . add ( ' description ' ) . value = event_obj . description
if event_obj . location :
event . add ( ' location ' ) . value = event_obj . location
if event_obj . rrule :
event . add ( ' rrule ' ) . value = event_obj . rrule
2013-11-08 16:05:49 +00:00
# if event_obj.organizer:
# event_org = event.add('organizer')
# event_org.params['CN'] = [event_obj.organizer]
# event_org.value = 'MAILTO:' + (event_obj.organizer)
# elif event_obj.user_id or event_obj.organizer_id:
# event_org = event.add('organizer')
# organizer = event_obj.organizer_id
# if not organizer:
# organizer = event_obj.user_id
# event_org.params['CN'] = [organizer.name]
# event_org.value = 'MAILTO:' + (organizer.email or organizer.name)
#"TO DO == replace by alarm ids"
# if event_obj.alarm_id:
# # computes alarm data
# valarm = event.add('valarm')
# alarm_object = self.pool.get('res.alarm')
# alarm_data = alarm_object.read(cr, uid, event_obj.alarm_id.id, context=context)
# # Compute trigger data
# interval = alarm_data['trigger_interval']
# occurs = alarm_data['trigger_occurs']
# duration = (occurs == 'after' and alarm_data['trigger_duration']) \
# or -(alarm_data['trigger_duration'])
# related = alarm_data['trigger_related']
# trigger = valarm.add('TRIGGER')
# trigger.params['related'] = [related.upper()]
# if interval == 'days':
# delta = timedelta(days=duration)
# if interval == 'hours':
# delta = timedelta(hours=duration)
# if interval == 'minutes':
# delta = timedelta(minutes=duration)
# trigger.value = delta
# # Compute other details
# valarm.add('DESCRIPTION').value = alarm_data['name'] or 'OpenERP'
2011-02-09 09:18:48 +00:00
2010-04-30 12:39:39 +00:00
for attendee in event_obj . attendee_ids :
attendee_add = event . add ( ' attendee ' )
attendee_add . params [ ' CUTYPE ' ] = [ str ( attendee . cutype ) ]
2013-11-08 16:05:49 +00:00
#attendee_add.params['ROLE'] = [str(attendee.role)]
2010-04-30 12:39:39 +00:00
attendee_add . params [ ' RSVP ' ] = [ str ( attendee . rsvp ) ]
2010-05-27 10:10:34 +00:00
attendee_add . value = ' MAILTO: ' + ( attendee . email or ' ' )
2010-04-30 12:39:39 +00:00
res = cal . serialize ( )
return res
2010-07-13 11:17:53 +00:00
2010-05-14 10:14:26 +00:00
def _send_mail ( self , cr , uid , ids , mail_to , email_from = tools . config . get ( ' email_from ' , False ) , context = None ) :
2010-03-18 11:30:31 +00:00
"""
2010-07-13 11:17:53 +00:00
Send mail for event invitation to event attendees .
2012-10-05 17:10:55 +00:00
@param email_from : email address for user sending the mail
2010-03-18 11:30:31 +00:00
@return : True
"""
2013-07-05 07:34:36 +00:00
mail_id = [ ]
2013-08-16 12:47:41 +00:00
data_pool = self . pool . get ( ' ir.model.data ' )
mail_pool = self . pool . get ( ' mail.mail ' )
template_pool = self . pool . get ( ' email.template ' )
2013-08-02 08:56:07 +00:00
local_context = context . copy ( )
2013-07-12 11:51:22 +00:00
color = {
' needs-action ' : ' grey ' ,
' accepted ' : ' green ' ,
' tentative ' : ' #FFFF00 ' ,
' declined ' : ' red ' ,
' delegated ' : ' grey '
2013-08-16 12:47:41 +00:00
}
2013-07-05 07:34:36 +00:00
for attendee in self . browse ( cr , uid , ids , context = context ) :
res_obj = attendee . ref
2010-09-20 11:37:45 +00:00
if res_obj :
2013-08-02 08:56:07 +00:00
model , template_id = data_pool . get_object_reference ( cr , uid , ' base_calendar ' , " crm_email_template_meeting_invitation " )
model , act_id = data_pool . get_object_reference ( cr , uid , ' base_calendar ' , " view_crm_meeting_calendar " )
action_id = self . pool . get ( ' ir.actions.act_window ' ) . search ( cr , uid , [ ( ' view_id ' , ' = ' , act_id ) ] , context = context )
base_url = self . pool . get ( ' ir.config_parameter ' ) . get_param ( cr , uid , ' web.base.url ' , default = ' http://localhost:8069 ' , context = context )
2013-08-16 12:47:41 +00:00
body = template_pool . browse ( cr , uid , template_id , context = context ) . body_html
2013-07-05 07:34:36 +00:00
if attendee . email and email_from :
2012-09-04 16:21:35 +00:00
ics_file = self . get_ics_file ( cr , uid , res_obj , context = context )
2013-08-02 08:56:07 +00:00
local_context [ ' att_obj ' ] = attendee
local_context [ ' color ' ] = color
local_context [ ' action_id ' ] = action_id [ 0 ]
local_context [ ' dbname ' ] = cr . dbname
local_context [ ' base_url ' ] = base_url
2013-08-16 12:47:41 +00:00
vals = template_pool . generate_email ( cr , uid , template_id , res_obj . id , context = local_context )
2012-09-04 16:21:35 +00:00
if ics_file :
vals [ ' attachment_ids ' ] = [ ( 0 , 0 , { ' name ' : ' invitation.ics ' ,
2013-07-05 07:34:36 +00:00
' datas_fname ' : ' invitation.ics ' ,
' datas ' : str ( ics_file ) . encode ( ' base64 ' ) } ) ]
2013-11-01 09:19:41 +00:00
if not attendee . partner_id . opt_out :
mail_id . append ( mail_pool . create ( cr , uid , vals , context = context ) )
if mail_id :
return mail_pool . send ( cr , uid , mail_id , context = context )
return False
2010-04-20 12:52:35 +00:00
2010-02-11 12:37:41 +00:00
def onchange_user_id ( self , cr , uid , ids , user_id , * args , * * argv ) :
2010-03-18 11:30:31 +00:00
"""
2010-04-06 07:28:49 +00:00
Make entry on email and availbility on change of user_id field .
2012-10-05 17:10:55 +00:00
@param ids : list of calendar attendee ' s IDs
@param user_id : changed value of User id
@return : dictionary of values which put value in email and availability fields
2010-03-18 11:30:31 +00:00
"""
2010-03-25 12:07:00 +00:00
2010-02-11 12:37:41 +00:00
if not user_id :
return { ' value ' : { ' email ' : ' ' } }
usr_obj = self . pool . get ( ' res.users ' )
user = usr_obj . browse ( cr , uid , user_id , * args )
2012-08-10 10:22:57 +00:00
return { ' value ' : { ' email ' : user . email , ' availability ' : user . availability } }
2010-01-25 12:57:21 +00:00
2010-02-11 12:37:41 +00:00
def do_tentative ( self , cr , uid , ids , context = None , * args ) :
2012-10-05 17:10:55 +00:00
"""
Makes event invitation as Tentative .
@param ids : list of calendar attendee ' s IDs
@param * args : get Tupple value
@param context : a standard dictionary for contextual values
2010-05-14 10:14:26 +00:00
"""
2010-07-02 07:34:06 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' tentative ' } , context )
2010-02-11 12:37:41 +00:00
def do_accept ( self , cr , uid , ids , context = None , * args ) :
2010-03-18 11:30:31 +00:00
"""
2013-02-26 06:52:39 +00:00
Marks event invitation as Accepted .
2012-10-05 17:10:55 +00:00
@param ids : list of calendar attendee ' s IDs
@param context : a standard dictionary for contextual values
2010-03-18 11:30:31 +00:00
@return : True
"""
2010-10-21 06:50:03 +00:00
if context is None :
2010-03-18 11:30:31 +00:00
context = { }
2013-06-27 10:42:06 +00:00
meeting_obj = self . pool . get ( ' crm.meeting ' )
2013-10-10 13:21:00 +00:00
res = self . write ( cr , uid , ids , { ' state ' : ' accepted ' } , context )
for attandee in self . browse ( cr , uid , ids , context = context ) :
meeting_ids = meeting_obj . search ( cr , uid , [ ( ' attendee_ids ' , ' = ' , attandee . id ) ] , context = context )
2013-10-11 05:17:16 +00:00
if meeting_ids :
2013-10-22 05:17:55 +00:00
meeting_obj . message_post ( cr , uid , get_real_ids ( meeting_ids ) , body = _ ( ( " %s has accepted invitation " ) % ( attandee . cn ) ) , context = context )
2013-10-10 13:21:00 +00:00
return res
2010-02-11 12:37:41 +00:00
def do_decline ( self , cr , uid , ids , context = None , * args ) :
2012-10-05 17:10:55 +00:00
"""
Marks event invitation as Declined .
@param ids : list of calendar attendee ' s IDs
@param * args : get Tupple value
@param context : a standard dictionary for contextual values
"""
2010-10-21 06:50:03 +00:00
if context is None :
2010-07-13 11:17:53 +00:00
context = { }
2013-07-05 07:34:36 +00:00
meeting_obj = self . pool . get ( ' crm.meeting ' )
2013-10-10 13:21:00 +00:00
res = self . write ( cr , uid , ids , { ' state ' : ' declined ' } , context )
for attandee in self . browse ( cr , uid , ids , context = context ) :
meeting_ids = meeting_obj . search ( cr , uid , [ ( ' attendee_ids ' , ' = ' , attandee . id ) ] , context = context )
2013-10-11 05:17:16 +00:00
if meeting_ids :
2013-10-22 05:17:55 +00:00
meeting_obj . message_post ( cr , uid , get_real_ids ( meeting_ids ) , body = _ ( ( " %s has declined invitation " ) % ( attandee . cn ) ) , context = context )
2013-10-11 05:17:16 +00:00
return res
2010-02-11 12:37:41 +00:00
2010-03-18 06:31:52 +00:00
def create ( self , cr , uid , vals , context = None ) :
2010-10-21 06:50:03 +00:00
if context is None :
2010-03-18 06:31:52 +00:00
context = { }
2010-02-11 12:37:41 +00:00
if not vals . get ( " email " ) and vals . get ( " cn " ) :
cnval = vals . get ( " cn " ) . split ( ' : ' )
2010-04-06 07:28:49 +00:00
email = filter ( lambda x : x . __contains__ ( ' @ ' ) , cnval )
2010-07-01 06:05:16 +00:00
vals [ ' email ' ] = email and email [ 0 ] or ' '
2010-02-11 12:37:41 +00:00
vals [ ' cn ' ] = vals . get ( " cn " )
2012-12-28 09:42:36 +00:00
res = super ( calendar_attendee , self ) . create ( cr , uid , vals , context = context )
2010-02-11 12:37:41 +00:00
return res
2012-10-05 11:49:19 +00:00
2013-11-08 16:05:49 +00:00
#
# class res_alarm(osv.osv):
# """Resource Alarm """
# _name = 'res.alarm'
# _description = 'Basic Alarm Information'
#
# _columns = {
# 'name':fields.char('Name', size=256, required=True),
# 'trigger_occurs': fields.selection([('before', 'Before'), ('after', 'After')], 'Triggers', required=True),
# 'trigger_interval': fields.selection([('minutes', 'Minutes'), ('hours', 'Hours'), ('days', 'Days')], 'Interval', required=True),
# 'trigger_duration': fields.integer('Duration', required=True),
# 'trigger_related': fields.selection([('start', 'The event starts'), ('end', 'The event ends')], 'Related to', required=True),
# 'duration': fields.integer('Duration', help="""Duration' and 'Repeat' are both optional, but if one occurs, so MUST the other"""),
# 'repeat': fields.integer('Repeat'),
# 'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the event alarm information without removing it.")
# }
# _defaults = {
# 'trigger_interval': 'minutes',
# 'trigger_duration': 5,
# 'trigger_occurs': 'before',
# 'trigger_related': 'start',
# 'active': 1,
# }
#
# def do_alarm_create(self, cr, uid, ids, model, date, context=None):
# """
# Create Alarm for event.
# @param model: Model name.
# @param date: Event date
# @param context: A standard dictionary for contextual values
# @return: True
# """
# if context is None:
# context = {}
# alarm_obj = self.pool.get('calendar.alarm')
# res_alarm_obj = self.pool.get('res.alarm')
# ir_obj = self.pool.get('ir.model')
# model_id = ir_obj.search(cr, uid, [('model', '=', model)])[0]
#
# model_obj = self.pool[model]
# for data in model_obj.browse(cr, uid, ids, context=context):
#
# basic_alarm = data.alarm_id
# cal_alarm = data.base_calendar_alarm_id
# if (not basic_alarm and cal_alarm) or (basic_alarm and cal_alarm):
# new_res_alarm = None
# # Find for existing res.alarm
# duration = cal_alarm.trigger_duration
# interval = cal_alarm.trigger_interval
# occurs = cal_alarm.trigger_occurs
# related = cal_alarm.trigger_related
# domain = [('trigger_duration', '=', duration), ('trigger_interval', '=', interval), ('trigger_occurs', '=', occurs), ('trigger_related', '=', related)]
# alarm_ids = res_alarm_obj.search(cr, uid, domain, context=context)
# if not alarm_ids:
# val = {
# 'trigger_duration': duration,
# 'trigger_interval': interval,
# 'trigger_occurs': occurs,
# 'trigger_related': related,
# 'name': str(duration) + ' ' + str(interval) + ' ' + str(occurs)
# }
# new_res_alarm = res_alarm_obj.create(cr, uid, val, context=context)
# else:
# new_res_alarm = alarm_ids[0]
# cr.execute('UPDATE %s ' % model_obj._table + \
# ' SET base_calendar_alarm_id=%s, alarm_id=%s ' \
# ' WHERE id=%s',
# (cal_alarm.id, new_res_alarm, data.id))
#
# self.do_alarm_unlink(cr, uid, [data.id], model)
# if basic_alarm:
# vals = {
# 'action': 'display',
# 'description': data.description,
# 'name': data.name,
# 'attendee_ids': [(6, 0, map(lambda x:x.id, data.attendee_ids))],
# 'trigger_related': basic_alarm.trigger_related,
# 'trigger_duration': basic_alarm.trigger_duration,
# 'trigger_occurs': basic_alarm.trigger_occurs,
# 'trigger_interval': basic_alarm.trigger_interval,
# 'duration': basic_alarm.duration,
# 'repeat': basic_alarm.repeat,
# 'state': 'run',
# 'event_date': data[date],
# 'res_id': data.id,
# 'model_id': model_id,
# 'user_id': uid
# }
# alarm_id = alarm_obj.create(cr, uid, vals)
# cr.execute('UPDATE %s ' % model_obj._table + \
# ' SET base_calendar_alarm_id=%s, alarm_id=%s '
# ' WHERE id=%s', \
# ( alarm_id, basic_alarm.id, data.id) )
# return True
#
# def do_alarm_unlink(self, cr, uid, ids, model, context=None):
# """
# Delete alarm specified in ids
# @param cr: the current row, from the database cursor,
# @param uid: the current user's ID for security checks,
# @param ids: List of res alarm's IDs.
# @param model: Model name for which alarm is to be cleared.
# @return: True
# """
# if context is None:
# context = {}
# alarm_obj = self.pool.get('calendar.alarm')
# ir_obj = self.pool.get('ir.model')
# model_id = ir_obj.search(cr, uid, [('model', '=', model)])[0]
# model_obj = self.pool[model]
# for data in model_obj.browse(cr, uid, ids, context=context):
# alarm_ids = alarm_obj.search(cr, uid, [('model_id', '=', model_id), ('res_id', '=', data.id)])
# if alarm_ids:
# alarm_obj.unlink(cr, uid, alarm_ids)
# cr.execute('Update %s set base_calendar_alarm_id=NULL, alarm_id=NULL\
# where id=%%s' % model_obj._table,(data.id,))
# return True
#
# class calendar_alarm(osv.osv):
# _name = 'calendar.alarm'
# _description = 'Event alarm information'
# _inherit = 'res.alarm'
# __attribute__ = {}
#
# _columns = {
# 'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
# 'name': fields.char('Summary', size=124, help="""Contains the text to be \
# used as the message subject for email \
# or contains the text to be used for display"""),
# 'action': fields.selection([('audio', 'Audio'), ('display', 'Display'), \
# ('procedure', 'Procedure'), ('email', 'Email') ], 'Action', \
# required=True, help="Defines the action to be invoked when an alarm is triggered"),
# 'description': fields.text('Description', help='Provides a more complete \
# description of the calendar component, than that \
# provided by the "SUMMARY" property'),
# 'attendee_ids': fields.many2many('calendar.attendee', 'alarm_attendee_rel', \
# 'alarm_id', 'attendee_id', 'Attendees', readonly=True),
# 'attach': fields.binary('Attachment', help="""* Points to a sound resource,\
# which is rendered when the alarm is triggered for audio,
# * File which is intended to be sent as message attachments for email,
# * Points to a procedure resource, which is invoked when\
# the alarm is triggered for procedure."""),
# 'res_id': fields.integer('Resource ID'),
# 'model_id': fields.many2one('ir.model', 'Model'),
# 'user_id': fields.many2one('res.users', 'Owner'),
# 'event_date': fields.datetime('Event Date'),
# 'event_end_date': fields.datetime('Event End Date'),
# 'trigger_date': fields.datetime('Trigger Date', readonly="True"),
# 'state':fields.selection([
# ('draft', 'Draft'),
# ('run', 'Run'),
# ('stop', 'Stop'),
# ('done', 'Done'),
# ], 'Status', select=True, readonly=True),
# }
#
# _defaults = {
# 'action': 'email',
# 'state': 'run',
# }
#
# def create(self, cr, uid, vals, context=None):
# """
# Overrides orm create method.
# @param self: The object pointer
# @param cr: the current row, from the database cursor,
# @param vals: dictionary of fields value.{'name_of_the_field': value, ...}
# @param context: A standard dictionary for contextual values
# @return: new record id for calendar_alarm.
# """
# if context is None:
# context = {}
# event_date = vals.get('event_date', False)
# if event_date:
# dtstart = datetime.strptime(vals['event_date'], "%Y-%m-%d %H:%M:%S")
# if vals['trigger_interval'] == 'days':
# delta = timedelta(days=vals['trigger_duration'])
# if vals['trigger_interval'] == 'hours':
# delta = timedelta(hours=vals['trigger_duration'])
# if vals['trigger_interval'] == 'minutes':
# delta = timedelta(minutes=vals['trigger_duration'])
# trigger_date = dtstart + (vals['trigger_occurs'] == 'after' and delta or -delta)
# vals['trigger_date'] = trigger_date
# res = super(calendar_alarm, self).create(cr, uid, vals, context=context)
# return res
class res_partner ( osv . osv ) :
2013-10-22 05:17:55 +00:00
_inherit = ' res.partner '
def get_attendee_detail ( self , cr , uid , ids , meeting_id , context = None ) :
datas = [ ]
meeting = False
if meeting_id :
meeting = self . pool . get ( ' crm.meeting ' ) . browse ( cr , uid , get_real_ids ( meeting_id ) , context )
for partner in self . browse ( cr , uid , ids , context = context ) :
data = self . name_get ( cr , uid , [ partner . id ] , context ) [ 0 ]
if meeting :
for attendee in meeting . attendee_ids :
if attendee . partner_id . id == partner . id :
data = ( data [ 0 ] , data [ 1 ] , attendee . state )
datas . append ( data )
return datas
2010-03-18 11:30:31 +00:00
def do_run_scheduler ( self , cr , uid , automatic = False , use_new_cursor = False , \
2010-02-11 12:37:41 +00:00
context = None ) :
2010-05-14 10:14:26 +00:00
""" Scheduler for event reminder
2012-10-05 17:10:55 +00:00
@param ids : List of calendar alarm ' s IDs.
2010-04-06 09:01:56 +00:00
@param use_new_cursor : False or the dbname
2010-03-25 12:07:00 +00:00
"""
2010-10-21 06:50:03 +00:00
if context is None :
2010-02-11 12:37:41 +00:00
context = { }
2010-07-02 13:30:13 +00:00
current_datetime = datetime . now ( )
alarm_ids = self . search ( cr , uid , [ ( ' state ' , ' != ' , ' done ' ) ] , context = context )
2010-07-13 11:17:53 +00:00
2012-12-28 08:48:40 +00:00
mail_to = " "
2010-07-02 13:30:13 +00:00
for alarm in self . browse ( cr , uid , alarm_ids , context = context ) :
next_trigger_date = None
update_vals = { }
2013-03-29 14:37:20 +00:00
model_obj = self . pool [ alarm . model_id . model ]
2010-07-02 13:30:13 +00:00
res_obj = model_obj . browse ( cr , uid , alarm . res_id , context = context )
re_dates = [ ]
2012-11-23 06:38:31 +00:00
if hasattr ( res_obj , ' rrule ' ) and res_obj . rrule :
2013-11-06 16:47:00 +00:00
recurrent_dates = get_recurrent_dates ( res_obj . rrule , res_obj . date , res_obj . exdate , res_obj . vtimezone , res_obj . exrule , context = context )
2010-07-02 13:30:13 +00:00
trigger_interval = alarm . trigger_interval
if trigger_interval == ' days ' :
delta = timedelta ( days = alarm . trigger_duration )
if trigger_interval == ' hours ' :
delta = timedelta ( hours = alarm . trigger_duration )
if trigger_interval == ' minutes ' :
delta = timedelta ( minutes = alarm . trigger_duration )
delta = alarm . trigger_occurs == ' after ' and delta or - delta
for rdate in recurrent_dates :
2010-07-06 05:42:47 +00:00
if rdate + delta > current_datetime :
break
2010-07-02 13:30:13 +00:00
if rdate + delta < = current_datetime :
re_dates . append ( rdate . strftime ( " % Y- % m- %d % H: % M: % S " ) )
rest_dates = recurrent_dates [ len ( re_dates ) : ]
next_trigger_date = rest_dates and rest_dates [ 0 ] or None
else :
re_dates = [ alarm . trigger_date ]
2012-09-04 16:36:44 +00:00
if re_dates :
2010-07-02 13:30:13 +00:00
if alarm . action == ' email ' :
2012-09-04 16:36:44 +00:00
sub = ' [OpenERP Reminder] %s ' % ( alarm . name )
2013-11-08 16:05:49 +00:00
body = """ <pre>Event: %s
Event Date : % s
Description : % s
From : % s
- - - -
% s
< / pre > """ % (alarm.name, alarm.trigger_date, alarm.description, alarm.user_id.name, alarm.user_id.signature)
2012-12-28 08:48:40 +00:00
mail_to = alarm . user_id . email
2010-07-02 13:30:13 +00:00
for att in alarm . attendee_ids :
2012-12-28 11:18:53 +00:00
mail_to = mail_to + " " + att . user_id . email
2010-07-02 13:30:13 +00:00
if mail_to :
2012-09-04 16:36:44 +00:00
vals = {
' state ' : ' outgoing ' ,
' subject ' : sub ,
' body_html ' : body ,
' email_to ' : mail_to ,
' email_from ' : tools . config . get ( ' email_from ' , mail_to ) ,
}
self . pool . get ( ' mail.mail ' ) . create ( cr , uid , vals , context = context )
2010-07-02 13:30:13 +00:00
if next_trigger_date :
update_vals . update ( { ' trigger_date ' : next_trigger_date } )
else :
update_vals . update ( { ' state ' : ' done ' } )
self . write ( cr , uid , [ alarm . id ] , update_vals )
2010-02-11 12:37:41 +00:00
return True
2010-01-21 08:14:58 +00:00
2013-11-08 16:05:49 +00:00
class calendar_alarm ( osv . osv ) :
_name = ' calendar.alarm '
_description = ' Event alarm '
2011-12-11 20:12:37 +00:00
2010-01-21 08:14:58 +00:00
_columns = {
2013-11-08 16:05:49 +00:00
' name ' : fields . char ( ' Name ' , size = 256 , required = True ) , # fields function
' type ' : fields . selection ( [ ( ' notification ' , ' Notification ' ) , ( ' email ' , ' Email ' ) ] , ' Type ' , required = True ) ,
' duration ' : fields . integer ( ' Amount ' , required = True ) ,
' interval ' : fields . selection ( [ ( ' minutes ' , ' Minutes ' ) , ( ' hours ' , ' Hours ' ) , ( ' days ' , ' Days ' ) ] , ' Unit ' , required = True ) ,
}
2010-01-21 12:58:40 +00:00
_defaults = {
2013-11-08 16:05:49 +00:00
' type ' : ' notification ' ,
' duration ' : 1 ,
' interval ' : ' hours ' ,
2010-07-13 11:17:53 +00:00
}
2013-11-06 16:47:00 +00:00
#
2013-11-08 16:05:49 +00:00
# def _get_date(self, cr, uid, ids, name, arg, context=None):
# """
# Get Date
# @param self: The object pointer
# @param cr: the current row, from the database cursor,
# @param uid: the current user's ID for security checks,
# @param ids: List of calendar todo's IDs.
# @param args: list of tuples of form [(‘ name_of_the_field', ‘ operator', value), ...].
# @param context: A standard dictionary for contextual values
# """
#
# res = {}
# for event in self.browse(cr, uid, ids, context=context):
# res[event.id] = event.date_start
# return res
#
# def _set_date(self, cr, uid, id, name, value, arg, context=None):
# """
# Set Date
# @param self: The object pointer
# @param cr: the current row, from the database cursor,
# @param uid: the current user's ID for security checks,
# @param id: calendar's ID.
# @param value: Get Value
# @param args: list of tuples of form [('name_of_the_field', 'operator', value), ...].
# @param context: A standard dictionary for contextual values
# """
#
# assert name == 'date'
# return self.write(cr, uid, id, { 'date_start': value }, context=context)
2010-03-25 12:07:00 +00:00
2010-02-11 12:37:41 +00:00
class ir_values ( osv . osv ) :
_inherit = ' ir.values '
2013-11-08 16:05:49 +00:00
def set ( self , cr , uid , key , key2 , name , models , value , replace = True , isobject = False , meta = False , preserve_user = False , company = False ) :
2010-02-11 12:37:41 +00:00
new_model = [ ]
for data in models :
if type ( data ) in ( list , tuple ) :
new_model . append ( ( data [ 0 ] , base_calendar_id2real_id ( data [ 1 ] ) ) )
2009-12-15 13:43:55 +00:00
else :
2010-02-11 12:37:41 +00:00
new_model . append ( data )
2010-03-18 11:30:31 +00:00
return super ( ir_values , self ) . set ( cr , uid , key , key2 , name , new_model , \
2010-02-11 12:37:41 +00:00
value , replace , isobject , meta , preserve_user , company )
2009-12-17 06:26:30 +00:00
2013-11-08 16:05:49 +00:00
def get ( self , cr , uid , key , key2 , models , meta = False , context = None , res_id_req = False , without_user = True , key2_req = True ) :
2010-10-21 06:50:03 +00:00
if context is None :
2010-05-14 10:14:26 +00:00
context = { }
2010-02-11 12:37:41 +00:00
new_model = [ ]
for data in models :
if type ( data ) in ( list , tuple ) :
new_model . append ( ( data [ 0 ] , base_calendar_id2real_id ( data [ 1 ] ) ) )
2009-12-14 11:07:43 +00:00
else :
2010-02-11 12:37:41 +00:00
new_model . append ( data )
return super ( ir_values , self ) . get ( cr , uid , key , key2 , new_model , \
meta , context , res_id_req , without_user , key2_req )
class ir_model ( osv . osv ) :
2009-12-18 13:44:31 +00:00
2010-02-11 12:37:41 +00:00
_inherit = ' ir.model '
2010-07-13 11:17:53 +00:00
def read ( self , cr , uid , ids , fields = None , context = None ,
2010-02-11 12:37:41 +00:00
load = ' _classic_read ' ) :
2013-11-08 16:05:49 +00:00
2010-05-26 12:15:25 +00:00
new_ids = isinstance ( ids , ( str , int , long ) ) and [ ids ] or ids
2010-10-21 06:50:03 +00:00
if context is None :
2010-05-14 10:14:26 +00:00
context = { }
2010-05-26 12:15:25 +00:00
data = super ( ir_model , self ) . read ( cr , uid , new_ids , fields = fields , \
2010-02-11 12:37:41 +00:00
context = context , load = load )
if data :
for val in data :
val [ ' id ' ] = base_calendar_id2real_id ( val [ ' id ' ] )
2010-05-19 12:22:19 +00:00
return isinstance ( ids , ( str , int , long ) ) and data [ 0 ] or data
2010-02-11 12:37:41 +00:00
2013-01-30 15:55:01 +00:00
original_exp_report = openerp . service . report . exp_report
2010-02-11 12:37:41 +00:00
2013-01-30 15:55:01 +00:00
def exp_report ( db , uid , object , ids , data = None , context = None ) :
"""
Export Report
"""
if object == ' printscreen.list ' :
original_exp_report ( db , uid , object , ids , data , context )
new_ids = [ ]
for id in ids :
new_ids . append ( base_calendar_id2real_id ( id ) )
if data . get ( ' id ' , False ) :
data [ ' id ' ] = base_calendar_id2real_id ( data [ ' id ' ] )
return original_exp_report ( db , uid , object , new_ids , data , context )
2010-02-11 12:37:41 +00:00
2013-01-30 15:55:01 +00:00
openerp . service . report . exp_report = exp_report
2010-02-11 12:37:41 +00:00
2013-11-08 16:05:49 +00:00