Example #1
0
def show_student_profile(username):
    '''查看学生的个人信息

    :参数 username:学生的用户名'''
    student = User.query.filter_by(username=username).first()
    if student:
        tab = request.args.get('tab','',type=str)
        if tab == 'lessons':
            lessons = student.lessons.filter_by(is_delete=False).order_by(Lesson.time.desc()).all()
            for lesson in lessons:
                lesson.teacher = User.query.get(lesson.teacher_id)
                lesson.localtime = get_localtime(lesson.time,current_user)
                # 开课十分钟前,课程是可以取消的
                if lesson.time>datetime.utcnow()+timedelta(0,600):
                    lesson.cancel = True
                else:
                    lesson.cancel = False
            return render_template('administrator/student_profile.html',student=student,tab=tab,lessons=lessons,username=username)
        elif tab == 'profile':
            teacher_id = student.student_profile.first().teacher_id
            if teacher_id:
                student.teacher = User.query.get(teacher_id)
            else:
                student.teacher = None
            student.localsince = get_localtime(student.member_since,current_user)
            student_country=student.timezone
            if len(student_country)>2:
                student.timezone_str = country_timezones[student_country[:2]][int(student_country[-1])]
            else:
                student.timezone_str = country_timezones[student_country][0]
            
            return render_template('administrator/student_profile.html',student=student,tab=tab,username=username)
Example #2
0
def check_detail(lesson_id):
    lesson = Lesson.query.get_or_404(lesson_id)
    status_dict = {'Complete':'正常完成','Tea Absent':'教师缺勤','Stu Absent':'学生缺勤','Tea Late':'教师迟到'}
    #添加中文描述的课时完成状态
    lesson.c_status = status_dict[lesson.status]
    #添加本节课的教师对象
    teacher = User.query.get(lesson.teacher_id)
    lesson.teacher = teacher
    #添加用户以用户时区为标准的上课时间对象
    lesson.localtime = get_localtime(lesson.time,current_user)
    record = lesson.lesson_record.first()
    return render_template('administrator/check_detail.html',lesson=lesson,record=record)
Example #3
0
def personal_info():
    '''协管员的个人信息,主要是为了修改自己的时区信息'''
    form = PersonalInfoForm()
    if form.validate_on_submit():
        user = current_user._get_current_object()
        user.name = form.name.data
        user.location = form.location.data
        user.timezone = form.timezone.data
        db.session.add(user)
        flash('成功修改个人信息')
        return redirect(url_for('moderator.personal_info'))
    form.email.data = current_user.email
    form.username.data = current_user.username
    form.name.data = current_user.name
    form.location.data = current_user.location
    form.timezone.data = current_user.timezone
    local_member_since = get_localtime(current_user.member_since, current_user)
    form.member_since.data = local_member_since.strftime('%Y-%m-%d')
    return render_template('moderator/personal_info.html', form=form)
