import json from decimal import Decimal from django.contrib.auth.decorators import login_required from django.http import JsonResponse, Http404 from django.shortcuts import render, get_object_or_404 from django.template.loader import render_to_string from django.urls import reverse from django.views.decorators.csrf import csrf_protect from django.views.decorators.http import require_POST, require_http_methods from application.fac_mgnt.forms import * from application.fac_mgnt.models import * from application.hrm_mgnt.models import PerformanceEvaluation 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('fac_mgnt.view_expensetype') def exp_type_list_view(request): query_set = ExpenseType.objects.filter().order_by('-type_id') expense_type = request.GET.get('expense_type', '') if expense_type: query_set = query_set.filter(expense_type__icontains=expense_type) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&expense_type={}'.format(expense_type) template_name = "财会管理-费用类型-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.ExpenseType', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "费用类型", "name": "exp_type_list"} ], "filters": [ {"type": "select", "id": "expense_type", "name": "expense_type", "label": "费用类型", "options": [{"value": "差旅费", "display": "差旅费"}, {"value": "办公费", "display": "办公费"}]} ], "table_exclude_field_name": ['type_id'], "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": { "type_id": {"type": "text", "width": "180px"}, "expense_type": {"type": "text", "width": "180px"}, "actions": {"type": "actions", "width": "100px"} } }, "query_params": query_params, "form_action_url": 'exp_type_list', "modify_url": reverse("exp_type_list_modify"), "add_url": reverse("exp_type_list_add"), "delete_url": reverse("exp_type_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_expensetype') def exp_type_list_add(request): if request.method == 'POST': form = ExpenseTypeForm(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 = ExpenseTypeForm() 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('fac_mgnt.change_expensetype') def exp_type_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = ExpenseType.objects.get(type_id=request.POST['id']) form = ExpenseTypeForm(request.POST, instance=instance) else: form = ExpenseTypeForm(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 = ExpenseType.objects.get(type_id=request.GET['id']) form = ExpenseTypeForm(instance=instance) except ExpenseType.DoesNotExist: raise Http404("对象不存在") else: form = ExpenseTypeForm() 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('fac_mgnt.delete_expensetype') def exp_type_list_delete(request): if request.method == 'GET': type_id = request.GET.get('type_id') ExpenseType.objects.filter(type_id=type_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_expensedetail') def exp_detail_list_view(request): query_set = ExpenseDetail.objects.filter().order_by('-detail_id') expense_detail = request.GET.get('expense_detail', '') if expense_detail: query_set = query_set.filter(expense_detail__icontains=expense_detail) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&expense_detail={}'.format(expense_detail) template_name = "财会管理-费用明细-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.ExpenseDetail', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "费用明细", "name": "exp_detail_list"} ], "filters": [ {"type": "select", "id": "expense_detail", "name": "expense_detail", "label": "费用明细", "options": [{"value": "工资", "display": "工资"}, {"value": "社保", "display": "社保"}, {"value": "公积金", "display": "公积金"}]} ], "table_exclude_field_name": ['detail_id'], "excel_upload_config": { "template_url": reverse("download_template", kwargs={'template_name': template_name}), "parse_url": reverse("common_excel_parse_exp"), "save_url": reverse("save_excel_table_data_exp"), "fields_preview_config": { "type_id": {"type": "text", "width": "180px"}, "expense_detail": {"type": "text", "width": "180px"}, } }, "query_params": query_params, "form_action_url": 'exp_detail_list', "modify_url": reverse("exp_detail_list_modify"), "add_url": reverse("exp_detail_list_add"), "delete_url": reverse("exp_detail_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_expensedetail') def exp_detail_list_add(request): if request.method == 'POST': form = ExpenseDetailForm(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 = ExpenseDetailForm() 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('fac_mgnt.change_expensedetail') def exp_detail_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = ExpenseDetail.objects.get(detail_id=request.POST['id']) form = ExpenseDetailForm(request.POST, instance=instance) else: form = ExpenseDetailForm(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 = ExpenseDetail.objects.get(detail_id=request.GET['id']) form = ExpenseDetailForm(instance=instance) except ExpenseDetail.DoesNotExist: raise Http404("对象不存在") else: form = ExpenseDetailForm() 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('fac_mgnt.delete_expensedetail') def exp_detail_list_delete(request): if request.method == 'GET': detail_id = request.GET.get('detail_id') ExpenseDetail.objects.filter(detail_id=detail_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_groupannualbudget') def gpb_list_view(request): query_set = GroupAnnualBudget.objects.filter().order_by('-budget_id') primary_department = request.GET.get('primary_department', '') expense_detail = request.GET.get('expense_detail', '') expense_type = request.GET.get('expense_type', '') year = request.GET.get('year', '') if primary_department: query_set = query_set.filter(primary_department__icontains=primary_department) if expense_detail: query_set = query_set.filter(expense_detail__expense_detail__icontains=expense_detail) if expense_type: query_set = query_set.filter(expense_type__expense_type__icontains=expense_type) if year: query_set = query_set.filter(year__icontains=year) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&primary_department={}&expense_detail={}&expense_type={}&year={}'.format( primary_department, expense_detail, expense_type, year) template_name = "财会管理-集团年度预算-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.GroupAnnualBudget', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "集团年度预算", "name": "gpb_list"} ], "filters": [ {"type": "select", "id": "primary_department", "name": "primary_department", "label": "一级部门", "options": [{"value": "天信", "display": "天信"}, {"value": "混改", "display": "混改"}, {"value": "艾力芬特", "display": "艾力芬特"}, {"value": "星河", "display": "星河"}, {"value": "星海", "display": "星海"}]}, {"type": "select", "id": "expense_detail", "name": "expense_detail", "label": "费用明细", "options": [{"value": "办公用品购置", "display": "办公用品购置"}, {"value": "员工出差住宿费", "display": "员工出差住宿费"}, {"value": "员工技能培训", "display": "员工技能培训"}, {"value": "软件订阅服务费", "display": "软件订阅服务费"}, {"value": "市场推广活动费", "display": "市场推广活动费"}]}, {"type": "select", "id": "expense_type", "name": "expense_type", "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"}]} ], "table_exclude_field_name": ['budget_id'], "excel_upload_config": { "template_url": reverse("download_template", kwargs={'template_name': template_name}), "parse_url": reverse("common_excel_parse_gab"), "save_url": reverse("save_excel_table_data_gab"), "fields_preview_config": { "primary_department": {"type": "text", "width": "180px"}, "year": {"type": "number", "width": "100px"}, "expense_type": {"type": "text", "width": "180px"}, "expense_detail": {"type": "text", "width": "180px"}, "amount": {"type": "number", "width": "100px"}, } }, "query_params": query_params, "form_action_url": 'gpb_list', "modify_url": reverse("gpb_list_modify"), "add_url": reverse("gpb_list_add"), "delete_url": reverse("gpb_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_groupannualbudget') def gpb_list_add(request): if request.method == 'POST': form = GroupAnnualBudgetForm(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 = GroupAnnualBudgetForm() 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('fac_mgnt.change_groupannualbudget') def gpb_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = GroupAnnualBudget.objects.get(budget_id=request.POST['id']) form = GroupAnnualBudgetForm(request.POST, instance=instance) else: form = GroupAnnualBudgetForm(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 = GroupAnnualBudget.objects.get(budget_id=request.GET['id']) form = GroupAnnualBudgetForm(instance=instance) except GroupAnnualBudget.DoesNotExist: raise Http404("对象不存在") else: form = GroupAnnualBudgetForm() 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('fac_mgnt.delete_groupannualbudget') def gpb_list_delete(request): if request.method == 'GET': budget_id = request.GET.get('budget_id') GroupAnnualBudget.objects.filter(budget_id=budget_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_laborcostdetail') def lcb_list_view(request): query_set = LaborCostDetail.objects.filter().order_by('-record_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__icontains=department) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&name={}&department={}'.format(name, department) template_name = "财会管理-人工费用明细-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.LaborCostDetail', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "人工费明细", "name": "lcb_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_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_month": {"type": "text", "width": "180px"}, "name": {"type": "text", "width": "180px"}, "primary_department": {"type": "text", "width": "180px"}, "secondary_department": {"type": "text", "width": "180px"}, "attendance_days": {"type": "number", "width": "100px"}, "gross_salary": {"type": "number", "width": "100px"}, "attendance_reward": {"type": "number", "width": "100px"}, "lunch_allowance": {"type": "number", "width": "100px"}, "other_monetary_benefits": {"type": "number", "width": "100px"}, "social_security_deduction": {"type": "number", "width": "100px"}, "housing_fund_deduction": {"type": "number", "width": "100px"}, "net_salary": {"type": "number", "width": "100px"}, "employer_social_security": {"type": "number", "width": "100px"}, "employer_housing_fund": {"type": "number", "width": "100px"}, } }, "table_exclude_field_name": ['record_id'], "query_params": query_params, "form_action_url": 'lcb_list', "modify_url": reverse("lcb_list_modify"), "add_url": reverse("lcb_list_add"), "delete_url": reverse("lcb_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_laborcostdetail') def lcb_list_add(request): if request.method == 'POST': form = LaborCostDetailForm(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 = LaborCostDetailForm() 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('fac_mgnt.change_laborcostdetail') def lcb_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = LaborCostDetail.objects.get(record_id=request.POST['id']) form = LaborCostDetailForm(request.POST, instance=instance) else: form = LaborCostDetailForm(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 = LaborCostDetail.objects.get(record_id=request.GET['id']) form = LaborCostDetailForm(instance=instance) except LaborCostDetail.DoesNotExist: raise Http404("对象不存在") else: form = LaborCostDetailForm() 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('fac_mgnt.delete_laborcostdetail') def lcb_list_delete(request): if request.method == 'GET': record_id = request.GET.get('record_id') LaborCostDetail.objects.filter(record_id=record_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_reimbursementdetail') def rbm_detail_list_view(request): query_set = ReimbursementDetail.objects.filter().order_by('-record_id') name = request.GET.get('name', '') year_month = request.GET.get('year_month', '') primary_department = request.GET.get('primary_department', '') project_name = request.GET.get('project_name', '') if name: query_set = query_set.filter(name__icontains=name) if year_month: query_set = query_set.filter(year_month__icontains=year_month) if primary_department: query_set = query_set.filter(primary_department__icontains=primary_department) if project_name: query_set = query_set.filter(project_name__icontains=project_name) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&name={}&year_month={}&primary_department={}&project_name={}'.format( name, year_month, primary_department, project_name ) template_name = "财会管理-报销明细-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.ReimbursementDetail', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "报销明细", "name": "rbm_detail_list"} ], "filters": [ {"type": "text", "id": "name", "name": "name", "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": "星海"}]}, {"type": "text", "id": "project_name", "name": "project_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": { "record_id": {"type": "number", "width": "180px"}, "year_month": {"type": "date", "width": "180px"}, "primary_department": {"type": "text", "width": "180px"}, "name": {"type": "text", "width": "180px"}, "is_project_based": {"type": "select", "width": "100px", "options": ["是", "否"]}, "project_id": {"type": "number", "width": "180px"}, "project_name": {"type": "text", "width": "180px"}, "expense_type": {"type": "text", "width": "180px"}, "expense_details": {"type": "text", "width": "180px"}, "expense_description": {"type": "textarea", "width": "300px"}, "expense_date": {"type": "date", "width": "180px"}, "amount": {"type": "number", "width": "100px"}, "actions": {"type": "actions", "width": "100px"} } }, "table_exclude_field_name": ['record_id'], "query_params": query_params, "form_action_url": 'rbm_detail_list', "modify_url": reverse("rbm_detail_list_modify"), "add_url": reverse("rbm_detail_list_add"), "delete_url": reverse("rbm_detail_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_reimbursementdetail') def rbm_detail_list_add(request): if request.method == 'POST': form = ReimbursementDetailForm(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 = ReimbursementDetailForm() 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('fac_mgnt.change_reimbursementdetail') def rbm_detail_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = ReimbursementDetail.objects.get(record_id=request.POST['id']) form = ReimbursementDetailForm(request.POST, instance=instance) else: form = ReimbursementDetailForm(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 = ReimbursementDetail.objects.get(record_id=request.GET['id']) form = ReimbursementDetailForm(instance=instance) except ReimbursementDetail.DoesNotExist: raise Http404("对象不存在") else: form = ReimbursementDetailForm() 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('fac_mgnt.delete_reimbursementdetail') def rbm_detail_list_delete(request): if request.method == 'GET': record_id = request.GET.get('record_id') ReimbursementDetail.objects.filter(record_id=record_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_bonuscategoty') def bns_cat_list_view(request): query_set = BonusCategory.objects.filter().order_by('-category_id') category_name = request.GET.get('category_name', '') if category_name: query_set = query_set.filter(category_name__icontains=category_name) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&category_name={}'.format(category_name) template_name = "财会管理-奖金类别-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.BonusCategory', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "奖金类别表", "name": "bns_cat_list"} ], "filters": [ {"type": "text", "id": "category_name", "name": "category_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": { "category_name": {"type": "text", "width": "180px"}, "description": {"type": "text", "width": "300px"}, } }, "table_exclude_field_name": ['category_id'], "query_params": query_params, "form_action_url": 'bns_cat_list', "modify_url": reverse("bns_cat_list_modify"), "add_url": reverse("bns_cat_list_add"), "delete_url": reverse("bns_cat_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_bonuscategoty') def bns_cat_list_add(request): if request.method == 'POST': form = BonusCategoryForm(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 = BonusCategoryForm() 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('fac_mgnt.change_bonuscategoty') def bns_cat_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = BonusCategory.objects.get(category_id=request.POST['id']) form = BonusCategoryForm(request.POST, instance=instance) else: form = BonusCategoryForm(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 = BonusCategory.objects.get(category_id=request.GET['id']) form = BonusCategoryForm(instance=instance) except BonusCategory.DoesNotExist: raise Http404("对象不存在") else: form = BonusCategoryForm() 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('fac_mgnt.delete_bonuscategoty') def bns_cat_list_delete(request): if request.method == 'GET': category_id = request.GET.get('category_id') BonusCategory.objects.filter(category_id=category_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_bonuscategoty') def bns_alloc_list_view(request): query_set = BonusAllocation.objects.filter().order_by('-record_id') name = request.GET.get('name', '') year_month = request.GET.get('year_month', '') department = request.GET.get('department', '') if name: query_set = query_set.filter(name__icontains=name) if year_month: query_set = query_set.filter(year_month__icontains=year_month) if department: query_set = query_set.filter(primary_department__icontains=department) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&name={}&year_month={}&department={}'.format(name, year_month, department) template_name = "财会管理-奖金分配-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.BonusAllocation', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "奖金分配表", "name": "bns_alloc_list"} ], "filters": [ {"type": "text", "id": "name", "name": "name", "label": "姓名", "placeholder": "请输入姓名"}, {"type": "month", "id": "year_month", "name": "year_month", "label": "年月"}, {"type": "select", "id": "department", "name": "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"), "save_url": reverse("save_excel_table_data"), "fields_preview_config": { "year_month": {"type": "text", "width": "180px"}, "primary_department": {"type": "text", "width": "180px"}, "secondary_department": {"type": "text", "width": "180px"}, "name": {"type": "text", "width": "180px"}, "bonus_category": {"type": "text", "width": "180px"}, "award_amount": {"type": "number", "width": "100px"}, } }, "table_exclude_field_name": ['record_id'], "query_params": query_params, "form_action_url": 'bns_alloc_list', "modify_url": reverse("bns_alloc_list_modify"), "add_url": reverse("bns_alloc_list_add"), "delete_url": reverse("bns_alloc_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_bonuscategoty') def bns_alloc_list_add(request): if request.method == 'POST': form = BonusAllocationForm(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 = BonusAllocationForm() 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('fac_mgnt.change_bonuscategoty') def bns_alloc_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = BonusAllocation.objects.get(record_id=request.POST['id']) form = BonusAllocationForm(request.POST, instance=instance) else: form = BonusAllocationForm(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 = BonusAllocation.objects.get(record_id=request.GET['id']) form = BonusAllocationForm(instance=instance) except BonusAllocation.DoesNotExist: raise Http404("对象不存在") else: form = BonusAllocationForm() 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('fac_mgnt.delete_bonuscategoty') def bns_alloc_list_delete(request): if request.method == 'GET': record_id = request.GET.get('record_id') BonusAllocation.objects.filter(record_id=record_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_taxrecord') def tax_rec_list_view(request): query_set = TaxRecord.objects.filter().order_by('-id') tax_entity = request.GET.get('tax_entity', '') year = request.GET.get('year', '') if tax_entity: query_set = query_set.filter(tax_entity__icontains=tax_entity) if year: query_set = query_set.filter(year__icontains=year) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&tax_entity={}&year={}'.format(tax_entity, year) template_name = "财会管理-纳税记录-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.TaxRecord', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "纳税记录表", "name": "tax_rec_list"} ], "filters": [ {"type": "text", "id": "tax_entity", "name": "tax_entity", "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": { "tax_entity": {"type": "text", "width": "180px"}, "year": {"type": "number", "width": "100px"}, "tax_type": {"type": "select", "width": "180px", "options": ["增值税", "消费税"]}, "tax_period": {"type": "select", "width": "180px", "options": ["月度", "季度", "年度"]}, "tax_date": {"type": "date", "width": "180px"}, "tax_amount": {"type": "number", "width": "100px"}, "annual_cumulative": {"type": "number", "width": "100px"}, "note": {"type": "text", "width": "300px"}, } }, "table_exclude_field_name": ['id'], "query_params": query_params, "form_action_url": 'tax_rec_list', "modify_url": reverse("tax_rec_list_modify"), "add_url": reverse("tax_rec_list_add"), "delete_url": reverse("tax_rec_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_taxrecord') def tax_rec_list_add(request): if request.method == 'POST': form = TaxRecordForm(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 = TaxRecordForm() 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('fac_mgnt.change_taxrecord') def tax_rec_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = TaxRecord.objects.get(id=request.POST['id']) form = TaxRecordForm(request.POST, instance=instance) else: form = TaxRecordForm(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 = TaxRecord.objects.get(id=request.GET['id']) form = TaxRecordForm(instance=instance) except TaxRecord.DoesNotExist: raise Http404("对象不存在") else: form = TaxRecordForm() 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('fac_mgnt.delete_taxrecord') def tax_rec_list_delete(request): if request.method == 'GET': target_id = request.GET.get('target_id') TaxRecord.objects.filter(id=target_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_electronicinvoiceledger') def inv_ledger_list_view(request): query_set = ElectronicInvoiceLedger.objects.filter().order_by('-invoice_number') expense_party = request.GET.get('expense_party', '') primary_department = request.GET.get('primary_department', '') invoice_code = request.GET.get('invoice_code', '') invoice_number = request.GET.get('invoice_number', '') invoice_date = request.GET.get('invoice_date', '') if expense_party: query_set = query_set.filter(expense_party__icontains=expense_party) if primary_department: query_set = query_set.filter(primary_department__icontains=primary_department) if invoice_code: query_set = query_set.filter(invoice_code__icontains=invoice_code) if invoice_number: query_set = query_set.filter(invoice_number__icontains=invoice_number) if invoice_date: query_set = query_set.filter(invoice_date__icontains=invoice_date) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&expense_party={}&primary_department={}&invoice_code={}&invoice_number={}&invoice_date={}'.format( expense_party, primary_department, invoice_code, invoice_number, invoice_date) template_name = "财会管理-电子发票台账-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.ElectronicInvoiceLedger', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "电子发票台账", "name": "inv_ledger_list"} ], "filters": [ {"type": "text", "id": "expense_party", "name": "expense_party", "label": "费用当事人", "placeholder": "请输入费用当事人"}, {"type": "select", "id": "primary_department", "name": "primary_department", "label": "一级部门", "options": [{"value": "天信", "display": "天信"}, {"value": "混改", "display": "混改"}, {"value": "艾力芬特", "display": "艾力芬特"}, {"value": "星河", "display": "星河"}, {"value": "星海", "display": "星海"}]}, {"type": "text", "id": "invoice_code", "name": "invoice_code", "label": "发票代码", "placeholder": "请输入发票代码"}, {"type": "text", "id": "invoice_number", "name": "invoice_number", "label": "发票号码", "placeholder": "请输入发票号码"}, {"type": "date", "id": "invoice_date", "name": "invoice_date", "label": "开票日期"} ], "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": { "expense_party": {"type": "text", "width": "180px"}, "primary_department": {"type": "text", "width": "180px"}, "submission_date": {"type": "date", "width": "180px"}, "invoice_code": {"type": "text", "width": "180px"}, "invoice_number": {"type": "text", "width": "180px"}, "invoice_date": {"type": "date", "width": "180px"}, "buyer_name": {"type": "text", "width": "180px"}, "buyer_tax_number": {"type": "text", "width": "180px"}, "seller_name": {"type": "text", "width": "180px"}, "seller_tax_number": {"type": "text", "width": "180px"}, "goods_or_services_name": {"type": "text", "width": "180px"}, "tax_rate": {"type": "number", "width": "100px"}, "total_amount_including_tax": {"type": "number", "width": "100px"}, } }, "table_exclude_field_name": ['id'], "query_params": query_params, "form_action_url": 'inv_ledger_list', "modify_url": reverse("inv_ledger_list_modify"), "add_url": reverse("inv_ledger_list_add"), "delete_url": reverse("inv_ledger_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_electronicinvoiceledger') def inv_ledger_list_add(request): if request.method == 'POST': form = ElectronicInvoiceLedgerForm(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 = ElectronicInvoiceLedgerForm() 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('fac_mgnt.change_electronicinvoiceledger') def inv_ledger_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = ElectronicInvoiceLedger.objects.get(invoice_number=request.POST['id']) form = ElectronicInvoiceLedgerForm(request.POST, instance=instance) else: form = ElectronicInvoiceLedgerForm(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 = ElectronicInvoiceLedger.objects.get(invoice_number=request.GET['id']) form = ElectronicInvoiceLedgerForm(instance=instance) except ElectronicInvoiceLedger.DoesNotExist: raise Http404("对象不存在") else: form = ElectronicInvoiceLedgerForm() 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('fac_mgnt.delete_electronicinvoiceledger') def inv_ledger_list_delete(request): if request.method == 'GET': target_id = request.GET.get('target_id') ElectronicInvoiceLedger.objects.filter(invoice_number=target_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_invoicerecord') def inv_rec_list_view(request): query_set = InvoiceRecord.objects.filter().order_by('-record_id') project_name = request.GET.get('project_name', '') project_nature = request.GET.get('project_nature', '') department = request.GET.get('department', '') invoice_date = request.GET.get('invoice_date', '') project_manager = request.GET.get('project_manager', '') if project_name: query_set = query_set.filter(project_name__icontains=project_name) if project_nature: query_set = query_set.filter(project_nature__icontains=project_nature) if department: query_set = query_set.filter(primary_department__icontains=department) if invoice_date: query_set = query_set.filter(invoice_date__icontains=invoice_date) if project_manager: query_set = query_set.filter(project_manager__icontains=project_manager) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&project_name={}&project_nature={}&department={}&invoice_date={}&project_manager={}'.format( project_name, project_nature, department, invoice_date, project_manager) template_name = "财会管理-开票记录-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.InvoiceRecord', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "开票记录", "name": "inv_rec_list"} ], "filters": [ {"type": "text", "id": "project_name", "name": "project_name", "label": "项目名称", "placeholder": "请输入项目名称"}, {"type": "select", "id": "project_nature", "name": "project_nature", "label": "项目性质", "options": [{"value": "新增", "display": "新增"}, {"value": "存续", "display": "存续"}, {"value": "新增及存续", "display": "新增及存续"}, {"value": "老客户新业务", "display": "老客户新业务"}]}, {"type": "select", "id": "department", "name": "department", "label": "一级部门", "options": [{"value": "天信", "display": "天信"}, {"value": "混改", "display": "混改"}, {"value": "艾力芬特", "display": "艾力芬特"}, {"value": "星河", "display": "星河"}, {"value": "星海", "display": "星海"}]}, {"type": "date", "id": "invoice_date", "name": "invoice_date", "label": "开票日期"}, {"type": "text", "id": "project_manager", "name": "project_manager", "label": "项目负责人", "placeholder": "请输入项目负责人"} ], "excel_upload_config": { "template_url": reverse("download_template", kwargs={'template_name': template_name}), "parse_url": reverse("common_excel_parse_pjt"), "save_url": reverse("save_excel_table_data_pjt"), "fields_preview_config": { "project_name": {"type": "text", "width": "180px"}, "primary_department": {"type": "text", "width": "180px"}, "project_manager": {"type": "text", "width": "180px"}, "nature": {"type": "select", "width": "100px", "options": ["新增", "开票"]}, "billing_entity": {"type": "text", "width": "180px"}, "invoice_number": {"type": "text", "width": "180px"}, "purchase_info": {"type": "text", "width": "180px"}, "invoice_date": {"type": "date", "width": "180px"}, "invoice_content": {"type": "text", "width": "180px"}, "total_amount": {"type": "number", "width": "100px"}, "tax_rate": {"type": "number", "width": "100px"}, "amount_excluding_tax": {"type": "number", "width": "100px"}, "tax_amount": {"type": "number", "width": "100px"}, "invoice_type": {"type": "select", "width": "100px", "options": ["专票", "普票"]}, } }, "query_params": query_params, "table_exclude_field_name": ['record_id', 'project_id'], "form_action_url": 'inv_rec_list', "modify_url": reverse("inv_rec_list_modify"), "add_url": reverse("inv_rec_list_add"), "delete_url": reverse("inv_rec_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_invoicerecord') def inv_rec_list_add(request): if request.method == 'POST': form = InvoiceRecordForm(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 = InvoiceRecordForm() 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('fac_mgnt.change_invoicerecord') def inv_rec_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = InvoiceRecord.objects.get(record_id=request.POST['id']) form = InvoiceRecordForm(request.POST, instance=instance) else: form = InvoiceRecordForm(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 = InvoiceRecord.objects.get(record_id=request.GET['id']) form = InvoiceRecordForm(instance=instance) except InvoiceRecord.DoesNotExist: raise Http404("对象不存在") else: form = InvoiceRecordForm() 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('fac_mgnt.delete_invoicerecord') def inv_rec_list_delete(request): if request.method == 'GET': target_id = request.GET.get('target_id') InvoiceRecord.objects.filter(record_id=target_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required @custom_permission_required('fac_mgnt.view_repaymentrecord') def rep_rec_list_view(request): query_set = RepaymentRecord.objects.filter().order_by('-record_id') project_name = request.GET.get('project_name', '') if project_name: query_set = query_set.filter(project_name__icontains=project_name) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&project_name={}'.format(project_name) template_name = "财会管理-回款记录-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.RepaymentRecord', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "回款记录表", "name": "rep_rec_list"} ], "filters": [ {"type": "text", "id": "project_name", "name": "project_name", "label": "项目名称", "placeholder": "请输入项目名称"} ], "excel_upload_config": { "template_url": reverse("download_template", kwargs={'template_name': template_name}), "parse_url": reverse("common_excel_parse_rr"), "save_url": reverse("save_excel_table_data_rr"), "fields_preview_config": { "project_name": {"type": "text", "width": "180px"}, "primary_department": {"type": "text", "width": "180px"}, "project_manager": {"type": "text", "width": "180px"}, "repayment_amount": {"type": "number", "width": "100px"}, } }, "table_exclude_field_name": ['record_id'], "query_params": query_params, "form_action_url": 'rep_rec_list', "modify_url": reverse("rep_rec_list_modify"), "add_url": reverse("rep_rec_list_add"), "delete_url": reverse("rep_rec_list_delete"), } return render(request, 'rep_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_repaymentrecord') def rep_rec_list_add(request): if request.method == 'POST': form = RepaymentRecordForm(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 = RepaymentRecordForm() 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('fac_mgnt.change_repaymentrecord') def rep_rec_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = RepaymentRecord.objects.get(record_id=request.POST['id']) form = RepaymentRecordForm(request.POST, instance=instance) else: form = RepaymentRecordForm(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 = RepaymentRecord.objects.get(record_id=request.GET['id']) form = RepaymentRecordForm(instance=instance) except RepaymentRecord.DoesNotExist: raise Http404("对象不存在") else: form = RepaymentRecordForm() 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('fac_mgnt.delete_repaymentrecord') def rep_rec_list_delete(request): if request.method == 'GET': target_id = request.GET.get('target_id') RepaymentRecord.objects.filter(record_id=target_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required # @custom_permission_required('hrm_mgnt.view_repaymentdetail') def get_repayment_details(request, repayment_record_id): details = RepaymentDetail.objects.filter(repayment_record_id=repayment_record_id).values( 'repayment_date', 'repayment_amount') return JsonResponse(list(details), safe=False) @login_required # @custom_permission_required('hrm_mgnt.add_repaymentdetail') @require_POST def add_repayment_detail(request): repayment_record_id = request.POST.get('repayment_record_id') repayment_date = request.POST.get('repayment_date') repayment_amount = request.POST.get('repayment_amount') repayment_record = get_object_or_404(RepaymentRecord, pk=repayment_record_id) # 新增回款详情 detail = RepaymentDetail.objects.create( repayment_record=repayment_record, repayment_date=repayment_date, repayment_amount=Decimal(repayment_amount) ) # 更新回款记录表中的回款金额字段 repayment_record.repayment_amount += Decimal(repayment_amount) repayment_record.save() return JsonResponse({ 'record_id': detail.record_id, 'repayment_date': detail.repayment_date, 'repayment_amount': detail.repayment_amount, }) @login_required @custom_permission_required('fac_mgnt.view_employeecommission') def emp_comm_list_view(request): query_set = EmployeeCommission.objects.filter().order_by('-record_id') project_name = request.GET.get('project_name', '') name = request.GET.get('name', '') primary_department = request.GET.get('primary_department', '') if project_name: query_set = query_set.filter(project_name__icontains=project_name) if name: query_set = query_set.filter(name__icontains=name) if primary_department: query_set = query_set.filter(primary_department__icontains=primary_department) items = paginate_query_and_assign_numbers(request=request, queryset=query_set, per_page=10) query_params = '&project_name={}&name={}&primary_department={}'.format(project_name, name, primary_department) template_name = "财会管理-员工提成情况-Excel上传模板.xlsx" context = { "model_config": 'fac_mgnt.EmployeeCommission', "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "财会管理", "name": "index"}, {"title": "员工提成情况表", "name": "emp_comm_list"} ], "filters": [ {"type": "text", "id": "project_name", "name": "project_name", "label": "项目名称", "placeholder": "请输入项目名称"}, {"type": "text", "id": "name", "name": "name", "label": "姓名", "placeholder": "请输入姓名"}, {"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"), "save_url": reverse("save_excel_table_data"), "fields_preview_config": { "project_name": {"type": "text", "width": "180px"}, "year_month": {"type": "date", "width": "180px"}, "company_retained": {"type": "number", "width": "100px"}, "name": {"type": "text", "width": "180px"}, "primary_department": {"type": "text", "width": "180px"}, "total_commission": {"type": "number", "width": "100px"}, "amount_paid": {"type": "number", "width": "100px"}, "accrued_amount": {"type": "number", "width": "100px"}, "chairman_fund": {"type": "number", "width": "100px"}, "actions": {"type": "actions", "width": "100px"} } }, "query_params": query_params, "table_exclude_field_name": ['record_id'], "form_action_url": 'emp_comm_list', "modify_url": reverse("emp_comm_list_modify"), "add_url": reverse("emp_comm_list_add"), "delete_url": reverse("emp_comm_list_delete"), } return render(request, 'items_list.html', context) @login_required @custom_permission_required('fac_mgnt.add_employeecommission') def emp_comm_list_add(request): if request.method == 'POST': form = EmployeeCommissionForm(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 = EmployeeCommissionForm() 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('fac_mgnt.change_employeecommission') def emp_comm_list_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = EmployeeCommission.objects.get(record_id=request.POST['id']) form = EmployeeCommissionForm(request.POST, instance=instance) else: form = EmployeeCommissionForm(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 = EmployeeCommission.objects.get(record_id=request.GET['id']) form = EmployeeCommissionForm(instance=instance) except EmployeeCommission.DoesNotExist: raise Http404("对象不存在") else: form = EmployeeCommissionForm() 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('fac_mgnt.delete_employeecommission') def emp_comm_list_delete(request): if request.method == 'GET': target_id = request.GET.get('target_id') EmployeeCommission.objects.filter(record_id=target_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required # @custom_permission_required('hrm_mgnt.view_projectcommission') def project_commission_list_view(request): # 声明查询集 query_set = ProjectCommission.objects.all().order_by('-record_id') # 获取查询参数 project_name = request.GET.get('project_name', '') # 根据提供的参数进行筛选 if project_name: query_set = query_set.filter(project_name__icontains=project_name) # 对查询结果进行分页,每页10条记录 items = paginate_query_and_assign_numbers( request=request, queryset=query_set, per_page=10 ) # 构建上下文查询参数字符串 query_params = '&project_name={}'.format(project_name) # Excel上传模板 template_name = "财会管理-项目提成情况-Excel上传模板.xlsx" # 构建上下文 context = { "model_config": "fac_mgnt.ProjectCommission", "items": items, "breadcrumb_list": [ {"title": "首页", "name": "index"}, {"title": "人力资源管理", "name": "index"}, {"title": "项目提成情况表", "name": "project_commission_list"} ], "filters": [ { "type": "text", "id": "project_name", "name": "project_name", "label": "项目名称", "placeholder": "请输入项目名称" } ], "excel_upload_config": { "template_url": reverse("download_template", kwargs={'template_name': template_name}), "parse_url": reverse("common_excel_parse_pc"), "save_url": reverse("save_excel_table_data_pc"), "fields_preview_config": { "project_name": {"type": "text", "width": "180px"}, "year_month": {"type": "text", "width": "220px"}, "company_retained": {"type": "text", "width": "120px"}, "total_commission": {"type": "number", "width": "120px"}, "chairman_fund": {"type": "number", "width": "120px"}, } }, "query_params": query_params, "table_exclude_field_name": ['record_id'], "form_action_url": "project_commission_list", "modify_url": reverse("project_commission_modify"), "add_url": reverse("project_commission_add"), "delete_url": reverse("project_commission_delete"), } return render(request, 'pc_list.html', context) @login_required # @custom_permission_required('hrm_mgnt.add_projectcommission') def project_commission_add(request): if request.method == 'POST': form = ProjectCommissionForm(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 = ProjectCommissionForm() 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_projectcommission') def project_commission_modify(request): if request.method == 'POST': if 'id' in request.POST: instance = ProjectCommission.objects.get(record_id=request.POST['id']) form = ProjectCommissionForm(request.POST, instance=instance) else: form = ProjectCommissionForm(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 = ProjectCommission.objects.get(record_id=request.GET['id']) form = ProjectCommissionForm(instance=instance) except ProjectCommission.DoesNotExist: raise Http404("对象不存在") else: form = ProjectCommissionForm() 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_projectcommission') def project_commission_delete(request): if request.method == 'GET': record_id = request.GET.get('record_id') ProjectCommission.objects.filter(record_id=record_id).delete() return JsonResponse({"message": "删除成功"}) return JsonResponse({"message": "无效的请求方法"}, status=405) @login_required # @custom_permission_required('hrm_mgnt.view_employeecommissiondetail') def get_employee_commission_details(request, project_commission_id): employee_commissions = EmployeeCommissionDetail.objects.filter(project_commission_id=project_commission_id) data = [ { "record_id": ec.record_id, "employee_name": ec.employee.name, "primary_department": ec.primary_department, "year": ec.year, "performance_score": ec.performance_score, "total_commission": ec.total_commission, "amount_paid": ec.amount_paid, "accrued_amount": ec.accrued_amount, "back_pay_amount": ec.back_pay_amount, "deduction_amount": ec.deduction_amount, } for ec in employee_commissions ] return JsonResponse(data, safe=False) @login_required # @custom_permission_required('hrm_mgnt.view_employeeinformation') def get_employees(request): employees = EmployeeInformation.objects.all() data = [{"id": emp.employee_id, "name": emp.name} for emp in employees] return JsonResponse({"employees": data}) @login_required # @custom_permission_required('hrm_mgnt.view_employeeinformation') def get_employee_info(request, employee_id): employee = get_object_or_404(EmployeeInformation, pk=employee_id) data = { "primary_department": employee.primary_department, } return JsonResponse(data) @login_required # @custom_permission_required('hrm_mgnt.view_performanceevaluation') def get_performance_score(request, employee_id, year): try: performance = PerformanceEvaluation.objects.get(employee_id=employee_id, year=year) data = {"performance_score": performance.performance_score} except PerformanceEvaluation.DoesNotExist: data = {"performance_score": ""} return JsonResponse(data) @login_required # @custom_permission_required('hrm_mgnt.add_employeecommissiondetail') def add_employee_commission_detail(request): if request.method == 'POST': employee_id = request.POST.get('employee') project_commission_id = request.POST.get('project_commission') primary_department = request.POST.get('primary_department') year = request.POST.get('year') performance_score = request.POST.get('performance_score') total_commission = request.POST.get('total_commission') amount_paid = request.POST.get('amount_paid') accrued_amount = request.POST.get('accrued_amount') back_pay_amount = request.POST.get('back_pay_amount') deduction_amount = request.POST.get('deduction_amount') employee = get_object_or_404(EmployeeInformation, pk=employee_id) project_commission = get_object_or_404(ProjectCommission, pk=project_commission_id) EmployeeCommissionDetail.objects.create( project_commission=project_commission, employee=employee, primary_department=primary_department, year=year, performance_score=performance_score, total_commission=total_commission, amount_paid=amount_paid, accrued_amount=accrued_amount, back_pay_amount=back_pay_amount, deduction_amount=deduction_amount ) return JsonResponse({"success": True}) return JsonResponse({"success": False, "message": "Invalid request method."}) @login_required @require_http_methods(["DELETE"]) def delete_employee_commission(request, commission_id): commission = get_object_or_404(EmployeeCommissionDetail, record_id=commission_id) commission.delete() return JsonResponse({"success": True}) @login_required # @custom_permission_required('fm.change_employeecommission') def edit_employee_commission_detail(request, commission_id): commission = get_object_or_404(EmployeeCommissionDetail, record_id=commission_id) if request.method == 'POST': form = EmployeeCommissionDetailForm(request.POST, instance=commission) if form.is_valid(): form.save() return JsonResponse({"success": True}) else: return JsonResponse({"success": False, "message": "表单无效", "form_html": render_to_string('form_partial.html', {'form': form}, request)}) elif request.method == 'GET': data = { 'record_id': commission.record_id, 'employee': commission.employee.name, 'primary_department': commission.primary_department, 'year': commission.year, 'performance_score': commission.performance_score, 'total_commission': commission.total_commission, 'amount_paid': commission.amount_paid, 'accrued_amount': commission.accrued_amount, 'back_pay_amount': commission.back_pay_amount, 'deduction_amount': commission.deduction_amount } return JsonResponse(data) else: return JsonResponse({"message": "无效的请求方法"}, status=405) @csrf_protect @login_required def common_excel_parse_exp(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 'type_id' in representation and instance.type_id: representation['type_id'] = instance.type_id.expense_type 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)) # 处理type_id字段,假设模型中有type_id字段并且Excel文件中的表头包含费用类型名称 expense_type_name = instance_data.get('type_id') if expense_type_name: try: expense_type_instance = ExpenseType.objects.get(expense_type=expense_type_name) instance_data['type_id'] = expense_type_instance except ExpenseType.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {expense_type_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_exp(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: # 处理type_id字段,假设模型中有type_id字段并且table_data中包含费用类型名称 expense_type_name = row_data.get('type_id') if expense_type_name: try: expense_type_instance = ExpenseType.objects.get(expense_type=expense_type_name) row_data['type_id'] = expense_type_instance except ExpenseType.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {expense_type_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_gab(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 'type_id' in representation and instance.type_id: representation['type_id'] = instance.type_id.expense_type if 'expense_detail' in representation and instance.expense_detail: representation['expense_detail'] = instance.expense_detail.expense_detail 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)) # 处理type_id字段,假设模型中有type_id字段并且Excel文件中的表头包含费用类型名称 expense_type_name = instance_data.get('expense_type') if expense_type_name: try: expense_type_instance = ExpenseType.objects.get(expense_type=expense_type_name) instance_data['expense_type'] = expense_type_instance except ExpenseType.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {expense_type_name} 的费用类型信息。'}, status=400) # 处理expense_detail字段,假设模型中有expense_detail字段并且Excel文件中的表头包含费用明细名称 expense_detail_name = instance_data.get('expense_detail') if expense_detail_name: try: expense_detail_instance = ExpenseDetail.objects.get(expense_detail=expense_detail_name) instance_data['expense_detail'] = expense_detail_instance except ExpenseDetail.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {expense_detail_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_gab(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: # 处理type_id字段,假设模型中有type_id字段并且table_data中包含费用类型名称 expense_type_name = row_data.get('expense_type') if expense_type_name: try: expense_type_instance = ExpenseType.objects.get(type_id=expense_type_name) row_data['expense_type'] = expense_type_instance except ExpenseType.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {expense_type_name} 的费用类型信息。'}, status=400) # 处理expense_detail字段,假设模型中有expense_detail字段并且table_data中包含费用明细名称 expense_detail_name = row_data.get('expense_detail') if expense_detail_name: try: expense_detail_instance = ExpenseDetail.objects.get(expense_detail=expense_detail_name) row_data['expense_detail'] = expense_detail_instance except ExpenseDetail.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {expense_detail_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_pjt(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 'project_id' in representation and instance.project_id: representation['project_id'] = instance.project_id.project_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 ['project_id']] model_verbose_name = [field.verbose_name for field in model._meta.fields if not field.primary_key and field.name not in ['project_id']] 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)) # 处理project_id字段,假设模型中有project_id字段并且Excel文件中的表头包含项目名称 project_name = instance_data.get('project_name') if project_name: try: project_instance = ProjectLedger.objects.get(project_name=project_name) instance_data['project_id'] = project_instance except ProjectLedger.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {project_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_pjt(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: # 处理project_id字段,假设模型中有project_id字段并且table_data中包含项目名称 project_name = row_data.get('project_name') if project_name: try: project_instance = ProjectLedger.objects.get(project_name=project_name) row_data['project_id'] = project_instance row_data['project_name'] = project_instance.project_name except ProjectLedger.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {project_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_rr(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 'project_id' in representation and instance.project_id: representation['project_id'] = instance.project_id.project_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 ['project_id', 'invoice']] model_verbose_name = [field.verbose_name for field in model._meta.fields if not field.primary_key and field.name not in ['project_id', 'invoice']] 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)) # 处理project_id字段,假设模型中有project_id字段并且Excel文件中的表头包含项目名称 project_name = instance_data.get('project_name') if project_name: try: project_instance = ProjectLedger.objects.get(project_name=project_name) invoice_instance = InvoiceRecord.objects.get(project_name=project_name) instance_data['invoice'] = invoice_instance instance_data['project_id'] = project_instance instance_data['project_name'] = project_instance.project_name except ProjectLedger.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {project_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_rr(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: # 处理project_id字段,假设模型中有project_id字段并且table_data中包含项目名称 project_name = row_data.get('project_name') if project_name: try: project_instance = ProjectLedger.objects.get(project_name=project_name) invoice_instance = InvoiceRecord.objects.get(project_name=project_name) row_data['invoice'] = invoice_instance row_data['project_id'] = project_instance row_data['project_name'] = project_instance.project_name except ProjectLedger.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {project_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_pc(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 'project_id' in representation and instance.project_id: representation['project_id'] = instance.project_id.project_name if 'project_name' in representation and instance.project_name: representation['project_name'] = instance.project_name.project_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 ['record_id']] model_verbose_name = [field.verbose_name for field in model._meta.fields if not field.primary_key and field.name not in ['record_id']] 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)) # 处理project_id字段,假设模型中有project_id字段并且Excel文件中的表头包含项目名称 project_name = instance_data.get('project_name') if project_name: try: project_instance = ProjectLedger.objects.get(project_name=project_name) instance_data['project_name'] = project_instance except ProjectLedger.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {project_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_pc(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: # 处理project_id字段,假设模型中有project_id字段并且table_data中包含项目名称 project_name = row_data.get('project_name') if project_name: try: project_instance = ProjectLedger.objects.get(project_name=project_name) row_data['project_name'] = project_instance except ProjectLedger.DoesNotExist: return JsonResponse({'error': f'找不到名称为 {project_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)