From bbfe5e703218f32b322777136f61757c7ad37782 Mon Sep 17 00:00:00 2001 From: "rpa (Open ERP)" Date: Tue, 19 Jan 2010 15:12:24 +0530 Subject: [PATCH 1/9] [REF]: caldav, crm: Moved caldav stuff from crm.meeting to caldav bzr revid: rpa@openerp.co.in-20100119094224-37iahxu4uzsot8bz --- addons/caldav/__init__.py | 1 + addons/caldav/__terp__.py | 3 +- addons/caldav/caldav_data.xml | 14 +- addons/caldav/calendar.py | 18 +- addons/caldav/common.py | 387 +++++++++++++++-- addons/caldav/security/ir.model.access.csv | 14 +- addons/caldav/wizard/__init__.py | 28 ++ .../wizard/wizard_cal_edit_event.py} | 31 +- .../wizard/wizard_cal_export.py | 13 +- .../wizard/wizard_cal_import.py | 11 +- .../wizard/wizard_cal_subscribe.py | 11 +- addons/crm/crm_meeting.py | 391 ++---------------- addons/crm/crm_meeting_view.xml | 2 +- addons/crm/crm_meeting_wizard.xml | 24 +- addons/crm/wizard/__init__.py | 5 - 15 files changed, 489 insertions(+), 464 deletions(-) create mode 100755 addons/caldav/wizard/__init__.py rename addons/{crm/wizard/crm_meeting_edit_wizard.py => caldav/wizard/wizard_cal_edit_event.py} (74%) rename addons/{crm => caldav}/wizard/wizard_cal_export.py (86%) rename addons/{crm => caldav}/wizard/wizard_cal_import.py (90%) rename addons/{crm => caldav}/wizard/wizard_cal_subscribe.py (90%) diff --git a/addons/caldav/__init__.py b/addons/caldav/__init__.py index e658ddcda72..2b6241a8f9d 100644 --- a/addons/caldav/__init__.py +++ b/addons/caldav/__init__.py @@ -21,5 +21,6 @@ import calendar import common +import wizard # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/caldav/__terp__.py b/addons/caldav/__terp__.py index a9f2b5befca..694b0f4365d 100644 --- a/addons/caldav/__terp__.py +++ b/addons/caldav/__terp__.py @@ -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, diff --git a/addons/caldav/caldav_data.xml b/addons/caldav/caldav_data.xml index 2b942d3b9ff..2043dd3e6e4 100644 --- a/addons/caldav/caldav_data.xml +++ b/addons/caldav/caldav_data.xml @@ -76,7 +76,7 @@ 3 hours before - + hours @@ -86,7 +86,7 @@ 4 hours before - + hours @@ -96,7 +96,7 @@ 5 hours before - + hours @@ -106,7 +106,7 @@ 18 hours before - + hours @@ -115,9 +115,9 @@ - - + + Run Event Reminder diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py index ec0a98d8af5..c746967692c 100644 --- a/addons/caldav/calendar.py +++ b/addons/caldav/calendar.py @@ -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() diff --git a/addons/caldav/common.py b/addons/caldav/common.py index 2119584a399..b897e1e3e08 100644 --- a/addons/caldav/common.py +++ b/addons/caldav/common.py @@ -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', []): diff --git a/addons/caldav/security/ir.model.access.csv b/addons/caldav/security/ir.model.access.csv index 00855f665e9..fabb3c42484 100644 --- a/addons/caldav/security/ir.model.access.csv +++ b/addons/caldav/security/ir.model.access.csv @@ -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 diff --git a/addons/caldav/wizard/__init__.py b/addons/caldav/wizard/__init__.py new file mode 100755 index 00000000000..e02dcdc0b06 --- /dev/null +++ b/addons/caldav/wizard/__init__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). +# +# 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 . +# +############################################################################## + +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: + diff --git a/addons/crm/wizard/crm_meeting_edit_wizard.py b/addons/caldav/wizard/wizard_cal_edit_event.py similarity index 74% rename from addons/crm/wizard/crm_meeting_edit_wizard.py rename to addons/caldav/wizard/wizard_cal_edit_event.py index dbb25f499c1..cfe98c65ea8 100644 --- a/addons/crm/wizard/crm_meeting_edit_wizard.py +++ b/addons/caldav/wizard/wizard_cal_edit_event.py @@ -22,46 +22,45 @@ import wizard import pooler -class meeting_edit_this(wizard.interface): - case_form = """ -
+class event_edit_this(wizard.interface): + event_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: diff --git a/addons/crm/wizard/wizard_cal_export.py b/addons/caldav/wizard/wizard_cal_export.py similarity index 86% rename from addons/crm/wizard/wizard_cal_export.py rename to addons/caldav/wizard/wizard_cal_export.py index d6064b926fd..4b32f02420f 100644 --- a/addons/crm/wizard/wizard_cal_export.py +++ b/addons/caldav/wizard/wizard_cal_export.py @@ -24,7 +24,7 @@ import base64 import pooler -class crm_cal_export_wizard(wizard.interface): +class cal_event_export_wizard(wizard.interface): form1 = '''
@@ -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: diff --git a/addons/crm/wizard/wizard_cal_import.py b/addons/caldav/wizard/wizard_cal_import.py similarity index 90% rename from addons/crm/wizard/wizard_cal_import.py rename to addons/caldav/wizard/wizard_cal_import.py index 58f2c1f34bb..259b3b48b03 100644 --- a/addons/crm/wizard/wizard_cal_import.py +++ b/addons/caldav/wizard/wizard_cal_import.py @@ -23,7 +23,7 @@ import wizard import pooler -class crm_cal_import_wizard(wizard.interface): +class cal_event_import_wizard(wizard.interface): form1 = ''' @@ -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: diff --git a/addons/crm/wizard/wizard_cal_subscribe.py b/addons/caldav/wizard/wizard_cal_subscribe.py similarity index 90% rename from addons/crm/wizard/wizard_cal_subscribe.py rename to addons/caldav/wizard/wizard_cal_subscribe.py index f51bbe29fb8..4fcdeffd89f 100644 --- a/addons/crm/wizard/wizard_cal_subscribe.py +++ b/addons/caldav/wizard/wizard_cal_subscribe.py @@ -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 = ''' @@ -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: diff --git a/addons/crm/crm_meeting.py b/addons/crm/crm_meeting.py index c1f4cbf995a..53c2219ae71 100644 --- a/addons/crm/crm_meeting.py +++ b/addons/crm/crm_meeting.py @@ -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: diff --git a/addons/crm/crm_meeting_view.xml b/addons/crm/crm_meeting_view.xml index 0f625fa1af7..b1b3c4b61f5 100644 --- a/addons/crm/crm_meeting_view.xml +++ b/addons/crm/crm_meeting_view.xml @@ -83,7 +83,7 @@