Example #4
0
def modify_schedule(username, time_type):
    '''根据协管员提交的教师用户名和要修改的时间类型来处理
    :参数 username:教师的用户名
    :参数 time_type:要修改的时间类型
    '''
    teacher = User.query.filter_by(username=username, is_delete=False).first()
    if teacher:
        # 设置临时休息时间
        if time_type == '1':
            form = RestTimeForm()
            if form.validate_on_submit():
                available_start = datetime.utcnow() + timedelta(1)
                if form.end.data <= form.start.data or form.start.data < available_start:
                    flash('起始时间或结束时间有误')
                    return redirect(
                        url_for('moderator.modify_schedule',
                                username=username,
                                time_type=time_type))
                else:
                    # 保存到数据库里,假设开始时间是9点,结束时间是11点
                    # 那就要保存9点和10点这两个时间点
                    time = form.start.data
                    end = form.end.data
                    while time < end:
                        naive_utctime = get_utctime(time, current_user)
                        sr = SpecialRest.query.filter_by(
                            rest_time=naive_utctime,
                            teacher_id=teacher.id,
                            type=form.rest_type.data).first()
                        if not sr:
                            sr = SpecialRest()
                            sr.rest_time = naive_utctime
                            sr.teacher_id = teacher.id
                            sr.type = form.rest_type.data
                        sr.expire = False
                        db.session.add(sr)
                        time = time + timedelta(seconds=3600)
                    flash('休息时间设置成功')
                    return redirect(
                        url_for('moderator.modify_schedule',
                                username=username,
                                time_type='4'))
            form.teacher.data = teacher.name
            return render_template('moderator/modify_schedule.html',
                                   form=form,
                                   username=username,
                                   time_type=time_type)
        # 设置临时的补班时间
        elif time_type == '2':
            form = MakeupTimeForm()
            if form.validate_on_submit():
                available_start = datetime.utcnow() + timedelta(1)
                if form.end.data <= form.start.data or form.start.data < available_start:
                    flash('起始时间或结束时间有误')
                    return redirect(
                        url_for('moderator.modify_schedule',
                                username=username,
                                time_type=time_type))
                else:
                    # 把数据保存到数据库里面
                    time = form.start.data
                    end = form.end.data
                    while time < end:
                        naive_utctime = get_utctime(time, current_user)
                        mt = MakeUpTime.query.filter_by(
                            make_up_time=naive_utctime,
                            teacher_id=teacher.id).first()
                        if not mt:
                            mt = MakeUpTime()
                            mt.make_up_time = naive_utctime
                            mt.teacher_id = teacher.id
                        mt.expire = False
                        db.session.add(mt)
                        time = time + timedelta(seconds=3600)
                    flash('补班时间设置成功')
                    return redirect(
                        url_for('moderator.modify_schedule',
                                username=username,
                                time_type='5'))
            form.teacher.data = teacher.name
            return render_template('moderator/modify_schedule.html',
                                   form=form,
                                   username=username,
                                   time_type=time_type)
        # 修改老师的常规工作时间
        elif time_type == '3':
            # 查询这位老师的工作时间,它们是UTC时间,还要转化为协管员时区的时间
            if teacher.word_time.first():
                worktime = teacher.work_time.first().work_time
                worktime_list = worktime.split(';')
            else:
                worktime_list = []

            # 让每个星期从星期天开始
            cal = Calendar(6)
            # 随便获取一个完整的naive的星期的日期
            week = cal.monthdatescalendar(2020, 2)[0]
            # 获取utc时区对象
            utc = timezone('UTC')
            # 获取协管员时区对象
            moderator_country = current_user.timezone
            if len(moderator_country) > 2:
                moderator_tz = country_timezones[moderator_country[:2]][int(
                    moderator_country[-1])]
            else:
                moderator_tz = country_timezones[moderator_country][0]
            tz_obj = timezone(moderator_tz)
            # 用来存放按照这个星期来看,用户视角的上课时间(年月日小时)
            temp = []
            for w in worktime_list:
                date = week[int(w[0])]
                time = datetime(date.year,
                                date.month,
                                date.day,
                                int(w[2:]),
                                tzinfo=utc)
                time = time.astimezone(tz_obj)
                temp.append(time)
            # datetime里的6代表星期天,也就是我定义的0,这里用一个字典来保存这种映射关系
            weekday_map = {6: 0, 0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6}
            # 清空worktime_list列表,用于存储用户视角的常规工作时间
            worktime_list = []
            for time in temp:
                # 依然要把每个工作时间点变成0-1的形式,存进列表
                worktime_list.append(
                    str(weekday_map[time.weekday()]) + '-' + str(time.hour))
            return render_template('moderator/modify_schedule.html',
                                   username=username,
                                   time_type=time_type,
                                   teacher=teacher,
                                   worktime_list=worktime_list)
        # 取消休息
        elif time_type == '4':
            special_rest_list = teacher.special_rest.filter_by(
                expire=False).order_by(SpecialRest.rest_time.asc()).all()
            for sr in special_rest_list:
                sr.localtime = get_localtime(sr.rest_time, current_user)
            return render_template('moderator/modify_schedule.html',
                                   username=username,
                                   time_type=time_type,
                                   special_rest_list=special_rest_list,
                                   teacher=teacher)
        # 取消补班
        elif time_type == '5':
            makeup_time_list = teacher.make_up_time.filter_by(
                expire=False).order_by(MakeUpTime.make_up_time.asc()).all()
            for mt in makeup_time_list:
                mt.localtime = get_localtime(mt.make_up_time, current_user)
            return render_template('moderator/modify_schedule.html',
                                   username=username,
                                   time_type=time_type,
                                   makeup_time_list=makeup_time_list,
                                   teacher=teacher)
        else:
            flash('修改时间类型有误')
            return redirect(url_for('main.personal_center'))
    flash('教师不存在')
    return redirect(url_for('main.personal_center'))
