[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', 'name': 'Calendar',
'version': '1.0', 'version': '1.0',
'depends': ['base', 'mail', 'base_action_rule','web_calendar'], 'depends': ['base', 'mail', 'base_action_rule', 'web_calendar'],
'summary': 'Personal & Shared Calendar', 'summary': 'Personal & Shared Calendar',
'description': """ 'description': """
This is a full-featured calendar system. 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', 'security/ir.model.access.csv',
'calendar_view.xml', 'calendar_view.xml',
'contacts_view.xml', 'contacts_view.xml',
'calendar_data.xml', 'calendar_data.xml',
], ],
'js': [ 'js': [
'static/src/js/*.js' 'static/src/js/*.js'
@ -52,14 +52,12 @@ If you need to manage your meetings, you should install the CRM module.
'css': [ 'css': [
'static/src/css/calendar.css' 'static/src/css/calendar.css'
], ],
'test' : [ 'test': [
'test/calendar_test.yml', 'test/calendar_test.yml',
'test/test_calendar_recurrent_event_case2.yml' 'test/test_calendar_recurrent_event_case2.yml'
], ],
'installable': True, 'installable': True,
'application': True, 'application': True,
'auto_install': False, 'auto_install': False,
'images': ['images/calendar1.jpeg','images/calendar2.jpeg','images/calendar3.jpeg','images/calendar4.jpeg'], '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: if len(res) >= 2:
real_id = res[0] real_id = res[0]
if with_date: if with_date:
real_date = time.strftime("%Y-%m-%d %H:%M:%S", time.strptime(res[1], "%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, "%Y-%m-%d %H:%M:%S") start = datetime.strptime(real_date, DEFAULT_SERVER_DATETIME_FORMAT)
end = start + timedelta(hours=with_date) 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 int(real_id)
return calendar_id and int(calendar_id) or calendar_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 result[id][name] = attdata.partner_id.name or False
else: else:
result[id][name] = attdata.email or '' 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 return result
STATE_SELECTION = [ 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), 'cn': fields.function(_compute_data, string='Common name', type="char", multi='cn', store=True),
'partner_id': fields.many2one('res.partner', 'Contact', readonly="True"), 'partner_id': fields.many2one('res.partner', 'Contact', readonly="True"),
'email': fields.char('Email', help="Email of Invited Person"), '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"), 'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"),
'access_token': fields.char('Invitation Token'), 'access_token': fields.char('Invitation Token'),
'event_id': fields.many2one('calendar.event', 'Meeting linked'), 'event_id': fields.many2one('calendar.event', 'Meeting linked'),
@ -144,9 +138,12 @@ class calendar_attendee(osv.Model):
""" """
res = None res = None
def ics_datetime(idate, short=False): def ics_datetime(idate, allday=False):
if idate: 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 return False
try: try:
@ -157,11 +154,11 @@ class calendar_attendee(osv.Model):
cal = vobject.iCalendar() cal = vobject.iCalendar()
event = cal.add('vevent') 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.")) 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('created').value = ics_datetime(time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
event.add('dtstart').value = ics_datetime(event_obj.date) event.add('dtstart').value = ics_datetime(event_obj.zstart, event_obj.allday)
event.add('dtend').value = ics_datetime(event_obj.date_deadline) event.add('dtend').value = ics_datetime(event_obj.zstop, event_obj.allday)
event.add('summary').value = event_obj.name event.add('summary').value = event_obj.name
if event_obj.description: if event_obj.description:
event.add('description').value = event_obj.description event.add('description').value = event_obj.description
@ -198,7 +195,7 @@ class calendar_attendee(osv.Model):
""" """
res = False 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 return res
mail_ids = [] mail_ids = []
@ -312,6 +309,10 @@ class res_partner(osv.Model):
} }
def get_attendee_detail(self, cr, uid, ids, meeting_id, context=None): 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 = [] datas = []
meeting = False meeting = False
if meeting_id: if meeting_id:
@ -339,15 +340,15 @@ class calendar_alarm_manager(osv.AbstractModel):
base_request = """ base_request = """
SELECT SELECT
cal.id, 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 CASE
WHEN cal.recurrency THEN cal.end_date - interval '1' minute * calcul_delta.min_delta WHEN cal.recurrency THEN cal.zfinal_date - interval '1' minute * calcul_delta.min_delta
ELSE cal.date_deadline - interval '1' minute * calcul_delta.min_delta ELSE cal.zstop - interval '1' minute * calcul_delta.min_delta
END as last_alarm, END as last_alarm,
cal.date as first_event_date, cal.zstart as first_event_date,
CASE CASE
WHEN cal.recurrency THEN cal.end_date WHEN cal.recurrency THEN cal.zfinal_date
ELSE cal.date_deadline ELSE cal.zstop
END as last_event_date, END as last_event_date,
calcul_delta.min_delta, calcul_delta.min_delta,
calcul_delta.max_delta, calcul_delta.max_delta,
@ -380,7 +381,7 @@ class calendar_alarm_manager(osv.AbstractModel):
tuple_params = (type_to_read,) tuple_params = (type_to_read,)
#ADD FILTER ON PARTNER_ID # ADD FILTER ON PARTNER_ID
if partner_id: if partner_id:
base_request += filter_user base_request += filter_user
tuple_params += (partner_id, ) tuple_params += (partner_id, )
@ -389,7 +390,7 @@ class calendar_alarm_manager(osv.AbstractModel):
tuple_params += (seconds, seconds,) tuple_params += (seconds, seconds,)
cr.execute("""SELECT * 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 ) 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 ) AND ALL_EVENTS.last_alarm > (now() at time zone 'utc' - interval '%%s' second )
""" % base_request, tuple_params) """ % base_request, tuple_params)
@ -421,7 +422,7 @@ class calendar_alarm_manager(osv.AbstractModel):
for alarm in event.alarm_ids: for alarm in event.alarm_ids:
if alarm.type in alarm_type and \ if alarm.type in alarm_type and \
one_date - timedelta(minutes=alarm.duration_minutes) < datetime.now() + timedelta(seconds=in_the_next_X_seconds) 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 = { alert = {
'alarm_id': alarm.id, 'alarm_id': alarm.id,
'event_id': event.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 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 break
else: 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) LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, cron_interval, notif=False, context=context)
if LastFound: if LastFound:
for alert in 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 if bFound and not LastFound: # if the precedent event had alarm but not this one, we can stop the search fot this event
break break
else: 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) 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: if LastFound:
for alert in LastFound: for alert in LastFound:
@ -539,7 +540,7 @@ class calendar_alarm_manager(osv.AbstractModel):
'title': event.name, 'title': event.name,
'message': message, 'message': message,
'timer': delta, '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 return res
_columns = { _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), 'type': fields.selection([('notification', 'Notification'), ('email', 'Email')], 'Type', required=True),
'duration': fields.integer('Amount', required=True), 'duration': fields.integer('Amount', required=True),
'interval': fields.selection([('minutes', 'Minutes'), ('hours', 'Hours'), ('days', 'Days')], 'Unit', 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' _inherit = 'ir.values'
def set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=False, preserve_user=False, company=False): def set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=False, preserve_user=False, company=False):
new_model = [] new_model = []
for data in models: for data in models:
if type(data) in (list, tuple): if type(data) in (list, tuple):
@ -648,7 +648,7 @@ class calendar_event_type(osv.Model):
class calendar_event(osv.Model): class calendar_event(osv.Model):
""" Model for Calendar Event """ """ Model for Calendar Event """
_name = 'calendar.event' _name = 'calendar.event'
_description = "Meeting" _description = "Event"
_order = "id desc" _order = "id desc"
_inherit = ["mail.thread", "ir.needaction_mixin"] _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): 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 """Get recurrent dates based on Rule string and all event where recurrent_id is child
""" """
def todate(date): def todate(date):
val = parser.parse(''.join((re.compile('\d')).findall(date))) val = parser.parse(''.join((re.compile('\d')).findall(date)))
## Dates are localized to saved timezone if any, else current timezone. ## 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) val = pytz.UTC.localize(val)
return val.astimezone(timezone) return val.astimezone(timezone)
timezone = pytz.timezone(event.vtimezone or context.get('tz') or 'UTC') timezone = pytz.timezone(context.get('tz') or 'UTC')
startdate = pytz.UTC.localize(datetime.strptime(event.date, "%Y-%m-%d %H:%M:%S")) # Add "+hh:mm" timezone startdate = pytz.UTC.localize(datetime.strptime(event.zstart, DEFAULT_SERVER_DATETIME_FORMAT)) # Add "+hh:mm" timezone
if not startdate: if not startdate:
startdate = datetime.now() startdate = datetime.now()
@ -677,20 +676,19 @@ class calendar_event(osv.Model):
rset1 = rrule.rrulestr(str(event.rrule), dtstart=startdate, forceset=True) 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) 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) all_events = self.browse(cr, uid, ids_depending, context=context)
for ev in all_events: for ev in all_events:
rset1._exdate.append(todate(ev.recurrent_id_date)) rset1._exdate.append(todate(ev.recurrent_id_date))
return [d.astimezone(pytz.UTC) for d in rset1] 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'): if not data.get('recurrency'):
return False return False
end_type = data.get('end_type') end_type = data.get('end_type')
end_date = data.get('end_date') final_date = data.get('zfinal_date')
if end_type == 'count' and all(data.get(key) for key in ['count', 'rrule_type', 'zstop']):
if end_type == 'count' and all(data.get(key) for key in ['count', 'rrule_type', 'date_deadline']):
count = data['count'] + 1 count = data['count'] + 1
delay, mult = { delay, mult = {
'daily': ('days', 1), 'daily': ('days', 1),
@ -699,9 +697,9 @@ class calendar_event(osv.Model):
'yearly': ('years', 1), 'yearly': ('years', 1),
}[data['rrule_type']] }[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 deadline + relativedelta(**{delay: count * mult})
return end_date return final_date
def _find_my_attendee(self, cr, uid, meeting_ids, context=None): def _find_my_attendee(self, cr, uid, meeting_ids, context=None):
""" """
@ -714,7 +712,7 @@ class calendar_event(osv.Model):
return attendee return attendee
return False 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 : Return date and time (from to from) based on duration with timezone in string :
eg. 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 ! if not tz: # tz can have a value False, so dont do it in the default value of get !
tz = pytz.timezone('UTC') tz = pytz.timezone('UTC')
meeting = self.browse(cr, uid, meeting_id, context=context) date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(zstart, tools.DEFAULT_SERVER_DATETIME_FORMAT), 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(zstop, 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)
event_date = date.strftime('%B-%d-%Y') event_date = date.strftime('%B-%d-%Y')
display_time = date.strftime('%H-%M') display_time = date.strftime('%H-%M')
if meeting.allday: if zallday:
time = _("AllDay , %s") % (event_date) time = _("AllDay , %s") % (event_date)
elif meeting.duration < 24: elif zduration < 24:
duration = date + timedelta(hours=meeting.duration) duration = date + timedelta(hours=zduration)
time = ("%s at (%s To %s) (%s)") % (event_date, display_time, duration.strftime('%H-%M'), tz) time = ("%s at (%s To %s) (%s)") % (event_date, display_time, duration.strftime('%H-%M'), tz)
else: 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) 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: for meeting_id in ids:
res[meeting_id] = {} res[meeting_id] = {}
attendee = self._find_my_attendee(cr, uid, [meeting_id], context) attendee = self._find_my_attendee(cr, uid, [meeting_id], context)
meeting = self.browse(cr, uid, [meeting_id], context=context)[0]
for field in fields: for field in fields:
if field == 'is_attendee': if field == 'is_attendee':
res[meeting_id][field] = True if attendee else False res[meeting_id][field] = True if attendee else False
elif field == 'attendee_status': elif field == 'attendee_status':
res[meeting_id][field] = attendee.state if attendee else 'needsAction' res[meeting_id][field] = attendee.state if attendee else 'needsAction'
elif field == 'display_time': 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 return res
def _get_rulestring(self, cr, uid, ids, name, arg, context=None): 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: if data.count and data.count <= 0:
raise osv.except_osv(_('Warning!'), _('Count cannot be negative or 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'] event = data['id']
if data['recurrency']: if data['recurrency']:
result[event] = self.compute_rule_string(data) result[event] = self.compute_rule_string(data)
@ -793,20 +798,53 @@ class calendar_event(osv.Model):
if field_value: if field_value:
data['recurrency'] = True data['recurrency'] = True
for event in self.browse(cr, uid, ids, context=context): 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) update_data = self._parse_rrule(field_value, dict(data), rdate)
data.update(update_data) data.update(update_data)
self.write(cr, uid, ids, data, context=context) self.write(cr, uid, ids, data, context=context)
return True return True
def _tz_get(self, cr, uid, context=None): def _set_date(self, cr, uid, values, id=False, context=None):
return [(x.lower(), x) for x in pytz.all_timezones]
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 = { _track = {
'location': { 'location': {
'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True, 'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True,
}, },
'date': { 'zstart': {
'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True, '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'), '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'), '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'), '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'), 'display_start': fields.function(_compute, string='Date', type="char", multi='display_start', store=True),
'date_deadline': fields.datetime('End Date', states={'done': [('readonly', True)]}, required=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)]}), 'duration': fields.float('Duration', states={'done': [('readonly', True)]}),
'description': fields.text('Description', 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)]}), '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)]}), '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)]}), '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': 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"), '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"), 'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"),
'recurrent_id': fields.integer('Recurrent ID'), 'recurrent_id': fields.integer('Recurrent ID'),
'recurrent_id_date': fields.datetime('Recurrent ID date'), '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'), '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)"), 'interval': fields.integer('Repeat Every', help="Repeat every (Days/Week/Month/Year)"),
'count': fields.integer('Repeat', help="Repeat x times"), 'count': fields.integer('Repeat', help="Repeat x times"),
@ -844,21 +889,21 @@ class calendar_event(osv.Model):
'day': fields.integer('Date of month'), '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'), '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'), 'byday': fields.selection([('1', 'First'), ('2', 'Second'), ('3', 'Third'), ('4', 'Fourth'), ('5', 'Fifth'), ('-1', 'Last')], 'By day'),
'end_date': fields.date('Repeat Until'), 'zfinal_date': fields.date('Repeat Until'), # The last event of a recurrence
'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}),
'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}), '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 '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."), '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'), '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'), 'attendee_ids': fields.one2many('calendar.attendee', 'event_id', 'Attendees', ondelete='cascade'),
'partner_ids': fields.many2many('res.partner', string='Attendees', states={'done': [('readonly', True)]}), 'partner_ids': fields.many2many('res.partner', 'calendar_event_res_partner_rel', string='Attendees', states={'done': [('readonly', True)]}),
'alarm_ids': fields.many2many('calendar.alarm', string='Reminders', ondelete="restrict"), 'alarm_ids': fields.many2many('calendar.alarm', 'calendar_alarm_calendar_event_rel', string='Reminders', ondelete="restrict"),
} }
_defaults = { _defaults = {
'end_type': 'count', 'end_type': 'count',
'count': 1, 'count': 1,
'rrule_type': False, 'rrule_type': False,
'allday': False,
'state': 'draft', 'state': 'draft',
'class': 'public', 'class': 'public',
'show_as': 'busy', 'show_as': 'busy',
@ -871,58 +916,86 @@ class calendar_event(osv.Model):
def _check_closing_date(self, cr, uid, ids, context=None): def _check_closing_date(self, cr, uid, ids, context=None):
for event in self.browse(cr, uid, ids, context=context): for event in self.browse(cr, uid, ids, context=context):
if event.date_deadline < event.date: if event.zstop < event.zstart:
return False return False
return True return True
_constraints = [ _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): def onchange_allday(self, cr, uid, ids, start=False, end=False, starttime=False, endtime=False, startdatetime=False, enddatetime=False, checkallday=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 = {}
value = {} value = {}
if not start_date:
if not ((starttime and endtime) or (start and end)): # At first intialize, we have not datetime
return value return value
if not end_date and not duration: if checkallday: # from datetime to date
duration = 1.00 startdatetime = startdatetime or start
value['duration'] = duration 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 enddatetime = enddatetime or end
start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S") if enddatetime:
user = self.pool['res.users'].browse(cr, uid, uid) 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 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 if starttime:
value['date'] = datetime.strftime(start, "%Y-%m-%d %H:%M:%S") 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: else:
start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S") if fromtype == 'start':
start = datetime.strptime(start, DEFAULT_SERVER_DATETIME_FORMAT)
if end_date and not duration: value['zstart_date'] = datetime.strftime(start, DEFAULT_SERVER_DATE_FORMAT)
end = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S") value['zstart'] = datetime.strftime(start, DEFAULT_SERVER_DATETIME_FORMAT)
diff = end - start if fromtype == 'stop':
duration = float(diff.days) * 24 + (float(diff.seconds) / 3600) end = datetime.strptime(end, DEFAULT_SERVER_DATETIME_FORMAT)
value['duration'] = round(duration, 2) value['zstop_date'] = datetime.strftime(end, DEFAULT_SERVER_DATE_FORMAT)
elif not end_date: value['zstop'] = datetime.strftime(end, DEFAULT_SERVER_DATETIME_FORMAT)
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)
return {'value': value} 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 @param order: The fields (comma separated, format "FIELD {DESC|ASC}") on which the events should be sorted
""" """
if not context: if not context:
context = {} context = {}
@ -1034,7 +1106,6 @@ class calendar_event(osv.Model):
result.append(ev.id) result.append(ev.id)
result_data.append(self.get_search_fields(ev, order_fields)) result_data.append(self.get_search_fields(ev, order_fields))
continue continue
rdates = self.get_recurrent_date_by_event(cr, uid, ev, context=context) rdates = self.get_recurrent_date_by_event(cr, uid, ev, context=context)
for r_date in rdates: for r_date in rdates:
@ -1045,7 +1116,7 @@ class calendar_event(osv.Model):
pile = [] pile = []
ok = True ok = True
for arg in domain: 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] == '='): if (arg[1] == '='):
ok = r_date.strftime('%Y-%m-%d') == arg[2] ok = r_date.strftime('%Y-%m-%d') == arg[2]
if (arg[1] == '>'): if (arg[1] == '>'):
@ -1108,8 +1179,6 @@ class calendar_event(osv.Model):
weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'] weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
if freq == 'weekly': 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(), 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: if byday:
return ';BYDAY=' + ','.join(byday) return ';BYDAY=' + ','.join(byday)
return '' return ''
@ -1126,8 +1195,8 @@ class calendar_event(osv.Model):
return '' return ''
def get_end_date(data): def get_end_date(data):
if data.get('end_date'): if data.get('zfinal_date'):
data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('end_date'))) + 'T235959Z' 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 '') +\ 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 '') ((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 { return {
'byday': False, 'byday': False,
'recurrency': False, 'recurrency': False,
'end_date': False, 'zfinal_date': False,
'rrule_type': False, 'rrule_type': False,
'month_by': False, 'month_by': False,
'interval': 0, 'interval': 0,
@ -1164,14 +1233,13 @@ class calendar_event(osv.Model):
def _parse_rrule(self, rule, data, date_start): def _parse_rrule(self, rule, data, date_start):
day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'] day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
rrule_type = ['yearly', 'monthly', 'weekly', 'daily'] 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: if r._freq > 0 and r._freq < 4:
data['rrule_type'] = rrule_type[r._freq] data['rrule_type'] = rrule_type[r._freq]
data['count'] = r._count data['count'] = r._count
data['interval'] = r._interval 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 #repeat weekly
if r._byweekday: if r._byweekday:
for i in xrange(0, 7): for i in xrange(0, 7):
@ -1197,12 +1265,12 @@ class calendar_event(osv.Model):
#FIXEME handle forever case #FIXEME handle forever case
#end of recurrence #end of recurrence
#in case of repeat for ever that we do not support right now #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 data['count'] = 100
if data.get('count'): if data.get('count'):
data['end_type'] = 'count' data['end_type'] = 'count'
else: else:
data['end_type'] = 'end_date' data['end_type'] = 'zfinal_date'
return data return data
def message_get_subscription_data(self, cr, uid, ids, user_pid=None, context=None): 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)) res.update(self.check_partners_email(cr, uid, value[0][2], context=context))
return res 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): def check_partners_email(self, cr, uid, partner_ids, context=None):
""" Verify that selected partner_ids have an email_address defined. """ Verify that selected partner_ids have an email_address defined.
Otherwise throw a warning. """ Otherwise throw a warning. """
@ -1262,14 +1311,13 @@ class calendar_event(osv.Model):
'message': warning_msg, 'message': warning_msg,
}} }}
# ----------------------------------------
# OpenChatter
# ----------------------------------------
# shows events of the day for this user # shows events of the day for this user
def _needaction_domain_get(self, cr, uid, context=None): 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): 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): if isinstance(thread_id, str):
@ -1326,15 +1374,15 @@ class calendar_event(osv.Model):
if context.get('mymeetings', False): if context.get('mymeetings', False):
partner_id = self.pool['res.users'].browse(cr, uid, uid, context).partner_id.id 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 = [] new_args = []
for arg in args: for arg in args:
new_arg = arg 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): 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": elif arg[0] == "id":
new_id = get_real_ids(arg[2]) new_id = get_real_ids(arg[2])
new_arg = (arg[0], arg[1], new_id) new_arg = (arg[0], arg[1], new_id)
@ -1357,6 +1405,8 @@ class calendar_event(osv.Model):
context = {} context = {}
default = default or {} default = default or {}
self._set_date(cr, uid, default, id=default.get('id'), context=context)
default['attendee_ids'] = False default['attendee_ids'] = False
res = super(calendar_event, self).copy(cr, uid, calendar_id2real_id(id), default, context) 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): def _detach_one_event(self, cr, uid, id, values=dict(), context=None):
real_event_id = calendar_id2real_id(id) 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'): if data.get('rrule'):
data.update( data.update(
values, values,
recurrent_id=real_event_id, recurrent_id=real_event_id,
recurrent_id_date=data.get('date'), recurrent_id_date=data.get('zstart'),
rrule_type=False, rrule_type=False,
rrule='', rrule='',
recurrency=False, 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 #do not copy the id
@ -1397,21 +1448,34 @@ class calendar_event(osv.Model):
'flags': {'form': {'action_buttons': True, 'options': {'mode': 'edit'}}} '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 write(self, cr, uid, ids, values, context=None):
def _only_changes_to_apply_on_real_ids(field_names): def _only_changes_to_apply_on_real_ids(field_names):
''' return True if changes are only to be made on the real ids''' ''' return True if changes are only to be made on the real ids'''
for field in field_names: 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 True
return False return False
context = context or {} if not isinstance(ids, (tuple, list)):
ids = [ids]
if isinstance(ids, (str, int, long)): context = context or {}
if len(str(ids).split('-')) == 1: self._set_date(cr, uid, values, id=ids[0], context=context)
ids = [int(ids)]
else: for one_ids in ids:
ids = [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 res = False
new_id = False new_id = False
@ -1431,7 +1495,7 @@ class calendar_event(osv.Model):
ids.append(real_event_id) ids.append(real_event_id)
continue continue
else: 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'): if data.get('rrule'):
new_id = self._detach_one_event(cr, uid, event_id, values, context=None) 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 # set end_date for calendar searching
if values.get('recurrency', True) and values.get('end_type', 'count') in ('count', unicode('count')) and \ 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')): (values.get('rrule_type') or values.get('count') or values.get('zstart') or values.get('zstop')):
for data in self.read(cr, uid, ids, ['end_date', 'date_deadline', 'recurrency', 'rrule_type', 'count', 'end_type'], context=context): for id in ids:
end_date = self._get_recurrency_end_date(data, context=context) final_date = self._get_recurrency_end_date(cr, uid, id, context=context)
super(calendar_event, self).write(cr, uid, [data['id']], {'end_date': end_date}, context=context) super(calendar_event, self).write(cr, uid, [id], {'zfinal_date': final_date}, context=context)
attendees_create = False attendees_create = False
if values.get('partner_ids', False): if values.get('partner_ids', False):
attendees_create = self.create_attendees(cr, uid, ids, context) 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])) the_id = new_id or (ids and int(ids[0]))
if attendees_create: if attendees_create:
@ -1461,21 +1525,20 @@ class calendar_event(osv.Model):
current_user = self.pool['res.users'].browse(cr, uid, uid, context=context) 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): 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) 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 return res or True and False
def create(self, cr, uid, vals, context=None): def create(self, cr, uid, vals, context=None):
if context is None: if context is None:
context = {} 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 if not 'user_id' in vals: # Else bug with quick_create when we are filter on an other user
vals['user_id'] = uid vals['user_id'] = uid
res = super(calendar_event, self).create(cr, uid, vals, context=context) 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] final_date = self._get_recurrency_end_date(cr, uid, res, context=context)
end_date = self._get_recurrency_end_date(data, context=context) self.write(cr, uid, [res], {'zfinal_date': final_date}, context=context)
self.write(cr, uid, [res], {'end_date': end_date}, context=context)
self.create_attendees(cr, uid, [res], context=context) self.create_attendees(cr, uid, [res], context=context)
return res return res
@ -1501,28 +1564,35 @@ class calendar_event(osv.Model):
if context is None: if context is None:
context = {} context = {}
fields2 = fields and fields[:] or None 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: for f in EXTRAFIELDS:
if fields and (f not in fields): if fields and (f not in fields):
fields2.append(f) fields2.append(f)
if isinstance(ids, (str, int, long)): if isinstance(ids, (str, int, long)):
select = [ids] select = [ids]
else: else:
select = ids select = ids
select = map(lambda x: (x, calendar_id2real_id(x)), select) select = map(lambda x: (x, calendar_id2real_id(x)), select)
result = [] 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 = 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)) real_data = dict(zip([x['id'] for x in real_data], real_data))
for calendar_id, real_id in select: for calendar_id, real_id in select:
res = real_data[real_id].copy() 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: if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
res['date'] = ls[1] res['zstart'] = ls[1]
res['date_deadline'] = ls[2] 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 res['id'] = calendar_id
result.append(res) result.append(res)
@ -1533,7 +1603,7 @@ class calendar_event(osv.Model):
continue continue
if r['class'] == 'private': if r['class'] == 'private':
for f in r.keys(): 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): if isinstance(r[f], list):
r[f] = [] r[f] = []
else: else:
@ -1545,12 +1615,11 @@ class calendar_event(osv.Model):
for k in EXTRAFIELDS: for k in EXTRAFIELDS:
if (k in r) and (fields and (k not in fields)): if (k in r) and (fields and (k not in fields)):
del r[k] del r[k]
if isinstance(ids, (str, int, long)): if isinstance(ids, (str, int, long)):
return result and result[0] or False return result and result[0] or False
return result 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): if not isinstance(ids, list):
ids = [ids] ids = [ids]
res = False res = False
@ -1558,9 +1627,8 @@ class calendar_event(osv.Model):
ids_to_exclure = [] ids_to_exclure = []
ids_to_unlink = [] 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: 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: if self.browse(cr, uid, event_id).recurrent_id:
ids_to_exclure.append(event_id) ids_to_exclure.append(event_id)
else: else:

