def get_by_date_at_location( session, location, start_date, end_date, tzone='UTC'): """ Returns all the meetings in a given time period at a given location. Recursive meetings are expanded as if each was a single meeting. :arg session: the database session to use :arg calendarobj: the calendar (object) of interest. :arg start_date: a Date object representing the beginning of the period :arg start_date: a Date object representing the ending of the period :kwarg tzone: the timezone in which the meetings should be displayed defaults to UTC. """ meetings_utc = Meeting.get_by_date_at_location( session, location, start_date, end_date, no_recursive=True) meetings_utc.extend(Meeting.get_regular_meeting_by_date_at_location( session, location, start_date, end_date)) meetings = list(set(meetings_utc)) if tzone: meetings = [ convert_meeting_timezone( meeting, meeting.meeting_timezone, tzone) for meeting in meetings ] meetings.sort(key=operator.attrgetter('meeting_date')) return meetings
def get_by_date(session, calendarobj, start_date, end_date, tzone='UTC', extended=True): """ Returns all the meetings in a given time period. Recursive meetings are expanded as if each was a single meeting. :arg session: the database session to use :arg calendarobj: the calendar (object) of interest. :arg start_date: a Date object representing the beginning of the period :arg start_date: a Date object representing the ending of the period :kwarg tzone: the timezone in which the meetings should be displayed defaults to UTC. """ meetings_utc = Meeting.get_by_date( session, calendarobj, start_date, end_date, no_recursive=extended) if extended: meetings_utc.extend( Meeting.get_regular_meeting_by_date( session, calendarobj, start_date, end_date)) else: meetings_utc.extend( Meeting.get_active_regular_meeting_by_date( session, calendarobj, start_date)) meetings = list(set(meetings_utc)) meetings.sort(key=operator.attrgetter('meeting_date')) return meetings
def get_full_day_meetings(self): """ Retrieve all the full day meetings for this week. """ if self.calendar: self.full_day_meetings = Meeting.get_by_date( self.session, self.calendar, self.start_date, self.stop_date, full_day=True) meetings = Meeting.get_active_regular_meeting( self.session, self.calendar, self.start_date, self.stop_date, full_day=True) else: self.full_day_meetings = Meeting.get_by_date_at_location( self.session, self.location, self.start_date, self.stop_date, full_day=True) meetings = Meeting.get_active_regular_meeting_at_location( self.session, self.location, self.start_date, self.stop_date, full_day=True) for meeting in meetings: for delta in range(0, 7): day = self.start_date + timedelta(days=delta) if ((meeting.meeting_date - day).days % meeting.recursion_frequency) == 0: if meeting not in self.full_day_meetings: self.full_day_meetings.append(meeting) # Expand the regular meetings so that they appear as meeting self.full_day_meetings = Meeting.expand_regular_meetings( self.full_day_meetings, end_date=self.stop_date, start_date=self.start_date) # Sort the meetings by date, time_start and name self.full_day_meetings.sort(key=operator.attrgetter( 'meeting_date', 'meeting_time_start', 'meeting_name'))
def update_date_rec_meeting(meeting, action='last'): """ From a recursive meeting, returns a meeting which date corresponds either to that of the last recursion that occured, or the next recursion that will occur. """ if meeting.recursion_frequency and meeting.recursion_ends \ and is_date_in_future( meeting.recursion_ends, meeting.meeting_time_start): meetingobj = Meeting.copy(meeting) while meetingobj.meeting_date < date.today(): if meetingobj.recursion_ends < meetingobj.meeting_date + \ timedelta( days=meetingobj.recursion_frequency ): # pragma: no cover break meetingobj.meeting_date = meetingobj.meeting_date + \ timedelta(days=meetingobj.recursion_frequency) meetingobj.meeting_date_end = meetingobj.meeting_date_end + \ timedelta(days=meetingobj.recursion_frequency) meetingobj.meeting_manager_user = meeting.meeting_manager_user meeting = meetingobj if action == 'last': meeting.meeting_date = meeting.meeting_date - \ timedelta(days=meeting.recursion_frequency) meeting.meeting_date_end = meeting.meeting_date_end - \ timedelta(days=meeting.recursion_frequency) return meeting
def delete_meeting(meeting_id): """ Delete a specific meeting given its identifier. :arg meeting_id: the identifier of the meeting to delete. """ if not flask.g.fas_user: return flask.redirect(flask.url_for("index")) meeting = Meeting.by_id(SESSION, meeting_id) if not (is_meeting_manager(meeting) or is_calendar_admin(meeting.calendar) or is_admin()): flask.flash( "You are not one of the manager of this meeting, " "or an admin, you are not allowed to delete it.", "errors", ) return flask.redirect(flask.url_for("view_meeting", meeting_id=meeting_id)) calendars = Calendar.get_all(SESSION) deleteform = forms.DeleteMeetingForm() # pylint: disable=E1101 if deleteform.validate_on_submit(): if deleteform.confirm_delete.data: if deleteform.confirm_futher_delete.data: fedocallib.delete_recursive_meeting(SESSION, meeting) else: meeting.delete(SESSION) try: SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print "edit_meeting:", err flask.flash("Could not update this meeting.", "error") flask.flash("Meeting deleted") return flask.redirect(flask.url_for("calendar", calendar_name=meeting.calendar_name))
def view_meeting_page(meeting_id, full): """ View a specific meeting given its identifier. :arg meeting_id: the identifier of the meeting to visualize. """ meeting = Meeting.by_id(SESSION, meeting_id) tzone = get_timezone() if not meeting: flask.flash("No meeting could be found for this identifier", "errors") return flask.redirect(flask.url_for("index")) meeting = fedocallib.convert_meeting_timezone(meeting, "UTC", tzone) auth_form = forms.LoginForm() editor = is_admin() if not editor: if is_meeting_manager(meeting) or is_calendar_admin(meeting.calendar): editor = True return flask.render_template( "view_meeting.html", full=full, meeting=meeting, tzone=tzone, title=meeting.meeting_name, editor=editor, auth_form=auth_form, )
def retrieve_meeting_to_remind(session, offset=30): """ Retrieve all the meetings for which we have to send a reminder. :arg session: the database session to use. :kwarg offset: the frequency at which the cron job is ran in order to avoid sending twice the same reminder. """ today = datetime.utcnow() meetings = [] for reminder_time in [12, 24, 48, 168]: # Retrieve meeting planned in less than X hours new_date = _generate_date_rounded_to_the_hour(today, reminder_time) end_date = new_date + timedelta(minutes=offset) if new_date.date() != end_date.date(): # in case the end_date is day after (ie: 23:45 + 30min), make # the end_date as start_date at 23:59 end_date = datetime( new_date.year, new_date.month, new_date.day, 23, 59) meetings.extend(Meeting.get_meeting_with_reminder( session, new_date.date(), new_date.time(), end_date.time(), 'H-%s' % reminder_time)) return meetings
def update_date_rec_meeting(meeting, action='last', date_limit=None): """ From a recursive meeting, returns a meeting which date corresponds either to that of the last recursion that occured, or the next recursion that will occur. """ if not date_limit: date_limit = date.today() if date_limit < meeting.meeting_date: date_limit = meeting.meeting_date if meeting.recursion_frequency and meeting.recursion_ends: meetingobj = Meeting.copy(meeting) while meetingobj.meeting_date < date_limit: if meetingobj.recursion_ends < meetingobj.meeting_date + \ timedelta( days=meetingobj.recursion_frequency ): # pragma: no cover break meetingobj.meeting_date = meetingobj.meeting_date + \ timedelta(days=meetingobj.recursion_frequency) meetingobj.meeting_date_end = meetingobj.meeting_date_end + \ timedelta(days=meetingobj.recursion_frequency) meetingobj.meeting_manager_user = meeting.meeting_manager_user if action == 'last': last_date = meetingobj.meeting_date - \ timedelta(days=meetingobj.recursion_frequency) if meeting.meeting_date < last_date: meetingobj.meeting_date = last_date meetingobj.meeting_date_end = meetingobj.meeting_date_end - \ timedelta(days=meetingobj.recursion_frequency) meeting = meetingobj return meeting
def get_full_day_meetings(self): """ Retrieve all the full day meetings for this week. """ if self.calendar: self.full_day_meetings = Meeting.get_by_date(self.session, self.calendar, self.start_date, self.stop_date, full_day=True) meetings = Meeting.get_active_regular_meeting(self.session, self.calendar, self.start_date, self.stop_date, full_day=True) else: self.full_day_meetings = Meeting.get_by_date_at_location( self.session, self.location, self.start_date, self.stop_date, full_day=True) meetings = Meeting.get_active_regular_meeting_at_location( self.session, self.location, self.start_date, self.stop_date, full_day=True) for meeting in meetings: for delta in range(0, 7): day = self.start_date + timedelta(days=delta) if ((meeting.meeting_date - day).days % meeting.recursion_frequency) == 0: if meeting not in self.full_day_meetings: self.full_day_meetings.append(meeting) # Expand the regular meetings so that they appear as meeting self.full_day_meetings = Meeting.expand_regular_meetings( self.full_day_meetings, end_date=self.stop_date, start_date=self.start_date) # Sort the meetings by date, time_start and name self.full_day_meetings.sort(key=operator.attrgetter( 'meeting_date', 'meeting_time_start', 'meeting_name'))
def agenda_is_free( session, calendarobj, meeting_date, meeting_date_end): """Check if there is already someting planned in this agenda at that time on that day. :arg session: the database session to use :arg calendar: the name of the calendar of interest. :arg meeting_date: the date of the meeting (as Datetime object) :arg meeting_date_end: the end date of the meeting (as Datetime object) :arg time_start: the time at which the meeting starts (as int) :arg time_stop: the time at which the meeting stops (as int) """ meetings = Meeting.get_overlaping_meetings( session, calendarobj, meeting_date.date(), meeting_date_end.date()) agenda_free = True for meeting in set(meetings): meeting_start_date_time = datetime( meeting.meeting_date.year, meeting.meeting_date.month, meeting.meeting_date.day, meeting.meeting_time_start.hour, meeting.meeting_time_start.minute, tzinfo=pytz.timezone(meeting.meeting_timezone)) meeting_stop_date_time = datetime( meeting.meeting_date_end.year, meeting.meeting_date_end.month, meeting.meeting_date_end.day, meeting.meeting_time_stop.hour, meeting.meeting_time_stop.minute, tzinfo=pytz.timezone(meeting.meeting_timezone)) if meeting_date <= meeting_start_date_time \ and meeting_date_end > meeting_start_date_time: agenda_free = False elif meeting_date < meeting_stop_date_time \ and meeting_date_end >= meeting_stop_date_time: agenda_free = False elif meeting_date < meeting_start_date_time \ and meeting_date_end > meeting_stop_date_time: agenda_free = False elif meeting_date > meeting_start_date_time \ and meeting_date_end < meeting_stop_date_time: agenda_free = False elif meeting_date == meeting_start_date_time \ and meeting_date_end == meeting_stop_date_time: agenda_free = False return agenda_free
def edit_meeting(meeting_id): """ Edit a specific meeting based on the meeting identifier. :arg meeting_id: the identifier of the meeting to edit. """ if not flask.g.fas_user: return flask.redirect(flask.url_for("index")) meeting = Meeting.by_id(SESSION, meeting_id) calendarobj = Calendar.by_id(SESSION, meeting.calendar_name) if not (is_meeting_manager(meeting) or is_calendar_admin(meeting.calendarobj) or is_admin()): flask.flash( "You are not one of the manager of this meeting, " "or an admin, you are not allowed to edit it.", "errors" ) return flask.redirect(flask.url_for("view_meeting", meeting_id=meeting_id)) tzone = get_timezone() form = forms.AddMeetingForm() # pylint: disable=E1101 if form.validate_on_submit(): try: fedocallib.edit_meeting( session=SESSION, meeting=meeting, calendarobj=calendarobj, fas_user=flask.g.fas_user, meeting_name=form.meeting_name.data, meeting_date=form.meeting_date.data, meeting_date_end=None, meeting_time_start=form.meeting_time_start.data, meeting_time_stop=form.meeting_time_stop.data, comanager=form.comanager.data, meeting_information=form.information.data, meeting_region=form.meeting_region.data, tzone=get_timezone(), recursion_frequency=form.frequency.data, recursion_ends=form.end_repeats.data, remind_when=form.remind_when.data, remind_who=form.remind_who.data, full_day=form.full_day.data, edit_all_meeting=form.recursive_edit.data, admin=is_admin(), ) except FedocalException, err: flask.flash(err, "warnings") return flask.render_template( "edit_meeting.html", meeting=meeting, calendar=calendarobj, form=form, tzone=tzone ) except SQLAlchemyError, err: SESSION.rollback() print "edit_meeting:", err flask.flash("Could not update this meeting.", "errors") return flask.render_template( "edit_meeting.html", meeting=meeting, calendar=calendarobj, form=form, tzone=tzone )
def get_past_meeting_of_user( session, username, tzone='UTC', from_date=date.today()): """ Return all past meeting which specified username is among the managers. :arg session: the database session to use :arg username: the FAS user name that you would like to have the past meetings for. :kwarg tzone: the time-zone to which to convert the meetings. Defaults to 'UTC'. :kwarg from_date: the date from which the futur meetings should be retrieved. Defaults to today """ meetings_tmp = Meeting.expand_regular_meetings( Meeting.get_past_meeting_of_user(session, username, from_date), end_date=from_date) meetings = [] for meeting in meetings_tmp: meetings.append(convert_meeting_timezone( meeting, meeting.meeting_timezone, tzone)) meetings.sort(key=operator.attrgetter('meeting_date')) return meetings
def get_by_date(session, calendarobj, start_date, end_date, tzone='UTC', extended=True, name=None): """ Returns all the meetings in a given time period. Recursive meetings are expanded as if each was a single meeting. :arg session: the database session to use :arg calendarobj: the calendar (object) of interest. :arg start_date: a Date object representing the beginning of the period :arg start_date: a Date object representing the ending of the period :kwarg tzone: the timezone in which the meetings should be displayed defaults to UTC. :kwarg name: Defaults to None, if set the meetings returned will be filtered for this string in their name. """ meetings_utc = Meeting.get_by_date( session, calendarobj, start_date, end_date, no_recursive=extended, name=name) if extended: meetings_utc.extend( Meeting.get_regular_meeting_by_date( session, calendarobj, start_date, end_date, name=name)) else: meetings_utc.extend( Meeting.get_active_regular_meeting_by_date( session, calendarobj, start_date, name=name)) meetings = list(set(meetings_utc)) if tzone: meetings = [ convert_meeting_timezone( meeting, meeting.meeting_timezone, tzone) for meeting in meetings ] meetings.sort(key=operator.attrgetter('meeting_date')) return meetings
def delete_meeting(meeting_id): """ Delete a specific meeting given its identifier. :arg meeting_id: the identifier of the meeting to delete. """ if not flask.g.fas_user: return flask.redirect(flask.url_for('index')) meeting = Meeting.by_id(SESSION, meeting_id) if meeting.calendar.calendar_status != 'Enabled': flask.flash('This calendar is "%s", you are not allowed to delete ' 'its meetings anymore.' % calendarobj.calendar_status, 'errors') return flask.redirect(flask.url_for('calendar', calendar_name=calendar_name)) if not (is_meeting_manager(meeting) or is_calendar_admin(meeting.calendar) or is_admin()): flask.flash('You are not one of the manager of this meeting, ' 'or an admin, you are not allowed to delete it.', 'errors') return flask.redirect(flask.url_for('view_meeting', meeting_id=meeting_id)) calendars = Calendar.get_all(SESSION) deleteform = forms.DeleteMeetingForm() # pylint: disable=E1101 if deleteform.validate_on_submit(): if deleteform.confirm_delete.data: if deleteform.confirm_futher_delete.data: fedocallib.delete_recursive_meeting(SESSION, meeting) else: meeting.delete(SESSION) try: SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print 'edit_meeting:', err flask.flash('Could not update this meeting.', 'error') flask.flash('Meeting deleted') fedmsg.publish(topic="meeting.delete", msg=dict( agent=flask.g.fas_user.username, meeting=meeting.to_json(), calendar=meeting.calendar.to_json(), )) return flask.redirect(flask.url_for( 'calendar', calendar_name=meeting.calendar_name))
def get_meetings_by_date_and_location( session, calendar, start_date, end_date, location): """ Return a list of meetings which have or will occur in between the two provided dates. :arg session: the database session to use :arg calendar: the name of the calendar of interest. :arg start_date: the date from which we would like to retrieve the meetings (this day is included in the selection). :arg start_date: the date until which we would like to retrieve the meetings (this day is excluded from the selection). :arg location: the location in which the meetings occurs. """ calendar = Calendar.by_id(session, calendar) return Meeting.get_by_date_and_location(session, calendar, start_date, end_date, location)
def update_date_rec_meeting(meeting, action='last', date_limit=None): """ From a recursive meeting, returns a meeting which date corresponds either to that of the last recursion that occured, or the next recursion that will occur. """ if not date_limit: date_limit = date.today() if date_limit < meeting.meeting_date: date_limit = meeting.meeting_date if meeting.recursion_frequency and meeting.recursion_ends: meetingobj = Meeting.copy(meeting) delta = timedelta(days=meetingobj.recursion_frequency) while meetingobj.meeting_date < date_limit: if meetingobj.recursion_ends < meetingobj.meeting_date + \ delta: # pragma: no cover break meetingobj.meeting_date = meetingobj.meeting_date + delta meetingobj.meeting_date_end = meetingobj.meeting_date_end + delta meetingobj.meeting_manager_user = meeting.meeting_manager_user if action == 'closest': last_date = meetingobj.meeting_date - delta delta_before = last_date - date_limit delta_after = meetingobj.meeting_date - date_limit if abs(delta_before) < abs(delta_after): action = 'last' if action == 'last': last_date = meetingobj.meeting_date - delta if meeting.meeting_date < last_date: meetingobj.meeting_date = last_date meetingobj.meeting_date_end = meetingobj.meeting_date_end - \ delta meeting = meetingobj return meeting
def update_date_rec_meeting(meeting, action='last', date_limit=None): """ From a recursive meeting, returns a meeting which date corresponds either to that of the last recursion that occured, or the next recursion that will occur. """ if not date_limit: date_limit = date.today() if date_limit < meeting.meeting_date: date_limit = meeting.meeting_date if meeting.recursion_frequency and meeting.recursion_ends \ and is_date_in_future( meeting.recursion_ends, meeting.meeting_time_start): meetingobj = Meeting.copy(meeting) while meetingobj.meeting_date < date_limit: if meetingobj.recursion_ends < meetingobj.meeting_date + \ timedelta( days=meetingobj.recursion_frequency ): # pragma: no cover break meetingobj.meeting_date = meetingobj.meeting_date + \ timedelta(days=meetingobj.recursion_frequency) meetingobj.meeting_date_end = meetingobj.meeting_date_end + \ timedelta(days=meetingobj.recursion_frequency) meetingobj.meeting_manager_user = meeting.meeting_manager_user if action == 'last': last_date = meetingobj.meeting_date - \ timedelta(days=meetingobj.recursion_frequency) if meeting.meeting_date < last_date: meetingobj.meeting_date = last_date meetingobj.meeting_date_end = meetingobj.meeting_date_end - \ timedelta(days=meetingobj.recursion_frequency) meeting = meetingobj return meeting
def get_future_regular_meeting_of_user( session, username, tzone='UTC', from_date=date.today()): """ Return all future recursive meeting which specified username is among the managers. :arg session: the database session to use. :arg username: the FAS user name that you would like to have the past meetings for. :kwarg tzone: the time-zone to which to convert the meetings. Defaults to 'UTC'. :kwarg from_date: the date from which the futur meetings should be retrieved. Defaults to today. """ meetings_tmp = Meeting.get_future_regular_meeting_of_user( session, username, from_date) meetings = [] for meeting in meetings_tmp: mtg_conv = convert_meeting_timezone( meeting, meeting.meeting_timezone, tzone) last_rec = mtg_conv.recursion_ends - timedelta( days=mtg_conv.recursion_frequency) if last_rec >= from_date: meetings.append(mtg_conv) return meetings
print "edit_meeting:", err flask.flash("Could not update this meeting.", "errors") return flask.render_template( "edit_meeting.html", meeting=meeting, calendar=calendarobj, form=form, tzone=tzone ) flask.flash("Meeting updated") return flask.redirect(flask.url_for("view_meeting", meeting_id=meeting_id)) else: if ( meeting.recursion_frequency and meeting.recursion_ends and fedocallib.is_date_in_future(meeting.recursion_ends, meeting.meeting_time_start) ): cnt = 0 meetingobj = Meeting.copy(meeting) while meetingobj.meeting_date < datetime.date.today(): if meetingobj.recursion_ends < meetingobj.meeting_date + datetime.timedelta( days=meetingobj.recursion_frequency * cnt ): break meetingobj = Meeting.copy(meeting) meetingobj.meeting_date = meetingobj.meeting_date + datetime.timedelta( days=meetingobj.recursion_frequency * cnt ) cnt = cnt + 1 meeting = meetingobj if not fedocallib.is_date_in_future(meeting.meeting_date, meeting.meeting_time_start): flask.flash("This meeting has already occured, you may not " "change it anymore", "warnings") return flask.redirect(flask.url_for("my_meetings")) form = forms.AddMeetingForm(meeting=meeting, tzone=get_timezone())
def clear_calendar(session, calendar): """ Remove all the meetings from the specified calendar. """ return Meeting.clear_from_calendar(session, calendar)
def search_locations(session, keyword): """ Return the list of locations matching the provided keyword. """ keyword = keyword.replace('*', '%') return Meeting.search_locations(session, keyword)
def get_locations(session): """ Return the list of all the locations where meetings happen according to the database. """ return Meeting.get_locations(session)
def edit_meeting(meeting_id): """ Edit a specific meeting based on the meeting identifier. :arg meeting_id: the identifier of the meeting to edit. """ if not flask.g.fas_user: return flask.redirect(flask.url_for('index')) meeting = Meeting.by_id(SESSION, meeting_id) calendarobj = Calendar.by_id(SESSION, meeting.calendar_name) if calendarobj.calendar_status != 'Enabled': flask.flash('This calendar is "%s", you are not allowed to edit its ' 'meetings anymore.' % calendarobj.calendar_status, 'errors') return flask.redirect(flask.url_for('calendar', calendar_name=calendar_name)) if not (is_meeting_manager(meeting) or is_calendar_admin(calendarobj) or is_admin()): flask.flash('You are not one of the manager of this meeting, ' 'or an admin, you are not allowed to edit it.', 'errors') return flask.redirect(flask.url_for('view_meeting', meeting_id=meeting_id)) tzone = get_timezone() form = forms.AddMeetingForm(timezone=tzone) # pylint: disable=E1101 if form.validate_on_submit(): tzone = form.meeting_timezone.data or tzone try: fedocallib.edit_meeting( session=SESSION, meeting=meeting, calendarobj=calendarobj, fas_user=flask.g.fas_user, meeting_name=form.meeting_name.data, meeting_date=form.meeting_date.data, meeting_date_end=None, meeting_time_start=form.meeting_time_start.data, meeting_time_stop=form.meeting_time_stop.data, comanager=form.comanager.data, meeting_information=form.information.data, meeting_region=form.meeting_region.data, tzone=tzone, recursion_frequency=form.frequency.data, recursion_ends=form.end_repeats.data, remind_when=form.remind_when.data, remind_who=form.remind_who.data, full_day=form.full_day.data, edit_all_meeting=form.recursive_edit.data, admin=is_admin()) except FedocalException, err: flask.flash(err, 'warnings') return flask.render_template( 'edit_meeting.html', meeting=meeting, calendar=calendarobj, form=form, tzone=tzone) except SQLAlchemyError, err: SESSION.rollback() print 'edit_meeting:', err flask.flash('Could not update this meeting.', 'errors') return flask.render_template( 'edit_meeting.html', meeting=meeting, calendar=calendarobj, form=form, tzone=tzone)