mirror of https://github.com/raiots/TasksManager
update: calclate the real workload and quality by quarter
This commit is contained in:
parent
3283478b42
commit
df9e174bd3
|
@ -26,7 +26,7 @@ SECRET_KEY = '&!38pk#dv=r!_c(+b&oegc0m(ndzoue+ez*7kvjv2uubuqootp'
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['192.168.31.198', '127.0.0.1', '172.20.22.40']
|
ALLOWED_HOSTS = ['192.168.31.198', '127.0.0.1', '172.20.22.40', '110.42.209.79']
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
|
@ -202,16 +202,17 @@ class TodoAdmin(ImportExportModelAdmin):
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def save_model(self, request, obj, form, change):
|
# def save_model(self, request, obj, form, change):
|
||||||
# 这一行代码写了一个晚上呜呜! 解决了当保存时,无法从未保存的数据中获取协办人数的问题!
|
# # 这一行代码写了一个晚上呜呜! 解决了当保存时,无法从未保存的数据中获取协办人数的问题!
|
||||||
mvDict = dict(request.POST)
|
# mvDict = dict(request.POST)
|
||||||
# dicts = request.POST
|
# dicts = request.POST
|
||||||
# print(dicts)
|
# print(dicts)
|
||||||
# for key, values in dicts:
|
# for key, values in dicts:
|
||||||
# print(key, values)
|
# print(key, values)
|
||||||
# obj.user = request.user
|
# obj.user = request.user
|
||||||
obj.sub_executor_count = int(len(mvDict['sub_executor']))
|
|
||||||
super().save_model(request, obj, form, change)
|
# obj.sub_executor_count = int(len(mvDict['sub_executor']))
|
||||||
|
# super().save_model(request, obj, form, change)
|
||||||
|
|
||||||
# 增加批量操作按钮
|
# 增加批量操作按钮
|
||||||
actions = ['bulk_action']
|
actions = ['bulk_action']
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
import decimal
|
||||||
|
|
||||||
from django.core import serializers
|
from django.core import serializers
|
||||||
from django.core.serializers.json import DjangoJSONEncoder
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
|
from django.db.models.functions import TruncMonth
|
||||||
from django.http import HttpResponse, JsonResponse
|
from django.http import HttpResponse, JsonResponse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
@ -13,79 +16,12 @@ from django.views import View
|
||||||
from apps.users.models import User
|
from apps.users.models import User
|
||||||
from apps.tasks.models import Todo
|
from apps.tasks.models import Todo
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from collections import defaultdict, Counter
|
from collections import defaultdict, Counter, ChainMap
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
|
|
||||||
class TestView(View):
|
# 用于按用户名合并任务,会对指定字段进行累加,类似GROUP BY(SUM),但会丢失无需计算的部分,因此之前需要单独构建姓名字典
|
||||||
def get(self, request, year=2021, month=7):
|
def solve(dataset, group_by_key, sum_value_keys):
|
||||||
# sub_credit = User.objects.filter(department=request.user.department).annotate(
|
|
||||||
# pre_credit=Sum(
|
|
||||||
# (F('sub_executor__predict_work') * (1 - F('sub_executor__evaluate_factor')) / F(
|
|
||||||
# 'sub_executor__sub_executor_count')
|
|
||||||
# ),
|
|
||||||
# filter=Q(sub_executor__deadline__year=year, sub_executor__deadline__month=month),
|
|
||||||
# output_field=FloatField()
|
|
||||||
# ),
|
|
||||||
# real_credit=Sum(
|
|
||||||
# (F('sub_executor__real_work') * (1 - F('sub_executor__evaluate_factor')) / F(
|
|
||||||
# 'sub_executor__sub_executor_count')
|
|
||||||
# ),
|
|
||||||
# filter=Q(sub_executor__deadline__year=year, sub_executor__deadline__month=month),
|
|
||||||
# output_field=FloatField()
|
|
||||||
# )
|
|
||||||
# ).values('id', 'real_name', 'pre_credit', 'real_credit')
|
|
||||||
# sub_credit = [entry for entry in sub_credit]
|
|
||||||
|
|
||||||
# 建立username和真实姓名的对应字典,并在工作量计算完成后插入结果集
|
|
||||||
user_info = User.objects.filter(department=request.user.department)\
|
|
||||||
.values_list('username', 'real_name')
|
|
||||||
user_name = {}
|
|
||||||
for user in user_info:
|
|
||||||
user_name[user[0]] = user[1]
|
|
||||||
# print(user_name)
|
|
||||||
|
|
||||||
# 以用户表查询,按用户列出所参与承办、协办任务,并在之后按用户名分组合并。
|
|
||||||
main_credit = User.objects.filter(department=request.user.department)\
|
|
||||||
.annotate(main_count=Count('main_executor'))\
|
|
||||||
.order_by('username')\
|
|
||||||
.values('username', 'main_executor', 'main_executor__predict_work', 'main_executor__real_work',
|
|
||||||
'main_executor__evaluate_factor', 'main_count') # 这里的annotate不知会不会有问题
|
|
||||||
|
|
||||||
sub_count = Todo.objects.filter(sub_executor__department=request.user.department) \
|
|
||||||
.annotate(sub_count=Count('sub_executor')).values('id', 'sub_count')
|
|
||||||
sub_credit = User.objects.filter(department=request.user.department) \
|
|
||||||
.order_by('username') \
|
|
||||||
.values('username', 'real_name', 'sub_executor', 'sub_executor__predict_work', 'sub_executor__real_work',
|
|
||||||
'sub_executor__evaluate_factor')
|
|
||||||
|
|
||||||
# 构建工作包id对应协办人人数的字典
|
|
||||||
sub_exe_count = {}
|
|
||||||
for i in sub_count:
|
|
||||||
key = i['id']
|
|
||||||
value = i['sub_count']
|
|
||||||
sub_exe_count[key] = value
|
|
||||||
# print(sub_exe_count)
|
|
||||||
|
|
||||||
# 计算每个承办任务的预计、实际工作量,并插入字典
|
|
||||||
for i in main_credit:
|
|
||||||
i['main_pre_cal'] = i['main_executor__predict_work'] * i['main_executor__evaluate_factor']
|
|
||||||
i['main_real_cal'] = i['main_executor__real_work'] * i['main_executor__evaluate_factor']
|
|
||||||
# print(i)
|
|
||||||
# print(str(i['sub_executor']))
|
|
||||||
|
|
||||||
# 将协办任务对应的人数插入,计算每个协办任务的预计、实际工作量,并插入字典
|
|
||||||
for i in sub_credit:
|
|
||||||
sub_todo_id = i['sub_executor']
|
|
||||||
i['sub_exe_count'] = sub_exe_count[sub_todo_id]
|
|
||||||
i['sub_pre_cal'] = i['sub_executor__predict_work'] * (1 - i['sub_executor__evaluate_factor']) / i['sub_exe_count']
|
|
||||||
i['sub_real_cal'] = i['sub_executor__real_work'] * (1 - i['sub_executor__evaluate_factor']) / i['sub_exe_count']
|
|
||||||
i['sub_count'] = 1 # 用于帮助累加程序计算每个用户的协办任务数量, sub_exe_count会返回此协办任务的协办人数,在累加时导致计算错误
|
|
||||||
# print(i)
|
|
||||||
# print(str(i['sub_executor']))
|
|
||||||
|
|
||||||
# 用于按用户名合并任务,会对指定字段进行累加,类似GROUP BY(SUM),但会丢失无需计算的部分,因此之前需要单独构建姓名字典
|
|
||||||
def solve(dataset, group_by_key, sum_value_keys):
|
|
||||||
dic = defaultdict(Counter)
|
dic = defaultdict(Counter)
|
||||||
for item in dataset:
|
for item in dataset:
|
||||||
key = item[group_by_key]
|
key = item[group_by_key]
|
||||||
|
@ -93,13 +29,38 @@ class TestView(View):
|
||||||
dic[key].update(vals)
|
dic[key].update(vals)
|
||||||
return dic
|
return dic
|
||||||
|
|
||||||
main_credit = solve(main_credit, 'username', ['main_pre_cal', 'main_real_cal', 'main_count'])
|
def cal_method(main_list, sub_list, user_name):
|
||||||
|
# print(main_list, sub_list, user_name)
|
||||||
|
|
||||||
|
# sub_credit = sub_list
|
||||||
|
# main_credit = main_list
|
||||||
|
|
||||||
|
total_data = []
|
||||||
|
season = 1
|
||||||
|
# 分别计算每个季度的工作量、评价
|
||||||
|
for main_credit, sub_credit in zip(main_list, sub_list):
|
||||||
|
# TODO 对于完成质量的核算,先对评价求和,再除以已评价的承办任务数
|
||||||
|
# for i in main_credit:
|
||||||
|
# print(i['main_executor__quality_mark__mark_value__mark_value'])
|
||||||
|
# print(main_credit)
|
||||||
|
quality_dict = {}
|
||||||
|
for i in main_credit:
|
||||||
|
quality_dict[i['username']] = []
|
||||||
|
if i['main_executor__quality_mark__mark_value__mark_value'] != None:
|
||||||
|
quality_dict[i['username']].append(i['main_executor__quality_mark__mark_value__mark_value'])
|
||||||
|
|
||||||
|
for key, value in quality_dict.items():
|
||||||
|
if value:
|
||||||
|
quality_dict[key] = sum(value) / len(value)
|
||||||
|
# print(quality_dict)
|
||||||
|
|
||||||
|
main_credit = solve(main_credit, 'username', ['main_pre_cal', 'main_real_cal', 'main_count', 'main_executor__evaluate_factor'])
|
||||||
main_credit = dict(main_credit)
|
main_credit = dict(main_credit)
|
||||||
sub_credit = solve(sub_credit, 'username', ['sub_pre_cal', 'sub_real_cal', 'sub_count'])
|
sub_credit = solve(sub_credit, 'username', ['sub_pre_cal', 'sub_real_cal', 'sub_count'])
|
||||||
sub_credit = dict(sub_credit)
|
sub_credit = dict(sub_credit)
|
||||||
total_credit = deepcopy(main_credit)
|
|
||||||
|
|
||||||
# 按用户名合并承办与协办任务字典
|
# 按用户名合并承办与协办任务字典
|
||||||
|
total_credit = deepcopy(main_credit)
|
||||||
for key in sub_credit.keys():
|
for key in sub_credit.keys():
|
||||||
if key in total_credit:
|
if key in total_credit:
|
||||||
total_credit[key].update(sub_credit[key])
|
total_credit[key].update(sub_credit[key])
|
||||||
|
@ -113,43 +74,139 @@ class TestView(View):
|
||||||
value['pre_cal'] = value['sub_pre_cal'] + value['main_pre_cal']
|
value['pre_cal'] = value['sub_pre_cal'] + value['main_pre_cal']
|
||||||
value['real_cal'] = value['sub_real_cal'] + value['main_real_cal']
|
value['real_cal'] = value['sub_real_cal'] + value['main_real_cal']
|
||||||
value['real_name'] = user_name[key]
|
value['real_name'] = user_name[key]
|
||||||
# total_credit = dict(main_credit.items() + sub_credit.items())
|
value['season'] = season
|
||||||
# for value in sub_credit.values():
|
|
||||||
# dict(value)
|
|
||||||
# print(sub_credit)
|
|
||||||
#
|
|
||||||
# new_pair = {}
|
|
||||||
# for doc, tab in sub_credit.items():
|
|
||||||
# new_pair[doc] = {}
|
|
||||||
# for word, freq in tab.items():
|
|
||||||
# new_pair[doc][word] = freq
|
|
||||||
# print(new_pair)
|
|
||||||
# return HttpResponse(str(main_credit)+str(sub_credit))
|
|
||||||
|
|
||||||
current_user = total_credit[request.user.username]
|
# 由于不计算协办任务,quality_dict会有空值情况
|
||||||
print(current_user)
|
try:
|
||||||
|
value['quality'] = quality_dict[key]
|
||||||
|
except:
|
||||||
|
value['quality'] = 0
|
||||||
|
|
||||||
# 累加该部门各个用户的工作量,计算部门工作量
|
for value in total_credit.values():
|
||||||
department_cal = {}
|
# print(value)
|
||||||
temp_pre = []
|
real_cal_season = "real_cal_" + str(season)
|
||||||
depart_pre, depart_real, depart_count = 0, 0, 0
|
value[real_cal_season] = value.pop("real_cal")
|
||||||
for username, value in total_credit.items():
|
quality_season = "quality_" + str(season)
|
||||||
print(username)
|
value[quality_season] = value.pop("quality")
|
||||||
print(value['pre_cal'])
|
# print(total_credit)
|
||||||
depart_pre = depart_pre + value['pre_cal']
|
total_data.append(total_credit)
|
||||||
depart_real = depart_real + value['real_cal']
|
# print(season)
|
||||||
depart_count = depart_count + value['main_count']
|
season += 1
|
||||||
temp_pre.append(value['pre_cal'])
|
|
||||||
department_cal['pre_cal'] = depart_pre
|
|
||||||
department_cal['real_cal'] = depart_real
|
|
||||||
department_cal['depart_count'] = depart_count
|
|
||||||
department_cal['pre_avg'] = department_cal['pre_cal'] / len(total_credit)
|
|
||||||
department_cal['real_avg'] = department_cal['real_cal'] / len(total_credit)
|
|
||||||
|
|
||||||
# 为页面提供日期信息
|
# new_credit = []
|
||||||
date = str(year) + '年' + str(month) + '月'
|
# for item in total_credit:
|
||||||
|
# for key, value in item.items():
|
||||||
|
# print(total_data, season)
|
||||||
|
dd = defaultdict(list)
|
||||||
|
for d in total_data: # you can list as many input dicts as you want here
|
||||||
|
for key, value in d.items():
|
||||||
|
dd[key].append(value)
|
||||||
|
# print(dd)
|
||||||
|
return dd
|
||||||
|
|
||||||
# return HttpResponse(str(total_credit) + '\n' + str(department_cal))
|
|
||||||
context = {'date': date, 'users_data': total_credit, 'department_cal': department_cal,
|
class TestView(View):
|
||||||
'current_user': current_user}
|
def get(self, request, year=2021, month=7):
|
||||||
return render(request, 'tasks/index.html', context)
|
user_info = User.objects.filter(department=request.user.department) \
|
||||||
|
.values_list('username', 'real_name')
|
||||||
|
user_name = {}
|
||||||
|
for user in user_info:
|
||||||
|
user_name[user[0]] = user[1]
|
||||||
|
|
||||||
|
work_cal = User.objects.filter(department=request.user.department, main_executor__deadline__year=2021) \
|
||||||
|
.order_by('main_executor__deadline').values('main_executor__todo_topic', 'main_executor__deadline')
|
||||||
|
|
||||||
|
# 以用户表查询,按用户列出所参与承办、协办任务,并在之后按用户名分组合并。
|
||||||
|
main_credit = User.objects.filter(department=request.user.department,
|
||||||
|
main_executor__deadline__year=year) \
|
||||||
|
.annotate(main_count=Count('main_executor')) \
|
||||||
|
.order_by('username') \
|
||||||
|
.values('username', 'main_executor', 'main_executor__predict_work', 'main_executor__real_work',
|
||||||
|
'main_executor__evaluate_factor', 'main_executor__maturity', 'main_executor__quality_mark__mark_value__mark_value', 'main_executor__deadline', 'main_count') # 这里的annotate不知会不会有问题
|
||||||
|
|
||||||
|
sub_count = Todo.objects.filter(sub_executor__department=request.user.department,
|
||||||
|
deadline__year=year) \
|
||||||
|
.annotate(sub_count=Count('sub_executor')).values('id', 'sub_count')
|
||||||
|
sub_credit = User.objects.filter(department=request.user.department,
|
||||||
|
sub_executor__deadline__year=year) \
|
||||||
|
.order_by('username') \
|
||||||
|
.values('username', 'real_name', 'sub_executor', 'sub_executor__predict_work', 'sub_executor__real_work',
|
||||||
|
'sub_executor__evaluate_factor', 'sub_executor__maturity', 'sub_executor__quality_mark__mark_value__mark_value', 'sub_executor__deadline')
|
||||||
|
|
||||||
|
# 构建工作包id对应协办人人数的字典
|
||||||
|
sub_exe_count = {}
|
||||||
|
for i in sub_count:
|
||||||
|
key = i['id']
|
||||||
|
value = i['sub_count']
|
||||||
|
sub_exe_count[key] = value
|
||||||
|
# print(sub_exe_count)
|
||||||
|
|
||||||
|
# 计算每个承办任务的预计、实际工作量,并插入字典
|
||||||
|
for i in main_credit:
|
||||||
|
# 将成熟度由百分数转小数,以便其后与其他变量计算 eg. 50% -> 0.5
|
||||||
|
i['main_executor__maturity'] = decimal.Decimal(float(i['main_executor__maturity'].strip('%')) / 100)
|
||||||
|
# print(i['main_executor__maturity'])
|
||||||
|
i['main_pre_cal'] = i['main_executor__predict_work'] * i['main_executor__evaluate_factor'] * i['main_executor__maturity']
|
||||||
|
i['main_real_cal'] = i['main_executor__real_work'] * i['main_executor__evaluate_factor'] * i['main_executor__maturity']
|
||||||
|
# print(i)
|
||||||
|
# print(str(i['sub_executor']))
|
||||||
|
|
||||||
|
# 将协办任务对应的人数插入,计算每个协办任务的预计、实际工作量,并插入字典
|
||||||
|
for i in sub_credit:
|
||||||
|
sub_todo_id = i['sub_executor']
|
||||||
|
i['sub_exe_count'] = sub_exe_count[sub_todo_id]
|
||||||
|
i['sub_executor__maturity'] = decimal.Decimal(float(i['sub_executor__maturity'].strip('%')) / 100)
|
||||||
|
i['sub_pre_cal'] = i['sub_executor__predict_work'] * (1 - i['sub_executor__evaluate_factor']) / i['sub_exe_count'] * i['sub_executor__maturity']
|
||||||
|
i['sub_real_cal'] = i['sub_executor__real_work'] * (1 - i['sub_executor__evaluate_factor']) / i['sub_exe_count'] * i['sub_executor__maturity']
|
||||||
|
i['sub_count'] = 1 # 用于帮助累加程序计算每个用户的协办任务数量, sub_exe_count会返回此协办任务的协办人数,在累加时导致计算错误
|
||||||
|
# print(i)
|
||||||
|
# print(str(i['sub_executor']))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
main_Q1st, main_Q2nd, main_Q3th, main_Q4th = [], [], [], []
|
||||||
|
for i in main_credit:
|
||||||
|
# print(i['main_executor__deadline'].month)
|
||||||
|
deadline_month = i['main_executor__deadline'].month
|
||||||
|
if 1 <= deadline_month <= 3:
|
||||||
|
main_Q1st.append(i)
|
||||||
|
elif 4 <= deadline_month <= 6:
|
||||||
|
main_Q2nd.append(i)
|
||||||
|
elif 7 <= deadline_month <= 9:
|
||||||
|
main_Q3th.append(i)
|
||||||
|
elif 10 <= deadline_month <= 12:
|
||||||
|
main_Q4th.append(i)
|
||||||
|
# print(Q1st, Q2nd, Q3th, Q4th)
|
||||||
|
|
||||||
|
sub_Q1st, sub_Q2nd, sub_Q3th, sub_Q4th = [], [], [], []
|
||||||
|
for i in sub_credit:
|
||||||
|
# print(i['main_executor__deadline'].month)
|
||||||
|
deadline_month = i['sub_executor__deadline'].month
|
||||||
|
if 1 <= deadline_month <= 3:
|
||||||
|
sub_Q1st.append(i)
|
||||||
|
elif 4 <= deadline_month <= 6:
|
||||||
|
sub_Q2nd.append(i)
|
||||||
|
elif 7 <= deadline_month <= 9:
|
||||||
|
sub_Q3th.append(i)
|
||||||
|
elif 10 <= deadline_month <= 12:
|
||||||
|
sub_Q4th.append(i)
|
||||||
|
|
||||||
|
main_list = [main_Q1st, main_Q2nd, main_Q3th, main_Q4th]
|
||||||
|
sub_list = [sub_Q1st, sub_Q2nd, sub_Q3th, sub_Q4th]
|
||||||
|
result = cal_method(main_list, sub_list, user_name)
|
||||||
|
print(result)
|
||||||
|
stat = {}
|
||||||
|
for key, value in result.items():
|
||||||
|
stat[key] = {}
|
||||||
|
for j in value:
|
||||||
|
stat[key]['real_name'] = j['real_name']
|
||||||
|
season = str(j['season'])
|
||||||
|
real_cal_season = 'real_cal_' + season
|
||||||
|
quality_season = 'quality_' + season
|
||||||
|
stat[key][real_cal_season] = j[real_cal_season]
|
||||||
|
stat[key][quality_season] = j[quality_season]
|
||||||
|
print(j)
|
||||||
|
print(stat)
|
||||||
|
|
||||||
|
return HttpResponse(stat)
|
||||||
|
# return render(request, 'tasks/index.html', context)
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
from django.urls import path
|
from django.urls import path, include
|
||||||
|
import debug_toolbar
|
||||||
from apps.tasks import views, tests
|
from apps.tasks import views, tests
|
||||||
|
from TasksManager import settings
|
||||||
|
|
||||||
app_name = 'tasks'
|
app_name = 'tasks'
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.IndexView.as_view(), name='index'),
|
path('', views.IndexView.as_view(), name='index'),
|
||||||
path('<int:year>/<int:month>/', views.IndexView.as_view(), name='index_month'),
|
path('<int:year>/<int:month>/', views.IndexView.as_view(), name='index_month'),
|
||||||
path('test/', tests.TestView.as_view(), name='index'),
|
path('test/', tests.TestView.as_view(), name='test'),
|
||||||
path('login/', views.UserLoginView.as_view(), name='login'),
|
path('login/', views.UserLoginView.as_view(), name='login'),
|
||||||
path('logout/', views.UserLogoutView.as_view(), name='logout'),
|
path('logout/', views.UserLogoutView.as_view(), name='logout'),
|
||||||
path('todolist/', views.TodoListView.as_view(), name='todolist'),
|
path('todolist/', views.TodoListView.as_view(), name='todolist'),
|
||||||
|
@ -16,3 +18,10 @@ urlpatterns = [
|
||||||
path('tasklist/', views.TaskListView.as_view(), name='tasklist'),
|
path('tasklist/', views.TaskListView.as_view(), name='tasklist'),
|
||||||
path('about/', views.AboutView.as_view(), name='about'),
|
path('about/', views.AboutView.as_view(), name='about'),
|
||||||
]
|
]
|
||||||
|
#
|
||||||
|
# if settings.DEBUG:
|
||||||
|
# import debug_toolbar
|
||||||
|
# urlpatterns = [
|
||||||
|
# path('__debug__/', include(debug_toolbar.urls)),
|
||||||
|
# ] + urlpatterns
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ from . import my_query
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
|
import decimal
|
||||||
|
|
||||||
|
|
||||||
class IndexView(View):
|
class IndexView(View):
|
||||||
# TODO 解决系统时间变化,日期不刷新的问题
|
# TODO 解决系统时间变化,日期不刷新的问题
|
||||||
|
@ -88,14 +90,13 @@ class IndexView(View):
|
||||||
vals = {k: item[k] for k in sum_value_keys}
|
vals = {k: item[k] for k in sum_value_keys}
|
||||||
dic[key].update(vals)
|
dic[key].update(vals)
|
||||||
return dic
|
return dic
|
||||||
|
|
||||||
main_credit = solve(main_credit, 'username', ['main_pre_cal', 'main_real_cal', 'main_count'])
|
main_credit = solve(main_credit, 'username', ['main_pre_cal', 'main_real_cal', 'main_count'])
|
||||||
main_credit = dict(main_credit)
|
main_credit = dict(main_credit)
|
||||||
sub_credit = solve(sub_credit, 'username', ['sub_pre_cal', 'sub_real_cal', 'sub_count'])
|
sub_credit = solve(sub_credit, 'username', ['sub_pre_cal', 'sub_real_cal', 'sub_count'])
|
||||||
sub_credit = dict(sub_credit)
|
sub_credit = dict(sub_credit)
|
||||||
total_credit = deepcopy(main_credit)
|
|
||||||
|
|
||||||
# 按用户名合并承办与协办任务字典
|
# 按用户名合并承办与协办任务字典
|
||||||
|
total_credit = deepcopy(main_credit)
|
||||||
for key in sub_credit.keys():
|
for key in sub_credit.keys():
|
||||||
if key in total_credit:
|
if key in total_credit:
|
||||||
total_credit[key].update(sub_credit[key])
|
total_credit[key].update(sub_credit[key])
|
||||||
|
@ -145,12 +146,212 @@ class IndexView(View):
|
||||||
else:
|
else:
|
||||||
department_cal, current_user = {}, {}
|
department_cal, current_user = {}, {}
|
||||||
|
|
||||||
|
|
||||||
|
# 计算实际工作量、完成质量
|
||||||
|
def cal_method(main_list, sub_list, user_name):
|
||||||
|
# print(main_list, sub_list, user_name)
|
||||||
|
|
||||||
|
# sub_credit = sub_list
|
||||||
|
# main_credit = main_list
|
||||||
|
|
||||||
|
total_data = []
|
||||||
|
season = 1
|
||||||
|
# 分别计算每个季度的工作量、评价
|
||||||
|
for main_credit, sub_credit in zip(main_list, sub_list):
|
||||||
|
# TODO 对于完成质量的核算,先对评价求和,再除以已评价的承办任务数
|
||||||
|
# for i in main_credit:
|
||||||
|
# print(i['main_executor__quality_mark__mark_value__mark_value'])
|
||||||
|
# print(main_credit)
|
||||||
|
quality_dict = {}
|
||||||
|
for i in main_credit:
|
||||||
|
# 先赋值0,避免前端显示个[]
|
||||||
|
quality_dict[i['username']] = []
|
||||||
|
if i['main_executor__quality_mark__mark_value__mark_value'] != None:
|
||||||
|
quality_dict[i['username']].append(i['main_executor__quality_mark__mark_value__mark_value'])
|
||||||
|
|
||||||
|
# TEST
|
||||||
|
for i in sub_credit:
|
||||||
|
# 先赋值0,避免前端显示个[]
|
||||||
|
quality_dict[i['username']] = []
|
||||||
|
if i['sub_executor__quality_mark__mark_value__mark_value'] != None:
|
||||||
|
quality_dict[i['username']].append(i['sub_executor__quality_mark__mark_value__mark_value'])
|
||||||
|
|
||||||
|
|
||||||
|
for key, value in quality_dict.items():
|
||||||
|
if value:
|
||||||
|
quality_dict[key] = sum(value) / len(value)
|
||||||
|
# print(quality_dict)
|
||||||
|
|
||||||
|
main_credit = solve(main_credit, 'username',
|
||||||
|
['main_pre_cal', 'main_real_cal', 'main_count', 'main_executor__evaluate_factor'])
|
||||||
|
main_credit = dict(main_credit)
|
||||||
|
sub_credit = solve(sub_credit, 'username', ['sub_pre_cal', 'sub_real_cal', 'sub_count'])
|
||||||
|
sub_credit = dict(sub_credit)
|
||||||
|
|
||||||
|
# 按用户名合并承办与协办任务字典
|
||||||
|
total_credit = deepcopy(main_credit)
|
||||||
|
for key in sub_credit.keys():
|
||||||
|
if key in total_credit:
|
||||||
|
total_credit[key].update(sub_credit[key])
|
||||||
|
else:
|
||||||
|
total_credit[key] = sub_credit[key]
|
||||||
|
|
||||||
|
# print(total_credit['admin']['sub_pre_cal'])
|
||||||
|
# 根据字典内容,计算总工作量
|
||||||
|
for key, value in total_credit.items():
|
||||||
|
# print(value)
|
||||||
|
value['pre_cal'] = value['sub_pre_cal'] + value['main_pre_cal']
|
||||||
|
value['real_cal'] = value['sub_real_cal'] + value['main_real_cal']
|
||||||
|
value['real_name'] = user_name[key]
|
||||||
|
value['season'] = season
|
||||||
|
|
||||||
|
# 由于不计算协办任务,quality_dict会有空值情况
|
||||||
|
try:
|
||||||
|
value['quality'] = quality_dict[key]
|
||||||
|
except:
|
||||||
|
value['quality'] = 0
|
||||||
|
|
||||||
|
for value in total_credit.values():
|
||||||
|
# print(value)
|
||||||
|
real_cal_season = "real_cal_" + str(season)
|
||||||
|
value[real_cal_season] = value.pop("real_cal")
|
||||||
|
quality_season = "quality_" + str(season)
|
||||||
|
value[quality_season] = value.pop("quality")
|
||||||
|
# print(total_credit)
|
||||||
|
total_data.append(total_credit)
|
||||||
|
# print(season)
|
||||||
|
season += 1
|
||||||
|
|
||||||
|
# new_credit = []
|
||||||
|
# for item in total_credit:
|
||||||
|
# for key, value in item.items():
|
||||||
|
# print(total_data, season)
|
||||||
|
dd = defaultdict(list)
|
||||||
|
for d in total_data: # you can list as many input dicts as you want here
|
||||||
|
for key, value in d.items():
|
||||||
|
dd[key].append(value)
|
||||||
|
# print(dd)
|
||||||
|
return dd
|
||||||
|
user_info = User.objects.filter(department=request.user.department) \
|
||||||
|
.values_list('username', 'real_name')
|
||||||
|
user_name = {}
|
||||||
|
for user in user_info:
|
||||||
|
user_name[user[0]] = user[1]
|
||||||
|
|
||||||
|
work_cal = User.objects.filter(department=request.user.department, main_executor__deadline__year=2021) \
|
||||||
|
.order_by('main_executor__deadline').values('main_executor__todo_topic', 'main_executor__deadline')
|
||||||
|
|
||||||
|
# 以用户表查询,按用户列出所参与承办、协办任务,并在之后按用户名分组合并。
|
||||||
|
main_credit = User.objects.filter(department=request.user.department,
|
||||||
|
main_executor__deadline__year=year) \
|
||||||
|
.annotate(main_count=Count('main_executor')) \
|
||||||
|
.order_by('username') \
|
||||||
|
.values('username', 'main_executor', 'main_executor__predict_work', 'main_executor__real_work',
|
||||||
|
'main_executor__evaluate_factor', 'main_executor__maturity', 'main_executor__quality_mark__mark_value__mark_value', 'main_executor__deadline', 'main_count') # 这里的annotate不知会不会有问题
|
||||||
|
|
||||||
|
sub_count = Todo.objects.filter(sub_executor__department=request.user.department,
|
||||||
|
deadline__year=year) \
|
||||||
|
.annotate(sub_count=Count('sub_executor')).values('id', 'sub_count')
|
||||||
|
sub_credit = User.objects.filter(department=request.user.department,
|
||||||
|
sub_executor__deadline__year=year) \
|
||||||
|
.order_by('username') \
|
||||||
|
.values('username', 'real_name', 'sub_executor', 'sub_executor__predict_work', 'sub_executor__real_work',
|
||||||
|
'sub_executor__evaluate_factor', 'sub_executor__maturity', 'sub_executor__quality_mark__mark_value__mark_value', 'sub_executor__deadline')
|
||||||
|
|
||||||
|
# 构建工作包id对应协办人人数的字典
|
||||||
|
sub_exe_count = {}
|
||||||
|
for i in sub_count:
|
||||||
|
key = i['id']
|
||||||
|
value = i['sub_count']
|
||||||
|
sub_exe_count[key] = value
|
||||||
|
# print(sub_exe_count)
|
||||||
|
|
||||||
|
# 计算每个承办任务的预计、实际工作量、成熟度,并插入字典
|
||||||
|
for i in main_credit:
|
||||||
|
# 将成熟度由百分数转小数,以便其后与其他变量计算 eg. 50% -> 0.5
|
||||||
|
print('ad', i['main_executor__maturity'])
|
||||||
|
# 临时补丁,解决用户将成熟度设置为空的问题,后面的协办任务也改了,记得改回去
|
||||||
|
# TODO 数据库中设置成熟度为非空
|
||||||
|
try:
|
||||||
|
i['main_executor__maturity'] = decimal.Decimal(float(i['main_executor__maturity'].strip('%')) / 100)
|
||||||
|
except:
|
||||||
|
i['main_executor__maturity'] = decimal.Decimal(float(0) / 100)
|
||||||
|
# print(i['main_executor__maturity'])
|
||||||
|
i['main_pre_cal'] = i['main_executor__predict_work'] * i['main_executor__evaluate_factor'] * i['main_executor__maturity']
|
||||||
|
i['main_real_cal'] = i['main_executor__real_work'] * i['main_executor__evaluate_factor'] * i['main_executor__maturity']
|
||||||
|
# print(i)
|
||||||
|
# print(str(i['sub_executor']))
|
||||||
|
|
||||||
|
# 将协办任务对应的人数插入,计算每个协办任务的预计、实际工作量,并插入字典
|
||||||
|
for i in sub_credit:
|
||||||
|
sub_todo_id = i['sub_executor']
|
||||||
|
i['sub_exe_count'] = sub_exe_count[sub_todo_id]
|
||||||
|
try:
|
||||||
|
i['sub_executor__maturity'] = decimal.Decimal(float(i['sub_executor__maturity'].strip('%')) / 100)
|
||||||
|
except:
|
||||||
|
i['sub_executor__maturity'] = decimal.Decimal(float(0) / 100)
|
||||||
|
i['sub_pre_cal'] = i['sub_executor__predict_work'] * (1 - i['sub_executor__evaluate_factor']) / i['sub_exe_count'] * i['sub_executor__maturity']
|
||||||
|
i['sub_real_cal'] = i['sub_executor__real_work'] * (1 - i['sub_executor__evaluate_factor']) / i['sub_exe_count'] * i['sub_executor__maturity']
|
||||||
|
i['sub_count'] = 1 # 用于帮助累加程序计算每个用户的协办任务数量, sub_exe_count会返回此协办任务的协办人数,在累加时导致计算错误
|
||||||
|
# print(i)
|
||||||
|
# print(str(i['sub_executor']))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
main_Q1st, main_Q2nd, main_Q3th, main_Q4th = [], [], [], []
|
||||||
|
for i in main_credit:
|
||||||
|
# print(i['main_executor__deadline'].month)
|
||||||
|
deadline_month = i['main_executor__deadline'].month
|
||||||
|
if 1 <= deadline_month <= 3:
|
||||||
|
main_Q1st.append(i)
|
||||||
|
elif 4 <= deadline_month <= 6:
|
||||||
|
main_Q2nd.append(i)
|
||||||
|
elif 7 <= deadline_month <= 9:
|
||||||
|
main_Q3th.append(i)
|
||||||
|
elif 10 <= deadline_month <= 12:
|
||||||
|
main_Q4th.append(i)
|
||||||
|
# print(Q1st, Q2nd, Q3th, Q4th)
|
||||||
|
|
||||||
|
sub_Q1st, sub_Q2nd, sub_Q3th, sub_Q4th = [], [], [], []
|
||||||
|
for i in sub_credit:
|
||||||
|
# print(i['main_executor__deadline'].month)
|
||||||
|
deadline_month = i['sub_executor__deadline'].month
|
||||||
|
if 1 <= deadline_month <= 3:
|
||||||
|
sub_Q1st.append(i)
|
||||||
|
elif 4 <= deadline_month <= 6:
|
||||||
|
sub_Q2nd.append(i)
|
||||||
|
elif 7 <= deadline_month <= 9:
|
||||||
|
sub_Q3th.append(i)
|
||||||
|
elif 10 <= deadline_month <= 12:
|
||||||
|
sub_Q4th.append(i)
|
||||||
|
|
||||||
|
main_list = [main_Q1st, main_Q2nd, main_Q3th, main_Q4th]
|
||||||
|
sub_list = [sub_Q1st, sub_Q2nd, sub_Q3th, sub_Q4th]
|
||||||
|
stat_result = cal_method(main_list, sub_list, user_name)
|
||||||
|
|
||||||
|
stat = {}
|
||||||
|
for key, value in stat_result.items():
|
||||||
|
stat[key] = {}
|
||||||
|
for j in value:
|
||||||
|
stat[key]['real_name'] = j['real_name']
|
||||||
|
season = str(j['season'])
|
||||||
|
real_cal_season = 'real_cal_' + season
|
||||||
|
quality_season = 'quality_' + season
|
||||||
|
stat[key][real_cal_season] = j[real_cal_season]
|
||||||
|
stat[key][quality_season] = j[quality_season]
|
||||||
|
print(stat_result)
|
||||||
|
|
||||||
|
# return HttpResponse(result.items())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 为页面提供日期信息
|
# 为页面提供日期信息
|
||||||
date = str(year) + '年' + str(month) + '月'
|
date = str(year) + '年' + str(month) + '月'
|
||||||
|
|
||||||
# return HttpResponse(str(total_credit) + '\n' + str(department_cal))
|
# return HttpResponse(str(total_credit) + '\n' + str(department_cal))
|
||||||
context = {'date': date, 'users_data': total_credit, 'department_cal': department_cal,
|
context = {'date': date, 'users_data': total_credit, 'department_cal': department_cal,
|
||||||
'current_user': current_user}
|
'current_user': current_user, 'stat': stat}
|
||||||
return render(request, 'tasks/index.html', context)
|
return render(request, 'tasks/index.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,3 +18,4 @@ sqlparse==0.4.1
|
||||||
tablib==3.0.0
|
tablib==3.0.0
|
||||||
xlrd==2.0.1
|
xlrd==2.0.1
|
||||||
xlwt==1.3.0
|
xlwt==1.3.0
|
||||||
|
django-debug-toolbar~=3.2.2
|
|
@ -9,6 +9,7 @@
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<h1>总览 ({{ date }}) </h1>
|
<h1>总览 ({{ date }}) </h1>
|
||||||
|
<h1><font color="#FF0000">测试版,请勿用于生产环境!!!</font></h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
{# <ol class="breadcrumb float-sm-right">#}
|
{# <ol class="breadcrumb float-sm-right">#}
|
||||||
|
@ -292,21 +293,35 @@
|
||||||
<div id="example2_wrapper" class="dataTables_wrapper dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"></div><div class="col-sm-12 col-md-6"></div></div><div class="row"><div class="col-sm-12"><table id="example2" class="table table-bordered table-hover dataTable" role="grid" aria-describedby="example2_info">
|
<div id="example2_wrapper" class="dataTables_wrapper dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"></div><div class="col-sm-12 col-md-6"></div></div><div class="row"><div class="col-sm-12"><table id="example2" class="table table-bordered table-hover dataTable" role="grid" aria-describedby="example2_info">
|
||||||
<thead>
|
<thead>
|
||||||
<tr role="row">
|
<tr role="row">
|
||||||
<th class="sorting_asc" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-sort="ascending" aria-label="Rendering engine: activate to sort column descending">姓名</th>
|
<th class="sorting_asc" tabindex="0" aria-controls="example2" rowspan="2" colspan="1" aria-sort="ascending" aria-label="Rendering engine: activate to sort column descending">姓名</th>
|
||||||
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-label="Browser: activate to sort column ascending">承办任务数</th>
|
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="2" style="text-align: center">一季度</th>
|
||||||
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-label="Platform(s): activate to sort column ascending">协办任务数</th>
|
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="2" style="text-align: center">二季度</th>
|
||||||
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-label="Engine version: activate to sort column ascending">预计工作量</th>
|
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="2" style="text-align: center">三季度</th>
|
||||||
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="1" aria-label="CSS grade: activate to sort column ascending">实际工作量</th>
|
<th class="sorting" tabindex="0" aria-controls="example2" rowspan="1" colspan="2" style="text-align: center">四季度</th>
|
||||||
|
</tr>
|
||||||
|
<tr role="row">
|
||||||
|
<th>实际工作量</th>
|
||||||
|
<th>完成质量</th>
|
||||||
|
<th>实际工作量</th>
|
||||||
|
<th>完成质量</th>
|
||||||
|
<th>实际工作量</th>
|
||||||
|
<th>完成质量</th>
|
||||||
|
<th>实际工作量</th>
|
||||||
|
<th>完成质量</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for user in users_data.values %}
|
{% for user in stat.values %}
|
||||||
<tr role="row" class="odd">
|
<tr role="row" class="odd">
|
||||||
<td class="sorting_1">{{ user.real_name }}</td>
|
<td class="sorting_1">{{ user.real_name }}</td>
|
||||||
<td>{{ user.main_executor_count}}</td>
|
<td>{{ user.real_cal_1}}</td>
|
||||||
<td>{{ user.sub_executor_count}}</td>
|
<td>{{ user.quality_1 }}</td>
|
||||||
<td>{{ user.pre_credit|floatformat:'1' }}</td>
|
<td>{{ user.real_cal_2 }}</td>
|
||||||
<td>{{ user.real_credit|floatformat:'1' }}</td>
|
<td>{{ user.quality_2|floatformat:'1' }}</td>
|
||||||
|
<td>{{ user.real_cal_3 }}</td>
|
||||||
|
<td>{{ user.quality_3 }}</td>
|
||||||
|
<td>{{ user.real_cal_4 }}</td>
|
||||||
|
<td>{{ user.quality_4|default_if_none:'0' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
Loading…
Reference in New Issue