def test_handle_extra_filters(teacher): new_user = User.create(email="[email protected]", password="******", name="absolutely", area="nope") student = Student.create(teacher=teacher, creator=teacher.user, user=new_user) def custom_filter(model, key, value): return getattr(model, key) == value extra_filters = {User: {"area": custom_filter}} new_student = Student._handle_extra_filters( query=Student.query, args={ "area": "npe" }, extra_filters=extra_filters).first() assert not new_student new_student = Student._handle_extra_filters( query=Student.query, args={ "area": "nope" }, extra_filters=extra_filters).first() assert new_student == student
def get_data(data: dict, user: User, appointment: Optional[Appointment] = None) -> dict: """get request data and a specific user - we need the user because we are not decorated in login_required here returns dict of new lesson or edited lesson""" try: date = datetime.strptime(data.get("date"), DATE_FORMAT).replace( second=0, microsecond=0 ) except (ValueError, TypeError): raise RouteError("Date is not valid.") if appointment: type_ = appointment.type else: type_ = None duration = data.get("duration") if not duration: raise RouteError("Duration is required.") duration = int(duration) if user.student: student = user.student teacher = user.student.teacher type_ = type_ or AppointmentType.LESSON if date < datetime.utcnow(): # trying to add a new lesson in the past?? raise RouteError("Date is not valid.") check_available_hours_for_student(date, student, appointment, duration) elif user.teacher: type_ = getattr( AppointmentType, data.get("type", "").upper(), type_ or AppointmentType.LESSON, ) handle_teacher_hours(user.teacher, date, duration, type_, appointment) teacher = user.teacher student = Student.get_by_id(data.get("student_id")) if not student: raise RouteError("Student does not exist.") else: raise RouteError("Not authorized.", 401) meetup, dropoff = handle_places(data, student, appointment) try: price = int(data.get("price", "")) except ValueError: price = None return { "date": date, "meetup_place": meetup, "dropoff_place": dropoff, "student": student, "teacher": teacher, "duration": duration, "price": price, "comments": data.get("comments"), "is_approved": True if user.teacher else False, "type": type_, }
def test_invalid_update_topics(auth, meetup, dropoff, teacher, requester, topic, student_id, topics, error): auth.login(email=teacher.user.email) date = tomorrow.replace(hour=13, minute=00) student = Student.get_by_id(student_id) if student_id else None lesson = create_lesson(teacher, student, meetup, dropoff, date) resp = requester.post(f"/appointments/{lesson.id}/topics", json={"topics": topics}) assert resp.status_code == 400 assert resp.json["message"] == error
def deactivate(student_id): student = Student.get_by_id(student_id) if not student: raise RouteError("Student does not exist.", 404) if student.teacher != current_user.teacher: raise RouteError("Not authorized.", 401) student.update(is_active=False) return {"data": student.to_dict()}
def delete_student(student_id): student = Student.get_by_id(student_id) if not student: raise RouteError("Student does not exist.", 404) if student.appointments.first(): # if any lessons exist raise RouteError("Can't delete student.") if current_user != student.teacher.user: raise RouteError("Not authorized.", 401) student.delete() return {"message": "Student deleted."}
def students(): """allow filtering by name / area of student, and sort by balance, lesson number""" try: query = current_user.teacher.students args = flask.request.args extra_filters = {User: {"name": like_filter, "area": like_filter}} return Student.filter_and_sort(args, query, extra_filters=extra_filters, with_pagination=True) except ValueError: raise RouteError("Wrong parameters passed.")
def test_students(auth, teacher, requester): new_user = User.create( email="[email protected]", password="******", name="absolutely", area="nope" ) new_student = Student.create(teacher=teacher, creator=teacher.user, user=new_user) auth.login(email=teacher.user.email) resp = requester.get("/teacher/students?order_by=balance desc") assert resp.json["data"][1]["student_id"] == new_student.id resp = requester.get("/teacher/students?name=solut") assert resp.json["data"][0]["student_id"] == new_student.id resp = requester.get("/teacher/students?name=le:no way") assert not resp.json["data"] resp = requester.get("/teacher/students?limit=1") assert len(resp.json["data"]) == 1
def test_delete_student(auth, requester, student, teacher): auth.login(email=teacher.user.email) resp = requester.delete(f"/student/{student.id}") assert "Can't delete" in resp.json["message"] student_user = User.create(email="*****@*****.**", password="******", name="student", area="test") new_student = Student.create(user=student_user, teacher=teacher, creator=teacher.user, is_approved=True) resp = requester.delete(f"/student/{new_student.id}") assert "deleted" in resp.json["message"]
def approve(student_id): student = Student.get_by_id(student_id) if not student: raise RouteError("Student does not exist.", 404) if current_user != student.creator and ( current_user.teacher == student.teacher or current_user.student == student or current_user.is_admin): # only allow approving for the user himself or # the teacher that is requested. don't allow for the requester to approve. student.update(is_approved=True) return {"data": student.to_dict()} raise RouteError("Not authorized.", 401)
def make_student(): data = flask.request.args user = current_user teacher = Teacher.get_by_id(data.get("teacher_id")) if current_user.teacher: user = User.get_by_id(data.get("user_id")) teacher = current_user.teacher if not user: raise RouteError("User was not found.", 401) if user.teacher or user.student: raise RouteError("User is already a student or a teacher.") if not teacher: raise RouteError("Teacher was not found.") try: price = int(data.get("price", "")) except ValueError: price = None student = Student.create(user=user, teacher=teacher, creator=current_user, price=price) # send notification user_to_send_to = student.user body_text = gettext("%(teacher)s added you as a student!", teacher=teacher.user.name) if student.creator == user_to_send_to: user_to_send_to = teacher.user body_text = gettext("%(student)s added you as a teacher!", student=student.user.name) if user_to_send_to.firebase_token: logger.debug(f"sending fcm to {user_to_send_to}") try: FCM.notify( token=user_to_send_to.firebase_token, title=gettext("Join Request"), body=body_text, ) except: pass return {"data": student.to_dict()}, 201
def create_bot_student(): teacher = current_user.teacher data = flask.request.values user = create_user_from_data(data, required=["email", "name", "phone"]) car = teacher.cars.filter_by(id=data.get("car_id")).first() if not car: raise RouteError("Car does not exist.") try: price = int(data.get("price", "")) except ValueError: price = None student = Student.create( user=user, teacher=teacher, creator=current_user, price=price, car=car, is_approved=True, ) return {"data": student.user.to_dict()}, 201
def topics(student_id: int): """show topics by: finished, unfinished or haven't started""" student = Student.get_by_id(student_id) if not student: raise RouteError("Student does not exist.", 404) finished_topics = [ topic.to_dict() for topic in student.topics(is_finished=True) ] in_progress_topics = [ topic.to_dict() for topic in student.topics(is_finished=False) ] new_topics = [ topic.to_dict() for topic in Topic.query.all() if topic.to_dict() not in in_progress_topics and topic.to_dict() not in finished_topics ] return { "data": { "finished": finished_topics, "in_progress": in_progress_topics, "new": new_topics, } }
def add_payment(): data = flask.request.get_json() student = Student.get_by_id(data.get("student_id")) amount = data.get("amount") details = data.get("details") if not student: raise RouteError("Student does not exist.") if not amount: raise RouteError("Amount must not be empty.") if not details: raise RouteError("Details must not be empty.") payment = Payment.create( teacher=current_user.teacher, student=student, amount=amount, payment_type=getattr(PaymentType, data.get("payment_type", ""), 1), details=details, crn=int(data.get("crn")) if data.get("crn") else None, ) # send notification to student if student.user.firebase_token: logger.debug(f"sending fcm to {student.user} for new payment") try: FCM.notify( token=student.user.firebase_token, title=gettext("New Payment"), body=gettext( "%(user)s charged you for %(amount)s", user=current_user.name, amount=amount, ), ) except NotificationError: pass return {"data": payment.to_dict()}, 201
def edit_student(student_id): student = Student.get_by_id(student_id) if not student: raise RouteError("Student does not exist.", 404) if (current_user.teacher and student.teacher == current_user.teacher) or ( current_user.student and current_user.student == student): data = flask.request.values image = flask.request.files.get("green_form") extra_data = dict() if (current_user.teacher ): # only teacher is allowed to edit num of lessons and theory try: price = int(data.get("price", "")) except ValueError: price = None car = current_user.teacher.cars.filter_by( id=data.get("car_id")).first() if not car: raise RouteError("Car does not exist.") extra_data = dict( theory=data.get("theory", False) == "true", number_of_old_lessons=float( data.get("number_of_old_lessons", 0)), car=car, price=price, ) if image: extra_data["green_form"] = upload(image)["public_id"] student.update(doctor_check=data.get("doctor_check", False) == "true", eyes_check=data.get("eyes_check", False) == "true", id_number=data.get("id_number"), **extra_data) return {"data": student.user.to_dict()} raise RouteError("Not authorized.", 401)
def setup_db(app): User.create(email="*****@*****.**", password="******", name="test", area="test", phone="044444444") User.create( email="*****@*****.**", password="******", name="admin", area="test", is_admin=True, phone="055555555", ) teacher_user = User.create(email="*****@*****.**", password="******", name="teacher", area="test") teacher = Teacher.create( user=teacher_user, price=100, lesson_duration=40, is_approved=True, crn=999999999, invoice_api_key=DEMO_API_KEY, ) Car.create(teacher=teacher, number=1111111111) student_user = User.create(email="*****@*****.**", password="******", name="student", area="test") student = Student.create(user=student_user, teacher=teacher, creator=teacher.user, is_approved=True) meetup = Place.create( description="test", used_as=PlaceType.meetup.value, student=student, google_id="ID1", ) dropoff = Place.create( description="test", used_as=PlaceType.dropoff.value, student=student, google_id="ID2", ) WorkDay.create( teacher=teacher, day=1, from_hour=0, to_hour=23, to_minutes=59, on_date=(datetime.utcnow() + timedelta(days=2)).date(), ) # 2 days from now Topic.create(title="topic test", min_lesson_number=1, max_lesson_number=5) Appointment.create( teacher=teacher, student=student, # schedule to 5 days from now to it won't bother with no test creator=teacher.user, duration=40, date=(datetime.utcnow() + timedelta(days=5)), meetup_place=meetup, dropoff_place=dropoff, )