您现在的位置是: 网站首页 >Django >Django轮班排班管理系统 Django

┗━ 生成值班模板┗━ 生成值班数据视图┗━ 模板中js获取上次值班人员┗━ 生成值班url

【Schedule轮班排班】06.生成值班数据,获取上次值班人员

admin2018年11月28日 15:05 Django | Html | JavaScript | Python 1959人已围观

Django轮班排班管理系统简介 基于内部业务需求,某些岗位需要进行工作日值班以及周六值班, 如果每次手动去制作Excel排班表,确实比较费时间,就考虑自动化生成的方式去做。 没有什么技术含量,可以了解下循环生成数据方法。我也没找到相关的代码参考,个人写的很烂,仅供参考。 环境要求:Django2.x.x

http://127.0.0.1:8000/duty/generate/duty/

BLOG_20181128_150628_11

分析:

  • 获取选择的日期
  • 然后会根据这个日期进行选择提示
  • 如果值班表没有历史数据的,则获取值班成员最后一个显示,也就是值班从第一名重新开始
  • 如果值班表有数据的,得到上次值班人员名字,和值班成员表进行匹配,知道匹配到在成员表的人(这儿考虑到离职的人)
  • 然后指定生成的开始日期和结束日期
  • 指定值班类型
  • 进入generate_duty_data函数生成
  • 得到值班的原始顺序,然后根据上次值班的人分析出顺序差值,得到一个新的值班顺序
  • 根据这个新的值班顺序,遍历值班表的日期,填充值班人员到值班表中
  • 完成

生成值班模板

创建eate-duty.html模板

{% extends 'base-duty.html' %}
{% load static %}
{% load duty_template_tags %}

{% block css %}
    <link href="{% static 'hAdmin/css/plugins/datapicker/datepicker3.css' %}" rel="stylesheet">
{% endblock %}

{% block title %}{{ block.super }} - 生成值班{% endblock %}

{% block breadcrumb %}
    <li>
        <a href="/">主页</a>
    </li>
    <li>
        <strong>生成值班</strong>
    </li>
{% endblock %}

{% block content %}
    <div class="ibox float-e-margins">
        <div class="ibox-title">
            <h5>根据已存在的日期数据,生成值班表</h5>
        </div>
        <div class="ibox-content">
            <p>若修改日期数据,需要重新生成值班表;从选择日期往后生成,下方显示的值班人员参考为该日期之前的值班人员</p>
            <p>
                上次值班已生成到:{% if last_schedule %}{{ last_schedule.last.date }}{% else %}未生成数据{% endif %}
                ,日期选择不得超过已生成的日期:{{ end_date }}
            </p>

            <form method="post" autocomplete="off">
                <div class="row">
                    <div class="col-sm-12">
                        <form role="form">
                            <div class="form-group" id="choose_date">
                                <label>可选日期</label>
                                <div class="input-group date">
                                    <input type="text" class="form-control" name="choose_date" value="{{ today|date:"Y-m-d" }}" id="id_choose_date">
                                    <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
                                </div>
                            </div>
                            <div class="form-group">
                                <label>上次晚班</label>
                                <select class="form-control m-b" name="last_night_duty">
                                    <option value="">------</option>
                                    {% for employee in all_employee %}
                                        <option value="{{ employee.id }}">{{ employee.name }}</option>
                                    {% endfor %}
                                </select>
                                <div style="color:#ADADAD" title="所选日期上一个值班人员">以上参考选择:<span id="id_last_night_duty">{{ last_night_duty.staff }}</span></div>
                            </div>
                            <div class="form-group">
                                <label>上次周末</label>
                                <select class="form-control m-b" name="last_weekend_duty">
                                    <option value="">------</option>
                                    {% for employee in all_employee %}
                                        <option value="{{ employee.id }}">{{ employee.name }}</option>
                                    {% endfor %}
                                </select>
                                <div style="color:#ADADAD" title="所选日期上一个值班人员">以上参考选择:<span id="id_last_weekend_duty">{{ last_weekend_duty.staff }}</span></div>
                            </div>
                            {% csrf_token %}
                            <div>
                                <button class="btn btn-primary" type="submit">开始生成</button>
                            </div>
                        </form>
                    </div>
                </div>
            </form>
        </div>
    </div>
{% endblock %}