View File

@ -142,12 +142,12 @@
<table> <table>
<tr> <tr>
<td> <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;"> <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>
<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='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.date, 'time', tz=object.partner_id.tz) or ''}</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>
<td> <td>
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;"> <table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
@ -275,12 +275,12 @@
<table> <table>
<tr> <tr>
<td> <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;"> <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>
<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='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.date, 'time', tz=object.partner_id.tz) or ''}</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>
<td> <td>
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;"> <table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
@ -407,12 +407,12 @@
<table> <table>
<tr> <tr>
<td> <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;"> <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>
<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='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.date, 'time', tz=object.partner_id.tz) or ''}</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>
<td> <td>
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;"> <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="partner_ids" eval="[(6,0,[ref('base.res_partner_6')])]"/>
<field name="name">Follow-up for Project proposal</field> <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 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 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="6.3" name="duration"/>
<field eval="0" name="allday"/>
<field name="state">open</field> <field name="state">open</field>
</record> </record>
<record id="calendar_event_2" model="calendar.event"> <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="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="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="name">Initial discussion</field>
<field name="description">Discussion with partner for product.</field> <field name="description">Discussion with partner for product.</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet3')])]"/> <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 12:00:00')" name="zstart"/>
<field eval="time.strftime('%Y-%m-05 19:00:00')" name="date_deadline"/> <field eval="time.strftime('%Y-%m-05 19:00:00')" name="zstop"/>
<field eval="0" name="allday"/>
<field eval="7.0" name="duration"/> <field eval="7.0" name="duration"/>
<field name="state">draft</field> <field name="state">draft</field>
</record> </record>
@ -49,9 +51,10 @@
<field name="name">Pricing Discussion</field> <field name="name">Pricing Discussion</field>
<field name="description">Internal meeting for discussion for new pricing for product and services.</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 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 15:55:05')" name="zstart"/>
<field eval="time.strftime('%Y-%m-12 18:55:05')" name="date_deadline"/> <field eval="time.strftime('%Y-%m-12 18:55:05')" name="zstop"/>
<field eval="3.0" name="duration"/> <field eval="3.0" name="duration"/>
<field eval="0" name="allday"/>
<field name="state">open</field> <field name="state">open</field>
</record> </record>
@ -61,9 +64,10 @@
<field name="partner_ids" eval="[(6,0,[ref('base.partner_demo'),ref('base.res_partner_6')])]"/> <field name="partner_ids" eval="[(6,0,[ref('base.partner_demo'),ref('base.res_partner_6')])]"/>
<field name="name">Requirements review</field> <field name="name">Requirements review</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet3')])]"/> <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 8:00:00')" name="zstart"/>
<field eval="time.strftime('%Y-%m-20 10:30:00')" name="date_deadline"/> <field eval="time.strftime('%Y-%m-20 10:30:00')" name="zstop"/>
<field eval="2.5" name="duration"/> <field eval="2.5" name="duration"/>
<field eval="0" name="allday"/>
<field name="state">open</field> <field name="state">open</field>
</record> </record>
@ -72,9 +76,9 @@
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_8')])]"/> <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="name">Changes in Designing</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/> <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')" name="zstart"/>
<field eval="time.strftime('%Y-%m-22 16:05:00')" name="date_deadline"/> <field eval="time.strftime('%Y-%m-22')" name="zstop"/>
<field eval="5" name="duration"/> <field eval="1" name="allday"/>
<field name="state">open</field> <field name="state">open</field>
</record> </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="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="name">Presentation for new Services</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/> <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 2:00:00')" name="zstart"/>
<field eval="time.strftime('%Y-%m-18 10:30:00')" name="date_deadline"/> <field eval="time.strftime('%Y-%m-18 10:30:00')" name="zstop"/>
<field eval="8.5" name="duration"/> <field eval="8.5" name="duration"/>
<field eval="0" name="allday"/>
<field name="state">draft</field> <field name="state">draft</field>
</record> </record>
@ -96,9 +101,10 @@
<field name="partner_ids" eval="[(6,0,[ref('base.res_partner_7')])]"/> <field name="partner_ids" eval="[(6,0,[ref('base.res_partner_7')])]"/>
<field name="name">Presentation of the new Calendar</field> <field name="name">Presentation of the new Calendar</field>
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/> <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')" name="zstart"/>
<field eval="time.strftime('%Y-%m-16 18:30:00')" name="date_deadline"/> <field eval="time.strftime('%Y-%m-16')" name="zstop"/>
<field eval="8.5" name="duration"/> <field eval="8.5" name="duration"/>
<field eval="1" name="allday"/>
<field name="state">draft</field> <field name="state">draft</field>
</record> </record>