Example #5
0
def book_lesson(student_username, teacher_username):
    teacher = User.query.filter_by(username=teacher_username,
                                   role_id=3,
                                   is_delete=False).first()
    student = User.query.filter(User.username == student_username,
                                User.is_delete == False).first()
    if teacher and (student.role_id == 1 or student.role_id == 2):
        #取出老师的工作时间字符串并转化为列表
        worktime = teacher.work_time.first().work_time
        worktime_list = worktime.split(';')

        #把以星期为单位的教师工作时间转化为UTC年月日小时的时间
        #第一步:构造出UTC的此时此刻
        cal = Calendar(6)  # 让每个星期都从星期天开始
        utc = timezone('UTC')
        utcnow = datetime.utcnow()
        utcnow = datetime(utcnow.year,
                          utcnow.month,
                          utcnow.day,
                          utcnow.hour,
                          tzinfo=utc)
        # 第二步:计算出可以选课的起始时间,也就是此时此刻的24小时后,以及截至时间,也就是现在开始的29天后
        available_start = utcnow + timedelta(1)
        available_end = utcnow + timedelta(29)
        # 第三步:找到起始日期和结束日期所在的星期,拼接出可以选课的28天的列表,
        # 大列表里的小列表代表一个个以周日开始的星期
        start_flag = False
        all_available_dates = []
        for week in cal.monthdatescalendar(available_start.year,
                                           available_start.month):
            # 在没找到起始日期所在的星期的时候,要检查这个星期是否就是我们寻找的
            if not start_flag and available_start.date() in week:
                start_flag = True
            # 从找到了起始日期所在的星期开始,我们要把它所在的以及它后面的星期加到列表里
            if start_flag:
                all_available_dates.append(week)
        # 遍历结束日期所在的月,如果当前星期不在列表里,就添加(因为前后两个月可能有重复的星期)
        # 遇到结束日期所在的星期,后面的就不用看了
        for week in cal.monthdatescalendar(available_end.year,
                                           available_end.month):
            if available_end not in week:
                all_available_dates.append(week)
            if available_end.date() in week:
                break
        # 第四步:根据老师的工作时间,构造出以datetime对象为元素的列表
        # 创建一个空列表,存放老师的以小时为单位的工作时间
        new_worktime_list = []
        for week in all_available_dates:
            # w是类似于0-1这样的字符串,它表示星期天的UTC时间1点钟
            for w in worktime_list:
                date = week[int(w[0])]
                time = datetime(date.year,
                                date.month,
                                date.day,
                                int(w[2:]),
                                tzinfo=utc)
                if time < available_start or time > available_end:
                    continue
                new_worktime_list.append(time)

        # 第五步:把教师的特殊休息时间去掉
        special_rest_set = set()
        temp = teacher.special_rest.filter_by(expire=False).all()
        for data in temp:
            rest_time = datetime(data.rest_time.year,
                                 data.rest_time.month,
                                 data.rest_time.day,
                                 data.rest_time.hour,
                                 tzinfo=utc)
            if rest_time >= available_start:
                special_rest_set.add(rest_time)
            else:
                data.expire = True
                db.session.add(data)
        for i in new_worktime_list[:]:
            if i in special_rest_set:
                new_worktime_list.remove(i)

        # 第六步:把教师的补班时间加进去(这一步要放在前面,因为可能补班的时间也被选上课了)
        makeup_time_list = []
        temp = teacher.make_up_time.filter_by(expire=False).all()
        for data in temp:
            makeup_time = datetime(data.make_up_time.year,
                                   data.make_up_time.month,
                                   data.make_up_time.day,
                                   data.make_up_time.hour,
                                   tzinfo=utc)
            if makeup_time >= available_start:
                makeup_time_list.append(makeup_time)
            # 把已经过期的补班时间的expire字段修改为True
            else:
                data.expire = True
                db.session.add(data)
        new_worktime_list += makeup_time_list

        # 第七步:生成一个已预约的课程时间列表,并把这些时间从老师的工作时间里去掉
        # 为了节约资源,我们在查询的时候就筛选一下时间
        lessons = Lesson.query.filter(
            Lesson.teacher_id == teacher.id, Lesson.is_delete == False,
            Lesson.time >= datetime.utcnow() + timedelta(1)).all()
        # 先用set存放时间,因为查询比较快
        lessons_set = set()
        for lesson in lessons:
            time = lesson.time
            time = datetime(time.year,
                            time.month,
                            time.day,
                            time.hour,
                            tzinfo=utc)
            lessons_set.add(time)
        for i in new_worktime_list[:]:
            if i in lessons_set:
                new_worktime_list.remove(i)
        lessons_list = list(lessons_set)

        #计算出协管员的时区
        visitor_country = current_user.timezone
        if len(visitor_country) > 2:
            visitor_tz = country_timezones[visitor_country[:2]][int(
                visitor_country[-1])]
        else:
            visitor_tz = country_timezones[visitor_country][0]
        tz_obj = timezone(visitor_tz)

        # 根据时区,生成协管员视角的可以选课的28天的日历
        visitor_start = get_localtime(available_start, current_user)
        visitor_end = get_localtime(available_end, current_user)

        visitor_dates = []
        start_flag = False
        for week in cal.monthdatescalendar(visitor_start.year,
                                           visitor_start.month):
            # 因为遍历一个星期也会浪费时间,所以我们这里设两个条件
            # 如果flag已经是True了,就不需要再看结束日期在不在这个星期里了
            if not start_flag and visitor_start.date() in week:
                start_flag = True
            if start_flag:
                visitor_dates.append(week)
        # 因为前后两个月可能有重复的星期,所以要判断是否在列表里,不在的才添加
        for week in cal.monthdatescalendar(visitor_end.year,
                                           visitor_end.month):
            if week not in visitor_dates:
                visitor_dates.append(week)
            # 如果已经到了结束日期所在的星期,就不用看后面的了
            if visitor_end.date() in week:
                break

        # 获取页码
        page = request.args.get('page', 1, type=int)
        # 如果有用户恶意修改页码,我们要把页码变成1
        if page > len(visitor_dates) or page < 1:
            page = 1

        # 每个星期的月份和年,应该以这个星期中间的那一天为标准
        current_page = Pagination(visitor_dates, page, 1, len(visitor_dates),
                                  visitor_dates[page - 1])
        middle_day = current_page.items[3]
        month_name = calendar.month_name[middle_day.month]
        year = middle_day.year

        this_week = []
        only_dates = []

        for date in current_page.items:
            this_week.append('%s-%s-%s' % (date.year, date.month, date.day))
            only_dates.append(date.day)

        #把老师的可选的时间列表换成协管员时区的时间(字符串)
        for i, time in enumerate(new_worktime_list):
            time = time.astimezone(tz_obj)
            new_worktime_list[i] = '%s-%s-%s-%s' % (time.year, time.month,
                                                    time.day, time.hour)
        #把老师有课的时间转换成协管员时区的时间(字符串)
        for i, time in enumerate(lessons_list):
            time = time.astimezone(tz_obj)
            lessons_list[i] = '%s-%s-%s-%s' % (time.year, time.month, time.day,
                                               time.hour)

        # 处理ajax请求
        time = request.form.get('time', '', type=str)
        if time:
            time = time.split('-')
            #先构造一个没有时区的datetime对象
            time = datetime(int(time[0]), int(time[1]), int(time[2]),
                            int(time[3]))
            #再把它变成时区为协管员所在地区的datetime对象
            time = tz_obj.localize(time)
            #再把时区变成utc时区
            time = time.astimezone(utc)

            # 再判断一次是否在可选时间范围内
            if time >= available_start:
                # 如果该用户是学生,需要操作课时包里的剩余课时
                if student.role_id == 2:
                    active_package = student.orders.filter(
                        Order.pay_status == 'paid',
                        Order.left_amount > 0).order_by(
                            Order.pay_time.asc()).first()
                    if active_package:
                        # 课时包的课程数量扣掉一节
                        active_package.left_amount -= 1
                        db.session.add(active_package)
                        # 把选课信息存进数据库
                        lesson = student.lessons.filter(
                            Lesson.time == time,
                            Lesson.teacher_id == teacher.id).first()
                        if lesson:
                            lesson.is_delete = False
                        else:
                            lesson = Lesson()
                            lesson.student_id = student.id
                            lesson.teacher_id = teacher.id
                            lesson.time = time
                            lesson.message = ''
                            lesson.lesson_type = active_package.lesson_type
                        db.session.add(lesson)
                        msg = "您已经成功地为学生%s选了一节%s老师的%s课" % (
                            student.username, teacher.name,
                            active_package.lesson_type)
                        return jsonify({'status': 'ok', 'msg': msg})
                    else:
                        return jsonify({
                            'status': 'ok',
                            'msg': '该生已经没有剩余课时,请联系该生购买课时包'
                        })
                # 如果该用户是游客,需要查看是否已经上过试听课
                elif student.role_id == 1:
                    #如果该游客已经有一节试听课记录了,并且那节试听课是完成或者还未开始的状态,不允许他再次选择试听课
                    trial = Lesson.query.filter_by(
                        student_id=student.id, lesson_type='Trial').order_by(
                            Lesson.time.desc()).first()
                    if trial and (trial.status == 'Complete'
                                  or trial.status == 'Not started'):
                        return jsonify({
                            'status': 'fail',
                            'msg': "该生已经正常完成一节试听课,或正在等待一节试听课开始,不能再选"
                        })
                    else:
                        # 先看看学生之前是否已经选过同一时间同一老师的试听课了
                        lesson = student.lessons.filter(
                            Lesson.time == time,
                            Lesson.teacher_id == teacher.id).first()
                        if lesson:
                            lesson.is_delete = False
                        else:
                            lesson = Lesson()
                            lesson.student_id = student.id
                            lesson.teacher_id = teacher.id
                            lesson.time = time
                            lesson.message = ''
                            lesson.lesson_type = 'Trial'
                        db.session.add(lesson)
                        msg = "您已经成功为学生%s选了一节%s老师的试听课" % (student.username,
                                                          teacher.username)
                        return jsonify({'status': 'ok', 'msg': msg})
            else:
                return jsonify({'status': 'fail', 'msg': '您需要至少提前24小时选课'})
        return render_template('moderator/book_lesson.html',
                               student=student,
                               teacher=teacher,
                               this_week=this_week,
                               only_dates=only_dates,
                               new_worktime_list=new_worktime_list,
                               month_name=month_name,
                               year=year,
                               current_page=current_page,
                               lessons_list=lessons_list)

    else:
        flash('学生或老师有误')
        return redirect(url_for('moderator.pre_book_lesson'))
