parent
dd96f1dcdb
commit
dd5faba1de
|
@ -5,13 +5,20 @@ from application.hrm_mgnt.models import EmployeeInformation
|
|||
|
||||
|
||||
class AccountProfile(models.Model):
|
||||
ROLE_CHOICES = [
|
||||
('all_permissions', 'All Permissions'),
|
||||
('department_permissions', 'Department Permissions'),
|
||||
('own_permissions', 'Own Permissions'),
|
||||
]
|
||||
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='profile')
|
||||
employee_information = models.OneToOneField(EmployeeInformation, on_delete=models.CASCADE, related_name='account_profile', verbose_name='员工信息')
|
||||
role = models.CharField(max_length=255, choices=ROLE_CHOICES, verbose_name='角色', default='own_permissions')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '账户信息'
|
||||
verbose_name_plural = '账户信息'
|
||||
|
||||
def __str__(self):
|
||||
return self.user.username
|
||||
return self.employee_information.name
|
||||
|
||||
|
|
|
@ -55,3 +55,11 @@ class EmployeeProjectIncomeSettlementForm(forms.ModelForm):
|
|||
'contribution_rate': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '贡献率'}),
|
||||
'sales_income': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': '销售收入(元)'}),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(EmployeeProjectIncomeSettlementForm, self).__init__(*args, **kwargs)
|
||||
|
||||
self.fields['primary_department'] = forms.ChoiceField(
|
||||
choices=[('', '---------')] + [(dept.department_name, dept.department_name) for dept in PrimaryDepartment.objects.all()],
|
||||
widget=forms.Select(attrs={'class': 'form-control'}),
|
||||
label="一级部门")
|
|
@ -62,12 +62,6 @@ class ProjectLedger(models.Model):
|
|||
verbose_name = '项目台账'
|
||||
verbose_name_plural = '项目台账'
|
||||
|
||||
permissions = [
|
||||
('view_all', 'Can view all records'),
|
||||
('view_department', 'Can view department records'),
|
||||
('view_own', 'Can view own records')
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return self.project_name
|
||||
|
||||
|
@ -254,6 +248,7 @@ class EmployeeProjectIncomeSettlement(models.Model):
|
|||
blank=True
|
||||
)
|
||||
name = models.CharField(max_length=255, verbose_name='姓名', help_text='员工姓名', null=True, blank=True)
|
||||
primary_department = models.CharField(max_length=255, verbose_name='一级部门', null=True, blank=True)
|
||||
contribution_rate = models.DecimalField(
|
||||
max_digits=5,
|
||||
decimal_places=2,
|
||||
|
@ -276,16 +271,26 @@ class EmployeeProjectIncomeSettlement(models.Model):
|
|||
verbose_name = '项目组员收入结算表'
|
||||
verbose_name_plural = '项目组员收入结算表'
|
||||
|
||||
permissions = [
|
||||
('view_all', 'Can view all records'),
|
||||
('view_department', 'Can view department records'),
|
||||
('view_own', 'Can view own records')
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"Record #{self.record_id} - Project: {self.project_name}, Year-Month: {self.year_month}, Employee: {self.name or 'N/A'}"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
primary_department_name = PrimaryDepartment.objects.filter(department_name=self.primary_department).first()
|
||||
name = EmployeeInformation.objects.filter(name=self.name).first()
|
||||
|
||||
if self.primary_department:
|
||||
if not primary_department_name:
|
||||
raise ValueError("一级部门不存在")
|
||||
|
||||
if self.name:
|
||||
if not name:
|
||||
raise ValueError("姓名不存在")
|
||||
|
||||
if self.pk is None:
|
||||
# 新增操作,进行唯一性校验
|
||||
if EmployeeProjectIncomeSettlement.objects.filter(project_name=self.project_name, year_month=self.year_month, name=self.name, primary_department=self.primary_department).exists():
|
||||
raise IntegrityError("该部门下的员工在同一年月的同一项目下已存在一个项目结算。")
|
||||
|
||||
# 只在贡献率不为空时计算销售收入
|
||||
if all([self.contribution_rate, self.total_amount_including_tax]):
|
||||
self.sales_income = self.total_amount_including_tax * (self.contribution_rate / 100)
|
||||
|
|
|
@ -241,7 +241,7 @@ def proj_ledger_list_delete(request):
|
|||
|
||||
|
||||
@custom_permission_required('pjt_mgnt.view_employeeprojectincomesettlement')
|
||||
@permission_based_queryset('pjt_mgnt', 'EmployeeProjectIncomeSettlement', 'record_id', 'name')
|
||||
@permission_based_queryset('pjt_mgnt', 'EmployeeProjectIncomeSettlement', 'record_id', 'name', 'primary_department')
|
||||
def emp_proj_income_list_view(request):
|
||||
"""
|
||||
基础数据-项目管理-项目组员收入结算表-列表视图
|
||||
|
@ -354,8 +354,8 @@ def emp_proj_income_list_modify(request):
|
|||
except ValueError:
|
||||
return JsonResponse({"message": "无效的日期格式"}, status=400)
|
||||
|
||||
if 'record_id' in request.POST:
|
||||
instance = EmployeeProjectIncomeSettlement.objects.get(record_id=request.POST['record_id'])
|
||||
if 'id' in request.POST:
|
||||
instance = EmployeeProjectIncomeSettlement.objects.get(record_id=request.POST['id'])
|
||||
form = EmployeeProjectIncomeSettlementForm(data, instance=instance)
|
||||
else:
|
||||
form = EmployeeProjectIncomeSettlementForm(data)
|
||||
|
@ -367,9 +367,9 @@ def emp_proj_income_list_modify(request):
|
|||
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 'record_id' in request.GET:
|
||||
if 'id' in request.GET:
|
||||
try:
|
||||
instance = EmployeeProjectIncomeSettlement.objects.get(record_id=request.GET['record_id'])
|
||||
instance = EmployeeProjectIncomeSettlement.objects.get(record_id=request.GET['id'])
|
||||
form = EmployeeProjectIncomeSettlementForm(instance=instance)
|
||||
form.fields['year_month'].initial = instance.year_month.strftime('%Y-%m')
|
||||
except EmployeeProjectIncomeSettlement.DoesNotExist:
|
||||
|
|
|
@ -67,7 +67,7 @@ class MembershipAccountsRegistryForm(forms.ModelForm):
|
|||
class StoredValueCardRegistrationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = StoredValueCardRegistration
|
||||
fields = '__all__'
|
||||
exclude = ['usage_records']
|
||||
widgets = {
|
||||
'merchant_name': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'merchant_type': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
|
|
|
@ -42,21 +42,18 @@ def permission_based_queryset(app_name, model_name, id_field, leader_field=None,
|
|||
except AccountProfile.DoesNotExist:
|
||||
return JsonResponse({'message': '您的账户未关联到员工信息,请联系管理员。'}, status=405)
|
||||
|
||||
view_all_perm = f'{app_name}.view_all'
|
||||
view_department_perm = f'{app_name}.view_department'
|
||||
|
||||
model = apps.get_model(app_name, model_name)
|
||||
|
||||
if current_user.has_perm(view_all_perm):
|
||||
if account_profile.role == 'all_permissions':
|
||||
query_set = model.objects.all().order_by(f'-{id_field}')
|
||||
elif department_field and current_user.has_perm(view_department_perm):
|
||||
elif department_field and account_profile.role == 'department_permissions':
|
||||
filter_kwargs = {department_field: employee.primary_department}
|
||||
query_set = model.objects.filter(**filter_kwargs).order_by(f'-{id_field}')
|
||||
elif leader_field:
|
||||
elif leader_field and account_profile.role == 'own_permissions':
|
||||
filter_kwargs = {leader_field: employee.name}
|
||||
query_set = model.objects.filter(**filter_kwargs).order_by(f'-{id_field}')
|
||||
else:
|
||||
return JsonResponse({'message': '您没有权限查看任何数据。'}, status=403)
|
||||
query_set = model.objects.none()
|
||||
|
||||
request.query_set = query_set
|
||||
|
||||
|
|
|
@ -1,23 +1,17 @@
|
|||
import json
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from urllib.parse import quote
|
||||
|
||||
from django.apps import apps
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.shortcuts import render
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import JsonResponse, HttpResponse
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.timezone import make_aware
|
||||
from django.http import JsonResponse
|
||||
from django.views.decorators.csrf import csrf_protect
|
||||
|
||||
from application.fac_mgnt.models import InvoiceRecord
|
||||
from application.org_mgnt.models import SecondaryDepartment, PrimaryDepartment
|
||||
from application.pjt_mgnt.models import ProjectLedger
|
||||
import pandas as pd
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.utils.http import quote
|
||||
from django.apps import apps
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.utils import get_column_letter
|
||||
from datetime import datetime
|
||||
from django.utils.timezone import make_aware
|
||||
|
||||
def error_page(request):
|
||||
return render(request, 'error_page.html')
|
||||
|
@ -128,16 +122,28 @@ def export_data(request):
|
|||
field_names = [field.name for field in model._meta.fields]
|
||||
verbose_names = [field.verbose_name for field in model._meta.fields]
|
||||
|
||||
# 创建 DataFrame 并设置 verbose_name 作为列名
|
||||
df = pd.DataFrame(data, columns=field_names)
|
||||
df.columns = verbose_names
|
||||
# 创建 Excel 工作簿
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
|
||||
# 写入表头
|
||||
for col_num, verbose_name in enumerate(verbose_names, 1):
|
||||
col_letter = get_column_letter(col_num)
|
||||
ws[f'{col_letter}1'] = verbose_name
|
||||
|
||||
# 写入数据
|
||||
for row_num, record in enumerate(data, 2):
|
||||
for col_num, field_name in enumerate(field_names, 1):
|
||||
col_letter = get_column_letter(col_num)
|
||||
# 如果字段在记录中不存在,使用空字符串
|
||||
ws[f'{col_letter}{row_num}'] = record.get(field_name, '')
|
||||
|
||||
# 使用模型的 verbose_name 作为文件名的一部分
|
||||
model_verbose_name = model._meta.verbose_name + '导出结果.xlsx'
|
||||
encoded_filename = quote(model_verbose_name)
|
||||
|
||||
response = HttpResponse(content_type='application/vnd.ms-excel')
|
||||
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
||||
response['Content-Disposition'] = f'attachment; filename*=UTF-8\'\'{encoded_filename}'
|
||||
df.to_excel(response, index=False)
|
||||
wb.save(response)
|
||||
|
||||
return response
|
||||
return response
|
Loading…
Reference in New Issue