[REF]: caldav, crm: Moved caldav stuff from crm.meeting to caldav

bzr revid: rpa@openerp.co.in-20100119094224-37iahxu4uzsot8bz
This commit is contained in:
rpa (Open ERP) 2010-01-19 15:12:24 +05:30
parent ad017e1b39
commit bbfe5e7032
15 changed files with 489 additions and 464 deletions

View File

@ -21,5 +21,6 @@
import calendar
import common
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -43,7 +43,8 @@
"demo_xml" : [],
"update_xml" : [
'security/ir.model.access.csv',
'caldav_view.xml'
'caldav_view.xml',
'caldav_wizard.xml',
],
"installable" : True,
"active" : False,

View File

@ -76,7 +76,7 @@
<record model="res.alarm" id="alarm9">
<field name="name">3 hours before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="3" />
<field name="trigger_interval">hours</field>
@ -86,7 +86,7 @@
<record model="res.alarm" id="alarm10">
<field name="name">4 hours before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="4" />
<field name="trigger_interval">hours</field>
@ -96,7 +96,7 @@
<record model="res.alarm" id="alarm11">
<field name="name">5 hours before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="5" />
<field name="trigger_interval">hours</field>
@ -106,7 +106,7 @@
<record model="res.alarm" id="alarm12">
<field name="name">18 hours before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="18" />
<field name="trigger_interval">hours</field>
@ -115,9 +115,9 @@
</record>
<!-- Scheduler for Event Alarm-->
<record forcecreate="True" id="ir_cron_scheduler_alarm"
model="ir.cron">
<!-- Scheduler for Event Alarm-->
<record forcecreate="True" id="ir_cron_scheduler_alarm"
model="ir.cron">
<field name="name">Run Event Reminder</field>
<field eval="True" name="active" />
<field name="user_id" ref="base.user_root" />

View File

@ -42,7 +42,7 @@ def map_data(cr, uid, obj):
if field_type == 'selection':
if not map_val:
continue
mapping =obj.__attribute__[map_dict].get('mapping', False)
mapping = obj.__attribute__[map_dict].get('mapping', False)
if mapping:
map_val = mapping[map_val.lower()]
else:
@ -97,12 +97,12 @@ class CalDAV(object):
val = self.__attribute__.get(name).get(type, None)
valtype = self.__attribute__.get(name).get('type', None)
if type == 'value':
if valtype and valtype=='datetime' and val:
if valtype and valtype == 'datetime' and val:
if isinstance(val, list):
val = ','.join(map(lambda x: x.strftime('%Y-%m-%d %H:%M:%S'), val))
else:
val = val.strftime('%Y-%m-%d %H:%M:%S')
if valtype and valtype=='integer' and val:
if valtype and valtype == 'integer' and val:
val = int(val)
return val
else:
@ -122,7 +122,7 @@ class CalDAV(object):
map_field = self.ical_get(field, 'field')
map_type = self.ical_get(field, 'type')
if map_field in data.keys():
if field == 'uid' :
if field == 'uid':
model = context.get('model', None)
if not model:
continue
@ -155,7 +155,7 @@ class CalDAV(object):
elif map_type == "timedelta":
vevent.add(field).value = timedelta(hours=data[map_field])
elif map_type == "many2one":
vevent.add(field).value = [data.get(map_field)[1]]
vevent.add(field).value = [data.get(map_field)[1]]
if self.__attribute__.get(field).has_key('mapping'):
for key1, val1 in self.ical_get(field, 'mapping').items():
if val1 == data[map_field]:
@ -377,15 +377,15 @@ class Alarm(CalDAV, osv.osv_memory):
related = 'before'
if not seconds:
duration = abs(days)
related = days>0 and 'after' or 'before'
related = days > 0 and 'after' or 'before'
elif (abs(diff) / 3600) == 0:
duration = abs(diff / 60)
interval = 'minutes'
related = days>=0 and 'after' or 'before'
related = days >= 0 and 'after' or 'before'
else:
duration = abs(diff / 3600)
interval = 'hours'
related = days>=0 and 'after' or 'before'
related = days >= 0 and 'after' or 'before'
self.ical_set('trigger_interval', interval, 'value')
self.ical_set('trigger_duration', duration, 'value')
self.ical_set('trigger_occurs', related.lower(), 'value')
@ -439,7 +439,7 @@ class Attendee(CalDAV, osv.osv_memory):
attendee_add.params[a_key] = [str(attendee[a_val['field']])]
if a_val['field'] == 'cn':
cn_val = [str(attendee[a_val['field']])]
attendee_add.params['CN']= cn_val
attendee_add.params['CN'] = cn_val
return vevent
Attendee()

View File