Example #6
0
def my_students():
    '''这是我的所有学生的视图'''
    username = request.args.get('username','',type=str)
    student = []
    lessons = []
    primary_teacher = []
    tab = request.args.get('tab','',type=str)
    #如果有用户名,就要查看某个学生的信息,否则就查看该教师的所有学生
    if username:
        student = User.query.filter_by(username=username).first()
        tz = current_user.timezone
        if len(tz) == 2:
            tz_str = country_timezones[tz][0]
        else:
            tz_str = country_timezones[tz[:2]][int(tz[3:])]
        tz = timezone(tz_str)
        utc = timezone('UTC')
        #查看该学生的所有课程
        if tab == 'lessons':
            lessons = student.lessons.filter_by(is_delete=False).order_by(Lesson.time.desc()).all()
            
            #给每节课添加教师信息,以及根据教师时区转化出的教师当地的上课时间
            for lesson in lessons:
                teacher = User.query.get(lesson.teacher_id)
                lesson.teacher = teacher
                utctime = datetime(lesson.time.year,lesson.time.month,lesson.time.day,lesson.time.hour,tzinfo=utc)
                localtime = utctime.astimezone(tz)
                lesson.localtime = localtime
        #查看该学生的个人信息
        elif tab == 'profile':
            member_since = student.member_since
            utcsince = datetime(member_since.year,member_since.month,member_since.day,member_since.hour,tzinfo=utc)
            localsince = utcsince.astimezone(tz)
            student.localsince = localsince
            student.timezone_str = tz_str
            teacher_id = student.student_profile.first().teacher_id
            primary_teacher = User.query.get(teacher_id)
        return render_template('teacher/my_students.html',username=username,student=student,tab=tab,lessons=lessons,primary_teacher=primary_teacher)
    #如果没有用户名,那就查询我的所有学生
    student_profiles = StudentProfile.query.filter_by(teacher_id=current_user.id).all()
    students=[]
    for profile in student_profiles:
        # 通过学生简历找到学生用户
        student = profile.student
        # 先把全部已支付的课时包的query对象查出来,一会儿要多次使用
        all_packages = student.orders.filter(Order.pay_status=='paid')
        # 查询该学生的课时类型
        active_packages = all_packages.filter(Order.left_amount>0).order_by(Order.id.asc()).all()
        # 如果有活跃课时包(里面还有剩余课时的课时包),那学生的课时类型就是最老的课时包的类型
        if active_packages:
            lesson_type = active_packages[0].lesson_type
        # 如果没有活跃课时包,那学生的课时类型就是最新的已完成的课时包的类型
        else:
            lesson_type = all_packages.order_by(Order.id.desc()).first().lesson_type
        student.lesson_type = lesson_type

        # 查询该学生的全部课时数和全部剩余课时数
        all_packages = all_packages.all()
        total_lessons = 0
        total_left = 0
        for package in all_packages:
            total_lessons += package.lesson_amount
            total_left += package.left_amount
        student.total_left = total_left
        student.total_finished = total_lessons-total_left
        if student.last_seen:
            local_last_seen = get_localtime(student.last_seen,current_user)
        else:
            local_last_seen = None
        student.local_last_seen = local_last_seen
        students.append(student)
    return render_template('teacher/my_students.html',students=students)
