XH_Digital_Management/application/fac_mgnt/views.py

2637 lines
119 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

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

import json
from 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)