{% block js %}
    <script src="{% static 'hAdmin/js/plugins/datapicker/bootstrap-datepicker.js' %}"></script>
    <script>
        $('#choose_date .input-group.date').datepicker({
            language: "zh-CN",
            todayBtn: "linked",
            keyboardNavigation: false,
            forceParse: false,
            calendarWeeks: true,
            autoclose: true,
            todayHighlight: true,
            endDate: "{{ end_date }}",
            format: "yyyy-mm-dd",
        });

        $('#id_choose_date').change(function () {
            let choose_date = $('#id_choose_date').val();
            $.ajax({
                url: '{% url "duty:get_last_duty" %}?this_date=' + choose_date,
                type: 'GET',
                dataType: 'json',
                timeout: 3000,
                cache: false,
                success: succFunction, //成功执行方法
            });
            function succFunction(last_duty) {
                let json2cval = eval(last_duty);
                $('#id_last_night_duty').html(json2cval.last_night_duty_name);
                $('#id_last_weekend_duty').html(json2cval.last_weekend_duty_name);
            }
        });
    </script>
{% endblock %}

生成值班数据视图

def generate_duty_data(last_duty_name, duty_type, start_date, end_date):
    print('正在生成类型为{}值班信息'.format(duty_type))
    all_employee = Employee.objects.filter(available=True)
    # 生成默认的顺序{name:{'default_order': num}, ...}
    employee_order = dict()
    for employee in all_employee:
        employee_order[employee.name] = {}
        employee_order[employee.name]['default_order'] = employee.num
    # print(employee_order)

    # 将选择的last_duty_name的新顺序变为值班成员的数量,也就是排班排到最后一位,得到新顺序和默认顺序的差值
    employee_order[last_duty_name]['new_order'] = all_employee.count()
    diff_num = all_employee.count() - employee_order[last_duty_name]['default_order']
    print('顺序差值:', diff_num)

    # 在默认的顺序字典中增加新的顺序
    new_employee_order = {}
    for name, item in employee_order.items():
        employee_order[name]['new_order'] = employee_order[name]['default_order'] + diff_num
        if employee_order[name]['new_order'] > all_employee.count():
            employee_order[name]['new_order'] -= all_employee.count()
        # 根据这个新字典顺便生成新顺序:名字的对应关系
        new_employee_order[employee_order[name]['new_order']] = name
    print(employee_order)
    print(new_employee_order)  # {new_order: name, ...}

    # 待排序的值班进行排序
    next_duty = Schedule.objects.filter(duty_type=duty_type, date__gte=start_date, date__lte=end_date).order_by('date')

    # 更新从选定日期到生成的最后日期的值班表
    i = 0
    for duty in next_duty:
        # print(duty, i % all_employee.count() + 1)
        duty.staff = new_employee_order[i % all_employee.count() + 1]
        duty.real_staff = ''
        duty.save()
        i += 1


