diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index 8943fe4c03f..2e8513fc5c2 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -373,12 +373,12 @@ class calendar_alarm_manager(osv.AbstractModel): tuple_params += (partner_id, ) #Add filter on hours - tuple_params += (seconds, seconds,) + tuple_params += (seconds,) cr.execute("""SELECT * 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 ) + AND ALL_EVENTS.last_event_date > (now() at time zone 'utc') """ % base_request, tuple_params) for event_id, first_alarm, last_alarm, first_meeting, last_meeting, min_duration, max_duration, rule in cr.fetchall(): @@ -395,20 +395,30 @@ class calendar_alarm_manager(osv.AbstractModel): return res - def do_check_alarm_for_one_date(self, cr, uid, one_date, event, event_maxdelta, in_the_next_X_seconds, after=False, notif=True, mail=True, context=None): - res = [] - alarm_type = [] + def do_check_alarm_for_one_date(self, cr, uid, one_date, event, event_maxdelta, in_the_next_X_seconds, after=False, notif=True, mail=True, missing=False, context=None): + # one_date: date of the event to check (not the same that in the event browse if recurrent) + # event: Event browse record + # event_maxdelta: biggest duration from alarms for this event + # in_the_next_X_seconds: looking in the future (in seconds) + # after: if not False: will return alert if after this date (date as string - todo: change in master) + # missing: if not False: will return alert even if we are too late + # notif: Looking for type notification + # mail: looking for type email + res = [] + + # TODO: replace notif and email in master by alarm_type + remove event_maxdelta and if using it + alarm_type = [] if notif: alarm_type.append('notification') if mail: alarm_type.append('email') - if one_date - timedelta(minutes=event_maxdelta) < datetime.now() + timedelta(seconds=in_the_next_X_seconds): # if an alarm is possible for this date + if one_date - timedelta(minutes=(missing and 0 or event_maxdelta)) < datetime.now() + timedelta(seconds=in_the_next_X_seconds): # if an alarm is possible for this date 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], DEFAULT_SERVER_DATETIME_FORMAT)): + one_date - timedelta(minutes=(missing and 0 or alarm.duration_minutes)) < datetime.now() + timedelta(seconds=in_the_next_X_seconds) and \ + (not after or one_date - timedelta(minutes=alarm.duration_minutes) > openerp.fields.Datetime.from_string(after)): alert = { 'alarm_id': alarm.id, 'event_id': event.id, @@ -418,55 +428,53 @@ class calendar_alarm_manager(osv.AbstractModel): return res def get_next_mail(self, cr, uid, context=None): + now = openerp.fields.Datetime.to_string(datetime.now()) + + icp = self.pool['ir.config_parameter'] + last_notif_mail = icp.get_param(cr, SUPERUSER_ID, 'calendar.last_notif_mail', default=False) or now + try: - cron = self.pool['ir.model.data'].get_object( - cr, uid, 'calendar', 'ir_cron_scheduler_alarm', context=context) + cron = self.pool['ir.model.data'].get_object(cr, uid, 'calendar', 'ir_cron_scheduler_alarm', context=context) except ValueError: _logger.error("Cron for " + self._name + " can not be identified !") return False - if cron.interval_type == "weeks": - cron_interval = cron.interval_number * 7 * 24 * 60 * 60 - elif cron.interval_type == "days": - cron_interval = cron.interval_number * 24 * 60 * 60 - elif cron.interval_type == "hours": - cron_interval = cron.interval_number * 60 * 60 - elif cron.interval_type == "minutes": - cron_interval = cron.interval_number * 60 - elif cron.interval_type == "seconds": - cron_interval = cron.interval_number - else: - cron_interval = False + interval_to_second = { + "weeks": 7 * 24 * 60 * 60, + "days": 24 * 60 * 60, + "hours": 60 * 60, + "minutes": 60, + "seconds": 1 + } - if not cron_interval: + if cron.interval_type not in interval_to_second.keys(): _logger.error("Cron delay can not be computed !") return False + cron_interval = cron.interval_number * interval_to_second[cron.interval_type] + all_events = self.get_next_potential_limit_alarm(cr, uid, cron_interval, notif=False, context=context) - for event in all_events: # .values() - max_delta = all_events[event]['max_duration'] - curEvent = self.pool.get('calendar.event').browse(cr, uid, event, context=context) + for curEvent in self.pool.get('calendar.event').browse(cr, uid, all_events.keys(), context=context): + max_delta = all_events[curEvent.id]['max_duration'] + if curEvent.recurrency: - bFound = False - LastFound = False + at_least_one = False + last_found = False for one_date in self.pool.get('calendar.event').get_recurrent_date_by_event(cr, uid, curEvent, context=context): in_date_format = one_date.replace(tzinfo=None) - 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: - self.do_mail_reminder(cr, uid, alert, context=context) - - if not bFound: # if it's the first alarm for this recurrent event - bFound = True - if bFound and not LastFound: # if the precedent event had an alarm but not this one, we can stop the search for this event + last_found = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, 0, after=last_notif_mail, notif=False, missing=True, context=context) + for alert in last_found: + self.do_mail_reminder(cr, uid, alert, context=context) + at_least_one = True # if it's the first alarm for this recurrent event + if at_least_one and not last_found: # 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.start, 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: - self.do_mail_reminder(cr, uid, alert, context=context) + last_found = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, 0, after=last_notif_mail, notif=False, missing=True, context=context) + for alert in last_found: + self.do_mail_reminder(cr, uid, alert, context=context) + icp.set_param(cr, SUPERUSER_ID, 'calendar.last_notif_mail', now) def get_next_notif(self, cr, uid, context=None): ajax_check_every_seconds = 300 @@ -496,7 +504,7 @@ class calendar_alarm_manager(osv.AbstractModel): break else: in_date_format = datetime.strptime(curEvent.start, 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, after=partner.calendar_last_notif_ack, mail=False, context=context) if LastFound: for alert in LastFound: all_notif.append(self.do_notif_reminder(cr, uid, alert, context=context)) @@ -515,6 +523,7 @@ class calendar_alarm_manager(osv.AbstractModel): cr, uid, [att.id for att in event.attendee_ids], + email_from=event.user_id.partner_id.email, template_xmlid='calendar_template_meeting_reminder', force=True, context=context