[REF] Calendar refactoring - Manage allday in date field and not datetime.

bzr revid: jke@openerp.com-20140430093613-3tdn2tfiwshcahbz
This commit is contained in:
Kersten Jeremy 2014-04-30 11:36:13 +02:00
parent 162fff3bfe
commit d9c3c175bd
12 changed files with 345 additions and 283 deletions

View File

@ -22,7 +22,7 @@
{
'name': 'Calendar',
'version': '1.0',
'depends': ['base', 'mail', 'base_action_rule','web_calendar'],
'depends': ['base', 'mail', 'base_action_rule', 'web_calendar'],
'summary': 'Personal & Shared Calendar',
'description': """
This is a full-featured calendar system.
@ -43,7 +43,7 @@ If you need to manage your meetings, you should install the CRM module.
'security/ir.model.access.csv',
'calendar_view.xml',
'contacts_view.xml',
'calendar_data.xml',
'calendar_data.xml',
],
'js': [
'static/src/js/*.js'
@ -52,14 +52,12 @@ If you need to manage your meetings, you should install the CRM module.
'css': [
'static/src/css/calendar.css'
],
'test' : [
'test/calendar_test.yml',
'test/test_calendar_recurrent_event_case2.yml'
],
'test': [
'test/calendar_test.yml',
'test/test_calendar_recurrent_event_case2.yml'
],
'installable': True,
'application': True,
'auto_install': False,
'images': ['images/calendar1.jpeg','images/calendar2.jpeg','images/calendar3.jpeg','images/calendar4.jpeg'],
}

View File

@ -54,10 +54,10 @@ def calendar_id2real_id(calendar_id=None, with_date=False):
if len(res) >= 2:
real_id = res[0]
if with_date:
real_date = time.strftime("%Y-%m-%d %H:%M:%S", time.strptime(res[1], "%Y%m%d%H%M%S"))
start = datetime.strptime(real_date, "%Y-%m-%d %H:%M:%S")
real_date = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT, time.strptime(res[1], "%Y%m%d%H%M%S"))
start = datetime.strptime(real_date, DEFAULT_SERVER_DATETIME_FORMAT)
end = start + timedelta(hours=with_date)
return (int(real_id), real_date, end.strftime("%Y-%m-%d %H:%M:%S"))
return (int(real_id), real_date, end.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
return int(real_id)
return calendar_id and int(calendar_id) or calendar_id
@ -95,10 +95,6 @@ class calendar_attendee(osv.Model):
result[id][name] = attdata.partner_id.name or False
else:
result[id][name] = attdata.email or ''
if name == 'event_date':
result[id][name] = attdata.event_id.date
if name == 'event_end_date':
result[id][name] = attdata.event_id.date_deadline
return result
STATE_SELECTION = [
@ -113,8 +109,6 @@ class calendar_attendee(osv.Model):
'cn': fields.function(_compute_data, string='Common name', type="char", multi='cn', store=True),
'partner_id': fields.many2one('res.partner', 'Contact', readonly="True"),
'email': fields.char('Email', help="Email of Invited Person"),
'event_date': fields.function(_compute_data, string='Event Date', type="datetime", multi='event_date'),
'event_end_date': fields.function(_compute_data, string='Event End Date', type="datetime", multi='event_end_date'),
'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"),
'access_token': fields.char('Invitation Token'),
'event_id': fields.many2one('calendar.event', 'Meeting linked'),
@ -144,9 +138,12 @@ class calendar_attendee(osv.Model):
"""
res = None
def ics_datetime(idate, short=False):
def ics_datetime(idate, allday=False):
if idate:
return datetime.strptime(idate.split('.')[0], '%Y-%m-%d %H:%M:%S').replace(tzinfo=pytz.timezone('UTC'))
if allday:
return datetime.strptime(idate.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT).replace(tzinfo=pytz.timezone('UTC'))
else:
return datetime.strptime(idate.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT).replace(tzinfo=pytz.timezone('UTC'))
return False
try:
@ -157,11 +154,11 @@ class calendar_attendee(osv.Model):
cal = vobject.iCalendar()
event = cal.add('vevent')
if not event_obj.date_deadline or not event_obj.date:
if not event_obj.zstart or not event_obj.zstop:
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)
event.add('created').value = ics_datetime(time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
event.add('dtstart').value = ics_datetime(event_obj.zstart, event_obj.allday)
event.add('dtend').value = ics_datetime(event_obj.zstop, event_obj.allday)
event.add('summary').value = event_obj.name
if event_obj.description:
event.add('description').value = event_obj.description
@ -198,7 +195,7 @@ class calendar_attendee(osv.Model):
"""
res = False
if self.pool['ir.config_parameter'].get_param(cr, uid, 'calendar.block_mail', default=False):
if self.pool['ir.config_parameter'].get_param(cr, uid, 'calendar.block_mail', default=False) or context.get("no_mail_to_attendees"):
return res
mail_ids = []
@ -312,6 +309,10 @@ class res_partner(osv.Model):
}
def get_attendee_detail(self, cr, uid, ids, meeting_id, context=None):
"""
Return a list of tuple (id, name, status)
Used by web_calendar.js : Many2ManyAttendee
"""
datas = []
meeting = False
if meeting_id:
@ -339,15 +340,15 @@ class calendar_alarm_manager(osv.AbstractModel):
base_request = """
SELECT
cal.id,
cal.date - interval '1' minute * calcul_delta.max_delta AS first_alarm,
cal.zstart - interval '1' minute * calcul_delta.max_delta AS first_alarm,
CASE
WHEN cal.recurrency THEN cal.end_date - interval '1' minute * calcul_delta.min_delta
ELSE cal.date_deadline - interval '1' minute * calcul_delta.min_delta
WHEN cal.recurrency THEN cal.zfinal_date - interval '1' minute * calcul_delta.min_delta
ELSE cal.zstop - interval '1' minute * calcul_delta.min_delta
END as last_alarm,
cal.date as first_event_date,
cal.zstart as first_event_date,
CASE
WHEN cal.recurrency THEN cal.end_date
ELSE cal.date_deadline
WHEN cal.recurrency THEN cal.zfinal_date
ELSE cal.zstop
END as last_event_date,
calcul_delta.min_delta,
calcul_delta.max_delta,
@ -380,7 +381,7 @@ class calendar_alarm_manager(osv.AbstractModel):
tuple_params = (type_to_read,)
#ADD FILTER ON PARTNER_ID
# ADD FILTER ON PARTNER_ID
if partner_id:
base_request += filter_user
tuple_params += (partner_id, )
@ -389,7 +390,7 @@ class calendar_alarm_manager(osv.AbstractModel):
tuple_params += (seconds, seconds,)
cr.execute("""SELECT *
FROM ( %s ) AS ALL_EVENTS
FROM ( %s WHERE cal.active = True ) AS ALL_EVENTS
WHERE ALL_EVENTS.first_alarm < (now() at time zone 'utc' + interval '%%s' second )
AND ALL_EVENTS.last_alarm > (now() at time zone 'utc' - interval '%%s' second )
""" % base_request, tuple_params)
@ -421,7 +422,7 @@ class calendar_alarm_manager(osv.AbstractModel):
for alarm in event.alarm_ids:
if alarm.type in alarm_type and \
one_date - timedelta(minutes=alarm.duration_minutes) < datetime.now() + timedelta(seconds=in_the_next_X_seconds) and \
(not after or one_date - timedelta(minutes=alarm.duration_minutes) > datetime.strptime(after.split('.')[0], "%Y-%m-%d %H:%M:%S")):
(not after or one_date - timedelta(minutes=alarm.duration_minutes) > datetime.strptime(after.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT)):
alert = {
'alarm_id': alarm.id,
'event_id': event.id,
@ -471,7 +472,7 @@ class calendar_alarm_manager(osv.AbstractModel):
if bFound and not LastFound: # if the precedent event had an alarm but not this one, we can stop the search for this event
break
else:
in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S')
in_date_format = datetime.strptime(curEvent.zstart, DEFAULT_SERVER_DATETIME_FORMAT)
LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, cron_interval, notif=False, context=context)
if LastFound:
for alert in LastFound:
@ -504,7 +505,7 @@ class calendar_alarm_manager(osv.AbstractModel):
if bFound and not LastFound: # if the precedent event had alarm but not this one, we can stop the search fot this event
break
else:
in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S')
in_date_format = datetime.strptime(curEvent.zstart, DEFAULT_SERVER_DATETIME_FORMAT)
LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, ajax_check_every_seconds, partner.calendar_last_notif_ack, mail=False, context=context)
if LastFound:
for alert in LastFound:
@ -539,7 +540,7 @@ class calendar_alarm_manager(osv.AbstractModel):
'title': event.name,
'message': message,
'timer': delta,
'notify_at': alert['notify_at'].strftime("%Y-%m-%d %H:%M:%S"),
'notify_at': alert['notify_at'].strftime(DEFAULT_SERVER_DATETIME_FORMAT),
}
@ -561,7 +562,7 @@ class calendar_alarm(osv.Model):
return res
_columns = {
'name': fields.char('Name', required=True), # fields function
'name': fields.char('Name', required=True),
'type': fields.selection([('notification', 'Notification'), ('email', 'Email')], 'Type', required=True),
'duration': fields.integer('Amount', required=True),
'interval': fields.selection([('minutes', 'Minutes'), ('hours', 'Hours'), ('days', 'Days')], 'Unit', required=True),
@ -579,7 +580,6 @@ class ir_values(osv.Model):
_inherit = 'ir.values'
def set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=False, preserve_user=False, company=False):
new_model = []
for data in models:
if type(data) in (list, tuple):
@ -648,7 +648,7 @@ class calendar_event_type(osv.Model):
class calendar_event(osv.Model):
""" Model for Calendar Event """
_name = 'calendar.event'
_description = "Meeting"
_description = "Event"
_order = "id desc"
_inherit = ["mail.thread", "ir.needaction_mixin"]
@ -658,7 +658,6 @@ class calendar_event(osv.Model):
def get_recurrent_date_by_event(self, cr, uid, event, context=None):
"""Get recurrent dates based on Rule string and all event where recurrent_id is child
"""
def todate(date):
val = parser.parse(''.join((re.compile('\d')).findall(date)))
## Dates are localized to saved timezone if any, else current timezone.
@ -666,8 +665,8 @@ class calendar_event(osv.Model):
val = pytz.UTC.localize(val)
return val.astimezone(timezone)
timezone = pytz.timezone(event.vtimezone or context.get('tz') or 'UTC')
startdate = pytz.UTC.localize(datetime.strptime(event.date, "%Y-%m-%d %H:%M:%S")) # Add "+hh:mm" timezone
timezone = pytz.timezone(context.get('tz') or 'UTC')
startdate = pytz.UTC.localize(datetime.strptime(event.zstart, DEFAULT_SERVER_DATETIME_FORMAT)) # Add "+hh:mm" timezone
if not startdate:
startdate = datetime.now()
@ -677,20 +676,19 @@ class calendar_event(osv.Model):
rset1 = rrule.rrulestr(str(event.rrule), dtstart=startdate, forceset=True)
ids_depending = self.search(cr, uid, [('recurrent_id', '=', event.id), '|', ('active', '=', False), ('active', '=', True)], context=context)
all_events = self.browse(cr, uid, ids_depending, context=context)
for ev in all_events:
rset1._exdate.append(todate(ev.recurrent_id_date))
return [d.astimezone(pytz.UTC) for d in rset1]
def _get_recurrency_end_date(self, data, context=None):
def _get_recurrency_end_date(self, cr, uid, id, context=None):
data = self.read(cr, uid, id, ['zfinal_date', 'recurrency', 'rrule_type', 'count', 'end_type', 'zstop'], context=context)
if not data.get('recurrency'):
return False
end_type = data.get('end_type')
end_date = data.get('end_date')
if end_type == 'count' and all(data.get(key) for key in ['count', 'rrule_type', 'date_deadline']):
final_date = data.get('zfinal_date')
if end_type == 'count' and all(data.get(key) for key in ['count', 'rrule_type', 'zstop']):
count = data['count'] + 1
delay, mult = {
'daily': ('days', 1),
@ -699,9 +697,9 @@ class calendar_event(osv.Model):
'yearly': ('years', 1),
}[data['rrule_type']]
deadline = datetime.strptime(data['date_deadline'], tools.DEFAULT_SERVER_DATETIME_FORMAT)
deadline = datetime.strptime(data['zstop'], tools.DEFAULT_SERVER_DATETIME_FORMAT)
return deadline + relativedelta(**{delay: count * mult})
return end_date
return final_date
def _find_my_attendee(self, cr, uid, meeting_ids, context=None):
"""
@ -714,7 +712,7 @@ class calendar_event(osv.Model):
return attendee
return False
def _get_display_time(self, cr, uid, meeting_id, context=None):
def _get_display_time(self, cr, uid, zstart, zstop, zduration, zallday, context=None):
"""
Return date and time (from to from) based on duration with timezone in string :
eg.
@ -728,15 +726,14 @@ class calendar_event(osv.Model):
if not tz: # tz can have a value False, so dont do it in the default value of get !
tz = pytz.timezone('UTC')
meeting = self.browse(cr, uid, meeting_id, context=context)
date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(meeting.date, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context)
date_deadline = fields.datetime.context_timestamp(cr, uid, datetime.strptime(meeting.date_deadline, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context)
date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(zstart, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context)
date_deadline = fields.datetime.context_timestamp(cr, uid, datetime.strptime(zstop, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context)
event_date = date.strftime('%B-%d-%Y')
display_time = date.strftime('%H-%M')
if meeting.allday:
if zallday:
time = _("AllDay , %s") % (event_date)
elif meeting.duration < 24:
duration = date + timedelta(hours=meeting.duration)
elif zduration < 24:
duration = date + timedelta(hours=zduration)
time = ("%s at (%s To %s) (%s)") % (event_date, display_time, duration.strftime('%H-%M'), tz)
else:
time = ("%s at %s To\n %s at %s (%s)") % (event_date, display_time, date_deadline.strftime('%B-%d-%Y'), date_deadline.strftime('%H-%M'), tz)
@ -747,13 +744,21 @@ class calendar_event(osv.Model):
for meeting_id in ids:
res[meeting_id] = {}
attendee = self._find_my_attendee(cr, uid, [meeting_id], context)
meeting = self.browse(cr, uid, [meeting_id], context=context)[0]
for field in fields:
if field == 'is_attendee':
res[meeting_id][field] = True if attendee else False
elif field == 'attendee_status':
res[meeting_id][field] = attendee.state if attendee else 'needsAction'
elif field == 'display_time':
res[meeting_id][field] = self._get_display_time(cr, uid, meeting_id, context=context)
res[meeting_id][field] = self._get_display_time(cr, uid, meeting.zstart, meeting.zstop, meeting.duration, meeting.allday, context=context)
elif field == "display_start":
res[meeting_id][field] = meeting.zstart_date if meeting.allday else meeting.zstart_datetime
elif field == 'zstart':
res[meeting_id][field] = meeting.zstart_date if meeting.allday else meeting.zstart_datetime
elif field == 'zstop':
res[meeting_id][field] = meeting.zstop_date if meeting.allday else meeting.zstop_datetime
return res
def _get_rulestring(self, cr, uid, ids, name, arg, context=None):
@ -774,7 +779,7 @@ class calendar_event(osv.Model):
if data.count and data.count <= 0:
raise osv.except_osv(_('Warning!'), _('Count cannot be negative or 0.'))
data = self.read(cr, uid, id, ['id', 'byday', 'recurrency', 'month_list', 'end_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list'], context=context)
data = self.read(cr, uid, id, ['id', 'byday', 'recurrency', 'month_list', 'zfinal_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list'], context=context)
event = data['id']
if data['recurrency']:
result[event] = self.compute_rule_string(data)
@ -793,20 +798,53 @@ class calendar_event(osv.Model):
if field_value:
data['recurrency'] = True
for event in self.browse(cr, uid, ids, context=context):
rdate = event.date
rdate = event.zstart
update_data = self._parse_rrule(field_value, dict(data), rdate)
data.update(update_data)
self.write(cr, uid, ids, data, context=context)
return True
def _tz_get(self, cr, uid, context=None):
return [(x.lower(), x) for x in pytz.all_timezones]
def _set_date(self, cr, uid, values, id=False, context=None):
if context is None:
context = {}
if values.get('zstart_datetime') or values.get('zstart_date') or values.get('zstart') \
or values.get('zstop_datetime') or values.get('zstop_date') or values.get('zstop'):
allday = values.get("allday", None)
if allday is None:
if id:
allday = self.read(cr, uid, [id], ['allday'], context=context)[0].get('allday')
else:
allday = False
_logger.warning("Calendar - All day is not specified, arbitrarily set to False")
#raise osv.except_osv(_('Error!'), ("Need to know if it's an allday or not..."))
key = "date" if allday else "datetime"
notkey = "datetime" if allday else "date"
for fld in ('zstart', 'zstop'):
if values.get('%s_%s' % (fld, key)) or values.get(fld):
values['%s_%s' % (fld, key)] = values.get('%s_%s' % (fld, key)) or values.get(fld)
values['%s_%s' % (fld, notkey)] = None
if fld not in values.keys():
values[fld] = values['%s_%s' % (fld, key)]
diff = False
if allday and values.get('zstop_date') and values.get('zstart_date'):
diff = datetime.strptime(values['zstop_date'].split(' ')[0], DEFAULT_SERVER_DATE_FORMAT) - datetime.strptime(values['zstart_date'].split(' ')[0], DEFAULT_SERVER_DATE_FORMAT)
elif values.get('zstop_datetime') and values.get('zstart_datetime'):
diff = datetime.strptime(values['zstop_datetime'].split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT) - datetime.strptime(values['zstart_datetime'].split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT)
if diff:
duration = float(diff.days) * 24 + (float(diff.seconds) / 3600)
values['duration'] = round(duration, 2)
_track = {
'location': {
'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True,
},
'date': {
'zstart': {
'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True,
},
}
@ -817,19 +855,26 @@ class calendar_event(osv.Model):
'is_attendee': fields.function(_compute, string='Attendee', type="boolean", multi='attendee'),
'attendee_status': fields.function(_compute, string='Attendee Status', type="selection", selection=calendar_attendee.STATE_SELECTION, multi='attendee'),
'display_time': fields.function(_compute, string='Event Time', type="char", multi='attendee'),
'date': fields.datetime('Date', states={'done': [('readonly', True)]}, required=True, track_visibility='onchange'),
'date_deadline': fields.datetime('End Date', states={'done': [('readonly', True)]}, required=True,),
'display_start': fields.function(_compute, string='Date', type="char", multi='display_start', store=True),
'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}),
'zstart': fields.function(_compute, string='Calculated start', type="datetime", multi='zstart', store=True, required=True),
'zstop': fields.function(_compute, string='Calculated stop', type="datetime", multi='zstop', store=True, required=True),
'zstart_date': fields.date('Start Date', states={'done': [('readonly', True)]}, track_visibility='onchange'),
'zstart_datetime': fields.datetime('Start DateTime', states={'done': [('readonly', True)]}, track_visibility='onchange'),
'zstop_date': fields.date('End Date', states={'done': [('readonly', True)]}, track_visibility='onchange'),
'zstop_datetime': fields.datetime('End Datetime', states={'done': [('readonly', True)]}, track_visibility='onchange'), # old date_deadline
'duration': fields.float('Duration', states={'done': [('readonly', True)]}),
'description': fields.text('Description', states={'done': [('readonly', True)]}),
'class': fields.selection([('public', 'Public'), ('private', 'Private'), ('confidential', 'Public for Employees')], 'Privacy', states={'done': [('readonly', True)]}),
'location': fields.char('Location', help="Location of Event", track_visibility='onchange', states={'done': [('readonly', True)]}),
'show_as': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Show Time as', states={'done': [('readonly', True)]}),
# RECURRENCE FIELD
'rrule': fields.function(_get_rulestring, type='char', fnct_inv=_set_rulestring, store=True, string='Recurrent Rule'),
'rrule_type': fields.selection([('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('yearly', 'Year(s)')], 'Recurrency', states={'done': [('readonly', True)]}, help="Let the event automatically repeat at that interval"),
'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"),
'recurrent_id': fields.integer('Recurrent ID'),
'recurrent_id_date': fields.datetime('Recurrent ID date'),
'vtimezone': fields.selection(_tz_get, string='Timezone'),
'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"),
@ -844,21 +889,21 @@ class calendar_event(osv.Model):
'day': fields.integer('Date of month'),
'week_list': fields.selection([('MO', 'Monday'), ('TU', 'Tuesday'), ('WE', 'Wednesday'), ('TH', 'Thursday'), ('FR', 'Friday'), ('SA', 'Saturday'), ('SU', 'Sunday')], 'Weekday'),
'byday': fields.selection([('1', 'First'), ('2', 'Second'), ('3', 'Third'), ('4', 'Fourth'), ('5', 'Fifth'), ('-1', 'Last')], 'By day'),
'end_date': fields.date('Repeat Until'),
'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}),
'zfinal_date': fields.date('Repeat Until'), # The last event of a recurrence
'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}),
'color_partner_id': fields.related('user_id', 'partner_id', 'id', type="integer", string="colorize", store=False), # Color of creator
'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."),
'categ_ids': fields.many2many('calendar.event.type', 'meeting_category_rel', 'event_id', 'type_id', 'Tags'),
'attendee_ids': fields.one2many('calendar.attendee', 'event_id', 'Attendees', ondelete='cascade'),
'partner_ids': fields.many2many('res.partner', string='Attendees', states={'done': [('readonly', True)]}),
'alarm_ids': fields.many2many('calendar.alarm', string='Reminders', ondelete="restrict"),
'partner_ids': fields.many2many('res.partner', 'calendar_event_res_partner_rel', string='Attendees', states={'done': [('readonly', True)]}),
'alarm_ids': fields.many2many('calendar.alarm', 'calendar_alarm_calendar_event_rel', string='Reminders', ondelete="restrict"),
}
_defaults = {
'end_type': 'count',
'count': 1,
'rrule_type': False,
'allday': False,
'state': 'draft',
'class': 'public',
'show_as': 'busy',
@ -871,58 +916,86 @@ class calendar_event(osv.Model):
def _check_closing_date(self, cr, uid, ids, context=None):
for event in self.browse(cr, uid, ids, context=context):
if event.date_deadline < event.date:
if event.zstop < event.zstart:
return False
return True
_constraints = [
(_check_closing_date, 'Error ! End date cannot be set before start date.', ['date_deadline']),
(_check_closing_date, 'Error ! End date cannot be set before start date.', ['zstart', 'zstop'])
]
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 ids: List of calendar event's IDs.
"""
if context is None:
context = {}
def onchange_allday(self, cr, uid, ids, start=False, end=False, starttime=False, endtime=False, startdatetime=False, enddatetime=False, checkallday=False, context=None):
value = {}
if not start_date:
if not ((starttime and endtime) or (start and end)): # At first intialize, we have not datetime
return value
if not end_date and not duration:
duration = 1.00
value['duration'] = duration
if checkallday: # from datetime to date
startdatetime = startdatetime or start
if startdatetime:
start = datetime.strptime(startdatetime, DEFAULT_SERVER_DATETIME_FORMAT)
value['zstart_date'] = datetime.strftime(start, DEFAULT_SERVER_DATE_FORMAT)
if allday: # For all day event
start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
user = self.pool['res.users'].browse(cr, uid, uid)
enddatetime = enddatetime or end
if enddatetime:
end = datetime.strptime(enddatetime, DEFAULT_SERVER_DATETIME_FORMAT)
value['zstop_date'] = datetime.strftime(end, DEFAULT_SERVER_DATE_FORMAT)
else: # from date to datetime
user = self.pool['res.users'].browse(cr, uid, uid, context)
tz = pytz.timezone(user.tz) if user.tz else pytz.utc
start = pytz.utc.localize(start).astimezone(tz) # convert start in user's timezone
start = start.astimezone(pytz.utc) # convert start back to utc
value['duration'] = 24.0
value['date'] = datetime.strftime(start, "%Y-%m-%d %H:%M:%S")
if starttime:
start = datetime.strptime(starttime.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT)
startdate = tz.localize(start) # Add "+hh:mm" timezone
startdate = startdate.replace(hour=8) # Set 8 AM in localtime
startdate = startdate.astimezone(pytz.utc) # Convert to UTC
value['zstart_datetime'] = datetime.strftime(startdate, DEFAULT_SERVER_DATETIME_FORMAT)
elif start:
value['zstart_datetime'] = start
if endtime:
end = datetime.strptime(endtime.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT)
enddate = tz.localize(end).replace(hour=18).astimezone(pytz.utc)
value['zstop_datetime'] = datetime.strftime(enddate, DEFAULT_SERVER_DATETIME_FORMAT)
elif end:
value['zstop_datetime'] = end
return {'value': value}
def onchange_dates(self, cr, uid, ids, fromtype, start=False, end=False, checkallday=False, allday=False, context=None):
"""Returns duration and end date based on values passed
@param ids: List of calendar event's IDs.
"""
value = {}
if checkallday != allday:
return value
value['allday'] = checkallday # Force to be rewrited
if allday:
if fromtype == 'start':
start = datetime.strptime(start, DEFAULT_SERVER_DATE_FORMAT)
value['zstart_datetime'] = datetime.strftime(start, DEFAULT_SERVER_DATETIME_FORMAT)
value['zstart'] = datetime.strftime(start, DEFAULT_SERVER_DATETIME_FORMAT)
if fromtype == 'stop':
end = datetime.strptime(end, DEFAULT_SERVER_DATE_FORMAT)
value['zstop_datetime'] = datetime.strftime(end, DEFAULT_SERVER_DATETIME_FORMAT)
value['zstop'] = datetime.strftime(end, DEFAULT_SERVER_DATETIME_FORMAT)
else:
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
duration = float(diff.days) * 24 + (float(diff.seconds) / 3600)
value['duration'] = round(duration, 2)
elif not end_date:
end = start + timedelta(hours=duration)
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
# 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
duration = float(diff.days) * 24 + (float(diff.seconds) / 3600)
value['duration'] = round(duration, 2)
if fromtype == 'start':
start = datetime.strptime(start, DEFAULT_SERVER_DATETIME_FORMAT)
value['zstart_date'] = datetime.strftime(start, DEFAULT_SERVER_DATE_FORMAT)
value['zstart'] = datetime.strftime(start, DEFAULT_SERVER_DATETIME_FORMAT)
if fromtype == 'stop':
end = datetime.strptime(end, DEFAULT_SERVER_DATETIME_FORMAT)
value['zstop_date'] = datetime.strftime(end, DEFAULT_SERVER_DATE_FORMAT)
value['zstop'] = datetime.strftime(end, DEFAULT_SERVER_DATETIME_FORMAT)
return {'value': value}
@ -1009,7 +1082,6 @@ class calendar_event(osv.Model):
@param order: The fields (comma separated, format "FIELD {DESC|ASC}") on which the events should be sorted
"""
if not context:
context = {}
@ -1034,7 +1106,6 @@ class calendar_event(osv.Model):
result.append(ev.id)
result_data.append(self.get_search_fields(ev, order_fields))
continue
rdates = self.get_recurrent_date_by_event(cr, uid, ev, context=context)
for r_date in rdates:
@ -1045,7 +1116,7 @@ class calendar_event(osv.Model):
pile = []
ok = True
for arg in domain:
if str(arg[0]) in (str('date'), str('date_deadline'), str('end_date')):
if str(arg[0]) in ('zstart', 'zstop', 'zfinal_date'):
if (arg[1] == '='):
ok = r_date.strftime('%Y-%m-%d') == arg[2]
if (arg[1] == '>'):
@ -1108,8 +1179,6 @@ class calendar_event(osv.Model):
weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
if freq == 'weekly':
byday = map(lambda x: x.upper(), filter(lambda x: data.get(x) and x in weekdays, data))
# byday = map(lambda x: x.upper(),[data[day] for day in weekdays if data[day]])
if byday:
return ';BYDAY=' + ','.join(byday)
return ''
@ -1126,8 +1195,8 @@ class calendar_event(osv.Model):
return ''
def get_end_date(data):
if data.get('end_date'):
data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('end_date'))) + 'T235959Z'
if data.get('zfinal_date'):
data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('zfinal_date'))) + 'T235959Z'
return (data.get('end_type') == 'count' and (';COUNT=' + str(data.get('count'))) or '') +\
((data.get('end_date_new') and data.get('end_type') == 'end_date' and (';UNTIL=' + data.get('end_date_new'))) or '')
@ -1144,7 +1213,7 @@ class calendar_event(osv.Model):
return {
'byday': False,
'recurrency': False,
'end_date': False,
'zfinal_date': False,
'rrule_type': False,
'month_by': False,
'interval': 0,
@ -1164,14 +1233,13 @@ class calendar_event(osv.Model):
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"))
r = rrule.rrulestr(rule, dtstart=datetime.strptime(date_start, DEFAULT_SERVER_DATETIME_FORMAT))
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")
data['zfinal_date'] = r._until and r._until.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
#repeat weekly
if r._byweekday:
for i in xrange(0, 7):
@ -1197,12 +1265,12 @@ class calendar_event(osv.Model):
#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')):
if not (data.get('count') or data.get('zfinal_date')):
data['count'] = 100
if data.get('count'):
data['end_type'] = 'count'
else:
data['end_type'] = 'end_date'
data['end_type'] = 'zfinal_date'
return data
def message_get_subscription_data(self, cr, uid, ids, user_pid=None, context=None):
@ -1226,25 +1294,6 @@ class calendar_event(osv.Model):
res.update(self.check_partners_email(cr, uid, value[0][2], context=context))
return res
def onchange_rec_day(self, cr, uid, id, date, mo, tu, we, th, fr, sa, su):
""" set the start date according to the first occurence of rrule"""
rrule_obj = self._get_empty_rrule_data()
rrule_obj.update({
'byday': True,
'rrule_type': 'weekly',
'mo': mo,
'tu': tu,
'we': we,
'th': th,
'fr': fr,
'sa': sa,
'su': su,
'interval': 1
})
str_rrule = self.compute_rule_string(rrule_obj)
first_occurence = list(rrule.rrulestr(str_rrule + ";COUNT=1", dtstart=datetime.strptime(date, "%Y-%m-%d %H:%M:%S"), forceset=True))[0]
return {'value': {'date': first_occurence.strftime("%Y-%m-%d") + ' 00:00:00'}}
def check_partners_email(self, cr, uid, partner_ids, context=None):
""" Verify that selected partner_ids have an email_address defined.
Otherwise throw a warning. """
@ -1262,14 +1311,13 @@ class calendar_event(osv.Model):
'message': warning_msg,
}}
# ----------------------------------------
# OpenChatter
# ----------------------------------------
# shows events of the day for this user
def _needaction_domain_get(self, cr, uid, context=None):
return [('end_date', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 23:59:59')), ('date', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 23:59:59')), ('user_id', '=', uid)]
return [
('zstop', '<=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 23:59:59')),
('zstart', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 00:00:00')),
('user_id', '=', uid),
]
def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
if isinstance(thread_id, str):
@ -1326,15 +1374,15 @@ class calendar_event(osv.Model):
if context.get('mymeetings', False):
partner_id = self.pool['res.users'].browse(cr, uid, uid, context).partner_id.id
args += ['|', ('partner_ids', 'in', [partner_id]), ('user_id', '=', uid)]
args += [('partner_ids', 'in', [partner_id])]
new_args = []
for arg in args:
new_arg = arg
if arg[0] in ('date', unicode('date')) and arg[1] == ">=":
if arg[0] in ('zstart_date', 'zstart_datetime', 'zstart',) and arg[1] == ">=":
if context.get('virtual_id', True):
new_args += ['|', '&', ('recurrency', '=', 1), ('end_date', arg[1], arg[2])]
new_args += ['|', '&', ('recurrency', '=', 1), ('zfinal_date', arg[1], arg[2])]
elif arg[0] == "id":
new_id = get_real_ids(arg[2])
new_arg = (arg[0], arg[1], new_id)
@ -1357,6 +1405,8 @@ class calendar_event(osv.Model):
context = {}
default = default or {}
self._set_date(cr, uid, default, id=default.get('id'), context=context)
default['attendee_ids'] = False
res = super(calendar_event, self).copy(cr, uid, calendar_id2real_id(id), default, context)
@ -1364,17 +1414,18 @@ class calendar_event(osv.Model):
def _detach_one_event(self, cr, uid, id, values=dict(), context=None):
real_event_id = calendar_id2real_id(id)
data = self.read(cr, uid, id, ['date', 'date_deadline', 'rrule', 'duration'])
data = self.read(cr, uid, id, ['allday', 'zstart', 'zstop', 'rrule', 'duration'])
data['zstart_date' if data['allday'] else 'zstart_datetime'] = data['zstart']
data['zstop_date' if data['allday'] else 'zstop_datetime'] = data['zstop']
if data.get('rrule'):
data.update(
values,
recurrent_id=real_event_id,
recurrent_id_date=data.get('date'),
recurrent_id_date=data.get('zstart'),
rrule_type=False,
rrule='',
recurrency=False,
end_date=datetime.strptime(values.get('date', False) or data.get('date'), "%Y-%m-%d %H:%M:%S") + timedelta(hours=values.get('duration', False) or data.get('duration'))
zfinal_date=datetime.strptime(values.get('zstart', False) or data.get('zstart'), DEFAULT_SERVER_DATETIME_FORMAT) + timedelta(hours=values.get('duration', False) or data.get('duration'))
)
#do not copy the id
@ -1397,21 +1448,34 @@ class calendar_event(osv.Model):
'flags': {'form': {'action_buttons': True, 'options': {'mode': 'edit'}}}
}
def _name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100, name_get_uid=None):
for arg in args:
if arg[0] == 'id':
for n, calendar_id in enumerate(arg[2]):
if isinstance(calendar_id, str):
arg[2][n] = calendar_id.split('-')[0]
return super(calendar_event, self)._name_search(cr, user, name=name, args=args, operator=operator, context=context, limit=limit, name_get_uid=name_get_uid)
def write(self, cr, uid, ids, values, context=None):
def _only_changes_to_apply_on_real_ids(field_names):
''' return True if changes are only to be made on the real ids'''
for field in field_names:
if field in ['date', 'active']:
if field in ['zstart', 'zstart_date', 'zstart_datetime', 'zstop', 'zstop_date', 'zstop_datetime', 'active']:
return True
return False
context = context or {}
if not isinstance(ids, (tuple, list)):
ids = [ids]
if isinstance(ids, (str, int, long)):
if len(str(ids).split('-')) == 1:
ids = [int(ids)]
else:
ids = [ids]
context = context or {}
self._set_date(cr, uid, values, id=ids[0], context=context)
for one_ids in ids:
if isinstance(one_ids, (str, int, long)):
if len(str(one_ids).split('-')) == 1:
ids = [int(one_ids)]
else:
ids = [one_ids]
res = False
new_id = False
@ -1431,7 +1495,7 @@ class calendar_event(osv.Model):
ids.append(real_event_id)
continue
else:
data = self.read(cr, uid, event_id, ['date', 'date_deadline', 'rrule', 'duration'])
data = self.read(cr, uid, event_id, ['zstart', 'zstop', 'rrule', 'duration'])
if data.get('rrule'):
new_id = self._detach_one_event(cr, uid, event_id, values, context=None)
@ -1439,16 +1503,16 @@ class calendar_event(osv.Model):
# set end_date for calendar searching
if values.get('recurrency', True) and values.get('end_type', 'count') in ('count', unicode('count')) and \
(values.get('rrule_type') or values.get('count') or values.get('date') or values.get('date_deadline')):
for data in self.read(cr, uid, ids, ['end_date', 'date_deadline', 'recurrency', 'rrule_type', 'count', 'end_type'], context=context):
end_date = self._get_recurrency_end_date(data, context=context)
super(calendar_event, self).write(cr, uid, [data['id']], {'end_date': end_date}, context=context)
(values.get('rrule_type') or values.get('count') or values.get('zstart') or values.get('zstop')):
for id in ids:
final_date = self._get_recurrency_end_date(cr, uid, id, context=context)
super(calendar_event, self).write(cr, uid, [id], {'zfinal_date': final_date}, context=context)
attendees_create = False
if values.get('partner_ids', False):
attendees_create = self.create_attendees(cr, uid, ids, context)
if values.get('date', False) and values.get('active', True):
if (values.get('zstart_date') or values.get('zstart_datetime', False)) and values.get('active', True):
the_id = new_id or (ids and int(ids[0]))
if attendees_create:
@ -1461,21 +1525,20 @@ class calendar_event(osv.Model):
current_user = self.pool['res.users'].browse(cr, uid, uid, context=context)
if self.pool['calendar.attendee']._send_mail_to_attendees(cr, uid, mail_to_ids, template_xmlid='calendar_template_meeting_changedate', email_from=current_user.email, context=context):
self.message_post(cr, uid, the_id, body=_("A email has been send to specify that the date has been changed !"), subtype="calendar.subtype_invitation", context=context)
return res or True and False
def create(self, cr, uid, vals, context=None):
if context is None:
context = {}
self._set_date(cr, uid, vals, id=False, context=context)
if not 'user_id' in vals: # Else bug with quick_create when we are filter on an other user
vals['user_id'] = uid
res = super(calendar_event, self).create(cr, uid, vals, context=context)
data = self.read(cr, uid, [res], ['end_date', 'date_deadline', 'recurrency', 'rrule_type', 'count', 'end_type'], context=context)[0]
end_date = self._get_recurrency_end_date(data, context=context)
self.write(cr, uid, [res], {'end_date': end_date}, context=context)
final_date = self._get_recurrency_end_date(cr, uid, res, context=context)
self.write(cr, uid, [res], {'zfinal_date': final_date}, context=context)
self.create_attendees(cr, uid, [res], context=context)
return res
@ -1501,28 +1564,35 @@ class calendar_event(osv.Model):
if context is None:
context = {}
fields2 = fields and fields[:] or None
EXTRAFIELDS = ('class', 'user_id', 'duration', 'date', 'rrule', 'vtimezone')
EXTRAFIELDS = ('class', 'user_id', 'duration', 'allday', 'zstart', 'zstart_date', 'zstart_datetime', 'rrule')
for f in EXTRAFIELDS:
if fields and (f not in fields):
fields2.append(f)
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = map(lambda x: (x, calendar_id2real_id(x)), select)
result = []
real_data = super(calendar_event, self).read(cr, uid, [real_id for 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 calendar_id, real_id in select:
res = real_data[real_id].copy()
ls = calendar_id2real_id(calendar_id, with_date=res and res.get('duration', 0) or 0)
ls = calendar_id2real_id(calendar_id, with_date=res and res.get('duration', 0) > 0 and res.get('duration') or 1)
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
res['date'] = ls[1]
res['date_deadline'] = ls[2]
res['zstart'] = ls[1]
res['zstop'] = ls[2]
if res['allday']:
res['zstart_date'] = ls[1]
res['zstop_date'] = ls[2]
else:
res['zstart_datetime'] = ls[1]
res['zstop_datetime'] = ls[2]
res['display_time'] = self._get_display_time(cr, uid, ls[1], ls[2], res['duration'], res['allday'], context=context)
res['id'] = calendar_id
result.append(res)
@ -1533,7 +1603,7 @@ class calendar_event(osv.Model):
continue
if r['class'] == 'private':
for f in r.keys():
if f not in ('id', 'date', 'date_deadline', 'duration', 'user_id', 'state', 'interval', 'count', 'recurrent_id_date'):
if f not in ('id', 'allday', 'zstart', 'zstop', 'duration', 'user_id', 'state', 'interval', 'count', 'recurrent_id_date'):
if isinstance(r[f], list):
r[f] = []
else:
@ -1545,12 +1615,11 @@ class calendar_event(osv.Model):
for k in EXTRAFIELDS:
if (k in r) and (fields and (k not in fields)):
del r[k]
if isinstance(ids, (str, int, long)):
return result and result[0] or False
return result
def unlink(self, cr, uid, ids, unlink_level=0, context=None):
def unlink(self, cr, uid, ids, can_be_deleted=True, context=None):
if not isinstance(ids, list):
ids = [ids]
res = False
@ -1558,9 +1627,8 @@ class calendar_event(osv.Model):
ids_to_exclure = []
ids_to_unlink = []
# One time moved to google_Calendar, we can specify, if not in google, and not rec or get_inst = 0, we delete it
for event_id in ids:
if unlink_level == 1 and len(str(event_id).split('-')) == 1: # if ID REAL
if can_be_deleted and len(str(event_id).split('-')) == 1: # if ID REAL
if self.browse(cr, uid, event_id).recurrent_id:
ids_to_exclure.append(event_id)
else:

View File

@ -142,12 +142,12 @@
<table>
<tr>
<td>
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.date, 'dayname')}</div>
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.zstart, 'dayname')}</div>
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
${object.event_id.get_interval(object.event_id.date,'day')}
${object.event_id.get_interval(object.event_id.zstart,'day')}
</div>
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.date, 'month')}</div>
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}</div>
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.zstart, 'month')}</div>
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.zstart, 'time', tz=object.partner_id.tz) or ''}</div>
</td>
<td>
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
@ -275,12 +275,12 @@
<table>
<tr>
<td>
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.date, 'dayname')}</div>
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.zstart, 'dayname')}</div>
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
${object.event_id.get_interval(object.event_id.date,'day')}
${object.event_id.get_interval(object.event_id.zstart,'day')}
</div>
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.date, 'month')}</div>
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}</div>
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.zstart, 'month')}</div>
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.zstart, 'time', tz=object.partner_id.tz) or ''}</div>
</td>
<td>
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
@ -407,12 +407,12 @@
<table>
<tr>
<td>
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.date, 'dayname')}</div>
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.zstart, 'dayname')}</div>
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
${object.event_id.get_interval(object.event_id.date,'day')}
${object.event_id.get_interval(object.event_id.zstart,'day')}
</div>
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.date, 'month')}</div>
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}</div>
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.zstart, 'month')}</div>
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.zstart, 'time', tz=object.partner_id.tz) or ''}</div>
</td>
<td>
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">