View File

@ -9,7 +9,7 @@
<field name="name">Meeting Types Tree</field> <field name="name">Meeting Types Tree</field>
<field name="model">calendar.event.type</field> <field name="model">calendar.event.type</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Meeting Types"> <tree string="Meeting Types" editable="bottom">
<field name="name"/> <field name="name"/>
</tree> </tree>
</field> </field>
@ -58,24 +58,24 @@
</group> </group>
<group> <group>
<group> <group>
<field name="date" string="Starting at" on_change="onchange_dates(date, duration, False, allday)"/> <field name="zstart" attrs="{'invisible': True}"/>
<label for="duration"/> <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> <div>
<field name="duration" widget="float_time" <field name="allday" class="oe_inline" on_change="onchange_allday(zstart, zstop, zstart_date, zstop_date, zstart_datetime, zstop_datetime, allday)"/>
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?"/>)
</div> </div>
<field name="date_deadline" groups="base.group_no_one" <field name="duration" widget="float_time" class="oe_inline" attrs="{ 'invisible': True }"/>
attrs="{'invisible': ['|', ('allday','=',True), ('duration','&lt;', 24)]}"
/>
</group> </group>
<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="alarm_ids" widget="many2many_tags" />
<field name="location"/> <field name="location" />
</group> </group>
</group> </group>
@ -98,17 +98,17 @@
<div> <div>
<field name="end_type" attrs="{'required': [('recurrency','==',True)]}" class="oe_inline"/> <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="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> </div>
<label string="Select Weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}"/> <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'])]}" > <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="mo" />
<field name="tu" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/> <field name="tu" />
<field name="we" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/> <field name="we" />
<field name="th" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/> <field name="th" />
<field name="fr" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/> <field name="fr" />
<field name="sa" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/> <field name="sa" />
<field name="su" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/> <field name="su" />
</group> </group>
<label string="Day of Month" <label string="Day of Month"
@ -178,7 +178,9 @@
<field name="name"/> <field name="name"/>
<group> <group>
<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="duration" string="Duration" widget="float_time" attrs="{'invisible': [('allday','=',True)]}"/>
<field name="allday" class="oe_inline" attrs="{'invisible': [('allday','=',False)]}"/> <field name="allday" class="oe_inline" attrs="{'invisible': [('allday','=',False)]}"/>
<field name="partner_ids" widget="many2manyattendee" string="Attendees"/> <field name="partner_ids" widget="many2manyattendee" string="Attendees"/>
@ -201,7 +203,8 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Meetings" fonts="bold:message_unread==True"> <tree string="Meetings" fonts="bold:message_unread==True">
<field name="name" string="Subject"/> <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="user_id"/>
<field name="location"/> <field name="location"/>
<field name="show_as"/> <field name="show_as"/>
@ -219,7 +222,7 @@
<field name="model">calendar.event</field> <field name="model">calendar.event</field>
<field name="priority" eval="2"/> <field name="priority" eval="2"/>
<field name="arch" type="xml"> <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" 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"> use_contacts="True" event_open_popup="%(calendar.view_calendar_event_form_popup)s">
@ -260,8 +263,7 @@
<group expand="0" string="Group By..."> <group expand="0" string="Group By...">
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> <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="Availability" icon="terp-camera_test" domain="[]" context="{'group_by':'show_as'}"/>
<filter string="Privacy" icon="terp-locked" domain="[]" context="{'group_by':'class'}"/> <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"/>
</group> </group>
</search> </search>
</field> </field>

