import json from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.http import JsonResponse from django.shortcuts import render from django.urls import reverse from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.decorators import api_view, permission_classes from common.utils.page_helper import paginate_query_and_assign_numbers from .models import GroupBusinessTarget, TargetAudit, EmployeeTargetAudit, EmployeePerformanceTarget from .serializers import TargetAuditSerializer, EmployeeTargetAuditSerializer def gbo_list_view(request): # 声明查询集 query_set = GroupBusinessTarget.objects.filter().order_by('-target_id') # 获取查询参数 primary_department = request.GET.get('primary_department', '') year = request.GET.get('year', '') project_nature = request.GET.get('project_nature', '') # 根据提供的参数进行筛选 if primary_department: query_set = query_set.filter(primary_department=primary_department) if year: query_set = query_set.filter(year=year) if project_nature: query_set = query_set.filter(project_nature=project_nature) # 对查询结果进行分页,每页10条记录 items = paginate_query_and_assign_numbers( request=request, queryset=query_set, per_page=10 ) # 构建上下文查询参数字符串 query_params = '&primary_department={}&year={}&project_nature={}'.format(primary_department, year, project_nature) fields = { "primary_department": {"id": "operation_primary_department", "type": "select", 'label': '一级部门', 'options': ['天信', '混改', '艾力芬特', '星河', '星海']}, "year": {"id": "operation_year", "type": "select", 'label': '年份', 'options': ['2024', '2023', '2022', '2021', '2020']}, "project_nature": {"id": "operation_project_nature", "type": "select", 'label': '项目性质', 'options': ['新增', '存续', '新增及存续', '老客户新业务']}, "sales": {"id": "operation_sales", "type": "text", 'label': '销售额(元)'}, "total_revenue_target": {"id": "operation_total_revenue_target", "type": "text", 'label': '收入总目标(元)'}, "new_revenue_target": {"id": "operation_new_revenue_target", "type": "text", 'label': '新增收入目标(元)'}, "existing_revenue_target": {"id": "operation_existing_revenue_target", "type": "text", 'label': '存量收入目标(元)'}, "cost_limit": {"id": "operation_cost_limit", "type": "text", 'label': '成本限额(元)'}, "gross_profit": {"id": "operation_gross_profit", "type": "text", 'label': '毛利润(元)'}, "expense_limit": {"id": "operation_expense_limit", "type": "text", 'label': '费用限额(元)'}, "operating_profit": {"id": "operation_operating_profit", "type": "text", 'label': '营业利润(元)'} } # 构建上下文 context = { "items": items, "list_key": "target_id", "filters": [ { "type": "select", "id": "primary_department", "name": "primary_department", "label": "一级部门", "options": [ {"value": "天信", "display": "天信"}, {"value": "混改", "display": "混改"}, {"value": "艾力芬特", "display": "艾力芬特"}, {"value": "星河", "display": "星河"}, {"value": "星海", "display": "星海"}, ], }, { "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"}, ], }, { "type": "select", "id": "project_nature", "name": "project_nature", "label": "项目性质", "options": [ {"value": "新增", "display": "新增"}, {"value": "存续", "display": "存续"}, {"value": "新增及存续", "display": "新增及存续"}, {"value": "老客户新业务", "display": "老客户新业务"}, ], }, ], # 筛选框配置 "form_action_url": "gbo_list", "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "基础数据", "name": "index"}, {"title": "集团经营目标表", "name": "gbo_list"}, ], # 面包屑 "query_params": query_params, # 查询参数字符串 "table_columns": [ {"header": "一级部门", "field": "primary_department"}, {"header": "年份", "field": "year"}, {"header": "项目性质", "field": "project_nature"}, {"header": "销售额(元)", "field": "sales"}, {"header": "收入总目标(元)", "field": "total_revenue_target"}, {"header": "新增收入目标(元)", "field": "new_revenue_target"}, {"header": "存量收入目标(元)", "field": "existing_revenue_target"}, {"header": "成本限额(元)", "field": "cost_limit"}, {"header": "毛利润(元)", "field": "gross_profit"}, {"header": "费用限额(元)", "field": "expense_limit"}, {"header": "营业利润(元)", "field": "operating_profit"}, {"header": "操作", "field": "actions"}, ], "modify_url": reverse("modify_gbo_data"), "add_url": reverse("add_gbo_data"), "delete_url": reverse("delete_gbo_data"), "modify_records_url": reverse("gbo_audit_record_list"), "form_fields_config": {"fields": fields}, "excel_upload_config": { "template_url": reverse("download_excel_template", kwargs={"template_name": "业绩管理-集团经营目标-Excel上传模板.xlsx", "fields": fields}), "parse_url": reverse("common_excel_parse"), "save_url": reverse("save_excel_table_data"), "model_config": {"app_label": "perf_mgnt", "model_name": "GroupBusinessTarget"}, "fields_map": { "primary_department": "一级部门", "year": "年份", "project_nature": "项目性质", "sales": "销售额(元)", "total_revenue_target": "收入总目标(元)", "new_revenue_target": "新增收入目标(元)", "existing_revenue_target": "存量收入目标(元)", "cost_limit": "成本限额(元)", "gross_profit": "毛利润(元)", "expense_limit": "费用限额(元)", "operating_profit": "营业利润(元)", }, "fields_preview_config": { "primary_department": {"type": "select", "width": "180px", "options": ["天信", "混改", "艾力芬特", "星河", "星海"]}, "year": {"type": "select", "width": "180px", "options": ["2024", "2023", "2022", "2021", "2020"]}, "project_nature": {"type": "select", "width": "180px", "options": ["新增", "存续", "新增及存续", "老客户新业务"]}, "sales": {"type": "text", "width": "180px"}, "total_revenue_target": {"type": "text", "width": "180px"}, "new_revenue_target": {"type": "text", "width": "180px"}, "existing_revenue_target": {"type": "text", "width": "180px"}, "cost_limit": {"type": "text", "width": "180px"}, "gross_profit": {"type": "text", "width": "180px"}, "expense_limit": {"type": "text", "width": "180px"}, "operating_profit": {"type": "text", "width": "180px"}, }, } } return render(request, 'perf_mgnt/gbo_list.html', context) def add_gbo_data(request): """ 添加集团经营目标数据 """ # 获取表单数据 primary_department = request.POST.get('primary_department') year = request.POST.get('year') project_nature = request.POST.get('project_nature') sales = request.POST.get('sales') total_revenue_target = request.POST.get('total_revenue_target') new_revenue_target = request.POST.get('new_revenue_target') existing_revenue_target = request.POST.get('existing_revenue_target') cost_limit = request.POST.get('cost_limit') gross_profit = request.POST.get('gross_profit') expense_limit = request.POST.get('expense_limit') operating_profit = request.POST.get('operating_profit') # 创建新的集团经营目标数据 new_gbo_data = GroupBusinessTarget( primary_department=primary_department, year=year, project_nature=project_nature, sales=sales, total_revenue_target=total_revenue_target, new_revenue_target=new_revenue_target, existing_revenue_target=existing_revenue_target, cost_limit=cost_limit, gross_profit=gross_profit, expense_limit=expense_limit, operating_profit=operating_profit ) new_gbo_data.save() # 返回添加成功的消息 return JsonResponse({'message': '添加成功'}) def delete_gbo_data(request): if request.method == 'GET': target_id = request.GET.get('target_id') try: target = GroupBusinessTarget.objects.get(target_id=target_id) target.delete() return JsonResponse({'message': '删除成功'}, status=200) except GroupBusinessTarget.DoesNotExist: return JsonResponse({'message': '记录不存在'}, status=404) except Exception as e: return JsonResponse({'message': '删除失败', 'error': str(e)}, status=400) return JsonResponse({'message': '无效的请求方法'}, status=405) def modify_gbo_data(request): """ 修改集团经营目标数据 """ try: # 获取表单数据 target_id = request.POST.get('target_id') primary_department = request.POST.get('primary_department') year = request.POST.get('year') project_nature = request.POST.get('project_nature') sales = request.POST.get('sales') total_revenue_target = request.POST.get('total_revenue_target') new_revenue_target = request.POST.get('new_revenue_target') existing_revenue_target = request.POST.get('existing_revenue_target') cost_limit = request.POST.get('cost_limit') gross_profit = request.POST.get('gross_profit') expense_limit = request.POST.get('expense_limit') operating_profit = request.POST.get('operating_profit') # 获取需要修改的对象 target = GroupBusinessTarget.objects.get(target_id=target_id) # 获取当前用户 modified_by = request.user.username # 比较新旧数据,找出修改的字段 changes = [] if target.primary_department != primary_department: changes.append(('primary_department', target.primary_department, primary_department)) if target.year != int(year): changes.append(('year', target.year, year)) if target.project_nature != project_nature: changes.append(('project_nature', target.project_nature, project_nature)) if target.sales != float(sales): changes.append(('sales', target.sales, sales)) if target.total_revenue_target != float(total_revenue_target): changes.append(('total_revenue_target', target.total_revenue_target, total_revenue_target)) if target.new_revenue_target != float(new_revenue_target): changes.append(('new_revenue_target', target.new_revenue_target, new_revenue_target)) if target.existing_revenue_target != float(existing_revenue_target): changes.append(('existing_revenue_target', target.existing_revenue_target, existing_revenue_target)) if target.cost_limit != float(cost_limit): changes.append(('cost_limit', target.cost_limit, cost_limit)) if target.gross_profit != float(gross_profit): changes.append(('gross_profit', target.gross_profit, gross_profit)) if target.expense_limit != float(expense_limit): changes.append(('expense_limit', target.expense_limit, expense_limit)) if target.operating_profit != float(operating_profit): changes.append(('operating_profit', target.operating_profit, operating_profit)) FIELD_NAME_MAP = { 'primary_department': '一级部门', 'year': '年份', 'project_nature': '项目性质', 'sales': '销售额', 'total_revenue_target': '收入总目标', 'new_revenue_target': '新增收入目标', 'existing_revenue_target': '存量收入目标', 'cost_limit': '成本限额', 'gross_profit': '毛利润', 'expense_limit': '费用限额', 'operating_profit': '营业利润' } # 生成修改记录 for field, old_value, new_value in changes: TargetAudit.objects.create( target_id=target, modified_field=FIELD_NAME_MAP.get(field, field), old_value=old_value, new_value=new_value, modified_by=modified_by ) # 修改数据 target.primary_department = primary_department target.year = year target.project_nature = project_nature target.sales = sales target.total_revenue_target = total_revenue_target target.new_revenue_target = new_revenue_target target.existing_revenue_target = existing_revenue_target target.cost_limit = cost_limit target.gross_profit = gross_profit target.expense_limit = expense_limit target.operating_profit = operating_profit # 保存修改 target.save() return JsonResponse({'message': '修改成功'}, status=200) except GroupBusinessTarget.DoesNotExist: return JsonResponse({'message': '记录不存在'}, status=404) except Exception as e: return JsonResponse({'message': '修改失败', 'error': str(e)}, status=400) @api_view(['GET']) @permission_classes([IsAuthenticated]) def gbo_audit_record_list_view(request): """ 获取集团目标修改记录,支持分页。 """ # 设置每页显示的记录数,默认为10 per_page = request.GET.get('per_page', 5) page_number = request.GET.get('page', 1) # 获取所有修改记录的查询集 queryset = TargetAudit.objects.all().order_by('-modification_date') # 使用Django的Paginator进行分页处理 paginator = Paginator(queryset, per_page) try: page_obj = paginator.page(page_number) except EmptyPage: page_obj = paginator.page(paginator.num_pages) # 如果页码太大,显示最后一页 except PageNotAnInteger: page_obj = paginator.page(1) # 如果页码不是整数,显示第一页 # 序列化分页后的数据 serializer = TargetAuditSerializer(page_obj, many=True) # 构造响应数据,包含分页信息 response_data = { 'modal_title': '集团经营目标修改记录', 'columns': ['修改对象', '修改字段', '旧值', '新值', '修改时间', '修改人'], 'records': serializer.data, 'page': page_obj.number, 'num_pages': paginator.num_pages, 'has_previous': page_obj.has_previous(), 'has_next': page_obj.has_next(), 'start_index': page_obj.start_index(), 'end_index': page_obj.end_index(), 'total_items': paginator.count } return Response(response_data) def emt_list_view(request): # 声明查询集 query_set = EmployeePerformanceTarget.objects.filter().order_by('-target_id') # 获取查询参数 name = request.GET.get('name', '') department = request.GET.get('department', '') year = request.GET.get('year', '') project_nature = request.GET.get('project_nature', '') # 根据提供的参数进行筛选 if request.GET.get('name', ''): query_set = query_set.filter(name=request.GET.get('name', '')) if request.GET.get('department', ''): query_set = query_set.filter(department=request.GET.get('department', '')) if request.GET.get('year', ''): query_set = query_set.filter(year=request.GET.get('year', '')) if request.GET.get('project_nature', ''): query_set = query_set.filter(project_nature=request.GET.get('project_nature', '')) # 对查询结果进行分页,每页10条记录 items = paginate_query_and_assign_numbers( request=request, queryset=query_set, per_page=10 ) # 构建上下文查询参数字符串 query_params = '&name={}' + format(name) + '&department={}' + format(department) + '&year={}' + format( year) + '&project_nature={}' + format(project_nature) fields = {"name": {"id": "operation_name", "type": "text", "label": "姓名"}, "department": {"id": "operation_department", "type": "select", "label": "一级部门", "options": ["天信", "混改", "艾力芬特", "星河", "星海"]}, "year": {"id": "operation_year", "type": "select", "label": "年份", "options": ["2024", "2023", "2022", "2021", "2020"]}, "project_nature": {"id": "operation_project_nature", "type": "select", "label": "项目性质", "options": ["新增", "存续", "新增及存续", "老客户新业务"]}, "sales_target": {"id": "operation_sales_target", "type": "text", "label": "销售额目标(元)"}, "total_revenue_target": {"id": "operation_total_revenue_target", "type": "text", "label": "收入总目标(元)"}, "new_revenue_target": {"id": "operation_new_revenue_target", "type": "text", "label": "新增收入目标(元)"}, "existing_revenue_target": {"id": "operation_existing_revenue_target", "type": "text", "label": "存量收入目标(元)"}} # 构建上下文 context = { "items": items, "list_key": "target_id", "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": "星海"}]}, {"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"}]}, {"type": "select", "id": "project_nature", "name": "project_nature", "label": "项目性质", "options": [{"value": "新增", "display": "新增"}, {"value": "存续", "display": "存续"}, {"value": "新增及存续", "display": "新增及存续"}, {"value": "老客户新业务", "display": "老客户新业务"}]}], "form_action_url": "emt_list", "breadcrumb_list": [{"title": "首页", "name": "index"}, {"title": "业绩管理", "name": "index"}, {"title": "员工业绩目标表", "name": "emt_list"}], "query_params": query_params, "table_columns": [{"header": "姓名", "field": "name"}, {"header": "一级部门", "field": "department"}, {"header": "年份", "field": "year"}, {"header": "项目性质", "field": "project_nature"}, {"header": "销售额目标(元)", "field": "sales_target"}, {"header": "收入总目标(元)", "field": "total_revenue_target"}, {"header": "新增收入目标(元)", "field": "new_revenue_target"}, {"header": "存量收入目标(元)", "field": "existing_revenue_target"}, {"header": "操作", "field": "actions"}], "show_modify_button": True, "show_add_button": True, "show_download_button": True, "show_upload_button": True, "modify_url": reverse("emt_list_modify"), "add_url": reverse("emt_list_add"), "delete_url": reverse("emt_list_delete"), "modify_records_url": reverse("emt_audit_record_list") if 1 else None, "form_fields_config": {"fields": fields}, "excel_upload_config": { "template_url": reverse("download_excel_template", kwargs={"template_name": "业绩管理-员工业绩目标-Excel上传模板.xlsx", "fields": fields}), "parse_url": reverse("common_excel_parse"), "save_url": reverse("save_excel_table_data"), "model_config": {"app_label": "perf_mgnt", "model_name": "EmployeePerformanceTarget"}, "fields_map": {"name": "姓名", "department": "一级部门", "year": "年份", "project_nature": "项目性质", "sales_target": "销售额目标(元)", "total_revenue_target": "收入总目标(元)", "new_revenue_target": "新增收入目标(元)", "existing_revenue_target": "存量收入目标(元)"}, "fields_preview_config": {"name": {"type": "text", "width": "180px"}, "department": {"type": "select", "width": "180px", "options": ["天信", "混改", "艾力芬特", "星河", "星海"]}, "year": {"type": "select", "width": "180px", "options": ["2024", "2023", "2022", "2021", "2020"]}, "project_nature": {"type": "select", "width": "180px", "options": ["新增", "存续", "新增及存续", "老客户新业务"]}, "sales_target": {"type": "text", "width": "180px"}, "total_revenue_target": {"type": "text", "width": "180px"}, "new_revenue_target": {"type": "text", "width": "180px"}, "existing_revenue_target": {"type": "text", "width": "180px"}}}, } return render(request, 'perf_mgnt/emt_list.html', context) def emt_list_add(request): if request.method == 'POST': data = { 'name': request.POST.get('name'), 'department': request.POST.get('department'), 'year': request.POST.get('year'), 'project_nature': request.POST.get('project_nature'), 'sales_target': request.POST.get('sales_target'), 'total_revenue_target': request.POST.get('total_revenue_target'), 'new_revenue_target': request.POST.get('new_revenue_target'), 'existing_revenue_target': request.POST.get('existing_revenue_target') } EmployeePerformanceTarget.objects.create(**data) return JsonResponse({"message": "添加成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) def emt_list_modify(request): if request.method == 'POST': target_id = request.POST.get('target_id') data = { 'name': request.POST.get('name'), 'department': request.POST.get('department'), 'year': int(request.POST.get('year')), 'project_nature': request.POST.get('project_nature'), 'sales_target': float(request.POST.get('sales_target')), 'total_revenue_target': float(request.POST.get('total_revenue_target')), 'new_revenue_target': float(request.POST.get('new_revenue_target')), 'existing_revenue_target': float(request.POST.get('existing_revenue_target')) } target = EmployeePerformanceTarget.objects.get(target_id=target_id) changes = [] if 1: for key, value in data.items(): if getattr(target, key) != value: changes.append((key, getattr(target, key), value)) FIELD_NAME_MAP = { 'name': '姓名', 'department': '一级部门', 'year': '年份', 'project_nature': '项目性质', 'sales_target': '销售额目标(元)', 'total_revenue_target': '收入总目标(元)', 'new_revenue_target': '新增收入目标(元)', 'existing_revenue_target': '存量收入目标(元)' } for field, old_value, new_value in changes: EmployeeTargetAudit.objects.create( target_id=target, modified_field=FIELD_NAME_MAP.get(field, field), old_value=old_value, new_value=new_value, modified_by=request.user.username ) EmployeePerformanceTarget.objects.filter(target_id=target_id).update(**data) return JsonResponse({"message": "修改成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) def emt_list_delete(request): if request.method == 'GET': target_id = request.GET.get('target_id') EmployeePerformanceTarget.objects.filter(target_id=target_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @api_view(['GET']) @permission_classes([IsAuthenticated]) def emt_audit_record_list(request): per_page = request.GET.get('per_page', 10) page_number = request.GET.get('page', 1) queryset = EmployeeTargetAudit.objects.all().order_by('-modification_date') paginator = Paginator(queryset, per_page) try: page_obj = paginator.page(page_number) except EmptyPage: page_obj = paginator.page(paginator.num_pages) except PageNotAnInteger: page_obj = paginator.page(1) serializer = EmployeeTargetAuditSerializer(page_obj, many=True) response_data = { 'modal_title': '修改记录', 'columns': ['修改对象', '修改字段', '旧值', '新值', '修改时间', '修改人'], 'records': serializer.data, 'page': page_obj.number, 'num_pages': paginator.num_pages, 'has_previous': page_obj.has_previous(), 'has_next': page_obj.has_next(), 'start_index': page_obj.start_index(), 'end_index': page_obj.end_index(), 'total_items': paginator.count } return Response(response_data)