View File

@ -23,22 +23,24 @@
<field name="partner_ids" eval="[(6,0,[ref('base.res_partner_6')])]"/>
<field name="name">Follow-up for Project proposal</field>
<field name="description">Meeting to discuss project plan and hash out the details of implementation.</field>
<field eval="time.strftime('%Y-%m-03 10:20:00')" name="date"/>
<field eval="time.strftime('%Y-%m-03 10:20:00')" name="zstart"/>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/>
<field eval="time.strftime('%Y-%m-03 16:30:00')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-03 16:30:00')" name="zstop"/>
<field eval="6.3" name="duration"/>
<field eval="0" name="allday"/>
<field name="state">open</field>
</record>
<record id="calendar_event_2" model="calendar.event">
<field eval="1" name="active"/>
<field eval="1" name="active"/>
<field name="user_id" ref="base.user_demo"/>
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_4'),ref('base.res_partner_5')])]"/>
<field name="name">Initial discussion</field>
<field name="description">Discussion with partner for product.</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet3')])]"/>
<field eval="time.strftime('%Y-%m-05 12:00:00')" name="date"/>
<field eval="time.strftime('%Y-%m-05 19:00:00')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-05 12:00:00')" name="zstart"/>
<field eval="time.strftime('%Y-%m-05 19:00:00')" name="zstop"/>
<field eval="0" name="allday"/>
<field eval="7.0" name="duration"/>
<field name="state">draft</field>
</record>
@ -49,9 +51,10 @@
<field name="name">Pricing Discussion</field>
<field name="description">Internal meeting for discussion for new pricing for product and services.</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
<field eval="time.strftime('%Y-%m-12 15:55:05')" name="date"/>
<field eval="time.strftime('%Y-%m-12 18:55:05')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-12 15:55:05')" name="zstart"/>
<field eval="time.strftime('%Y-%m-12 18:55:05')" name="zstop"/>
<field eval="3.0" name="duration"/>
<field eval="0" name="allday"/>
<field name="state">open</field>
</record>
@ -61,9 +64,10 @@
<field name="partner_ids" eval="[(6,0,[ref('base.partner_demo'),ref('base.res_partner_6')])]"/>
<field name="name">Requirements review</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet3')])]"/>
<field eval="time.strftime('%Y-%m-20 8:00:00')" name="date"/>
<field eval="time.strftime('%Y-%m-20 10:30:00')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-20 8:00:00')" name="zstart"/>
<field eval="time.strftime('%Y-%m-20 10:30:00')" name="zstop"/>
<field eval="2.5" name="duration"/>
<field eval="0" name="allday"/>
<field name="state">open</field>
</record>
@ -72,9 +76,9 @@
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_8')])]"/>
<field name="name">Changes in Designing</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/>
<field eval="time.strftime('%Y-%m-22 11:05:00')" name="date"/>
<field eval="time.strftime('%Y-%m-22 16:05:00')" name="date_deadline"/>
<field eval="5" name="duration"/>
<field eval="time.strftime('%Y-%m-22')" name="zstart"/>
<field eval="time.strftime('%Y-%m-22')" name="zstop"/>
<field eval="1" name="allday"/>
<field name="state">open</field>
</record>
@ -84,9 +88,10 @@
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_1'),ref('base.res_partner_4'),ref('base.res_partner_6'),ref('base.res_partner_8')])]"/>
<field name="name">Presentation for new Services</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
<field eval="time.strftime('%Y-%m-18 2:00:00')" name="date"/>
<field eval="time.strftime('%Y-%m-18 10:30:00')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-18 2:00:00')" name="zstart"/>
<field eval="time.strftime('%Y-%m-18 10:30:00')" name="zstop"/>
<field eval="8.5" name="duration"/>
<field eval="0" name="allday"/>
<field name="state">draft</field>
</record>
@ -96,9 +101,10 @@
<field name="partner_ids" eval="[(6,0,[ref('base.res_partner_7')])]"/>
<field name="name">Presentation of the new Calendar</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
<field eval="time.strftime('%Y-%m-16 6:00:00')" name="date"/>
<field eval="time.strftime('%Y-%m-16 18:30:00')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-16')" name="zstart"/>
<field eval="time.strftime('%Y-%m-16')" name="zstop"/>
<field eval="8.5" name="duration"/>
<field eval="1" name="allday"/>
<field name="state">draft</field>
</record>