Example #7
0
def record_lesson(id):
    '''这是填写课程详情的视图'''
    lesson = Lesson.query.get_or_404(id)
    lesson.localtime = get_localtime(lesson.time,current_user)
    
    form = RecordLessonForm()
    # 可能是修改,也可能是新建
    record = lesson.lesson_record.first() or LessonRecord()
    if not record.lesson_id:
        record.lesson_id = lesson.id
    if form.validate_on_submit():
        record.talk = form.talk.data
        record.this_lesson = form.this_lesson.data
        record.next_lesson = form.next_lesson.data
        record.homework = form.homework.data
        record.textbook = form.textbook.data
        record.other = form.other.data
        
        # 选课的时候已经扣了课时,而一般情况下,课程就是正常完成了,不需要做什么
        # 如果课程状态由Complete,Tea Late,Stu Absent,None变成了Tea Absent,那就要把课时加回来
        if lesson.status in {'Complete','Tea Late','Stu Absent',None} and form.status.data == 'Tea Absent':
            # 我们要从最新的课时包开始,找到第一个不满(也就是left_amount<lesson_amount的课时包),把还给学生的课加到这个包里
            all_packages = lesson.student.orders.filter(Order.pay_status=='paid').order_by(Order.id.desc()).all()
            for package in all_packages:
                if package.left_amount <package.lesson_amount:
                    package.left_amount += 1
                    break
            db.session.add(package)
        # 如果课程状态由Tea Absent又变成了Complete,Tea Late,Stu Absent,就说明老师一开始填错了,再把课时扣掉
        elif lesson.status == 'Tea Absent' and form.status.data in {'Complete','Tea Late','Stu Absent'}:
            current_package = lesson.student.orders.filter(Order.pay_status=='paid',Order.left_amount>0).order_by(Order.id.asc()).first()
            current_package.left_amount -= 1
            db.session.add(current_package)
        # 如果这节课的状态由None,Tea Absent或Stu Absent变成了Complete,Tea Late,更新最后一次见到学生的时间
        if lesson.status in {None,'Tea Absent','Stu Absent'} and form.status.data in {'Complete','Tea Late'}:
            if lesson.student.last_seen is None or lesson.time > lesson.student.last_seen:
                lesson.student.last_seen = lesson.time
                db.session.add(lesson.student)
        # 如果这节课的状态由Complete,Tea Late变成了Tea Absent,Stu Absent,这可能会使得最后一次见学生的时间往前推
        elif lesson.status in {'Complete','Tea Late'} and form.status.data in {'Tea Absent','Stu Absent'}:
            # 只有这节课的时间正好就是最后一次见学生的时间时,才需要修改,否则这是一节老课,不影响最后见学生的时间
            if lesson.time == lesson.student.last_seen:
                # 查询出这个学生的所有课时,降序排列
                all_lessons = lesson.student.lessons.filter(Lesson.is_delete==False).order_by(Lesson.id.desc()).all()
                for lesson_ in all_lessons:
                    # 找到离现在最近的见到学生的课时,把这个时间更新为最后见到学生的时间(注意要刨除当前这节课,所以要找的替代者的时间必须早于当前这节课)
                    if lesson_.status in {'Complete','Tea Late'} and lesson_.time<lesson.time:
                        lesson.student.last_seen = lesson_.time
                        break
                # 如果找不到这样的课时,那就说明其实学生一节课也没上,把最后见到学生的时间改为None
                else:
                    lesson.student.last_seen = None
                db.session.add(lesson.student)
        lesson.status = form.status.data
        lesson.t_comment = form.t_comment.data
        db.session.add(record)
        db.session.add(lesson)
        

        return redirect(url_for('main.personal_center'))
    
    form.talk.data = record.talk
    form.this_lesson.data = record.this_lesson
    form.next_lesson.data = record.next_lesson
    form.homework.data = record.homework
    form.textbook.data = record.textbook
    form.other.data = record.other
    form.status.data = lesson.status
    form.t_comment.data = lesson.t_comment
   
    
    return render_template('teacher/record_lesson.html',form=form,lesson=lesson)
