from datetime import datetime, timedelta, date
from dateutil import parser
from dateutil import rrule
+from dateutil.relativedelta import relativedelta
from osv import fields, osv
from service import web_services
from tools.translate import _
if not startdate:
startdate = datetime.now()
+
if not exdate:
exdate = []
- rset1 = rrule.rrulestr(str(rrulestring), dtstart=startdate, forceset=True)
+ rset1 = rrule.rrulestr(str(rrulestring), dtstart=startdate, forceset=True)
for date in exdate:
datetime_obj = todate(date)
rset1._exdate.append(datetime_obj)
+
if exrule:
rset1.exrule(rrule.rrulestr(str(exrule), dtstart=startdate))
- return list(rset1._iter())
+ return list(rset1)
def base_calendar_id2real_id(base_calendar_id=None, with_date=False):
"""
continue
else:
result[id][name] = self._get_address(attdata.sent_by_uid.name, \
- attdata.sent_by_uid.address_id.email)
+ attdata.sent_by_uid.user_email)
if name == 'cn':
if attdata.user_id:
result[id][name] = attdata.user_id.name
- elif attdata.partner_address_id:
- result[id][name] = attdata.partner_address_id.name or attdata.partner_id.name
+ elif attdata.partner_id:
+ result[id][name] = attdata.partner_id.name or False
else:
result[id][name] = attdata.email or ''
_columns = {
'cutype': fields.selection([('individual', 'Individual'), \
('group', 'Group'), ('resource', 'Resource'), \
- ('room', 'Room'), ('unknown', '') ], \
+ ('room', 'Room'), ('unknown', 'Unknown') ], \
'Invite Type', help="Specify the type of Invitation"),
'member': fields.char('Member', size=124,
help="Indicate the groups that the attendee belongs to"),
('opt-participant', 'Optional Participation'), \
('non-participant', 'For information Purpose')], 'Role', \
help='Participation role for the calendar user'),
- 'state': fields.selection([('tentative', 'Tentative'),
- ('needs-action', 'Needs Action'),
- ('accepted', 'Accepted'),
+ 'state': fields.selection([('needs-action', 'Needs Action'),
+ ('tentative', 'Tentative'),
('declined', 'Declined'),
- ('delegated', 'Delegated')], 'State', readonly=True, \
+ ('accepted', 'Accepted'),
+ ('delegated', 'Delegated')], 'Status', readonly=True, \
help="Status of the attendee's participation"),
'rsvp': fields.boolean('Required Reply?',
help="Indicats whether the favor of a reply is requested"),
- 'delegated_to': fields.function(_compute_data, method=True, \
+ 'delegated_to': fields.function(_compute_data, \
string='Delegated To', type="char", size=124, store=True, \
multi='delegated_to', help="The users that the original \
request was delegated to"),
- 'delegated_from': fields.function(_compute_data, method=True, string=\
+ 'delegated_from': fields.function(_compute_data, string=\
'Delegated From', type="char", store=True, size=124, multi='delegated_from'),
'parent_ids': fields.many2many('calendar.attendee', 'calendar_attendee_parent_rel', \
'attendee_id', 'parent_id', 'Delegrated From'),
'child_ids': fields.many2many('calendar.attendee', 'calendar_attendee_child_rel', \
'attendee_id', 'child_id', 'Delegrated To'),
- 'sent_by': fields.function(_compute_data, method=True, string='Sent By', \
+ 'sent_by': fields.function(_compute_data, string='Sent By', \
type="char", multi='sent_by', store=True, size=124, \
help="Specify the user that is acting on behalf of the calendar user"),
- 'sent_by_uid': fields.function(_compute_data, method=True, string='Sent By User', \
+ 'sent_by_uid': fields.function(_compute_data, string='Sent By User', \
type="many2one", relation="res.users", multi='sent_by_uid'),
- 'cn': fields.function(_compute_data, method=True, string='Common name', \
+ 'cn': fields.function(_compute_data, string='Common name', \
type="char", size=124, multi='cn', store=True),
'dir': fields.char('URI Reference', size=124, help="Reference to the URI\
that points to the directory information corresponding to the attendee."),
- 'language': fields.function(_compute_data, method=True, string='Language', \
+ 'language': fields.function(_compute_data, string='Language', \
type="selection", selection=_lang_get, multi='language', \
store=True, help="To specify the language for text values in a\
property or property parameter."),
'user_id': fields.many2one('res.users', 'User'),
- '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', help="Partner related to contact"),
+ 'partner_id': fields.many2one('res.partner', 'Contact'),
'email': fields.char('Email', size=124, help="Email of Invited Person"),
- 'event_date': fields.function(_compute_data, method=True, string='Event Date', \
+ 'event_date': fields.function(_compute_data, string='Event Date', \
type="datetime", multi='event_date'),
- 'event_end_date': fields.function(_compute_data, method=True, \
+ 'event_end_date': fields.function(_compute_data, \
string='Event End Date', type="datetime", \
multi='event_end_date'),
'ref': fields.reference('Event Ref', selection=_links_get, size=128),
'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"),
- }
+ }
+
_defaults = {
'state': 'needs-action',
'role': 'req-participant',
}
def copy(self, cr, uid, id, default=None, context=None):
- raise osv.except_osv(_('Warning!'), _('Can not Duplicate'))
+ raise osv.except_osv(_('Warning!'), _('You cannot duplicate a calendar attendee.'))
def get_ics_file(self, cr, uid, event_obj, context=None):
"""
cal = vobject.iCalendar()
event = cal.add('vevent')
if not event_obj.date_deadline or not event_obj.date:
- raise osv.except_osv(_('Warning !'),_("Couldn't Invite because date is not specified!"))
+ raise osv.except_osv(_('Warning!'),_("First you have to specify the date of the invitation."))
event.add('created').value = ics_datetime(time.strftime('%Y-%m-%d %H:%M:%S'))
event.add('dtstart').value = ics_datetime(event_obj.date)
event.add('dtend').value = ics_datetime(event_obj.date_deadline)
trigger.value = delta
# Compute other details
valarm.add('DESCRIPTION').value = alarm_data['name'] or 'OpenERP'
-
+
for attendee in event_obj.attendee_ids:
attendee_add = event.add('attendee')
attendee_add.params['CUTYPE'] = [str(attendee.cutype)]
context = {}
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.name
- email_message_obj = self.pool.get('email.message')
+ mail_message = self.pool.get('mail.message')
for att in self.browse(cr, uid, ids, context=context):
sign = att.sent_by_uid and att.sent_by_uid.signature or ''
sign = '<br>'.join(sign and sign.split('\n') or [])
body = html_invitation % body_vals
if mail_to and email_from:
attach = self.get_ics_file(cr, uid, res_obj, context=context)
- email_message_obj.email_send(
+ mail_message.schedule_with_attach(cr, uid,
email_from,
mail_to,
sub,
body,
- model='calendar.attendee',
- attach=attach and [('invitation.ics', attach)] or None,
- subtype='html',
- reply_to=email_from
+ attachments=attach and {'invitation.ics': attach} or None,
+ content_subtype='html',
+ reply_to=email_from,
+ context=context
)
return True
return {'value': {'email': ''}}
usr_obj = self.pool.get('res.users')
user = usr_obj.browse(cr, uid, user_id, *args)
- return {'value': {'email': user.address_id.email, 'availability':user.availability}}
+ return {'value': {'email': user.user_email, 'availability':user.availability}}
def do_tentative(self, cr, uid, ids, context=None, *args):
""" Makes event invitation as Tentative
new_res_alarm = alarm_ids[0]
cr.execute('UPDATE %s ' % model_obj._table + \
' SET base_calendar_alarm_id=%s, alarm_id=%s ' \
- ' WHERE id=%s',
+ ' WHERE id=%s',
(cal_alarm.id, new_res_alarm, data.id))
self.do_alarm_unlink(cr, uid, [data.id], model)
('run', 'Run'),
('stop', 'Stop'),
('done', 'Done'),
- ], 'State', select=True, readonly=True),
+ ], 'Status', select=True, readonly=True),
}
_defaults = {
@param use_new_cursor: False or the dbname
@param context: A standard dictionary for contextual values
"""
- return True # XXX FIXME REMOVE THIS AFTER FIXING get_recurrent_dates!!
if context is None:
context = {}
- email_message_obj = self.pool.get('email.message')
+ mail_message = self.pool.get('mail.message')
current_datetime = datetime.now()
- request_obj = self.pool.get('res.request')
alarm_ids = self.search(cr, uid, [('state', '!=', 'done')], context=context)
mail_to = []
ref = alarm.model_id.model + ',' + str(alarm.res_id)
# search for alreay sent requests
- if request_obj.search(cr, uid, [('trigger_date', '=', r_date), ('ref_doc1', '=', ref)], context=context):
- continue
-
- if alarm.action == 'display':
- value = {
- 'name': alarm.name,
- 'act_from': alarm.user_id.id,
- 'act_to': alarm.user_id.id,
- 'body': alarm.description,
- 'trigger_date': r_date,
- 'ref_doc1': ref
- }
- request_id = request_obj.create(cr, uid, value)
- request_ids = [request_id]
- for attendee in res_obj.attendee_ids:
- if attendee.user_id:
- value['act_to'] = attendee.user_id.id
- request_id = request_obj.create(cr, uid, value)
- request_ids.append(request_id)
- request_obj.request_send(cr, uid, request_ids)
+ #if request_obj.search(cr, uid, [('trigger_date', '=', r_date), ('ref_doc1', '=', ref)], context=context):
+ #continue
+
+ # Deactivated because of the removing of res.request
+ # TODO: when cleaning calendar module, re-add this in a new mechanism
+ #if alarm.action == 'display':
+ #value = {
+ #'name': alarm.name,
+ #'act_from': alarm.user_id.id,
+ #'act_to': alarm.user_id.id,
+ #'body': alarm.description,
+ #'trigger_date': r_date,
+ #'ref_doc1': ref
+ #}
+ #request_id = request_obj.create(cr, uid, value)
+ #request_ids = [request_id]
+ #for attendee in res_obj.attendee_ids:
+ #if attendee.user_id:
+ #value['act_to'] = attendee.user_id.id
+ #request_id = request_obj.create(cr, uid, value)
+ #request_ids.append(request_id)
+ #request_obj.request_send(cr, uid, request_ids)
if alarm.action == 'email':
sub = '[Openobject Reminder] %s' % (alarm.name)
""" % (alarm.name, alarm.trigger_date, alarm.description, \
alarm.user_id.name, alarm.user_id.signature)
- mail_to = [alarm.user_id.address_id.email]
+ mail_to = [alarm.user_id.user_email]
for att in alarm.attendee_ids:
- mail_to.append(att.user_id.address_id.email)
+ mail_to.append(att.user_id.user_email)
if mail_to:
- email_message_obj.email_send(
+ mail_message.schedule_with_attach(cr, uid,
tools.config.get('email_from', False),
mail_to,
sub,
body,
- model='calendar.alarm'
+ context=context
)
if next_trigger_date:
update_vals.update({'trigger_date': next_trigger_date})
def _tz_get(self, cr, uid, context=None):
return [(x.lower(), x) for x in pytz.all_timezones]
- def onchange_allday(self, cr, uid, ids, allday, context=None):
- """Sets duration as 24 Hours if event is selected for all day
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param ids: List of calendar event’s IDs.
- @param allday: Value of allday boolean
- @param context: A standard dictionary for contextual values
- """
- if not allday or not ids:
- return {}
- value = {
- 'duration': 24
- }
- return {'value': value}
-
def onchange_dates(self, cr, uid, ids, start_date, duration=False, end_date=False, allday=False, context=None):
"""Returns duration and/or end date based on values passed
@param self: The object pointer
duration = 1.00
value['duration'] = duration
+ start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
if allday: # For all day event
- value = {'duration': 24}
duration = 24.0
+ value['duration'] = duration
+ # change start_date's time to 00:00:00 in the user's timezone
+ user = self.pool.get('res.users').browse(cr, uid, uid)
+ tz = pytz.timezone(user.context_tz) if user.context_tz else pytz.utc
+ start = pytz.utc.localize(start).astimezone(tz) # convert start in user's timezone
+ start = start.replace(hour=0, minute=0, second=0) # change start's time to 00:00:00
+ start = start.astimezone(pytz.utc) # convert start back to utc
+ start_date = start.strftime("%Y-%m-%d %H:%M:%S")
+ value['date'] = start_date
- start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
if end_date and not duration:
end = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")
diff = end - start
value['date_deadline'] = end.strftime("%Y-%m-%d %H:%M:%S")
elif end_date and duration and not allday:
# we have both, keep them synchronized:
- # set duration based on end_date (arbitrary decision: this avoid
+ # set duration based on end_date (arbitrary decision: this avoid
# getting dates like 06:31:48 instead of 06:32:00)
end = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")
diff = end - start
self.unlink(cr, uid, r_ids, context=context)
return True
- def _set_rrulestring(self, cr, uid, id, name, value, arg, context=None):
- """
- Sets values of fields that defines event recurrence from the value of rrule string
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param id: List of calendar event's ids.
- @param context: A standard dictionary for contextual values
- @return: dictionary of rrule value.
- """
- if context is None:
- context = {}
- cr.execute("UPDATE %s set freq='None',interval=0,count=0,end_date=Null,\
- mo=False,tu=False,we=False,th=False,fr=False,sa=False,su=False,\
- day=0,select1='date',month_list=Null ,byday=Null where id=%%s" % (self._table), (id,))
-
- if not value:
- cr.execute("UPDATE %s set rrule_type='none' where id=%%s" % self._table,(id,))
- return True
- val = {}
- for part in value.split(';'):
- if part.lower().__contains__('freq') and len(value.split(';')) <=2:
- rrule_type = part.lower()[5:]
- break
- else:
- rrule_type = 'custom'
- break
- ans = value.split(';')
- for i in ans:
- val[i.split('=')[0].lower()] = i.split('=')[1].lower()
- if not val.get('interval'):
- rrule_type = 'custom'
- elif int(val.get('interval')) > 1: #If interval is other than 1 rule is custom
- rrule_type = 'custom'
-
- qry = "UPDATE \"%s\" set rrule_type=%%s " % self._table
- qry_args = [ rrule_type, ]
- new_val = val.copy()
- for k, v in val.items():
- if val['freq'] == 'weekly' and val.get('byday'):
- for day in val['byday'].split(','):
- new_val[day] = True
- val.pop('byday')
-
- if val.get('until'):
- until = parser.parse(''.join((re.compile('\d')).findall(val.get('until'))))
- new_val['end_date'] = until.strftime('%Y-%m-%d')
- val.pop('until')
- new_val.pop('until')
-
- if val.get('bymonthday'):
- new_val['day'] = val.get('bymonthday')
- val.pop('bymonthday')
- new_val['select1'] = 'date'
- new_val.pop('bymonthday')
-
- if val.get('byday'):
- d = val.get('byday')
- if '-' in d:
- new_val['byday'] = d[:2]
- new_val['week_list'] = d[2:4].upper()
- else:
- new_val['byday'] = d[:1]
- new_val['week_list'] = d[1:3].upper()
- new_val['select1'] = 'day'
-
- if val.get('bymonth'):
- new_val['month_list'] = val.get('bymonth')
- val.pop('bymonth')
- new_val.pop('bymonth')
-
- for k, v in new_val.items():
- qry += ", %s=%%s" % k
- qry_args.append(v)
-
- qry = qry + " where id=%s"
- qry_args.append(id)
- cr.execute(qry, qry_args)
- return True
-
def _get_rulestring(self, cr, uid, ids, name, arg, context=None):
"""
Gets Recurrence rule string according to value type RECUR of iCalendar from the values given.
@param context: A standard dictionary for contextual values
@return: dictionary of rrule value.
"""
+
result = {}
- for datas in self.read(cr, uid, ids, context=context):
- event = datas['id']
- if datas.get('rrule_type'):
- if datas.get('rrule_type') == 'none':
- result[event] = False
- cr.execute("UPDATE %s set exrule=Null where id=%%s" % self._table,( event,))
- if datas.get('rrule_type') :
- if datas.get('interval', 0) < 0:
- raise osv.except_osv(_('Warning!'), _('Interval can not be Negative'))
- if datas.get('count', 0) < 0:
- raise osv.except_osv(_('Warning!'), _('Count can not be Negative'))
- rrule_custom = self.compute_rule_string(cr, uid, datas, \
- context=context)
- result[event] = rrule_custom
- else:
- result[event] = self.compute_rule_string(cr, uid, {'freq': datas.get('rrule_type').upper(), 'interval': 1}, context=context)
+ if not isinstance(ids, list):
+ ids = [ids]
- for id, myrule in result.items():
- #Remove the events generated from recurrent event
- if not myrule:
- self.unlink_events(cr, uid, [id], context=context)
+ for datas in self.read(cr, uid, ids, ['id','byday','recurrency', 'month_list','end_date', 'rrule_type', 'select1', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'exrule', 'day', 'week_list' ], context=context):
+ event = datas['id']
+ if datas.get('interval', 0) < 0:
+ raise osv.except_osv(_('Warning!'), _('Interval cannot be negative.'))
+ if datas.get('count', 0) < 0:
+ raise osv.except_osv(_('Warning!'), _('Count cannot be negative.'))
+ if datas['recurrency']:
+ result[event] = self.compute_rule_string(datas)
+ else:
+ result[event] = ""
return result
+ def _rrule_write(self, obj, cr, uid, ids, field_name, field_value, args, context=None):
+ data = self._get_empty_rrule_data()
+ if field_value:
+ data['recurrency'] = True
+ for event in self.browse(cr, uid, ids, context=context):
+ rdate = rule_date or event.date
+ update_data = self._parse_rrule(field_value, dict(data), rdate)
+ data.update(update_data)
+ super(calendar_event, obj).write(cr, uid, ids, data, context=context)
+ return True
+
+
_columns = {
- 'id': fields.integer('ID'),
+ 'id': fields.integer('ID', readonly=True),
'sequence': fields.integer('Sequence'),
'name': fields.char('Description', size=64, required=False, states={'done': [('readonly', True)]}),
- 'date': fields.datetime('Date', states={'done': [('readonly', True)]}),
- 'date_deadline': fields.datetime('Deadline', states={'done': [('readonly', True)]}),
+ 'date': fields.datetime('Date', states={'done': [('readonly', True)]}, required=True,),
+ 'date_deadline': fields.datetime('Deadline', states={'done': [('readonly', True)]}, required=True,),
'create_date': fields.datetime('Created', readonly=True),
'duration': fields.float('Duration', states={'done': [('readonly', True)]}),
'description': fields.text('Description', states={'done': [('readonly', True)]}),
'class': fields.selection([('public', 'Public'), ('private', 'Private'), \
- ('confidential', 'Confidential')], 'Mark as', states={'done': [('readonly', True)]}),
+ ('confidential', 'Public for Employees')], 'Privacy', states={'done': [('readonly', True)]}),
'location': fields.char('Location', size=264, help="Location of Event", states={'done': [('readonly', True)]}),
'show_as': fields.selection([('free', 'Free'), ('busy', 'Busy')], \
- 'Show as', states={'done': [('readonly', True)]}),
+ 'Show Time as', states={'done': [('readonly', True)]}),
'base_calendar_url': fields.char('Caldav URL', size=264),
'state': fields.selection([('tentative', 'Tentative'),
+ ('cancelled', 'Cancelled'),
('confirmed', 'Confirmed'),
- ('cancelled', 'Cancelled')], 'State', readonly=True),
+ ], 'Status', readonly=True),
'exdate': fields.text('Exception Date/Times', help="This property \
defines the list of date/time exceptions for a recurring calendar component."),
'exrule': fields.char('Exception Rule', size=352, help="Defines a \
rule or repeating pattern of time to exclude from the recurring rule."),
- 'rrule': fields.function(_get_rulestring, type='char', size=124, method=True, \
- string='Recurrent Rule', store=True, \
- fnct_inv=_set_rrulestring, help='Defines a\
- rule or repeating pattern for recurring events\n\
-e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
- FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=-1SU'),
+ 'rrule': fields.function(_get_rulestring, type='char', size=124, \
+ fnct_inv=_rrule_write, store=True, string='Recurrent Rule'),
'rrule_type': fields.selection([('none', ''), ('daily', 'Daily'), \
('weekly', 'Weekly'), ('monthly', 'Monthly'), \
- ('yearly', 'Yearly'),],
+ ('yearly', 'Yearly'),],
'Recurrency', states={'done': [('readonly', True)]},
help="Let the event automatically repeat at that interval"),
- 'alarm_id': fields.many2one('res.alarm', 'Alarm', states={'done': [('readonly', True)]},
+ 'alarm_id': fields.many2one('res.alarm', 'Reminder', states={'done': [('readonly', True)]},
help="Set an alarm at this time, before the event occurs" ),
'base_calendar_alarm_id': fields.many2one('calendar.alarm', 'Alarm'),
'recurrent_uid': fields.integer('Recurrent ID'),
'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}),
'organizer': fields.char("Organizer", size=256, states={'done': [('readonly', True)]}), # Map with Organizer Attribure of VEvent.
'organizer_id': fields.many2one('res.users', 'Organizer', states={'done': [('readonly', True)]}),
- 'freq': fields.selection([('None', 'No Repeat'),
- ('hourly', 'Hours'),
- ('daily', 'Days'),
- ('weekly', 'Weeks'),
- ('monthly', 'Months'),
- ('yearly', 'Years'), ], 'Frequency'),
-
- 'end_type' : fields.selection([('forever', 'Forever'), ('count', 'Fix amout of times'), ('end_date','End date')], 'Way to end reccurency'),
- 'interval': fields.integer('Repeat every', help="Repeat every (Days/Week/Month/Year)"),
+ 'end_type' : fields.selection([('count', 'Number of repetitions'), ('end_date','End date')], 'Recurrence Termination'),
+ 'interval': fields.integer('Repeat Every', help="Repeat every (Days/Week/Month/Year)"),
'count': fields.integer('Repeat', help="Repeat x times"),
'mo': fields.boolean('Mon'),
'tu': fields.boolean('Tue'),
'fr': fields.boolean('Fri'),
'sa': fields.boolean('Sat'),
'su': fields.boolean('Sun'),
- 'select1': fields.selection([('date', 'Date of month'),
+ 'select1': fields.selection([('date', 'Date of month'),
('day', 'Day of month')], 'Option'),
'day': fields.integer('Date of month'),
'week_list': fields.selection([('MO', 'Monday'), ('TU', 'Tuesday'), \
'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}),
'active': fields.boolean('Active', help="If the active field is set to \
true, it will allow you to hide the event alarm information without removing it."),
- 'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"),
- 'edit_all': fields.boolean('Edit All', help="Edit all Occurrences of recurrent Meeting."),
+ 'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"),
}
+
def default_organizer(self, cr, uid, context=None):
user_pool = self.pool.get('res.users')
user = user_pool.browse(cr, uid, uid, context=context)
return res
_defaults = {
- 'end_type' : 'forever',
+ 'end_type' : 'count',
+ 'count' : 1,
+ 'rrule_type' : 'none',
'state': 'tentative',
'class': 'public',
'show_as': 'busy',
- 'freq': 'None',
'select1': 'date',
'interval': 1,
'active': 1,
'user_id': lambda self, cr, uid, ctx: uid,
'organizer': default_organizer,
- 'edit_all' : False,
}
- def onchange_edit_all(self, cr, uid, ids, rrule_type,edit_all, context=None):
- if not context:
- context = {}
-
- value = {}
- if edit_all and rrule_type:
- for id in ids:
- base_calendar_id2real_id(id)
- return value
-
- def modify_all(self, cr, uid, event_ids, defaults, context=None, *args):
- """
- Modifies the recurring event
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param event_ids: List of crm meeting’s IDs.
- @param context: A standard dictionary for contextual values
- @return: True
- """
- for event_id in event_ids:
- event_id = base_calendar_id2real_id(event_id)
-
- defaults.pop('id')
- defaults.update({'table': self._table})
-
- qry = "UPDATE %(table)s set name = '%(name)s', \
- date = '%(date)s', date_deadline = '%(date_deadline)s'"
- if defaults.get('alarm_id'):
- qry += ", alarm_id = %(alarm_id)s"
- if defaults.get('location'):
- qry += ", location = '%(location)s'"
- qry += "WHERE id = %s" % (event_id)
- cr.execute(qry, defaults)
-
- return True
-
- def get_recurrent_ids(self, cr, uid, select, base_start_date, base_until_date, limit=100):
+ def get_recurrent_ids(self, cr, uid, select, domain, limit=100, context=None):
"""Gives virtual event ids for recurring events based on value of Recurrence Rule
This method gives ids of dates that comes between start date and end date of calendar views
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
- @param base_start_date: Get Start Date
- @param base_until_date: Get End Date
@param limit: The Number of Results to Return """
+ if not context:
+ context = {}
- if not limit:
- limit = 100
- if isinstance(select, (str, int, long)):
- ids = [select]
- else:
- ids = select
result = []
- recur_dict = []
- if ids and (base_start_date or base_until_date):
- cr.execute("select m.id, m.rrule, m.date, m.date_deadline, m.duration, \
- m.exdate, m.exrule, m.recurrent_id, m.recurrent_uid from " + self._table + \
- " m where m.id = ANY(%s)", (ids,) )
-
- count = 0
- for data in cr.dictfetchall():
- start_date = base_start_date and datetime.strptime(base_start_date[:10]+ ' 00:00:00' , "%Y-%m-%d %H:%M:%S") or False
- until_date = base_until_date and datetime.strptime(base_until_date[:10]+ ' 23:59:59', "%Y-%m-%d %H:%M:%S") or False
- if count > limit:
- break
- event_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
+ for data in super(calendar_event, self).read(cr, uid, select, context=context):
+ if not data['rrule']:
+ result.append(data['id'])
+ continue
+ event_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
# To check: If the start date is replace by event date .. the event date will be changed by that of calendar code
- 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_id2base_calendar_id(data['id'], data['date'])
- if not data['recurrent_id']:
- result.append(idval)
- count += 1
- else:
- ex_id = real_id2base_calendar_id(data['recurrent_uid'], data['recurrent_id'])
- ls = base_calendar_id2real_id(ex_id, with_date=data and data.get('duration', 0) or 0)
- if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
- if ls[1] == data['recurrent_id']:
- result.append(idval)
- recur_dict.append(ex_id)
- else:
- exdate = data['exdate'] and data['exdate'].split(',') or []
- 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)
- rdates = get_recurrent_dates(str(new_rrule_str), exdate, start_date, data['exrule'])
- for r_date in rdates:
- if start_date and r_date < start_date:
- continue
- if until_date and r_date > until_date:
- continue
- idval = real_id2base_calendar_id(data['id'], r_date.strftime("%Y-%m-%d %H:%M:%S"))
- result.append(idval)
- count += 1
- if result:
- ids = list(set(result)-set(recur_dict))
+
+ if not data['rrule']:
+ continue
+
+ exdate = data['exdate'] and data['exdate'].split(',') or []
+ 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 %H:%M:%S"))
+ value = value.strftime("%Y%m%d%H%M%S")
+ new_rule = '%s=%s' % (name, value)
+ new_rrule_str.append(new_rule)
+ new_rrule_str = ';'.join(new_rrule_str)
+ rdates = get_recurrent_dates(str(new_rrule_str), exdate, event_date, data['exrule'])
+ for r_date in rdates:
+ ok = True
+ for arg in domain:
+ if arg[0] in ('date', 'date_deadline'):
+ if (arg[1]=='='):
+ ok = ok and r_date.strftime('%Y-%m-%d')==arg[2]
+ if (arg[1]=='>'):
+ ok = ok and r_date.strftime('%Y-%m-%d')>arg[2]
+ if (arg[1]=='<'):
+ ok = ok and r_date.strftime('%Y-%m-%d')<arg[2]
+ if (arg[1]=='>='):
+ ok = ok and r_date.strftime('%Y-%m-%d')>=arg[2]
+ if (arg[1]=='<='):
+ ok = ok and r_date.strftime('%Y-%m-%d')<=arg[2]
+ if not ok:
+ continue
+ idval = real_id2base_calendar_id(data['id'], r_date.strftime("%Y-%m-%d %H:%M:%S"))
+ result.append(idval)
+
if isinstance(select, (str, int, long)):
return ids and ids[0] or False
+ else:
+ ids = list(set(result))
return ids
- def compute_rule_string(self, cr, uid, datas, context=None, *args):
+ def compute_rule_string(self, datas):
"""
Compute rule string according to value type RECUR of iCalendar from the values given.
@param self: the object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
@param datas: dictionary of freq and interval value.
- @param context: A standard dictionary for contextual values
- @return: String value of the format RECUR of iCalendar
"""
+ def get_week_string(freq, datas):
+ weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
+ if freq == 'weekly':
+ byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
+ if byday:
+ return ';BYDAY=' + ','.join(byday)
+ return ''
- weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
- weekstring = ''
- monthstring = ''
- yearstring = ''
- freq=datas.get('rrule_type')
- if freq == 'none':
+ def get_month_string(freq, datas):
+ if freq == 'monthly':
+ if datas.get('select1')=='date' and (datas.get('day') < 1 or datas.get('day') > 31):
+ raise osv.except_osv(_('Error!'), ("Please select a proper day of the month."))
+
+ if datas.get('select1')=='day':
+ return ';BYDAY=' + datas.get('byday') + datas.get('week_list')
+ elif datas.get('select1')=='date':
+ return ';BYMONTHDAY=' + str(datas.get('day'))
return ''
-
- interval_srting = datas.get('interval') and (';INTERVAL=' + str(datas.get('interval'))) or ''
- if freq == 'weekly':
- byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
- if byday:
- weekstring = ';BYDAY=' + ','.join(byday)
+ def get_end_date(datas):
+ if datas.get('end_date'):
+ datas['end_date_new'] = ''.join((re.compile('\d')).findall(datas.get('end_date'))) + 'T235959Z'
+
+ return (datas.get('end_type') == 'count' and (';COUNT=' + str(datas.get('count'))) or '') +\
+ ((datas.get('end_date_new') and datas.get('end_type') == 'end_date' and (';UNTIL=' + datas.get('end_date_new'))) or '')
- elif freq == 'monthly':
- if datas.get('select1')=='date' and (datas.get('day') < 1 or datas.get('day') > 31):
- raise osv.except_osv(_('Error!'), ("Please select proper Day of month"))
- if datas.get('select1')=='day':
- monthstring = ';BYDAY=' + datas.get('byday') + datas.get('week_list')
- elif datas.get('select1')=='date':
- monthstring = ';BYMONTHDAY=' + str(datas.get('day'))
+ freq=datas.get('rrule_type')
+ if freq == 'none':
+ return ''
-
- if datas.get('end_date'):
- datas['end_date'] = ''.join((re.compile('\d')).findall(datas.get('end_date'))) + 'T235959Z'
- enddate = (datas.get('count') and (';COUNT=' + str(datas.get('count'))) or '') +\
- ((datas.get('end_date') and (';UNTIL=' + datas.get('end_date'))) or '')
+ interval_srting = datas.get('interval') and (';INTERVAL=' + str(datas.get('interval'))) or ''
- rrule_string = 'FREQ=' + freq.upper() + weekstring + interval_srting \
- + enddate + monthstring + yearstring
+ return 'FREQ=' + freq.upper() + get_week_string(freq, datas) + interval_srting + get_end_date(datas) + get_month_string(freq, datas)
+
+ def _get_empty_rrule_data(self):
+ return {
+ 'byday' : False,
+ 'recurrency' : False,
+ 'end_date' : False,
+ 'rrule_type' : False,
+ 'select1' : False,
+ 'interval' : 0,
+ 'count' : False,
+ 'end_type' : False,
+ 'mo' : False,
+ 'tu' : False,
+ 'we' : False,
+ 'th' : False,
+ 'fr' : False,
+ 'sa' : False,
+ 'su' : False,
+ 'exrule' : False,
+ 'day' : False,
+ 'week_list' : False
+ }
+
+ #def _write_rrule(self, cr, uid, ids, field_value, rule_date=False, context=None):
+ # data = self._get_empty_rrule_data()
+ #
+ # if field_value:
+ # data['recurrency'] = True
+ # for event in self.browse(cr, uid, ids, context=context):
+ # rdate = rule_date or event.date
+ # update_data = self._parse_rrule(field_value, dict(data), rdate)
+ # data.update(update_data)
+ # #parse_rrule
+ # self.write(cr, uid, event.id, data, context=context)
+
+
+ def _parse_rrule(self, rule, data, date_start):
+ day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
+ rrule_type = ['yearly', 'monthly', 'weekly', 'daily']
+ r = rrule.rrulestr(rule, dtstart=datetime.strptime(date_start, "%Y-%m-%d %H:%M:%S"))
+
+ if r._freq > 0 and r._freq < 4:
+ data['rrule_type'] = rrule_type[r._freq]
+
+ data['count'] = r._count
+ data['interval'] = r._interval
+ data['end_date'] = r._until and r._until.strftime("%Y-%m-%d %H:%M:%S")
+ #repeat weekly
+ if r._byweekday:
+ for i in xrange(0,7):
+ if i in r._byweekday:
+ data[day_list[i]] = True
+ data['rrule_type'] = 'weekly'
+ #repeat monthly bynweekday ((weekday, weeknumber), )
+ if r._bynweekday:
+ data['week_list'] = day_list[r._bynweekday[0][0]].upper()
+ data['byday'] = r._bynweekday[0][1]
+ data['select1'] = 'day'
+ data['rrule_type'] = 'monthly'
+
+ if r._bymonthday:
+ data['day'] = r._bymonthday[0]
+ data['select1'] = 'date'
+ data['rrule_type'] = 'monthly'
+
+ #yearly but for openerp it's monthly, take same information as monthly but interval is 12 times
+ if r._bymonth:
+ data['interval'] = data['interval'] * 12
+
+ #FIXEME handle forever case
+ #end of recurrence
+ #in case of repeat for ever that we do not support right now
+ if not (data.get('count') or data.get('end_date')):
+ data['count'] = 100
+ if data.get('count'):
+ data['end_type'] = 'count'
+ else:
+ data['end_type'] = 'end_date'
+ return data
- return rrule_string
+ def remove_virtual_id(self, ids):
+ if isinstance(ids, (str, int, long)):
+ return base_calendar_id2real_id(ids)
- def search(self, cr, uid, args, offset=0, limit=100, order=None,
- context=None, count=False):
- """
- Overrides orm search method.
- @param cr: the current row, from the database cursor,
- @param user: the current user’s ID for security checks,
- @param args: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...].
- @param offset: The Number of Results to Pass
- @param limit: The Number of Results to Return
- @param context: A standard dictionary for contextual values
- @param count: If its True the method returns number of records instead of ids
- @return: List of id
- """
+ if isinstance(ids, (list, tuple)):
+ res = []
+ for id in ids:
+ res.append(base_calendar_id2real_id(id))
+ return res
+
+ def search(self, cr, uid, args, offset=0, limit=0, order=None, context=None, count=False):
+ context = context or {}
args_without_date = []
- start_date = False
- until_date = False
+ filter_date = []
for arg in args:
- if arg[0] not in ('date', unicode('date'), 'date_deadline', unicode('date_deadline')):
+ if arg[0] == "id":
+ new_id = self.remove_virtual_id(arg[2])
+ new_arg = (arg[0], arg[1], new_id)
+ args_without_date.append(new_arg)
+ elif arg[0] not in ('date', unicode('date'), 'date_deadline', unicode('date_deadline')):
args_without_date.append(arg)
else:
- if arg[1] in ('>', '>='):
- if start_date:
- continue
- start_date = arg[2]
- elif arg[1] in ('<', '<='):
- if until_date:
- continue
- until_date = arg[2]
+ if context.get('virtual_id', True):
+ args_without_date.append('|')
+ args_without_date.append(arg)
+ if context.get('virtual_id', True):
+ args_without_date.append(('recurrency','=',1))
+ filter_date.append(arg)
+
res = super(calendar_event, self).search(cr, uid, args_without_date, \
- offset, limit, order, context, count)
+ 0, 0, order, context, count=False)
+ if context.get('virtual_id', True):
+ res = self.get_recurrent_ids(cr, uid, res, args, limit, context=context)
+
+ if count:
+ return len(res)
+ elif limit:
+ return res[offset:offset+limit]
+ else:
+ return res
- res = self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit)
- return res
-
-
- def get_edit_all(self, cr, uid, id, vals=None):
- """
- return true if we have to edit all meeting from the same recurrent
- or only on occurency
- """
- meeting = self.read(cr,uid, id, ['edit_all', 'recurrency'] )
- if(vals and 'edit_all' in vals): #we jsut check edit_all
- return vals['edit_all']
- else: #it's a recurrent event and edit_all is already check
- return meeting['recurrency'] and meeting['edit_all']
+ def _get_data(self, cr, uid, id, context=None):
+ res = self.read(cr, uid, [id],['date', 'date_deadline'])
+ return res[0]
+ def need_to_update(self, event_id, vals):
+ split_id = str(event_id).split("-")
+ if len(split_id) < 2:
+ return False
+ else:
+ date_start = vals.get('date', '')
+ try:
+ date_start = datetime.strptime(date_start, '%Y-%m-%d %H:%M:%S').strftime("%Y%m%d%H%M%S")
+ return date_start == split_id[1]
+ except Exception:
+ return True
-
def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True):
- """
- Overrides orm write method.
- @param self: the object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param ids: List of crm meeting's ids
- @param vals: Dictionary of field value.
- @param context: A standard dictionary for contextual values
- @return: True
- """
- if context is None:
- context = {}
+ context = context or {}
if isinstance(ids, (str, int, long)):
- select = [ids]
- else:
- select = ids
- new_ids = []
+ ids = [ids]
res = False
- for event_id in select:
- real_event_id = base_calendar_id2real_id(event_id)
-
-
- if(self.get_edit_all(cr, uid, event_id, vals=vals)):
- event_id = real_event_id
-
-
- if len(str(event_id).split('-')) > 1:
- data = self.read(cr, uid, event_id, ['date', 'date_deadline', \
- 'rrule', 'duration', 'exdate'])
- if data.get('rrule'):
- data.update(vals)
- data.update({
- 'recurrent_uid': real_event_id,
- 'recurrent_id': data.get('date'),
- 'rrule_type': 'none',
- 'rrule': '',
- 'edit_all': False,
- 'recurrency' : False,
- })
-
- new_id = self.copy(cr, uid, real_event_id, default=data, context=context)
-
- date_new = event_id.split('-')[1]
- date_new = time.strftime("%Y%m%dT%H%M%S", \
- time.strptime(date_new, "%Y%m%d%H%M%S"))
- exdate = (data['exdate'] and (data['exdate'] + ',') or '') + date_new
- res = self.write(cr, uid, [real_event_id], {'exdate': exdate})
-
- context.update({'active_id': new_id, 'active_ids': [new_id]})
- continue
- if not real_event_id in new_ids:
- new_ids.append(real_event_id)
- if vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'):
- vals['vtimezone'] = vals['vtimezone'][40:]
+ # Special write of complex IDS
+ for event_id in ids[:]:
+ if len(str(event_id).split('-')) == 1:
+ continue
+ ids.remove(event_id)
+ real_event_id = base_calendar_id2real_id(event_id)
+ if not vals.get('recurrency', True):
+ ids.append(real_event_id)
+ continue
- updated_vals = self.onchange_dates(cr, uid, new_ids,
- vals.get('date', False),
- vals.get('duration', False),
- vals.get('date_deadline', False),
- vals.get('allday', False),
- context=context)
- vals.update(updated_vals.get('value', {}))
+ #if edit one instance of a reccurrent id
+ data = self.read(cr, uid, event_id, ['date', 'date_deadline', \
+ 'rrule', 'duration', 'exdate'])
+ if data.get('rrule'):
+ data.update(vals)
+ data.update({
+ 'recurrent_uid': real_event_id,
+ 'recurrent_id': data.get('date'),
+ 'rrule_type': 'none',
+ 'rrule': '',
+ 'recurrency' : False,
+ })
+
+ new_id = self.copy(cr, uid, real_event_id, default=data, context=context)
+
+ date_new = event_id.split('-')[1]
+ date_new = time.strftime("%Y%m%dT%H%M%S", \
+ time.strptime(date_new, "%Y%m%d%H%M%S"))
+ exdate = (data['exdate'] and (data['exdate'] + ',') or '') + date_new
+ res = self.write(cr, uid, [real_event_id], {'exdate': exdate})
+
+ context.update({'active_id': new_id, 'active_ids': [new_id]})
+ continue
- if not 'edit_all' in vals:
- vals['edit_all'] = False
+ if vals.get('vtimezone', '') and vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'):
+ vals['vtimezone'] = vals['vtimezone'][40:]
- if new_ids:
- res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context)
+ res = super(calendar_event, self).write(cr, uid, ids, vals, context=context)
if ('alarm_id' in vals or 'base_calendar_alarm_id' in vals)\
or ('date' in vals or 'duration' in vals or 'date_deadline' in vals):
- # change alarm details
alarm_obj = self.pool.get('res.alarm')
- alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date', context=context)
- return res
+ alarm_obj.do_alarm_create(cr, uid, ids, self._name, 'date', context=context)
+ return res or True and False
- def browse(self, cr, uid, ids, context=None, list_class=None, fields_process=None):
- """
- Overrides orm browse method.
- @param self: the object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param ids: List of crm meeting's ids
- @param context: A standard dictionary for contextual values
- @return: the object list.
- """
- if isinstance(ids, (str, int, long)):
- select = [ids]
- else:
- select = ids
- select = map(lambda x: base_calendar_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
+ def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False):
+ if not context:
+ context = {}
+ if 'date' in groupby:
+ raise osv.except_osv(_('Warning!'), _('Group by date is not supported, use the calendar view instead.'))
+ virtual_id = context.get('virtual_id', True)
+ context.update({'virtual_id': False})
+ res = super(calendar_event, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby)
+ for re in res:
+ #remove the count, since the value is not consistent with the result of the search when expand the group
+ for groupname in groupby:
+ if re.get(groupname + "_count"):
+ del re[groupname + "_count"]
+ re.get('__context', {}).update({'virtual_id' : virtual_id})
return res
def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'):
- """
- Overrides orm Read method.Read List of fields for calendar event.
- @param cr: the current row, from the database cursor,
- @param user: the current user’s ID for security checks,
- @param ids: List of calendar event's id.
- @param fields: List of fields.
- @param context: A standard dictionary for contextual values
- @return: List of Dictionary of form [{‘name_of_the_field’: value, ...}, ...]
- """
# FIXME This whole id mangling has to go!
if context is None:
context = {}
+ fields2 = fields and fields[:] or None
+
+ EXTRAFIELDS = ('class','user_id','duration')
+ for f in EXTRAFIELDS:
+ if fields and (f not in fields):
+ fields2.append(f)
if isinstance(ids, (str, int, long)):
select = [ids]
select = ids
select = map(lambda x: (x, base_calendar_id2real_id(x)), select)
result = []
- if fields and 'date' not in fields:
- fields.append('date')
- if fields and 'duration' not in fields:
- fields.append('duration')
+ real_data = super(calendar_event, self).read(cr, uid,
+ [real_id for base_calendar_id, real_id in select],
+ fields=fields2, context=context, load=load)
+ real_data = dict(zip([x['id'] for x in real_data], real_data))
for base_calendar_id, real_id in select:
- #REVET: Revision ID: olt@tinyerp.com-20100924131709-cqsd1ut234ni6txn
- res = super(calendar_event, self).read(cr, uid, real_id, fields=fields, context=context, load=load)
- if not res :
- continue
+ res = real_data[real_id].copy()
ls = base_calendar_id2real_id(base_calendar_id, with_date=res and res.get('duration', 0) or 0)
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
res['date'] = ls[1]
res['id'] = base_calendar_id
result.append(res)
+
+ for r in result:
+ if r['user_id']:
+ user_id = type(r['user_id']) in (tuple,list) and r['user_id'][0] or r['user_id']
+ if user_id==uid:
+ continue
+ if r['class']=='private':
+ for f in r.keys():
+ if f not in ('id','date','date_deadline','duration','user_id','state'):
+ r[f] = False
+ if f=='name':
+ r[f] = _('Busy')
+
+ for r in result:
+ for k in EXTRAFIELDS:
+ if (k in r) and ((not fields) or (k not in fields)):
+ del r[k]
if isinstance(ids, (str, int, long)):
return result and result[0] or False
return result
def copy(self, cr, uid, id, default=None, context=None):
- """
- Duplicate record on specified id.
- @param self: the object pointer.
- @param cr: the current row, from the database cursor,
- @param id: id of record from which we duplicated.
- @param context: A standard dictionary for contextual values
- @return: Duplicate record id.
- """
if context is None:
context = {}
+
res = super(calendar_event, self).copy(cr, uid, base_calendar_id2real_id(id), default, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context)
-
return res
def unlink(self, cr, uid, ids, context=None):
- """
- Deletes records specified in ids.
- @param self: the object pointer.
- @param cr: the current row, from the database cursor,
- @param id: List of calendar event's id.
- @param context: A standard dictionary for contextual values
- @return: True
- """
+ if not isinstance(ids, list):
+ ids = [ids]
res = False
- for event_datas in self.read(cr, uid, ids, ['date', 'rrule', 'exdate'], context=context):
- event_id = event_datas['id']
-
- if self.get_edit_all(cr, uid, event_id, vals=None):
- event_id = base_calendar_id2real_id(event_id)
-
- if isinstance(event_id, (int, long)):
- res = super(calendar_event, self).unlink(cr, uid, event_id, context=context)
- self.pool.get('res.alarm').do_alarm_unlink(cr, uid, [event_id], self._name)
- self.unlink_events(cr, uid, [event_id], context=context)
- else:
- str_event, date_new = event_id.split('-')
- event_id = int(str_event)
- if event_datas['rrule']:
- # Remove one of the recurrent event
- date_new = time.strftime("%Y%m%dT%H%M%S", \
- time.strptime(date_new, "%Y%m%d%H%M%S"))
- exdate = (event_datas['exdate'] and (event_datas['exdate'] + ',') or '') + date_new
- res = self.write(cr, uid, [event_id], {'exdate': exdate})
- else:
- res = super(calendar_event, self).unlink(cr, uid, [event_id], context=context)
- self.pool.get('res.alarm').do_alarm_unlink(cr, uid, [event_id], self._name)
- self.unlink_events(cr, uid, [event_id], context=context)
+ attendee_obj=self.pool.get('calendar.attendee')
+ for event_id in ids[:]:
+ if len(str(event_id).split('-')) == 1:
+ continue
+
+ real_event_id = base_calendar_id2real_id(event_id)
+ data = self.read(cr, uid, real_event_id, ['exdate'], context=context)
+ date_new = event_id.split('-')[1]
+ date_new = time.strftime("%Y%m%dT%H%M%S", \
+ time.strptime(date_new, "%Y%m%d%H%M%S"))
+ exdate = (data['exdate'] and (data['exdate'] + ',') or '') + date_new
+ self.write(cr, uid, [real_event_id], {'exdate': exdate})
+ ids.remove(event_id)
+ for event in self.browse(cr, uid, ids, context=context):
+ if event.attendee_ids:
+ attendee_obj.unlink(cr, uid, [x.id for x in event.attendee_ids], context=context)
+
+ res = super(calendar_event, self).unlink(cr, uid, ids, context=context)
+ self.pool.get('res.alarm').do_alarm_unlink(cr, uid, ids, self._name)
+ self.unlink_events(cr, uid, ids, context=context)
return res
+
def create(self, cr, uid, vals, context=None):
- """
- Create new record.
- @param self: the object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param vals: dictionary of every field value.
- @param context: A standard dictionary for contextual values
- @return: new created record id.
- """
if context is None:
context = {}
if vals.get('vtimezone', '') and vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'):
vals['vtimezone'] = vals['vtimezone'][40:]
- updated_vals = self.onchange_dates(cr, uid, [],
- vals.get('date', False),
- vals.get('duration', False),
- vals.get('date_deadline', False),
- vals.get('allday', False),
- context=context)
- vals.update(updated_vals.get('value', {}))
+ #updated_vals = self.onchange_dates(cr, uid, [],
+ # vals.get('date', False),
+ # vals.get('duration', False),
+ # vals.get('date_deadline', False),
+ # vals.get('allday', False),
+ # context=context)
+ #vals.update(updated_vals.get('value', {}))
res = super(calendar_event, self).create(cr, uid, vals, context)
alarm_obj = self.pool.get('res.alarm')
@param args: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...].
@param context: A standard dictionary for contextual values
"""
-
+
assert name == 'date'
return self.write(cr, uid, id, { 'date_start': value }, context=context)
_columns = {
- 'date': fields.function(_get_date, method=True, fnct_inv=_set_date, \
+ 'date': fields.function(_get_date, fnct_inv=_set_date, \
string='Duration', store=True, type='datetime'),
'duration': fields.integer('Duration'),
}
_inherit = 'ir.attachment'
def search_count(self, cr, user, args, context=None):
- """
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param user: the current user’s ID for security checks,
- @param args: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...].
- @param context: A standard dictionary for contextual values
- """
+ new_args = []
+ for domain_item in args:
+ if isinstance(domain_item, (list, tuple)) and len(domain_item) == 3 and domain_item[0] == 'res_id':
+ new_args.append((domain_item[0], domain_item[1], base_calendar_id2real_id(domain_item[2])))
+ else:
+ new_args.append(domain_item)
+ return super(ir_attachment, self).search_count(cr, user, new_args, context)
- args1 = []
- for arg in args:
- args1.append(map(lambda x:str(x).split('-')[0], arg))
- return super(ir_attachment, self).search_count(cr, user, args1, context)
-
-
-
def create(self, cr, uid, vals, context=None):
if context:
id = context.get('default_res_id', False)
def search(self, cr, uid, args, offset=0, limit=None, order=None,
context=None, count=False):
- """
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param args: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...].
- @param offset: The Number of Results to pass,
- @param limit: The Number of Results to Return,
- @param context: A standard dictionary for contextual values
- """
-
- new_args = args
- for i, arg in enumerate(new_args):
- if arg[0] == 'res_id':
- new_args[i] = (arg[0], arg[1], base_calendar_id2real_id(arg[2]))
-
+ new_args = []
+ for domain_item in args:
+ if isinstance(domain_item, (list, tuple)) and len(domain_item) == 3 and domain_item[0] == 'res_id':
+ new_args.append((domain_item[0], domain_item[1], base_calendar_id2real_id(domain_item[2])))
+ else:
+ new_args.append(domain_item)
return super(ir_attachment, self).search(cr, uid, new_args, offset=offset,
limit=limit, order=order, context=context, count=False)
ir_attachment()
_columns = {
'availability': fields.function(_get_user_avail_fun, type='selection', \
selection=[('free', 'Free'), ('busy', 'Busy')], \
- string='Free/Busy', method=True),
+ string='Free/Busy'),
}
res_users()