class GenerateDutyInfo(View):
    """
    生成值班表,填充值班人员
    """

    def get(self, request):
        # 获取上次值班安排到的日期,也就是安排了值班人员的最后一个日期
        last_schedule = Schedule.objects.exclude(Q(staff__isnull=True) | Q(staff='')).order_by('date')

        all_employee = Employee.objects.filter(available=True)
        today = datetime.date.today()  # 可选日期开始
        if Schedule.objects.all():  # 如果存在值班表
            end_date = Schedule.objects.order_by('-date').first().date  # 可选日期结束
        else:
            end_date = today
        last_night_duty = last_schedule.filter(duty_type=1).last()  # 获取上次晚班的数据
        last_weekend_duty = last_schedule.filter(duty_type=2).last()  # 获取上次周末值班数据

        return render(request, 'create-duty.html', locals())

    def post(self, request):
        choose_date = request.POST.get('choose_date')
        end_date = Schedule.objects.order_by('-date').first().date  # 排班结束日期
        this_date = datetime.date.today()  # 默认为今天的日期
        if choose_date:
            yy, mm, dd = choose_date.split('-')
            this_date = datetime.date(int(yy), int(mm), int(dd))  # 获取选择的日期

        # 获取选择的上次值班人员id
        last_night_duty_id = request.POST.get('last_night_duty')
        last_weekend_duty_id = request.POST.get('last_weekend_duty')

        # 获取值班表中该日期数据信息,以日期从小到大排序
        previous_night_duty = Schedule.objects.filter(duty_type=1, date__lt=this_date).order_by('date')
        previous_weekend_duty = Schedule.objects.filter(duty_type=2, date__lt=this_date).order_by('date')

        # 值班成员中的第一个
        all_employee = Employee.objects.filter(available=True)

        # 如果选择了上次晚班值班人员
        if last_night_duty_id:
            last_night_duty_name, last_night_duty_num = Employee.objects.filter(id=last_night_duty_id).values_list('name', 'num').first()
        else:
            # 默认情况下为值班成员第一个
            last_night_duty_name = all_employee.first().name

            # 如果值班表中已安排过晚班,从中获取上次值班人员,exclude表示得到staff中有值得数据
            all_previous_night_duty = previous_night_duty.exclude(Q(staff__isnull=True) & Q(staff=''))

            if all_previous_night_duty:
                # 得到上次值班人员,要考虑到值班成员列表中消失的名字
                for previous_night_duty in all_previous_night_duty.reverse():  # 倒序,日期最新的在前
                    # print(previous_night_duty)
                    if all_employee.filter(name=previous_night_duty.staff):
                        last_night_duty_name = previous_night_duty.staff  # 获取值班表名字在成员中的一个,获取到后停止
                        break
        print('上次晚上值班人员:', last_night_duty_name)
        generate_duty_data(last_duty_name=last_night_duty_name, duty_type=1, start_date=this_date, end_date=end_date)

        # ---------------------------------------------------------
        # 如果选择了上次周末值班人员
        if last_weekend_duty_id:
            last_weekend_duty_name, last_weekend_duty_num = Employee.objects.filter(id=last_weekend_duty_id).values_list('name', 'num').first()
        else:
            # 默认情况下为值班成员第一个
            last_weekend_duty_name = all_employee.first().name

            # 如果值班表中已安排过周末值班,从中获取上次值班人员,exclude表示得到staff中有值得数据
            all_previous_weekend_duty = previous_weekend_duty.exclude(Q(staff__isnull=True) & Q(staff=''))

            if all_previous_weekend_duty:
                # 得到上次值班人员,要考虑到值班成员列表中消失的名字
                for previous_weekend_duty in all_previous_weekend_duty.reverse():  # 倒序,日期最新的在前
                    # print(previous_weekend_duty)
                    if all_employee.filter(name=previous_weekend_duty.staff):
                        last_weekend_duty_name = previous_weekend_duty.staff  # 获取值班表名字在成员中的一个,获取到后停止
                        break
        print('上次周末值班人员:', last_weekend_duty_name)
        generate_duty_data(last_duty_name=last_weekend_duty_name, duty_type=2, start_date=this_date, end_date=end_date)

        return redirect(reverse('duty:create_duty'))

模板中js获取上次值班人员

def get_last_duty(request):
    """
    根据给定的一个日期,从值班表中得到这个日期之前的值班人员信息
    :param reqeust:
    :return:
    """
    yy, mm, dd = request.GET.get('this_date').split('-')
    this_date = datetime.date(int(yy), int(mm), int(dd))

    # 获取值班表中日期数据信息,以日期从大到小排序
    previous_night_duty = Schedule.objects.filter(duty_type=1, date__lt=this_date).order_by('-date')
    previous_weekend_duty = Schedule.objects.filter(duty_type=2, date__lt=this_date).order_by('-date')

    all_employee = Employee.objects.filter(available=True)

    last_night_duty_name = last_weekend_duty_name = all_employee.last().name  # 未安排过值班的,默认显示值班成员最后一个,然后从第一人开始排

    for night_duty in previous_night_duty:
        if all_employee.filter(name=night_duty.staff):
            last_night_duty_name = night_duty.staff  # 获取值班表名字在成员中的一个,获取到后停止
            break

    for weekend_duty in previous_weekend_duty:
        if all_employee.filter(name=weekend_duty.staff):
            last_weekend_duty_name = weekend_duty.staff  # 获取值班表名字在成员中的一个,获取到后停止
            break

    last_duty = dict()
    last_duty['last_night_duty_name'] = last_night_duty_name
    last_duty['last_weekend_duty_name'] = last_weekend_duty_name
    return HttpResponse(json.dumps(last_duty))

生成值班url

from .views import  GenerateDutyInfo
urlpatterns = [
    path('generate/duty/', permission_required('usercenter.permission_user_manage', raise_exception=True)(GenerateDutyInfo.as_view()), name='create_duty'),  # 生成值班日期
]

BLOG_20181128_151955_12

点击生成,这样选择就从第一名成员开始排序

BLOG_20181128_152027_16

生成好后再访问 http://127.0.0.1:8000/duty/generate/duty/ 选择30号,下方就显示上次排班的人员信息

BLOG_20181128_152152_21

核对一下都是正确的

很赞哦! (2)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行2417天
  • 系统信息:Linux
  • 后台程序:Python: 3.8.10
  • 网站框架:Django: 3.2.6
  • 文章统计:257 篇
  • 文章评论:63 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 公众号:微信扫描二维码,关注我们
  • QQ群:QQ加群,下载网站的学习源码
返回
顶部
标题 换行 登录
网站