View File

@ -11,7 +11,7 @@
</t> </t>
</t> </t>
<t t-name='notify_title'> <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"/> <t t-esc="title"/>
</span> </span>
</t> </t>

View File

@ -3,8 +3,8 @@
- -
!record {model: calendar.event, id: calendar_event_technicalpresentation0}: !record {model: calendar.event, id: calendar_event_technicalpresentation0}:
class: private class: private
date: '2011-04-30 16:00:00' zstart: '2011-04-30 16:00:00'
date_deadline: '2011-04-30 18:30:00' zstop: '2011-04-30 18:30:00'
description: The Technical Presentation will cover following topics:\n* Creating OpenERP description: The Technical Presentation will cover following topics:\n* Creating OpenERP
class\n* Views\n* Wizards\n* Workflows class\n* Views\n* Wizards\n* Workflows
duration: 2.5 duration: 2.5
@ -14,7 +14,7 @@
Now I will set recurrence for this event to occur monday and friday of week Now I will set recurrence for this event to occur monday and friday of week
- -
!python {model: calendar.event}: | !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) 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 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 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}: | !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' 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 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}: | !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} )
before = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False}) 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 # We start by detach the event
newid = self._detach_one_event(cr, uid,ids[1]) newid = self._detach_one_event(cr, uid,ids[1])
self.write(cr, uid,[newid], {'name':'New Name','recurrency' : True}, context={'virtual_id': True}) 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' 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_id = list(set(after)-set(before))[0]
new_event = self.browse(cr,uid,new_id,context=context) new_event = self.browse(cr,uid,new_id,context=context)
@ -47,8 +47,8 @@
!record {model: calendar.event, id: calendar_event_alldaytestevent0}: !record {model: calendar.event, id: calendar_event_alldaytestevent0}:
allday: 1 allday: 1
class: confidential class: confidential
date: '2011-04-30 00:00:00' zstart: '2011-04-30 00:00:00'
date_deadline: '2011-04-30 00:00:00' zstop: '2011-04-30 00:00:00'
description: 'All day technical test ' description: 'All day technical test '
location: School location: School
name: All day test event name: All day test event
@ -70,7 +70,8 @@
- -
!record {model: calendar.event, id: calendar.event_sprintreview1}: !record {model: calendar.event, id: calendar.event_sprintreview1}:
name: Begin of month meeting 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 recurrency: true
rrule: FREQ=MONTHLY;INTERVAL=1;COUNT=12;BYDAY=1MO rrule: FREQ=MONTHLY;INTERVAL=1;COUNT=12;BYDAY=1MO
- -