View File

@ -9,7 +9,7 @@
<field name="name">Meeting Types Tree</field>
<field name="model">calendar.event.type</field>
<field name="arch" type="xml">
<tree string="Meeting Types">
<tree string="Meeting Types" editable="bottom">
<field name="name"/>
</tree>
</field>
@ -58,24 +58,24 @@
</group>
<group>
<group>
<field name="date" string="Starting at" on_change="onchange_dates(date, duration, False, allday)"/>
<label for="duration"/>
<field name="zstart" attrs="{'invisible': True}"/>
<field name="zstop" attrs="{'invisible': True}"/>
<field name="zstart_date" string="Starting at" on_change="onchange_dates('start', zstart_date, zstop_date, allday, True)" attrs="{'invisible': [('allday','=',False)]}"/>
<field name="zstop_date" string="Ending at" on_change="onchange_dates('stop', zstart_date, zstop_date, allday, True)" attrs="{'invisible': [('allday','=',False)]}"/>
<field name="zstart_datetime" string="Starting at" on_change="onchange_dates('start', zstart_datetime, zstop_datetime, allday, False)" attrs="{'invisible': [('allday','=',True)]}"/>
<field name="zstop_datetime" string="Ending at" on_change="onchange_dates('stop', zstart_datetime, zstop_datetime, allday, False)" attrs="{'invisible': [('allday','=',True)]}"/>
<label for="allday"/>
<div>
<field name="duration" widget="float_time"
on_change="onchange_dates(date, duration, False, allday)"
class="oe_inline" attrs="{'invisible': [('allday','=',True)]}"/>
<label string="hours" attrs="{'invisible': [('allday','=',True)]}"/>
(<field name="allday" class="oe_inline"/>
<label for="allday" string="All Day?"/>)
<field name="allday" class="oe_inline" on_change="onchange_allday(zstart, zstop, zstart_date, zstop_date, zstart_datetime, zstop_datetime, allday)"/>
</div>
<field name="date_deadline" groups="base.group_no_one"
attrs="{'invisible': ['|', ('allday','=',True), ('duration','&lt;', 24)]}"
/>
<field name="duration" widget="float_time" class="oe_inline" attrs="{ 'invisible': True }"/>
</group>
<group>
<field name="categ_ids" widget="many2many_tags"/>
<field name="categ_ids" widget="many2many_tags" />
<field name="alarm_ids" widget="many2many_tags" />
<field name="location"/>
<field name="location" />
</group>
</group>
@ -98,17 +98,17 @@
<div>
<field name="end_type" attrs="{'required': [('recurrency','==',True)]}" class="oe_inline"/>
<field name="count" attrs="{'invisible': [('end_type', '!=', 'count')], 'required': [('recurrency','==',True)]}" class="oe_inline"/>
<field name="end_date" attrs="{'invisible': [('end_type', '!=', 'end_date')], 'required': [('end_type', '=', 'end_date')]}" class="oe_inline"/>
<field name="zfinal_date" attrs="{'invisible': [('end_type', '!=', 'end_date')], 'required': [('end_type', '=', 'end_date')]}" class="oe_inline"/>
</div>
<label string="Select Weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}"/>
<group col="2" colspan="1" name="weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}" >
<field name="mo" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
<field name="tu" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
<field name="we" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
<field name="th" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
<field name="fr" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
<field name="sa" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
<field name="su" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
<field name="mo" />
<field name="tu" />
<field name="we" />
<field name="th" />
<field name="fr" />
<field name="sa" />
<field name="su" />
</group>
<label string="Day of Month"
@ -178,7 +178,9 @@
<field name="name"/>
<group>
<group>
<field name="date" string="Start" />
<field name="zstart_date" string="Starting at" attrs="{'invisible': [('allday','=',False)]}"/>
<field name="zstart_datetime" string="Starting at" attrs="{'invisible': [('allday','=',True)]}"/>
<field name="duration" string="Duration" widget="float_time" attrs="{'invisible': [('allday','=',True)]}"/>
<field name="allday" class="oe_inline" attrs="{'invisible': [('allday','=',False)]}"/>
<field name="partner_ids" widget="many2manyattendee" string="Attendees"/>
@ -201,7 +203,8 @@
<field name="arch" type="xml">
<tree string="Meetings" fonts="bold:message_unread==True">
<field name="name" string="Subject"/>
<field name="date" string="Event Date"/>
<field name="allday" invisible="True"/>
<field name="display_start" string="Date" />
<field name="user_id"/>
<field name="location"/>
<field name="show_as"/>
@ -219,7 +222,7 @@
<field name="model">calendar.event</field>
<field name="priority" eval="2"/>
<field name="arch" type="xml">
<calendar string="Meetings" date_start="date" date_stop="date_deadline" date_delay="duration" all_day="allday"
<calendar string="Meetings" date_start="zstart" date_stop="zstop" date_delay="duration" all_day="allday"
display="[name]" color="color_partner_id" attendee="partner_ids" avatar_model="res.partner"
use_contacts="True" event_open_popup="%(calendar.view_calendar_event_form_popup)s">
@ -260,8 +263,7 @@
<group expand="0" string="Group By...">
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Availability" icon="terp-camera_test" domain="[]" context="{'group_by':'show_as'}"/>
<filter string="Privacy" icon="terp-locked" domain="[]" context="{'group_by':'class'}"/>
<filter string="Event Month" icon="terp-go-month" domain="[]" context="{'group_by':'date'}" help="Start Date of Event by Month"/>
<filter string="Privacy" icon="terp-locked" domain="[]" context="{'group_by':'class'}"/>
</group>
</search>
</field>

