def test_stream_zipped_bundle(self, app): with mock_legacy_note_attachment(app): sid = '9000000000' filename = 'advising_notes' stream = get_zip_stream( filename=filename, notes=get_advising_notes(sid), student={ 'first_name': 'Wolfgang', 'last_name': 'Pauli-O\'Rourke', 'sid': sid, }, ) body = b'' for chunk in stream: body += chunk zipfile = ZipFile(io.BytesIO(body), 'r') contents = {} for name in zipfile.namelist(): contents[name] = zipfile.read(name) assert len(contents) == 2 assert contents['dog_eaten_homework.pdf'] == b'When in the course of human events, it becomes necessarf arf woof woof woof' csv_rows = contents[f'{filename}.csv'].decode('utf-8').strip().split('\r\n') assert len(csv_rows) == 4 assert csv_rows[0] == 'date_created,student_sid,student_name,author_uid,author_csid,author_name,subject,' \ 'topics,attachments,body,is_private,late_change_request_action,' \ 'late_change_request_status,late_change_request_term,late_change_request_course' assert csv_rows[1] == '2017-11-02,9000000000,Wolfgang Pauli-O\'Rourke,,700600500,,,,' \ 'dog_eaten_homework.pdf,I am confounded by this confounding student,False,,,,' assert csv_rows[2] == "2017-11-02,9000000000,Wolfgang Pauli-O'Rourke,,600500400,,,Ne Scéaw,," \ 'Is this student even on campus?,False,,,,' assert csv_rows[3] == "2020-12-05,9000000000,Wolfgang Pauli-O'Rourke,,,,,,,," \ 'False,Late Grading Basis Change,In Error,Fall 2020,' \ '24460 PSYCH 110 - INTROD BIOL PSYCH 001'
def download_notes_and_attachments(sid): students = data_loch.get_basic_student_data([sid]) student = students[0] if students else None notes = get_advising_notes(sid) if student else None if not student or not notes: return Response('Not found', status=404) filename = '_'.join([ 'advising_notes', student.get('first_name', '').lower(), student.get('last_name', '').lower(), localize_datetime(utc_now()).strftime('%Y%m%d'), ]) def generator(): for chunk in get_zip_stream(filename=filename, notes=notes, student=student): yield chunk response = Response(stream_with_context(generator()), mimetype='application/zip') encoding_safe_filename = urllib.parse.quote( f'{filename}.zip'.encode('utf8')) response.headers[ 'Content-Disposition'] = f'attachment; filename={encoding_safe_filename}' return response
def test_get_advising_notes_timestamp_format(self, app, fake_auth): fake_auth.login(coe_advisor) notes = get_advising_notes('9000000000') ucbconversion_note = notes[0] cs_note = notes[1] assert parse(ucbconversion_note['createdAt']) == parse('2017-11-02') assert ucbconversion_note['updatedAt'] is None assert parse(cs_note['createdAt']) == parse('2017-11-02T12:00:00+00') assert parse(cs_note['updatedAt']) == parse('2017-11-02T13:00:00+00')
def test_get_advising_notes_ucbconversion_attachment(self, app, fake_auth): fake_auth.login(coe_advisor) notes = get_advising_notes('11667051') assert notes[0]['attachments'] == [ { 'displayName': '11667051_00001_1.pdf', 'id': '11667051_00001_1.pdf', 'sisFilename': '11667051_00001_1.pdf', }, ]
def test_get_advising_notes_cs_attachment(self, app, mock_advising_note, fake_auth): fake_auth.login(coe_advisor) notes = get_advising_notes('11667051') assert notes[1]['attachments'] == [ { 'id': '11667051_00002_2.jpeg', 'sisFilename': '11667051_00002_2.jpeg', 'displayName': 'brigitte_photo.jpeg', }, ] boa_created_note = next((n for n in notes if n['id'] == mock_advising_note.id), None) assert boa_created_note assert boa_created_note['attachments'][0]['uploadedBy'] == mock_advising_note.author_uid
def put_notifications(student): sid = student['sid'] student['notifications'] = { 'note': [], 'alert': [], 'hold': [], 'requirement': [], } if app.config['FEATURE_FLAG_ADVISOR_APPOINTMENTS']: student['notifications']['appointment'] = [] for appointment in Appointment.get_appointments_per_sid(sid) or []: student['notifications']['appointment'].append({ **appointment.to_api_json(current_user.get_id()), **{ 'message': appointment.details, 'type': 'appointment', }, }) # The front-end requires 'type', 'message' and 'read'. Optional fields: id, status, createdAt, updatedAt. for note in get_advising_notes(sid) or []: message = note['body'] student['notifications']['note'].append({ **note, **{ 'message': message.strip() if message else None, 'type': 'note', }, }) for alert in Alert.current_alerts_for_sid(viewer_id=current_user.get_id(), sid=sid): student['notifications']['alert'].append({ **alert, **{ 'id': alert['id'], 'read': alert['dismissed'], 'type': 'alert', }, }) for row in get_sis_holds(sid): hold = json.loads(row['feed']) reason = hold.get('reason', {}) student['notifications']['hold'].append({ **hold, **{ 'createdAt': hold.get('fromDate'), 'message': join_if_present('. ', [ reason.get('description'), reason.get('formalDescription') ]), 'read': True, 'type': 'hold', }, }) degree_progress = student.get('sisProfile', {}).get('degreeProgress', {}) if degree_progress: for key, requirement in degree_progress.get('requirements', {}).items(): student['notifications']['requirement'].append( { **requirement, **{ 'type': 'requirement', 'message': requirement['name'] + ' ' + requirement['status'], 'read': True, }, })
def test_get_advising_notes(self, app, mock_advising_note, fake_auth): fake_auth.login(coe_advisor) notes = get_advising_notes('11667051') # Legacy SIS notes assert notes[0]['id'] == '11667051-00001' assert notes[0]['sid'] == '11667051' assert notes[0][ 'body'] == 'Brigitte is making athletic and moral progress' assert notes[0]['category'] == 'Quick Question' assert notes[0]['subcategory'] == 'Hangouts' assert notes[0]['appointmentId'] is None assert notes[0]['createdBy'] is None assert parse( notes[0]['createdAt']) == parse('2017-10-31T12:00:00+00:00') assert notes[0]['updatedBy'] is None assert notes[0]['updatedAt'] is None assert notes[0]['read'] is False assert notes[0]['topics'] == ['God Scéaw'] assert notes[1]['id'] == '11667051-00002' assert notes[1]['sid'] == '11667051' assert notes[1][ 'body'] == 'Brigitte demonstrates a cavalier attitude toward university requirements' assert notes[1]['category'] == 'Evaluation' assert notes[1]['subcategory'] == '' assert notes[1]['appointmentId'] is None assert notes[1]['createdBy'] is None assert parse(notes[1]['createdAt']) == parse('2017-11-01T12:00:00+00') assert notes[1]['updatedBy'] is None assert notes[1]['updatedAt'] is None assert notes[1]['read'] is False assert notes[1]['topics'] == ['Earg Scéaw', 'Ofscéaw'] # Legacy ASC notes assert notes[4]['id'] == '11667051-139362' assert notes[4]['sid'] == '11667051' assert notes[4]['body'] is None assert notes[4]['author']['uid'] == '1133399' assert notes[4]['author']['name'] == 'Lemmy Kilmister' assert notes[4]['topics'] == ['Academic', 'Other'] assert notes[4]['createdAt'] assert notes[4]['updatedAt'] is None assert notes[4]['read'] is False assert notes[5]['id'] == '11667051-139379' assert notes[5]['sid'] == '11667051' assert notes[5]['body'] is None assert notes[5]['author']['uid'] == '90412' assert notes[5]['author']['name'] == 'Ginger Baker' assert notes[5]['topics'] is None assert notes[5]['createdAt'] assert notes[5]['updatedAt'] is None assert notes[5]['read'] is False # Legacy E&I notes assert notes[6]['id'] == '11667051-151620' assert notes[6]['sid'] == '11667051' assert notes[6]['body'] is None assert notes[6]['author']['uid'] == '1133398' assert notes[6]['author']['name'] == 'Charlie Christian' assert notes[6]['topics'] == ['Course Planning', 'Personal'] assert notes[6]['createdAt'] assert notes[6]['updatedAt'] is None assert notes[6]['read'] is False # Non-legacy note boa_created_note = next( (n for n in notes if n['id'] == mock_advising_note.id), None) assert boa_created_note['id'] assert boa_created_note['author'][ 'uid'] == mock_advising_note.author_uid assert boa_created_note['sid'] == '11667051' assert boa_created_note[ 'subject'] == 'In France they kiss on main street' assert 'My darling dime store thief' in boa_created_note['body'] assert boa_created_note['category'] is None assert boa_created_note['subcategory'] is None assert boa_created_note['appointmentId'] is None assert boa_created_note['createdBy'] is None assert boa_created_note['createdAt'] assert boa_created_note['updatedBy'] is None assert boa_created_note['updatedAt'] is None assert boa_created_note['read'] is False assert boa_created_note['topics'] == [] assert len(boa_created_note['attachments']) == 1
def test_get_advising_notes(self, app, mock_advising_note, fake_auth): fake_auth.login(coe_advisor) notes = get_advising_notes('11667051') # Legacy SIS notes assert notes[0]['id'] == '11667051-00001' assert notes[0]['sid'] == '11667051' assert notes[0]['body'] == 'Brigitte is making athletic and moral progress' assert notes[0]['category'] == 'Quick Question' assert notes[0]['subcategory'] == 'Hangouts' assert notes[0]['appointmentId'] is None assert notes[0]['createdBy'] is None assert parse(notes[0]['createdAt']) == parse('2017-10-31T12:00:00+00:00') assert notes[0]['updatedBy'] is None assert notes[0]['updatedAt'] is None assert notes[0]['read'] is False assert notes[0]['topics'] == ['God Scéaw'] assert notes[0]['legacySource'] == 'SIS' assert notes[1]['id'] == '11667051-00002' assert notes[1]['sid'] == '11667051' assert notes[1]['body'] == 'Brigitte demonstrates a cavalier attitude toward university requirements' assert notes[1]['category'] == 'Evaluation' assert notes[1]['subcategory'] == '' assert notes[1]['appointmentId'] is None assert notes[1]['createdBy'] is None assert parse(notes[1]['createdAt']) == parse('2017-11-01T12:00:00+00') assert notes[1]['updatedBy'] is None assert notes[1]['updatedAt'] is None assert notes[1]['read'] is False assert notes[1]['topics'] == ['Earg Scéaw', 'Ofscéaw'] assert notes[1]['legacySource'] == 'SIS' # Legacy ASC note without subject/body assert notes[4]['id'] == '11667051-139362' assert notes[4]['sid'] == '11667051' assert notes[4]['subject'] is None assert notes[4]['body'] is None assert notes[4]['author']['uid'] == '1133399' assert notes[4]['author']['name'] == 'Lemmy Kilmister' assert notes[4]['topics'] == ['Academic', 'Other'] assert notes[4]['createdAt'] assert notes[4]['updatedAt'] is None assert notes[4]['read'] is False assert notes[4]['legacySource'] == 'ASC' # Legacy ASC note with subject/body assert notes[5]['id'] == '11667051-139379' assert notes[5]['sid'] == '11667051' assert notes[5]['subject'] == 'Ginger Baker\'s Air Force' assert notes[5]['body'] == 'Bands led by drummers tend to leave a lot of space for drum solos' assert notes[5]['author']['uid'] == '90412' assert notes[5]['author']['name'] == 'Ginger Baker' assert notes[5]['topics'] is None assert notes[5]['createdAt'] assert notes[5]['updatedAt'] is None assert notes[5]['read'] is False assert notes[5]['legacySource'] == 'ASC' # Legacy Data Science notes assert notes[6]['id'] == '11667051-20181003051208' assert notes[6]['sid'] == '11667051' assert notes[6]['body'] == 'Data that is loved tends to survive.' assert notes[6]['author']['email'] == '*****@*****.**' assert notes[6]['createdAt'] == '2018-10-04T00:12:08+00:00' assert notes[6]['topics'] == ['Declaring the major', 'Course planning', 'Domain Emphasis'] assert notes[6]['legacySource'] == 'Data Science' # Legacy E&I notes assert notes[8]['id'] == '11667051-151620' assert notes[8]['sid'] == '11667051' assert notes[8]['body'] is None assert notes[8]['author']['uid'] == '1133398' assert notes[8]['author']['name'] == 'Charlie Christian' assert notes[8]['topics'] == ['Course Planning', 'Personal'] assert notes[8]['createdAt'] assert notes[8]['updatedAt'] is None assert notes[8]['read'] is False assert notes[8]['legacySource'] == 'CE3' # Non-legacy note boa_created_note = next((n for n in notes if n['id'] == mock_advising_note.id), None) assert boa_created_note['id'] assert boa_created_note['author']['uid'] == mock_advising_note.author_uid assert boa_created_note['sid'] == '11667051' assert boa_created_note['subject'] == 'In France they kiss on main street' assert 'My darling dime store thief' in boa_created_note['body'] assert boa_created_note['category'] is None assert boa_created_note['subcategory'] is None assert boa_created_note['appointmentId'] is None assert boa_created_note['createdBy'] is None assert boa_created_note['createdAt'] assert boa_created_note['updatedBy'] is None assert boa_created_note['updatedAt'] is None assert boa_created_note['read'] is False assert boa_created_note['topics'] == [] assert len(boa_created_note['attachments']) == 1 assert 'legacySource' not in boa_created_note