XH_Digital_Management/application/hrm_mgnt/views.py

1282 lines
52 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
from datetime import datetime
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.http import JsonResponse, Http404
from django.shortcuts import render
from django.template.loader import render_to_string
from django.urls import reverse
from django.views.decorators.csrf import csrf_protect
from application.hrm_mgnt.forms import *
from application.hrm_mgnt.models import *
from common.auth import custom_permission_required
from common.utils.page_helper import paginate_query_and_assign_numbers
from django.http import JsonResponse
from django.core.files.storage import default_storage
from django.conf import settings
from openpyxl import load_workbook
from django.apps import apps
from rest_framework.serializers import ModelSerializer
from django.core.exceptions import ValidationError
import os
@login_required
@custom_permission_required('hrm_mgnt.view_employeeinformation')
def emp_list_view(request):
# 声明查询集
query_set = EmployeeInformation.objects.filter().order_by('-employee_id')
# 获取查询参数
name = request.GET.get('name', '')
department = request.GET.get('department', '')
# 根据提供的参数进行筛选
if name:
query_set = query_set.filter(name__icontains=name)
if department:
query_set = query_set.filter(primary_department=department)
# 对查询结果进行分页每页10条记录
items = paginate_query_and_assign_numbers(
request=request,
queryset=query_set,
per_page=10
)
# 构建上下文查询参数字符串
query_params = '&name={}'.format(name) + '&department={}'.format(department)
# Excel上传模板
template_name = "人力资源管理-人员基本信息-Excel上传模板.xlsx"
# 构建上下文
context = {
# 模型设置
"model_config": "hrm_mgnt.EmployeeInformation",
# 分页数据
"items": items,
# 面包屑
"breadcrumb_list": [
{"title": "首页", "name": "index"},
{"title": "人力资源管理", "name": "index"},
{"title": "人员基本信息表", "name": "emt_list"}
],
# 筛选表单选项
"filters": [
{
"type": "text",
"id": "name",
"name": "name",
"label": "姓名",
"placeholder": "请输入姓名"
},
{
"type": "select",
"id": "department",
"name": "department",
"label": "一级部门",
"options": [
{"value": "天信", "display": "天信"},
{"value": "混改", "display": "混改"},
{"value": "艾力芬特", "display": "艾力芬特"},
{"value": "星河", "display": "星河"},
{"value": "星海", "display": "星海"}
]
}
],
# Excel上传解析
"excel_upload_config": {
"template_url": reverse("download_template", kwargs={'template_name': template_name}),
"parse_url": reverse("common_excel_parse"),
"save_url": reverse("save_excel_table_data"),
"fields_preview_config": {
"name": {"type": "text", "width": "180px"},
"id_number": {"type": "text", "width": "220px"},
"gender": {"type": "text", "width": "100px"},
"birthday": {"type": "date", "width": "110px"},
"age": {"type": "text", "width": "80px"},
"height": {"type": "text", "width": "100px"},
"weight": {"type": "text", "width": "100px"},
"blood_type": {"type": "text", "width": "80px"},
"ethnicity": {"type": "text", "width": "180px"},
"domicile": {"type": "text", "width": "220px"},
"marital_status": {"type": "text", "width": "120px"},
"political_affiliation": {"type": "text", "width": "120px"},
"entry_date": {"type": "date", "width": "110px"},
"regularization_date": {"type": "date", "width": "110px"},
"departure_date": {"type": "date", "width": "110px"},
"employment_type": {"type": "text", "width": "100px"},
"status": {"type": "text", "width": "80px"},
"primary_department": {"type": "text", "width": "180px"},
"secondary_department": {"type": "text", "width": "180px"},
"position": {"type": "text", "width": "180px"},
"grade": {"type": "text", "width": "120px"},
"contract_end_date": {"type": "date", "width": "110px"},
"mobile_number": {"type": "text", "width": "150px"},
"email": {"type": "text", "width": "200px"},
"mailing_address": {"type": "text", "width": "280px"},
"emergency_contact": {"type": "text", "width": "150px"},
"relation_with_contact": {"type": "text", "width": "150px"},
"emergency_contact_phone": {"type": "text", "width": "150px"},
"education": {"type": "text", "width": "100px"},
"undergraduate_school": {"type": "text", "width": "220px"},
"graduate_school": {"type": "text", "width": "220px"},
"major": {"type": "text", "width": "220px"},
"technical_title": {"type": "text", "width": "180px"},
"base_salary": {"type": "text", "width": "120px"},
"salary_account_number": {"type": "text", "width": "220px"},
"bank_of_salary_account": {"type": "text", "width": "220px"},
"resignation_type": {"type": "text", "width": "120px"},
"resignation_reason": {"type": "textarea", "width": "300px"}
}
},
# 上下文查询参数
"query_params": query_params,
# 表格显示排除配置
"table_exclude_field_name": ['employee_id'],
# 筛选表单提交链接
"form_action_url": "emp_list",
# 修改对象提交链接
"modify_url": reverse("emp_list_modify"),
# 新增对象提交链接
"add_url": reverse("emp_list_add"),
# 删除对象提交链接
"delete_url": reverse("emp_list_delete"),
}
return render(request, 'emp_list.html', context)
@login_required
@custom_permission_required('hrm_mgnt.add_employeeinformation')
def emp_list_add(request):
if request.method == 'POST':
form = EmployeeInformationAddForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "添加成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
form = EmployeeInformationAddForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.change_employeeinformation')
def emp_list_modify(request):
if request.method == 'POST':
current_base_salary = None
if 'id' in request.POST:
instance = EmployeeInformation.objects.get(employee_id=request.POST['id'])
current_base_salary = instance.base_salary # 获取当前基本工资
form = EmployeeInformationForm(request.POST, instance=instance)
else:
form = EmployeeInformationEditForm(request.POST)
if form.is_valid():
employee = form.save()
new_base_salary = form.cleaned_data.get('base_salary')
# 判断基本工资是否有变化
if 'id' in request.POST and current_base_salary != new_base_salary:
SalaryChangeRecord.objects.create(
employee=employee,
change_date=datetime.datetime.now(),
previous_value=current_base_salary if current_base_salary else 0,
new_value=new_base_salary,
approved_by=request.user.username
)
return JsonResponse({"message": "保存成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
if 'id' in request.GET:
try:
instance = EmployeeInformation.objects.get(employee_id=request.GET['id'])
form = EmployeeInformationEditForm(instance=instance)
except EmployeeInformation.DoesNotExist:
raise Http404("对象不存在")
else:
form = EmployeeInformationEditForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.delete_employeeinformation')
def emp_list_delete(request):
if request.method == 'GET':
employee_id = request.GET.get('employee_id')
EmployeeInformation.objects.filter(employee_id=employee_id).delete()
return JsonResponse({"message": "删除成功"})
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.view_salarychangerecord')
def get_salary_change_records(request, employee_id):
records = SalaryChangeRecord.objects.filter(employee_id=employee_id).values(
'change_date', 'previous_value', 'new_value', 'approved_by')
return JsonResponse(list(records), safe=False)
@login_required
@custom_permission_required('hrm_mgnt.view_employeeattendancerecord')
def attd_rec_list_view(request):
# 声明查询集
query_set = EmployeeAttendanceRecord.objects.filter().order_by('-record_id')
# 获取查询参数
employee = request.GET.get('employee', '')
year_month = request.GET.get('year_month', '')
primary_department = request.GET.get('primary_department', '')
# 根据提供的参数进行筛选
if employee:
query_set = query_set.filter(employee__name__icontains=employee)
if year_month:
query_set = query_set.filter(year_month__icontains=year_month)
if primary_department:
query_set = query_set.filter(employee__primary_department__icontains=primary_department)
# 对查询结果进行分页每页10条记录
items = paginate_query_and_assign_numbers(
request=request,
queryset=query_set,
per_page=10
)
# 构建上下文查询参数字符串
query_params = '&employee={}'.format(employee) + '&year_month={}'.format(
year_month) + '&primary_department={}'.format(primary_department)
# Excel上传模板
template_name = "人力资源管理-员工考勤记录-Excel上传模板.xlsx"
# 构建上下文
context = {
"model_config": 'hrm_mgnt.EmployeeAttendanceRecord',
"items": items,
"breadcrumb_list": [
{"title": "首页", "name": "index"},
{"title": "人力资源管理", "name": "index"},
{"title": "员工考勤记录表", "name": "attd_rec_list"}
],
"filters": [
{"type": "text", "id": "employee", "name": "employee", "label": "员工", "placeholder": "请输入员工姓名"},
{"type": "month", "id": "year_month", "name": "year_month", "label": "年月"},
{"type": "select", "id": "primary_department", "name": "primary_department", "label": "一级部门",
"options": [{"value": "天信", "display": "天信"}, {"value": "混改", "display": "混改"},
{"value": "艾力芬特", "display": "艾力芬特"}, {"value": "星河", "display": "星河"},
{"value": "星海", "display": "星海"}]}
],
"excel_upload_config": {
"template_url": reverse("download_template", kwargs={'template_name': template_name}),
"parse_url": reverse("common_excel_parse_attd"),
"save_url": reverse("save_excel_table_data_attd"),
"fields_preview_config": {
"employee": {"type": "text", "width": "180px"},
"year_month": {"type": "date", "width": "110px"},
"late": {"type": "number", "width": "80px"},
"early_leave": {"type": "number", "width": "80px"},
"absenteeism": {"type": "number", "width": "80px"},
"annual_leave": {"type": "number", "width": "80px"},
"personal_leave": {"type": "number", "width": "80px"},
"sick_leave": {"type": "number", "width": "80px"},
}
},
"query_params": query_params,
"form_action_url": 'attd_rec_list',
"modify_url": reverse("attd_rec_list_modify"),
"add_url": reverse("attd_rec_list_add"),
"delete_url": reverse("attd_rec_list_delete"),
"table_exclude_field_name": ['record_id'],
}
return render(request, 'attd_list.html', context)
@login_required
@custom_permission_required('hrm_mgnt.add_employeeattendancerecord')
def attd_rec_list_add(request):
if request.method == 'POST':
form = EmployeeAttendanceRecordForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "添加成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
form = EmployeeAttendanceRecordForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.change_employeeattendancerecord')
def attd_rec_list_modify(request):
if request.method == 'POST':
if 'id' in request.POST:
instance = EmployeeAttendanceRecord.objects.get(record_id=request.POST['id'])
form = EmployeeAttendanceRecordForm(request.POST, instance=instance)
else:
form = EmployeeAttendanceRecordForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "保存成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
if 'id' in request.GET:
try:
instance = EmployeeAttendanceRecord.objects.get(record_id=request.GET['id'])
form = EmployeeAttendanceRecordForm(instance=instance)
except EmployeeAttendanceRecord.DoesNotExist:
raise Http404("对象不存在")
else:
form = EmployeeAttendanceRecordForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.delete_employeeattendancerecord')
def attd_rec_list_delete(request):
if request.method == 'GET':
record_id = request.GET.get('record_id')
EmployeeAttendanceRecord.objects.filter(record_id=record_id).delete()
return JsonResponse({"message": "删除成功"})
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.view_otherleavedetails')
def get_other_leave_details(request, attendance_record_id):
records = OtherLeaveDetails.objects.filter(attendance_record_id=attendance_record_id).values(
'leave_type', 'days', 'description')
return JsonResponse(list(records), safe=False)
@login_required
@custom_permission_required('hrm_mgnt.view_annualleaverecord')
def alv_list_view(request):
# 声明查询集
query_set = AnnualLeaveRecord.objects.filter().order_by('-record_id')
# 获取查询参数
employee_name = request.GET.get('employee_name', '')
year = request.GET.get('year', '')
# 根据提供的参数进行筛选
if employee_name:
query_set = query_set.filter(employee_name__icontains=employee_name)
if year:
query_set = query_set.filter(year__icontains=year)
# 对查询结果进行分页每页10条记录
items = paginate_query_and_assign_numbers(
request=request,
queryset=query_set,
per_page=10
)
# 构建上下文查询参数字符串
query_params = '&employee_name={}'.format(employee_name) + '&year={}'.format(year)
# Excel上传模板
template_name = "人力资源管理-年假使用记录-Excel上传模板.xlsx"
# 构建上下文
context = {
"model_config": 'hrm_mgnt.AnnualLeaveRecord',
"items": items,
"breadcrumb_list": [
{"title": "首页", "name": "index"},
{"title": "人力资源管理", "name": "index"},
{"title": "年假使用记录", "name": "alv_list"}
],
"filters": [
{"type": "text", "id": "employee_name", "name": "employee_name", "label": "姓名",
"placeholder": "请输入姓名"},
{"type": "select", "id": "year", "name": "year", "label": "年度",
"options": [{"value": "2024", "display": "2024"}, {"value": "2023", "display": "2023"},
{"value": "2022", "display": "2022"}, {"value": "2021", "display": "2021"},
{"value": "2020", "display": "2020"}]}
],
"excel_upload_config": {
"template_url": reverse("download_template", kwargs={'template_name': template_name}),
"parse_url": reverse("common_excel_parse"),
"save_url": reverse("save_excel_table_data"),
"fields_preview_config": {
"year": {"type": "text", "width": "80px"},
"employee_name": {"type": "text", "width": "180px"},
"primary_department": {"type": "text", "width": "180px"},
"total_annual_leave": {"type": "number", "width": "80px"},
"used_annual_leave": {"type": "number", "width": "80px"},
"remaining_annual_leave": {"type": "number", "width": "80px"}
}
},
"query_params": query_params,
"form_action_url": 'alv_list',
"modify_url": reverse("alv_list_modify"),
"add_url": reverse("alv_list_add"),
"delete_url": reverse("alv_list_delete"),
"table_exclude_field_name": ['record_id'],
}
return render(request, 'items_list.html', context)
@login_required
@custom_permission_required('hrm_mgnt.add_annualleaverecord')
def alv_list_add(request):
if request.method == 'POST':
form = AnnualLeaveRecordForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "添加成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
form = AnnualLeaveRecordForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.change_annualleaverecord')
def alv_list_modify(request):
if request.method == 'POST':
if 'id' in request.POST:
instance = AnnualLeaveRecord.objects.get(record_id=request.POST['id'])
form = AnnualLeaveRecordForm(request.POST, instance=instance)
else:
form = AnnualLeaveRecordForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "保存成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
if 'id' in request.GET:
try:
instance = AnnualLeaveRecord.objects.get(record_id=request.GET['id'])
form = AnnualLeaveRecordForm(instance=instance)
except AnnualLeaveRecord.DoesNotExist:
raise Http404("对象不存在")
else:
form = AnnualLeaveRecordForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.delete_annualleaverecord')
def alv_list_delete(request):
if request.method == 'GET':
record_id = request.GET.get('record_id')
AnnualLeaveRecord.objects.filter(record_id=record_id).delete()
return JsonResponse({"message": "删除成功"})
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.view_rank')
def rk_list_view(request):
# 声明查询集
query_set = Rank.objects.filter().order_by('-rank_id')
# 获取查询参数
rank_name = request.GET.get('rank_name', '')
# 根据提供的参数进行筛选
if rank_name:
query_set = query_set.filter(rank_name__icontains=rank_name)
# 对查询结果进行分页每页10条记录
items = paginate_query_and_assign_numbers(
request=request,
queryset=query_set,
per_page=10
)
# 构建上下文查询参数字符串
query_params = '&rank_name={}'.format(rank_name)
# Excel上传模板
template_name = "人力资源管理-职级表-Excel上传模板.xlsx"
# 构建上下文
context = {
"model_config": 'hrm_mgnt.Rank',
"items": items,
"breadcrumb_list": [
{"title": "首页", "name": "index"},
{"title": "人力资源管理", "name": "index"},
{"title": "职级表", "name": "rk_list"}
],
"filters": [{"type": "text", "id": "rank_name", "name": "rank_name", "label": "职级名称",
"placeholder": "请输入职级名称"}],
"excel_upload_config": {
"template_url": reverse("download_template", kwargs={'template_name': template_name}),
"parse_url": reverse("common_excel_parse"),
"save_url": reverse("save_excel_table_data"),
"fields_preview_config": {
"rank_name": {"type": "text", "width": "180px"},
"rank_description": {"type": "text", "width": "220px"},
}
},
"query_params": query_params,
"form_action_url": 'rk_list',
"modify_url": reverse("rk_list_modify"),
"add_url": reverse("rk_list_add"),
"delete_url": reverse("rk_list_delete"),
"table_exclude_field_name": ['rank_id'],
}
return render(request, 'items_list.html', context)
@login_required
@custom_permission_required('hrm_mgnt.add_rank')
def rk_list_add(request):
if request.method == 'POST':
form = RankForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "添加成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
form = RankForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.change_rank')
def rk_list_modify(request):
if request.method == 'POST':
if 'id' in request.POST:
instance = Rank.objects.get(rank_id=request.POST['id'])
form = RankForm(request.POST, instance=instance)
else:
form = RankForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "保存成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
if 'id' in request.GET:
try:
instance = Rank.objects.get(rank_id=request.GET['id'])
form = RankForm(instance=instance)
except Rank.DoesNotExist:
raise Http404("对象不存在")
else:
form = RankForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.delete_rank')
def rk_list_delete(request):
if request.method == 'GET':
rank_id = request.GET.get('rank_id')
Rank.objects.filter(rank_id=rank_id).delete()
return JsonResponse({"message": "删除成功"})
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.view_position')
def pst_list_view(request):
# 声明查询集
query_set = Position.objects.filter().order_by('-position_id')
# 获取查询参数
position_name = request.GET.get('position_name', '')
# 根据提供的参数进行筛选
if position_name:
query_set = query_set.filter(position_name__icontains=position_name)
# 对查询结果进行分页每页10条记录
items = paginate_query_and_assign_numbers(
request=request,
queryset=query_set,
per_page=10
)
# 构建上下文查询参数字符串
query_params = '&position_name={}'.format(position_name)
# Excel上传模板
template_name = "人力资源管理-岗位表-Excel上传模板.xlsx"
# 构建上下文
context = {
"model_config": 'hrm_mgnt.Position',
"items": items,
"breadcrumb_list": [
{"title": "首页", "name": "index"},
{"title": "人力资源管理", "name": "index"},
{"title": "岗位表", "name": "pst_list"}
],
"filters": [
{"type": "text", "id": "position_name", "name": "position_name", "label": "岗位名称",
"placeholder": "请输入岗位名称"}
],
"excel_upload_config": {
"template_url": reverse("download_template", kwargs={'template_name': template_name}),
"parse_url": reverse("common_excel_parse"),
"save_url": reverse("save_excel_table_data"),
"fields_preview_config": {
"position_name": {"type": "text", "width": "180px"},
"position_description": {"type": "text", "width": "220px"},
}
},
"query_params": query_params,
"form_action_url": 'pst_list',
"modify_url": reverse("pst_list_modify"),
"add_url": reverse("pst_list_add"),
"delete_url": reverse("pst_list_delete"),
"table_exclude_field_name": ['position_id'],
}
return render(request, 'items_list.html', context)
@login_required
@custom_permission_required('hrm_mgnt.add_position')
def pst_list_add(request):
if request.method == 'POST':
form = PositionForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "添加成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
form = PositionForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.change_position')
def pst_list_modify(request):
if request.method == 'POST':
if 'id' in request.POST:
instance = Position.objects.get(position_id=request.POST['id'])
form = PositionForm(request.POST, instance=instance)
else:
form = PositionForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "保存成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
if 'id' in request.GET:
try:
instance = Position.objects.get(position_id=request.GET['id'])
form = PositionForm(instance=instance)
except Position.DoesNotExist:
raise Http404("对象不存在")
else:
form = PositionForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
@custom_permission_required('hrm_mgnt.delete_position')
def pst_list_delete(request):
if request.method == 'GET':
position_id = request.GET.get('position_id')
Position.objects.filter(position_id=position_id).delete()
return JsonResponse({"message": "删除成功"})
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
def emp_list_for_create_account_profile(request):
# 查询还没有创建AccountProfile的员工信息
query_set = EmployeeInformation.objects.exclude(account_profile__isnull=False).order_by('-employee_id')
# 获取查询参数
name = request.GET.get('name', '')
# 根据提供的参数进行筛选
if name:
query_set = query_set.filter(name__icontains=name)
# 对查询结果进行分页
paginator = Paginator(query_set, 10) # 每页显示10条记录
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
# 创建员工信息的列表,包含需要的字段
employees = list(page_obj.object_list.values(
'employee_id', 'name', 'email', 'mobile_number', 'primary_department', 'position'
))
# 返回JSON响应
return JsonResponse({
'success': True,
'employees': employees,
'has_previous': page_obj.has_previous(),
'has_next': page_obj.has_next(),
'num_pages': paginator.num_pages,
'current_page': page_obj.number
})
@login_required
# @custom_permission_required('hrm_mgnt.view_performanceevaluation')
def performance_list_view(request):
# 声明查询集
query_set = PerformanceEvaluation.objects.select_related('employee').order_by('-performance_id')
# 获取查询参数
name = request.GET.get('name', '')
department = request.GET.get('department', '')
# 根据提供的参数进行筛选
if name:
query_set = query_set.filter(employee__name__icontains=name)
if department:
query_set = query_set.filter(employee__primary_department=department)
# 对查询结果进行分页每页10条记录
items = paginate_query_and_assign_numbers(
request=request,
queryset=query_set,
per_page=10
)
# 构建上下文查询参数字符串
query_params = '&name={}'.format(name) + '&department={}'.format(department)
# Excel上传模板
template_name = "人力资源管理-员工绩效-Excel上传模板.xlsx"
# 构建上下文
context = {
"model_config": "hrm_mgnt.PerformanceEvaluation",
"items": items,
"breadcrumb_list": [
{"title": "首页", "name": "index"},
{"title": "人力资源管理", "name": "index"},
{"title": "员工绩效表", "name": "performance_list"}
],
"filters": [
{
"type": "text",
"id": "name",
"name": "name",
"label": "姓名",
"placeholder": "请输入姓名"
},
{
"type": "select",
"id": "department",
"name": "department",
"label": "一级部门",
"options": [
{"value": "天信", "display": "天信"},
{"value": "混改", "display": "混改"},
{"value": "艾力芬特", "display": "艾力芬特"},
{"value": "星河", "display": "星河"},
{"value": "星海", "display": "星海"}
]
}
],
"table_exclude_field_name": ['performance_id'],
"excel_upload_config": {
"template_url": reverse("download_template", kwargs={'template_name': template_name}),
"parse_url": reverse("common_excel_parse_pe"),
"save_url": reverse("save_excel_table_data_pe"),
"fields_preview_config": {
"employee": {"type": "text", "width": "180px"},
"year": {"type": "text", "width": "180px"},
"performance_score": {"type": "number", "width": "180px"},
}
},
"query_params": query_params,
"form_action_url": "performance_list",
"modify_url": reverse("performance_modify"),
"add_url": reverse("performance_add"),
"delete_url": reverse("performance_delete"),
}
return render(request, 'performance_list.html', context)
@login_required
# @custom_permission_required('hrm_mgnt.add_performanceevaluation')
def performance_add(request):
if request.method == 'POST':
form = PerformanceEvaluationAddForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "添加成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
form = PerformanceEvaluationAddForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
# @custom_permission_required('hrm_mgnt.change_performanceevaluation')
def performance_modify(request):
if request.method == 'POST':
if 'id' in request.POST:
instance = PerformanceEvaluation.objects.get(performance_id=request.POST['id'])
form = PerformanceEvaluationForm(request.POST, instance=instance)
else:
form = PerformanceEvaluationForm(request.POST)
if form.is_valid():
form.save()
return JsonResponse({"message": "保存成功"})
else:
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html, "errors": form.errors}, status=400)
elif request.method == 'GET':
if 'id' in request.GET:
try:
instance = PerformanceEvaluation.objects.get(performance_id=request.GET['id'])
form = PerformanceEvaluationForm(instance=instance)
except PerformanceEvaluation.DoesNotExist:
raise Http404("对象不存在")
else:
form = PerformanceEvaluationForm()
form_html = render_to_string('form_partial.html', {'form': form}, request)
return JsonResponse({"form_html": form_html})
else:
return JsonResponse({"message": "无效的请求方法"}, status=405)
@login_required
# @custom_permission_required('hrm_mgnt.delete_performanceevaluation')
def performance_delete(request):
if request.method == 'GET':
performance_id = request.GET.get('performance_id')
PerformanceEvaluation.objects.filter(performance_id=performance_id).delete()
return JsonResponse({"message": "删除成功"})
return JsonResponse({"message": "无效的请求方法"}, status=405)
@csrf_protect
@login_required
def common_excel_parse(request):
"""
该函数用于解析上传的Excel文件并返回数据。
Args:
request: HTTP请求对象包含上传的Excel文件。
Returns:
JsonResponse: 包含解析后的Excel数据的JSON响应或包含错误消息的JSON响应。
Raises:
N/A
"""
# 如果是POST请求并且有上传的文件
if request.method == 'POST' and request.FILES:
# 获取上传的Excel文件
excel_file = request.FILES.get('excel_file')
# 如果没有提供文件,返回错误响应
if not excel_file:
return JsonResponse({'error': '请先选择文件。'}, status=400)
# 获取模型名称
model_config = request.POST.get('model_config', '')
# 动态获取模型
try:
app_label, model_name = model_config.split('.')
model = apps.get_model(app_label, model_name)
except (LookupError, KeyError, ValueError):
return JsonResponse({'error': '模型配置错误。'}, status=400)
# 获取模型中配置的不需要的字段
exclude_fields = getattr(model, 'excluded_fields', [])
# 保存文件到服务器
file_name = default_storage.save(excel_file.name, excel_file)
file_path = os.path.join(settings.MEDIA_ROOT, file_name)
def create_dynamic_serializer(mod, include):
class DynamicSerializer(ModelSerializer):
class Meta:
model = mod
fields = include
def to_representation(self, instance):
representation = super().to_representation(instance)
if 'employee' in representation and instance.employee:
representation['employee'] = instance.employee.name
return representation
return DynamicSerializer
try:
# 打开并解析Excel文件
workbook = load_workbook(file_path, data_only=True)
sheet = workbook.active
data = []
# 读取第一行作为表头
header_row = [cell.value for cell in sheet[1]]
# 获取字段名和 verbose_name排除索引字段
model_fields = [field.name for field in model._meta.fields if
not field.primary_key and field.name not in exclude_fields]
model_verbose_name = [field.verbose_name for field in model._meta.fields if
not field.primary_key and field.name not in exclude_fields]
if not all(item in model_verbose_name for item in header_row):
return JsonResponse({'error': '表头不匹配请使用正确的Excel上传模板。'}, status=400)
# 组成 fields_map
fields_map = dict(zip(model_fields, header_row))
fields_map_nf = dict(zip(header_row, model_fields))
# 创建一个映射将Excel表头映射到模型字段名
header_to_field_map = {header: fields_map_nf[header] for header in header_row}
header_fields = [header_to_field_map[header] for header in header_row]
for row in sheet.iter_rows(min_row=2, values_only=True):
if not all(value is None for value in row):
instance_data = dict(zip(model_fields, row))
# 处理employee字段假设模型中有employee字段并且Excel文件中的表头包含员工姓名
employee_name = instance_data.get('employee')
if employee_name:
try:
employee_instance = EmployeeInformation.objects.get(name=employee_name)
instance_data['employee'] = employee_instance
except EmployeeInformation.DoesNotExist:
return JsonResponse({'error': f'找不到姓名为 {employee_name} 的员工信息。'}, status=400)
instance = model(**instance_data)
try:
instance.full_clean()
data.append(instance)
except ValidationError as e:
return JsonResponse({'error': f'数据校验错误: {e.message_dict}'}, status=400)
# 动态获取序列化器
serializer_class = create_dynamic_serializer(model, include=header_fields)
serializer = serializer_class(data, many=True)
# 清理,删除上传的文件
os.remove(file_path)
return JsonResponse({"table_data": serializer.data, "fields_map": fields_map}, safe=False)
except Exception as e:
# 清理,删除上传的文件
os.remove(file_path)
return JsonResponse({'error': f'解析文件时出错: {str(e)}'}, status=500)
return JsonResponse({'error': '请求错误'}, status=400)
@csrf_protect
@login_required
def save_excel_table_data(request):
if request.method == 'POST':
try:
data = json.loads(request.body)
model_config = data.get('model_config')
table_data = data.get('table_data')
if not model_config or not table_data:
return JsonResponse({'error': '缺少必要的参数'}, status=400)
# 分割 model_config 以获取 app_label 和 model_name
try:
app_label, model_name = model_config.split('.')
Model = apps.get_model(app_label, model_name)
except (ValueError, LookupError):
return JsonResponse({'error': '无效的 model_config'}, status=400)
# 获取模型中配置的不需要的字段
exclude_fields = getattr(Model, 'excluded_fields', [])
# 创建模型实例列表
instances = []
for row_data in table_data:
# 处理employee字段假设模型中有employee字段并且table_data中包含员工姓名
employee_name = row_data.get('employee')
if employee_name:
try:
employee_instance = EmployeeInformation.objects.get(name=employee_name)
row_data['employee'] = employee_instance
except EmployeeInformation.DoesNotExist:
return JsonResponse({'error': f'找不到姓名为 {employee_name} 的员工信息。'}, status=400)
try:
# 排除不需要的字段
instance_data = {key: value for key, value in row_data.items() if key not in exclude_fields}
instance = Model(**instance_data)
instance.full_clean() # 验证数据
instances.append(instance)
except ValidationError as e:
return JsonResponse({'error': f'数据校验错误: {e.message_dict}'}, status=400)
except Exception as e:
return JsonResponse({'error': f'创建实例时出错: {str(e)}'}, status=500)
# 批量创建模型实例
try:
Model.objects.bulk_create(instances)
except Exception as e:
return JsonResponse({'error': f'批量保存数据时出错: {str(e)}'}, status=500)
return JsonResponse({'message': '表格数据保存成功'}, status=200)
except json.JSONDecodeError:
return JsonResponse({'error': '无效的JSON格式'}, status=400)
except Exception as e:
return JsonResponse({'error': f'服务器内部错误: {str(e)}'}, status=500)
return JsonResponse({'error': '无效的请求方法'}, status=400)
@csrf_protect
@login_required
def common_excel_parse_pe(request):
"""
该函数用于解析上传的Excel文件并返回数据。
Args:
request: HTTP请求对象包含上传的Excel文件。
Returns:
JsonResponse: 包含解析后的Excel数据的JSON响应或包含错误消息的JSON响应。
Raises:
N/A
"""
# 如果是POST请求并且有上传的文件
if request.method == 'POST' and request.FILES:
# 获取上传的Excel文件
excel_file = request.FILES.get('excel_file')
# 如果没有提供文件,返回错误响应
if not excel_file:
return JsonResponse({'error': '请先选择文件。'}, status=400)
# 获取模型名称
model_config = request.POST.get('model_config', '')
# 动态获取模型
try:
app_label, model_name = model_config.split('.')
model = apps.get_model(app_label, model_name)
except (LookupError, KeyError, ValueError):
return JsonResponse({'error': '模型配置错误。'}, status=400)
# 获取模型中配置的不需要的字段
exclude_fields = getattr(model, 'excluded_fields', [])
# 保存文件到服务器
file_name = default_storage.save(excel_file.name, excel_file)
file_path = os.path.join(settings.MEDIA_ROOT, file_name)
def create_dynamic_serializer(mod, include):
class DynamicSerializer(ModelSerializer):
class Meta:
model = mod
fields = include
def to_representation(self, instance):
representation = super().to_representation(instance)
if 'employee' in representation and instance.employee:
representation['employee'] = instance.employee.name
return representation
return DynamicSerializer
try:
# 打开并解析Excel文件
workbook = load_workbook(file_path, data_only=True)
sheet = workbook.active
data = []
# 读取第一行作为表头
header_row = [cell.value for cell in sheet[1]]
# 获取字段名和 verbose_name排除索引字段
model_fields = [field.name for field in model._meta.fields if
not field.primary_key and field.name not in exclude_fields]
model_verbose_name = [field.verbose_name for field in model._meta.fields if
not field.primary_key and field.name not in exclude_fields]
if not all(item in model_verbose_name for item in header_row):
return JsonResponse({'error': '表头不匹配请使用正确的Excel上传模板。'}, status=400)
# 组成 fields_map
fields_map = dict(zip(model_fields, header_row))
fields_map_nf = dict(zip(header_row, model_fields))
# 创建一个映射将Excel表头映射到模型字段名
header_to_field_map = {header: fields_map_nf[header] for header in header_row}
header_fields = [header_to_field_map[header] for header in header_row]
for row in sheet.iter_rows(min_row=2, values_only=True):
if not all(value is None for value in row):
instance_data = dict(zip(model_fields, row))
# 处理employee字段假设模型中有employee字段并且Excel文件中的表头包含员工姓名
employee_name = instance_data.get('employee')
if employee_name:
try:
employee_instance = EmployeeInformation.objects.get(name=employee_name)
instance_data['employee'] = employee_instance
except EmployeeInformation.DoesNotExist:
return JsonResponse({'error': f'找不到姓名为 {employee_name} 的员工信息。'}, status=400)
instance = model(**instance_data)
try:
instance.full_clean()
data.append(instance)
except ValidationError as e:
return JsonResponse({'error': f'数据校验错误: {e.message_dict}'}, status=400)
# 动态获取序列化器
serializer_class = create_dynamic_serializer(model, include=header_fields)
serializer = serializer_class(data, many=True)
# 清理,删除上传的文件
os.remove(file_path)
return JsonResponse({"table_data": serializer.data, "fields_map": fields_map}, safe=False)
except Exception as e:
# 清理,删除上传的文件
os.remove(file_path)
return JsonResponse({'error': f'解析文件时出错: {str(e)}'}, status=500)
return JsonResponse({'error': '请求错误'}, status=400)
@csrf_protect
@login_required
def save_excel_table_data_pe(request):
if request.method == 'POST':
try:
data = json.loads(request.body)
model_config = data.get('model_config')
table_data = data.get('table_data')
if not model_config or not table_data:
return JsonResponse({'error': '缺少必要的参数'}, status=400)
# 分割 model_config 以获取 app_label 和 model_name
try:
app_label, model_name = model_config.split('.')
Model = apps.get_model(app_label, model_name)
except (ValueError, LookupError):
return JsonResponse({'error': '无效的 model_config'}, status=400)
# 获取模型中配置的不需要的字段
exclude_fields = getattr(Model, 'excluded_fields', [])
# 创建模型实例列表
instances = []
for row_data in table_data:
# 处理employee字段假设模型中有employee字段并且table_data中包含员工姓名
employee_name = row_data.get('employee')
if employee_name:
try:
employee_instance = EmployeeInformation.objects.get(name=employee_name)
row_data['employee'] = employee_instance
except EmployeeInformation.DoesNotExist:
return JsonResponse({'error': f'找不到姓名为 {employee_name} 的员工信息。'}, status=400)
try:
# 排除不需要的字段
instance_data = {key: value for key, value in row_data.items() if key not in exclude_fields}
instance = Model(**instance_data)
instance.full_clean() # 验证数据
instances.append(instance)
except ValidationError as e:
return JsonResponse({'error': f'数据校验错误: {e.message_dict}'}, status=400)
except Exception as e:
return JsonResponse({'error': f'创建实例时出错: {str(e)}'}, status=500)
# 批量创建模型实例
try:
Model.objects.bulk_create(instances)
except Exception as e:
return JsonResponse({'error': f'批量保存数据时出错: {str(e)}'}, status=500)
return JsonResponse({'message': '表格数据保存成功'}, status=200)
except json.JSONDecodeError:
return JsonResponse({'error': '无效的JSON格式'}, status=400)
except Exception as e:
return JsonResponse({'error': f'服务器内部错误: {str(e)}'}, status=500)
return JsonResponse({'error': '无效的请求方法'}, status=400)