Example #8
0
def personal_center():
    '''这是个人中心的视图,不同角色会显示不同的页面'''
    if current_user.role.name == 'Visitor':
        #查询该游客是否定过试听课
        trial_lessons = Lesson.query.filter_by(student_id=current_user.id,
                                               lesson_type='Trial').all()
        #如果定过试听课
        if trial_lessons:
            #获取游客的时区信息
            if len(current_user.timezone) == 2:
                tz = country_timezones[current_user.timezone][0]
                tz = timezone(tz)
            else:
                tz = country_timezones[current_user.timezone[:2]][int(
                    current_user.timezone[3:])]
                tz = timezone(tz)
            utc = timezone('UTC')
            #把试听课的时间转化为游客当地的时间,同时也查询出老师的对象,然后把时间和教师信息都附加到每节试听课对象上
            for lesson in trial_lessons:
                utctime = datetime(lesson.time.year,
                                   lesson.time.month,
                                   lesson.time.day,
                                   lesson.time.hour,
                                   tzinfo=utc)
                localtime = utctime.astimezone(tz)
                localtime = '%s-%s-%s %s:00' % (localtime.year,
                                                localtime.month, localtime.day,
                                                localtime.hour)
                lesson.localtime = localtime
                teacher = User.query.get(lesson.teacher_id)
                lesson.teacher = teacher

        return render_template('visitor/homepage.html',
                               trial_lessons=trial_lessons)
    elif current_user.role.name == 'Student':
        #查询出学生所有的课程
        lessons = current_user.lessons.filter_by(is_delete=False).order_by(
            Lesson.time.desc()).all()
        utc = timezone('UTC')
        tz = current_user.timezone
        if len(tz) == 2:
            tz = country_timezones[tz]
        else:
            tz = country_timezones[tz[:2]][int(tz[3:])]
        tz = timezone(tz)
        for lesson in lessons:
            lesson.teacher = User.query.get(lesson.teacher_id)
            time = lesson.time
            utctime = datetime(time.year,
                               time.month,
                               time.day,
                               time.hour,
                               tzinfo=utc)
            localtime = utctime.astimezone(tz)
            lesson.localtime = localtime
            if lesson.status == 'Not started':
                #课程开始时间距离现在还大于10分钟
                if lesson.time > datetime.utcnow() + timedelta(0, 600):
                    lesson.cancel = True
                else:
                    lesson.cancel = False
        return render_template('student/homepage.html', lessons=lessons)
    elif current_user.role.name == 'Teacher':
        #查询出24小时内老师的未开始课程
        lessons = Lesson.query.filter_by(teacher_id=current_user.id,
                                         status='Not started',
                                         is_delete=False).order_by(
                                             Lesson.time.desc()).all()
        lesson_list = []
        if lessons:
            utcnow = datetime.utcnow()
            utc = timezone('UTC')
            #获取老师的时区信息(是国家代码和数字的组合,比如CN-0)
            tz = current_user.timezone
            if len(tz) == 2:
                #获取具体的时区代码,比如Asia/Shanghai
                tz = country_timezones[tz][0]
            else:
                tz = country_timezones[tz[:2]][int(tz[3:])]
            #获取时区对象
            tz = timezone(tz)

            for lesson in lessons:
                #如果课程的时间距离现在已经大于24小时了,就跳出循环
                if lesson.time > utcnow + timedelta(1):
                    break
                #在24小时内的课都添加到列表里
                utctime = datetime(lesson.time.year,
                                   lesson.time.month,
                                   lesson.time.day,
                                   lesson.time.hour,
                                   tzinfo=utc)
                localtime = utctime.astimezone(tz)
                lesson.localtime = localtime
                lesson_list.append(lesson)

        return render_template('teacher/homepage.html',
                               lesson_list=lesson_list)
    elif current_user.role.name == 'Moderator':
        # 查找最近24小时内入学的新生
        utcnow = datetime.utcnow()
        start_time = utcnow - timedelta(1)
        new_orders = Order.query.filter(Order.pay_status == 'paid',
                                        Order.pay_time >= start_time).order_by(
                                            Order.pay_time.desc()).all()
        students = {
            order.student
            for order in new_orders
            if order.student.orders.filter_by(pay_status='paid').order_by(
                Order.pay_time.asc()).first().pay_time >= start_time
        }
        students = list(students)
        for student in students:
            teacher_id = student.student_profile.first().teacher_id
            if teacher_id:
                student.teacher = User.query.get(teacher_id)
            else:
                student.teacher = None
            student.enrollment_time = get_localtime(
                student.orders.filter_by(pay_status='paid').order_by(
                    Order.pay_time.asc()).first().pay_time, current_user)
        return render_template('moderator/homepage.html', students=students)
    elif current_user.role.name == 'Administrator':
        # 查找最近24小时内入学的新生
        utcnow = datetime.utcnow()
        start_time = utcnow - timedelta(1)
        new_orders = Order.query.filter(Order.pay_status == 'paid',
                                        Order.pay_time >= start_time).order_by(
                                            Order.pay_time.desc()).all()
        students = {
            order.student
            for order in new_orders
            if order.student.orders.filter_by(pay_status='paid').order_by(
                Order.pay_time.asc()).first().pay_time >= start_time
        }
        students = list(students)
        for student in students:
            teacher_id = student.student_profile.first().teacher_id
            if teacher_id:
                student.teacher = User.query.get(teacher_id)
            else:
                student.teacher = None
            student.enrollment_time = get_localtime(
                student.orders.filter_by(pay_status='paid').order_by(
                    Order.pay_time.asc()).first().pay_time, current_user)
        return render_template('administrator/homepage.html',
                               students=students)
Example #9
0
def book_lesson():
    '''这是学生订课的视图'''
    # 找到该学生的老师
    teacher = User.query.filter_by(
        id=current_user.student_profile.first().teacher_id).first()
    # 学生可能还没有分配老师,我们只操作分配了老师的情况
    if teacher:
        #取出老师的工作时间字符串并转化为列表
        worktime = teacher.work_time.first().work_time
        worktime_list = worktime.split(';')

        #把以星期为单位的教师工作时间转化为UTC年月日小时的时间
        #第一步:构造出UTC的此时此刻
        cal = Calendar(6)  # 让每个星期都从星期天开始
        utc = timezone('UTC')
        utcnow = datetime.utcnow()
        utcnow = datetime(utcnow.year,
                          utcnow.month,
                          utcnow.day,
                          utcnow.hour,
                          tzinfo=utc)
        # 第二步:计算出可以选课的起始时间,也就是此时此刻的24小时后,以及截至时间,也就是现在开始的29天后
        available_start = utcnow + timedelta(1)
        available_end = utcnow + timedelta(29)
        # 第三步:找到起始日期和结束日期所在的星期,拼接出可以选课的28天的列表,
        # 大列表里的小列表代表一个个以周日开始的星期
        start_flag = False
        all_available_dates = []
        for week in cal.monthdatescalendar(available_start.year,
                                           available_start.month):
            # 在没找到起始日期所在的星期的时候,要检查这个星期是否就是我们寻找的
            if not start_flag and available_start.date() in week:
                start_flag = True
            # 从找到了起始日期所在的星期开始,我们要把它所在的以及它后面的星期加到列表里
            if start_flag:
                all_available_dates.append(week)

        # 遍历结束日期所在的月,如果当前星期不在列表里,就添加(因为前后两个月可能有重复的星期)
        # 遇到结束日期所在的星期,后面的就不用看了
        for week in cal.monthdatescalendar(available_end.year,
                                           available_end.month):
            if available_end not in week:
                all_available_dates.append(week)
            if available_end.date() in week:
                break

        # 第四步:根据老师的工作时间,构造出以datetime对象为元素的列表
        # 创建一个空列表,存放老师的以小时为单位的工作时间
        new_worktime_list = []
        for week in all_available_dates:
            # w是类似于0-1这样的字符串,它表示星期天的UTC时间1点钟
            for w in worktime_list:
                date = week[int(w[0])]
                time = datetime(date.year,
                                date.month,
                                date.day,
                                int(w[2:]),
                                tzinfo=utc)
                if time < available_start or time > available_end:
                    continue
                new_worktime_list.append(time)
        # 第五步:把教师的特殊休息时间去掉
        special_rest_set = set()
        temp = teacher.special_rest.filter_by(expire=False).all()
        for data in temp:
            rest_time = datetime(data.rest_time.year,
                                 data.rest_time.month,
                                 data.rest_time.day,
                                 data.rest_time.hour,
                                 tzinfo=utc)
            if rest_time >= available_start:
                special_rest_set.add(rest_time)
            else:
                data.expire = True
                db.session.add(data)
        for i in new_worktime_list[:]:
            if i in special_rest_set:
                new_worktime_list.remove(i)
        # 第六步:把教师的补班时间加进去(这一步要放在前面,因为可能补班的时间也被选上课了)
        makeup_time_list = []
        # 先把当前显示没有过期的补班时间都查出来
        temp = teacher.make_up_time.filter_by(expire=False).all()
        for data in temp:
            makeup_time = datetime(data.make_up_time.year,
                                   data.make_up_time.month,
                                   data.make_up_time.day,
                                   data.make_up_time.hour,
                                   tzinfo=utc)
            if makeup_time >= available_start:
                makeup_time_list.append(makeup_time)
            # 如果补班时间在可选开始时间之前,说明事实上已经过期了
            # 把expire改为True
            else:
                data.expire = True
                db.session.add(data)

        new_worktime_list += makeup_time_list
        # 第七步:生成一个已预约的课程时间列表,并把这些时间从老师的工作时间里去掉
        # 为了节约资源,我们在查询的时候就筛选一下时间
        lessons = Lesson.query.filter(
            Lesson.teacher_id == teacher.id, Lesson.is_delete == False,
            Lesson.time >= datetime.utcnow() + timedelta(1)).all()
        # 先用set存放时间,因为查询比较快
        lessons_set = set()
        for lesson in lessons:
            time = lesson.time
            time = datetime(time.year,
                            time.month,
                            time.day,
                            time.hour,
                            tzinfo=utc)
            lessons_set.add(time)
        for i in new_worktime_list[:]:
            if i in lessons_set:
                new_worktime_list.remove(i)
        lessons_list = list(lessons_set)

        #计算出游客的时区
        visitor_country = current_user.timezone
        if len(visitor_country) > 2:
            visitor_tz = country_timezones[visitor_country[:2]][int(
                visitor_country[-1])]
        else:
            visitor_tz = country_timezones[visitor_country][0]
        tz_obj = timezone(visitor_tz)

        # 根据时区,生成游客视角的可以选课的28天的日历
        visitor_start = get_localtime(available_start, current_user)
        visitor_end = get_localtime(available_end, current_user)

        visitor_dates = []
        start_flag = False
        for week in cal.monthdatescalendar(visitor_start.year,
                                           visitor_start.month):
            # 因为遍历一个星期也会浪费时间,所以我们这里设两个条件
            # 如果flag已经是True了,就不需要再看结束日期在不在这个星期里了
            if not start_flag and visitor_start.date() in week:
                start_flag = True
            if start_flag:
                visitor_dates.append(week)
        # 因为前后两个月可能有重复的星期,所以要判断是否在列表里,不在的才添加
        for week in cal.monthdatescalendar(visitor_end.year,
                                           visitor_end.month):
            if week not in visitor_dates:
                visitor_dates.append(week)
            # 如果已经到了结束日期所在的星期,就不用看后面的了
            if visitor_end.date() in week:
                break

        # 获取页码
        page = request.args.get('page', 1, type=int)
        # 如果有用户恶意修改页码,我们要把页码变成1
        if page > len(visitor_dates) or page < 1:
            page = 1

        # 每个星期的月份和年,应该以这个星期中间的那一天为标准
        current_page = Pagination(visitor_dates, page, 1, len(visitor_dates),
                                  visitor_dates[page - 1])
        middle_day = current_page.items[3]
        month_name = calendar.month_name[middle_day.month]
        year = middle_day.year

        this_week = []
        only_dates = []

        for date in current_page.items:
            this_week.append('%s-%s-%s' % (date.year, date.month, date.day))
            only_dates.append(date.day)

        #把老师的可选的时间列表换成游客时区的时间(字符串)
        for i, time in enumerate(new_worktime_list):
            time = time.astimezone(tz_obj)
            new_worktime_list[i] = '%s-%s-%s-%s' % (time.year, time.month,
                                                    time.day, time.hour)
        #把老师有课的时间转换成游客时区的时间(字符串)
        for i, time in enumerate(lessons_list):
            time = time.astimezone(tz_obj)
            lessons_list[i] = '%s-%s-%s-%s' % (time.year, time.month, time.day,
                                               time.hour)

        # 查看并处理选课的ajax请求
        time = request.form.get('time', '', type=str)
        if time:
            time = time.split('-')
            #先构造一个没有时区的datetime对象
            time = datetime(int(time[0]), int(time[1]), int(time[2]),
                            int(time[3]))
            #再把它变成时区为游客所在地区的datetime对象
            time = tz_obj.localize(time)
            #再把时区变成utc时区
            time = time.astimezone(utc)

            # 再判断一次是否在可选时间范围内
            if time >= available_start:
                # 看看学生的课时包里是否还有课
                active_package = current_user.orders.filter(
                    Order.pay_status == 'paid',
                    Order.left_amount > 0).order_by(Order.id.asc()).first()
                if active_package:
                    # 课时包的课程数量扣掉一节
                    active_package.left_amount -= 1
                    db.session.add(active_package)
                    # 把选课信息存进数据库
                    lesson = current_user.lessons.filter(
                        Lesson.time == time,
                        Lesson.teacher_id == teacher.id).first()
                    if lesson:
                        lesson.is_delete = False
                    else:
                        lesson = Lesson()
                        lesson.student_id = current_user.id
                        lesson.teacher_id = teacher.id
                        lesson.time = time
                        lesson.message = ''
                        lesson.lesson_type = active_package.lesson_type
                    db.session.add(lesson)
                    return jsonify({
                        'status':
                        'ok',
                        'msg':
                        "You've successfully booked a lesson."
                    })
                else:
                    return jsonify({
                        'status':
                        'fail',
                        'msg':
                        "You don't have any lessons now. Please buy another package."
                    })
            else:
                return jsonify({
                    'status':
                    'fail',
                    'msg':
                    'You need to book lessons not earlier than 24 hours from now.'
                })
        return render_template('student/book_lesson.html',
                               teacher=teacher,
                               this_week=this_week,
                               only_dates=only_dates,
                               new_worktime_list=new_worktime_list,
                               month_name=month_name,
                               year=year,
                               current_page=current_page,
                               lessons_list=lessons_list)

    return render_template('student/book_lesson.html', teacher=teacher)