View File

@ -5,8 +5,8 @@
- -
!record {model: calendar.event, id: calendar_event_testmeeting0}: !record {model: calendar.event, id: calendar_event_testmeeting0}:
count: 5 count: 5
date: '2011-04-13 11:04:00' zstart: '2011-04-13 11:04:00'
date_deadline: '2011-04-13 12:04:00' zstop: '2011-04-13 12:04:00'
day: 0.0 day: 0.0
duration: 1.0 duration: 1.0
name: Test Meeting name: Test Meeting
@ -17,17 +17,17 @@
I search for all the recurrent meetings. I search for all the recurrent meetings.
- -
!python {model: calendar.event}: | !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 !' assert len(meeting_ids) == 5, 'Recurrent daily meetings are not created !'
- -
I create a weekly meeting till a particular end date. I create a weekly meeting till a particular end date.
- -
!record {model: calendar.event, id: calendar_event_reviewcodewithprogrammer0}: !record {model: calendar.event, id: calendar_event_reviewcodewithprogrammer0}:
date: '2011-04-18 11:47:00' zstart: '2011-04-18 11:47:00'
date_deadline: '2011-04-18 12:47:00' zstop: '2011-04-18 12:47:00'
day: 0.0 day: 0.0
duration: 1.0 duration: 1.0
end_date: '2011-04-30' zfinal_date: '2011-04-30'
end_type: end_date end_type: end_date
fr: true fr: true
mo: true mo: true
@ -36,21 +36,21 @@
we: true we: true
name: Review code with programmer name: Review code with programmer
recurrency: true recurrency: true
recurrent_id: 0.0 recurrent_id: 0
rrule_type: weekly rrule_type: weekly
- -
I search for all the recurrent weekly meetings. I search for all the recurrent weekly meetings.
- -
!python {model: calendar.event}: | !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 !' assert len(meeting_ids) == 10, 'Recurrent weekly meetings are not created !'
- -
I want to schedule a meeting every month for Sprint review. I want to schedule a meeting every month for Sprint review.
- -
!record {model: calendar.event, id: calendar_event_sprintreview0}: !record {model: calendar.event, id: calendar_event_sprintreview0}:
count: 12 count: 12
date: '2011-04-01 12:01:00' zstart: '2011-04-01 12:01:00'
date_deadline: '2011-04-01 13:01:00' zstop: '2011-04-01 13:01:00'
day: 1 day: 1
duration: 1.0 duration: 1.0
name: Sprint Review name: Sprint Review
@ -61,7 +61,7 @@
I search for all the recurrent monthly meetings. I search for all the recurrent monthly meetings.
- -
!python {model: calendar.event}: | !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 !' assert len(meeting_ids) == 12, 'Recurrent monthly meetings are not created !'
- -
I change name of my monthly Sprint Review meeting. I change name of my monthly Sprint Review meeting.
@ -73,7 +73,7 @@
I check whether all the records are edited or not. I check whether all the records are edited or not.
- -
!python {model: calendar.event}: | !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) meetings = self.browse(cr, uid, meeting_ids, context)
for meeting in meetings: for meeting in meetings:
assert meeting.name == 'Sprint Review for google modules', 'Name not changed for id: %s' %meeting.id 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) res = super(calendar_event, self).create(cr, uid, vals, context=context)
obj = self.browse(cr, uid, res, context=context) obj = self.browse(cr, uid, res, context=context)
if obj.opportunity_id: 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 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: # 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_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_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_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,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 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 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: else:
if event_to_synchronize[base_event][0][1].OE.event_id: if event_to_synchronize[base_event][0][1].OE.event_id:
parent_oe_id = 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): elif isinstance(actToDo, Delete):
if actSrc == 'GG': if actSrc == 'GG':
self.delete_an_event(cr, uid, current_event[0], context=context) self.delete_an_event(cr, uid, current_event[0], context=context)
elif actSrc == 'OE': 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 return True
def check_and_sync(self, cr, uid, oe_event, google_event, context): 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 default['oe_update_date'] = False
return super(calendar_event, self).copy(cr, uid, id, default, context) 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 = { _columns = {
'oe_update_date': fields.datetime('OpenERP Update Date'), '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, 'duration': record.number_of_days_temp * 8,
'description': record.notes, 'description': record.notes,
'user_id': record.user_id.id, 'user_id': record.user_id.id,
'date': record.date_from, 'zstart': record.date_from,
'end_date': record.date_to, 'zstop': record.date_to,
'date_deadline': record.date_to, 'allday': False,
'state': 'open', # to block that meeting date in the calendar 'state': 'open', # to block that meeting date in the calendar
'class': 'confidential' 'class': 'confidential'
} }