View File

@ -11,7 +11,7 @@
</t>
</t>
<t t-name='notify_title'>
<span t-attf-class="'link2event eid_' + id" class='link2event eid_" + res.event_id + "'>
<span t-attf-class="link2event eid_#{id}">
<t t-esc="title"/>
</span>
</t>

View File

@ -3,8 +3,8 @@
-
!record {model: calendar.event, id: calendar_event_technicalpresentation0}:
class: private
date: '2011-04-30 16:00:00'
date_deadline: '2011-04-30 18:30:00'
zstart: '2011-04-30 16:00:00'
zstop: '2011-04-30 18:30:00'
description: The Technical Presentation will cover following topics:\n* Creating OpenERP
class\n* Views\n* Wizards\n* Workflows
duration: 2.5
@ -14,7 +14,7 @@
Now I will set recurrence for this event to occur monday and friday of week
-
!python {model: calendar.event}: |
data = {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly', 'end_type': 'end_date', 'end_date': '2011-05-31 00:00:00', 'recurrency' : True}
data = {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly', 'end_type': 'end_date', 'zfinal_date': '2011-05-31 00:00:00', 'recurrency' : True}
self.write(cr, uid, [ref("calendar_event_technicalpresentation0")], data)
-
In order to check that recurrent events are views successfully in calendar view, I will open calendar view of events
@ -25,18 +25,18 @@
In order to check that recurrent events are views successfully in calendar view, I will search for one of the recurrent event and count the number of events
-
!python {model: calendar.event}: |
ids = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
ids = self.search(cr, uid, [('zstart', '>=', '2011-04-30 16:00:00'), ('zstart', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
assert len(ids) == 9, 'Wrong number of events found'
-
Now I move a virtual event, to see that a real event is well created and depending from the native recurrence
-
!python {model: calendar.event}: |
ids = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
before = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
ids = self.search(cr, uid, [('zstart', '>=', '2011-04-30 16:00:00'), ('zstart', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
before = self.search(cr, uid, [('zstart', '>=', '2011-04-30 16:00:00'), ('zstart', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
# We start by detach the event
newid = self._detach_one_event(cr, uid,ids[1])
self.write(cr, uid,[newid], {'name':'New Name','recurrency' : True}, context={'virtual_id': True})
after = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
after = self.search(cr, uid, [('zstart', '>=', '2011-04-30 16:00:00'), ('zstart', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
assert len(after) == len(before)+1, 'Wrong number of events found, after to have moved a virtual event'
new_id = list(set(after)-set(before))[0]
new_event = self.browse(cr,uid,new_id,context=context)
@ -47,8 +47,8 @@
!record {model: calendar.event, id: calendar_event_alldaytestevent0}:
allday: 1
class: confidential
date: '2011-04-30 00:00:00'
date_deadline: '2011-04-30 00:00:00'
zstart: '2011-04-30 00:00:00'
zstop: '2011-04-30 00:00:00'
description: 'All day technical test '
location: School
name: All day test event
@ -70,7 +70,8 @@
-
!record {model: calendar.event, id: calendar.event_sprintreview1}:
name: Begin of month meeting
date: !eval time.strftime('%Y-%m-%d 12:00:00')
zstart: !eval time.strftime('%Y-%m-%d 12:00:00')
zstop: !eval time.strftime('%Y-%m-%d 18:00:00')
recurrency: true
rrule: FREQ=MONTHLY;INTERVAL=1;COUNT=12;BYDAY=1MO
-

View File

@ -5,8 +5,8 @@
-
!record {model: calendar.event, id: calendar_event_testmeeting0}:
count: 5
date: '2011-04-13 11:04:00'
date_deadline: '2011-04-13 12:04:00'
zstart: '2011-04-13 11:04:00'
zstop: '2011-04-13 12:04:00'
day: 0.0
duration: 1.0
name: Test Meeting
@ -17,17 +17,17 @@
I search for all the recurrent meetings.
-
!python {model: calendar.event}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_testmeeting0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_testmeeting0')]),('zstart','>=','2011-03-13'), ('zstop', '<=', '2011-05-13')], context={'virtual_id': True})
assert len(meeting_ids) == 5, 'Recurrent daily meetings are not created !'
-
I create a weekly meeting till a particular end date.
-
!record {model: calendar.event, id: calendar_event_reviewcodewithprogrammer0}:
date: '2011-04-18 11:47:00'
date_deadline: '2011-04-18 12:47:00'
zstart: '2011-04-18 11:47:00'
zstop: '2011-04-18 12:47:00'
day: 0.0
duration: 1.0
end_date: '2011-04-30'
zfinal_date: '2011-04-30'
end_type: end_date
fr: true
mo: true
@ -36,21 +36,21 @@
we: true
name: Review code with programmer
recurrency: true
recurrent_id: 0.0
recurrent_id: 0
rrule_type: weekly
-
I search for all the recurrent weekly meetings.
-
!python {model: calendar.event}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_reviewcodewithprogrammer0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_reviewcodewithprogrammer0')]),('zstart','>=','2011-03-13'), ('zstop', '<=', '2011-05-13')], context={'virtual_id': True})
assert len(meeting_ids) == 10, 'Recurrent weekly meetings are not created !'
-
I want to schedule a meeting every month for Sprint review.
-
!record {model: calendar.event, id: calendar_event_sprintreview0}:
count: 12
date: '2011-04-01 12:01:00'
date_deadline: '2011-04-01 13:01:00'
zstart: '2011-04-01 12:01:00'
zstop: '2011-04-01 13:01:00'
day: 1
duration: 1.0
name: Sprint Review
@ -61,7 +61,7 @@
I search for all the recurrent monthly meetings.
-
!python {model: calendar.event}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('zstart','>=','2011-03-01'), ('zstop', '<=', '2012-05-13')], context={'virtual_id': True})
assert len(meeting_ids) == 12, 'Recurrent monthly meetings are not created !'
-
I change name of my monthly Sprint Review meeting.
@ -73,7 +73,7 @@
I check whether all the records are edited or not.
-
!python {model: calendar.event}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('zstart','>=','2011-03-01'), ('zstop', '<=', '2012-05-13')], context={'virtual_id': True})
meetings = self.browse(cr, uid, meeting_ids, context)
for meeting in meetings:
assert meeting.name == 'Sprint Review for google modules', 'Name not changed for id: %s' %meeting.id

View File

@ -36,21 +36,7 @@ class calendar_event(osv.Model):
res = super(calendar_event, self).create(cr, uid, vals, context=context)
obj = self.browse(cr, uid, res, context=context)
if obj.opportunity_id:
self.pool.get('crm.lead').log_meeting(cr, uid, [obj.opportunity_id.id], obj.name, obj.date, obj.duration, context=context)
self.pool.get('crm.lead').log_meeting(cr, uid, [obj.opportunity_id.id], obj.name, obj.zstart, obj.duration, context=context)
return res
class calendar_attendee(osv.osv):
""" Calendar Attendee """
_inherit = 'calendar.attendee'
_description = 'Calendar Attendee'
def _noop(self, cr, uid, ids, name, arg, context=None):
return dict.fromkeys(ids, False)
_columns = {
'categ_id': fields.function(_noop, string='Event Type', deprecated="Unused Field - TODO : Remove it in trunk", type="many2one", relation="crm.case.categ"),
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -22,8 +22,6 @@ access_crm_phonecall_report_user,crm.phonecall.report.user,model_crm_phonecall_r
access_crm_phonecall_report_manager,crm.phonecall.report,model_crm_phonecall_report,base.group_sale_manager,1,1,1,1
access_res_partner_manager,res.partner.crm.manager,base.model_res_partner,base.group_sale_manager,1,0,0,0
access_res_partner_category_manager,res.partner.category.crm.manager,base.model_res_partner_category,base.group_sale_manager,1,0,0,0
access_calendar_attendee_crm_user,calendar.attendee.crm.user,model_calendar_attendee,base.group_sale_salesman,1,1,1,0
access_calendar_attendee_crm_manager,calendar.attendee.crm.manager,model_calendar_attendee,base.group_sale_manager,1,1,1,1
access_res_partner,res.partner.crm.user,base.model_res_partner,base.group_sale_salesman,1,1,1,0
access_res_partner_category,res.partner.category.crm.user,base.model_res_partner_category,base.group_sale_salesman,1,1,1,0
mail_mailgate_thread,mail.thread,mail.model_mail_thread,base.group_sale_salesman,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
22 access_crm_phonecall_report_manager crm.phonecall.report model_crm_phonecall_report base.group_sale_manager 1 1 1 1
23 access_res_partner_manager res.partner.crm.manager base.model_res_partner base.group_sale_manager 1 0 0 0
24 access_res_partner_category_manager res.partner.category.crm.manager base.model_res_partner_category base.group_sale_manager 1 0 0 0
access_calendar_attendee_crm_user calendar.attendee.crm.user model_calendar_attendee base.group_sale_salesman 1 1 1 0
access_calendar_attendee_crm_manager calendar.attendee.crm.manager model_calendar_attendee base.group_sale_manager 1 1 1 1
25 access_res_partner res.partner.crm.user base.model_res_partner base.group_sale_salesman 1 1 1 0
26 access_res_partner_category res.partner.category.crm.user base.model_res_partner_category base.group_sale_salesman 1 1 1 0
27 mail_mailgate_thread mail.thread mail.model_mail_thread base.group_sale_salesman 1 1 1 1

View File

@ -628,13 +628,13 @@ class google_calendar(osv.AbstractModel):
else:
if event_to_synchronize[base_event][0][1].OE.event_id:
parent_oe_id = event_to_synchronize[base_event][0][1].OE.event_id
calendar_event.unlink(cr, uid, "%s-%s" % (parent_oe_id, new_google_event_id), unlink_level=1, context=context)
calendar_event.unlink(cr, uid, "%s-%s" % (parent_oe_id, new_google_event_id), can_be_deleted=True, context=context)
elif isinstance(actToDo, Delete):
if actSrc == 'GG':
self.delete_an_event(cr, uid, current_event[0], context=context)
elif actSrc == 'OE':
calendar_event.unlink(cr, uid, event.OE.event_id, unlink_level=0, context=context)
calendar_event.unlink(cr, uid, event.OE.event_id, can_be_deleted=False, context=context)
return True
def check_and_sync(self, cr, uid, oe_event, google_event, context):
@ -750,6 +750,9 @@ class calendar_event(osv.Model):
default['oe_update_date'] = False
return super(calendar_event, self).copy(cr, uid, id, default, context)
def unlink(self, cr, uid, ids, can_be_deleted=False, context=None):
return super(calendar_event, self).unlink(cr, uid, ids, can_be_deleted=can_be_deleted, context=context)
_columns = {
'oe_update_date': fields.datetime('OpenERP Update Date'),
}

View File

@ -367,9 +367,9 @@ class hr_holidays(osv.osv):
'duration': record.number_of_days_temp * 8,
'description': record.notes,
'user_id': record.user_id.id,
'date': record.date_from,
'end_date': record.date_to,
'date_deadline': record.date_to,
'zstart': record.date_from,
'zstop': record.date_to,
'allday': False,
'state': 'open', # to block that meeting date in the calendar
'class': 'confidential'
}