2009-12-04 08:40:21 +00:00
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields , osv
from time import strftime
import time
import base64
import vobject
from dateutil . rrule import *
from dateutil import parser
from datetime import datetime
from time import strftime
from pytz import timezone
import tools
class crm_section ( osv . osv ) :
_name = ' crm.case.section '
_inherit = ' crm.case.section '
_description = ' Cases Section '
def export_cal ( self , cr , uid , ids , context = { } ) :
# Set all property of CalDAV
self . export_ical ( )
def import_cal ( self , cr , uid , ids , context = { } ) :
self . import_ical ( cr , uid )
# get all property of CalDAV
crm_section ( )
2009-12-04 14:15:17 +00:00
class crm_caldav_attendee ( osv . osv ) :
_name = ' crm.caldav.attendee '
2009-12-04 08:40:21 +00:00
_description = ' Attendee information '
_rec_name = ' cutype '
__attribute__ = {
' cutype ' : { ' field ' : ' cutype ' , ' type ' : ' text ' } , # Use: 0-1 Specify the type of calendar user specified by the property like "INDIVIDUAL"/"GROUP"/"RESOURCE"/"ROOM"/"UNKNOWN".
' member ' : { ' field ' : ' member ' , ' type ' : ' text ' } , # Use: 0-1 Specify the group or list membership of the calendar user specified by the property.
' role ' : { ' field ' : ' role ' , ' type ' : ' text ' } , # Use: 0-1 Specify the participation role for the calendar user specified by the property like "CHAIR"/"REQ-PARTICIPANT"/"OPT-PARTICIPANT"/"NON-PARTICIPANT"
' partstat ' : { ' field ' : ' partstat ' , ' type ' : ' text ' } , # Use: 0-1 Specify the participation status for the calendar user specified by the property. like use for VEVENT :- "NEEDS-ACTION"/"ACCEPTED"/"DECLINED"/"TENTATIVE"/"DELEGATED", use for VTODO :-"NEEDS-ACTION"/"ACCEPTED"/"DECLINED"/"TENTATIVE"/"DELEGATED"/"COMPLETED"/"IN-PROCESS" and use for VJOURNAL :- "NEEDS-ACTION"/"ACCEPTED"/"DECLINED".
' rsvp ' : { ' field ' : ' rsvp ' , ' type ' : ' boolean ' } , # Use: 0-1 Specify whether there is an expectation of a favor of a reply from the calendar user specified by the property value like TRUE / FALSE.
' delegated-to ' : { ' field ' : ' delegated_to ' , ' type ' : ' char ' } , # Use: 0-1 Specify the calendar users to whom the calendar user specified by the property has delegated participation.
' delegated-from ' : { ' field ' : ' delegated_from ' , ' type ' : ' char ' } , # Use: 0-1 Specify the calendar users that have delegated their participation to the calendar user specified by the property.
' sent-by ' : { ' field ' : ' sent_by ' , ' type ' : ' text ' } , # Use: 0-1 Specify the calendar user that is acting on behalf of the calendar user specified by the property.
' cn ' : { ' field ' : ' cn ' , ' type ' : ' text ' } , # Use: 0-1 Specify the common name to be associated with the calendar user specified by the property.
' dir ' : { ' field ' : ' dir ' , ' type ' : ' text ' } , # Use: 0-1 Specify reference to a directory entry associated with the calendar user specified by the property.
' language ' : { ' field ' : ' language ' , ' type ' : ' text ' } , # Use: 0-1 Specify the language for text values in a property or property parameter.
}
_columns = {
' cutype ' : fields . selection ( [ ( ' INDIVIDUAL ' , ' INDIVIDUAL ' ) , ( ' GROUP ' , ' GROUP ' ) , \
( ' RESOURCE ' , ' RESOURCE ' ) , ( ' ROOM ' , ' ROOM ' ) , ( ' UNKNOWN ' , ' UNKNOWN ' ) ] , ' CUTYPE ' ) ,
' member ' : fields . char ( ' Member ' , size = 124 ) ,
' role ' : fields . selection ( [ ( ' CHAIR ' , ' CHAIR ' ) , ( ' REQ-PARTICIPANT ' , ' REQ-PARTICIPANT ' ) , \
( ' OPT-PARTICIPANT ' , ' OPT-PARTICIPANT ' ) , ( ' NON-PARTICIPANT ' , ' NON-PARTICIPANT ' ) ] , ' ROLE ' ) ,
' partstat ' : fields . selection ( [ ( ' NEEDS-ACTION ' , ' NEEDS-ACTION ' ) , ( ' ACCEPTED ' , ' ACCEPTED ' ) , \
( ' DECLINED ' , ' DECLINED ' ) , ( ' TENTATIVE ' , ' TENTATIVE ' ) , ( ' DELEGATED ' , ' DELEGATED ' ) ] , ' PARTSTAT ' ) ,
' rsvp ' : fields . boolean ( ' RSVP ' ) ,
' delegated_to ' : fields . char ( ' DELEGATED-TO ' , size = 124 ) ,
' delegated_from ' : fields . char ( ' DELEGATED-FROM ' , size = 124 ) ,
' sent_by ' : fields . char ( ' SENT-BY ' , size = 124 ) ,
' cn ' : fields . char ( ' CN ' , size = 124 ) ,
' dir ' : fields . char ( ' DIR ' , size = 124 ) ,
' language ' : fields . char ( ' LANGUAGE ' , size = 124 ) ,
}
2009-12-04 14:15:17 +00:00
crm_caldav_attendee ( )
2009-12-04 08:40:21 +00:00
2009-12-07 14:02:31 +00:00
class crm_caldav_alarm ( osv . osv ) :
_name = ' crm.caldav.alarm '
_description = ' Event alarm information '
__attribute__ = {
}
_columns = {
' name ' : fields . char ( ' Summary ' , size = 124 ) ,
' action ' : fields . selection ( [ ( ' AUDIO ' , ' AUDIO ' ) , ( ' DISPLAY ' , ' DISPLAY ' ) , \
( ' PROCEDURE ' , ' PROCEDURE ' ) , ( ' EMAIL ' , ' EMAIL ' ) ] , ' Action ' , required = True ) ,
' description ' : fields . text ( ' Description ' ) ,
' attendee ' : fields . many2many ( ' crm.caldav.attendee ' , ' alarm_attendee_rel ' , ' alarm_id ' , ' attendee_id ' , ' Attendees ' ) ,
' trigger_related ' : fields . selection ( [ ( ' BEFORE ' , ' BEFORE ' ) , ( ' AFTER ' , ' AFTER ' ) ] \
, ' Trigger time ' , required = True ) ,
' trigger_duration ' : fields . selection ( [ ( ' MINUTES ' , ' MINUTES ' ) , ( ' HOURS ' , ' HOURS ' ) , \
( ' DAYS ' , ' DAYS ' ) ] , ' Trugger duration ' , required = True ) ,
' trigger_interval ' : fields . integer ( ' TIme ' , required = True ) ,
' trigger_occurs ' : fields . selection ( [ ( ' starts ' , ' The event starts ' ) , ( ' ends ' , ' The event ends ' ) ] , \
' Trigger Occures at ' , required = True ) ,
' duration ' : fields . integer ( ' Duration ' ) ,
' repeat ' : fields . integer ( ' Repeat ' ) , # TODO
' attach ' : fields . binary ( ' Attachment ' ) ,
}
_defaults = {
' action ' : lambda * x : ' EMAIL ' ,
' trigger_interval ' : lambda * x : 5 ,
' trigger_duration ' : lambda * x : ' MINUTES ' ,
' trigger_related ' : lambda * x : ' BEFORE ' ,
' trigger_occurs ' : lambda * x : ' starts ' ,
}
crm_caldav_alarm ( )
2009-12-04 08:40:21 +00:00
class crm_case ( osv . osv ) :
_name = ' crm.case '
_inherit = ' crm.case '
_description = ' Cases '
__attribute__ = {
' class ' : { ' field ' : ' class ' , ' type ' : ' text ' } ,
' created ' : { ' field ' : ' create_date ' , ' type ' : ' datetime ' } , # keep none for now
' description ' : { ' field ' : ' description ' , ' type ' : ' text ' } ,
' dtstart ' : { ' field ' : ' date ' , ' type ' : ' datetime ' } ,
#'last-mod' : {'field':'write_date', 'type':'datetime'},
' location ' : { ' field ' : ' location ' , ' type ' : ' text ' } ,
' organizer ' : { ' field ' : ' partner_id ' , ' sub-field ' : ' name ' , ' type ' : ' many2one ' } ,
' priority ' : { ' field ' : ' priority ' , ' type ' : ' int ' } ,
' dtstamp ' : { ' field ' : ' date ' , ' type ' : ' datetime ' } ,
' seq ' : None ,
' status ' : { ' field ' : ' state ' , ' type ' : ' selection ' , ' mapping ' : { ' TENTATIVE ' : ' draft ' , \
' CONFIRMED ' : ' open ' , ' CANCELLED ' : ' cancel ' } } ,
' summary ' : { ' field ' : ' name ' , ' type ' : ' text ' } ,
' transp ' : { ' field ' : ' transparent ' , ' type ' : ' text ' } ,
' uid ' : { ' field ' : ' id ' , ' type ' : ' text ' } ,
' url ' : { ' field ' : ' caldav_url ' , ' type ' : ' text ' } ,
' recurid ' : None ,
# 'attach' : {'field':'attachment_ids', 'sub-field':'datas', 'type':'list'},
' attendee ' : { ' field ' : ' attendees ' , ' type ' : ' text ' } ,
# 'categories' : {'field':'categ_id', 'sub-field':'name'},
# 'categories' : {'field':None , 'sub-field':'name', 'type':'text'}, # keep none for now
' comment ' : None ,
' contact ' : None ,
' exdate ' : None ,
' exrule ' : None ,
' rstatus ' : None ,
' related ' : None ,
' resources ' : None ,
' rdate ' : None ,
' rrule ' : { ' field ' : ' rrule ' , ' type ' : ' text ' } ,
' x-openobject-id ' : { ' field ' : ' id ' , ' type ' : ' text ' } ,
' x-openobject-model ' : { ' value ' : _name , ' type ' : ' text ' } ,
# 'duration' : {'field':'duration'},
' dtend ' : { ' field ' : ' date_closed ' , ' type ' : ' datetime ' } ,
}
def _get_location ( self , cr , uid , ids , name , arg , context = None ) :
res = { }
for case in self . browse ( cr , uid , ids ) :
if case . partner_address_id :
add = case . partner_address_id
st = add . street and add . street + ' , \n ' or ' '
st2 = add . street2 and add . street2 + ' , \n ' or ' '
ct = add . city and add . city + ' , \n ' or ' '
zip = add . zip and add . zip or ' '
country = add . country_id and add . country_id . name + ' , \n ' or ' '
res [ case . id ] = st + st2 + ct + country + zip
else :
res [ case . id ] = ' '
return res
def _get_rdates ( self , cr , uid , ids , name , arg , context = None ) :
res = { }
context . update ( { ' read ' : True } )
for case in self . read ( cr , uid , ids , [ ' date ' , ' rrule ' ] , context = context ) :
if case [ ' rrule ' ] :
rule = case [ ' rrule ' ] . split ( ' \n ' ) [ 0 ]
exdate = case [ ' rrule ' ] . split ( ' \n ' ) [ 1 : ]
event_obj = self . pool . get ( ' caldav.event ' )
res [ case [ ' id ' ] ] = str ( event_obj . get_recurrent_dates ( str ( rule ) , exdate , case [ ' date ' ] ) )
return res
_columns = {
' class ' : fields . selection ( [ ( ' PUBLIC ' , ' PUBLIC ' ) , ( ' PRIVATE ' , ' PRIVATE ' ) , \
( ' CONFIDENTIAL ' , ' CONFIDENTIAL ' ) ] , ' Class ' ) ,
' location ' : fields . function ( _get_location , method = True , store = True , string = ' Location ' , type = ' text ' ) ,
' freebusy ' : fields . text ( ' FreeBusy ' ) ,
' transparent ' : fields . selection ( [ ( ' OPAQUE ' , ' OPAQUE ' ) , ( ' TRANSPARENT ' , ' TRANSPARENT ' ) ] , ' Trensparent ' ) ,
' caldav_url ' : fields . char ( ' Caldav URL ' , size = 34 ) ,
' rrule ' : fields . text ( ' Recurrent Rule ' ) ,
' rdates ' : fields . function ( _get_rdates , method = True , string = ' Recurrent Dates ' , \
store = True , type = ' text ' ) ,
2009-12-07 14:02:31 +00:00
' attendees ' : fields . many2many ( ' crm.caldav.attendee ' , ' crm_attendee_rel ' , ' case_id ' , ' attendee_id ' , ' Attendees ' ) ,
' alarm_id ' : fields . many2one ( ' crm.caldav.alarm ' , ' Alarm ' ) ,
2009-12-04 08:40:21 +00:00
}
_defaults = {
' caldav_url ' : lambda * a : ' http://localhost:8080 ' ,
' class ' : lambda * a : ' PUBLIC ' ,
' transparent ' : lambda * a : ' OPAQUE ' ,
}
def export_cal ( self , cr , uid , ids , context = { } ) :
2009-12-07 14:02:31 +00:00
crm_data = self . read ( cr , uid , ids , [ ] , context = { ' read ' : True } )
2009-12-04 08:40:21 +00:00
ical = vobject . iCalendar ( )
event_obj = self . pool . get ( ' caldav.event ' )
2009-12-04 14:15:17 +00:00
uid_val = ' '
2009-12-04 08:40:21 +00:00
for crm in crm_data :
2009-12-04 14:15:17 +00:00
vevent = ical . add ( ' vevent ' )
2009-12-04 08:40:21 +00:00
for key , val in self . __attribute__ . items ( ) :
2009-12-04 14:15:17 +00:00
if key == ' uid ' :
uid_val + = str ( crm [ val [ ' field ' ] ] )
continue
2009-12-07 14:02:31 +00:00
if val == None or key == ' rrule ' or not val . has_key ( ' field ' ) or not crm [ val [ ' field ' ] ] :
2009-12-04 08:40:21 +00:00
continue
2009-12-07 14:02:31 +00:00
if key == " attendee " :
attendee_object = self . pool . get ( ' crm.caldav.attendee ' )
for attendee in attendee_object . read ( cr , uid , crm [ val [ ' field ' ] ] , [ ] ) :
attendee_add = vevent . add ( ' attendee ' )
for a_key , a_val in attendee_object . __attribute__ . items ( ) :
if attendee [ a_val [ ' field ' ] ] :
if a_val [ ' type ' ] == ' text ' :
attendee_add . params [ a_key ] = [ str ( attendee [ a_val [ ' field ' ] ] ) ]
elif a_val [ ' type ' ] == ' boolean ' :
attendee_add . params [ a_key ] = [ str ( attendee [ a_val [ ' field ' ] ] ) ]
elif val . has_key ( ' sub-field ' ) :
2009-12-04 08:40:21 +00:00
vevent . add ( key ) . value = crm [ val [ ' field ' ] ] [ 1 ]
2009-12-07 14:02:31 +00:00
elif val . has_key ( ' mapping ' ) :
for key1 , val1 in val [ ' mapping ' ] . items ( ) :
if val1 == crm [ val [ ' field ' ] ] :
vevent . add ( key ) . value = key1
else :
2009-12-04 08:40:21 +00:00
if val [ ' type ' ] == " text " :
vevent . add ( key ) . value = str ( crm [ val [ ' field ' ] ] )
elif val [ ' type ' ] == ' datetime ' and crm [ val [ ' field ' ] ] :
vevent . add ( key ) . value = datetime . strptime ( crm [ val [ ' field ' ] ] , " % Y- % m- %d % H: % M: % S " )
if crm [ self . __attribute__ [ ' rrule ' ] [ ' field ' ] ] :
startdate = datetime . strptime ( crm [ ' date ' ] , " % Y- % m- %d % H: % M: % S " )
if not startdate :
startdate = datetime . now ( )
2009-12-07 14:02:31 +00:00
rset1 = rrulestr ( str ( crm [ self . __attribute__ [ ' rrule ' ] [ ' field ' ] ] ) , dtstart = startdate , forceset = True )
2009-12-04 08:40:21 +00:00
vevent . rruleset = rset1
2009-12-04 14:15:17 +00:00
vevent . add ( ' uid ' ) . value = uid_val
return ical . serialize ( ) #.replace(vobject.icalendar.CRLF, vobject.icalendar.LF).strip()
2009-12-04 08:40:21 +00:00
def import_cal ( self , cr , uid , ids , data , context = { } ) :
file_content = base64 . decodestring ( data [ ' form ' ] [ ' file_path ' ] )
event_obj = self . pool . get ( ' caldav.event ' )
event_obj . __attribute__ . update ( self . __attribute__ )
event_obj . import_ical ( cr , uid , file_content )
vals = { }
for map_dict in event_obj . __attribute__ :
map_val = event_obj . ical_get ( map_dict , ' value ' )
field = event_obj . ical_get ( map_dict , ' field ' )
field_type = event_obj . ical_get ( map_dict , ' type ' )
if field and map_val :
if field_type == ' selection ' :
mapping = event_obj . __attribute__ [ map_dict ] . get ( ' mapping ' , False )
if mapping :
map_val = mapping [ map_val ]
if field_type == ' many2one ' :
# TODO: Map field value to many2one object
continue # For now
vals [ field ] = map_val
# TODO: Select proper section
section_id = self . pool . get ( ' crm.case.section ' ) . search ( cr , uid , [ ] ) [ 0 ]
vals . update ( { ' section_id ' : section_id } )
vals . pop ( ' id ' )
vals . pop ( ' create_date ' )
case_id = self . create ( cr , uid , vals )
return
def search ( self , cr , uid , args , offset = 0 , limit = None , order = None ,
context = None , count = False ) :
res = super ( crm_case , self ) . search ( cr , uid , args , offset ,
limit , order , context , count )
return res
def write ( self , cr , uid , ids , vals , context = None ) :
res = super ( crm_case , self ) . write ( cr , uid , ids , vals , context = context )
return res
def browse ( self , cr , uid , select , context = None , list_class = None , fields_process = { } ) :
2009-12-04 14:15:17 +00:00
if not type ( select ) == list :
# Called from code
id = int ( str ( select ) . split ( ' - ' ) [ 0 ] )
return super ( crm_case , self ) . browse ( cr , uid , id , context , list_class , fields_process )
2009-12-04 08:40:21 +00:00
select = map ( lambda x : int ( str ( x ) . split ( ' - ' ) [ 0 ] ) , select )
return super ( crm_case , self ) . browse ( cr , uid , select , context , list_class , fields_process )
def read ( self , cr , uid , ids , fields = None , context = { } ,
load = ' _classic_read ' ) :
""" logic for recurrent event
example : 123 - 20091111170822 """
if context and context . has_key ( ' read ' ) :
return super ( crm_case , self ) . read ( cr , uid , ids , fields = fields , context = context , load = load )
2009-12-04 14:15:17 +00:00
if not type ( ids ) == list :
# Called from code
ids = int ( str ( ids ) . split ( ' - ' ) [ 0 ] )
res = super ( crm_case , self ) . read ( cr , uid , ids , fields = fields , context = context , load = load )
return res
else :
ids = map ( lambda x : int ( str ( x ) . split ( ' - ' ) [ 0 ] ) , ids )
2009-12-04 08:40:21 +00:00
res = super ( crm_case , self ) . read ( cr , uid , ids , fields = fields , context = context , load = load )
read_ids = " , " . join ( [ str ( x ) for x in ids ] )
2009-12-08 09:51:25 +00:00
if not read_ids :
return [ ]
2009-12-04 08:40:21 +00:00
cr . execute ( ' select id,rrule,rdates from crm_case where id in ( %s ) ' % read_ids )
rrules = filter ( lambda x : not x [ ' rrule ' ] == None , cr . dictfetchall ( ) )
rdates = [ ]
2009-12-04 14:15:17 +00:00
if not rrules :
return res
result = res + [ ]
2009-12-04 08:40:21 +00:00
for data in rrules :
if data [ ' rrule ' ] and data [ ' rdates ' ] : # delete 2nd condition at last
rdates = eval ( data [ ' rdates ' ] )
for res_temp in res :
if res_temp [ ' id ' ] == data [ ' id ' ] :
val = res_temp
if rdates :
result . remove ( val )
for rdate in rdates :
import re
idval = ( re . compile ( ' \ d ' ) ) . findall ( rdate )
val [ ' date ' ] = rdate
id = str ( val [ ' id ' ] ) . split ( ' - ' ) [ 0 ]
val [ ' id ' ] = id + ' - ' + ' ' . join ( idval )
val1 = val . copy ( )
result + = [ val1 ]
return result
def unlink ( self , cr , uid , ids , context = None ) :
#TODO: Change RRULE
for id in ids :
if len ( str ( id ) . split ( ' - ' ) ) > 1 :
date_new = time . strftime ( " % Y- % m- %d % H: % M: % S " , time . strptime ( str ( str ( id ) . split ( ' - ' ) [ 1 ] ) , " % Y % m %d % H % M % S " ) )
for record in self . read ( cr , uid , [ str ( id ) . split ( ' - ' ) [ 0 ] ] , [ ' date ' , ' rdates ' , ' rrule ' ] ) :
if record [ ' date ' ] == date_new :
self . write ( cr , uid , [ int ( str ( id ) . split ( ' - ' ) [ 0 ] ) ] , { ' rrule ' : record [ ' rrule ' ] + " \n " + str ( date_new ) } )
else :
return super ( crm_case , self ) . unlink ( cr , uid , ids )
crm_case ( )
class ir_attachment ( osv . osv ) :
_name = ' ir.attachment '
_inherit = ' ir.attachment '
def search_count ( self , cr , user , args , context = None ) :
args1 = [ ]
for arg in args :
args1 . append ( map ( lambda x : str ( x ) . split ( ' - ' ) [ 0 ] , arg ) )
return super ( ir_attachment , self ) . search_count ( cr , user , args1 , context )
ir_attachment ( )