2009-12-18 13:44:31 +00:00
# -*- coding: utf-8 -*-
2010-03-25 12:07:00 +00:00
2013-11-23 11:36:27 +00:00
import pytz
import re
import time
import openerp
import openerp . service . report
2014-01-13 19:31:21 +00:00
import uuid
2014-11-21 10:55:00 +00:00
import collections
2015-02-10 12:37:14 +00:00
import babel . dates
2014-02-18 11:11:38 +00:00
from werkzeug . exceptions import BadRequest
2014-01-10 17:09:12 +00:00
from datetime import datetime , timedelta
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
2014-07-28 16:07:17 +00:00
from openerp import api
2013-11-23 11:36:27 +00:00
from openerp import tools , SUPERUSER_ID
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
2013-11-23 11:36:27 +00:00
from openerp . tools import DEFAULT_SERVER_DATE_FORMAT , DEFAULT_SERVER_DATETIME_FORMAT
2012-12-06 14:56:32 +00:00
from openerp . tools . translate import _
2014-01-13 17:41:57 +00:00
from openerp . http import request
2014-01-14 13:37:36 +00:00
from operator import itemgetter
2013-11-06 16:47:00 +00:00
2014-01-10 17:09:12 +00:00
import logging
_logger = logging . getLogger ( __name__ )
2013-11-06 16:47:00 +00:00
2013-12-02 14:52:42 +00:00
2013-12-19 14:47:39 +00:00
def calendar_id2real_id ( 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.
2013-12-19 14:47:39 +00:00
@param 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 + calendar_id
2012-10-05 17:10:55 +00:00
@return : real event id
2010-03-18 11:30:31 +00:00
"""
2014-12-31 10:56:28 +00:00
if calendar_id and isinstance ( calendar_id , ( basestring ) ) :
2013-12-19 14:47:39 +00:00
res = calendar_id . split ( ' - ' )
2010-02-11 12:37:41 +00:00
if len ( res ) > = 2 :
real_id = res [ 0 ]
if with_date :
2014-04-30 09:36:13 +00:00
real_date = time . strftime ( DEFAULT_SERVER_DATETIME_FORMAT , time . strptime ( res [ 1 ] , " % Y % m %d % H % M % S " ) )
start = datetime . strptime ( real_date , DEFAULT_SERVER_DATETIME_FORMAT )
2014-01-10 17:09:12 +00:00
end = start + timedelta ( hours = with_date )
2014-04-30 09:36:13 +00:00
return ( int ( real_id ) , real_date , end . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) )
2010-02-11 12:37:41 +00:00
return int ( real_id )
2013-12-19 14:47:39 +00:00
return calendar_id and int ( calendar_id ) or calendar_id
2010-01-21 09:09:21 +00:00
2014-02-24 22:02:22 +00:00
2012-12-11 15:56:27 +00:00
def get_real_ids ( ids ) :
2014-12-31 10:56:28 +00:00
if isinstance ( ids , ( basestring , int , long ) ) :
2013-12-19 14:47:39 +00:00
return calendar_id2real_id ( ids )
2012-12-11 15:56:27 +00:00
if isinstance ( ids , ( list , tuple ) ) :
2014-01-10 17:09:12 +00:00
return [ calendar_id2real_id ( id ) for id in ids ]
2012-12-11 15:56:27 +00:00
2014-01-10 17:09:12 +00:00
class calendar_attendee ( osv . Model ) :
2010-03-18 11:30:31 +00:00
"""
Calendar Attendee Information
"""
2010-02-11 12:37:41 +00:00
_name = ' calendar.attendee '
2014-02-24 22:02:22 +00:00
_rec_name = ' cn '
2010-02-11 12:37:41 +00:00
_description = ' Attendee information '
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 ] = { }
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 ' '
2010-02-11 12:37:41 +00:00
return result
2010-01-22 13:55:53 +00:00
2014-01-20 12:59:53 +00:00
STATE_SELECTION = [
( ' needsAction ' , ' Needs Action ' ) ,
( ' tentative ' , ' Uncertain ' ) ,
( ' declined ' , ' Declined ' ) ,
( ' accepted ' , ' Accepted ' ) ,
]
2010-01-21 15:05:53 +00:00
_columns = {
2014-01-20 12:59:53 +00:00
' state ' : fields . selection ( STATE_SELECTION , ' Status ' , readonly = True , help = " Status of the attendee ' s participation " ) ,
2014-01-10 17:09:12 +00:00
' cn ' : fields . function ( _compute_data , string = ' Common name ' , type = " char " , multi = ' cn ' , store = True ) ,
' partner_id ' : fields . many2one ( ' res.partner ' , ' Contact ' , readonly = " True " ) ,
' email ' : fields . char ( ' Email ' , help = " Email of Invited Person " ) ,
2010-04-29 13:50:23 +00:00
' availability ' : fields . selection ( [ ( ' free ' , ' Free ' ) , ( ' busy ' , ' Busy ' ) ] , ' Free/Busy ' , readonly = " True " ) ,
2014-01-10 17:09:12 +00:00
' access_token ' : fields . char ( ' Invitation Token ' ) ,
2015-06-19 09:35:41 +00:00
' event_id ' : fields . many2one ( ' calendar.event ' , ' Meeting linked ' , ondelete = ' cascade ' ) ,
2011-03-09 10:59:59 +00:00
}
2010-02-11 12:37:41 +00:00
_defaults = {
2014-01-10 17:09:12 +00:00
' state ' : ' needsAction ' ,
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. ' ) )
2014-01-10 17:09:12 +00:00
def onchange_partner_id ( self , cr , uid , ids , partner_id , context = None ) :
2012-11-30 06:00:20 +00:00
"""
2013-11-12 08:18:57 +00:00
Make entry on email and availability on change of partner_id field .
2012-11-30 06:00:20 +00:00
@param partner_id : changed value of partner id
2014-01-10 17:09:12 +00:00
"""
2012-11-30 06:00:20 +00:00
if not partner_id :
return { ' value ' : { ' email ' : ' ' } }
2014-01-10 17:09:12 +00:00
partner = self . pool [ ' res.partner ' ] . browse ( cr , uid , partner_id , context = context )
2012-11-30 06:00:20 +00:00
return { ' value ' : { ' email ' : partner . email } }
2014-01-10 17:09:12 +00:00
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 event_obj : event object ( browse record )
2010-04-30 12:39:39 +00:00
@return : . ics file content
"""
res = None
2014-01-10 17:09:12 +00:00
2014-04-30 09:36:13 +00:00
def ics_datetime ( idate , allday = False ) :
2010-09-20 11:49:32 +00:00
if idate :
2014-04-30 09:36:13 +00:00
if allday :
2015-02-11 20:28:38 +00:00
return openerp . fields . Date . from_string ( idate )
2014-04-30 09:36:13 +00:00
else :
2015-02-11 20:28:38 +00:00
return openerp . fields . Datetime . from_string ( idate ) . replace ( tzinfo = pytz . timezone ( ' UTC ' ) )
2012-12-28 09:42:36 +00:00
return False
2014-01-10 17:09:12 +00:00
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
2014-01-10 17:09:12 +00:00
2010-04-30 12:39:39 +00:00
cal = vobject . iCalendar ( )
2010-07-13 11:17:53 +00:00
event = cal . add ( ' vevent ' )
2014-05-05 15:42:46 +00:00
if not event_obj . start or not event_obj . stop :
2014-01-10 17:09:12 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " First you have to specify the date of the invitation. " ) )
2014-04-30 09:36:13 +00:00
event . add ( ' created ' ) . value = ics_datetime ( time . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) )
2014-05-05 15:42:46 +00:00
event . add ( ' dtstart ' ) . value = ics_datetime ( event_obj . start , event_obj . allday )
event . add ( ' dtend ' ) . value = ics_datetime ( event_obj . stop , event_obj . allday )
2010-04-30 12:39:39 +00:00
event . add ( ' summary ' ) . value = event_obj . name
2014-01-10 17:09:12 +00:00
if event_obj . description :
2010-04-30 12:39:39 +00:00
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
2013-11-23 11:36:27 +00:00
if event_obj . alarm_ids :
2014-01-10 17:09:12 +00:00
for alarm in event_obj . alarm_ids :
2013-11-23 11:36:27 +00:00
valarm = event . add ( ' valarm ' )
interval = alarm . interval
duration = alarm . duration
trigger = valarm . add ( ' TRIGGER ' )
trigger . params [ ' related ' ] = [ " START " ]
if interval == ' days ' :
delta = timedelta ( days = duration )
elif interval == ' hours ' :
delta = timedelta ( hours = duration )
elif interval == ' minutes ' :
delta = timedelta ( minutes = duration )
trigger . value = delta
2014-07-09 11:39:38 +00:00
valarm . add ( ' DESCRIPTION ' ) . value = alarm . name or ' Odoo '
2010-04-30 12:39:39 +00:00
for attendee in event_obj . attendee_ids :
attendee_add = event . add ( ' attendee ' )
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
2014-05-14 08:28:10 +00:00
def _send_mail_to_attendees ( self , cr , uid , ids , email_from = tools . config . get ( ' email_from ' , False ) ,
2015-02-06 13:01:45 +00:00
template_xmlid = ' calendar_template_meeting_invitation ' , force = 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
2015-02-06 13:01:45 +00:00
@param force : If set to True , email will be sent to user himself . Usefull for example for alert , . . .
2010-03-18 11:30:31 +00:00
"""
2013-11-23 11:36:27 +00:00
res = False
2014-04-14 20:29:36 +00:00
2014-04-30 09:36:13 +00:00
if self . pool [ ' ir.config_parameter ' ] . get_param ( cr , uid , ' calendar.block_mail ' , default = False ) or context . get ( " no_mail_to_attendees " ) :
2014-04-14 20:29:36 +00:00
return res
2013-12-19 13:33:16 +00:00
mail_ids = [ ]
2014-01-10 17:09:12 +00:00
data_pool = self . pool [ ' ir.model.data ' ]
mailmess_pool = self . pool [ ' mail.message ' ]
mail_pool = self . pool [ ' mail.mail ' ]
template_pool = self . pool [ ' email.template ' ]
2013-12-19 13:33:16 +00:00
local_context = context . copy ( )
color = {
2014-01-10 17:09:12 +00:00
' needsAction ' : ' grey ' ,
' accepted ' : ' green ' ,
' tentative ' : ' #FFFF00 ' ,
' declined ' : ' red '
2013-12-19 13:33:16 +00:00
}
2014-01-10 17:09:12 +00:00
2013-12-19 13:33:16 +00:00
if not isinstance ( ids , ( tuple , list ) ) :
ids = [ ids ]
2014-01-10 17:09:12 +00:00
dummy , template_id = data_pool . get_object_reference ( cr , uid , ' calendar ' , template_xmlid )
2014-01-15 09:38:05 +00:00
dummy , act_id = data_pool . get_object_reference ( cr , uid , ' calendar ' , " view_calendar_event_calendar " )
2014-01-10 17:09:12 +00:00
local_context . update ( {
' color ' : color ,
' action_id ' : self . pool [ ' ir.actions.act_window ' ] . search ( cr , uid , [ ( ' view_id ' , ' = ' , act_id ) ] , context = context ) [ 0 ] ,
' dbname ' : cr . dbname ,
' base_url ' : self . pool [ ' ir.config_parameter ' ] . get_param ( cr , uid , ' web.base.url ' , default = ' http://localhost:8069 ' , context = context )
} )
for attendee in self . browse ( cr , uid , ids , context = context ) :
2015-02-06 13:01:45 +00:00
if attendee . email and email_from and ( attendee . email != email_from or force ) :
2013-12-19 13:33:16 +00:00
ics_file = self . get_ics_file ( cr , uid , attendee . event_id , context = context )
mail_id = template_pool . send_mail ( cr , uid , template_id , attendee . id , context = local_context )
2014-01-10 17:09:12 +00:00
vals = { }
2013-12-19 13:33:16 +00:00
if ics_file :
2014-01-10 17:09:12 +00:00
vals [ ' attachment_ids ' ] = [ ( 0 , 0 , { ' name ' : ' invitation.ics ' ,
' datas_fname ' : ' invitation.ics ' ,
' datas ' : str ( ics_file ) . encode ( ' base64 ' ) } ) ]
vals [ ' model ' ] = None # We don't want to have the mail in the tchatter while in queue!
the_mailmess = mail_pool . browse ( cr , uid , mail_id , context = context ) . mail_message_id
mailmess_pool . write ( cr , uid , [ the_mailmess . id ] , vals , context = context )
2013-12-19 13:33:16 +00:00
mail_ids . append ( mail_id )
2014-01-10 17:09:12 +00:00
2013-12-19 13:33:16 +00:00
if mail_ids :
2014-01-10 17:09:12 +00:00
res = mail_pool . send ( cr , uid , mail_ids , context = context )
2013-12-19 13:33:16 +00:00
return res
2014-01-10 17:09:12 +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
"""
2013-12-20 16:08:18 +00:00
Make entry on email and availability on change of user_id field .
2013-11-15 16:59:05 +00:00
@param ids : list of attendee ' s IDs
2012-10-05 17:10:55 +00:00
@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-02-11 12:37:41 +00:00
if not user_id :
return { ' value ' : { ' email ' : ' ' } }
2014-01-10 17:09:12 +00:00
user = self . pool [ ' res.users ' ] . browse ( cr , uid , user_id , * args )
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 .
2013-11-15 16:59:05 +00:00
@param ids : list of attendee ' s IDs
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 .
2013-11-15 16:59:05 +00:00
@param ids : list of attendee ' s IDs
2010-03-18 11:30:31 +00:00
"""
2010-10-21 06:50:03 +00:00
if context is None :
2010-03-18 11:30:31 +00:00
context = { }
2014-01-15 09:38:05 +00:00
meeting_obj = self . pool [ ' calendar.event ' ]
2013-10-10 13:21:00 +00:00
res = self . write ( cr , uid , ids , { ' state ' : ' accepted ' } , context )
2013-11-15 16:59:05 +00:00
for attendee in self . browse ( cr , uid , ids , context = context ) :
2014-05-14 08:28:10 +00:00
meeting_obj . message_post ( cr , uid , attendee . event_id . id , body = _ ( ( " %s has accepted invitation " ) % ( attendee . cn ) ) ,
subtype = " calendar.subtype_invitation " , context = context )
2014-01-10 17:09:12 +00:00
2013-10-10 13:21:00 +00:00
return res
2014-01-10 17:09:12 +00:00
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
"""
2010-10-21 06:50:03 +00:00
if context is None :
2010-07-13 11:17:53 +00:00
context = { }
2014-01-15 09:38:05 +00:00
meeting_obj = self . pool [ ' calendar.event ' ]
2013-10-10 13:21:00 +00:00
res = self . write ( cr , uid , ids , { ' state ' : ' declined ' } , context )
2013-11-26 18:01:06 +00:00
for attendee in self . browse ( cr , uid , ids , context = context ) :
2014-01-10 17:09:12 +00:00
meeting_obj . message_post ( cr , uid , attendee . event_id . id , body = _ ( ( " %s has declined invitation " ) % ( attendee . cn ) ) , subtype = " calendar.subtype_invitation " , 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 ( ' : ' )
2014-01-10 17:09:12 +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
2014-01-10 17:09:12 +00:00
class res_partner ( osv . Model ) :
2013-10-22 05:17:55 +00:00
_inherit = ' res.partner '
2013-11-23 11:36:27 +00:00
_columns = {
2014-01-14 13:37:36 +00:00
' calendar_last_notif_ack ' : fields . datetime ( ' Last notification marked as read from base Calendar ' ) ,
2014-01-10 17:09:12 +00:00
}
2013-10-22 05:17:55 +00:00
def get_attendee_detail ( self , cr , uid , ids , meeting_id , context = None ) :
2014-04-30 09:36:13 +00:00
"""
Return a list of tuple ( id , name , status )
Used by web_calendar . js : Many2ManyAttendee
"""
2013-10-22 05:17:55 +00:00
datas = [ ]
2014-07-06 14:44:26 +00:00
meeting = None
2013-10-22 05:17:55 +00:00
if meeting_id :
2014-01-15 09:38:05 +00:00
meeting = self . pool [ ' calendar.event ' ] . browse ( cr , uid , get_real_ids ( meeting_id ) , context = context )
2013-10-22 05:17:55 +00:00
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
2014-07-06 14:44:26 +00:00
def _set_calendar_last_notif_ack ( self , cr , uid , context = None ) :
2014-01-10 17:09:12 +00:00
partner = self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context = context ) . partner_id
2014-01-14 13:37:36 +00:00
self . write ( cr , uid , partner . id , { ' calendar_last_notif_ack ' : datetime . now ( ) } , context = context )
2014-01-10 17:09:12 +00:00
return
2013-12-02 14:52:42 +00:00
2013-11-23 11:36:27 +00:00
2014-01-13 17:41:57 +00:00
class calendar_alarm_manager ( osv . AbstractModel ) :
2013-11-23 11:36:27 +00:00
_name = ' calendar.alarm_manager '
2014-01-10 17:09:12 +00:00
def get_next_potential_limit_alarm ( self , cr , uid , seconds , notif = True , mail = True , partner_id = None , context = None ) :
2013-11-23 11:36:27 +00:00
res = { }
base_request = """
2014-01-10 17:09:12 +00:00
SELECT
2014-02-25 16:58:59 +00:00
cal . id ,
2014-05-05 15:42:46 +00:00
cal . start - interval ' 1 ' minute * calcul_delta . max_delta AS first_alarm ,
2014-01-10 17:09:12 +00:00
CASE
2014-05-05 15:42:46 +00:00
WHEN cal . recurrency THEN cal . final_date - interval ' 1 ' minute * calcul_delta . min_delta
ELSE cal . stop - interval ' 1 ' minute * calcul_delta . min_delta
2014-01-10 17:09:12 +00:00
END as last_alarm ,
2014-05-05 15:42:46 +00:00
cal . start as first_event_date ,
2014-01-10 17:09:12 +00:00
CASE
2014-05-05 15:42:46 +00:00
WHEN cal . recurrency THEN cal . final_date
ELSE cal . stop
2013-11-23 11:36:27 +00:00
END as last_event_date ,
calcul_delta . min_delta ,
calcul_delta . max_delta ,
2014-02-25 16:58:59 +00:00
cal . rrule AS rule
2014-01-10 17:09:12 +00:00
FROM
2014-02-25 16:58:59 +00:00
calendar_event AS cal
2013-11-23 11:36:27 +00:00
RIGHT JOIN
(
2014-01-10 17:09:12 +00:00
SELECT
2014-01-15 09:38:05 +00:00
rel . calendar_event_id , max ( alarm . duration_minutes ) AS max_delta , min ( alarm . duration_minutes ) AS min_delta
2013-11-23 11:36:27 +00:00
FROM
2014-01-15 09:38:05 +00:00
calendar_alarm_calendar_event_rel AS rel
2013-11-23 11:36:27 +00:00
LEFT JOIN calendar_alarm AS alarm ON alarm . id = rel . calendar_alarm_id
2014-01-10 17:09:12 +00:00
WHERE alarm . type in % s
2014-01-15 09:38:05 +00:00
GROUP BY rel . calendar_event_id
2014-02-25 16:58:59 +00:00
) AS calcul_delta ON calcul_delta . calendar_event_id = cal . id
2013-11-23 11:36:27 +00:00
"""
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
filter_user = """
2014-02-27 14:29:33 +00:00
RIGHT JOIN calendar_event_res_partner_rel AS part_rel ON part_rel . calendar_event_id = cal . id
2013-11-23 11:36:27 +00:00
AND part_rel . res_partner_id = % s
2010-03-25 12:07:00 +00:00
"""
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
#Add filter on type
2014-01-10 17:09:12 +00:00
type_to_read = ( )
2013-11-23 11:36:27 +00:00
if notif :
type_to_read + = ( ' notification ' , )
if mail :
type_to_read + = ( ' email ' , )
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
tuple_params = ( type_to_read , )
2014-01-10 17:09:12 +00:00
2014-04-30 09:36:13 +00:00
# ADD FILTER ON PARTNER_ID
2013-11-23 11:36:27 +00:00
if partner_id :
base_request + = filter_user
tuple_params + = ( partner_id , )
2010-07-02 13:30:13 +00:00
2013-11-23 11:36:27 +00:00
#Add filter on hours
2015-02-11 20:31:20 +00:00
tuple_params + = ( seconds , )
2014-01-10 17:09:12 +00:00
2014-02-25 16:58:59 +00:00
cr . execute ( """ SELECT *
2014-04-30 09:36:13 +00:00
FROM ( % s WHERE cal . active = True ) AS ALL_EVENTS
2014-02-25 16:58:59 +00:00
WHERE ALL_EVENTS . first_alarm < ( now ( ) at time zone ' utc ' + interval ' %% s ' second )
2015-02-11 20:31:20 +00:00
AND ALL_EVENTS . last_event_date > ( now ( ) at time zone ' utc ' )
2014-02-25 16:58:59 +00:00
""" % base_request, tuple_params)
2014-01-10 17:09:12 +00:00
for event_id , first_alarm , last_alarm , first_meeting , last_meeting , min_duration , max_duration , rule in cr . fetchall ( ) :
2014-02-25 16:58:59 +00:00
res [ event_id ] = {
2014-01-10 17:09:12 +00:00
' event_id ' : event_id ,
' first_alarm ' : first_alarm ,
' last_alarm ' : last_alarm ,
' first_meeting ' : first_meeting ,
' last_meeting ' : last_meeting ,
' min_duration ' : min_duration ,
' max_duration ' : max_duration ,
' rrule ' : rule
2014-02-25 16:58:59 +00:00
}
2013-12-09 14:08:19 +00:00
2013-11-23 11:36:27 +00:00
return res
2014-01-10 17:09:12 +00:00
2015-02-11 20:31:20 +00:00
def do_check_alarm_for_one_date ( self , cr , uid , one_date , event , event_maxdelta , in_the_next_X_seconds , after = False , notif = True , mail = True , missing = False , context = None ) :
# one_date: date of the event to check (not the same that in the event browse if recurrent)
# event: Event browse record
# event_maxdelta: biggest duration from alarms for this event
# in_the_next_X_seconds: looking in the future (in seconds)
# after: if not False: will return alert if after this date (date as string - todo: change in master)
# missing: if not False: will return alert even if we are too late
# notif: Looking for type notification
# mail: looking for type email
2013-11-23 11:36:27 +00:00
res = [ ]
2014-01-10 17:09:12 +00:00
2015-02-11 20:31:20 +00:00
# TODO: replace notif and email in master by alarm_type + remove event_maxdelta and if using it
alarm_type = [ ]
2013-11-23 11:36:27 +00:00
if notif :
alarm_type . append ( ' notification ' )
if mail :
alarm_type . append ( ' email ' )
2014-01-10 17:09:12 +00:00
2015-02-11 20:31:20 +00:00
if one_date - timedelta ( minutes = ( missing and 0 or event_maxdelta ) ) < datetime . now ( ) + timedelta ( seconds = in_the_next_X_seconds ) : # if an alarm is possible for this date
2013-11-23 11:36:27 +00:00
for alarm in event . alarm_ids :
if alarm . type in alarm_type and \
2015-02-11 20:31:20 +00:00
one_date - timedelta ( minutes = ( missing and 0 or alarm . duration_minutes ) ) < datetime . now ( ) + timedelta ( seconds = in_the_next_X_seconds ) and \
( not after or one_date - timedelta ( minutes = alarm . duration_minutes ) > openerp . fields . Datetime . from_string ( after ) ) :
2014-01-10 17:09:12 +00:00
alert = {
' alarm_id ' : alarm . id ,
' event_id ' : event . id ,
' notify_at ' : one_date - timedelta ( minutes = alarm . duration_minutes ) ,
}
res . append ( alert )
2013-11-23 11:36:27 +00:00
return res
2014-02-24 22:02:22 +00:00
def get_next_mail ( self , cr , uid , context = None ) :
2015-02-11 20:31:20 +00:00
now = openerp . fields . Datetime . to_string ( datetime . now ( ) )
icp = self . pool [ ' ir.config_parameter ' ]
last_notif_mail = icp . get_param ( cr , SUPERUSER_ID , ' calendar.last_notif_mail ' , default = False ) or now
2014-06-12 13:08:33 +00:00
try :
2015-02-11 20:31:20 +00:00
cron = self . pool [ ' ir.model.data ' ] . get_object ( cr , uid , ' calendar ' , ' ir_cron_scheduler_alarm ' , context = context )
2014-06-12 13:08:33 +00:00
except ValueError :
_logger . error ( " Cron for " + self . _name + " can not be identified ! " )
return False
2014-01-13 17:41:57 +00:00
2015-02-11 20:31:20 +00:00
interval_to_second = {
" weeks " : 7 * 24 * 60 * 60 ,
" days " : 24 * 60 * 60 ,
" hours " : 60 * 60 ,
" minutes " : 60 ,
" seconds " : 1
}
if cron . interval_type not in interval_to_second . keys ( ) :
2014-06-12 13:08:33 +00:00
_logger . error ( " Cron delay can not be computed ! " )
return False
2014-01-13 17:41:57 +00:00
2015-02-11 20:31:20 +00:00
cron_interval = cron . interval_number * interval_to_second [ cron . interval_type ]
2014-02-24 22:02:22 +00:00
all_events = self . get_next_potential_limit_alarm ( cr , uid , cron_interval , notif = False , context = context )
2014-01-13 17:41:57 +00:00
2015-02-11 20:31:20 +00:00
for curEvent in self . pool . get ( ' calendar.event ' ) . browse ( cr , uid , all_events . keys ( ) , context = context ) :
max_delta = all_events [ curEvent . id ] [ ' max_duration ' ]
2013-11-23 11:36:27 +00:00
if curEvent . recurrency :
2015-02-11 20:31:20 +00:00
at_least_one = False
last_found = False
2014-02-24 22:02:22 +00:00
for one_date in self . pool . get ( ' calendar.event ' ) . get_recurrent_date_by_event ( cr , uid , curEvent , context = context ) :
2014-03-14 16:56:41 +00:00
in_date_format = one_date . replace ( tzinfo = None )
2015-02-11 20:31:20 +00:00
last_found = self . do_check_alarm_for_one_date ( cr , uid , in_date_format , curEvent , max_delta , 0 , after = last_notif_mail , notif = False , missing = True , context = context )
for alert in last_found :
self . do_mail_reminder ( cr , uid , alert , context = context )
at_least_one = True # if it's the first alarm for this recurrent event
if at_least_one and not last_found : # if the precedent event had an alarm but not this one, we can stop the search for this event
2014-01-10 17:09:12 +00:00
break
2010-07-02 13:30:13 +00:00
else :
2014-05-05 15:42:46 +00:00
in_date_format = datetime . strptime ( curEvent . start , DEFAULT_SERVER_DATETIME_FORMAT )
2015-02-11 20:31:20 +00:00
last_found = self . do_check_alarm_for_one_date ( cr , uid , in_date_format , curEvent , max_delta , 0 , after = last_notif_mail , notif = False , missing = True , context = context )
for alert in last_found :
self . do_mail_reminder ( cr , uid , alert , context = context )
icp . set_param ( cr , SUPERUSER_ID , ' calendar.last_notif_mail ' , now )
2014-01-13 17:41:57 +00:00
2014-02-24 22:02:22 +00:00
def get_next_notif ( self , cr , uid , context = None ) :
2014-01-13 17:41:57 +00:00
ajax_check_every_seconds = 300
2015-05-20 13:49:36 +00:00
partner = self . pool [ ' res.users ' ] . read ( cr , SUPERUSER_ID , uid , [ ' partner_id ' , ' calendar_last_notif_ack ' ] , context = context )
2014-01-13 17:41:57 +00:00
all_notif = [ ]
2014-02-24 10:48:50 +00:00
2014-02-24 22:02:22 +00:00
if not partner :
2014-02-24 10:48:50 +00:00
return [ ]
2015-05-20 13:49:36 +00:00
all_events = self . get_next_potential_limit_alarm ( cr , uid , ajax_check_every_seconds , partner_id = partner [ ' partner_id ' ] [ 0 ] , mail = False , context = context )
2014-01-13 17:41:57 +00:00
for event in all_events : # .values()
2014-02-24 22:02:22 +00:00
max_delta = all_events [ event ] [ ' max_duration ' ]
curEvent = self . pool . get ( ' calendar.event ' ) . browse ( cr , uid , event , context = context )
2014-01-13 17:41:57 +00:00
if curEvent . recurrency :
bFound = False
LastFound = False
2014-02-24 22:02:22 +00:00
for one_date in self . pool . get ( " calendar.event " ) . get_recurrent_date_by_event ( cr , uid , curEvent , context = context ) :
2014-03-14 16:56:41 +00:00
in_date_format = one_date . replace ( tzinfo = None )
2015-05-12 10:20:35 +00:00
LastFound = self . do_check_alarm_for_one_date ( cr , uid , in_date_format , curEvent , max_delta , ajax_check_every_seconds , after = partner [ ' calendar_last_notif_ack ' ] , mail = False , context = context )
2014-01-13 17:41:57 +00:00
if LastFound :
for alert in LastFound :
2014-02-24 22:02:22 +00:00
all_notif . append ( self . do_notif_reminder ( cr , uid , alert , context = context ) )
if not bFound : # if it's the first alarm for this recurrent event
bFound = True
if bFound and not LastFound : # if the precedent event had alarm but not this one, we can stop the search fot this event
2014-01-13 17:41:57 +00:00
break
else :
2014-05-05 15:42:46 +00:00
in_date_format = datetime . strptime ( curEvent . start , DEFAULT_SERVER_DATETIME_FORMAT )
2015-05-12 10:20:35 +00:00
LastFound = self . do_check_alarm_for_one_date ( cr , uid , in_date_format , curEvent , max_delta , ajax_check_every_seconds , after = partner [ ' calendar_last_notif_ack ' ] , mail = False , context = context )
2014-01-13 17:41:57 +00:00
if LastFound :
for alert in LastFound :
2014-02-24 22:02:22 +00:00
all_notif . append ( self . do_notif_reminder ( cr , uid , alert , context = context ) )
return all_notif
2014-01-13 17:41:57 +00:00
2014-01-10 17:09:12 +00:00
def do_mail_reminder ( self , cr , uid , alert , context = None ) :
2013-11-23 11:36:27 +00:00
if context is None :
context = { }
2013-11-27 12:33:29 +00:00
res = False
2014-01-10 17:09:12 +00:00
2014-01-15 09:38:05 +00:00
event = self . pool [ ' calendar.event ' ] . browse ( cr , uid , alert [ ' event_id ' ] , context = context )
2014-01-10 17:09:12 +00:00
alarm = self . pool [ ' calendar.alarm ' ] . browse ( cr , uid , alert [ ' alarm_id ' ] , context = context )
2013-11-23 11:36:27 +00:00
if alarm . type == ' email ' :
2015-02-06 13:01:45 +00:00
res = self . pool [ ' calendar.attendee ' ] . _send_mail_to_attendees (
cr ,
uid ,
[ att . id for att in event . attendee_ids ] ,
2015-02-11 20:31:20 +00:00
email_from = event . user_id . partner_id . email ,
2015-02-06 13:01:45 +00:00
template_xmlid = ' calendar_template_meeting_reminder ' ,
force = True ,
context = context
)
2014-01-15 09:38:05 +00:00
2013-11-27 12:33:29 +00:00
return res
2010-01-21 08:14:58 +00:00
2014-01-10 17:09:12 +00:00
def do_notif_reminder ( self , cr , uid , alert , context = None ) :
alarm = self . pool [ ' calendar.alarm ' ] . browse ( cr , uid , alert [ ' alarm_id ' ] , context = context )
2014-01-15 09:38:05 +00:00
event = self . pool [ ' calendar.event ' ] . browse ( cr , uid , alert [ ' event_id ' ] , context = context )
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
if alarm . type == ' notification ' :
2014-01-10 17:09:12 +00:00
message = event . display_time
2013-11-23 11:36:27 +00:00
delta = alert [ ' notify_at ' ] - datetime . now ( )
delta = delta . seconds + delta . days * 3600 * 24
2013-12-18 13:39:39 +00:00
2014-01-10 17:09:12 +00:00
return {
' event_id ' : event . id ,
' title ' : event . name ,
' message ' : message ,
' timer ' : delta ,
2014-04-30 09:36:13 +00:00
' notify_at ' : alert [ ' notify_at ' ] . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) ,
2014-01-10 17:09:12 +00:00
}
2013-11-15 16:59:05 +00:00
2013-11-23 11:36:27 +00:00
2014-01-10 17:09:12 +00:00
class calendar_alarm ( osv . Model ) :
2013-11-08 16:05:49 +00:00
_name = ' calendar.alarm '
_description = ' Event alarm '
2011-12-11 20:12:37 +00:00
2013-11-23 11:36:27 +00:00
def _get_duration ( self , cr , uid , ids , field_name , arg , context = None ) :
res = { }
for alarm in self . browse ( cr , uid , ids , context = context ) :
if alarm . interval == " minutes " :
res [ alarm . id ] = alarm . duration
elif alarm . interval == " hours " :
res [ alarm . id ] = alarm . duration * 60
elif alarm . interval == " days " :
res [ alarm . id ] = alarm . duration * 60 * 24
else :
res [ alarm . id ] = 0
return res
2010-01-21 08:14:58 +00:00
_columns = {
2014-04-30 09:36:13 +00:00
' name ' : fields . char ( ' Name ' , required = True ) ,
2013-11-08 16:05:49 +00:00
' 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 ) ,
2015-07-28 12:06:52 +00:00
' duration_minutes ' : fields . function ( _get_duration , type = ' integer ' , string = ' Duration in minutes ' , store = True ) ,
2014-01-10 17:09:12 +00:00
}
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
}
2010-02-11 12:37:41 +00:00
2014-06-12 13:08:33 +00:00
def _update_cron ( self , cr , uid , context = None ) :
try :
cron = self . pool [ ' ir.model.data ' ] . get_object (
2015-05-19 09:03:47 +00:00
cr , SUPERUSER_ID , ' calendar ' , ' ir_cron_scheduler_alarm ' , context = context )
2014-06-12 13:08:33 +00:00
except ValueError :
return False
return cron . toggle ( model = self . _name , domain = [ ( ' type ' , ' = ' , ' email ' ) ] )
def create ( self , cr , uid , values , context = None ) :
res = super ( calendar_alarm , self ) . create ( cr , uid , values , context = context )
self . _update_cron ( cr , uid , context = context )
return res
def write ( self , cr , uid , ids , values , context = None ) :
res = super ( calendar_alarm , self ) . write ( cr , uid , ids , values , context = context )
self . _update_cron ( cr , uid , context = context )
return res
def unlink ( self , cr , uid , ids , context = None ) :
res = super ( calendar_alarm , self ) . unlink ( cr , uid , ids , context = context )
self . _update_cron ( cr , uid , context = context )
return res
2014-01-10 17:09:12 +00:00
class ir_values ( osv . Model ) :
2010-02-11 12:37:41 +00:00
_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 ) :
2013-12-19 14:47:39 +00:00
new_model . append ( ( data [ 0 ] , 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 )
2014-01-10 17:09:12 +00:00
return super ( ir_values , self ) . set ( cr , uid , key , key2 , name , new_model ,
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 ) :
2013-12-19 14:47:39 +00:00
new_model . append ( ( data [ 0 ] , 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 )
2014-01-10 17:09:12 +00:00
return super ( ir_values , self ) . get ( cr , uid , key , key2 , new_model ,
meta , context , res_id_req , without_user , key2_req )
2010-02-11 12:37:41 +00:00
2013-11-12 08:18:57 +00:00
2014-01-10 17:09:12 +00:00
class ir_model ( osv . Model ) :
2009-12-18 13:44:31 +00:00
2010-02-11 12:37:41 +00:00
_inherit = ' ir.model '
2013-11-12 08:18:57 +00:00
def read ( self , cr , uid , ids , fields = None , context = None , load = ' _classic_read ' ) :
2014-12-31 10:56:28 +00:00
new_ids = isinstance ( ids , ( basestring , 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 = { }
2014-01-10 17:09:12 +00:00
data = super ( ir_model , self ) . read ( cr , uid , new_ids , fields = fields , context = context , load = load )
2010-02-11 12:37:41 +00:00
if data :
for val in data :
2013-12-19 14:47:39 +00:00
val [ ' id ' ] = calendar_id2real_id ( val [ ' id ' ] )
2014-12-31 10:56:28 +00:00
return isinstance ( ids , ( basestring , 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
2014-01-10 17:09:12 +00:00
2015-06-18 17:29:47 +00:00
def exp_report ( db , uid , object , ids , datas = None , context = None ) :
2013-01-30 15:55:01 +00:00
"""
Export Report
"""
if object == ' printscreen.list ' :
2015-06-18 17:29:47 +00:00
original_exp_report ( db , uid , object , ids , datas , context )
2013-01-30 15:55:01 +00:00
new_ids = [ ]
for id in ids :
2013-12-19 14:47:39 +00:00
new_ids . append ( calendar_id2real_id ( id ) )
2015-06-18 17:29:47 +00:00
if datas . get ( ' id ' , False ) :
datas [ ' id ' ] = calendar_id2real_id ( datas [ ' id ' ] )
return original_exp_report ( db , uid , object , new_ids , datas , context )
2010-02-11 12:37:41 +00:00
2014-01-10 17:09:12 +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
2014-01-15 09:38:05 +00:00
class calendar_event_type ( osv . Model ) :
_name = ' calendar.event.type '
2013-11-23 11:36:27 +00:00
_description = ' Meeting Type '
_columns = {
2014-01-10 17:09:12 +00:00
' name ' : fields . char ( ' Name ' , required = True , translate = True ) ,
2013-11-23 11:36:27 +00:00
}
2013-12-09 14:08:19 +00:00
2014-01-15 09:38:05 +00:00
class calendar_event ( osv . Model ) :
""" Model for Calendar Event """
_name = ' calendar.event '
2014-04-30 09:36:13 +00:00
_description = " Event "
2013-11-23 11:36:27 +00:00
_order = " id desc "
_inherit = [ " mail.thread " , " ir.needaction_mixin " ]
2014-01-10 17:09:12 +00:00
def do_run_scheduler ( self , cr , uid , id , context = None ) :
2014-04-14 20:29:36 +00:00
self . pool [ ' calendar.alarm_manager ' ] . get_next_mail ( cr , uid , context = context )
2014-01-10 17:09:12 +00:00
def get_recurrent_date_by_event ( self , cr , uid , event , context = None ) :
2013-12-09 14:08:19 +00:00
""" Get recurrent dates based on Rule string and all event where recurrent_id is child
"""
def todate ( date ) :
val = parser . parse ( ' ' . join ( ( re . compile ( ' \ d ' ) ) . findall ( date ) ) )
## Dates are localized to saved timezone if any, else current timezone.
if not val . tzinfo :
val = pytz . UTC . localize ( val )
return val . astimezone ( timezone )
2014-01-10 17:09:12 +00:00
2015-05-11 08:40:19 +00:00
if context is None :
context = { }
2014-04-30 09:36:13 +00:00
timezone = pytz . timezone ( context . get ( ' tz ' ) or ' UTC ' )
2014-05-05 15:42:46 +00:00
startdate = pytz . UTC . localize ( datetime . strptime ( event . start , DEFAULT_SERVER_DATETIME_FORMAT ) ) # Add "+hh:mm" timezone
2013-12-09 14:08:19 +00:00
if not startdate :
startdate = datetime . now ( )
2014-01-10 17:09:12 +00:00
2013-12-09 14:08:19 +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.
2014-01-10 17:09:12 +00:00
startdate = startdate . astimezone ( timezone ) # transform "+hh:mm" timezone
2013-12-09 14:08:19 +00:00
rset1 = rrule . rrulestr ( str ( event . rrule ) , dtstart = startdate , forceset = True )
2014-01-10 17:09:12 +00:00
ids_depending = self . search ( cr , uid , [ ( ' recurrent_id ' , ' = ' , event . id ) , ' | ' , ( ' active ' , ' = ' , False ) , ( ' active ' , ' = ' , True ) ] , context = context )
all_events = self . browse ( cr , uid , ids_depending , context = context )
for ev in all_events :
2013-12-09 14:08:19 +00:00
rset1 . _exdate . append ( todate ( ev . recurrent_id_date ) )
2014-01-10 17:09:12 +00:00
return [ d . astimezone ( pytz . UTC ) for d in rset1 ]
2014-04-30 09:36:13 +00:00
def _get_recurrency_end_date ( self , cr , uid , id , context = None ) :
2016-12-20 20:08:28 +00:00
data = self . read ( cr , uid , id , [ ' final_date ' , ' recurrency ' , ' rrule_type ' , ' count ' , ' end_type ' , ' stop ' , ' interval ' ] , context = context )
2014-04-30 09:36:13 +00:00
2014-03-14 10:57:53 +00:00
if not data . get ( ' recurrency ' ) :
return False
end_type = data . get ( ' end_type ' )
2014-05-05 15:42:46 +00:00
final_date = data . get ( ' final_date ' )
2016-12-20 20:08:28 +00:00
if end_type == ' count ' and all ( data . get ( key ) for key in [ ' count ' , ' rrule_type ' , ' stop ' , ' interval ' ] ) :
count = ( data [ ' count ' ] + 1 ) * data [ ' interval ' ]
2014-03-14 10:57:53 +00:00
delay , mult = {
' daily ' : ( ' days ' , 1 ) ,
' weekly ' : ( ' days ' , 7 ) ,
' monthly ' : ( ' months ' , 1 ) ,
' yearly ' : ( ' years ' , 1 ) ,
} [ data [ ' rrule_type ' ] ]
2014-05-05 15:42:46 +00:00
deadline = datetime . strptime ( data [ ' stop ' ] , tools . DEFAULT_SERVER_DATETIME_FORMAT )
2014-03-14 10:57:53 +00:00
return deadline + relativedelta ( * * { delay : count * mult } )
2014-04-30 09:36:13 +00:00
return final_date
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
def _find_my_attendee ( self , cr , uid , meeting_ids , context = None ) :
"""
Return the first attendee where the user connected has been invited from all the meeting_ids in parameters
"""
2014-01-10 17:09:12 +00:00
user = self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context = context )
2013-11-23 11:36:27 +00:00
for meeting_id in meeting_ids :
2014-01-10 17:09:12 +00:00
for attendee in self . browse ( cr , uid , meeting_id , context ) . attendee_ids :
2013-11-23 11:36:27 +00:00
if user . partner_id . id == attendee . partner_id . id :
return attendee
return False
2014-01-10 17:09:12 +00:00
2014-05-05 10:46:11 +00:00
def get_date_formats ( self , cr , uid , context ) :
lang = context . get ( " lang " )
res_lang = self . pool . get ( ' res.lang ' )
lang_params = { }
if lang :
ids = res_lang . search ( request . cr , uid , [ ( " code " , " = " , lang ) ] )
if ids :
lang_params = res_lang . read ( request . cr , uid , ids [ 0 ] , [ " date_format " , " time_format " ] )
2014-11-20 17:16:31 +00:00
# formats will be used for str{f,p}time() which do not support unicode in Python 2, coerce to str
format_date = lang_params . get ( " date_format " , ' % B- %d - % Y ' ) . encode ( ' utf-8 ' )
format_time = lang_params . get ( " time_format " , ' % I- % M % p ' ) . encode ( ' utf-8 ' )
2014-05-05 10:46:11 +00:00
return ( format_date , format_time )
def get_display_time_tz ( self , cr , uid , ids , tz = False , context = None ) :
2014-07-06 14:44:26 +00:00
context = dict ( context or { } )
2014-05-05 10:46:11 +00:00
if tz :
context [ " tz " ] = tz
ev = self . browse ( cr , uid , ids , context = context ) [ 0 ]
2014-05-05 15:42:46 +00:00
return self . _get_display_time ( cr , uid , ev . start , ev . stop , ev . duration , ev . allday , context = context )
2014-05-05 10:46:11 +00:00
2014-05-05 15:42:46 +00:00
def _get_display_time ( self , cr , uid , start , stop , zduration , zallday , context = None ) :
2013-11-23 11:36:27 +00:00
"""
Return date and time ( from to from ) based on duration with timezone in string :
eg .
2014-04-07 09:51:27 +00:00
1 ) if user add duration for 2 hours , return : August - 23 - 2013 at ( 04 - 30 To 06 - 30 ) ( Europe / Brussels )
2013-11-23 11:36:27 +00:00
2 ) if event all day , return : AllDay , July - 31 - 2013
"""
2014-07-06 14:44:26 +00:00
context = dict ( context or { } )
2014-01-10 17:09:12 +00:00
tz = context . get ( ' tz ' , False )
if not tz : # tz can have a value False, so dont do it in the default value of get !
2014-05-05 10:46:11 +00:00
context [ ' tz ' ] = self . pool . get ( ' res.users ' ) . read ( cr , SUPERUSER_ID , uid , [ ' tz ' ] ) [ ' tz ' ]
tz = context [ ' tz ' ]
2014-12-12 18:09:12 +00:00
tz = tools . ustr ( tz ) . encode ( ' utf-8 ' ) # make safe for str{p,f}time()
2014-01-10 17:09:12 +00:00
2014-05-05 10:46:11 +00:00
format_date , format_time = self . get_date_formats ( cr , uid , context = context )
2014-05-05 15:42:46 +00:00
date = fields . datetime . context_timestamp ( cr , uid , datetime . strptime ( start , tools . DEFAULT_SERVER_DATETIME_FORMAT ) , context = context )
date_deadline = fields . datetime . context_timestamp ( cr , uid , datetime . strptime ( stop , tools . DEFAULT_SERVER_DATETIME_FORMAT ) , context = context )
2014-05-05 10:46:11 +00:00
event_date = date . strftime ( format_date )
display_time = date . strftime ( format_time )
2014-04-30 09:36:13 +00:00
if zallday :
2014-01-10 17:09:12 +00:00
time = _ ( " AllDay , %s " ) % ( event_date )
2014-04-30 09:36:13 +00:00
elif zduration < 24 :
duration = date + timedelta ( hours = zduration )
2015-11-25 13:35:02 +00:00
time = _ ( " %s at ( %s To %s ) ( %s ) " ) % ( event_date , display_time , duration . strftime ( format_time ) , tz )
2014-01-10 17:09:12 +00:00
else :
2015-11-25 13:35:02 +00:00
time = _ ( " %s at %s To \n %s at %s ( %s ) " ) % ( event_date , display_time , date_deadline . strftime ( format_date ) , date_deadline . strftime ( format_time ) , tz )
2013-11-23 11:36:27 +00:00
return time
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
def _compute ( self , cr , uid , ids , fields , arg , context = None ) :
res = { }
2014-06-25 13:03:11 +00:00
if not isinstance ( fields , list ) :
fields = [ fields ]
2014-08-05 15:49:47 +00:00
for meeting in self . browse ( cr , uid , ids , context = context ) :
meeting_data = { }
res [ meeting . id ] = meeting_data
attendee = self . _find_my_attendee ( cr , uid , [ meeting . id ] , context )
2013-11-23 11:36:27 +00:00
for field in fields :
if field == ' is_attendee ' :
2014-08-05 15:49:47 +00:00
meeting_data [ field ] = bool ( attendee )
2013-11-23 11:36:27 +00:00
elif field == ' attendee_status ' :
2014-08-05 15:49:47 +00:00
meeting_data [ field ] = attendee . state if attendee else ' needsAction '
2013-11-23 11:36:27 +00:00
elif field == ' display_time ' :
2014-08-05 15:49:47 +00:00
meeting_data [ field ] = self . _get_display_time ( cr , uid , meeting . start , meeting . stop , meeting . duration , meeting . allday , context = context )
2014-04-30 09:36:13 +00:00
elif field == " display_start " :
2014-08-05 15:49:47 +00:00
meeting_data [ field ] = meeting . start_date if meeting . allday else meeting . start_datetime
2014-05-05 15:42:46 +00:00
elif field == ' start ' :
2014-08-05 15:49:47 +00:00
meeting_data [ field ] = meeting . start_date if meeting . allday else meeting . start_datetime
2014-05-05 15:42:46 +00:00
elif field == ' stop ' :
2014-08-05 15:49:47 +00:00
meeting_data [ field ] = meeting . stop_date if meeting . allday else meeting . stop_datetime
2013-11-23 11:36:27 +00:00
return res
2014-01-10 17:09:12 +00:00
2016-01-08 17:08:35 +00:00
def _get_recurrent_fields ( self , cr , uid , context = None ) :
return [ ' byday ' , ' recurrency ' , ' final_date ' , ' rrule_type ' , ' month_by ' ,
' interval ' , ' count ' , ' end_type ' , ' mo ' , ' tu ' , ' we ' , ' th ' , ' fr ' , ' sa ' ,
' su ' , ' day ' , ' week_list ' ]
2013-11-23 11:36:27 +00:00
def _get_rulestring ( self , cr , uid , ids , name , arg , context = None ) :
"""
Gets Recurrence rule string according to value type RECUR of iCalendar from the values given .
@return : dictionary of rrule value .
"""
result = { }
if not isinstance ( ids , list ) :
ids = [ ids ]
2014-08-05 15:22:56 +00:00
#read these fields as SUPERUSER because if the record is private a normal search could raise an error
2016-01-08 17:08:35 +00:00
recurrent_fields = self . _get_recurrent_fields ( cr , uid , context = context )
events = self . read ( cr , SUPERUSER_ID , ids , recurrent_fields , context = context )
2014-08-05 15:22:56 +00:00
for event in events :
if event [ ' recurrency ' ] :
result [ event [ ' id ' ] ] = self . compute_rule_string ( event )
2013-11-23 11:36:27 +00:00
else :
2014-08-05 15:22:56 +00:00
result [ event [ ' id ' ] ] = ' '
2013-11-23 11:36:27 +00:00
return result
2014-02-24 22:02:22 +00:00
2014-03-13 17:09:40 +00:00
# retro compatibility function
2013-12-09 14:08:19 +00:00
def _rrule_write ( self , cr , uid , ids , field_name , field_value , args , context = None ) :
2014-03-13 17:09:40 +00:00
return self . _set_rulestring ( self , cr , uid , ids , field_name , field_value , args , context = context )
def _set_rulestring ( self , cr , uid , ids , field_name , field_value , args , context = None ) :
2013-12-09 14:08:19 +00:00
if not isinstance ( ids , list ) :
ids = [ ids ]
2013-11-23 11:36:27 +00:00
data = self . _get_empty_rrule_data ( )
if field_value :
data [ ' recurrency ' ] = True
for event in self . browse ( cr , uid , ids , context = context ) :
2014-05-05 15:42:46 +00:00
rdate = event . start
2013-11-23 11:36:27 +00:00
update_data = self . _parse_rrule ( field_value , dict ( data ) , rdate )
data . update ( update_data )
self . write ( cr , uid , ids , data , context = context )
return True
2014-02-24 22:02:22 +00:00
2014-04-30 09:36:13 +00:00
def _set_date ( self , cr , uid , values , id = False , context = None ) :
if context is None :
context = { }
2014-05-05 15:42:46 +00:00
if values . get ( ' start_datetime ' ) or values . get ( ' start_date ' ) or values . get ( ' start ' ) \
or values . get ( ' stop_datetime ' ) or values . get ( ' stop_date ' ) or values . get ( ' stop ' ) :
2014-04-30 09:36:13 +00:00
allday = values . get ( " allday " , None )
2015-01-08 11:21:03 +00:00
event = self . browse ( cr , uid , id , context = context )
2014-04-30 09:36:13 +00:00
if allday is None :
if id :
2015-01-08 11:21:03 +00:00
allday = event . allday
2014-04-30 09:36:13 +00:00
else :
allday = False
_logger . warning ( " Calendar - All day is not specified, arbitrarily set to False " )
#raise osv.except_osv(_('Error!'), ("Need to know if it's an allday or not..."))
key = " date " if allday else " datetime "
notkey = " datetime " if allday else " date "
2014-05-05 15:42:46 +00:00
for fld in ( ' start ' , ' stop ' ) :
2014-04-30 09:36:13 +00:00
if values . get ( ' %s _ %s ' % ( fld , key ) ) or values . get ( fld ) :
values [ ' %s _ %s ' % ( fld , key ) ] = values . get ( ' %s _ %s ' % ( fld , key ) ) or values . get ( fld )
values [ ' %s _ %s ' % ( fld , notkey ) ] = None
if fld not in values . keys ( ) :
values [ fld ] = values [ ' %s _ %s ' % ( fld , key ) ]
diff = False
2015-01-08 11:21:03 +00:00
if allday and ( values . get ( ' stop_date ' ) or values . get ( ' start_date ' ) ) :
stop_date = values . get ( ' stop_date ' ) or event . stop_date
start_date = values . get ( ' start_date ' ) or event . start_date
if stop_date and start_date :
2015-02-11 20:28:38 +00:00
diff = openerp . fields . Date . from_string ( stop_date ) - openerp . fields . Date . from_string ( start_date )
2015-01-08 11:21:03 +00:00
elif values . get ( ' stop_datetime ' ) or values . get ( ' start_datetime ' ) :
stop_datetime = values . get ( ' stop_datetime ' ) or event . stop_datetime
start_datetime = values . get ( ' start_datetime ' ) or event . start_datetime
if stop_datetime and start_datetime :
2015-02-11 20:28:38 +00:00
diff = openerp . fields . Datetime . from_string ( stop_datetime ) - openerp . fields . Datetime . from_string ( start_datetime )
2014-04-30 09:36:13 +00:00
if diff :
duration = float ( diff . days ) * 24 + ( float ( diff . seconds ) / 3600 )
values [ ' duration ' ] = round ( duration , 2 )
2013-11-23 11:36:27 +00:00
2013-11-24 13:02:41 +00:00
_track = {
' location ' : {
2013-12-19 14:47:39 +00:00
' calendar.subtype_invitation ' : lambda self , cr , uid , obj , ctx = None : True ,
2013-11-26 11:45:02 +00:00
} ,
2014-05-05 15:42:46 +00:00
' start ' : {
2013-12-19 14:47:39 +00:00
' calendar.subtype_invitation ' : lambda self , cr , uid , obj , ctx = None : True ,
2013-11-24 13:02:41 +00:00
} ,
}
2013-11-23 11:36:27 +00:00
_columns = {
2014-02-18 17:15:08 +00:00
' id ' : fields . integer ( ' ID ' , readonly = True ) ,
2014-01-10 17:09:12 +00:00
' state ' : fields . selection ( [ ( ' draft ' , ' Unconfirmed ' ) , ( ' open ' , ' Confirmed ' ) ] , string = ' Status ' , readonly = True , track_visibility = ' onchange ' ) ,
' name ' : fields . char ( ' Meeting Subject ' , required = True , states = { ' done ' : [ ( ' readonly ' , True ) ] } ) ,
2013-11-23 11:36:27 +00:00
' is_attendee ' : fields . function ( _compute , string = ' Attendee ' , type = " boolean " , multi = ' attendee ' ) ,
2014-01-20 12:59:53 +00:00
' attendee_status ' : fields . function ( _compute , string = ' Attendee Status ' , type = " selection " , selection = calendar_attendee . STATE_SELECTION , multi = ' attendee ' ) ,
2013-11-23 11:36:27 +00:00
' display_time ' : fields . function ( _compute , string = ' Event Time ' , type = " char " , multi = ' attendee ' ) ,
2014-08-05 15:49:47 +00:00
' display_start ' : fields . function ( _compute , string = ' Date ' , type = " char " , multi = ' attendee ' , store = True ) ,
2014-04-30 09:36:13 +00:00
' allday ' : fields . boolean ( ' All Day ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } ) ,
2014-08-05 15:49:47 +00:00
' start ' : fields . function ( _compute , string = ' Calculated start ' , type = " datetime " , multi = ' attendee ' , store = True , required = True ) ,
' stop ' : fields . function ( _compute , string = ' Calculated stop ' , type = " datetime " , multi = ' attendee ' , store = True , required = True ) ,
2014-05-05 15:42:46 +00:00
' start_date ' : fields . date ( ' Start Date ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } , track_visibility = ' onchange ' ) ,
' start_datetime ' : fields . datetime ( ' Start DateTime ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } , track_visibility = ' onchange ' ) ,
' stop_date ' : fields . date ( ' End Date ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } , track_visibility = ' onchange ' ) ,
' stop_datetime ' : fields . datetime ( ' End Datetime ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } , track_visibility = ' onchange ' ) , # old date_deadline
2013-11-23 11:36:27 +00:00
' duration ' : fields . float ( ' Duration ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } ) ,
' description ' : fields . text ( ' Description ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } ) ,
' class ' : fields . selection ( [ ( ' public ' , ' Public ' ) , ( ' private ' , ' Private ' ) , ( ' confidential ' , ' Public for Employees ' ) ] , ' Privacy ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } ) ,
2014-01-10 17:09:12 +00:00
' location ' : fields . char ( ' Location ' , help = " Location of Event " , track_visibility = ' onchange ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } ) ,
' show_as ' : fields . selection ( [ ( ' free ' , ' Free ' ) , ( ' busy ' , ' Busy ' ) ] , ' Show Time as ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } ) ,
2014-04-30 09:36:13 +00:00
# RECURRENCE FIELD
2014-03-13 17:09:40 +00:00
' rrule ' : fields . function ( _get_rulestring , type = ' char ' , fnct_inv = _set_rulestring , store = True , string = ' Recurrent Rule ' ) ,
2014-01-10 17:09:12 +00:00
' rrule_type ' : fields . selection ( [ ( ' daily ' , ' Day(s) ' ) , ( ' weekly ' , ' Week(s) ' ) , ( ' monthly ' , ' Month(s) ' ) , ( ' yearly ' , ' Year(s) ' ) ] , ' Recurrency ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } , help = " Let the event automatically repeat at that interval " ) ,
2013-11-23 11:36:27 +00:00
' recurrency ' : fields . boolean ( ' Recurrent ' , help = " Recurrent Meeting " ) ,
' recurrent_id ' : fields . integer ( ' Recurrent ID ' ) ,
2013-12-09 14:08:19 +00:00
' recurrent_id_date ' : fields . datetime ( ' Recurrent ID date ' ) ,
2014-01-10 17:09:12 +00:00
' end_type ' : fields . selection ( [ ( ' count ' , ' Number of repetitions ' ) , ( ' end_date ' , ' End date ' ) ] , ' Recurrence Termination ' ) ,
2013-11-23 11:36:27 +00:00
' interval ' : fields . integer ( ' Repeat Every ' , help = " Repeat every (Days/Week/Month/Year) " ) ,
' count ' : fields . integer ( ' Repeat ' , help = " Repeat x times " ) ,
' mo ' : fields . boolean ( ' Mon ' ) ,
' tu ' : fields . boolean ( ' Tue ' ) ,
' we ' : fields . boolean ( ' Wed ' ) ,
' th ' : fields . boolean ( ' Thu ' ) ,
' fr ' : fields . boolean ( ' Fri ' ) ,
' sa ' : fields . boolean ( ' Sat ' ) ,
' su ' : fields . boolean ( ' Sun ' ) ,
2014-01-20 16:40:54 +00:00
' month_by ' : fields . selection ( [ ( ' date ' , ' Date of month ' ) , ( ' day ' , ' Day of month ' ) ] , ' Option ' , oldname = ' select1 ' ) ,
2013-11-23 11:36:27 +00:00
' day ' : fields . integer ( ' Date of month ' ) ,
2014-01-10 17:09:12 +00:00
' week_list ' : fields . selection ( [ ( ' MO ' , ' Monday ' ) , ( ' TU ' , ' Tuesday ' ) , ( ' WE ' , ' Wednesday ' ) , ( ' TH ' , ' Thursday ' ) , ( ' FR ' , ' Friday ' ) , ( ' SA ' , ' Saturday ' ) , ( ' SU ' , ' Sunday ' ) ] , ' Weekday ' ) ,
' byday ' : fields . selection ( [ ( ' 1 ' , ' First ' ) , ( ' 2 ' , ' Second ' ) , ( ' 3 ' , ' Third ' ) , ( ' 4 ' , ' Fourth ' ) , ( ' 5 ' , ' Fifth ' ) , ( ' -1 ' , ' Last ' ) ] , ' By day ' ) ,
2014-05-05 15:42:46 +00:00
' final_date ' : fields . date ( ' Repeat Until ' ) , # The last event of a recurrence
2014-04-30 09:36:13 +00:00
2014-01-10 17:09:12 +00:00
' user_id ' : fields . many2one ( ' res.users ' , ' Responsible ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } ) ,
2014-01-20 11:49:01 +00:00
' color_partner_id ' : fields . related ( ' user_id ' , ' partner_id ' , ' id ' , type = " integer " , string = " colorize " , store = False ) , # Color of creator
2015-07-29 10:07:34 +00:00
' active ' : fields . boolean ( ' Active ' , help = " If the active field is set to false, it will allow you to hide the event alarm information without removing it. " ) ,
2014-01-15 09:38:05 +00:00
' categ_ids ' : fields . many2many ( ' calendar.event.type ' , ' meeting_category_rel ' , ' event_id ' , ' type_id ' , ' Tags ' ) ,
2013-12-09 14:08:19 +00:00
' attendee_ids ' : fields . one2many ( ' calendar.attendee ' , ' event_id ' , ' Attendees ' , ondelete = ' cascade ' ) ,
2014-04-30 09:36:13 +00:00
' partner_ids ' : fields . many2many ( ' res.partner ' , ' calendar_event_res_partner_rel ' , string = ' Attendees ' , states = { ' done ' : [ ( ' readonly ' , True ) ] } ) ,
2014-07-06 14:44:26 +00:00
' alarm_ids ' : fields . many2many ( ' calendar.alarm ' , ' calendar_alarm_calendar_event_rel ' , string = ' Reminders ' , ondelete = " restrict " , copy = False ) ,
2013-11-23 11:36:27 +00:00
}
2014-08-07 11:02:59 +00:00
def _get_default_partners ( self , cr , uid , ctx = None ) :
ret = [ self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context = ctx ) . partner_id . id ]
active_id = ctx . get ( ' active_id ' )
if ctx . get ( ' active_model ' ) == ' res.partner ' and active_id :
if active_id not in ret :
ret . append ( active_id )
return ret
2013-11-23 11:36:27 +00:00
_defaults = {
' end_type ' : ' count ' ,
' count ' : 1 ,
' rrule_type ' : False ,
2014-04-30 09:36:13 +00:00
' allday ' : False ,
2013-11-23 11:36:27 +00:00
' state ' : ' draft ' ,
' class ' : ' public ' ,
' show_as ' : ' busy ' ,
' month_by ' : ' date ' ,
' interval ' : 1 ,
' active ' : 1 ,
' user_id ' : lambda self , cr , uid , ctx : uid ,
2014-08-07 11:02:59 +00:00
' partner_ids ' : _get_default_partners ,
2013-11-23 11:36:27 +00:00
}
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
def _check_closing_date ( self , cr , uid , ids , context = None ) :
for event in self . browse ( cr , uid , ids , context = context ) :
2015-01-08 13:16:08 +00:00
if event . start_datetime and event . stop_datetime < event . start_datetime :
return False
if event . start_date and event . stop_date < event . start_date :
2013-11-23 11:36:27 +00:00
return False
return True
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
_constraints = [
2015-01-08 13:16:08 +00:00
( _check_closing_date , ' Error ! End date cannot be set before start date. ' , [ ' start_datetime ' , ' stop_datetime ' , ' start_date ' , ' stop_date ' ] )
2013-11-23 11:36:27 +00:00
]
2014-01-10 17:09:12 +00:00
2014-04-30 09:36:13 +00:00
def onchange_allday ( self , cr , uid , ids , start = False , end = False , starttime = False , endtime = False , startdatetime = False , enddatetime = False , checkallday = False , context = None ) :
value = { }
if not ( ( starttime and endtime ) or ( start and end ) ) : # At first intialize, we have not datetime
return value
if checkallday : # from datetime to date
startdatetime = startdatetime or start
if startdatetime :
start = datetime . strptime ( startdatetime , DEFAULT_SERVER_DATETIME_FORMAT )
2016-12-23 02:12:39 +00:00
value [ ' start_date ' ] = fields . date . context_today ( self , cr , uid , context = context , timestamp = start )
2014-04-30 09:36:13 +00:00
enddatetime = enddatetime or end
if enddatetime :
end = datetime . strptime ( enddatetime , DEFAULT_SERVER_DATETIME_FORMAT )
2016-12-23 02:12:39 +00:00
value [ ' stop_date ' ] = fields . date . context_today ( self , cr , uid , context = context , timestamp = end )
2014-04-30 09:36:13 +00:00
else : # from date to datetime
user = self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context )
tz = pytz . timezone ( user . tz ) if user . tz else pytz . utc
if starttime :
2015-02-11 20:28:38 +00:00
start = openerp . fields . Datetime . from_string ( starttime )
2014-04-30 09:36:13 +00:00
startdate = tz . localize ( start ) # Add "+hh:mm" timezone
startdate = startdate . replace ( hour = 8 ) # Set 8 AM in localtime
startdate = startdate . astimezone ( pytz . utc ) # Convert to UTC
2014-05-05 15:42:46 +00:00
value [ ' start_datetime ' ] = datetime . strftime ( startdate , DEFAULT_SERVER_DATETIME_FORMAT )
2014-04-30 09:36:13 +00:00
elif start :
2014-05-05 15:42:46 +00:00
value [ ' start_datetime ' ] = start
2014-04-30 09:36:13 +00:00
if endtime :
end = datetime . strptime ( endtime . split ( ' ' ) [ 0 ] , DEFAULT_SERVER_DATE_FORMAT )
enddate = tz . localize ( end ) . replace ( hour = 18 ) . astimezone ( pytz . utc )
2014-05-05 15:42:46 +00:00
value [ ' stop_datetime ' ] = datetime . strftime ( enddate , DEFAULT_SERVER_DATETIME_FORMAT )
2014-04-30 09:36:13 +00:00
elif end :
2014-05-05 15:42:46 +00:00
value [ ' stop_datetime ' ] = end
2014-04-30 09:36:13 +00:00
return { ' value ' : value }
def onchange_dates ( self , cr , uid , ids , fromtype , start = False , end = False , checkallday = False , allday = False , context = None ) :
2014-02-18 11:11:38 +00:00
2014-04-30 09:36:13 +00:00
""" Returns duration and end date based on values passed
2013-11-23 11:36:27 +00:00
@param ids : List of calendar event ' s IDs.
"""
value = { }
2014-04-30 09:36:13 +00:00
if checkallday != allday :
2013-11-23 11:36:27 +00:00
return value
2014-01-10 17:09:12 +00:00
2014-04-30 09:36:13 +00:00
value [ ' allday ' ] = checkallday # Force to be rewrited
2013-11-23 11:36:27 +00:00
2014-04-30 09:36:13 +00:00
if allday :
2014-08-01 11:48:33 +00:00
if fromtype == ' start ' and start :
2014-04-30 09:36:13 +00:00
start = datetime . strptime ( start , DEFAULT_SERVER_DATE_FORMAT )
2014-05-05 15:42:46 +00:00
value [ ' start_datetime ' ] = datetime . strftime ( start , DEFAULT_SERVER_DATETIME_FORMAT )
value [ ' start ' ] = datetime . strftime ( start , DEFAULT_SERVER_DATETIME_FORMAT )
2014-04-30 09:36:13 +00:00
2014-08-01 11:48:33 +00:00
if fromtype == ' stop ' and end :
2014-04-30 09:36:13 +00:00
end = datetime . strptime ( end , DEFAULT_SERVER_DATE_FORMAT )
2014-05-05 15:42:46 +00:00
value [ ' stop_datetime ' ] = datetime . strftime ( end , DEFAULT_SERVER_DATETIME_FORMAT )
value [ ' stop ' ] = datetime . strftime ( end , DEFAULT_SERVER_DATETIME_FORMAT )
2014-02-18 11:11:38 +00:00
2013-12-09 14:08:19 +00:00
else :
2014-08-01 11:48:33 +00:00
if fromtype == ' start ' and start :
2014-04-30 09:36:13 +00:00
start = datetime . strptime ( start , DEFAULT_SERVER_DATETIME_FORMAT )
2014-05-05 15:42:46 +00:00
value [ ' start_date ' ] = datetime . strftime ( start , DEFAULT_SERVER_DATE_FORMAT )
value [ ' start ' ] = datetime . strftime ( start , DEFAULT_SERVER_DATETIME_FORMAT )
2014-08-01 11:48:33 +00:00
if fromtype == ' stop ' and end :
2014-04-30 09:36:13 +00:00
end = datetime . strptime ( end , DEFAULT_SERVER_DATETIME_FORMAT )
2014-05-05 15:42:46 +00:00
value [ ' stop_date ' ] = datetime . strftime ( end , DEFAULT_SERVER_DATE_FORMAT )
value [ ' stop ' ] = datetime . strftime ( end , DEFAULT_SERVER_DATETIME_FORMAT )
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
return { ' value ' : value }
2014-01-15 09:38:05 +00:00
def new_invitation_token ( self , cr , uid , record , partner_id ) :
2014-01-13 17:41:57 +00:00
return uuid . uuid4 ( ) . hex
2014-01-10 17:09:12 +00:00
2014-10-03 18:43:48 +00:00
def create_attendees ( self , cr , uid , ids , context = None ) :
if context is None :
context = { }
2014-01-10 17:09:12 +00:00
user_obj = self . pool [ ' res.users ' ]
2013-11-23 11:36:27 +00:00
current_user = user_obj . browse ( cr , uid , uid , context = context )
2013-11-26 18:01:06 +00:00
res = { }
2014-01-10 17:09:12 +00:00
for event in self . browse ( cr , uid , ids , context ) :
2013-11-23 11:36:27 +00:00
attendees = { }
for att in event . attendee_ids :
attendees [ att . partner_id . id ] = True
new_attendees = [ ]
2014-01-10 17:09:12 +00:00
new_att_partner_ids = [ ]
2013-11-23 11:36:27 +00:00
for partner in event . partner_ids :
2014-01-10 17:09:12 +00:00
if partner . id in attendees :
2013-11-23 11:36:27 +00:00
continue
access_token = self . new_invitation_token ( cr , uid , event , partner . id )
2013-12-19 13:33:16 +00:00
values = {
2013-11-23 11:36:27 +00:00
' partner_id ' : partner . id ,
2013-12-09 14:08:19 +00:00
' event_id ' : event . id ,
2013-11-23 11:36:27 +00:00
' access_token ' : access_token ,
' email ' : partner . email ,
2013-12-19 13:33:16 +00:00
}
2014-01-10 17:09:12 +00:00
2013-12-19 13:33:16 +00:00
if partner . id == current_user . partner_id . id :
2014-01-10 17:09:12 +00:00
values [ ' state ' ] = ' accepted '
att_id = self . pool [ ' calendar.attendee ' ] . create ( cr , uid , values , context = context )
2013-11-23 11:36:27 +00:00
new_attendees . append ( att_id )
new_att_partner_ids . append ( partner . id )
2014-01-10 17:09:12 +00:00
if not current_user . email or current_user . email != partner . email :
2013-11-26 11:45:02 +00:00
mail_from = current_user . email or tools . config . get ( ' email_from ' , False )
2014-10-03 18:43:48 +00:00
if not context . get ( ' no_email ' ) :
if self . pool [ ' calendar.attendee ' ] . _send_mail_to_attendees ( cr , uid , att_id , email_from = mail_from , context = context ) :
self . message_post ( cr , uid , event . id , body = _ ( " An invitation email has been sent to attendee %s " ) % ( partner . name , ) , subtype = " calendar.subtype_invitation " , context = context )
2014-01-10 17:09:12 +00:00
if new_attendees :
self . write ( cr , uid , [ event . id ] , { ' attendee_ids ' : [ ( 4 , att ) for att in new_attendees ] } , context = context )
if new_att_partner_ids :
2013-11-26 11:45:02 +00:00
self . message_subscribe ( cr , uid , [ event . id ] , new_att_partner_ids , context = context )
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
# We remove old attendees who are not in partner_ids now.
all_partner_ids = [ part . id for part in event . partner_ids ]
2013-12-10 16:45:25 +00:00
all_part_attendee_ids = [ att . partner_id . id for att in event . attendee_ids ]
all_attendee_ids = [ att . id for att in event . attendee_ids ]
partner_ids_to_remove = map ( lambda x : x , set ( all_part_attendee_ids + new_att_partner_ids ) - set ( all_partner_ids ) )
2014-01-10 17:09:12 +00:00
2013-11-26 18:01:06 +00:00
attendee_ids_to_remove = [ ]
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
if partner_ids_to_remove :
2014-01-10 17:09:12 +00:00
attendee_ids_to_remove = self . pool [ " calendar.attendee " ] . search ( cr , uid , [ ( ' partner_id.id ' , ' in ' , partner_ids_to_remove ) , ( ' event_id.id ' , ' = ' , event . id ) ] , context = context )
if attendee_ids_to_remove :
self . pool [ ' calendar.attendee ' ] . unlink ( cr , uid , attendee_ids_to_remove , context )
res [ event . id ] = {
' new_attendee_ids ' : new_attendees ,
' old_attendee_ids ' : all_attendee_ids ,
' removed_attendee_ids ' : attendee_ids_to_remove
}
2013-11-26 18:01:06 +00:00
return res
2013-11-23 11:36:27 +00:00
2014-02-24 22:02:22 +00:00
def get_search_fields ( self , browse_event , order_fields , r_date = None ) :
2014-01-14 13:37:36 +00:00
sort_fields = { }
for ord in order_fields :
if ord == ' id ' and r_date :
sort_fields [ ord ] = ' %s - %s ' % ( browse_event [ ord ] , r_date . strftime ( " % Y % m %d % H % M % S " ) )
else :
sort_fields [ ord ] = browse_event [ ord ]
if type ( browse_event [ ord ] ) is openerp . osv . orm . browse_record :
name_get = browse_event [ ord ] . name_get ( )
2014-02-24 22:02:22 +00:00
if len ( name_get ) and len ( name_get [ 0 ] ) > = 2 :
2014-01-14 13:37:36 +00:00
sort_fields [ ord ] = name_get [ 0 ] [ 1 ]
2014-11-21 10:55:00 +00:00
if r_date :
sort_fields [ ' sort_start ' ] = r_date . strftime ( " % Y % m %d % H % M % S " )
else :
sort_fields [ ' sort_start ' ] = browse_event [ ' display_start ' ] . replace ( ' ' , ' ' ) . replace ( ' - ' , ' ' )
2014-01-14 13:37:36 +00:00
return sort_fields
def get_recurrent_ids ( self , cr , uid , event_id , domain , order = None , context = None ) :
2014-02-24 22:02:22 +00:00
""" Gives virtual event ids for recurring events
2014-01-14 13:37:36 +00:00
This method gives ids of dates that comes between start date and end date of calendar views
2014-02-24 22:02:22 +00:00
@param order : The fields ( comma separated , format " FIELD { DESC|ASC} " ) on which the events should be sorted
2014-01-14 13:37:36 +00:00
"""
2013-11-23 11:36:27 +00:00
if not context :
context = { }
2014-01-15 09:38:05 +00:00
2014-12-31 10:56:28 +00:00
if isinstance ( event_id , ( basestring , int , long ) ) :
2014-01-14 13:37:36 +00:00
ids_to_browse = [ event_id ] # keep select for return
2013-12-09 14:08:19 +00:00
else :
2014-01-14 13:37:36 +00:00
ids_to_browse = event_id
2014-01-10 17:09:12 +00:00
2014-01-14 13:37:36 +00:00
if order :
order_fields = [ field . split ( ) [ 0 ] for field in order . split ( ' , ' ) ]
else :
# fallback on self._order defined on the model
order_fields = [ field . split ( ) [ 0 ] for field in self . _order . split ( ' , ' ) ]
2014-01-15 09:38:05 +00:00
2014-01-14 13:37:36 +00:00
if ' id ' not in order_fields :
order_fields . append ( ' id ' )
2014-01-14 15:51:52 +00:00
2014-01-14 13:37:36 +00:00
result_data = [ ]
2013-11-23 11:36:27 +00:00
result = [ ]
2014-01-10 17:09:12 +00:00
for ev in self . browse ( cr , uid , ids_to_browse , context = context ) :
2013-12-09 14:08:19 +00:00
if not ev . recurrency or not ev . rrule :
result . append ( ev . id )
2014-02-24 22:02:22 +00:00
result_data . append ( self . get_search_fields ( ev , order_fields ) )
2013-11-23 11:36:27 +00:00
continue
2013-12-09 14:08:19 +00:00
rdates = self . get_recurrent_date_by_event ( cr , uid , ev , context = context )
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
for r_date in rdates :
# fix domain evaluation
# step 1: check date and replace expression by True or False, replace other expressions by True
# step 2: evaluation of & and |
# check if there are one False
pile = [ ]
ok = True
for arg in domain :
2014-05-05 15:42:46 +00:00
if str ( arg [ 0 ] ) in ( ' start ' , ' stop ' , ' final_date ' ) :
2013-11-23 11:36:27 +00:00
if ( arg [ 1 ] == ' = ' ) :
2014-01-10 17:09:12 +00:00
ok = r_date . strftime ( ' % Y- % m- %d ' ) == arg [ 2 ]
2013-11-23 11:36:27 +00:00
if ( arg [ 1 ] == ' > ' ) :
2014-01-10 17:09:12 +00:00
ok = r_date . strftime ( ' % Y- % m- %d ' ) > arg [ 2 ]
2013-11-23 11:36:27 +00:00
if ( arg [ 1 ] == ' < ' ) :
2014-01-10 17:09:12 +00:00
ok = r_date . strftime ( ' % Y- % m- %d ' ) < arg [ 2 ]
2013-11-23 11:36:27 +00:00
if ( arg [ 1 ] == ' >= ' ) :
2014-01-10 17:09:12 +00:00
ok = r_date . strftime ( ' % Y- % m- %d ' ) > = arg [ 2 ]
2013-11-23 11:36:27 +00:00
if ( arg [ 1 ] == ' <= ' ) :
2014-01-10 17:09:12 +00:00
ok = r_date . strftime ( ' % Y- % m- %d ' ) < = arg [ 2 ]
2013-11-23 11:36:27 +00:00
pile . append ( ok )
elif str ( arg ) == str ( ' & ' ) or str ( arg ) == str ( ' | ' ) :
pile . append ( arg )
else :
pile . append ( True )
pile . reverse ( )
new_pile = [ ]
for item in pile :
if not isinstance ( item , basestring ) :
res = item
elif str ( item ) == str ( ' & ' ) :
first = new_pile . pop ( )
second = new_pile . pop ( )
res = first and second
elif str ( item ) == str ( ' | ' ) :
first = new_pile . pop ( )
second = new_pile . pop ( )
res = first or second
new_pile . append ( res )
if [ True for item in new_pile if not item ] :
continue
2014-02-24 22:02:22 +00:00
result_data . append ( self . get_search_fields ( ev , order_fields , r_date = r_date ) )
2014-01-14 13:37:36 +00:00
if order_fields :
2014-11-21 10:55:00 +00:00
uniq = lambda it : collections . OrderedDict ( ( id ( x ) , x ) for x in it ) . values ( )
2014-01-14 13:37:36 +00:00
def comparer ( left , right ) :
for fn , mult in comparers :
result = cmp ( fn ( left ) , fn ( right ) )
if result :
return mult * result
return 0
sort_params = [ key . split ( ) [ 0 ] if key [ - 4 : ] . lower ( ) != ' desc ' else ' - %s ' % key . split ( ) [ 0 ] for key in ( order or self . _order ) . split ( ' , ' ) ]
2014-11-21 10:55:00 +00:00
sort_params = uniq ( [ comp if comp not in [ ' start ' , ' start_date ' , ' start_datetime ' ] else ' sort_start ' for comp in sort_params ] )
sort_params = uniq ( [ comp if comp not in [ ' -start ' , ' -start_date ' , ' -start_datetime ' ] else ' -sort_start ' for comp in sort_params ] )
2014-02-24 22:02:22 +00:00
comparers = [ ( ( itemgetter ( col [ 1 : ] ) , - 1 ) if col [ 0 ] == ' - ' else ( itemgetter ( col ) , 1 ) ) for col in sort_params ]
2014-01-14 13:37:36 +00:00
ids = [ r [ ' id ' ] for r in sorted ( result_data , cmp = comparer ) ]
2014-12-31 10:56:28 +00:00
if isinstance ( event_id , ( basestring , int , long ) ) :
2014-01-14 13:37:36 +00:00
return ids and ids [ 0 ] or False
2013-11-23 11:36:27 +00:00
else :
2014-01-14 13:37:36 +00:00
return ids
2013-11-23 11:36:27 +00:00
def compute_rule_string ( self , data ) :
"""
Compute rule string according to value type RECUR of iCalendar from the values given .
@param self : the object pointer
@param data : dictionary of freq and interval value
@return : string containing recurring rule ( empty if no rule )
"""
2014-08-05 15:22:56 +00:00
if data [ ' interval ' ] and data [ ' interval ' ] < 0 :
raise osv . except_osv ( _ ( ' warning! ' ) , _ ( ' interval cannot be negative. ' ) )
2016-07-25 12:39:16 +00:00
if data [ ' end_type ' ] == ' count ' and int ( data [ ' count ' ] ) < = 0 :
2014-08-05 15:22:56 +00:00
raise osv . except_osv ( _ ( ' warning! ' ) , _ ( ' count cannot be negative or 0. ' ) )
2013-11-23 11:36:27 +00:00
def get_week_string ( freq , data ) :
weekdays = [ ' mo ' , ' tu ' , ' we ' , ' th ' , ' fr ' , ' sa ' , ' su ' ]
if freq == ' weekly ' :
byday = map ( lambda x : x . upper ( ) , filter ( lambda x : data . get ( x ) and x in weekdays , data ) )
if byday :
return ' ;BYDAY= ' + ' , ' . join ( byday )
return ' '
def get_month_string ( freq , data ) :
if freq == ' monthly ' :
2014-01-10 17:09:12 +00:00
if data . get ( ' month_by ' ) == ' date ' and ( data . get ( ' day ' ) < 1 or data . get ( ' day ' ) > 31 ) :
2013-11-23 11:36:27 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , ( " Please select a proper day of the month. " ) )
2014-01-10 17:09:12 +00:00
if data . get ( ' month_by ' ) == ' day ' : # Eg : Second Monday of the month
2013-11-23 11:36:27 +00:00
return ' ;BYDAY= ' + data . get ( ' byday ' ) + data . get ( ' week_list ' )
2014-01-10 17:09:12 +00:00
elif data . get ( ' month_by ' ) == ' date ' : # Eg : 16th of the month
2013-11-23 11:36:27 +00:00
return ' ;BYMONTHDAY= ' + str ( data . get ( ' day ' ) )
return ' '
def get_end_date ( data ) :
2014-05-05 15:42:46 +00:00
if data . get ( ' final_date ' ) :
data [ ' end_date_new ' ] = ' ' . join ( ( re . compile ( ' \ d ' ) ) . findall ( data . get ( ' final_date ' ) ) ) + ' T235959Z '
2013-11-23 11:36:27 +00:00
return ( data . get ( ' end_type ' ) == ' count ' and ( ' ;COUNT= ' + str ( data . get ( ' count ' ) ) ) or ' ' ) + \
2014-02-24 22:02:22 +00:00
( ( data . get ( ' end_date_new ' ) and data . get ( ' end_type ' ) == ' end_date ' and ( ' ;UNTIL= ' + data . get ( ' end_date_new ' ) ) ) or ' ' )
2013-11-23 11:36:27 +00:00
2014-01-10 17:09:12 +00:00
freq = data . get ( ' rrule_type ' , False ) # day/week/month/year
2013-11-23 11:36:27 +00:00
res = ' '
if freq :
interval_srting = data . get ( ' interval ' ) and ( ' ;INTERVAL= ' + str ( data . get ( ' interval ' ) ) ) or ' '
res = ' FREQ= ' + freq . upper ( ) + get_week_string ( freq , data ) + interval_srting + get_end_date ( data ) + get_month_string ( freq , data )
return res
def _get_empty_rrule_data ( self ) :
2014-01-10 17:09:12 +00:00
return {
' byday ' : False ,
' recurrency ' : False ,
2014-05-05 15:42:46 +00:00
' final_date ' : False ,
2014-01-10 17:09:12 +00:00
' rrule_type ' : False ,
' month_by ' : False ,
' interval ' : 0 ,
' count ' : False ,
' end_type ' : False ,
' mo ' : False ,
' tu ' : False ,
' we ' : False ,
' th ' : False ,
' fr ' : False ,
' sa ' : False ,
' su ' : False ,
' day ' : False ,
' week_list ' : False
2013-11-23 11:36:27 +00:00
}
def _parse_rrule ( self , rule , data , date_start ) :
day_list = [ ' mo ' , ' tu ' , ' we ' , ' th ' , ' fr ' , ' sa ' , ' su ' ]
rrule_type = [ ' yearly ' , ' monthly ' , ' weekly ' , ' daily ' ]
2014-04-30 09:36:13 +00:00
r = rrule . rrulestr ( rule , dtstart = datetime . strptime ( date_start , DEFAULT_SERVER_DATETIME_FORMAT ) )
2013-11-23 11:36:27 +00:00
2014-01-10 17:09:12 +00:00
if r . _freq > 0 and r . _freq < 4 :
2013-11-23 11:36:27 +00:00
data [ ' rrule_type ' ] = rrule_type [ r . _freq ]
data [ ' count ' ] = r . _count
data [ ' interval ' ] = r . _interval
2014-05-05 15:42:46 +00:00
data [ ' final_date ' ] = r . _until and r . _until . strftime ( DEFAULT_SERVER_DATETIME_FORMAT )
2013-11-23 11:36:27 +00:00
#repeat weekly
if r . _byweekday :
2014-01-10 17:09:12 +00:00
for i in xrange ( 0 , 7 ) :
2013-11-23 11:36:27 +00:00
if i in r . _byweekday :
data [ day_list [ i ] ] = True
data [ ' rrule_type ' ] = ' weekly '
#repeat monthly by nweekday ((weekday, weeknumber), )
if r . _bynweekday :
2016-10-28 08:48:01 +00:00
data [ ' week_list ' ] = day_list [ list ( r . _bynweekday ) [ 0 ] [ 0 ] ] . upper ( )
data [ ' byday ' ] = str ( list ( r . _bynweekday ) [ 0 ] [ 1 ] )
2013-11-23 11:36:27 +00:00
data [ ' month_by ' ] = ' day '
data [ ' rrule_type ' ] = ' monthly '
if r . _bymonthday :
2016-12-20 20:10:51 +00:00
data [ ' day ' ] = list ( r . _bymonthday ) [ 0 ]
2013-11-23 11:36:27 +00:00
data [ ' month_by ' ] = ' date '
data [ ' rrule_type ' ] = ' monthly '
#repeat yearly but for openerp it's monthly, take same information as monthly but interval is 12 times
if r . _bymonth :
data [ ' interval ' ] = data [ ' interval ' ] * 12
#FIXEME handle forever case
#end of recurrence
#in case of repeat for ever that we do not support right now
2014-05-05 15:42:46 +00:00
if not ( data . get ( ' count ' ) or data . get ( ' final_date ' ) ) :
2013-11-23 11:36:27 +00:00
data [ ' count ' ] = 100
if data . get ( ' count ' ) :
data [ ' end_type ' ] = ' count '
else :
2014-06-02 10:02:11 +00:00
data [ ' end_type ' ] = ' end_date '
2013-11-23 11:36:27 +00:00
return data
def message_get_subscription_data ( self , cr , uid , ids , user_pid = None , context = None ) :
res = { }
for virtual_id in ids :
2013-12-19 14:47:39 +00:00
real_id = calendar_id2real_id ( virtual_id )
2014-01-15 09:38:05 +00:00
result = super ( calendar_event , self ) . message_get_subscription_data ( cr , uid , [ real_id ] , user_pid = None , context = context )
2013-11-23 11:36:27 +00:00
res [ virtual_id ] = result [ real_id ]
return res
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
def onchange_partner_ids ( self , cr , uid , ids , value , context = None ) :
""" The basic purpose of this method is to check that destination partners
effectively have email addresses . Otherwise a warning is thrown .
: param value : value format : [ [ 6 , 0 , [ 3 , 4 ] ] ]
"""
res = { ' value ' : { } }
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
if not value or not value [ 0 ] or not value [ 0 ] [ 0 ] == 6 :
return
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
res . update ( self . check_partners_email ( cr , uid , value [ 0 ] [ 2 ] , context = context ) )
return res
def check_partners_email ( self , cr , uid , partner_ids , context = None ) :
""" Verify that selected partner_ids have an email_address defined.
Otherwise throw a warning . """
partner_wo_email_lst = [ ]
2014-01-10 17:09:12 +00:00
for partner in self . pool [ ' res.partner ' ] . browse ( cr , uid , partner_ids , context = context ) :
2013-11-23 11:36:27 +00:00
if not partner . email :
partner_wo_email_lst . append ( partner )
if not partner_wo_email_lst :
return { }
warning_msg = _ ( ' The following contacts have no email address : ' )
for partner in partner_wo_email_lst :
warning_msg + = ' \n - %s ' % ( partner . name )
2014-02-24 22:02:22 +00:00
return { ' warning ' : {
' title ' : _ ( ' Email addresses not found ' ) ,
' message ' : warning_msg ,
} }
2013-12-20 16:08:18 +00:00
2013-11-23 11:36:27 +00:00
# shows events of the day for this user
def _needaction_domain_get ( self , cr , uid , context = None ) :
2014-04-30 09:36:13 +00:00
return [
2014-05-05 15:42:46 +00:00
( ' stop ' , ' <= ' , time . strftime ( DEFAULT_SERVER_DATE_FORMAT + ' 23:59:59 ' ) ) ,
( ' start ' , ' >= ' , time . strftime ( DEFAULT_SERVER_DATE_FORMAT + ' 00:00:00 ' ) ) ,
2014-04-30 09:36:13 +00:00
( ' user_id ' , ' = ' , uid ) ,
]
2013-11-23 11:36:27 +00:00
2014-07-28 16:07:17 +00:00
@api.cr_uid_ids_context
2013-11-23 11:36:27 +00:00
def message_post ( self , cr , uid , thread_id , body = ' ' , subject = None , type = ' notification ' , subtype = None , parent_id = False , attachments = None , context = None , * * kwargs ) :
2014-12-31 10:56:28 +00:00
if isinstance ( thread_id , basestring ) :
2013-11-23 11:36:27 +00:00
thread_id = get_real_ids ( thread_id )
if context . get ( ' default_date ' ) :
del context [ ' default_date ' ]
2014-01-15 09:38:05 +00:00
return super ( calendar_event , self ) . message_post ( cr , uid , thread_id , body = body , subject = subject , type = type , subtype = subtype , parent_id = parent_id , attachments = attachments , context = context , * * kwargs )
2013-11-23 11:36:27 +00:00
2015-02-23 13:25:07 +00:00
def message_subscribe ( self , cr , uid , ids , partner_ids , subtype_ids = None , context = None ) :
return super ( calendar_event , self ) . message_subscribe ( cr , uid , get_real_ids ( ids ) , partner_ids , subtype_ids = subtype_ids , context = context )
def message_unsubscribe ( self , cr , uid , ids , partner_ids , context = None ) :
return super ( calendar_event , self ) . message_unsubscribe ( cr , uid , get_real_ids ( ids ) , partner_ids , context = context )
2013-11-23 11:36:27 +00:00
def do_sendmail ( self , cr , uid , ids , context = None ) :
2014-01-10 17:09:12 +00:00
for event in self . browse ( cr , uid , ids , context ) :
current_user = self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context = context )
2013-11-23 11:36:27 +00:00
if current_user . email :
2014-01-10 17:09:12 +00:00
if self . pool [ ' calendar.attendee ' ] . _send_mail_to_attendees ( cr , uid , [ att . id for att in event . attendee_ids ] , email_from = current_user . email , context = context ) :
2013-12-19 14:47:39 +00:00
self . message_post ( cr , uid , event . id , body = _ ( " An invitation email has been sent to attendee(s) " ) , subtype = " calendar.subtype_invitation " , context = context )
2014-01-10 17:09:12 +00:00
return
2013-11-23 11:36:27 +00:00
def get_attendee ( self , cr , uid , meeting_id , context = None ) :
2014-01-10 17:09:12 +00:00
# Used for view in controller
2014-01-13 17:41:57 +00:00
invitation = { ' meeting ' : { } , ' attendee ' : [ ] }
2014-01-15 09:38:05 +00:00
2014-05-05 10:46:11 +00:00
meeting = self . browse ( cr , uid , int ( meeting_id ) , context = context )
2013-11-23 11:36:27 +00:00
invitation [ ' meeting ' ] = {
2014-01-10 17:09:12 +00:00
' event ' : meeting . name ,
' where ' : meeting . location ,
' when ' : meeting . display_time
2013-11-23 11:36:27 +00:00
}
2014-01-15 09:38:05 +00:00
2013-11-23 11:36:27 +00:00
for attendee in meeting . attendee_ids :
2014-01-10 17:09:12 +00:00
invitation [ ' attendee ' ] . append ( { ' name ' : attendee . cn , ' status ' : attendee . state } )
2013-11-23 11:36:27 +00:00
return invitation
2014-04-07 09:46:24 +00:00
def get_interval ( self , cr , uid , ids , date , interval , tz = None , context = None ) :
2015-02-10 12:37:14 +00:00
''' Format and localize some dates to be used in email templates
: param string date : date / time to be formatted
: param string interval : Among ' day ' , ' month ' , ' dayname ' and ' time ' indicating the desired formatting
: param string tz : Timezone indicator ( optional )
: return unicode : Formatted date or time ( as unicode string , to prevent jinja2 crash )
( Function used only in calendar_event_data . xml ) '''
2015-02-11 20:28:38 +00:00
date = openerp . fields . Datetime . from_string ( date )
2014-04-07 09:46:24 +00:00
if tz :
timezone = pytz . timezone ( tz or ' UTC ' )
date = date . replace ( tzinfo = pytz . timezone ( ' UTC ' ) ) . astimezone ( timezone )
2013-11-23 11:36:27 +00:00
if interval == ' day ' :
2015-02-10 12:37:14 +00:00
# Day number (1-31)
res = unicode ( date . day )
2013-11-23 11:36:27 +00:00
elif interval == ' month ' :
2015-02-10 12:37:14 +00:00
# Localized month name and year
res = babel . dates . format_date ( date = date , format = ' MMMM y ' , locale = context . get ( ' lang ' , ' en_US ' ) )
2013-11-23 11:36:27 +00:00
elif interval == ' dayname ' :
2015-02-10 12:37:14 +00:00
# Localized day name
res = babel . dates . format_date ( date = date , format = ' EEEE ' , locale = context . get ( ' lang ' , ' en_US ' ) )
2013-11-23 11:36:27 +00:00
elif interval == ' time ' :
2015-02-10 12:37:14 +00:00
# Localized time
2014-05-05 10:46:11 +00:00
dummy , format_time = self . get_date_formats ( cr , uid , context = context )
2015-02-10 12:37:14 +00:00
res = tools . ustr ( date . strftime ( format_time + " % Z " ) )
2013-11-23 11:36:27 +00:00
return res
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
def search ( self , cr , uid , args , offset = 0 , limit = 0 , order = None , context = None , count = False ) :
if context is None :
2014-01-10 17:09:12 +00:00
context = { }
if context . get ( ' mymeetings ' , False ) :
partner_id = self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context ) . partner_id . id
2014-04-30 09:36:13 +00:00
args + = [ ( ' partner_ids ' , ' in ' , [ partner_id ] ) ]
2014-01-10 17:09:12 +00:00
new_args = [ ]
2013-11-23 11:36:27 +00:00
for arg in args :
new_arg = arg
2014-01-10 17:09:12 +00:00
2014-05-05 15:42:46 +00:00
if arg [ 0 ] in ( ' start_date ' , ' start_datetime ' , ' start ' , ) and arg [ 1 ] == " >= " :
2013-11-23 11:36:27 +00:00
if context . get ( ' virtual_id ' , True ) :
2014-05-05 15:42:46 +00:00
new_args + = [ ' | ' , ' & ' , ( ' recurrency ' , ' = ' , 1 ) , ( ' final_date ' , arg [ 1 ] , arg [ 2 ] ) ]
2013-11-23 11:36:27 +00:00
elif arg [ 0 ] == " id " :
new_id = get_real_ids ( arg [ 2 ] )
new_arg = ( arg [ 0 ] , arg [ 1 ] , new_id )
new_args . append ( new_arg )
2014-01-10 17:09:12 +00:00
2014-01-29 18:47:03 +00:00
if not context . get ( ' virtual_id ' , True ) :
2014-05-14 08:28:10 +00:00
return super ( calendar_event , self ) . search ( cr , uid , new_args , offset = offset , limit = limit , order = order , count = count , context = context )
2014-01-29 18:47:03 +00:00
2014-03-11 16:38:33 +00:00
# offset, limit, order and count must be treated separately as we may need to deal with virtual ids
res = super ( calendar_event , self ) . search ( cr , uid , new_args , offset = 0 , limit = 0 , order = None , context = context , count = False )
2014-01-29 18:47:03 +00:00
res = self . get_recurrent_ids ( cr , uid , res , args , order = order , context = context )
2013-11-23 11:36:27 +00:00
if count :
return len ( res )
elif limit :
2014-01-10 17:09:12 +00:00
return res [ offset : offset + limit ]
2013-11-23 11:36:27 +00:00
return res
def copy ( self , cr , uid , id , default = None , context = None ) :
default = default or { }
2014-04-30 09:36:13 +00:00
self . _set_date ( cr , uid , default , id = default . get ( ' id ' ) , context = context )
2014-07-06 14:44:26 +00:00
return super ( calendar_event , self ) . copy ( cr , uid , calendar_id2real_id ( id ) , default , context )
2013-11-23 11:36:27 +00:00
2014-02-18 17:15:08 +00:00
def _detach_one_event ( self , cr , uid , id , values = dict ( ) , context = None ) :
real_event_id = calendar_id2real_id ( id )
2014-05-05 15:42:46 +00:00
data = self . read ( cr , uid , id , [ ' allday ' , ' start ' , ' stop ' , ' rrule ' , ' duration ' ] )
data [ ' start_date ' if data [ ' allday ' ] else ' start_datetime ' ] = data [ ' start ' ]
data [ ' stop_date ' if data [ ' allday ' ] else ' stop_datetime ' ] = data [ ' stop ' ]
2014-02-18 17:15:08 +00:00
if data . get ( ' rrule ' ) :
data . update (
values ,
recurrent_id = real_event_id ,
2014-05-05 15:42:46 +00:00
recurrent_id_date = data . get ( ' start ' ) ,
2014-02-18 17:15:08 +00:00
rrule_type = False ,
2016-07-25 12:39:16 +00:00
end_type = False ,
2014-02-18 17:15:08 +00:00
rrule = ' ' ,
recurrency = False ,
2014-05-05 15:42:46 +00:00
final_date = datetime . strptime ( data . get ( ' start ' ) , DEFAULT_SERVER_DATETIME_FORMAT if data [ ' allday ' ] else DEFAULT_SERVER_DATETIME_FORMAT ) + timedelta ( hours = values . get ( ' duration ' , False ) or data . get ( ' duration ' ) )
2014-02-18 17:15:08 +00:00
)
#do not copy the id
if data . get ( ' id ' ) :
del ( data [ ' id ' ] )
new_id = self . copy ( cr , uid , real_event_id , default = data , context = context )
return new_id
def open_after_detach_event ( self , cr , uid , ids , context = None ) :
if context is None :
context = { }
new_id = self . _detach_one_event ( cr , uid , ids [ 0 ] , context = context )
return {
2014-02-24 22:02:22 +00:00
' type ' : ' ir.actions.act_window ' ,
' res_model ' : ' calendar.event ' ,
' view_mode ' : ' form ' ,
' res_id ' : new_id ,
' target ' : ' current ' ,
' flags ' : { ' form ' : { ' action_buttons ' : True , ' options ' : { ' mode ' : ' edit ' } } }
2014-02-18 17:15:08 +00:00
}
2014-04-30 09:36:13 +00:00
def _name_search ( self , cr , user , name = ' ' , args = None , operator = ' ilike ' , context = None , limit = 100 , name_get_uid = None ) :
for arg in args :
if arg [ 0 ] == ' id ' :
for n , calendar_id in enumerate ( arg [ 2 ] ) :
2014-12-31 10:56:28 +00:00
if isinstance ( calendar_id , basestring ) :
2014-04-30 09:36:13 +00:00
arg [ 2 ] [ n ] = calendar_id . split ( ' - ' ) [ 0 ]
return super ( calendar_event , self ) . _name_search ( cr , user , name = name , args = args , operator = operator , context = context , limit = limit , name_get_uid = name_get_uid )
2013-11-23 11:36:27 +00:00
def write ( self , cr , uid , ids , values , context = None ) :
2016-01-21 13:26:30 +00:00
context = context or { }
2014-04-30 09:36:13 +00:00
if not isinstance ( ids , ( tuple , list ) ) :
ids = [ ids ]
2016-01-21 13:26:30 +00:00
values0 = values
2014-01-10 17:09:12 +00:00
2016-01-21 13:26:30 +00:00
# process events one by one
for event_id in ids :
# make a copy, since _set_date() modifies values depending on event
values = dict ( values0 )
self . _set_date ( cr , uid , values , event_id , context = context )
2013-11-23 11:36:27 +00:00
2016-01-21 13:26:30 +00:00
# special write of complex IDS
real_ids = [ ]
new_ids = [ ]
if ' - ' not in str ( event_id ) :
real_ids = [ int ( event_id ) ]
2014-02-18 17:15:08 +00:00
else :
2016-01-21 13:26:30 +00:00
real_event_id = calendar_id2real_id ( event_id )
# if we are setting the recurrency flag to False or if we are only changing fields that
# should be only updated on the real ID and not on the virtual (like message_follower_ids):
# then set real ids to be updated.
blacklisted = any ( key in values for key in ( ' start ' , ' stop ' , ' active ' ) )
if not values . get ( ' recurrency ' , True ) or not blacklisted :
real_ids = [ real_event_id ]
2014-05-14 08:28:10 +00:00
else :
2016-01-21 13:26:30 +00:00
data = self . read ( cr , uid , event_id , [ ' start ' , ' stop ' , ' rrule ' , ' duration ' ] )
if data . get ( ' rrule ' ) :
new_ids = [ self . _detach_one_event ( cr , uid , event_id , values , context = None ) ]
super ( calendar_event , self ) . write ( cr , uid , real_ids , values , context = context )
# set end_date for calendar searching
if values . get ( ' recurrency ' ) and values . get ( ' end_type ' , ' count ' ) in ( ' count ' , unicode ( ' count ' ) ) and \
( values . get ( ' rrule_type ' ) or values . get ( ' count ' ) or values . get ( ' start ' ) or values . get ( ' stop ' ) ) :
for id in real_ids :
final_date = self . _get_recurrency_end_date ( cr , uid , id , context = context )
super ( calendar_event , self ) . write ( cr , uid , [ id ] , { ' final_date ' : final_date } , context = context )
attendees_create = False
if values . get ( ' partner_ids ' , False ) :
attendees_create = self . create_attendees ( cr , uid , real_ids + new_ids , context )
if ( values . get ( ' start_date ' ) or values . get ( ' start_datetime ' ) ) and values . get ( ' active ' , True ) :
for the_id in real_ids + new_ids :
if attendees_create :
attendees_create = attendees_create [ the_id ]
mail_to_ids = list ( set ( attendees_create [ ' old_attendee_ids ' ] ) - set ( attendees_create [ ' removed_attendee_ids ' ] ) )
else :
mail_to_ids = [ att . id for att in self . browse ( cr , uid , the_id , context = context ) . attendee_ids ]
if mail_to_ids :
current_user = self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context = context )
if self . pool [ ' calendar.attendee ' ] . _send_mail_to_attendees ( cr , uid , mail_to_ids , template_xmlid = ' calendar_template_meeting_changedate ' , email_from = current_user . email , context = context ) :
self . message_post ( cr , uid , the_id , body = _ ( " A email has been send to specify that the date has been changed ! " ) , subtype = " calendar.subtype_invitation " , context = context )
2014-01-10 17:09:12 +00:00
2016-01-21 13:26:30 +00:00
return True
2013-11-23 11:36:27 +00:00
def create ( self , cr , uid , vals , context = None ) :
if context is None :
context = { }
2014-04-30 09:36:13 +00:00
self . _set_date ( cr , uid , vals , id = False , context = context )
2014-01-10 17:09:12 +00:00
if not ' user_id ' in vals : # Else bug with quick_create when we are filter on an other user
2013-11-23 11:36:27 +00:00
vals [ ' user_id ' ] = uid
2014-01-10 17:09:12 +00:00
2014-01-15 09:38:05 +00:00
res = super ( calendar_event , self ) . create ( cr , uid , vals , context = context )
2014-03-14 10:57:53 +00:00
2014-04-30 09:36:13 +00:00
final_date = self . _get_recurrency_end_date ( cr , uid , res , context = context )
2014-05-05 15:42:46 +00:00
self . write ( cr , uid , [ res ] , { ' final_date ' : final_date } , context = context )
2014-03-14 10:57:53 +00:00
2013-11-23 11:36:27 +00:00
self . create_attendees ( cr , uid , [ res ] , context = context )
return res
2015-08-27 12:49:35 +00:00
def export_data ( self , cr , uid , ids , * args , * * kwargs ) :
""" Override to convert virtual ids to ids """
real_ids = [ ]
for real_id in get_real_ids ( ids ) :
if real_id not in real_ids :
real_ids . append ( real_id )
return super ( calendar_event , self ) . export_data ( cr , uid , real_ids , * args , * * kwargs )
2014-04-09 10:42:30 +00:00
def read_group ( self , cr , uid , domain , fields , groupby , offset = 0 , limit = None , context = None , orderby = False , lazy = True ) :
2014-07-06 14:44:26 +00:00
context = dict ( context or { } )
2013-11-23 11:36:27 +00:00
if ' date ' in groupby :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( ' Group by date is not supported, use the calendar view instead. ' ) )
virtual_id = context . get ( ' virtual_id ' , True )
context . update ( { ' virtual_id ' : False } )
2014-04-09 10:51:27 +00:00
res = super ( calendar_event , self ) . read_group ( cr , uid , domain , fields , groupby , offset = offset , limit = limit , context = context , orderby = orderby , lazy = lazy )
2013-11-23 11:36:27 +00:00
return res
def read ( self , cr , uid , ids , fields = None , context = None , load = ' _classic_read ' ) :
if context is None :
context = { }
fields2 = fields and fields [ : ] or None
2014-05-05 15:42:46 +00:00
EXTRAFIELDS = ( ' class ' , ' user_id ' , ' duration ' , ' allday ' , ' start ' , ' start_date ' , ' start_datetime ' , ' rrule ' )
2013-11-23 11:36:27 +00:00
for f in EXTRAFIELDS :
if fields and ( f not in fields ) :
fields2 . append ( f )
2014-12-31 10:56:28 +00:00
if isinstance ( ids , ( basestring , int , long ) ) :
2013-11-23 11:36:27 +00:00
select = [ ids ]
else :
select = ids
2013-12-19 14:47:39 +00:00
select = map ( lambda x : ( x , calendar_id2real_id ( x ) ) , select )
2013-11-23 11:36:27 +00:00
result = [ ]
2014-01-15 09:38:05 +00:00
real_data = super ( calendar_event , self ) . read ( cr , uid , [ real_id for calendar_id , real_id in select ] , fields = fields2 , context = context , load = load )
2013-11-23 11:36:27 +00:00
real_data = dict ( zip ( [ x [ ' id ' ] for x in real_data ] , real_data ) )
2014-01-10 17:09:12 +00:00
2013-12-19 14:47:39 +00:00
for calendar_id , real_id in select :
2013-11-23 11:36:27 +00:00
res = real_data [ real_id ] . copy ( )
2014-04-30 09:36:13 +00:00
ls = calendar_id2real_id ( calendar_id , with_date = res and res . get ( ' duration ' , 0 ) > 0 and res . get ( ' duration ' ) or 1 )
2014-12-31 10:56:28 +00:00
if not isinstance ( ls , ( basestring , int , long ) ) and len ( ls ) > = 2 :
2014-05-05 15:42:46 +00:00
res [ ' start ' ] = ls [ 1 ]
res [ ' stop ' ] = ls [ 2 ]
2014-04-30 09:36:13 +00:00
if res [ ' allday ' ] :
2014-05-05 15:42:46 +00:00
res [ ' start_date ' ] = ls [ 1 ]
res [ ' stop_date ' ] = ls [ 2 ]
2014-04-30 09:36:13 +00:00
else :
2014-05-05 15:42:46 +00:00
res [ ' start_datetime ' ] = ls [ 1 ]
res [ ' stop_datetime ' ] = ls [ 2 ]
2014-04-30 09:36:13 +00:00
2014-08-05 15:40:22 +00:00
if ' display_time ' in fields :
res [ ' display_time ' ] = self . _get_display_time ( cr , uid , ls [ 1 ] , ls [ 2 ] , res [ ' duration ' ] , res [ ' allday ' ] , context = context )
2014-04-30 09:36:13 +00:00
2013-12-19 14:47:39 +00:00
res [ ' id ' ] = calendar_id
2013-11-23 11:36:27 +00:00
result . append ( res )
for r in result :
if r [ ' user_id ' ] :
2014-01-10 17:09:12 +00:00
user_id = type ( r [ ' user_id ' ] ) in ( tuple , list ) and r [ ' user_id ' ] [ 0 ] or r [ ' user_id ' ]
if user_id == uid :
2013-11-23 11:36:27 +00:00
continue
2014-01-10 17:09:12 +00:00
if r [ ' class ' ] == ' private ' :
2013-11-23 11:36:27 +00:00
for f in r . keys ( ) :
2016-02-25 14:13:00 +00:00
recurrent_fields = self . _get_recurrent_fields ( cr , uid , context = context )
2016-03-29 14:11:00 +00:00
public_fields = list ( set ( recurrent_fields + [ ' id ' , ' allday ' , ' start ' , ' stop ' , ' display_start ' , ' display_stop ' , ' duration ' , ' user_id ' , ' state ' , ' interval ' , ' count ' , ' recurrent_id_date ' , ' rrule ' ] ) )
2016-02-25 14:13:00 +00:00
if f not in public_fields :
2013-11-23 11:36:27 +00:00
if isinstance ( r [ f ] , list ) :
r [ f ] = [ ]
else :
r [ f ] = False
2014-01-10 17:09:12 +00:00
if f == ' name ' :
2013-11-23 11:36:27 +00:00
r [ f ] = _ ( ' Busy ' )
for r in result :
for k in EXTRAFIELDS :
if ( k in r ) and ( fields and ( k not in fields ) ) :
del r [ k ]
2014-12-31 10:56:28 +00:00
if isinstance ( ids , ( basestring , int , long ) ) :
2013-11-23 11:36:27 +00:00
return result and result [ 0 ] or False
return result
2014-01-10 17:09:12 +00:00
2014-04-30 09:36:13 +00:00
def unlink ( self , cr , uid , ids , can_be_deleted = True , context = None ) :
2013-11-23 11:36:27 +00:00
if not isinstance ( ids , list ) :
ids = [ ids ]
res = False
2013-12-09 14:08:19 +00:00
ids_to_exclure = [ ]
ids_to_unlink = [ ]
2014-01-10 17:09:12 +00:00
2014-02-24 22:02:22 +00:00
for event_id in ids :
2014-04-30 09:36:13 +00:00
if can_be_deleted and len ( str ( event_id ) . split ( ' - ' ) ) == 1 : # if ID REAL
2014-04-30 13:36:23 +00:00
if self . browse ( cr , uid , int ( event_id ) , context ) . recurrent_id :
2013-12-09 14:08:19 +00:00
ids_to_exclure . append ( event_id )
else :
2014-04-30 13:36:23 +00:00
ids_to_unlink . append ( int ( event_id ) )
2013-12-09 14:08:19 +00:00
else :
ids_to_exclure . append ( event_id )
2013-11-23 11:36:27 +00:00
2013-12-09 14:08:19 +00:00
if ids_to_unlink :
2014-01-15 09:38:05 +00:00
res = super ( calendar_event , self ) . unlink ( cr , uid , ids_to_unlink , context = context )
2014-01-10 17:09:12 +00:00
if ids_to_exclure :
2013-12-09 14:08:19 +00:00
for id_to_exclure in ids_to_exclure :
res = self . write ( cr , uid , id_to_exclure , { ' active ' : False } , context = context )
2014-01-10 17:09:12 +00:00
2013-11-23 11:36:27 +00:00
return res
2014-01-10 17:09:12 +00:00
class mail_message ( osv . Model ) :
2013-11-23 11:36:27 +00:00
_inherit = " mail.message "
def search ( self , cr , uid , args , offset = 0 , limit = 0 , order = None , context = None , count = False ) :
'''
convert the search on real ids in the case it was asked on virtual ids , then call super ( )
'''
2016-04-26 12:55:41 +00:00
args = list ( args )
2013-11-23 11:36:27 +00:00
for index in range ( len ( args ) ) :
2014-12-31 10:56:28 +00:00
if args [ index ] [ 0 ] == " res_id " and isinstance ( args [ index ] [ 2 ] , basestring ) :
2016-04-26 12:55:41 +00:00
args [ index ] = ( args [ index ] [ 0 ] , args [ index ] [ 1 ] , get_real_ids ( args [ index ] [ 2 ] ) )
2013-11-23 11:36:27 +00:00
return super ( mail_message , self ) . search ( cr , uid , args , offset = offset , limit = limit , order = order , context = context , count = count )
def _find_allowed_model_wise ( self , cr , uid , doc_model , doc_dict , context = None ) :
2014-04-01 16:14:40 +00:00
if context is None :
context = { }
2014-01-15 09:38:05 +00:00
if doc_model == ' calendar.event ' :
2014-02-24 22:02:22 +00:00
order = context . get ( ' order ' , self . _order )
2014-01-14 13:37:36 +00:00
for virtual_id in self . pool [ doc_model ] . get_recurrent_ids ( cr , uid , doc_dict . keys ( ) , [ ] , order = order , context = context ) :
2013-11-23 11:36:27 +00:00
doc_dict . setdefault ( virtual_id , doc_dict [ get_real_ids ( virtual_id ) ] )
return super ( mail_message , self ) . _find_allowed_model_wise ( cr , uid , doc_model , doc_dict , context = context )
2014-01-10 17:09:12 +00:00
class ir_attachment ( osv . Model ) :
2013-11-23 11:36:27 +00:00
_inherit = " ir.attachment "
def search ( self , cr , uid , args , offset = 0 , limit = 0 , order = None , context = None , count = False ) :
'''
convert the search on real ids in the case it was asked on virtual ids , then call super ( )
'''
2016-04-26 12:55:41 +00:00
args = list ( args )
2013-11-23 11:36:27 +00:00
for index in range ( len ( args ) ) :
2014-12-31 10:56:28 +00:00
if args [ index ] [ 0 ] == " res_id " and isinstance ( args [ index ] [ 2 ] , basestring ) :
2016-04-26 12:55:41 +00:00
args [ index ] = ( args [ index ] [ 0 ] , args [ index ] [ 1 ] , get_real_ids ( args [ index ] [ 2 ] ) )
2013-11-23 11:36:27 +00:00
return super ( ir_attachment , self ) . search ( cr , uid , args , offset = offset , limit = limit , order = order , context = context , count = count )
def write ( self , cr , uid , ids , vals , context = None ) :
'''
when posting an attachment ( new or not ) , convert the virtual ids in real ids .
'''
2014-12-31 10:56:28 +00:00
if isinstance ( vals . get ( ' res_id ' ) , basestring ) :
2013-11-23 11:36:27 +00:00
vals [ ' res_id ' ] = get_real_ids ( vals . get ( ' res_id ' ) )
return super ( ir_attachment , self ) . write ( cr , uid , ids , vals , context = context )
2014-01-15 09:38:05 +00:00
2014-01-13 17:41:57 +00:00
class ir_http ( osv . AbstractModel ) :
_inherit = ' ir.http '
2014-01-15 09:38:05 +00:00
2014-01-13 17:41:57 +00:00
def _auth_method_calendar ( self ) :
2014-01-15 09:38:05 +00:00
token = request . params [ ' token ' ]
2014-02-24 22:02:22 +00:00
db = request . params [ ' db ' ]
2014-01-15 09:38:05 +00:00
2014-01-13 17:41:57 +00:00
registry = openerp . modules . registry . RegistryManager . get ( db )
attendee_pool = registry . get ( ' calendar.attendee ' )
error_message = False
with registry . cursor ( ) as cr :
2014-02-24 22:02:22 +00:00
attendee_id = attendee_pool . search ( cr , openerp . SUPERUSER_ID , [ ( ' access_token ' , ' = ' , token ) ] )
2014-01-13 17:41:57 +00:00
if not attendee_id :
error_message = """ Invalid Invitation Token. """
elif request . session . uid and request . session . login != ' anonymous ' :
# if valid session but user is not match
attendee = attendee_pool . browse ( cr , openerp . SUPERUSER_ID , attendee_id [ 0 ] )
user = registry . get ( ' res.users ' ) . browse ( cr , openerp . SUPERUSER_ID , request . session . uid )
2014-02-24 22:02:22 +00:00
if attendee . partner_id . id != user . partner_id . id :
error_message = """ Invitation cannot be forwarded via email. This event/meeting belongs to %s and you are logged in as %s . Please ask organizer to add you. """ % ( attendee . email , user . email )
2014-01-15 09:38:05 +00:00
2014-01-13 17:41:57 +00:00
if error_message :
raise BadRequest ( error_message )
2014-05-05 10:46:11 +00:00
2014-01-13 17:41:57 +00:00
return True
2014-01-15 09:38:05 +00:00
2014-02-24 22:02:22 +00:00
2013-11-23 11:36:27 +00:00
class invite_wizard ( osv . osv_memory ) :
_inherit = ' mail.wizard.invite '
def default_get ( self , cr , uid , fields , context = None ) :
'''
in case someone clicked on ' invite others ' wizard in the followers widget , transform virtual ids in real ids
'''
2015-02-20 15:10:23 +00:00
if ' default_res_id ' in context :
2015-02-20 15:52:33 +00:00
context = dict ( context , default_res_id = get_real_ids ( context [ ' default_res_id ' ] ) )
2013-11-23 11:36:27 +00:00
result = super ( invite_wizard , self ) . default_get ( cr , uid , fields , context = context )
if ' res_id ' in result :
result [ ' res_id ' ] = get_real_ids ( result [ ' res_id ' ] )
return result