@ -21,9 +21,12 @@
from datetime import datetime, timedelta
from datetime import datetime, timedelta
from dateutil import parser
from osv import fields, osv
from service import web_services
from tools.translate import _
import base64
import re
import time
@ -48,7 +51,7 @@ def real_id2caldav_id(real_id, recurrent_date):
if real_id and recurrent_date:
recurrent_date = time.strftime("%Y%m%d%H%M%S", \
time.strptime(recurrent_date, "%Y-%m-%d %H:%M:%S"))
return '%d-%s'%(real_id, recurrent_date)
return '%d-%s' % (real_id, recurrent_date)
return real_id
def uid2openobjectid(cr, uidval, oomodel, rdate):
@ -221,8 +224,8 @@ request was delegated to"),
'partner_address_id': fields.many2one('res.partner.address', 'Contact'),
'partner_id':fields.related('partner_address_id', 'partner_id', type='many2one', relation='res.partner', string='Partner'),
'email': fields.char('Email', size=124),
'event_date' : fields.function(_compute_data, method=True, string='Event Date', type="datetime", multi='event_date'),
'event_end_date' : fields.function(_compute_data, method=True, string='Event End Date', type="datetime", multi='event_end_date'),
'event_date': fields.function(_compute_data, method=True, string='Event Date', type="datetime", multi='event_date'),
'event_end_date': fields.function(_compute_data, method=True, string='Event End Date', type="datetime", multi='event_end_date'),
'ref': fields.reference('Document Ref', selection=_links_get, size=128),
'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"),
}
@ -318,8 +321,8 @@ are both optional, but if one occurs, so MUST the other"""),
alarm_ids = alarm_obj.search(cr, uid, [('model_id', '=', model_id), ('res_id', '=', datas.id)])
if alarm_ids and len(alarm_ids):
alarm_obj.unlink(cr, uid, alarm_ids)
cr.execute('Update crm_meeting set caldav_alarm_id=NULL, \
alarm_id=NULL where id=%s' % (datas.id))
cr.execute('Update %s set caldav_alarm_id=NULL, \
alarm_id=NULL where id=%s' % (self._table, datas.id))
cr.commit()
return True
@ -356,12 +359,12 @@ or contains the text to be used for display"""),
'attach': fields.binary('Attachment', help="""* Points to a sound resource, which is rendered when the alarm is triggered for audio,
* File which is intended to be sent as message attachments for email,
* Points to a procedure resource, which is invoked when the alarm is triggered for procedure."""),
'res_id' : fields.integer('Resource ID'),
'res_id': fields.integer('Resource ID'),
'model_id': fields.many2one('ir.model', 'Model'),
'user_id': fields.many2one('res.users', 'Owner'),
'event_date' : fields.datetime('Event Date'),
'event_end_date' : fields.datetime('Event End Date'),
'trigger_date' : fields.datetime('Trigger Date', readonly="True"),
'event_date': fields.datetime('Event Date'),
'event_end_date': fields.datetime('Event End Date'),
'trigger_date': fields.datetime('Trigger Date', readonly="True"),
'state':fields.selection([
('draft', 'Draft'),
('run', 'Run'),
@ -372,7 +375,7 @@ or contains the text to be used for display"""),
_defaults = {
'action': lambda *x: 'email',
'state' : lambda *x: 'run',
'state': lambda *x: 'run',
}
def create(self, cr, uid, vals, context={}):
@ -411,7 +414,7 @@ or contains the text to be used for display"""),
'act_to': alarm.user_id.id,
'body': alarm.description,
'trigger_date': alarm.trigger_date,
'ref_doc1' : '%s,%s' %(alarm.model_id.model, alarm.res_id)
'ref_doc1': '%s,%s' % (alarm.model_id.model, alarm.res_id)
}
request_id = request_obj.create(cr, uid, value)
request_ids = [request_id]
@ -422,17 +425,17 @@ or contains the text to be used for display"""),
request_obj.request_send(cr, uid, request_ids)
if alarm.action == 'email':
sub = '[Openobject Remainder] %s' %(alarm.name)
sub = '[Openobject Remainder] %s' % (alarm.name)
body = """
Name : %s
Date : %s
Description : %s
Name: %s
Date: %s
Description: %s
From :
From:
%s
%s
""" %(alarm.name, alarm.trigger_date, alarm.description, \
""" % (alarm.name, alarm.trigger_date, alarm.description, \
alarm.user_id.name, alarm.user_id.sign)
mail_to = [alarm.user_id.address_id.email]
for att in alarm.attendee_ids:
@ -449,6 +452,344 @@ or contains the text to be used for display"""),
calendar_alarm()
class calendar_event(osv.osv):
_name = "calendar.event"
_description = "Calendar Event"
#kept it until fields mapping implemented
__attribute__ = {
'class': {'field': 'class', 'type': 'selection'},
'created': {'field': 'create_date', 'type': 'datetime'},
'description': {'field': 'description', 'type': 'text'},
'dtstart': {'field': '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'},
'recurrence-id': {'field': 'recurrent_id', 'type': 'datetime'},
'attendee': {'field': 'attendee_ids', 'type': 'many2many', 'object': 'calendar.attendee'},
'categories': {'field': 'categ_id', 'type': 'many2one', 'object': 'crm.meeting.categ'},
'comment': None,
'contact': None,
'exdate': {'field': 'exdate', 'type': 'datetime'},
'exrule': {'field': 'exrule', 'type': 'text'},
'rstatus': None,
'related': None,
'resources': None,
'rdate': None,
'rrule': {'field': 'rrule', 'type': 'text'},
'x-openobject-model': {'value': _name, 'type': 'text'},
'dtend': {'field': 'date_deadline', 'type': 'datetime'},
'valarm': {'field': 'caldav_alarm_id', 'type': 'many2one', 'object': 'calendar.alarm'},
}
def onchange_rrule_type(self, cr, uid, ids, rtype, *args, **argv):
if rtype == 'none' or not rtype:
return {'value': {'rrule': ''}}
if rtype == 'custom':
return {}
rrule = self.pool.get('calendar.custom.rrule')
rrulestr = rrule.compute_rule_string(cr, uid, {'freq': rtype.upper(), \
'interval': 1})
return {'value': {'rrule': rrulestr}}
def _get_duration(self, cr, uid, ids, name, arg, context):
res = {}
for event in self.browse(cr, uid, ids, context=context):
start = datetime.strptime(event.date, "%Y-%m-%d %H:%M:%S")
end = datetime.strptime(event.date_deadline[:19], "%Y-%m-%d %H:%M:%S")
diff = end - start
duration = float(diff.days)* 24 + (float(diff.seconds) / 3600)
res[event.id] = round(duration, 2)
return res
def _set_duration(self, cr, uid, id, name, value, arg, context):
event = self.browse(cr, uid, id, context=context)
start = datetime.strptime(event.date, "%Y-%m-%d %H:%M:%S")
end = start + timedelta(hours=value)
cr.execute("UPDATE %s set date_deadline='%s' \
where id=%s"% (self._table, end.strftime("%Y-%m-%d %H:%M:%S"), id))
return True
_columns = {
'name': fields.char('Description', size=64, required=True),
'date': fields.datetime('Date'),
'date_deadline': fields.datetime('Deadline'),
'duration': fields.function(_get_duration, method=True, \
fnct_inv=_set_duration, string='Duration'),
'description': fields.text('Your action'),
'class': fields.selection([('public', 'Public'), ('private', 'Private'), \
('confidential', 'Confidential')], 'Mark as'),
'location': fields.char('Location', size=264, help="Location of Event"),
'show_as': fields.selection([('free', 'Free'), \
('busy', 'Busy')],
'Show as'),
'caldav_url': fields.char('Caldav URL', size=264),
'exdate': fields.text('Exception Date/Times', help="This property \
defines the list of date/time exceptions for arecurring calendar component."),
'exrule': fields.char('Exception Rule', size=352, help="defines a \
rule or repeating pattern for anexception to a recurrence set"),
'rrule': fields.char('Recurrent Rule', size=124),
'rrule_type': fields.selection([('none', 'None'), ('daily', 'Daily'), \
('weekly', 'Weekly'), ('monthly', 'Monthly'), \
('yearly', 'Yearly'), ('custom', 'Custom')], 'Recurrency'),
'attendee_ids': fields.many2many('calendar.attendee', 'event_attendee_rel', 'event_id', 'attendee_id', 'Attendees'),
'alarm_id': fields.many2one('res.alarm', 'Alarm'),
'caldav_alarm_id': fields.many2one('calendar.alarm', 'Alarm'),
'recurrent_uid': fields.integer('Recurrent ID'),
'recurrent_id': fields.datetime('Recurrent ID date'),
}
_defaults = {
'class': lambda *a: 'public',
'show_as': lambda *a: 'busy',
}
def export_cal(self, cr, uid, ids, context={}):
ids = map(lambda x: caldav_id2real_id(x), ids)
event_data = self.read(cr, uid, ids)
event_obj = self.pool.get('basic.calendar.event')
event = self.pool.get('calendar.event')
event_obj.__attribute__.update(event.__attribute__)
ical = event_obj.export_ical(cr, uid, event_data, context={'model': self._name})
cal_val = ical.serialize()
cal_val = cal_val.replace('"', '').strip()
return cal_val
def import_cal(self, cr, uid, data, context={}):
file_content = base64.decodestring(data)
event_obj = self.pool.get('basic.calendar.event')
event = self.pool.get('calendar.event')
event_obj.__attribute__.update(event.__attribute__)
attendee_obj = self.pool.get('basic.calendar.attendee')
attendee = self.pool.get('calendar.attendee')
attendee_obj.__attribute__.update(attendee.__attribute__)
alarm_obj = self.pool.get('basic.calendar.alarm')
alarm = self.pool.get('calendar.alarm')
alarm_obj.__attribute__.update(alarm.__attribute__)
vals = event_obj.import_ical(cr, uid, file_content)
ids = []
for val in vals:
exists, r_id = uid2openobjectid(cr, val['id'], self._name, \
val.get('recurrent_id'))
if val.has_key('create_date'): val.pop('create_date')
val['caldav_url'] = context.get('url') or ''
val.pop('id')
if exists and r_id:
val.update({'recurrent_uid': exists})
self.write(cr, uid, [r_id], val)
ids.append(r_id)
elif exists:
self.write(cr, uid, [exists], val)
ids.append(exists)
else:
event_id = self.create(cr, uid, val)
ids.append(event_id)
return ids
def modify_this(self, cr, uid, ids, defaults, context=None, *args):
datas = self.read(cr, uid, ids[0], context=context)
date = datas.get('date')
defaults.update({
'recurrent_uid': caldav_id2real_id(datas['id']),
'recurrent_id': defaults.get('date'),
'rrule_type': 'none',
'rrule': ''
})
new_id = self.copy(cr, uid, ids[0], default=defaults, context=context)
return new_id
def get_recurrent_ids(self, cr, uid, select, base_start_date, base_until_date, limit=100):
if not limit:
limit = 100
if isinstance(select, (str, int, long)):
ids = [select]
else:
ids = select
result = []
if ids and (base_start_date or base_until_date):
cr.execute("select m.id, m.rrule, m.date, m.exdate \
from " + self._table + " m where m.id in ("\
+ ','.join(map(lambda x: str(x), ids))+")")
count = 0
for data in cr.dictfetchall():
start_date = base_start_date and datetime.strptime(base_start_date, "%Y-%m-%d") or False
until_date = base_until_date and datetime.strptime(base_until_date, "%Y-%m-%d") or False
if count > limit:
break
event_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
if start_date and start_date <= event_date:
start_date = event_date
if not data['rrule']:
if start_date and event_date < start_date:
continue
if until_date and event_date > until_date:
continue
idval = real_id2caldav_id(data['id'], data['date'])
result.append(idval)
count += 1
else:
exdate = data['exdate'] and data['exdate'].split(',') or []
event_obj = self.pool.get('basic.calendar.event')
rrule_str = data['rrule']
new_rrule_str = []
rrule_until_date = False
is_until = False
for rule in rrule_str.split(';'):
name, value = rule.split('=')
if name == "UNTIL":
is_until = True
value = parser.parse(value)
rrule_until_date = parser.parse(value.strftime("%Y-%m-%d"))
if until_date and until_date >= rrule_until_date:
until_date = rrule_until_date
if until_date:
value = until_date.strftime("%Y%m%d%H%M%S")
new_rule = '%s=%s' % (name, value)
new_rrule_str.append(new_rule)
if not is_until and until_date:
value = until_date.strftime("%Y%m%d%H%M%S")
name = "UNTIL"
new_rule = '%s=%s' % (name, value)
new_rrule_str.append(new_rule)
new_rrule_str = ';'.join(new_rrule_str)
start_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
rdates = event_obj.get_recurrent_dates(str(new_rrule_str), exdate, start_date)
for rdate in rdates:
r_date = datetime.strptime(rdate, "%Y-%m-%d %H:%M:%S")
if start_date and r_date < start_date:
continue
if until_date and r_date > until_date:
continue
idval = real_id2caldav_id(data['id'], rdate)
result.append(idval)
count += 1
if result:
ids = result
if isinstance(select, (str, int, long)):
return ids and ids[0] or False
return ids
def search(self, cr, uid, args, offset=0, limit=100, order=None,
context=None, count=False):
args_without_date = []
start_date = False
until_date = False
for arg in args:
if arg[0] not in ('date', unicode('date')):
args_without_date.append(arg)
else:
if arg[1] in ('>', '>='):
start_date = arg[2]
elif arg[1] in ('<', '<='):
until_date = arg[2]
res = super(calendar_event, self).search(cr, uid, args_without_date, offset,
limit, order, context, count)
return self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit)
def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
new_ids = []
for id in select:
id = caldav_id2real_id(id)
if not id in new_ids:
new_ids.append(id)
res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context)
if vals.get('alarm_id'):
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date')
return res
def browse(self, cr, uid, ids, context=None, list_class=None, fields_process={}):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = map(lambda x: caldav_id2real_id(x), select)
res = super(calendar_event, self).browse(cr, uid, select, context, list_class, fields_process)
if isinstance(ids, (str, int, long)):
return res and res[0] or False
return res
def read(self, cr, uid, ids, fields=None, context={}, load='_classic_read'):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = map(lambda x: (x, caldav_id2real_id(x)), select)
result = []
if fields and 'date' not in fields:
fields.append('date')
for caldav_id, real_id in select:
res = super(calendar_event, self).read(cr, uid, real_id, fields=fields, context=context, \
load=load)
ls = caldav_id2real_id(caldav_id, with_date=True)
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
res['date'] = ls[1]
res['id'] = caldav_id
result.append(res)
if isinstance(ids, (str, int, long)):
return result and result[0] or False
return result
def copy(self, cr, uid, id, default=None, context={}):
res = super(calendar_event, self).copy(cr, uid, caldav_id2real_id(id), default, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date')
return res
def unlink(self, cr, uid, ids, context=None):
res = False
for id in ids:
ls = caldav_id2real_id(id)
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
date_new = ls[1]
for record in self.read(cr, uid, [caldav_id2real_id(id)], \
['date', 'rrule', 'exdate']):
if record['rrule']:
exdate = (record['exdate'] and (record['exdate'] + ',') or '') + \
''.join((re.compile('\d')).findall(date_new)) + 'Z'
if record['date'] == date_new:
res = self.write(cr, uid, [caldav_id2real_id(id)], {'exdate': exdate})
else:
ids = map(lambda x: caldav_id2real_id(x), ids)
res = super(calendar_event, self).unlink(cr, uid, caldav_id2real_id(ids))
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_unlink(cr, uid, ids, self._name)
else:
ids = map(lambda x: caldav_id2real_id(x), ids)
res = super(calendar_event, self).unlink(cr, uid, ids)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_unlink(cr, uid, ids, self._name)
return res
def create(self, cr, uid, vals, context={}):
res = super(calendar_event, self).create(cr, uid, vals, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date')
return res
calendar_event()
class ir_attachment(osv.osv):
_name = 'ir.attachment'
_inherit = 'ir.attachment'
@ -481,10 +822,10 @@ class ir_values(osv.osv):
new_model.append((data[0], caldav_id2real_id(data[1])))
else:
new_model.append(data)
return super(ir_values, self).set(cr, uid, key, key2, name, new_model,\
return super(ir_values, self).set(cr, uid, key, key2, name, new_model, \
value, replace, isobject, meta, preserve_user, company)
def get(self, cr, uid, key, key2, models, meta=False, context={},\
def get(self, cr, uid, key, key2, models, meta=False, context={}, \
res_id_req=False, without_user=True, key2_req=True):
new_model = []
for data in models:
@ -579,7 +920,7 @@ class calendar_custom_rrule(osv.osv):
freq = datas.get('freq')
if freq == 'None':
obj.write(cr, uid, [res_obj.id], {'rrule' : ''})
obj.write(cr, uid, [res_obj.id], {'rrule': ''})
return {}
if freq == 'weekly':
@ -630,7 +971,7 @@ class calendar_custom_rrule(osv.osv):
res_obj = obj.browse(cr, uid, context['active_id'])
rrule_string = self.compute_rule_string(cr, uid, datas)
obj.write(cr, uid, [res_obj.id], {'rrule' : rrule_string})
obj.write(cr, uid, [res_obj.id], {'rrule': rrule_string})
return {}
calendar_custom_rrule()
@ -653,7 +994,7 @@ class res_users(osv.osv):
status = 'busy'
res.update({user_id:status})
#TOCHECK : Delegrated Event
#TOCHECK: Delegrated Event
#cr.execute("SELECT user_id,'busy' FROM att_del_to_user_rel where user_id = ANY(%s)", (ids,))
#res.update(cr.dictfetchall())
for user_id in ids:
@ -698,7 +1039,7 @@ class invite_attendee_wizard(osv.osv_memory):
res_obj = obj.browse(cr, uid, context['active_id'])
type = datas.get('type')
att_obj = self.pool.get('calendar.attendee')
vals = {'ref': '%s,%s'%(model, caldav_id2real_id(context['active_id']))}
vals = {'ref': '%s,%s' % (model, caldav_id2real_id(context['active_id']))}
if type == 'internal':
user_obj = self.pool.get('res.users')
for user_id in datas.get('user_ids', []):

View File

@ -1,6 +1,10 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"basic_calendar_all","basic.calendar","model_basic_calendar",,1,1,1,1
"basic_calendar_event_all","basic.calendar.event","model_basic_calendar_event",,1,1,1,1
"basic_calendar_attendee_all","basic.calendar.attendee","model_basic_calendar_attendee",,1,1,1,1
"access_basic_calendar_attendee","calendar.attendee","model_basic_calendar_attendee",,1,1,1,1
"access_basic_calendar_alarm","calendar.alarm","model_basic_calendar_alarm",,1,1,1,1
"access_basic_calendar_all","basic.calendar","model_basic_calendar",,1,1,1,1
"access_basic_calendar_event_all","basic.calendar.event","model_basic_calendar_event",,1,1,1,1
"access_basic_calendar_attendee_all","basic.calendar.attendee","model_basic_calendar_attendee",,1,1,1,1
"access_calendar_todo_all","basic.calendar.todo","model_basic_calendar_todo",,1,1,1,1
"access_calendar_todo_all","basic.calendar.todo","model_basic_calendar_todo",,1,1,1,1
"access_calendar_attendee","calendar.attendee","model_calendar_attendee",,1,1,1,1
"access_calendar_alarm","calendar.alarm","model_calendar_alarm",,1,1,1,1
"access_res_alarm","res.alarm","model_res_alarm",,1,1,1,1
"access_calendar_event_all","calendar.event","model_calendar_event",,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 basic_calendar_all access_basic_calendar_all basic.calendar model_basic_calendar 1 1 1 1
3 basic_calendar_event_all access_basic_calendar_event_all basic.calendar.event model_basic_calendar_event 1 1 1 1
4 basic_calendar_attendee_all access_basic_calendar_attendee_all basic.calendar.attendee model_basic_calendar_attendee 1 1 1 1
5 access_basic_calendar_attendee access_calendar_todo_all calendar.attendee basic.calendar.todo model_basic_calendar_attendee model_basic_calendar_todo 1 1 1 1
6 access_basic_calendar_alarm access_calendar_todo_all calendar.alarm basic.calendar.todo model_basic_calendar_alarm model_basic_calendar_todo 1 1 1 1
7 access_calendar_attendee calendar.attendee model_calendar_attendee 1 1 1 1
8 access_calendar_alarm calendar.alarm model_calendar_alarm 1 1 1 1
9 access_res_alarm res.alarm model_res_alarm 1 1 1 1
10 access_calendar_event_all calendar.event model_calendar_event 1 1 1 1

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import wizard_cal_export
import wizard_cal_import
import wizard_cal_subscribe
import wizard_cal_edit_event
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -22,46 +22,45 @@
import wizard
import pooler
class meeting_edit_this(wizard.interface):
case_form = """<?xml version="1.0"?>
<form string="Edit Meeting">
class event_edit_this(wizard.interface):
event_form = """<?xml version="1.0"?>
<form string="Edit Event">
<separator string="" colspan="4" />
<newline />
<field name='name' colspan="4" />
<newline />
<field name='location' colspan="4" />
<newline />
<field name='categ_id'/>
<newline />
<field name='date' />
<field name='date_deadline' />
<newline />
<field name='alarm_id'/>
</form>"""
case_fields = {
event_fields = {
'name': {'string': 'Title', 'type': 'char', 'size': 64},
'date': {'string': 'Start Date', 'type': 'datetime'},
'date_deadline': {'string': 'End Date', 'type': 'datetime'},
'location': {'string': 'Location', 'type': 'char', 'size': 124},
'categ_id': {'string': 'Category', 'type': 'many2one', 'relation': 'crm.meeting.categ'},
'alarm_id': {'string': 'Reminder', 'type': 'many2one', 'relation': 'res.alarm'},
}
def _default_values(self, cr, uid, data, context):
case_obj = pooler.get_pool(cr.dbname).get('crm.meeting')
case = case_obj.read(cr, uid, data['id'], ['name', 'location', 'date',\
'date_deadline', 'categ_id', 'alarm_id'])
return case
model = data.get('model')
model_obj = pooler.get_pool(cr.dbname).get(model)
event = model_obj.read(cr, uid, data['id'], ['name', 'location', 'date',\
'date_deadline', 'alarm_id'])
return event
def _modify_this(self, cr, uid, datas, *args):
case_obj = pooler.get_pool(cr.dbname).get('crm.meeting')
new_id = case_obj.modify_this(cr, uid, [datas['id']], datas['form'])
model = datas.get('model')
model_obj = pooler.get_pool(cr.dbname).get(model)
new_id = model_obj.modify_this(cr, uid, [datas['id']], datas['form'])
value = {
'name': 'New event',
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'crm.meeting',
'res_model': model,
'res_id': new_id,
'view_id': False,
'type': 'ir.actions.act_window',
@ -71,7 +70,7 @@ class meeting_edit_this(wizard.interface):
states = {
'init': {
'actions': [_default_values],
'result': {'type': 'form', 'arch': case_form, 'fields': case_fields,
'result': {'type': 'form', 'arch': event_form, 'fields': event_fields,
'state': [('end', 'Cancel', 'gtk-cancel'), ('edit', '_Save', 'gtk-save')]}
},
'edit': {
@ -80,6 +79,6 @@ class meeting_edit_this(wizard.interface):
}
}
meeting_edit_this('crm.meeting.edit.this')
event_edit_this('calendar.event.edit.this')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -24,7 +24,7 @@ import base64
import pooler
class crm_cal_export_wizard(wizard.interface):
class cal_event_export_wizard(wizard.interface):
form1 = '''<?xml version="1.0"?>
<form string="Export ICS">
<field name="name"/>
@ -35,8 +35,8 @@ class crm_cal_export_wizard(wizard.interface):
'file_path': {
'string': 'Save ICS file',
'type': 'binary',
'required' : True,
'filters' : '*.ics'
'required': True,
'filters': '*.ics'
},
'name': {
'string': 'File name',
@ -47,8 +47,9 @@ class crm_cal_export_wizard(wizard.interface):
}
def _process_export_ics(self, cr, uid, data, context):
case_obj = pooler.get_pool(cr.dbname).get('crm.meeting')
calendar = case_obj.export_cal(cr, uid, data['ids'], context)
model = data.get('model')
model_obj = pooler.get_pool(cr.dbname).get(model)
calendar = model_obj.export_cal(cr, uid, data['ids'], context)
return {'file_path': base64.encodestring(calendar), \
'name': 'OpenERP Events.ics'}
@ -59,6 +60,6 @@ class crm_cal_export_wizard(wizard.interface):
'state': [('end', '_Cancel', 'gtk-cancel'), ('end', 'Ok', 'gtk-ok')]}},
}
crm_cal_export_wizard('caldav.crm.export')
cal_event_export_wizard('caldav.event.export')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -23,7 +23,7 @@ import wizard
import pooler
class crm_cal_import_wizard(wizard.interface):
class cal_event_import_wizard(wizard.interface):
form1 = '''<?xml version="1.0"?>
<form string="Import ICS">
<separator string="Select ICS file"/>
@ -52,8 +52,9 @@ class crm_cal_import_wizard(wizard.interface):
}
def _process_imp_ics(self, cr, uid, data, context=None):
case_obj = pooler.get_pool(cr.dbname).get('crm.meeting')
vals = case_obj.import_cal(cr, uid, data['form']['file_path'], context)
model = data.get('model')
model_obj = pooler.get_pool(cr.dbname).get(model)
vals = model_obj.import_cal(cr, uid, data['form']['file_path'], context)
global cnt
cnt = 0
if vals:
@ -72,7 +73,7 @@ class crm_cal_import_wizard(wizard.interface):
'open': {
'actions': [],
'result': {'type': 'action', 'action': _process_imp_ics, 'state': 'display'}
},
},
'display': {
'actions': [_result_set],
'result': {'type': 'form', 'arch': display, 'fields': display_fields, \
@ -80,6 +81,6 @@ class crm_cal_import_wizard(wizard.interface):
},
}
crm_cal_import_wizard('caldav.crm.import')
cal_event_import_wizard('caldav.event.import')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -25,7 +25,7 @@ import pooler
import urllib
import wizard
class crm_cal_subscribe_wizard(wizard.interface):
class cal_event_subscribe_wizard(wizard.interface):
form1 = '''<?xml version="1.0"?>
<form string="Subscribe to Remote ICS">
<separator string="Provide path for Remote Calendar"/>
@ -58,13 +58,14 @@ class crm_cal_subscribe_wizard(wizard.interface):
cnt = 0
try:
f = urllib.urlopen(data['form']['url_path'])
caldata= f.fp.read()
caldata = f.fp.read()
f.close()
except Exception,e:
raise wizard.except_wizard(_('Error!'), _('Please provide Proper URL !'))
case_obj = pooler.get_pool(cr.dbname).get('crm.meeting')
model = data.get('model')
model_obj = pooler.get_pool(cr.dbname).get(model)
context.update({'url': data['form']['url_path']})
vals = case_obj.import_cal(cr, uid, base64.encodestring(caldata), context)
vals = model_obj.import_cal(cr, uid, base64.encodestring(caldata), context)
if vals:
cnt = vals['count']
return {}
@ -89,6 +90,6 @@ class crm_cal_subscribe_wizard(wizard.interface):
},
}
crm_cal_subscribe_wizard('caldav.crm.subscribe')
cal_event_subscribe_wizard('caldav.event.subscribe')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -19,391 +19,46 @@
#
##############################################################################
from caldav import common
from datetime import datetime, timedelta
from dateutil import parser
from osv import fields, osv
from tools.translate import _
import base64
import re
class crm_meeting(osv.osv):
_name = 'crm.meeting'
_description = "Meeting Cases"
_order = "id desc"
_inherit = "crm.case"
__attribute__ = {
'class': {'field': 'class', 'type': 'selection'},
'created': {'field': 'create_date', 'type': 'datetime'},
'description': {'field': 'description', 'type': 'text'},
'dtstart': {'field': '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'},
'recurrence-id': {'field': 'recurrent_id', 'type': 'datetime'},
'attendee': {'field': 'attendee_ids', 'type': 'many2many', 'object': 'calendar.attendee'},
'categories': {'field': 'categ_id', 'type': 'many2one', 'object': 'crm.case.categ'},
'comment': None,
'contact': None,
'exdate': {'field': 'exdate', 'type': 'datetime'},
'exrule': {'field': 'exrule', 'type': 'text'},
'rstatus': None,
'related': None,
'resources': None,
'rdate': None,
'rrule': {'field': 'rrule', 'type': 'text'},
'x-openobject-model': {'value': _name, 'type': 'text'},
'dtend': {'field': 'date_deadline', 'type': 'datetime'},
'valarm': {'field': 'caldav_alarm_id', 'type': 'many2one', 'object': 'calendar.alarm'},
}
def _get_duration(self, cr, uid, ids, name, arg, context):
res = {}
for meeting in self.browse(cr, uid, ids, context=context):
start = datetime.strptime(meeting.date, "%Y-%m-%d %H:%M:%S")
end = datetime.strptime(meeting.date_deadline[:19], "%Y-%m-%d %H:%M:%S")
diff = end - start
duration = float(diff.days)* 24 + (float(diff.seconds) / 3600)
res[meeting.id] = round(duration, 2)
return res
def _set_duration(self, cr, uid, id, name, value, arg, context):
meeting = self.browse(cr, uid, id, context=context)
start = datetime.strptime(meeting.date, "%Y-%m-%d %H:%M:%S")
end = start + timedelta(hours=value)
cr.execute("UPDATE crm_meeting set date_deadline='%s' \
where id=%s"% (end.strftime("%Y-%m-%d %H:%M:%S"), id))
return True
def onchange_rrule_type(self, cr, uid, ids, rtype, *args, **argv):
if rtype == 'none' or not rtype:
return {'value': {'rrule': ''}}
if rtype == 'custom':
return {}
rrule = self.pool.get('calendar.custom.rrule')
rrulestr = rrule.compute_rule_string(cr, uid, {'freq': rtype.upper(), \
'interval': 1})
return {'value': {'rrule': rrulestr}}
_inherit = ["crm.case", "calendar.event"]
_columns = {
'id': fields.integer('ID', readonly=True),
'name': fields.char('Description', size=64, required=True),
'section_id': fields.many2one('crm.case.section', 'Section', select=True, help='Section to which Case belongs to. Define Responsible user and Email \
account for mail gateway.'),
'priority': fields.selection([('5','Lowest'),
('4','Low'),
('3','Normal'),
('2','High'),
('1','Highest')
], 'Priority'),
'date': fields.datetime('Date'),
'date_deadline': fields.datetime('Deadline'),
'duration': fields.function(_get_duration, method=True, \
fnct_inv=_set_duration, string='Duration'),
('4','Low'),
('3','Normal'),
('2','High'),
('1','Highest')
], 'Priority'),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.meeting')]", \
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.meeting')]", \
help='Category related to the section.Subdivide the CRM cases \
independently or section-wise.'),
'description': fields.text('Your action'),
'class': fields.selection([('public', 'Public'), ('private', 'Private'), \
('confidential', 'Confidential')], 'Mark as'),
'location': fields.char('Location', size=264, help="Location of Meeting"),
'show_as': fields.selection([('free', 'Free'), \
('busy', 'Busy')],
'Show as'),
'caldav_url': fields.char('Caldav URL', size=264),
'exdate': fields.text('Exception Date/Times', help="This property \
defines the list of date/time exceptions for arecurring calendar component."),
'exrule': fields.char('Exception Rule', size=352, help="defines a \
rule or repeating pattern for anexception to a recurrence set"),
'rrule': fields.char('Recurrent Rule', size=124),
'rrule_type': fields.selection([('none', 'None'), ('daily', 'Daily'), \
('weekly', 'Weekly'), ('monthly', 'Monthly'), \
('yearly', 'Yearly'), ('custom', 'Custom')], 'Recurrency'),
'attendee_ids': fields.many2many('calendar.attendee', 'crm_attendee_rel', 'case_id', 'attendee_id', 'Attendees'),
'alarm_id': fields.many2one('res.alarm', 'Alarm'),
'caldav_alarm_id': fields.many2one('calendar.alarm', 'Alarm'),
'recurrent_uid': fields.integer('Recurrent ID'),
'recurrent_id': fields.datetime('Recurrent ID date'),
}
_defaults = {
'class': lambda *a: 'public',
'show_as': lambda *a: 'busy',
}
def on_change_duration(self, cr, uid, id, date, duration):
if not date:
return {}
start_date = datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
if duration >= 0:
end = start_date + datetime.timedelta(hours=duration)
if duration < 0:
raise osv.except_osv(_('Warning !'),
_('You can not set negative Duration.'))
res = {'value': {'date_deadline': end.strftime('%Y-%m-%d %H:%M:%S')}}
return res
def export_cal(self, cr, uid, ids, context={}):
ids = map(lambda x: common.caldav_id2real_id(x), ids)
crm_data = self.read(cr, uid, ids)
event_obj = self.pool.get('basic.calendar.event')
event_obj.__attribute__.update(self.__attribute__)
ical = event_obj.export_ical(cr, uid, crm_data, context={'model': self._name})
cal_val = ical.serialize()
cal_val = cal_val.replace('"', '').strip()
return cal_val
def import_cal(self, cr, uid, data, context={}):
file_content = base64.decodestring(data)
event_obj = self.pool.get('basic.calendar.event')
event_obj.__attribute__.update(self.__attribute__)
attendee_obj = self.pool.get('basic.calendar.attendee')
attendee = self.pool.get('calendar.attendee')
attendee_obj.__attribute__.update(attendee.__attribute__)
alarm_obj = self.pool.get('basic.calendar.alarm')
alarm = self.pool.get('calendar.alarm')
alarm_obj.__attribute__.update(alarm.__attribute__)
vals = event_obj.import_ical(cr, uid, file_content)
ids = []
for val in vals:
exists, r_id = common.uid2openobjectid(cr, val['id'], self._name, \
val.get('recurrent_id'))
if val.has_key('create_date'): val.pop('create_date')
val['caldav_url'] = context.get('url') or ''
val.pop('id')
if exists and r_id:
val.update({'recurrent_uid': exists})
self.write(cr, uid, [r_id], val)
ids.append(r_id)
elif exists:
self.write(cr, uid, [exists], val)
ids.append(exists)
else:
case_id = self.create(cr, uid, val)
ids.append(case_id)
return ids
def get_recurrent_ids(self, cr, uid, select, base_start_date, base_until_date, limit=100):
if not limit:
limit = 100
if isinstance(select, (str, int, long)):
ids = [select]
else:
ids = select
result = []
if ids and (base_start_date or base_until_date):
cr.execute("select m.id, m.rrule, m.date, m.exdate \
from crm_meeting m\
where m.id in ("+ ','.join(map(lambda x: str(x), ids))+")")
count = 0
for data in cr.dictfetchall():
start_date = base_start_date and datetime.strptime(base_start_date, "%Y-%m-%d") or False
until_date = base_until_date and datetime.strptime(base_until_date, "%Y-%m-%d") or False
if count > limit:
break
event_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
if start_date and start_date <= event_date:
start_date = event_date
if not data['rrule']:
if start_date and event_date < start_date:
continue
if until_date and event_date > until_date:
continue
idval = common.real_id2caldav_id(data['id'], data['date'])
result.append(idval)
count += 1
else:
exdate = data['exdate'] and data['exdate'].split(',') or []
event_obj = self.pool.get('basic.calendar.event')
rrule_str = data['rrule']
new_rrule_str = []
rrule_until_date = False
is_until = False
for rule in rrule_str.split(';'):
name, value = rule.split('=')
if name == "UNTIL":
is_until = True
value = parser.parse(value)
rrule_until_date = parser.parse(value.strftime("%Y-%m-%d"))
if until_date and until_date >= rrule_until_date:
until_date = rrule_until_date
if until_date:
value = until_date.strftime("%Y%m%d%H%M%S")
new_rule = '%s=%s' % (name, value)
new_rrule_str.append(new_rule)
if not is_until and until_date:
value = until_date.strftime("%Y%m%d%H%M%S")
name = "UNTIL"
new_rule = '%s=%s' % (name, value)
new_rrule_str.append(new_rule)
new_rrule_str = ';'.join(new_rrule_str)
start_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
rdates = event_obj.get_recurrent_dates(str(new_rrule_str), exdate, start_date)
for rdate in rdates:
r_date = datetime.strptime(rdate, "%Y-%m-%d %H:%M:%S")
if start_date and r_date < start_date:
continue
if until_date and r_date > until_date:
continue
idval = common.real_id2caldav_id(data['id'], rdate)
result.append(idval)
count += 1
if result:
ids = result
if isinstance(select, (str, int, long)):
return ids and ids[0] or False
return ids
def modify_this(self, cr, uid, ids, defaults, context=None, *args):
datas = self.read(cr, uid, ids[0], context=context)
date = datas.get('date')
defaults.update({
'recurrent_uid': common.caldav_id2real_id(datas['id']),
'recurrent_id': defaults.get('date'),
'rrule_type': 'none',
'rrule': ''
})
new_id = self.copy(cr, uid, ids[0], default=defaults, context=context)
return new_id
def search(self, cr, uid, args, offset=0, limit=100, order=None,
context=None, count=False):
args_without_date = []
start_date = False
until_date = False
for arg in args:
if arg[0] not in ('date', unicode('date')):
args_without_date.append(arg)
else:
if arg[1] in ('>', '>='):
start_date = arg[2]
elif arg[1] in ('<', '<='):
until_date = arg[2]
res = super(crm_meeting, self).search(cr, uid, args_without_date, offset,
limit, order, context, count)
return self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit)
def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
new_ids = []
for id in select:
id = common.caldav_id2real_id(id)
if not id in new_ids:
new_ids.append(id)
res = super(crm_meeting, self).write(cr, uid, new_ids, vals, context=context)
if vals.get('alarm_id'):
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date')
return res
def browse(self, cr, uid, ids, context=None, list_class=None, fields_process={}):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = map(lambda x: common.caldav_id2real_id(x), select)
res = super(crm_meeting, self).browse(cr, uid, select, context, list_class, fields_process)
if isinstance(ids, (str, int, long)):
return res and res[0] or False
return res
def read(self, cr, uid, ids, fields=None, context={}, load='_classic_read'):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = map(lambda x: (x, common.caldav_id2real_id(x)), select)
result = []
if fields and 'date' not in fields:
fields.append('date')
for caldav_id, real_id in select:
res = super(crm_meeting, self).read(cr, uid, real_id, fields=fields, context=context, \
load=load)
ls = common.caldav_id2real_id(caldav_id, with_date=True)
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
res['date'] = ls[1]
res['id'] = caldav_id
result.append(res)
if isinstance(ids, (str, int, long)):
return result and result[0] or False
return result
def copy(self, cr, uid, id, default=None, context={}):
res = super(crm_meeting, self).copy(cr, uid, common.caldav_id2real_id(id), default, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date')
return res
def unlink(self, cr, uid, ids, context=None):
res = False
for id in ids:
ls = common.caldav_id2real_id(id)
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
date_new = ls[1]
for record in self.read(cr, uid, [common.caldav_id2real_id(id)], \
['date', 'rrule', 'exdate']):
if record['rrule']:
exdate = (record['exdate'] and (record['exdate'] + ',') or '') + \
''.join((re.compile('\d')).findall(date_new)) + 'Z'
if record['date'] == date_new:
res = self.write(cr, uid, [common.caldav_id2real_id(id)], {'exdate': exdate})
else:
ids = map(lambda x: common.caldav_id2real_id(x), ids)
res = super(crm_meeting, self).unlink(cr, uid, common.caldav_id2real_id(ids))
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_unlink(cr, uid, ids, self._name)
else:
ids = map(lambda x: common.caldav_id2real_id(x), ids)
res = super(crm_meeting, self).unlink(cr, uid, ids)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_unlink(cr, uid, ids, self._name)
return res
def create(self, cr, uid, vals, context={}):
res = super(crm_meeting, self).create(cr, uid, vals, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date')
def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
}
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
data.update(res)
res = self.create(cr, uid, data)
return res
crm_meeting()
class res_users(osv.osv):
_inherit = 'res.users'
def _get_user_avail(self, cr, uid, ids, context=None):
current_datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
res = super(res_users, self)._get_user_avail(cr, uid, ids, context)
cr.execute("SELECT m.user_id, 'busy' as status \
FROM crm_meeting m\
where m.date <= %s and m.date_deadline >= %s \
and m.user_id = ANY(%s) and m.show_as = %s",
(current_datetime, current_datetime, ids, 'busy'))
result = cr.dictfetchall()
for user_data in result:
user_id = user_data['user_id']
status = user_data['status']
res.update({user_id:status})
return res
res_users()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -83,7 +83,7 @@
<group col="3" colspan="4" attrs="{'invisible':[('rrule_type','in', ('none', False))]}">
<label string="" />
<button string="Modify this Occurrence"
name="%(crm.wizard_meeting_edit_this)d" icon="gtk-save"
name="%(caldav.wizard_edit_this_event)d" icon="gtk-save"
type="action" context="{'model' : 'crm.meeting'}" />
</group>
</form>

View File

@ -1,20 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<wizard string="Import ICS File" model="crm.meeting"
name="caldav.crm.import" id="wizard_crm_cal_import" multi="True"
/>
<wizard string="Subscribe to a Remote calendar" model="crm.meeting"
name="caldav.crm.subscribe" id="wizard_crm_cal_subscribe" multi="True"
/>
<wizard string="Export ICS File" model="crm.meeting"
name="caldav.crm.export" id="wizard_crm_cal_export" multi="True" />
<wizard string="Import .ics File" model="crm.meeting"
name="caldav.event.import" id="caldav.wizard_cal_event_import" multi="True" />
<wizard string="Edit this meeting" model="crm.meeting"
name="crm.meeting.edit.this" id="wizard_meeting_edit_this"
<wizard string="Subscribe to a Remote calendar"
model="crm.meeting" name="caldav.event.subscribe"
id="caldav.wizard_cal_event_subscribe" multi="True" />
<wizard string="Export .ics File" model="crm.meeting"
name="caldav.event.export" id="caldav.wizard_cal_event_export" multi="True" />
<wizard string="Edit this event" model="crm.meeting"
name="calendar.event.edit.this" id="caldav.wizard_edit_this_event"
menu="False" />
</data>
</openerp>

View File

@ -22,14 +22,9 @@
import crm_opportunity_wizard
import crm_lead_wizard
import crm_phonecall_wizard
import crm_meeting_edit_wizard
import wizard_crm_send_email
import wizard_crm_new_send_email
import wizard_cal_export
import wizard_cal_import
import wizard_cal_subscribe
import wizard_history_event