def get_full_day_meetings(self): """ Retrieve all the full day meetings of this week. """ self.full_day_meetings = Meeting.get_by_date( self.session, self.calendar, self.start_date, self.stop_date, full_day=True ) for meeting in Meeting.get_active_regular_meeting( self.session, self.calendar, self.start_date, self.stop_date, full_day=True ): 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)
def get_meetings(self): """ Retrieves the list of this week meeting from the database. """ self.meetings = Meeting.get_by_date(self.session, self.calendar, self.start_date, self.stop_date) self.meetings.extend( Meeting.get_by_date(self.session, self.calendar, self.start_date, self.stop_date, full_day=True) ) for meeting in Meeting.get_active_regular_meeting(self.session, self.calendar, self.start_date, self.stop_date): 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.meetings: self.meetings.append(meeting)
def update_attended_staff(meeting: Meeting, staff: Staff): """ Updates the Database with staff members who have attended the meeting """ if staff.id not in meeting.attended_staff: meeting.attended_staff.append(staff.id) db.update_meeting(meeting.id, meeting.to_json_dict())
def test_parse_and_convert_modified_meeting(): original_dict = db.get_all_meetings()[0] parsed_object = Meeting.parse(original_dict) # Type: Meeting parsed_object.started = not parsed_object.started original_dict["started"] = not original_dict["started"] parsed_dict = parsed_object.to_json_dict() assert original_dict == parsed_dict
def load_meetings(): """Load meetings from source CSV into database.""" print "Importing meetings..." # Delete all rows in table, so if we need to run this a second time, # we won't be trying to add duplicate retailers Meeting.query.delete() # Read CSV file with open("seed_data/meetings.csv") as source_file: example_data = list(csv.reader(source_file)) # skip header row for populating db for list_item in example_data[1:]: meeting = Meeting(meeting_title=list_item[1], meeting_time=list_item[2], attendees=list_item[3], length=list_item[4], topic_id=list_item[5]) # Add the current retailer to the session db.session.add(meeting) # Commit the db.session changes to the database db.session.commit()
def test_get_role_none(): meeting = Meeting.parse(db.get_meeting(mid)) all_staff_ids = set([staff["_id"] for staff in db.get_all_staff()]) non_participants = all_staff_ids.difference(set(meeting.staff)) staff = Staff.parse(db.get_staff(non_participants.pop())) roles = get_role(staff, meeting) assert (len(roles) == 0)
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.utc) 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.utc) 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 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, 'UTC', tzone)) meetings.sort(key=operator.attrgetter('meeting_date')) return meetings
def test_meeting_contract_deployment(): mch = MeetingContractHelper(c) meeting = Meeting.parse(db.get_all_meetings()[0]) contract_addr = mch.new_meeting_contract(meeting) mdt_meeting = w3.eth.contract( address=contract_addr, abi=mch.contract_abi, ) assert mdt_meeting.functions.getMeetingId().call() == meeting.id
def get_by_date(session, calendarobj, start_date, end_date, tzone='UTC'): """ 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=True) meetings_utc.extend(Meeting.get_regular_meeting_by_date(session, calendarobj, start_date, end_date)) meetings = [] for meeting in list(set(meetings_utc)): meetings.append(convert_meeting_timezone( meeting, 'UTC', tzone)) meetings.sort(key=operator.attrgetter('meeting_date')) return meetings
def get_meetings(self): """ Retrieves the list of this week's meeting from the database. """ self.meetings = Meeting.get_by_date( self.session, self.calendar, self.start_date, self.stop_date) for meeting in Meeting.get_active_regular_meeting( self.session, self.calendar, self.start_date, self.stop_date): 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.meetings: self.meetings.append(meeting) # Expand the regular meetings so that they appear as meeting self.meetings = Meeting.expand_regular_meetings( self.meetings, end_date=self.stop_date, start_date=self.start_date) # Sort the meetings by date, time_start and name self.meetings.sort(key=operator.attrgetter( 'meeting_date', 'meeting_time_start', 'meeting_name'))
def load_meetings(): """Load meetings into db""" print("Meetings") #Delete row to avoid duplicates Meeting.query.delete() meeting_rows = csv.DictReader(open('data/meetings.csv')) for meeting in meeting_rows: new_meeting = Meeting(month=meeting["month"], year=meeting["year"]) db.session.add(new_meeting) db.session.commit()
def test_meeting_contract_set_hash(): mch = MeetingContractHelper(c) meeting = Meeting.parse(db.get_all_meetings()[0]) contract_addr = mch.new_meeting_contract(meeting) meeting.contract_id = contract_addr mch.set_event_hash(meeting, "start_event", "end_event") mdt_meeting = w3.eth.contract( address=contract_addr, abi=mch.contract_abi, ) assert mdt_meeting.functions.getEvents().call() == [ "start_event", "end_event" ]
def get_meetings_by_date_and_region( session, calendar, start_date, end_date, region): """ 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 region: the region in which the meetings should occur. """ calendar = Calendar.by_id(session, calendar) return Meeting.get_by_date_and_region(session, calendar, start_date, end_date, region)
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: meetings.append(convert_meeting_timezone(meeting, 'UTC', tzone)) return meetings
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) meetings.extend(Meeting.get_meeting_with_reminder( session, new_date.date(), new_date.time(), end_date.time(), 'H-%s' % reminder_time)) return meetings
def room_message(event_string): """ Main function that handles all events that enter through the web socket """ # Parse json as dict try: event_json = json.loads(event_string) except ValueError as ve: log.error("Error Parsing room-message as JSON!") log.error(ve) traceback.print_tb(ve.__traceback__) return json.dumps( sign( get_error_ack( "unknown", "unknown", content=AckErrorContent( error_code=EventError.MALFORMED_EVENT, details='Cant parse message as JSON'))).to_json_dict()) # Validate JSON dict using schema ok, err_event = validate_schema(event_json) if not ok: log.error("Sending error msg") errormsg = json.dumps(sign(err_event).to_json_dict()) log.error("======== error_msg: " + errormsg) return errormsg # Parse dict as event object try: event = Event.parse(event_json) except KeyError as ve: log.error("Error Parsing room-message!") log.error(ve) traceback.print_tb(ve.__traceback__) return json.dumps( sign( get_error_ack("unknown", "unknown", content=AckErrorContent( error_code=EventError.MALFORMED_EVENT, details='Cant parse message as Event'))). to_json_dict()) # Check timestamp ok, err_event = validate_timestamp(event) if not ok: return json.dumps(sign(err_event).to_json_dict()) # Get the staff try: staff = Staff.parse(db.get_staff(event.by)) except KeyError as ke: log.error(ke) traceback.print_tb(ke.__traceback__) return json.dumps( sign( get_error_ack(event.id, event.meeting_id, content=AckErrorContent( error_code=EventError.STAFF_NOT_FOUND, details=''))).to_json_dict()) except TypeError as te: log.error(te) traceback.print_tb(te.__traceback__) return json.dumps( sign( get_error_ack(event.id, event.meeting_id, content=AckErrorContent( error_code=EventError.STAFF_NOT_FOUND, details=''))).to_json_dict()) # Get the meeting try: meeting = Meeting.parse(db.get_meeting(event.meeting_id)) except KeyError as ke: log.error(ke) traceback.print_tb(ke.__traceback__) return json.dumps( sign( get_error_ack(event.id, event.meeting_id, content=AckErrorContent( error_code=EventError.MEETING_NOT_FOUND, details=''))).to_json_dict()) except TypeError as te: log.error(te) traceback.print_tb(te.__traceback__) return json.dumps( sign( get_error_ack(event.id, event.meeting_id, content=AckErrorContent( error_code=EventError.MEETING_NOT_FOUND, details=''))).to_json_dict()) # Check signature, before trusting anything it says if event.type in [MeetingEventType.JOIN, MeetingEventType.START ]: # We check contract for join and start ok, err_event = validate_signature(event, staff, meeting, check_contract=True) if not ok: return json.dumps(sign(err_event).to_json_dict()) else: ok, err_event = validate_signature(event, staff, meeting) if not ok: return json.dumps(sign(err_event).to_json_dict()) # Get the roles roles = get_role(staff, meeting) # A preliminary authority check to see if the user can make any statements about the meeting ok, err_event = validate_preliminary_authority(event, roles) if not ok: return json.dumps(sign(err_event).to_json_dict()) # Get the event type event_type = MeetingEventType(event.type) ack_event = None ok = False end_meeting = False send_privately = False if event_type == MeetingEventType.START: ok, ack_event = start(event, staff, meeting, roles) if event_type == MeetingEventType.JOIN: ok, ack_event = join(event, staff, meeting, roles) if event_type == MeetingEventType.LEAVE: ok, ack_event = leave(event, staff, meeting) if event_type == MeetingEventType.POLL: ok, ack_event = poll(event, staff, meeting, roles) if event_type == MeetingEventType.VOTE: ok, ack_event = vote(event, staff, meeting, roles) if event_type == MeetingEventType.POLL_END: ok, ack_event = end_poll(event, staff, meeting, roles) if event_type == MeetingEventType.COMMENT or event_type == MeetingEventType.REPLY or event_type == MeetingEventType.DISAGREEMENT: ok, ack_event = comment_reply_disagreement(event, staff, meeting, roles) if event_type == MeetingEventType.DISCUSSION: ok, ack_event = discussion(event, staff, meeting, roles) if event_type == MeetingEventType.PATIENT_DATA_CHANGE: ok, ack_event = patient_data_change(event, staff, meeting, roles) if event_type == MeetingEventType.END: ok, ack_event = end(event, staff, meeting, roles) if ok: end_meeting = True if not ok: # If not ok we send the error ack event privately return json.dumps(sign(ack_event).to_json_dict()) else: # If an event has been referenced check_and_remove_ref_event(meeting, event.ref_event) # Add ack and event to unreferenced events add_event_as_unref(meeting, event) add_event_as_unref(meeting, ack_event) # Sign the ack signed_ack_event = sign(ack_event) if not send_privately: # Only Broadcast if the send_privately is set to False # Broadcast event send(json.dumps(event.to_json_dict()), broadcast_room=meeting.id) send(json.dumps(signed_ack_event.to_json_dict()), broadcast_room=meeting.id) record(event, meeting) record(signed_ack_event, meeting) if end_meeting: end_meeting_session(meeting, event, signed_ack_event) # Send the ack event to the user privately as well return json.dumps(signed_ack_event.to_json_dict())
def test_get_role_host(): meeting = Meeting.parse(db.get_meeting(mid)) staff = Staff.parse(db.get_staff(meeting.host)) roles = get_role(staff, meeting) assert (Role.HOST in roles) and (Role.PARTICIPANT in roles)
def test_get_role_participant(): meeting = Meeting.parse(db.get_meeting(mid)) staff = Staff.parse(db.get_staff(meeting.staff[1])) roles = get_role(staff, meeting) assert (Role.PARTICIPANT in roles)
def edit_meeting( session, meeting, calendarobj, fas_user, meeting_name, meeting_date, meeting_date_end, meeting_time_start, meeting_time_stop, comanager, meeting_information, meeting_region, tzone, recursion_frequency, recursion_ends, remind_when, remind_who, full_day, edit_all_meeting=True, admin=False): """ When a user wants to edit a meeting to the database, we need to perform a number of test first checking that the input is valid and then edit the desired meeting. """ if not is_user_managing_in_calendar( session, calendarobj.calendar_name, fas_user) and not admin: raise UserNotAllowed( 'You are not allowed to add a meeting to this calendar') if not meeting_date_end: meeting_date_end = meeting_date if full_day: meeting_time_start = time(0, 0) meeting_time_stop = time(0, 0) tzone = 'UTC' meeting_time_start = convert_time( datetime(meeting_date.year, meeting_date.month, meeting_date.day, meeting_time_start.hour, meeting_time_start.minute), tzone, 'UTC') meeting_time_stop = convert_time( datetime(meeting_date_end.year, meeting_date_end.month, meeting_date_end.day, meeting_time_stop.hour, meeting_time_stop.minute), tzone, 'UTC') if not is_date_in_future(meeting_date, meeting_time_start): raise InvalidMeeting('The date you entered is in the past') if meeting_time_start.date() > meeting_time_stop.date(): raise InvalidMeeting( 'The start date of your meeting is later than the stop date.') if meeting_time_start > meeting_time_stop: raise InvalidMeeting( 'The start time of your meeting is later than the stop time.') if full_day: meeting_time_stop = meeting_time_stop + timedelta(days=1) if recursion_frequency and recursion_ends: agenda_free = agenda_is_free_in_future( session, calendarobj, meeting_time_start.date(), meeting_time_stop.date(), recursion_ends, meeting_time_start.time(), meeting_time_stop.time(), meeting_id = meeting.meeting_id) if not bool(calendarobj.calendar_multiple_meetings) and \ not agenda_free: raise InvalidMeeting( 'The start or end time you have entered is already ' 'occupied in the future.') ## The information are correct ## What we do now: # a) the meeting is not recursive -> edit the information as provided # b) the meeting is recursive and we update all the meetings # -> recursion_end = today # -> copy meeting to new object # -> update new object # c) the meeting is recursive and the update only one meeting # -> recursion_end = today # -> copy meeting to new object w/o recursion # -> update new object # -> copy meeting to new object w/ recursion and date = date + offset remove_recursion = False if meeting.recursion_frequency: old_meeting = Meeting.copy(meeting) old_meeting.recursion_ends = meeting_date - timedelta(days=1) if old_meeting.recursion_ends > old_meeting.meeting_date: old_meeting.save(session) if not edit_all_meeting: remove_recursion = True new_meeting = Meeting.copy(meeting) new_meeting.meeting_date = meeting_date + timedelta( days=meeting.recursion_frequency) dt_start = datetime( new_meeting.meeting_date.year, new_meeting.meeting_date.month, new_meeting.meeting_date.day, new_meeting.meeting_time_start.hour, new_meeting.meeting_time_start.minute, tzinfo=pytz.utc) dt_stop = datetime( new_meeting.meeting_date_end.year, new_meeting.meeting_date_end.month, new_meeting.meeting_date_end.day, new_meeting.meeting_time_start.hour, new_meeting.meeting_time_start.minute, tzinfo=pytz.utc) free_time = agenda_is_free( session, calendarobj, dt_start, dt_stop) if not bool(calendarobj.calendar_multiple_meetings) and \ bool(free_time): new_meeting.save(session) meeting.meeting_name = meeting_name meeting.meeting_manager = '%s,' % fas_user.username if comanager: meeting.meeting_manager = '%s%s,' % (meeting.meeting_manager, comanager) meeting.meeting_date = meeting_time_start.date() meeting.meeting_date_end = meeting_time_stop.date() meeting.meeting_time_start = meeting_time_start.time() meeting.meeting_time_stop = meeting_time_stop.time() meeting.meeting_information = meeting_information region = meeting_region if not region: region = None meeting.meeting_region = region recursion_frequency = recursion_frequency if not recursion_frequency: recursion_frequency = None meeting.recursion_frequency = recursion_frequency if not recursion_ends: recursion_ends = date(2025, 12, 31) meeting.recursion_ends = recursion_ends if remind_when and remind_who: if meeting.reminder_id: meeting.reminder.reminder_offset = remind_when meeting.reminder.reminder_to = remind_who meeting.reminder.save(session) else: reminder = Reminder(remind_when, remind_who, None) reminder.save(session) session.flush() meeting.reminder = reminder session.flush() elif meeting.reminder_id: meeting.reminder.delete(session) meeting.reminder_id = None if remove_recursion: meeting.recursion_frequency = None meeting.recursion_ends = None meeting.save(session) session.commit()
def test_parse_and_convert_bad_event(): original_dict = copy.deepcopy(general_event_dict) print(original_dict) original_dict.pop("meetingId") with pytest.raises(KeyError) as e: parsed_dict = Meeting.parse(original_dict)
def test_parse_and_convert_meeting(): original_dict = db.get_all_meetings()[0] parsed_object = Meeting.parse(original_dict) generated_dict = parsed_object.to_json_dict() assert original_dict == generated_dict
def test_parse_and_convert_bad_staff(): original_dict = db.get_all_staff()[0] print(original_dict) original_dict.pop("name") with pytest.raises(KeyError) as e: parsed_dict = Meeting.parse(original_dict)