[REF] Calendar refactoring - Manage allday in date field and not datetime.
bzr revid: jke@openerp.com-20140430093613-3tdn2tfiwshcahbz
This commit is contained in:
parent
162fff3bfe
commit
d9c3c175bd
|
@ -22,7 +22,7 @@
|
|||
{
|
||||
'name': 'Calendar',
|
||||
'version': '1.0',
|
||||
'depends': ['base', 'mail', 'base_action_rule','web_calendar'],
|
||||
'depends': ['base', 'mail', 'base_action_rule', 'web_calendar'],
|
||||
'summary': 'Personal & Shared Calendar',
|
||||
'description': """
|
||||
This is a full-featured calendar system.
|
||||
|
@ -43,7 +43,7 @@ If you need to manage your meetings, you should install the CRM module.
|
|||
'security/ir.model.access.csv',
|
||||
'calendar_view.xml',
|
||||
'contacts_view.xml',
|
||||
'calendar_data.xml',
|
||||
'calendar_data.xml',
|
||||
],
|
||||
'js': [
|
||||
'static/src/js/*.js'
|
||||
|
@ -52,14 +52,12 @@ If you need to manage your meetings, you should install the CRM module.
|
|||
'css': [
|
||||
'static/src/css/calendar.css'
|
||||
],
|
||||
'test' : [
|
||||
'test/calendar_test.yml',
|
||||
'test/test_calendar_recurrent_event_case2.yml'
|
||||
],
|
||||
'test': [
|
||||
'test/calendar_test.yml',
|
||||
'test/test_calendar_recurrent_event_case2.yml'
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
'images': ['images/calendar1.jpeg','images/calendar2.jpeg','images/calendar3.jpeg','images/calendar4.jpeg'],
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -54,10 +54,10 @@ def calendar_id2real_id(calendar_id=None, with_date=False):
|
|||
if len(res) >= 2:
|
||||
real_id = res[0]
|
||||
if with_date:
|
||||
real_date = time.strftime("%Y-%m-%d %H:%M:%S", time.strptime(res[1], "%Y%m%d%H%M%S"))
|
||||
start = datetime.strptime(real_date, "%Y-%m-%d %H:%M:%S")
|
||||
real_date = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT, time.strptime(res[1], "%Y%m%d%H%M%S"))
|
||||
start = datetime.strptime(real_date, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
end = start + timedelta(hours=with_date)
|
||||
return (int(real_id), real_date, end.strftime("%Y-%m-%d %H:%M:%S"))
|
||||
return (int(real_id), real_date, end.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
|
||||
return int(real_id)
|
||||
return calendar_id and int(calendar_id) or calendar_id
|
||||
|
||||
|
@ -95,10 +95,6 @@ class calendar_attendee(osv.Model):
|
|||
result[id][name] = attdata.partner_id.name or False
|
||||
else:
|
||||
result[id][name] = attdata.email or ''
|
||||
if name == 'event_date':
|
||||
result[id][name] = attdata.event_id.date
|
||||
if name == 'event_end_date':
|
||||
result[id][name] = attdata.event_id.date_deadline
|
||||
return result
|
||||
|
||||
STATE_SELECTION = [
|
||||
|
@ -113,8 +109,6 @@ class calendar_attendee(osv.Model):
|
|||
'cn': fields.function(_compute_data, string='Common name', type="char", multi='cn', store=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Contact', readonly="True"),
|
||||
'email': fields.char('Email', help="Email of Invited Person"),
|
||||
'event_date': fields.function(_compute_data, string='Event Date', type="datetime", multi='event_date'),
|
||||
'event_end_date': fields.function(_compute_data, string='Event End Date', type="datetime", multi='event_end_date'),
|
||||
'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"),
|
||||
'access_token': fields.char('Invitation Token'),
|
||||
'event_id': fields.many2one('calendar.event', 'Meeting linked'),
|
||||
|
@ -144,9 +138,12 @@ class calendar_attendee(osv.Model):
|
|||
"""
|
||||
res = None
|
||||
|
||||
def ics_datetime(idate, short=False):
|
||||
def ics_datetime(idate, allday=False):
|
||||
if idate:
|
||||
return datetime.strptime(idate.split('.')[0], '%Y-%m-%d %H:%M:%S').replace(tzinfo=pytz.timezone('UTC'))
|
||||
if allday:
|
||||
return datetime.strptime(idate.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT).replace(tzinfo=pytz.timezone('UTC'))
|
||||
else:
|
||||
return datetime.strptime(idate.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT).replace(tzinfo=pytz.timezone('UTC'))
|
||||
return False
|
||||
|
||||
try:
|
||||
|
@ -157,11 +154,11 @@ class calendar_attendee(osv.Model):
|
|||
|
||||
cal = vobject.iCalendar()
|
||||
event = cal.add('vevent')
|
||||
if not event_obj.date_deadline or not event_obj.date:
|
||||
if not event_obj.zstart or not event_obj.zstop:
|
||||
raise osv.except_osv(_('Warning!'), _("First you have to specify the date of the invitation."))
|
||||
event.add('created').value = ics_datetime(time.strftime('%Y-%m-%d %H:%M:%S'))
|
||||
event.add('dtstart').value = ics_datetime(event_obj.date)
|
||||
event.add('dtend').value = ics_datetime(event_obj.date_deadline)
|
||||
event.add('created').value = ics_datetime(time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
|
||||
event.add('dtstart').value = ics_datetime(event_obj.zstart, event_obj.allday)
|
||||
event.add('dtend').value = ics_datetime(event_obj.zstop, event_obj.allday)
|
||||
event.add('summary').value = event_obj.name
|
||||
if event_obj.description:
|
||||
event.add('description').value = event_obj.description
|
||||
|
@ -198,7 +195,7 @@ class calendar_attendee(osv.Model):
|
|||
"""
|
||||
res = False
|
||||
|
||||
if self.pool['ir.config_parameter'].get_param(cr, uid, 'calendar.block_mail', default=False):
|
||||
if self.pool['ir.config_parameter'].get_param(cr, uid, 'calendar.block_mail', default=False) or context.get("no_mail_to_attendees"):
|
||||
return res
|
||||
|
||||
mail_ids = []
|
||||
|
@ -312,6 +309,10 @@ class res_partner(osv.Model):
|
|||
}
|
||||
|
||||
def get_attendee_detail(self, cr, uid, ids, meeting_id, context=None):
|
||||
"""
|
||||
Return a list of tuple (id, name, status)
|
||||
Used by web_calendar.js : Many2ManyAttendee
|
||||
"""
|
||||
datas = []
|
||||
meeting = False
|
||||
if meeting_id:
|
||||
|
@ -339,15 +340,15 @@ class calendar_alarm_manager(osv.AbstractModel):
|
|||
base_request = """
|
||||
SELECT
|
||||
cal.id,
|
||||
cal.date - interval '1' minute * calcul_delta.max_delta AS first_alarm,
|
||||
cal.zstart - interval '1' minute * calcul_delta.max_delta AS first_alarm,
|
||||
CASE
|
||||
WHEN cal.recurrency THEN cal.end_date - interval '1' minute * calcul_delta.min_delta
|
||||
ELSE cal.date_deadline - interval '1' minute * calcul_delta.min_delta
|
||||
WHEN cal.recurrency THEN cal.zfinal_date - interval '1' minute * calcul_delta.min_delta
|
||||
ELSE cal.zstop - interval '1' minute * calcul_delta.min_delta
|
||||
END as last_alarm,
|
||||
cal.date as first_event_date,
|
||||
cal.zstart as first_event_date,
|
||||
CASE
|
||||
WHEN cal.recurrency THEN cal.end_date
|
||||
ELSE cal.date_deadline
|
||||
WHEN cal.recurrency THEN cal.zfinal_date
|
||||
ELSE cal.zstop
|
||||
END as last_event_date,
|
||||
calcul_delta.min_delta,
|
||||
calcul_delta.max_delta,
|
||||
|
@ -380,7 +381,7 @@ class calendar_alarm_manager(osv.AbstractModel):
|
|||
|
||||
tuple_params = (type_to_read,)
|
||||
|
||||
#ADD FILTER ON PARTNER_ID
|
||||
# ADD FILTER ON PARTNER_ID
|
||||
if partner_id:
|
||||
base_request += filter_user
|
||||
tuple_params += (partner_id, )
|
||||
|
@ -389,7 +390,7 @@ class calendar_alarm_manager(osv.AbstractModel):
|
|||
tuple_params += (seconds, seconds,)
|
||||
|
||||
cr.execute("""SELECT *
|
||||
FROM ( %s ) AS ALL_EVENTS
|
||||
FROM ( %s WHERE cal.active = True ) AS ALL_EVENTS
|
||||
WHERE ALL_EVENTS.first_alarm < (now() at time zone 'utc' + interval '%%s' second )
|
||||
AND ALL_EVENTS.last_alarm > (now() at time zone 'utc' - interval '%%s' second )
|
||||
""" % base_request, tuple_params)
|
||||
|
@ -421,7 +422,7 @@ class calendar_alarm_manager(osv.AbstractModel):
|
|||
for alarm in event.alarm_ids:
|
||||
if alarm.type in alarm_type and \
|
||||
one_date - timedelta(minutes=alarm.duration_minutes) < datetime.now() + timedelta(seconds=in_the_next_X_seconds) and \
|
||||
(not after or one_date - timedelta(minutes=alarm.duration_minutes) > datetime.strptime(after.split('.')[0], "%Y-%m-%d %H:%M:%S")):
|
||||
(not after or one_date - timedelta(minutes=alarm.duration_minutes) > datetime.strptime(after.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT)):
|
||||
alert = {
|
||||
'alarm_id': alarm.id,
|
||||
'event_id': event.id,
|
||||
|
@ -471,7 +472,7 @@ class calendar_alarm_manager(osv.AbstractModel):
|
|||
if bFound and not LastFound: # if the precedent event had an alarm but not this one, we can stop the search for this event
|
||||
break
|
||||
else:
|
||||
in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S')
|
||||
in_date_format = datetime.strptime(curEvent.zstart, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, cron_interval, notif=False, context=context)
|
||||
if LastFound:
|
||||
for alert in LastFound:
|
||||
|
@ -504,7 +505,7 @@ class calendar_alarm_manager(osv.AbstractModel):
|
|||
if bFound and not LastFound: # if the precedent event had alarm but not this one, we can stop the search fot this event
|
||||
break
|
||||
else:
|
||||
in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S')
|
||||
in_date_format = datetime.strptime(curEvent.zstart, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, ajax_check_every_seconds, partner.calendar_last_notif_ack, mail=False, context=context)
|
||||
if LastFound:
|
||||
for alert in LastFound:
|
||||
|
@ -539,7 +540,7 @@ class calendar_alarm_manager(osv.AbstractModel):
|
|||
'title': event.name,
|
||||
'message': message,
|
||||
'timer': delta,
|
||||
'notify_at': alert['notify_at'].strftime("%Y-%m-%d %H:%M:%S"),
|
||||
'notify_at': alert['notify_at'].strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
}
|
||||
|
||||
|
||||
|
@ -561,7 +562,7 @@ class calendar_alarm(osv.Model):
|
|||
return res
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True), # fields function
|
||||
'name': fields.char('Name', required=True),
|
||||
'type': fields.selection([('notification', 'Notification'), ('email', 'Email')], 'Type', required=True),
|
||||
'duration': fields.integer('Amount', required=True),
|
||||
'interval': fields.selection([('minutes', 'Minutes'), ('hours', 'Hours'), ('days', 'Days')], 'Unit', required=True),
|
||||
|
@ -579,7 +580,6 @@ class ir_values(osv.Model):
|
|||
_inherit = 'ir.values'
|
||||
|
||||
def set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=False, preserve_user=False, company=False):
|
||||
|
||||
new_model = []
|
||||
for data in models:
|
||||
if type(data) in (list, tuple):
|
||||
|
@ -648,7 +648,7 @@ class calendar_event_type(osv.Model):
|
|||
class calendar_event(osv.Model):
|
||||
""" Model for Calendar Event """
|
||||
_name = 'calendar.event'
|
||||
_description = "Meeting"
|
||||
_description = "Event"
|
||||
_order = "id desc"
|
||||
_inherit = ["mail.thread", "ir.needaction_mixin"]
|
||||
|
||||
|
@ -658,7 +658,6 @@ class calendar_event(osv.Model):
|
|||
def get_recurrent_date_by_event(self, cr, uid, event, context=None):
|
||||
"""Get recurrent dates based on Rule string and all event where recurrent_id is child
|
||||
"""
|
||||
|
||||
def todate(date):
|
||||
val = parser.parse(''.join((re.compile('\d')).findall(date)))
|
||||
## Dates are localized to saved timezone if any, else current timezone.
|
||||
|
@ -666,8 +665,8 @@ class calendar_event(osv.Model):
|
|||
val = pytz.UTC.localize(val)
|
||||
return val.astimezone(timezone)
|
||||
|
||||
timezone = pytz.timezone(event.vtimezone or context.get('tz') or 'UTC')
|
||||
startdate = pytz.UTC.localize(datetime.strptime(event.date, "%Y-%m-%d %H:%M:%S")) # Add "+hh:mm" timezone
|
||||
timezone = pytz.timezone(context.get('tz') or 'UTC')
|
||||
startdate = pytz.UTC.localize(datetime.strptime(event.zstart, DEFAULT_SERVER_DATETIME_FORMAT)) # Add "+hh:mm" timezone
|
||||
if not startdate:
|
||||
startdate = datetime.now()
|
||||
|
||||
|
@ -677,20 +676,19 @@ class calendar_event(osv.Model):
|
|||
rset1 = rrule.rrulestr(str(event.rrule), dtstart=startdate, forceset=True)
|
||||
ids_depending = self.search(cr, uid, [('recurrent_id', '=', event.id), '|', ('active', '=', False), ('active', '=', True)], context=context)
|
||||
all_events = self.browse(cr, uid, ids_depending, context=context)
|
||||
|
||||
for ev in all_events:
|
||||
rset1._exdate.append(todate(ev.recurrent_id_date))
|
||||
|
||||
return [d.astimezone(pytz.UTC) for d in rset1]
|
||||
|
||||
def _get_recurrency_end_date(self, data, context=None):
|
||||
def _get_recurrency_end_date(self, cr, uid, id, context=None):
|
||||
data = self.read(cr, uid, id, ['zfinal_date', 'recurrency', 'rrule_type', 'count', 'end_type', 'zstop'], context=context)
|
||||
|
||||
if not data.get('recurrency'):
|
||||
return False
|
||||
|
||||
end_type = data.get('end_type')
|
||||
end_date = data.get('end_date')
|
||||
|
||||
if end_type == 'count' and all(data.get(key) for key in ['count', 'rrule_type', 'date_deadline']):
|
||||
final_date = data.get('zfinal_date')
|
||||
if end_type == 'count' and all(data.get(key) for key in ['count', 'rrule_type', 'zstop']):
|
||||
count = data['count'] + 1
|
||||
delay, mult = {
|
||||
'daily': ('days', 1),
|
||||
|
@ -699,9 +697,9 @@ class calendar_event(osv.Model):
|
|||
'yearly': ('years', 1),
|
||||
}[data['rrule_type']]
|
||||
|
||||
deadline = datetime.strptime(data['date_deadline'], tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
deadline = datetime.strptime(data['zstop'], tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
return deadline + relativedelta(**{delay: count * mult})
|
||||
return end_date
|
||||
return final_date
|
||||
|
||||
def _find_my_attendee(self, cr, uid, meeting_ids, context=None):
|
||||
"""
|
||||
|
@ -714,7 +712,7 @@ class calendar_event(osv.Model):
|
|||
return attendee
|
||||
return False
|
||||
|
||||
def _get_display_time(self, cr, uid, meeting_id, context=None):
|
||||
def _get_display_time(self, cr, uid, zstart, zstop, zduration, zallday, context=None):
|
||||
"""
|
||||
Return date and time (from to from) based on duration with timezone in string :
|
||||
eg.
|
||||
|
@ -728,15 +726,14 @@ class calendar_event(osv.Model):
|
|||
if not tz: # tz can have a value False, so dont do it in the default value of get !
|
||||
tz = pytz.timezone('UTC')
|
||||
|
||||
meeting = self.browse(cr, uid, meeting_id, context=context)
|
||||
date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(meeting.date, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context)
|
||||
date_deadline = fields.datetime.context_timestamp(cr, uid, datetime.strptime(meeting.date_deadline, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context)
|
||||
date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(zstart, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context)
|
||||
date_deadline = fields.datetime.context_timestamp(cr, uid, datetime.strptime(zstop, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context)
|
||||
event_date = date.strftime('%B-%d-%Y')
|
||||
display_time = date.strftime('%H-%M')
|
||||
if meeting.allday:
|
||||
if zallday:
|
||||
time = _("AllDay , %s") % (event_date)
|
||||
elif meeting.duration < 24:
|
||||
duration = date + timedelta(hours=meeting.duration)
|
||||
elif zduration < 24:
|
||||
duration = date + timedelta(hours=zduration)
|
||||
time = ("%s at (%s To %s) (%s)") % (event_date, display_time, duration.strftime('%H-%M'), tz)
|
||||
else:
|
||||
time = ("%s at %s To\n %s at %s (%s)") % (event_date, display_time, date_deadline.strftime('%B-%d-%Y'), date_deadline.strftime('%H-%M'), tz)
|
||||
|
@ -747,13 +744,21 @@ class calendar_event(osv.Model):
|
|||
for meeting_id in ids:
|
||||
res[meeting_id] = {}
|
||||
attendee = self._find_my_attendee(cr, uid, [meeting_id], context)
|
||||
meeting = self.browse(cr, uid, [meeting_id], context=context)[0]
|
||||
for field in fields:
|
||||
if field == 'is_attendee':
|
||||
res[meeting_id][field] = True if attendee else False
|
||||
elif field == 'attendee_status':
|
||||
res[meeting_id][field] = attendee.state if attendee else 'needsAction'
|
||||
elif field == 'display_time':
|
||||
res[meeting_id][field] = self._get_display_time(cr, uid, meeting_id, context=context)
|
||||
res[meeting_id][field] = self._get_display_time(cr, uid, meeting.zstart, meeting.zstop, meeting.duration, meeting.allday, context=context)
|
||||
elif field == "display_start":
|
||||
res[meeting_id][field] = meeting.zstart_date if meeting.allday else meeting.zstart_datetime
|
||||
elif field == 'zstart':
|
||||
res[meeting_id][field] = meeting.zstart_date if meeting.allday else meeting.zstart_datetime
|
||||
elif field == 'zstop':
|
||||
res[meeting_id][field] = meeting.zstop_date if meeting.allday else meeting.zstop_datetime
|
||||
|
||||
return res
|
||||
|
||||
def _get_rulestring(self, cr, uid, ids, name, arg, context=None):
|
||||
|
@ -774,7 +779,7 @@ class calendar_event(osv.Model):
|
|||
if data.count and data.count <= 0:
|
||||
raise osv.except_osv(_('Warning!'), _('Count cannot be negative or 0.'))
|
||||
|
||||
data = self.read(cr, uid, id, ['id', 'byday', 'recurrency', 'month_list', 'end_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list'], context=context)
|
||||
data = self.read(cr, uid, id, ['id', 'byday', 'recurrency', 'month_list', 'zfinal_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list'], context=context)
|
||||
event = data['id']
|
||||
if data['recurrency']:
|
||||
result[event] = self.compute_rule_string(data)
|
||||
|
@ -793,20 +798,53 @@ class calendar_event(osv.Model):
|
|||
if field_value:
|
||||
data['recurrency'] = True
|
||||
for event in self.browse(cr, uid, ids, context=context):
|
||||
rdate = event.date
|
||||
rdate = event.zstart
|
||||
update_data = self._parse_rrule(field_value, dict(data), rdate)
|
||||
data.update(update_data)
|
||||
self.write(cr, uid, ids, data, context=context)
|
||||
return True
|
||||
|
||||
def _tz_get(self, cr, uid, context=None):
|
||||
return [(x.lower(), x) for x in pytz.all_timezones]
|
||||
def _set_date(self, cr, uid, values, id=False, context=None):
|
||||
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
if values.get('zstart_datetime') or values.get('zstart_date') or values.get('zstart') \
|
||||
or values.get('zstop_datetime') or values.get('zstop_date') or values.get('zstop'):
|
||||
allday = values.get("allday", None)
|
||||
|
||||
if allday is None:
|
||||
if id:
|
||||
allday = self.read(cr, uid, [id], ['allday'], context=context)[0].get('allday')
|
||||
else:
|
||||
allday = False
|
||||
_logger.warning("Calendar - All day is not specified, arbitrarily set to False")
|
||||
#raise osv.except_osv(_('Error!'), ("Need to know if it's an allday or not..."))
|
||||
|
||||
key = "date" if allday else "datetime"
|
||||
notkey = "datetime" if allday else "date"
|
||||
|
||||
for fld in ('zstart', 'zstop'):
|
||||
if values.get('%s_%s' % (fld, key)) or values.get(fld):
|
||||
values['%s_%s' % (fld, key)] = values.get('%s_%s' % (fld, key)) or values.get(fld)
|
||||
values['%s_%s' % (fld, notkey)] = None
|
||||
if fld not in values.keys():
|
||||
values[fld] = values['%s_%s' % (fld, key)]
|
||||
|
||||
diff = False
|
||||
if allday and values.get('zstop_date') and values.get('zstart_date'):
|
||||
diff = datetime.strptime(values['zstop_date'].split(' ')[0], DEFAULT_SERVER_DATE_FORMAT) - datetime.strptime(values['zstart_date'].split(' ')[0], DEFAULT_SERVER_DATE_FORMAT)
|
||||
elif values.get('zstop_datetime') and values.get('zstart_datetime'):
|
||||
diff = datetime.strptime(values['zstop_datetime'].split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT) - datetime.strptime(values['zstart_datetime'].split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
if diff:
|
||||
duration = float(diff.days) * 24 + (float(diff.seconds) / 3600)
|
||||
values['duration'] = round(duration, 2)
|
||||
|
||||
_track = {
|
||||
'location': {
|
||||
'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True,
|
||||
},
|
||||
'date': {
|
||||
'zstart': {
|
||||
'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True,
|
||||
},
|
||||
}
|
||||
|
@ -817,19 +855,26 @@ class calendar_event(osv.Model):
|
|||
'is_attendee': fields.function(_compute, string='Attendee', type="boolean", multi='attendee'),
|
||||
'attendee_status': fields.function(_compute, string='Attendee Status', type="selection", selection=calendar_attendee.STATE_SELECTION, multi='attendee'),
|
||||
'display_time': fields.function(_compute, string='Event Time', type="char", multi='attendee'),
|
||||
'date': fields.datetime('Date', states={'done': [('readonly', True)]}, required=True, track_visibility='onchange'),
|
||||
'date_deadline': fields.datetime('End Date', states={'done': [('readonly', True)]}, required=True,),
|
||||
'display_start': fields.function(_compute, string='Date', type="char", multi='display_start', store=True),
|
||||
'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}),
|
||||
'zstart': fields.function(_compute, string='Calculated start', type="datetime", multi='zstart', store=True, required=True),
|
||||
'zstop': fields.function(_compute, string='Calculated stop', type="datetime", multi='zstop', store=True, required=True),
|
||||
'zstart_date': fields.date('Start Date', states={'done': [('readonly', True)]}, track_visibility='onchange'),
|
||||
'zstart_datetime': fields.datetime('Start DateTime', states={'done': [('readonly', True)]}, track_visibility='onchange'),
|
||||
'zstop_date': fields.date('End Date', states={'done': [('readonly', True)]}, track_visibility='onchange'),
|
||||
'zstop_datetime': fields.datetime('End Datetime', states={'done': [('readonly', True)]}, track_visibility='onchange'), # old date_deadline
|
||||
'duration': fields.float('Duration', states={'done': [('readonly', True)]}),
|
||||
'description': fields.text('Description', states={'done': [('readonly', True)]}),
|
||||
'class': fields.selection([('public', 'Public'), ('private', 'Private'), ('confidential', 'Public for Employees')], 'Privacy', states={'done': [('readonly', True)]}),
|
||||
'location': fields.char('Location', help="Location of Event", track_visibility='onchange', states={'done': [('readonly', True)]}),
|
||||
'show_as': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Show Time as', states={'done': [('readonly', True)]}),
|
||||
|
||||
# RECURRENCE FIELD
|
||||
'rrule': fields.function(_get_rulestring, type='char', fnct_inv=_set_rulestring, store=True, string='Recurrent Rule'),
|
||||
'rrule_type': fields.selection([('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)'), ('yearly', 'Year(s)')], 'Recurrency', states={'done': [('readonly', True)]}, help="Let the event automatically repeat at that interval"),
|
||||
'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"),
|
||||
'recurrent_id': fields.integer('Recurrent ID'),
|
||||
'recurrent_id_date': fields.datetime('Recurrent ID date'),
|
||||
'vtimezone': fields.selection(_tz_get, string='Timezone'),
|
||||
'end_type': fields.selection([('count', 'Number of repetitions'), ('end_date', 'End date')], 'Recurrence Termination'),
|
||||
'interval': fields.integer('Repeat Every', help="Repeat every (Days/Week/Month/Year)"),
|
||||
'count': fields.integer('Repeat', help="Repeat x times"),
|
||||
|
@ -844,21 +889,21 @@ class calendar_event(osv.Model):
|
|||
'day': fields.integer('Date of month'),
|
||||
'week_list': fields.selection([('MO', 'Monday'), ('TU', 'Tuesday'), ('WE', 'Wednesday'), ('TH', 'Thursday'), ('FR', 'Friday'), ('SA', 'Saturday'), ('SU', 'Sunday')], 'Weekday'),
|
||||
'byday': fields.selection([('1', 'First'), ('2', 'Second'), ('3', 'Third'), ('4', 'Fourth'), ('5', 'Fifth'), ('-1', 'Last')], 'By day'),
|
||||
'end_date': fields.date('Repeat Until'),
|
||||
'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}),
|
||||
'zfinal_date': fields.date('Repeat Until'), # The last event of a recurrence
|
||||
|
||||
'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}),
|
||||
'color_partner_id': fields.related('user_id', 'partner_id', 'id', type="integer", string="colorize", store=False), # Color of creator
|
||||
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the event alarm information without removing it."),
|
||||
'categ_ids': fields.many2many('calendar.event.type', 'meeting_category_rel', 'event_id', 'type_id', 'Tags'),
|
||||
'attendee_ids': fields.one2many('calendar.attendee', 'event_id', 'Attendees', ondelete='cascade'),
|
||||
'partner_ids': fields.many2many('res.partner', string='Attendees', states={'done': [('readonly', True)]}),
|
||||
'alarm_ids': fields.many2many('calendar.alarm', string='Reminders', ondelete="restrict"),
|
||||
|
||||
'partner_ids': fields.many2many('res.partner', 'calendar_event_res_partner_rel', string='Attendees', states={'done': [('readonly', True)]}),
|
||||
'alarm_ids': fields.many2many('calendar.alarm', 'calendar_alarm_calendar_event_rel', string='Reminders', ondelete="restrict"),
|
||||
}
|
||||
_defaults = {
|
||||
'end_type': 'count',
|
||||
'count': 1,
|
||||
'rrule_type': False,
|
||||
'allday': False,
|
||||
'state': 'draft',
|
||||
'class': 'public',
|
||||
'show_as': 'busy',
|
||||
|
@ -871,58 +916,86 @@ class calendar_event(osv.Model):
|
|||
|
||||
def _check_closing_date(self, cr, uid, ids, context=None):
|
||||
for event in self.browse(cr, uid, ids, context=context):
|
||||
if event.date_deadline < event.date:
|
||||
if event.zstop < event.zstart:
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_closing_date, 'Error ! End date cannot be set before start date.', ['date_deadline']),
|
||||
(_check_closing_date, 'Error ! End date cannot be set before start date.', ['zstart', 'zstop'])
|
||||
]
|
||||
|
||||
def onchange_dates(self, cr, uid, ids, start_date, duration=False, end_date=False, allday=False, context=None):
|
||||
|
||||
"""Returns duration and/or end date based on values passed
|
||||
@param ids: List of calendar event's IDs.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
def onchange_allday(self, cr, uid, ids, start=False, end=False, starttime=False, endtime=False, startdatetime=False, enddatetime=False, checkallday=False, context=None):
|
||||
|
||||
value = {}
|
||||
if not start_date:
|
||||
|
||||
if not ((starttime and endtime) or (start and end)): # At first intialize, we have not datetime
|
||||
return value
|
||||
|
||||
if not end_date and not duration:
|
||||
duration = 1.00
|
||||
value['duration'] = duration
|
||||
if checkallday: # from datetime to date
|
||||
startdatetime = startdatetime or start
|
||||
if startdatetime:
|
||||
start = datetime.strptime(startdatetime, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
value['zstart_date'] = datetime.strftime(start, DEFAULT_SERVER_DATE_FORMAT)
|
||||
|
||||
if allday: # For all day event
|
||||
start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
|
||||
user = self.pool['res.users'].browse(cr, uid, uid)
|
||||
enddatetime = enddatetime or end
|
||||
if enddatetime:
|
||||
end = datetime.strptime(enddatetime, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
value['zstop_date'] = datetime.strftime(end, DEFAULT_SERVER_DATE_FORMAT)
|
||||
else: # from date to datetime
|
||||
user = self.pool['res.users'].browse(cr, uid, uid, context)
|
||||
tz = pytz.timezone(user.tz) if user.tz else pytz.utc
|
||||
start = pytz.utc.localize(start).astimezone(tz) # convert start in user's timezone
|
||||
start = start.astimezone(pytz.utc) # convert start back to utc
|
||||
|
||||
value['duration'] = 24.0
|
||||
value['date'] = datetime.strftime(start, "%Y-%m-%d %H:%M:%S")
|
||||
if starttime:
|
||||
start = datetime.strptime(starttime.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT)
|
||||
startdate = tz.localize(start) # Add "+hh:mm" timezone
|
||||
startdate = startdate.replace(hour=8) # Set 8 AM in localtime
|
||||
startdate = startdate.astimezone(pytz.utc) # Convert to UTC
|
||||
value['zstart_datetime'] = datetime.strftime(startdate, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
elif start:
|
||||
value['zstart_datetime'] = start
|
||||
|
||||
if endtime:
|
||||
end = datetime.strptime(endtime.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT)
|
||||
enddate = tz.localize(end).replace(hour=18).astimezone(pytz.utc)
|
||||
|
||||
value['zstop_datetime'] = datetime.strftime(enddate, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
elif end:
|
||||
value['zstop_datetime'] = end
|
||||
|
||||
return {'value': value}
|
||||
|
||||
def onchange_dates(self, cr, uid, ids, fromtype, start=False, end=False, checkallday=False, allday=False, context=None):
|
||||
|
||||
"""Returns duration and end date based on values passed
|
||||
@param ids: List of calendar event's IDs.
|
||||
"""
|
||||
value = {}
|
||||
|
||||
if checkallday != allday:
|
||||
return value
|
||||
|
||||
value['allday'] = checkallday # Force to be rewrited
|
||||
|
||||
if allday:
|
||||
if fromtype == 'start':
|
||||
start = datetime.strptime(start, DEFAULT_SERVER_DATE_FORMAT)
|
||||
value['zstart_datetime'] = datetime.strftime(start, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
value['zstart'] = datetime.strftime(start, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
if fromtype == 'stop':
|
||||
end = datetime.strptime(end, DEFAULT_SERVER_DATE_FORMAT)
|
||||
value['zstop_datetime'] = datetime.strftime(end, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
value['zstop'] = datetime.strftime(end, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
else:
|
||||
start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
|
||||
|
||||
if end_date and not duration:
|
||||
end = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")
|
||||
diff = end - start
|
||||
duration = float(diff.days) * 24 + (float(diff.seconds) / 3600)
|
||||
value['duration'] = round(duration, 2)
|
||||
elif not end_date:
|
||||
end = start + timedelta(hours=duration)
|
||||
value['date_deadline'] = end.strftime("%Y-%m-%d %H:%M:%S")
|
||||
elif end_date and duration and not allday:
|
||||
# we have both, keep them synchronized:
|
||||
# set duration based on end_date (arbitrary decision: this avoid
|
||||
# getting dates like 06:31:48 instead of 06:32:00)
|
||||
end = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")
|
||||
diff = end - start
|
||||
duration = float(diff.days) * 24 + (float(diff.seconds) / 3600)
|
||||
value['duration'] = round(duration, 2)
|
||||
if fromtype == 'start':
|
||||
start = datetime.strptime(start, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
value['zstart_date'] = datetime.strftime(start, DEFAULT_SERVER_DATE_FORMAT)
|
||||
value['zstart'] = datetime.strftime(start, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
if fromtype == 'stop':
|
||||
end = datetime.strptime(end, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
value['zstop_date'] = datetime.strftime(end, DEFAULT_SERVER_DATE_FORMAT)
|
||||
value['zstop'] = datetime.strftime(end, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
return {'value': value}
|
||||
|
||||
|
@ -1009,7 +1082,6 @@ class calendar_event(osv.Model):
|
|||
|
||||
@param order: The fields (comma separated, format "FIELD {DESC|ASC}") on which the events should be sorted
|
||||
"""
|
||||
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
|
@ -1034,7 +1106,6 @@ class calendar_event(osv.Model):
|
|||
result.append(ev.id)
|
||||
result_data.append(self.get_search_fields(ev, order_fields))
|
||||
continue
|
||||
|
||||
rdates = self.get_recurrent_date_by_event(cr, uid, ev, context=context)
|
||||
|
||||
for r_date in rdates:
|
||||
|
@ -1045,7 +1116,7 @@ class calendar_event(osv.Model):
|
|||
pile = []
|
||||
ok = True
|
||||
for arg in domain:
|
||||
if str(arg[0]) in (str('date'), str('date_deadline'), str('end_date')):
|
||||
if str(arg[0]) in ('zstart', 'zstop', 'zfinal_date'):
|
||||
if (arg[1] == '='):
|
||||
ok = r_date.strftime('%Y-%m-%d') == arg[2]
|
||||
if (arg[1] == '>'):
|
||||
|
@ -1108,8 +1179,6 @@ class calendar_event(osv.Model):
|
|||
weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
|
||||
if freq == 'weekly':
|
||||
byday = map(lambda x: x.upper(), filter(lambda x: data.get(x) and x in weekdays, data))
|
||||
# byday = map(lambda x: x.upper(),[data[day] for day in weekdays if data[day]])
|
||||
|
||||
if byday:
|
||||
return ';BYDAY=' + ','.join(byday)
|
||||
return ''
|
||||
|
@ -1126,8 +1195,8 @@ class calendar_event(osv.Model):
|
|||
return ''
|
||||
|
||||
def get_end_date(data):
|
||||
if data.get('end_date'):
|
||||
data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('end_date'))) + 'T235959Z'
|
||||
if data.get('zfinal_date'):
|
||||
data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('zfinal_date'))) + 'T235959Z'
|
||||
|
||||
return (data.get('end_type') == 'count' and (';COUNT=' + str(data.get('count'))) or '') +\
|
||||
((data.get('end_date_new') and data.get('end_type') == 'end_date' and (';UNTIL=' + data.get('end_date_new'))) or '')
|
||||
|
@ -1144,7 +1213,7 @@ class calendar_event(osv.Model):
|
|||
return {
|
||||
'byday': False,
|
||||
'recurrency': False,
|
||||
'end_date': False,
|
||||
'zfinal_date': False,
|
||||
'rrule_type': False,
|
||||
'month_by': False,
|
||||
'interval': 0,
|
||||
|
@ -1164,14 +1233,13 @@ class calendar_event(osv.Model):
|
|||
def _parse_rrule(self, rule, data, date_start):
|
||||
day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
|
||||
rrule_type = ['yearly', 'monthly', 'weekly', 'daily']
|
||||
r = rrule.rrulestr(rule, dtstart=datetime.strptime(date_start, "%Y-%m-%d %H:%M:%S"))
|
||||
r = rrule.rrulestr(rule, dtstart=datetime.strptime(date_start, DEFAULT_SERVER_DATETIME_FORMAT))
|
||||
|
||||
if r._freq > 0 and r._freq < 4:
|
||||
data['rrule_type'] = rrule_type[r._freq]
|
||||
|
||||
data['count'] = r._count
|
||||
data['interval'] = r._interval
|
||||
data['end_date'] = r._until and r._until.strftime("%Y-%m-%d %H:%M:%S")
|
||||
data['zfinal_date'] = r._until and r._until.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
#repeat weekly
|
||||
if r._byweekday:
|
||||
for i in xrange(0, 7):
|
||||
|
@ -1197,12 +1265,12 @@ class calendar_event(osv.Model):
|
|||
#FIXEME handle forever case
|
||||
#end of recurrence
|
||||
#in case of repeat for ever that we do not support right now
|
||||
if not (data.get('count') or data.get('end_date')):
|
||||
if not (data.get('count') or data.get('zfinal_date')):
|
||||
data['count'] = 100
|
||||
if data.get('count'):
|
||||
data['end_type'] = 'count'
|
||||
else:
|
||||
data['end_type'] = 'end_date'
|
||||
data['end_type'] = 'zfinal_date'
|
||||
return data
|
||||
|
||||
def message_get_subscription_data(self, cr, uid, ids, user_pid=None, context=None):
|
||||
|
@ -1226,25 +1294,6 @@ class calendar_event(osv.Model):
|
|||
res.update(self.check_partners_email(cr, uid, value[0][2], context=context))
|
||||
return res
|
||||
|
||||
def onchange_rec_day(self, cr, uid, id, date, mo, tu, we, th, fr, sa, su):
|
||||
""" set the start date according to the first occurence of rrule"""
|
||||
rrule_obj = self._get_empty_rrule_data()
|
||||
rrule_obj.update({
|
||||
'byday': True,
|
||||
'rrule_type': 'weekly',
|
||||
'mo': mo,
|
||||
'tu': tu,
|
||||
'we': we,
|
||||
'th': th,
|
||||
'fr': fr,
|
||||
'sa': sa,
|
||||
'su': su,
|
||||
'interval': 1
|
||||
})
|
||||
str_rrule = self.compute_rule_string(rrule_obj)
|
||||
first_occurence = list(rrule.rrulestr(str_rrule + ";COUNT=1", dtstart=datetime.strptime(date, "%Y-%m-%d %H:%M:%S"), forceset=True))[0]
|
||||
return {'value': {'date': first_occurence.strftime("%Y-%m-%d") + ' 00:00:00'}}
|
||||
|
||||
def check_partners_email(self, cr, uid, partner_ids, context=None):
|
||||
""" Verify that selected partner_ids have an email_address defined.
|
||||
Otherwise throw a warning. """
|
||||
|
@ -1262,14 +1311,13 @@ class calendar_event(osv.Model):
|
|||
'message': warning_msg,
|
||||
}}
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter
|
||||
# ----------------------------------------
|
||||
|
||||
# shows events of the day for this user
|
||||
|
||||
def _needaction_domain_get(self, cr, uid, context=None):
|
||||
return [('end_date', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 23:59:59')), ('date', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 23:59:59')), ('user_id', '=', uid)]
|
||||
return [
|
||||
('zstop', '<=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 23:59:59')),
|
||||
('zstart', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 00:00:00')),
|
||||
('user_id', '=', uid),
|
||||
]
|
||||
|
||||
def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
|
||||
if isinstance(thread_id, str):
|
||||
|
@ -1326,15 +1374,15 @@ class calendar_event(osv.Model):
|
|||
|
||||
if context.get('mymeetings', False):
|
||||
partner_id = self.pool['res.users'].browse(cr, uid, uid, context).partner_id.id
|
||||
args += ['|', ('partner_ids', 'in', [partner_id]), ('user_id', '=', uid)]
|
||||
args += [('partner_ids', 'in', [partner_id])]
|
||||
|
||||
new_args = []
|
||||
for arg in args:
|
||||
new_arg = arg
|
||||
|
||||
if arg[0] in ('date', unicode('date')) and arg[1] == ">=":
|
||||
if arg[0] in ('zstart_date', 'zstart_datetime', 'zstart',) and arg[1] == ">=":
|
||||
if context.get('virtual_id', True):
|
||||
new_args += ['|', '&', ('recurrency', '=', 1), ('end_date', arg[1], arg[2])]
|
||||
new_args += ['|', '&', ('recurrency', '=', 1), ('zfinal_date', arg[1], arg[2])]
|
||||
elif arg[0] == "id":
|
||||
new_id = get_real_ids(arg[2])
|
||||
new_arg = (arg[0], arg[1], new_id)
|
||||
|
@ -1357,6 +1405,8 @@ class calendar_event(osv.Model):
|
|||
context = {}
|
||||
|
||||
default = default or {}
|
||||
|
||||
self._set_date(cr, uid, default, id=default.get('id'), context=context)
|
||||
default['attendee_ids'] = False
|
||||
|
||||
res = super(calendar_event, self).copy(cr, uid, calendar_id2real_id(id), default, context)
|
||||
|
@ -1364,17 +1414,18 @@ class calendar_event(osv.Model):
|
|||
|
||||
def _detach_one_event(self, cr, uid, id, values=dict(), context=None):
|
||||
real_event_id = calendar_id2real_id(id)
|
||||
data = self.read(cr, uid, id, ['date', 'date_deadline', 'rrule', 'duration'])
|
||||
|
||||
data = self.read(cr, uid, id, ['allday', 'zstart', 'zstop', 'rrule', 'duration'])
|
||||
data['zstart_date' if data['allday'] else 'zstart_datetime'] = data['zstart']
|
||||
data['zstop_date' if data['allday'] else 'zstop_datetime'] = data['zstop']
|
||||
if data.get('rrule'):
|
||||
data.update(
|
||||
values,
|
||||
recurrent_id=real_event_id,
|
||||
recurrent_id_date=data.get('date'),
|
||||
recurrent_id_date=data.get('zstart'),
|
||||
rrule_type=False,
|
||||
rrule='',
|
||||
recurrency=False,
|
||||
end_date=datetime.strptime(values.get('date', False) or data.get('date'), "%Y-%m-%d %H:%M:%S") + timedelta(hours=values.get('duration', False) or data.get('duration'))
|
||||
zfinal_date=datetime.strptime(values.get('zstart', False) or data.get('zstart'), DEFAULT_SERVER_DATETIME_FORMAT) + timedelta(hours=values.get('duration', False) or data.get('duration'))
|
||||
)
|
||||
|
||||
#do not copy the id
|
||||
|
@ -1397,21 +1448,34 @@ class calendar_event(osv.Model):
|
|||
'flags': {'form': {'action_buttons': True, 'options': {'mode': 'edit'}}}
|
||||
}
|
||||
|
||||
def _name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100, name_get_uid=None):
|
||||
for arg in args:
|
||||
if arg[0] == 'id':
|
||||
for n, calendar_id in enumerate(arg[2]):
|
||||
if isinstance(calendar_id, str):
|
||||
arg[2][n] = calendar_id.split('-')[0]
|
||||
return super(calendar_event, self)._name_search(cr, user, name=name, args=args, operator=operator, context=context, limit=limit, name_get_uid=name_get_uid)
|
||||
|
||||
def write(self, cr, uid, ids, values, context=None):
|
||||
def _only_changes_to_apply_on_real_ids(field_names):
|
||||
''' return True if changes are only to be made on the real ids'''
|
||||
for field in field_names:
|
||||
if field in ['date', 'active']:
|
||||
if field in ['zstart', 'zstart_date', 'zstart_datetime', 'zstop', 'zstop_date', 'zstop_datetime', 'active']:
|
||||
return True
|
||||
return False
|
||||
|
||||
context = context or {}
|
||||
if not isinstance(ids, (tuple, list)):
|
||||
ids = [ids]
|
||||
|
||||
if isinstance(ids, (str, int, long)):
|
||||
if len(str(ids).split('-')) == 1:
|
||||
ids = [int(ids)]
|
||||
else:
|
||||
ids = [ids]
|
||||
context = context or {}
|
||||
self._set_date(cr, uid, values, id=ids[0], context=context)
|
||||
|
||||
for one_ids in ids:
|
||||
if isinstance(one_ids, (str, int, long)):
|
||||
if len(str(one_ids).split('-')) == 1:
|
||||
ids = [int(one_ids)]
|
||||
else:
|
||||
ids = [one_ids]
|
||||
|
||||
res = False
|
||||
new_id = False
|
||||
|
@ -1431,7 +1495,7 @@ class calendar_event(osv.Model):
|
|||
ids.append(real_event_id)
|
||||
continue
|
||||
else:
|
||||
data = self.read(cr, uid, event_id, ['date', 'date_deadline', 'rrule', 'duration'])
|
||||
data = self.read(cr, uid, event_id, ['zstart', 'zstop', 'rrule', 'duration'])
|
||||
if data.get('rrule'):
|
||||
new_id = self._detach_one_event(cr, uid, event_id, values, context=None)
|
||||
|
||||
|
@ -1439,16 +1503,16 @@ class calendar_event(osv.Model):
|
|||
|
||||
# set end_date for calendar searching
|
||||
if values.get('recurrency', True) and values.get('end_type', 'count') in ('count', unicode('count')) and \
|
||||
(values.get('rrule_type') or values.get('count') or values.get('date') or values.get('date_deadline')):
|
||||
for data in self.read(cr, uid, ids, ['end_date', 'date_deadline', 'recurrency', 'rrule_type', 'count', 'end_type'], context=context):
|
||||
end_date = self._get_recurrency_end_date(data, context=context)
|
||||
super(calendar_event, self).write(cr, uid, [data['id']], {'end_date': end_date}, context=context)
|
||||
(values.get('rrule_type') or values.get('count') or values.get('zstart') or values.get('zstop')):
|
||||
for id in ids:
|
||||
final_date = self._get_recurrency_end_date(cr, uid, id, context=context)
|
||||
super(calendar_event, self).write(cr, uid, [id], {'zfinal_date': final_date}, context=context)
|
||||
|
||||
attendees_create = False
|
||||
if values.get('partner_ids', False):
|
||||
attendees_create = self.create_attendees(cr, uid, ids, context)
|
||||
|
||||
if values.get('date', False) and values.get('active', True):
|
||||
if (values.get('zstart_date') or values.get('zstart_datetime', False)) and values.get('active', True):
|
||||
the_id = new_id or (ids and int(ids[0]))
|
||||
|
||||
if attendees_create:
|
||||
|
@ -1461,21 +1525,20 @@ class calendar_event(osv.Model):
|
|||
current_user = self.pool['res.users'].browse(cr, uid, uid, context=context)
|
||||
if self.pool['calendar.attendee']._send_mail_to_attendees(cr, uid, mail_to_ids, template_xmlid='calendar_template_meeting_changedate', email_from=current_user.email, context=context):
|
||||
self.message_post(cr, uid, the_id, body=_("A email has been send to specify that the date has been changed !"), subtype="calendar.subtype_invitation", context=context)
|
||||
|
||||
return res or True and False
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
self._set_date(cr, uid, vals, id=False, context=context)
|
||||
if not 'user_id' in vals: # Else bug with quick_create when we are filter on an other user
|
||||
vals['user_id'] = uid
|
||||
|
||||
res = super(calendar_event, self).create(cr, uid, vals, context=context)
|
||||
|
||||
data = self.read(cr, uid, [res], ['end_date', 'date_deadline', 'recurrency', 'rrule_type', 'count', 'end_type'], context=context)[0]
|
||||
end_date = self._get_recurrency_end_date(data, context=context)
|
||||
self.write(cr, uid, [res], {'end_date': end_date}, context=context)
|
||||
final_date = self._get_recurrency_end_date(cr, uid, res, context=context)
|
||||
self.write(cr, uid, [res], {'zfinal_date': final_date}, context=context)
|
||||
|
||||
self.create_attendees(cr, uid, [res], context=context)
|
||||
return res
|
||||
|
@ -1501,28 +1564,35 @@ class calendar_event(osv.Model):
|
|||
if context is None:
|
||||
context = {}
|
||||
fields2 = fields and fields[:] or None
|
||||
EXTRAFIELDS = ('class', 'user_id', 'duration', 'date', 'rrule', 'vtimezone')
|
||||
EXTRAFIELDS = ('class', 'user_id', 'duration', 'allday', 'zstart', 'zstart_date', 'zstart_datetime', 'rrule')
|
||||
for f in EXTRAFIELDS:
|
||||
if fields and (f not in fields):
|
||||
fields2.append(f)
|
||||
|
||||
if isinstance(ids, (str, int, long)):
|
||||
select = [ids]
|
||||
else:
|
||||
select = ids
|
||||
|
||||
select = map(lambda x: (x, calendar_id2real_id(x)), select)
|
||||
result = []
|
||||
|
||||
real_data = super(calendar_event, self).read(cr, uid, [real_id for calendar_id, real_id in select], fields=fields2, context=context, load=load)
|
||||
real_data = dict(zip([x['id'] for x in real_data], real_data))
|
||||
|
||||
for calendar_id, real_id in select:
|
||||
res = real_data[real_id].copy()
|
||||
ls = calendar_id2real_id(calendar_id, with_date=res and res.get('duration', 0) or 0)
|
||||
ls = calendar_id2real_id(calendar_id, with_date=res and res.get('duration', 0) > 0 and res.get('duration') or 1)
|
||||
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
|
||||
res['date'] = ls[1]
|
||||
res['date_deadline'] = ls[2]
|
||||
res['zstart'] = ls[1]
|
||||
res['zstop'] = ls[2]
|
||||
|
||||
if res['allday']:
|
||||
res['zstart_date'] = ls[1]
|
||||
res['zstop_date'] = ls[2]
|
||||
else:
|
||||
res['zstart_datetime'] = ls[1]
|
||||
res['zstop_datetime'] = ls[2]
|
||||
|
||||
res['display_time'] = self._get_display_time(cr, uid, ls[1], ls[2], res['duration'], res['allday'], context=context)
|
||||
|
||||
res['id'] = calendar_id
|
||||
result.append(res)
|
||||
|
||||
|
@ -1533,7 +1603,7 @@ class calendar_event(osv.Model):
|
|||
continue
|
||||
if r['class'] == 'private':
|
||||
for f in r.keys():
|
||||
if f not in ('id', 'date', 'date_deadline', 'duration', 'user_id', 'state', 'interval', 'count', 'recurrent_id_date'):
|
||||
if f not in ('id', 'allday', 'zstart', 'zstop', 'duration', 'user_id', 'state', 'interval', 'count', 'recurrent_id_date'):
|
||||
if isinstance(r[f], list):
|
||||
r[f] = []
|
||||
else:
|
||||
|
@ -1545,12 +1615,11 @@ class calendar_event(osv.Model):
|
|||
for k in EXTRAFIELDS:
|
||||
if (k in r) and (fields and (k not in fields)):
|
||||
del r[k]
|
||||
|
||||
if isinstance(ids, (str, int, long)):
|
||||
return result and result[0] or False
|
||||
return result
|
||||
|
||||
def unlink(self, cr, uid, ids, unlink_level=0, context=None):
|
||||
def unlink(self, cr, uid, ids, can_be_deleted=True, context=None):
|
||||
if not isinstance(ids, list):
|
||||
ids = [ids]
|
||||
res = False
|
||||
|
@ -1558,9 +1627,8 @@ class calendar_event(osv.Model):
|
|||
ids_to_exclure = []
|
||||
ids_to_unlink = []
|
||||
|
||||
# One time moved to google_Calendar, we can specify, if not in google, and not rec or get_inst = 0, we delete it
|
||||
for event_id in ids:
|
||||
if unlink_level == 1 and len(str(event_id).split('-')) == 1: # if ID REAL
|
||||
if can_be_deleted and len(str(event_id).split('-')) == 1: # if ID REAL
|
||||
if self.browse(cr, uid, event_id).recurrent_id:
|
||||
ids_to_exclure.append(event_id)
|
||||
else:
|
||||
|
|
|
@ -142,12 +142,12 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.date, 'dayname')}</div>
|
||||
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.zstart, 'dayname')}</div>
|
||||
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
|
||||
${object.event_id.get_interval(object.event_id.date,'day')}
|
||||
${object.event_id.get_interval(object.event_id.zstart,'day')}
|
||||
</div>
|
||||
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.date, 'month')}</div>
|
||||
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}</div>
|
||||
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.zstart, 'month')}</div>
|
||||
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.zstart, 'time', tz=object.partner_id.tz) or ''}</div>
|
||||
</td>
|
||||
<td>
|
||||
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
|
||||
|
@ -275,12 +275,12 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.date, 'dayname')}</div>
|
||||
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.zstart, 'dayname')}</div>
|
||||
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
|
||||
${object.event_id.get_interval(object.event_id.date,'day')}
|
||||
${object.event_id.get_interval(object.event_id.zstart,'day')}
|
||||
</div>
|
||||
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.date, 'month')}</div>
|
||||
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}</div>
|
||||
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.zstart, 'month')}</div>
|
||||
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.zstart, 'time', tz=object.partner_id.tz) or ''}</div>
|
||||
</td>
|
||||
<td>
|
||||
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
|
||||
|
@ -407,12 +407,12 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.date, 'dayname')}</div>
|
||||
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.event_id.get_interval(object.event_id.zstart, 'dayname')}</div>
|
||||
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
|
||||
${object.event_id.get_interval(object.event_id.date,'day')}
|
||||
${object.event_id.get_interval(object.event_id.zstart,'day')}
|
||||
</div>
|
||||
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.date, 'month')}</div>
|
||||
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}</div>
|
||||
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.event_id.get_interval(object.event_id.zstart, 'month')}</div>
|
||||
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${not object.event_id.allday and object.event_id.get_interval(object.event_id.zstart, 'time', tz=object.partner_id.tz) or ''}</div>
|
||||
</td>
|
||||
<td>
|
||||
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
|
||||
|
|
|
@ -23,22 +23,24 @@
|
|||
<field name="partner_ids" eval="[(6,0,[ref('base.res_partner_6')])]"/>
|
||||
<field name="name">Follow-up for Project proposal</field>
|
||||
<field name="description">Meeting to discuss project plan and hash out the details of implementation.</field>
|
||||
<field eval="time.strftime('%Y-%m-03 10:20:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-03 10:20:00')" name="zstart"/>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-03 16:30:00')" name="date_deadline"/>
|
||||
<field eval="time.strftime('%Y-%m-03 16:30:00')" name="zstop"/>
|
||||
<field eval="6.3" name="duration"/>
|
||||
<field eval="0" name="allday"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
|
||||
<record id="calendar_event_2" model="calendar.event">
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_4'),ref('base.res_partner_5')])]"/>
|
||||
<field name="name">Initial discussion</field>
|
||||
<field name="description">Discussion with partner for product.</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet3')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-05 12:00:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-05 19:00:00')" name="date_deadline"/>
|
||||
<field eval="time.strftime('%Y-%m-05 12:00:00')" name="zstart"/>
|
||||
<field eval="time.strftime('%Y-%m-05 19:00:00')" name="zstop"/>
|
||||
<field eval="0" name="allday"/>
|
||||
<field eval="7.0" name="duration"/>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
|
@ -49,9 +51,10 @@
|
|||
<field name="name">Pricing Discussion</field>
|
||||
<field name="description">Internal meeting for discussion for new pricing for product and services.</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-12 15:55:05')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-12 18:55:05')" name="date_deadline"/>
|
||||
<field eval="time.strftime('%Y-%m-12 15:55:05')" name="zstart"/>
|
||||
<field eval="time.strftime('%Y-%m-12 18:55:05')" name="zstop"/>
|
||||
<field eval="3.0" name="duration"/>
|
||||
<field eval="0" name="allday"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
|
||||
|
@ -61,9 +64,10 @@
|
|||
<field name="partner_ids" eval="[(6,0,[ref('base.partner_demo'),ref('base.res_partner_6')])]"/>
|
||||
<field name="name">Requirements review</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet3')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-20 8:00:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-20 10:30:00')" name="date_deadline"/>
|
||||
<field eval="time.strftime('%Y-%m-20 8:00:00')" name="zstart"/>
|
||||
<field eval="time.strftime('%Y-%m-20 10:30:00')" name="zstop"/>
|
||||
<field eval="2.5" name="duration"/>
|
||||
<field eval="0" name="allday"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
|
||||
|
@ -72,9 +76,9 @@
|
|||
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_8')])]"/>
|
||||
<field name="name">Changes in Designing</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-22 11:05:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-22 16:05:00')" name="date_deadline"/>
|
||||
<field eval="5" name="duration"/>
|
||||
<field eval="time.strftime('%Y-%m-22')" name="zstart"/>
|
||||
<field eval="time.strftime('%Y-%m-22')" name="zstop"/>
|
||||
<field eval="1" name="allday"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
|
||||
|
@ -84,9 +88,10 @@
|
|||
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_1'),ref('base.res_partner_4'),ref('base.res_partner_6'),ref('base.res_partner_8')])]"/>
|
||||
<field name="name">Presentation for new Services</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-18 2:00:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-18 10:30:00')" name="date_deadline"/>
|
||||
<field eval="time.strftime('%Y-%m-18 2:00:00')" name="zstart"/>
|
||||
<field eval="time.strftime('%Y-%m-18 10:30:00')" name="zstop"/>
|
||||
<field eval="8.5" name="duration"/>
|
||||
<field eval="0" name="allday"/>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
|
||||
|
@ -96,9 +101,10 @@
|
|||
<field name="partner_ids" eval="[(6,0,[ref('base.res_partner_7')])]"/>
|
||||
<field name="name">Presentation of the new Calendar</field>
|
||||
<field name="categ_ids" eval="[(6,0,[ref('categ_meet1'), ref('categ_meet2')])]"/>
|
||||
<field eval="time.strftime('%Y-%m-16 6:00:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-16 18:30:00')" name="date_deadline"/>
|
||||
<field eval="time.strftime('%Y-%m-16')" name="zstart"/>
|
||||
<field eval="time.strftime('%Y-%m-16')" name="zstop"/>
|
||||
<field eval="8.5" name="duration"/>
|
||||
<field eval="1" name="allday"/>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<field name="name">Meeting Types Tree</field>
|
||||
<field name="model">calendar.event.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Meeting Types">
|
||||
<tree string="Meeting Types" editable="bottom">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
@ -58,24 +58,24 @@
|
|||
</group>
|
||||
<group>
|
||||
<group>
|
||||
<field name="date" string="Starting at" on_change="onchange_dates(date, duration, False, allday)"/>
|
||||
<label for="duration"/>
|
||||
<field name="zstart" attrs="{'invisible': True}"/>
|
||||
<field name="zstop" attrs="{'invisible': True}"/>
|
||||
|
||||
<field name="zstart_date" string="Starting at" on_change="onchange_dates('start', zstart_date, zstop_date, allday, True)" attrs="{'invisible': [('allday','=',False)]}"/>
|
||||
<field name="zstop_date" string="Ending at" on_change="onchange_dates('stop', zstart_date, zstop_date, allday, True)" attrs="{'invisible': [('allday','=',False)]}"/>
|
||||
|
||||
<field name="zstart_datetime" string="Starting at" on_change="onchange_dates('start', zstart_datetime, zstop_datetime, allday, False)" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
<field name="zstop_datetime" string="Ending at" on_change="onchange_dates('stop', zstart_datetime, zstop_datetime, allday, False)" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
<label for="allday"/>
|
||||
<div>
|
||||
<field name="duration" widget="float_time"
|
||||
on_change="onchange_dates(date, duration, False, allday)"
|
||||
class="oe_inline" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
<label string="hours" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
(<field name="allday" class="oe_inline"/>
|
||||
<label for="allday" string="All Day?"/>)
|
||||
<field name="allday" class="oe_inline" on_change="onchange_allday(zstart, zstop, zstart_date, zstop_date, zstart_datetime, zstop_datetime, allday)"/>
|
||||
</div>
|
||||
<field name="date_deadline" groups="base.group_no_one"
|
||||
attrs="{'invisible': ['|', ('allday','=',True), ('duration','<', 24)]}"
|
||||
/>
|
||||
<field name="duration" widget="float_time" class="oe_inline" attrs="{ 'invisible': True }"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="categ_ids" widget="many2many_tags"/>
|
||||
<field name="categ_ids" widget="many2many_tags" />
|
||||
<field name="alarm_ids" widget="many2many_tags" />
|
||||
<field name="location"/>
|
||||
<field name="location" />
|
||||
</group>
|
||||
|
||||
</group>
|
||||
|
@ -98,17 +98,17 @@
|
|||
<div>
|
||||
<field name="end_type" attrs="{'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
<field name="count" attrs="{'invisible': [('end_type', '!=', 'count')], 'required': [('recurrency','==',True)]}" class="oe_inline"/>
|
||||
<field name="end_date" attrs="{'invisible': [('end_type', '!=', 'end_date')], 'required': [('end_type', '=', 'end_date')]}" class="oe_inline"/>
|
||||
<field name="zfinal_date" attrs="{'invisible': [('end_type', '!=', 'end_date')], 'required': [('end_type', '=', 'end_date')]}" class="oe_inline"/>
|
||||
</div>
|
||||
<label string="Select Weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}"/>
|
||||
<group col="2" colspan="1" name="weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}" >
|
||||
<field name="mo" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="tu" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="we" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="th" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="fr" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="sa" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="su" on_change="onchange_rec_day(date,mo,tu,we,th,fr,sa,su)"/>
|
||||
<field name="mo" />
|
||||
<field name="tu" />
|
||||
<field name="we" />
|
||||
<field name="th" />
|
||||
<field name="fr" />
|
||||
<field name="sa" />
|
||||
<field name="su" />
|
||||
</group>
|
||||
|
||||
<label string="Day of Month"
|
||||
|
@ -178,7 +178,9 @@
|
|||
<field name="name"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="date" string="Start" />
|
||||
<field name="zstart_date" string="Starting at" attrs="{'invisible': [('allday','=',False)]}"/>
|
||||
<field name="zstart_datetime" string="Starting at" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
|
||||
<field name="duration" string="Duration" widget="float_time" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
<field name="allday" class="oe_inline" attrs="{'invisible': [('allday','=',False)]}"/>
|
||||
<field name="partner_ids" widget="many2manyattendee" string="Attendees"/>
|
||||
|
@ -201,7 +203,8 @@
|
|||
<field name="arch" type="xml">
|
||||
<tree string="Meetings" fonts="bold:message_unread==True">
|
||||
<field name="name" string="Subject"/>
|
||||
<field name="date" string="Event Date"/>
|
||||
<field name="allday" invisible="True"/>
|
||||
<field name="display_start" string="Date" />
|
||||
<field name="user_id"/>
|
||||
<field name="location"/>
|
||||
<field name="show_as"/>
|
||||
|
@ -219,7 +222,7 @@
|
|||
<field name="model">calendar.event</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Meetings" date_start="date" date_stop="date_deadline" date_delay="duration" all_day="allday"
|
||||
<calendar string="Meetings" date_start="zstart" date_stop="zstop" date_delay="duration" all_day="allday"
|
||||
display="[name]" color="color_partner_id" attendee="partner_ids" avatar_model="res.partner"
|
||||
use_contacts="True" event_open_popup="%(calendar.view_calendar_event_form_popup)s">
|
||||
|
||||
|
@ -260,8 +263,7 @@
|
|||
<group expand="0" string="Group By...">
|
||||
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Availability" icon="terp-camera_test" domain="[]" context="{'group_by':'show_as'}"/>
|
||||
<filter string="Privacy" icon="terp-locked" domain="[]" context="{'group_by':'class'}"/>
|
||||
<filter string="Event Month" icon="terp-go-month" domain="[]" context="{'group_by':'date'}" help="Start Date of Event by Month"/>
|
||||
<filter string="Privacy" icon="terp-locked" domain="[]" context="{'group_by':'class'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</t>
|
||||
</t>
|
||||
<t t-name='notify_title'>
|
||||
<span t-attf-class="'link2event eid_' + id" class='link2event eid_" + res.event_id + "'>
|
||||
<span t-attf-class="link2event eid_#{id}">
|
||||
<t t-esc="title"/>
|
||||
</span>
|
||||
</t>
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
-
|
||||
!record {model: calendar.event, id: calendar_event_technicalpresentation0}:
|
||||
class: private
|
||||
date: '2011-04-30 16:00:00'
|
||||
date_deadline: '2011-04-30 18:30:00'
|
||||
zstart: '2011-04-30 16:00:00'
|
||||
zstop: '2011-04-30 18:30:00'
|
||||
description: The Technical Presentation will cover following topics:\n* Creating OpenERP
|
||||
class\n* Views\n* Wizards\n* Workflows
|
||||
duration: 2.5
|
||||
|
@ -14,7 +14,7 @@
|
|||
Now I will set recurrence for this event to occur monday and friday of week
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
data = {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly', 'end_type': 'end_date', 'end_date': '2011-05-31 00:00:00', 'recurrency' : True}
|
||||
data = {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly', 'end_type': 'end_date', 'zfinal_date': '2011-05-31 00:00:00', 'recurrency' : True}
|
||||
self.write(cr, uid, [ref("calendar_event_technicalpresentation0")], data)
|
||||
-
|
||||
In order to check that recurrent events are views successfully in calendar view, I will open calendar view of events
|
||||
|
@ -25,18 +25,18 @@
|
|||
In order to check that recurrent events are views successfully in calendar view, I will search for one of the recurrent event and count the number of events
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
ids = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
|
||||
ids = self.search(cr, uid, [('zstart', '>=', '2011-04-30 16:00:00'), ('zstart', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
|
||||
assert len(ids) == 9, 'Wrong number of events found'
|
||||
-
|
||||
Now I move a virtual event, to see that a real event is well created and depending from the native recurrence
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
ids = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
|
||||
before = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
|
||||
ids = self.search(cr, uid, [('zstart', '>=', '2011-04-30 16:00:00'), ('zstart', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
|
||||
before = self.search(cr, uid, [('zstart', '>=', '2011-04-30 16:00:00'), ('zstart', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
|
||||
# We start by detach the event
|
||||
newid = self._detach_one_event(cr, uid,ids[1])
|
||||
self.write(cr, uid,[newid], {'name':'New Name','recurrency' : True}, context={'virtual_id': True})
|
||||
after = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
|
||||
after = self.search(cr, uid, [('zstart', '>=', '2011-04-30 16:00:00'), ('zstart', '<=', '2011-05-31 00:00:00')], context={'virtual_id': False})
|
||||
assert len(after) == len(before)+1, 'Wrong number of events found, after to have moved a virtual event'
|
||||
new_id = list(set(after)-set(before))[0]
|
||||
new_event = self.browse(cr,uid,new_id,context=context)
|
||||
|
@ -47,8 +47,8 @@
|
|||
!record {model: calendar.event, id: calendar_event_alldaytestevent0}:
|
||||
allday: 1
|
||||
class: confidential
|
||||
date: '2011-04-30 00:00:00'
|
||||
date_deadline: '2011-04-30 00:00:00'
|
||||
zstart: '2011-04-30 00:00:00'
|
||||
zstop: '2011-04-30 00:00:00'
|
||||
description: 'All day technical test '
|
||||
location: School
|
||||
name: All day test event
|
||||
|
@ -70,7 +70,8 @@
|
|||
-
|
||||
!record {model: calendar.event, id: calendar.event_sprintreview1}:
|
||||
name: Begin of month meeting
|
||||
date: !eval time.strftime('%Y-%m-%d 12:00:00')
|
||||
zstart: !eval time.strftime('%Y-%m-%d 12:00:00')
|
||||
zstop: !eval time.strftime('%Y-%m-%d 18:00:00')
|
||||
recurrency: true
|
||||
rrule: FREQ=MONTHLY;INTERVAL=1;COUNT=12;BYDAY=1MO
|
||||
-
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
-
|
||||
!record {model: calendar.event, id: calendar_event_testmeeting0}:
|
||||
count: 5
|
||||
date: '2011-04-13 11:04:00'
|
||||
date_deadline: '2011-04-13 12:04:00'
|
||||
zstart: '2011-04-13 11:04:00'
|
||||
zstop: '2011-04-13 12:04:00'
|
||||
day: 0.0
|
||||
duration: 1.0
|
||||
name: Test Meeting
|
||||
|
@ -17,17 +17,17 @@
|
|||
I search for all the recurrent meetings.
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_testmeeting0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
|
||||
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_testmeeting0')]),('zstart','>=','2011-03-13'), ('zstop', '<=', '2011-05-13')], context={'virtual_id': True})
|
||||
assert len(meeting_ids) == 5, 'Recurrent daily meetings are not created !'
|
||||
-
|
||||
I create a weekly meeting till a particular end date.
|
||||
-
|
||||
!record {model: calendar.event, id: calendar_event_reviewcodewithprogrammer0}:
|
||||
date: '2011-04-18 11:47:00'
|
||||
date_deadline: '2011-04-18 12:47:00'
|
||||
zstart: '2011-04-18 11:47:00'
|
||||
zstop: '2011-04-18 12:47:00'
|
||||
day: 0.0
|
||||
duration: 1.0
|
||||
end_date: '2011-04-30'
|
||||
zfinal_date: '2011-04-30'
|
||||
end_type: end_date
|
||||
fr: true
|
||||
mo: true
|
||||
|
@ -36,21 +36,21 @@
|
|||
we: true
|
||||
name: Review code with programmer
|
||||
recurrency: true
|
||||
recurrent_id: 0.0
|
||||
recurrent_id: 0
|
||||
rrule_type: weekly
|
||||
-
|
||||
I search for all the recurrent weekly meetings.
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_reviewcodewithprogrammer0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
|
||||
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_reviewcodewithprogrammer0')]),('zstart','>=','2011-03-13'), ('zstop', '<=', '2011-05-13')], context={'virtual_id': True})
|
||||
assert len(meeting_ids) == 10, 'Recurrent weekly meetings are not created !'
|
||||
-
|
||||
I want to schedule a meeting every month for Sprint review.
|
||||
-
|
||||
!record {model: calendar.event, id: calendar_event_sprintreview0}:
|
||||
count: 12
|
||||
date: '2011-04-01 12:01:00'
|
||||
date_deadline: '2011-04-01 13:01:00'
|
||||
zstart: '2011-04-01 12:01:00'
|
||||
zstop: '2011-04-01 13:01:00'
|
||||
day: 1
|
||||
duration: 1.0
|
||||
name: Sprint Review
|
||||
|
@ -61,7 +61,7 @@
|
|||
I search for all the recurrent monthly meetings.
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
|
||||
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('zstart','>=','2011-03-01'), ('zstop', '<=', '2012-05-13')], context={'virtual_id': True})
|
||||
assert len(meeting_ids) == 12, 'Recurrent monthly meetings are not created !'
|
||||
-
|
||||
I change name of my monthly Sprint Review meeting.
|
||||
|
@ -73,7 +73,7 @@
|
|||
I check whether all the records are edited or not.
|
||||
-
|
||||
!python {model: calendar.event}: |
|
||||
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
|
||||
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('calendar_event_sprintreview0')]),('zstart','>=','2011-03-01'), ('zstop', '<=', '2012-05-13')], context={'virtual_id': True})
|
||||
meetings = self.browse(cr, uid, meeting_ids, context)
|
||||
for meeting in meetings:
|
||||
assert meeting.name == 'Sprint Review for google modules', 'Name not changed for id: %s' %meeting.id
|
||||
|
|
|
@ -36,21 +36,7 @@ class calendar_event(osv.Model):
|
|||
res = super(calendar_event, self).create(cr, uid, vals, context=context)
|
||||
obj = self.browse(cr, uid, res, context=context)
|
||||
if obj.opportunity_id:
|
||||
self.pool.get('crm.lead').log_meeting(cr, uid, [obj.opportunity_id.id], obj.name, obj.date, obj.duration, context=context)
|
||||
self.pool.get('crm.lead').log_meeting(cr, uid, [obj.opportunity_id.id], obj.name, obj.zstart, obj.duration, context=context)
|
||||
return res
|
||||
|
||||
|
||||
class calendar_attendee(osv.osv):
|
||||
""" Calendar Attendee """
|
||||
|
||||
_inherit = 'calendar.attendee'
|
||||
_description = 'Calendar Attendee'
|
||||
|
||||
def _noop(self, cr, uid, ids, name, arg, context=None):
|
||||
return dict.fromkeys(ids, False)
|
||||
|
||||
_columns = {
|
||||
'categ_id': fields.function(_noop, string='Event Type', deprecated="Unused Field - TODO : Remove it in trunk", type="many2one", relation="crm.case.categ"),
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -22,8 +22,6 @@ access_crm_phonecall_report_user,crm.phonecall.report.user,model_crm_phonecall_r
|
|||
access_crm_phonecall_report_manager,crm.phonecall.report,model_crm_phonecall_report,base.group_sale_manager,1,1,1,1
|
||||
access_res_partner_manager,res.partner.crm.manager,base.model_res_partner,base.group_sale_manager,1,0,0,0
|
||||
access_res_partner_category_manager,res.partner.category.crm.manager,base.model_res_partner_category,base.group_sale_manager,1,0,0,0
|
||||
access_calendar_attendee_crm_user,calendar.attendee.crm.user,model_calendar_attendee,base.group_sale_salesman,1,1,1,0
|
||||
access_calendar_attendee_crm_manager,calendar.attendee.crm.manager,model_calendar_attendee,base.group_sale_manager,1,1,1,1
|
||||
access_res_partner,res.partner.crm.user,base.model_res_partner,base.group_sale_salesman,1,1,1,0
|
||||
access_res_partner_category,res.partner.category.crm.user,base.model_res_partner_category,base.group_sale_salesman,1,1,1,0
|
||||
mail_mailgate_thread,mail.thread,mail.model_mail_thread,base.group_sale_salesman,1,1,1,1
|
||||
|
|
|
|
@ -628,13 +628,13 @@ class google_calendar(osv.AbstractModel):
|
|||
else:
|
||||
if event_to_synchronize[base_event][0][1].OE.event_id:
|
||||
parent_oe_id = event_to_synchronize[base_event][0][1].OE.event_id
|
||||
calendar_event.unlink(cr, uid, "%s-%s" % (parent_oe_id, new_google_event_id), unlink_level=1, context=context)
|
||||
calendar_event.unlink(cr, uid, "%s-%s" % (parent_oe_id, new_google_event_id), can_be_deleted=True, context=context)
|
||||
|
||||
elif isinstance(actToDo, Delete):
|
||||
if actSrc == 'GG':
|
||||
self.delete_an_event(cr, uid, current_event[0], context=context)
|
||||
elif actSrc == 'OE':
|
||||
calendar_event.unlink(cr, uid, event.OE.event_id, unlink_level=0, context=context)
|
||||
calendar_event.unlink(cr, uid, event.OE.event_id, can_be_deleted=False, context=context)
|
||||
return True
|
||||
|
||||
def check_and_sync(self, cr, uid, oe_event, google_event, context):
|
||||
|
@ -750,6 +750,9 @@ class calendar_event(osv.Model):
|
|||
default['oe_update_date'] = False
|
||||
return super(calendar_event, self).copy(cr, uid, id, default, context)
|
||||
|
||||
def unlink(self, cr, uid, ids, can_be_deleted=False, context=None):
|
||||
return super(calendar_event, self).unlink(cr, uid, ids, can_be_deleted=can_be_deleted, context=context)
|
||||
|
||||
_columns = {
|
||||
'oe_update_date': fields.datetime('OpenERP Update Date'),
|
||||
}
|
||||
|
|
|
@ -367,9 +367,9 @@ class hr_holidays(osv.osv):
|
|||
'duration': record.number_of_days_temp * 8,
|
||||
'description': record.notes,
|
||||
'user_id': record.user_id.id,
|
||||
'date': record.date_from,
|
||||
'end_date': record.date_to,
|
||||
'date_deadline': record.date_to,
|
||||
'zstart': record.date_from,
|
||||
'zstop': record.date_to,
|
||||
'allday': False,
|
||||
'state': 'open', # to block that meeting date in the calendar
|
||||
'class': 'confidential'
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue