Beispiel #1
0
    def longterm_wk(self, request, queryset, week_num):
        if not request.user.is_superuser:
            return self.message_user(request=request,
                                     message='操作失败,没有权限,请联系老师!',
                                     level=messages.WARNING)
        if len(queryset) != 1:
            return self.message_user(request=request,
                                     message='每次仅允许将一条预约长线化!',
                                     level=messages.WARNING)
        for appoint in queryset:
            # print(appoint)
            try:
                with transaction.atomic():
                    stuid_list = [stu.Sid for stu in appoint.students.all()]
                    for i in range(week_num):
                        # 调用函数完成预约
                        feedback = addAppoint({
                            'Rid':
                            appoint.Room.Rid,
                            'students':
                            stuid_list,
                            'non_yp_num':
                            appoint.Anon_yp_num,
                            'Astart':
                            appoint.Astart + (i + 1) * timedelta(days=7),
                            'Afinish':
                            appoint.Afinish + (i + 1) * timedelta(days=7),
                            'Sid':
                            appoint.major_student.Sid,
                            'Ausage':
                            appoint.Ausage,
                            'announcement':
                            appoint.Aannouncement,
                            'new_require':  # 长线预约,不需要每一个都添加信息, 直接统一添加
                            0
                        })
                        if feedback.status_code != 200:  # 成功预约
                            warning = eval(
                                feedback.content.decode(
                                    'unicode-escape'))['statusInfo']['message']
                            print(warning)
                            raise Exception(warning)
                        '''
                        newappoint = Appoint(
                            Room=appoint.Room,
                            Astart=appoint.Astart + (i+1) * timedelta(days=7),
                            Afinish=appoint.Afinish + \
                                (i+1) * timedelta(days=7),
                            Ausage=appoint.Ausage,
                            Aannouncement=appoint.Aannouncement,
                            major_student=appoint.major_student,
                            Anon_yp_num=appoint.Anon_yp_num,
                            Ayp_num=appoint.Ayp_num
                        )
                        newappoint.save()
                        for tempstudent in appoint.students.all():
                            print(tempstudent)
                            newappoint.students.add(tempstudent)
                        newappoint.save()
                        '''
            except Exception as e:
                operation_writer(
                    global_info.system_log, "学生" + str(appoint.major_student) +
                    "出现添加长线化预约失败的问题:" + str(e), "admin.longterm", "Problem")
                return self.message_user(request=request,
                                         message=str(e),
                                         level=messages.WARNING)

            # 到这里, 长线化预约发起成功
            scheduler.add_job(
                send_wechat_message,
                args=[
                    stuid_list,  # stuid_list
                    appoint.Astart,  # start_time
                    appoint.Room,  # room
                    "longterm",  # message_type
                    appoint.major_student.Sname,  # major_student
                    appoint.Ausage,  # usage
                    appoint.Aannouncement,
                    len(stuid_list) + appoint.Anon_yp_num,
                    week_num,  # reason, 这里用作表示持续周数
                    #appoint.major_student.Scredit,
                ],
                id=f'{appoint.Aid}_new_wechat',
                next_run_time=datetime.now() + timedelta(seconds=5))  # 2s足够了
            operation_writer(
                appoint.major_student.Sid,
                "发起" + str(week_num) + "周的长线化预约, 原始预约号" + str(appoint.Aid),
                "admin.longterm", "OK")
        return self.message_user(request, '长线化成功!')
def check_out(request):  # 预约表单提交
    if not identity_check(request):
        return redirect(direct_to_login(request))
    temp_time = datetime.now()
    warn_code = 0
    try:
        if request.method == "GET":
            Rid = request.GET.get('Rid')
            weekday = request.GET.get('weekday')
            startid = request.GET.get('startid')
            endid = request.GET.get('endid')
        else:
            Rid = request.POST.get('Rid')
            weekday = request.POST.get('weekday')
            startid = request.POST.get('startid')
            endid = request.POST.get('endid')
        # 防止恶意篡改参数
        assert weekday in wklist
        assert int(startid) >= 0
        assert int(endid) >= 0
        assert int(endid) >= int(startid)
        appoint_params = {
            'Rid': Rid,
            'weekday': weekday,
            'startid': int(startid),
            'endid': int(endid)
        }
        room_object = Room.objects.filter(Rid=Rid)[0]
        dayrange_list = web_func.get_dayrange()
        for day in dayrange_list:
            if day['weekday'] == appoint_params['weekday']:  # get day
                appoint_params['date'] = day['date']
                appoint_params['starttime'], valid = web_func.get_hour_time(
                    room_object, appoint_params['startid'])
                assert valid is True
                appoint_params['endtime'], valid = web_func.get_hour_time(
                    room_object, appoint_params['endid'] + 1)
                assert valid is True
                appoint_params['year'] = day['year']
                appoint_params['month'] = day['month']
                appoint_params['day'] = day['day']
                # 最小人数下限控制
                appoint_params['Rmin'] = room_object.Rmin
                if datetime.now().strftime("%a") == appoint_params['weekday']:
                    appoint_params['Rmin'] = min(global_info.today_min,
                                                 room_object.Rmin)
        appoint_params['Sid'] = request.session['Sid']
        appoint_params['Sname'] = Student.objects.get(
            Sid=appoint_params['Sid']).Sname
        Stu_all = Student.objects.all()

    except:
        return redirect(reverse('Appointment:index'))
    if request.method == "GET":
        js_stu_list = web_func.get_student_chosen_list(request)
        return render(request, "Appointment/checkout.html", locals())
    elif request.method == 'POST':  # 提交预约信息
        contents = dict(request.POST)
        for key in contents.keys():
            if key != "students":
                contents[key] = contents[key][0]
                if key in {'year', 'month', 'day'}:
                    contents[key] = int(contents[key])
        # 处理外院人数
        if contents['non_yp_num'] == "":
            contents['non_yp_num'] = 0
        else:
            try:
                contents['non_yp_num'] = int(contents['non_yp_num'])
                assert contents['non_yp_num'] >= 0
            except:
                warn_code = 1
                warning = "外院人数有误,请按要求输入!"
                # return render(request, "Appointment/checkout.html", locals())
        # 处理用途未填写
        if contents['Ausage'] == "":
            warn_code = 1
            warning = "请输入房间用途!"
            # return render(request, "Appointment/checkout.html", locals())
        # 处理单人预约
        if "students" not in contents.keys():
            contents['students'] = [contents['Sid']]
        else:
            contents['students'].append(contents['Sid'])

        contents['Astart'] = datetime(contents['year'], contents['month'],
                                      contents['day'],
                                      int(contents['starttime'].split(":")[0]),
                                      int(contents['starttime'].split(":")[1]),
                                      0)
        contents['Afinish'] = datetime(contents['year'], contents['month'],
                                       contents['day'],
                                       int(contents['endtime'].split(":")[0]),
                                       int(contents['endtime'].split(":")[1]),
                                       0)
        if warn_code != 1:
            # 增加contents内容,这里添加的预约需要所有提醒,所以contents['new_require'] = 1
            contents['new_require'] = 1
            response = scheduler_func.addAppoint(
                contents)  # 否则没必要执行 并且有warn_code&message

            if response.status_code == 200:  # 成功预约
                urls = reverse(
                    "Appointment:admin_index"
                ) + "?warn_code=2&warning=预约" + room_object.Rtitle + "成功!"
                return redirect(urls)
            else:
                add_dict = eval(
                    response.content.decode('unicode-escape'))['statusInfo']
                warn_code = 1
                warning = add_dict['message']

        # 到这里说明预约失败 补充一些已有信息,避免重复填写
        js_stu_list = web_func.get_student_chosen_list(request)
        # selected_stu_list = Stu_all.filter(
        #    Sid__in=contents['students']).exclude(Sid=contents['Sid'])
        selected_stu_list = [
            w for w in js_stu_list if w['id'] in contents['students']
        ]
        no_clause = True
        return render(request, 'Appointment/checkout.html', locals())
def door_check(request):  # 先以Sid Rid作为参数,看之后怎么改

    # --------- 基本信息 --------- #

    Sid, Rid = request.GET.get("Sid", None), request.GET.get("Rid", None)
    student, room, now_time, min15 = None, None, datetime.now(), timedelta(
        minutes=15)
    try:
        student = Student.objects.get(Sid=Sid)
        all_Rid = [room.Rid for room in Room.objects.all()]
        Rid = doortoroom(Rid)
        if Rid[:4] in all_Rid:  # 表示增加了一个未知的A\B号
            Rid = Rid[:4]
        room = Room.objects.get(Rid=Rid)
    except:
        user = student or None  # TODO: 设置默认刷卡记录者
        cardcheckinfo_writer(user, room, False, False, f"学号{Sid}或房间号{Rid}错误")
        return JsonResponse({"code": 1, "openDoor": "false"}, status=400)

    # --------- 直接进入 --------- #

    if room.Rstatus == Room.Status.FORBIDDEN:  # 禁止使用的房间
        cardcheckinfo_writer(student, room, False, False, f"刷卡拒绝:禁止使用")
        return JsonResponse({"code": 1, "openDoor": "false"}, status=400)

    if room.Rstatus == Room.Status.SUSPENDED:  # 自习室

        if room.RIsAllNight == Room.IsAllNight.Yes:  # 通宵自习室
            cardcheckinfo_writer(student, room, True, True, f"刷卡开门:通宵自习室")
            return JsonResponse({"code": 0, "openDoor": "true"}, status=200)

        else:  # 不是通宵自习室

            # 考虑到次晨的情况,判断一天内的时段
            now = timedelta(hours=now_time.hour, minutes=now_time.minute)
            start = timedelta(hours=room.Rstart.hour,
                              minutes=room.Rstart.minute)
            finish = timedelta(hours=room.Rfinish.hour,
                               minutes=room.Rfinish.minute)

            if (now >= min(start, finish) and
                    now <= max(start, finish)) ^ (start > finish):  # 在开放时间内
                cardcheckinfo_writer(student, room, True, True, f"刷卡开门:自习室")
                return JsonResponse({
                    "code": 0,
                    "openDoor": "true"
                },
                                    status=200)

            else:  # 不在开放时间内
                cardcheckinfo_writer(student, room, False, False,
                                     f"刷卡拒绝:自习室不开放")
            return JsonResponse({"code": 1, "openDoor": "false"}, status=400)

    # --------- 预约进入 --------- #

    # 获取房间的预约
    room_appoint = Appoint.objects.not_canceled().filter(  # 只选取接下来15分钟进行的预约
        Astart__lte=now_time + min15,
        Afinish__gte=now_time,
        Room_id=Rid)

    # --- modify by dyh: 更改规则 --- #
    # --- modify by lhw: 临时预约 --- #

    if len(room_appoint) != 0:  # 当前有预约

        if len(room_appoint.filter(students__in=[student])) == 0:  # 不是自己的预约
            cardcheckinfo_writer(student, room, False, False,
                                 f"刷卡拒绝:该房间有别人的预约,或者距离别人的下一条预约开始不到15min!")
            return JsonResponse({"code": 1, "openDoor": "false"}, status=400)

        else:  # 自己的预约
            cardcheckinfo_writer(student, room, True, True, f"刷卡开门:预约进入")
            return JsonResponse({"code": 0, "openDoor": "true"}, status=200)

    else:  # 当前无预约

        if check_temp_appoint(room) == False:  # 房间不可以临时预约
            cardcheckinfo_writer(student, room, False, False,
                                 f"刷卡拒绝:该房间不可临时预约")
            return JsonResponse({"code": 1, "openDoor": "false"}, status=400)

        else:  # 该房间可以用于临时预约

            # 注意,由于制度上不允许跨天预约,这里的逻辑也不支持跨日预约(比如从晚上23:00约到明天1:00)。
            start = datetime(now_time.year, now_time.month, now_time.day,
                             now_time.hour, now_time.minute,
                             0)  # 需要剥离秒级以下的数据,否则admin-index无法正确渲染
            timeid = web_func.get_time_id(room, time(start.hour, start.minute))

            # 房间未开放
            if timeid < 0:
                message = f"该时段房间未开放!别熬夜了,回去睡觉!"
                cardcheckinfo_writer(student, room, False, False,
                                     f"刷卡拒绝:临时预约失败({message})")
                send_wechat_message([Sid], start, room,
                                    "temp_appointment_fail", student, "临时预约",
                                    "", 1, message)
                return JsonResponse({
                    "code": 1,
                    "openDoor": "false"
                },
                                    status=400)

            finish, valid = web_func.get_hour_time(room, timeid + 1)
            finish = datetime(now_time.year, now_time.month, now_time.day,
                              int(finish.split(':')[0]),
                              int(finish.split(':')[1]), 0)

            # 检查时间是否合法
            # 合法条件:为避免冲突,临时预约时长必须超过15分钟;预约时在房间可用时段
            # OBSELETE: 时间合法(暂时将间隔定为5min)
            if valid:
                contents = {
                    'Rid': Rid,
                    'students': [Sid],
                    'Sid': Sid,
                    'Astart': start,
                    'Afinish': finish,
                    'non_yp_num': 0,
                    'Ausage': "临时预约",
                    'announcement': "",
                    'Atemp_flag': True
                }
                response = scheduler_func.addAppoint(contents)

                if response.status_code == 200:  # 临时预约成功
                    cardcheckinfo_writer(student, room, True, True,
                                         f"刷卡开门:临时预约")
                    return JsonResponse({
                        "code": 0,
                        "openDoor": "true"
                    },
                                        status=200)

                else:  # 无法预约(比如没信用分了)
                    message = json.loads(
                        response.content.decode())["statusInfo"]["message"]
                    cardcheckinfo_writer(student, room, False, False,
                                         f"刷卡拒绝:临时预约失败({message})")
                    send_wechat_message([Sid], start, room,
                                        "temp_appointment_fail", student,
                                        "临时预约", "", 1, message)
                    return JsonResponse({
                        "code": 1,
                        "openDoor": "false"
                    },
                                        status=400)

            else:  # 预约时间不合法
                message = f"预约时间不合法,请不要恶意篡改数据!"
                cardcheckinfo_writer(student, room, False, False,
                                     f"刷卡拒绝:临时预约失败({message})")
                send_wechat_message([Sid], start, room,
                                    "temp_appointment_fail", student, "临时预约",
                                    "", 1, message)
                return JsonResponse({
                    "code": 1,
                    "openDoor": "false"
                },
                                    status=400)