1466 lines
77 KiB
Python
1466 lines
77 KiB
Python
from decimal import Decimal
|
||
|
||
from django.db import models
|
||
from django.db.models import Sum, F
|
||
from django.utils import timezone
|
||
|
||
from application.fac_mgnt.models import ReimbursementDetail, LaborCostDetail, RepaymentRecord, InvoiceRecord, \
|
||
GroupAnnualBudget, ProjectCommission, EmployeeCommissionDetail
|
||
from application.hrm_mgnt.models import EmployeeInformation
|
||
from application.org_mgnt.models import PrimaryDepartment
|
||
from application.perf_mgnt.models import GroupBusinessTarget, EmployeePerformanceTarget
|
||
from application.pjt_mgnt.models import ProjectLedger
|
||
|
||
|
||
class UpdateLog(models.Model):
|
||
table_name = models.CharField(max_length=255, unique=True, verbose_name="表名")
|
||
last_update = models.DateField(verbose_name="最后更新时间", default=timezone.now)
|
||
|
||
class Meta:
|
||
verbose_name = "更新记录"
|
||
verbose_name_plural = "更新记录"
|
||
|
||
def __str__(self):
|
||
return f"{self.table_name} - {self.last_update}"
|
||
|
||
|
||
# 1.年度总体经营目标
|
||
class DepartmentAnnualPerformance(models.Model):
|
||
"""
|
||
年度营业收入(万元)(=价税合计金额按一级部门和年份筛选完后的累计值)及 完成率(= 年度营业收入 / 收入总目标)【项目台账-价税合计金额, 集团经营目标-收入总目标】
|
||
年度新增收入(万元)(=价税合计金额按一级部门、年份、性质筛选完后的累计值)及 完成率(=年度新增收入/ 新增收入目标)【项目台账-价税合计金额, 集团经营目标-新增收入总目标】
|
||
年度存量收入(万元) (=价税合计金额按一级部门、年份、性质筛选完后的累计值)及 完成率(=年度存量收入 / 存量收入目标)【项目台账-价税合计金额, 集团经营目标-存量收入目标】
|
||
年度营业成本(万元) (=价税合计金额累计-应收净收入累计)及 占用率(年度营业成本 / 成本限额)【项目台账-价税合计金额,项目台账-应收净收入, 集团经营目标-存量收入目标, 集团经营目标表-成本限额 】
|
||
年度费用开销(万元) (=费用金额累计 + 全勤奖 + 餐津贴 + 其他货币性福利 + 实发工资 + 公司承担社保 + 公司承担公积金)及 占用率(=年度费用开销 / 费用限额)【报销明细-费用金额 ,人工费用明细-全勤奖、午餐津贴、其他货币型福利、实发工资、公司承担社保、公司承担公积金, 集团经营目标-费用限额 】
|
||
营业利润(万元) (=年度营业收入-年度营业成本-年度费用开销-开票税金(=税额按部门按年累计*1.12))【回款记录-不含税金额】
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门")
|
||
year = models.IntegerField(verbose_name="年份", help_text="表示数据统计的年份")
|
||
annual_revenue = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年度营业收入")
|
||
annual_revenue_completion_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="年度营业收入完成率")
|
||
annual_new_revenue = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年度新增收入")
|
||
annual_new_revenue_completion_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="年度新增收入完成率")
|
||
annual_existing_revenue = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年度存量收入")
|
||
annual_existing_revenue_completion_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="年度存量收入完成率")
|
||
annual_operating_costs = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年度营业成本")
|
||
annual_operating_costs_utilization_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="年度营业成本占用率")
|
||
annual_expenses = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年度费用开销")
|
||
annual_expenses_utilization_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="年度费用开销占用率")
|
||
operating_profit = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="营业利润")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门年度总体经营指标"
|
||
verbose_name_plural = "业务部门年度总体经营指标"
|
||
db_table_comment = '存储业务部门年度总体经营指标数据,包括一级部门、年份、营业收入及其完成率、新增收入及其完成率、存量收入及其完成率、营业成本及其占用率、费用开销及其占用率、营业利润等'
|
||
|
||
def __str__(self):
|
||
return f"{self.year} 年 {self.primary_department} 的经营指标"
|
||
|
||
@staticmethod
|
||
def calculate_and_update_for_year(year):
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 年度营业收入
|
||
annual_revenue = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 收入总目标
|
||
total_revenue_target = GroupBusinessTarget.objects.filter(
|
||
primary_department=primary_department,
|
||
year=year
|
||
).aggregate(total=Sum('total_revenue_target'))['total'] or Decimal('1') # 避免除以零
|
||
|
||
# 年度营业收入完成率
|
||
annual_revenue_completion_rate = annual_revenue / total_revenue_target
|
||
|
||
# 年度新增收入
|
||
annual_new_revenue = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
project_nature="新增"
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 新增收入总目标
|
||
new_revenue_target = GroupBusinessTarget.objects.filter(
|
||
primary_department=primary_department,
|
||
year=year
|
||
).aggregate(total=Sum('new_revenue_target'))['total'] or Decimal('1')
|
||
|
||
# 年度新增收入完成率
|
||
annual_new_revenue_completion_rate = annual_new_revenue / new_revenue_target
|
||
|
||
# 年度存量收入
|
||
annual_existing_revenue = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
project_nature="存量"
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 存量收入总目标
|
||
existing_revenue_target = GroupBusinessTarget.objects.filter(
|
||
primary_department=primary_department,
|
||
year=year
|
||
).aggregate(total=Sum('existing_revenue_target'))['total'] or Decimal('1')
|
||
|
||
# 年度存量收入完成率
|
||
annual_existing_revenue_completion_rate = annual_existing_revenue / existing_revenue_target
|
||
|
||
# 年度营业成本
|
||
total_amount_including_tax = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
net_receivable_amount = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('receivable_net_income'))['total'] or Decimal('0')
|
||
|
||
annual_operating_costs = total_amount_including_tax - net_receivable_amount
|
||
|
||
# 成本限额
|
||
cost_limit = GroupBusinessTarget.objects.filter(
|
||
primary_department=primary_department,
|
||
year=year
|
||
).aggregate(total=Sum('cost_limit'))['total'] or Decimal('1')
|
||
|
||
# 年度营业成本占用率
|
||
annual_operating_costs_utilization_rate = annual_operating_costs / cost_limit
|
||
|
||
# 年度费用开销
|
||
reimbursement_amount = ReimbursementDetail.objects.filter(
|
||
primary_department=primary_department,
|
||
year_month__year=year
|
||
).aggregate(total=Sum('amount'))['total'] or Decimal('0')
|
||
|
||
labor_cost = LaborCostDetail.objects.filter(
|
||
primary_department=primary_department,
|
||
year_month__year=year
|
||
).aggregate(
|
||
attendance_reward=Sum('attendance_reward'),
|
||
lunch_allowance=Sum('lunch_allowance'),
|
||
other_monetary_benefits=Sum('other_monetary_benefits'),
|
||
net_salary=Sum('net_salary'),
|
||
employer_social_security=Sum('employer_social_security'),
|
||
employer_housing_fund=Sum('employer_housing_fund')
|
||
)
|
||
|
||
labor_cost_total = sum(value or Decimal('0') for value in labor_cost.values())
|
||
|
||
annual_expenses = reimbursement_amount + labor_cost_total
|
||
|
||
# 费用限额
|
||
expense_limit = GroupBusinessTarget.objects.filter(
|
||
primary_department=primary_department,
|
||
year=year
|
||
).aggregate(total=Sum('expense_limit'))['total'] or Decimal('1')
|
||
|
||
# 年度费用开销占用率
|
||
annual_expenses_utilization_rate = annual_expenses / expense_limit
|
||
|
||
# 营业利润
|
||
amount_excluding_tax = InvoiceRecord.objects.filter(
|
||
primary_department=primary_department,
|
||
invoice_date__year=year
|
||
).aggregate(total=Sum('amount_excluding_tax'))['total'] or Decimal('0')
|
||
|
||
operating_profit = annual_revenue - annual_operating_costs - annual_expenses - (
|
||
amount_excluding_tax * Decimal('1.12'))
|
||
|
||
# 更新或创建模型实例
|
||
performance, created = DepartmentAnnualPerformance.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
year=year,
|
||
defaults={
|
||
'annual_revenue': annual_revenue,
|
||
'annual_revenue_completion_rate': annual_revenue_completion_rate,
|
||
'annual_new_revenue': annual_new_revenue,
|
||
'annual_new_revenue_completion_rate': annual_new_revenue_completion_rate,
|
||
'annual_existing_revenue': annual_existing_revenue,
|
||
'annual_existing_revenue_completion_rate': annual_existing_revenue_completion_rate,
|
||
'annual_operating_costs': annual_operating_costs,
|
||
'annual_operating_costs_utilization_rate': annual_operating_costs_utilization_rate,
|
||
'annual_expenses': annual_expenses,
|
||
'annual_expenses_utilization_rate': annual_expenses_utilization_rate,
|
||
'operating_profit': operating_profit
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentAnnualPerformance',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_departments_for_year(cls, year):
|
||
cls.calculate_and_update_for_year(year)
|
||
|
||
|
||
# 2.收入情况
|
||
class DepartmentMonthlyIncome(models.Model):
|
||
"""
|
||
当月收入 = 价税合计金额按一级部门和年月筛选完后的累计值 【项目台账-价税合计金额】
|
||
月收入目标 = 收入总目标/12 【集团经营目标-收入总目标】
|
||
月目标完成率 = 当月收入 / 月目标收入
|
||
当月新增收入 = 价税合计金额按年月、一级部门、性质筛选完后的累计值 【项目台账-价税合计金额】
|
||
月新增收入目标 = 新增收入目标 / 12 【集团经营目标-新增收入目标】
|
||
月新增收入完成率 = 当月新增收入 / 月新增收入目标
|
||
当月存量收入 = 当月存量收入按年月、一级部门、性质筛选完后的累计值 【项目台账-价税合计金额】
|
||
月存量收入目标 = 新增收入目标 / 12 【集团经营目标-新增收入目标】
|
||
月存量收入完成率 = 当月存量收入 / 月存量收入目标
|
||
年累计收入 = 价税合计金额按一级部门和当前筛选完后的累计值 【项目台账-价税合计金额】
|
||
累计目标完成率(年累计收入/ 收入总目标)【集团经营目标-收入总目标】
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
year_month = models.CharField(max_length=7, verbose_name="年月", help_text="格式为'YYYY-MM',表示统计数据的年月")
|
||
current_month_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="当月收入", help_text="当月总收入,以万元为单位")
|
||
monthly_income_target = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="月收入目标", help_text="当月收入目标,以万元为单位")
|
||
monthly_target_completion_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="月目标完成率", help_text="当月收入与月收入目标的完成比率")
|
||
current_month_new_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="当月新增收入", help_text="当月新增的收入,以万元为单位")
|
||
monthly_new_income_target = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="月新增收入目标", help_text="当月新增收入的目标,以万元为单位")
|
||
monthly_new_income_completion_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="月新增收入完成率", help_text="当月新增收入与月新增收入目标的完成比率")
|
||
current_month_existing_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="当月存量收入", help_text="当月存量收入,以万元为单位")
|
||
monthly_existing_income_target = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="月存量收入目标", help_text="当月存量收入的目标,以万元为单位")
|
||
monthly_existing_income_completion_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="月存量收入完成率", help_text="当月存量收入与月存量收入目标的完成比率")
|
||
annual_accumulated_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年累计收入", help_text="年度累计收入,以万元为单位")
|
||
accumulated_target_completion_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="累计目标完成率", help_text="年度累计收入与年度总收入目标的完成比率")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门收入情况"
|
||
verbose_name_plural = "业务部门收入情况"
|
||
db_table_comment = '存储业务部门收入情况数据,包括一级部门、年月、当月收入及其目标和完成率、新增收入及其目标和完成率、存量收入及其目标和完成率、年累计收入及其目标完成率等'
|
||
|
||
def __str__(self):
|
||
return f"{self.year_month} 年 {self.primary_department} 的收入情况"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'year_month': '年月',
|
||
'current_month_income': '当月收入',
|
||
'monthly_income_target': '月收入目标',
|
||
'monthly_target_completion_rate': '月目标完成率',
|
||
'current_month_new_income': '当月新增收入',
|
||
'monthly_new_income_target': '月新增收入目标',
|
||
'monthly_new_income_completion_rate': '月新增收入完成率',
|
||
'current_month_existing_income': '当月存量收入',
|
||
'monthly_existing_income_target': '月存量收入目标',
|
||
'monthly_existing_income_completion_rate': '月存量收入完成率',
|
||
'annual_accumulated_income': '年累计收入',
|
||
'accumulated_target_completion_rate': '累计目标完成率',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_for_month(year_month):
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
year, month = map(int, year_month.split('-'))
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 当月收入
|
||
current_month_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 月收入目标
|
||
annual_revenue_target = GroupBusinessTarget.objects.filter(
|
||
primary_department=primary_department,
|
||
year=year
|
||
).aggregate(total=Sum('total_revenue_target'))['total'] or Decimal('1')
|
||
monthly_income_target = annual_revenue_target / Decimal('12')
|
||
|
||
# 月目标完成率
|
||
monthly_target_completion_rate = current_month_income / monthly_income_target
|
||
|
||
# 当月新增收入
|
||
current_month_new_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month,
|
||
project_nature="新增"
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 月新增收入目标
|
||
annual_new_revenue_target = GroupBusinessTarget.objects.filter(
|
||
primary_department=primary_department,
|
||
year=year
|
||
).aggregate(total=Sum('new_revenue_target'))['total'] or Decimal('1')
|
||
monthly_new_income_target = annual_new_revenue_target / Decimal('12')
|
||
|
||
# 月新增收入完成率
|
||
monthly_new_income_completion_rate = current_month_new_income / monthly_new_income_target
|
||
|
||
# 当月存量收入
|
||
current_month_existing_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month,
|
||
project_nature="存量"
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 月存量收入目标
|
||
monthly_existing_income_target = annual_new_revenue_target / Decimal('12')
|
||
|
||
# 月存量收入完成率
|
||
monthly_existing_income_completion_rate = current_month_existing_income / monthly_existing_income_target
|
||
|
||
# 年累计收入
|
||
annual_accumulated_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 累计目标完成率
|
||
accumulated_target_completion_rate = annual_accumulated_income / annual_revenue_target
|
||
|
||
# 更新或创建模型实例
|
||
income, created = DepartmentMonthlyIncome.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
year_month=year_month,
|
||
defaults={
|
||
'current_month_income': current_month_income,
|
||
'monthly_income_target': monthly_income_target,
|
||
'monthly_target_completion_rate': monthly_target_completion_rate,
|
||
'current_month_new_income': current_month_new_income,
|
||
'monthly_new_income_target': monthly_new_income_target,
|
||
'monthly_new_income_completion_rate': monthly_new_income_completion_rate,
|
||
'current_month_existing_income': current_month_existing_income,
|
||
'monthly_existing_income_target': monthly_existing_income_target,
|
||
'monthly_existing_income_completion_rate': monthly_existing_income_completion_rate,
|
||
'annual_accumulated_income': annual_accumulated_income,
|
||
'accumulated_target_completion_rate': accumulated_target_completion_rate,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentMonthlyIncome',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_departments_for_month(cls, year_month):
|
||
cls.calculate_and_update_for_month(year_month)
|
||
|
||
|
||
# 3.成本情况
|
||
class DepartmentMonthlyCost(models.Model):
|
||
"""
|
||
当月成本 = 价税合计金额 - 应收净收入 【项目台账-价税合计金额, 项目台账- 应收净收入】
|
||
月成本限额 = 成本限额 / 12 【集团经营目标-成本限额】
|
||
月成本占用率 = 当月成本 / 月成本限额
|
||
年累计成本 = 当年成本累计值
|
||
累计成本占用率 = 年累计成本 / 成本限额 【集团经营目标-成本限额】
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
year_month = models.CharField(max_length=7, verbose_name="年月", help_text="格式为'YYYY-MM',表示统计数据的年月")
|
||
current_month_cost = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="当月成本(万元)", help_text="当月成本总额,以万元为单位")
|
||
monthly_cost_limit = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="月成本限额(万元)", help_text="每月的成本限额,以万元为单位")
|
||
monthly_cost_utilization_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="月成本占用率", help_text="当月成本占用月成本限额的比率,以百分比表示")
|
||
annual_accumulated_cost = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年累计成本(万元)", help_text="年度累计成本总额,以万元为单位")
|
||
accumulated_cost_utilization_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="累计成本占用率", help_text="年累计成本占用年度成本限额的比率,以百分比表示")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门成本情况"
|
||
verbose_name_plural = "业务部门成本情况"
|
||
db_table_comment = '存储业务部门成本情况数据,包括一级部门、年月、当月成本及其限额和占用率、年累计成本及其占用率等'
|
||
|
||
def __str__(self):
|
||
return f"{self.year_month} 年 {self.primary_department} 的成本情况"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'year_month': '年月',
|
||
'current_month_cost': '当月成本(万元)',
|
||
'monthly_cost_limit': '月成本限额(万元)',
|
||
'monthly_cost_utilization_rate': '月成本占用率',
|
||
'annual_accumulated_cost': '年累计成本(万元)',
|
||
'accumulated_cost_utilization_rate': '累计成本占用率',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_for_month(year_month):
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
year, month = map(int, year_month.split('-'))
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 当月成本
|
||
total_amount_including_tax = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
net_receivable_amount = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month
|
||
).aggregate(total=Sum('receivable_net_income'))['total'] or Decimal('0')
|
||
|
||
current_month_cost = total_amount_including_tax - net_receivable_amount
|
||
|
||
# 月成本限额
|
||
annual_cost_limit = GroupBusinessTarget.objects.filter(
|
||
primary_department=primary_department,
|
||
year=year
|
||
).aggregate(total=Sum('cost_limit'))['total'] or Decimal('1')
|
||
monthly_cost_limit = annual_cost_limit / Decimal('12')
|
||
|
||
# 月成本占用率
|
||
monthly_cost_utilization_rate = current_month_cost / monthly_cost_limit
|
||
|
||
# 年累计成本
|
||
annual_accumulated_cost = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0') - ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('receivable_net_income'))['total'] or Decimal('0')
|
||
|
||
# 累计成本占用率
|
||
accumulated_cost_utilization_rate = annual_accumulated_cost / annual_cost_limit
|
||
|
||
# 更新或创建模型实例
|
||
cost, created = DepartmentMonthlyCost.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
year_month=year_month,
|
||
defaults={
|
||
'current_month_cost': current_month_cost,
|
||
'monthly_cost_limit': monthly_cost_limit,
|
||
'monthly_cost_utilization_rate': monthly_cost_utilization_rate,
|
||
'annual_accumulated_cost': annual_accumulated_cost,
|
||
'accumulated_cost_utilization_rate': accumulated_cost_utilization_rate,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentMonthlyCost',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_departments_for_month(cls, year_month):
|
||
cls.calculate_and_update_for_month(year_month)
|
||
|
||
|
||
# 4.费用情况
|
||
class DepartmentExpense(models.Model):
|
||
"""
|
||
费用情况
|
||
年月、费用类型、费用明细、费用限额(集团年度预算表-按一级部门年份费用类型费用明细筛选后取金额)
|
||
已报销额度(报销明细表-费用金额按时间、类型、明细筛选后汇总,算当年总额)
|
||
可用额度(=费用限额-已报销额度)
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
year_month = models.CharField(max_length=7, verbose_name="年月", help_text="格式为'YYYY-MM',表示统计数据的年月")
|
||
expense_type = models.CharField(max_length=255, verbose_name="费用类型")
|
||
expense_detail = models.CharField(max_length=255, verbose_name="费用明细")
|
||
expense_limit = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="费用限额(元)")
|
||
reimbursed_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="已报销额度(元)")
|
||
available_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="可用额度(元)")
|
||
|
||
class Meta:
|
||
verbose_name = "费用情况"
|
||
verbose_name_plural = "费用情况"
|
||
db_table_comment = '存储业务部门费用情况数据,包括一级部门、年月、费用类型、费用明细、费用限额、已报销额度、可用额度等'
|
||
|
||
def __str__(self):
|
||
return f"{self.year_month} 年 {self.primary_department} 的费用情况"
|
||
|
||
@staticmethod
|
||
def calculate_and_update_for_month(year_month):
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
year, month = map(int, year_month.split('-'))
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 从集团年度预算表获取费用类型和费用明细
|
||
budget_entries = GroupAnnualBudget.objects.filter(
|
||
primary_department=primary_department,
|
||
year=year
|
||
)
|
||
|
||
for entry in budget_entries:
|
||
expense_type = entry.expense_type.name
|
||
expense_detail = entry.expense_detail.name
|
||
|
||
# 费用限额
|
||
expense_limit = entry.amount
|
||
|
||
# 已报销额度
|
||
reimbursed_amount = ReimbursementDetail.objects.filter(
|
||
primary_department=primary_department,
|
||
year_month__year=year,
|
||
expense_type__name=expense_type,
|
||
expense_detail__name=expense_detail
|
||
).aggregate(total=Sum('amount'))['total'] or Decimal('0')
|
||
|
||
# 可用额度
|
||
available_amount = expense_limit - reimbursed_amount
|
||
|
||
# 更新或创建模型实例
|
||
expense, created = DepartmentExpense.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
year_month=year_month,
|
||
expense_type=expense_type,
|
||
expense_detail=expense_detail,
|
||
defaults={
|
||
'expense_limit': expense_limit,
|
||
'reimbursed_amount': reimbursed_amount,
|
||
'available_amount': available_amount,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentExpense',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_departments_for_month(cls, year_month):
|
||
cls.calculate_and_update_for_month(year_month)
|
||
|
||
|
||
# 5.利润情况
|
||
class DepartmentMonthlyProfit(models.Model):
|
||
"""
|
||
费用情况
|
||
年月、营业利润(万元)、年累计营业利润(万元)
|
||
营业利润(万元)=【项目台账-应收净收入】应收净收入按一级部门、年月筛选-【报销明细表-费用金额】费用金额按一级部门、年月筛选累计-【人工费用明细-全勤奖、午餐津贴、其他货币性福利、实发工资、公司承担社保、公司承担公积金】(全勤奖+午餐津贴+其他货币性福利+实发工资+公司承担社保+公司承担公积金)按一级部门、年月筛选累计-【开票记录-不含税金额】税额按一级部门、年月筛选累计*1.12
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
year_month = models.CharField(max_length=7, verbose_name="年月", help_text="格式为'YYYY-MM',表示统计数据的年月")
|
||
operating_profit = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="营业利润", help_text="当月的营业利润,计算方式如描述,以万元为单位")
|
||
annual_operating_profit = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年累计营业利润", help_text="当年的累计营业利润,以万元为单位")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门利润情况"
|
||
verbose_name_plural = "业务部门利润情况"
|
||
db_table_comment = '存储业务部门利润情况数据,包括一级部门、年月、当月营业利润和年累计营业利润等'
|
||
|
||
def __str__(self):
|
||
return f"{self.year_month} 年 {self.primary_department} 的利润情况"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'year_month': '年月',
|
||
'operating_profit': '营业利润',
|
||
'annual_operating_profit': '年累计营业利润',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_for_month(year_month):
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
year, month = map(int, year_month.split('-'))
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 应收净收入
|
||
net_receivable_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month
|
||
).aggregate(total=Sum('receivable_net_income'))['total'] or Decimal('0')
|
||
|
||
# 费用金额
|
||
reimbursed_amount = ReimbursementDetail.objects.filter(
|
||
primary_department=primary_department,
|
||
year_month__year=year,
|
||
year_month__month=month
|
||
).aggregate(total=Sum('amount'))['total'] or Decimal('0')
|
||
|
||
# 人工费用
|
||
labor_cost = LaborCostDetail.objects.filter(
|
||
primary_department=primary_department,
|
||
year_month__year=year,
|
||
year_month__month=month
|
||
).aggregate(
|
||
attendance_reward=Sum('attendance_reward'),
|
||
lunch_allowance=Sum('lunch_allowance'),
|
||
other_monetary_benefits=Sum('other_monetary_benefits'),
|
||
net_salary=Sum('net_salary'),
|
||
employer_social_security=Sum('employer_social_security'),
|
||
employer_housing_fund=Sum('employer_housing_fund')
|
||
)
|
||
|
||
labor_cost_total = sum(value or Decimal('0') for value in labor_cost.values())
|
||
|
||
# 开票税金
|
||
tax_amount = InvoiceRecord.objects.filter(
|
||
primary_department=primary_department,
|
||
invoice_date__year=year,
|
||
invoice_date__month=month
|
||
).aggregate(total=Sum('amount_excluding_tax'))['total'] or Decimal('0')
|
||
|
||
# 营业利润
|
||
operating_profit = net_receivable_income - reimbursed_amount - labor_cost_total - (tax_amount * Decimal('1.12'))
|
||
|
||
# 年累计营业利润
|
||
annual_operating_profit = DepartmentMonthlyProfit.objects.filter(
|
||
primary_department=primary_department,
|
||
year_month__year=year
|
||
).aggregate(total=Sum('operating_profit'))['total'] or Decimal('0')
|
||
|
||
annual_operating_profit += operating_profit
|
||
|
||
# 更新或创建模型实例
|
||
profit, created = DepartmentMonthlyProfit.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
year_month=year_month,
|
||
defaults={
|
||
'operating_profit': operating_profit,
|
||
'annual_operating_profit': annual_operating_profit,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentMonthlyProfit',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_departments_for_month(cls, year_month):
|
||
cls.calculate_and_update_for_month(year_month)
|
||
|
||
|
||
# 6.项目进度
|
||
class DepartmentProjectProgress(models.Model):
|
||
"""
|
||
所有均摘自表28项目台账中对应的信息
|
||
项目类型根据一级部门不同有所区别
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
project_name = models.CharField(max_length=255, verbose_name="项目名称", help_text="项目的名称")
|
||
project_type = models.CharField(max_length=255, verbose_name="项目类型", help_text="项目的类型,如开发、研究等")
|
||
project_manager = models.CharField(max_length=255, verbose_name="负责人", help_text="负责项目的人员")
|
||
project_status = models.CharField(max_length=255, verbose_name="项目状态", help_text="项目当前的状态,如进行中、已完成、暂停等")
|
||
project_progress = models.CharField(max_length=255, verbose_name="项目进度", help_text="项目的完成进度,通常以百分比表示")
|
||
project_nature = models.CharField(max_length=255, verbose_name="项目性质", help_text="项目的性质,如内部项目、外包项目等")
|
||
contract_date = models.DateField(verbose_name="签约时间", help_text="项目签约的日期")
|
||
target_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="标的金额(元)", help_text="项目的标的金额,以元为单位")
|
||
contract_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="合同费率", help_text="项目合同中约定的费率")
|
||
revenue = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="收入(元)", help_text="项目实际产生的收入,以元为单位")
|
||
cost_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="成本费率", help_text="项目成本的费率")
|
||
cost = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="成本(元)", help_text="项目的实际成本,以元为单位")
|
||
net_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="净收入(元)", help_text="项目的净收入,计算为收入减去成本")
|
||
transaction_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="成交金额(元)", help_text="项目的成交金额,以元为单位")
|
||
total_tax_inclusive_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="价税合计金额(元)", help_text="项目的价税合计金额,以元为单位")
|
||
payment_received = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="回款金额(元)", help_text="项目实际已回款的金额,以元为单位")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门项目进度"
|
||
verbose_name_plural = "业务部门项目进度"
|
||
db_table_comment = '存储业务部门项目进度数据,包括一级部门、项目名称、项目类型、负责人、项目状态、项目进度、项目性质、签约时间、标的金额、合同费率、收入、成本费率、成本、净收入、成交金额、价税合计金额和回款金额等'
|
||
|
||
def __str__(self):
|
||
return f"{self.primary_department} 部门的项目 {self.project_name} 进度"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'project_name': '项目名称',
|
||
'project_type': '项目类型',
|
||
'project_manager': '负责人',
|
||
'project_status': '项目状态',
|
||
'project_progress': '项目进度',
|
||
'project_nature': '项目性质',
|
||
'contract_date': '签约时间',
|
||
'target_amount': '标的金额(元)',
|
||
'contract_rate': '合同费率',
|
||
'revenue': '收入(元)',
|
||
'cost_rate': '成本费率',
|
||
'cost': '成本(元)',
|
||
'net_income': '净收入(元)',
|
||
'transaction_amount': '成交金额(元)',
|
||
'total_tax_inclusive_amount': '价税合计金额(元)',
|
||
'payment_received': '回款金额(元)',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_progress():
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 从项目台账中获取项目进度相关数据
|
||
projects = ProjectLedger.objects.filter(primary_department=primary_department)
|
||
|
||
for project in projects:
|
||
project_name = project.project_name
|
||
project_type = project.project_type
|
||
project_manager = project.project_manager
|
||
project_status = project.project_status
|
||
project_progress = project.project_progress
|
||
project_nature = project.project_nature
|
||
contract_date = project.contract_date
|
||
target_amount = project.target_amount
|
||
contract_rate = project.contract_rate
|
||
revenue = project.revenue
|
||
cost_rate = project.cost_rate
|
||
cost = project.cost
|
||
net_income = revenue - cost
|
||
transaction_amount = project.transaction_amount
|
||
total_tax_inclusive_amount = project.total_tax_inclusive_amount
|
||
payment_received = project.payment_received
|
||
|
||
# 更新或创建模型实例
|
||
progress, created = DepartmentProjectProgress.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
project_name=project_name,
|
||
defaults={
|
||
'project_type': project_type,
|
||
'project_manager': project_manager,
|
||
'project_status': project_status,
|
||
'project_progress': project_progress,
|
||
'project_nature': project_nature,
|
||
'contract_date': contract_date,
|
||
'target_amount': target_amount,
|
||
'contract_rate': contract_rate,
|
||
'revenue': revenue,
|
||
'cost_rate': cost_rate,
|
||
'cost': cost,
|
||
'net_income': net_income,
|
||
'transaction_amount': transaction_amount,
|
||
'total_tax_inclusive_amount': total_tax_inclusive_amount,
|
||
'payment_received': payment_received,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentProjectProgress',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_projects_progress(cls):
|
||
cls.calculate_and_update_progress()
|
||
|
||
|
||
# 7.项目结算情况
|
||
class DepartmentProjectSettlement(models.Model):
|
||
"""
|
||
项目结算情况
|
||
项目名称、营业收入、营业成本、税金及附加、营业利润、公司留存、项目提成、项目公积金
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
project_name = models.CharField(max_length=255, verbose_name="项目名称", help_text="项目的名称")
|
||
revenue = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="营业收入(元)", help_text="项目的总营业收入")
|
||
operating_costs = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="营业成本(元)", help_text="项目的总营业成本")
|
||
taxes_and_surcharges = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="税金及附加(元)", help_text="项目相关的税金及附加费用,根据公式计算")
|
||
operating_profit = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="营业利润(元)", help_text="项目的营业利润,计算为营业收入减去营业成本和税金及附加")
|
||
company_retention = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="公司留存(元)", help_text="项目为公司留存的部分收益")
|
||
project_commission = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="项目提成(元)", help_text="项目团队的提成金额")
|
||
project_provision_fund = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="项目公积金(元)", help_text="从营业利润中提取的项目公积金")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门项目结算情况"
|
||
verbose_name_plural = "业务部门项目结算情况"
|
||
db_table_comment = '存储业务部门项目结算情况数据,包括一级部门、项目名称、营业收入、营业成本、税金及附加、营业利润、公司留存、项目提成和项目公积金等'
|
||
|
||
def __str__(self):
|
||
return f"{self.primary_department} 部门的项目 {self.project_name} 结算情况"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'project_name': '项目名称',
|
||
'revenue': '营业收入(元)',
|
||
'operating_costs': '营业成本(元)',
|
||
'taxes_and_surcharges': '税金及附加(元)',
|
||
'operating_profit': '营业利润(元)',
|
||
'company_retention': '公司留存(元)',
|
||
'project_commission': '项目提成(元)',
|
||
'project_provision_fund': '项目公积金(元)',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_settlement():
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 从项目台账中获取项目结算相关数据
|
||
projects = ProjectLedger.objects.filter(primary_department=primary_department)
|
||
|
||
for project in projects:
|
||
project_name = project.project_name
|
||
|
||
# 营业收入
|
||
revenue = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
project_name=project_name
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 营业成本
|
||
net_receivable_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
project_name=project_name
|
||
).aggregate(total=Sum('receivable_net_income'))['total'] or Decimal('0')
|
||
operating_costs = revenue - net_receivable_income
|
||
|
||
# 税金及附加
|
||
tax_amount = InvoiceRecord.objects.filter(
|
||
primary_department=primary_department,
|
||
project_name=project
|
||
).aggregate(total=Sum('tax_amount'))['total'] or Decimal('0')
|
||
taxes_and_surcharges = tax_amount * Decimal('1.12')
|
||
|
||
# 营业利润
|
||
operating_profit = revenue - operating_costs - taxes_and_surcharges
|
||
|
||
# 公司留存和项目提成
|
||
project_commission_record = ProjectCommission.objects.filter(
|
||
primary_department=primary_department,
|
||
project_name=project
|
||
).first()
|
||
company_retention = project_commission_record.company_retained if project_commission_record else Decimal('0')
|
||
project_commission = project_commission_record.total_commission if project_commission_record else Decimal('0')
|
||
|
||
# 项目公积金
|
||
project_provision_fund = operating_profit - company_retention - project_commission
|
||
|
||
# 更新或创建模型实例
|
||
settlement, created = DepartmentProjectSettlement.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
project_name=project_name,
|
||
defaults={
|
||
'revenue': revenue,
|
||
'operating_costs': operating_costs,
|
||
'taxes_and_surcharges': taxes_and_surcharges,
|
||
'operating_profit': operating_profit,
|
||
'company_retention': company_retention,
|
||
'project_commission': project_commission,
|
||
'project_provision_fund': project_provision_fund,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentProjectSettlement',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_projects_settlement(cls):
|
||
cls.calculate_and_update_settlement()
|
||
|
||
|
||
# 8.项目回款情况
|
||
class DepartmentProjectPayment(models.Model):
|
||
"""
|
||
项目回款情况
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
project_name = models.CharField(max_length=255, verbose_name="项目名称", help_text="项目的名称")
|
||
project_type = models.CharField(max_length=255, verbose_name="项目类型", help_text="项目的类型")
|
||
project_manager = models.CharField(max_length=255, verbose_name="负责人", help_text="负责项目的人员")
|
||
total_tax_inclusive_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="价税合计金额(元)", help_text="项目的价税合计金额,累计数")
|
||
payment_received = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="回款金额(元)", help_text="项目的回款金额,累计数")
|
||
outstanding_payment_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="待回款金额(元)", help_text="计算得出的待回款金额,价税合计金额减去回款金额")
|
||
receivable_net_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="应收净收入(元)", help_text="应收的净收入,累计数")
|
||
actual_net_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="实收净收入(元)", help_text="实际收到的净收入,累计数")
|
||
outstanding_net_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="待收净收入(元)", help_text="待收净收入,计算为应收净收入减去实收净收入")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门项目回款情况"
|
||
verbose_name_plural = "业务部门项目回款情况"
|
||
db_table_comment = '存储业务部门项目回款情况,包括一级部门、项目名称、项目类型、负责人、价税合计金额、回款金额、待回款金额、应收净收入、实收净收入和待收净收入等'
|
||
|
||
def __str__(self):
|
||
return f"Department Project Payment for {self.project_name} in {self.primary_department}"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'project_name': '项目名称',
|
||
'project_type': '项目类型',
|
||
'project_manager': '负责人',
|
||
'total_tax_inclusive_amount': '价税合计金额(元)',
|
||
'payment_received': '回款金额(元)',
|
||
'outstanding_payment_amount': '待回款金额(元)',
|
||
'receivable_net_income': '应收净收入(元)',
|
||
'actual_net_income': '实收净收入(元)',
|
||
'outstanding_net_income': '待收净收入(元)',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_payments():
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 从项目台账中获取项目回款相关数据
|
||
projects = ProjectLedger.objects.filter(primary_department=primary_department)
|
||
|
||
for project in projects:
|
||
project_name = project.project_name
|
||
project_type = project.project_type
|
||
project_manager = project.project_manager
|
||
|
||
# 获取价税合计金额
|
||
total_tax_inclusive_amount = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
project_name=project_name
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 获取回款金额
|
||
payment_received = RepaymentRecord.objects.filter(
|
||
primary_department=primary_department,
|
||
project_name=project
|
||
).aggregate(total=Sum('repayment_amount'))['total'] or Decimal('0')
|
||
|
||
# 计算待回款金额
|
||
outstanding_payment_amount = total_tax_inclusive_amount - payment_received
|
||
|
||
# 获取应收净收入
|
||
receivable_net_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
project_name=project_name
|
||
).aggregate(total=Sum('receivable_net_income'))['total'] or Decimal('0')
|
||
|
||
# 获取实收净收入
|
||
actual_net_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
project_name=project_name
|
||
).aggregate(total=Sum('actual_net_income'))['total'] or Decimal('0')
|
||
|
||
# 计算待收净收入
|
||
outstanding_net_income = receivable_net_income - actual_net_income
|
||
|
||
# 更新或创建模型实例
|
||
payment, created = DepartmentProjectPayment.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
project_name=project_name,
|
||
defaults={
|
||
'project_type': project_type,
|
||
'project_manager': project_manager,
|
||
'total_tax_inclusive_amount': total_tax_inclusive_amount,
|
||
'payment_received': payment_received,
|
||
'outstanding_payment_amount': outstanding_payment_amount,
|
||
'receivable_net_income': receivable_net_income,
|
||
'actual_net_income': actual_net_income,
|
||
'outstanding_net_income': outstanding_net_income,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentProjectPayment',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_projects_payments(cls):
|
||
cls.calculate_and_update_payments()
|
||
|
||
|
||
# 9.收入结构
|
||
class DepartmentRevenueStructure(models.Model):
|
||
"""
|
||
业务部门收入结构
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
year_month = models.CharField(max_length=7, verbose_name="年月", help_text="格式为'YYYY-MM',表示统计数据的年月")
|
||
project_type = models.CharField(max_length=255, verbose_name="项目类型", help_text="项目的分类类型")
|
||
total_tax_inclusive_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="价税合计金额", help_text="当月按项目类型的价税合计金额")
|
||
percentage = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="占比", help_text="该项目类型的价税合计金额占当月总收入的百分比")
|
||
cumulative_tax_inclusive_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="累计价税合计金额", help_text="从年初到当前月的累计价税合计金额")
|
||
cumulative_percentage = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="累计占比", help_text="该项目类型的累计价税合计金额占当年1月至当月的")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门收入结构"
|
||
verbose_name_plural = "业务部门收入结构"
|
||
db_table_comment = '存储业务部门收入结构数据,包括一级部门、年月、项目类型、价税合计金额、占比、累计价税合计金额和累计占比等'
|
||
|
||
def __str__(self):
|
||
return f"Department Revenue Structure for {self.primary_department} in {self.year_month}"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'year_month': '年月',
|
||
'project_type': '项目类型',
|
||
'total_tax_inclusive_amount': '价税合计金额',
|
||
'percentage': '占比',
|
||
'cumulative_tax_inclusive_amount': '累计价税合计金额',
|
||
'cumulative_percentage': '累计占比',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_revenue_structure(year_month):
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
year, month = map(int, year_month.split('-'))
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 获取当月总收入
|
||
total_revenue = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 获取累计总收入
|
||
cumulative_revenue = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
# 获取各项目类型的收入
|
||
project_types = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month
|
||
).values('project_type').annotate(total_amount=Sum('total_amount_including_tax'))
|
||
|
||
for project in project_types:
|
||
project_type = project['project_type']
|
||
total_tax_inclusive_amount = project['total_amount']
|
||
percentage = (total_tax_inclusive_amount / total_revenue * 100) if total_revenue > 0 else 0
|
||
|
||
cumulative_tax_inclusive_amount = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
project_type=project_type,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('total_amount_including_tax'))['total'] or Decimal('0')
|
||
|
||
cumulative_percentage = (cumulative_tax_inclusive_amount / cumulative_revenue * 100) if cumulative_revenue > 0 else 0
|
||
|
||
# 更新或创建模型实例
|
||
revenue_structure, created = DepartmentRevenueStructure.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
year_month=year_month,
|
||
project_type=project_type,
|
||
defaults={
|
||
'total_tax_inclusive_amount': total_tax_inclusive_amount,
|
||
'percentage': percentage,
|
||
'cumulative_tax_inclusive_amount': cumulative_tax_inclusive_amount,
|
||
'cumulative_percentage': cumulative_percentage,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentRevenueStructure',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_departments_revenue_structure(cls, year_month):
|
||
cls.calculate_and_update_revenue_structure(year_month)
|
||
|
||
|
||
# 10.利润结果
|
||
class DepartmentProfitStructure(models.Model):
|
||
"""
|
||
业务部门利润结构
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
year_month = models.CharField(max_length=7, verbose_name="年月", help_text="格式为'YYYY-MM',表示统计数据的年月")
|
||
project_type = models.CharField(max_length=255, verbose_name="项目类型", help_text="项目的分类类型")
|
||
net_receivable_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="应收净收入(元)", help_text="当月按项目类型的应收净收入")
|
||
percentage = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="占比", help_text="该项目类型的应收净收入占当月总利润的百分比")
|
||
cumulative_net_receivable_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="累计应收净收入(元)", help_text="从年初到当前月的累计应收净收入")
|
||
cumulative_percentage = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="累计占比", help_text="该项目类型的累计应收净收入占当年1月至当月的")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门利润结构"
|
||
verbose_name_plural = "业务部门利润结构"
|
||
db_table_comment = '存储业务部门利润结构数据,包括一级部门、年月、项目类型、应收净收入、占比、累计应收净收入和累计占比等'
|
||
|
||
def __str__(self):
|
||
return f"Department Profit Structure for {self.primary_department} in {self.year_month}"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'year_month': '年月',
|
||
'project_type': '项目类型',
|
||
'net_receivable_income': '应收净收入(元)',
|
||
'percentage': '占比',
|
||
'cumulative_net_receivable_income': '累计应收净收入(元)',
|
||
'cumulative_percentage': '累计占比',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_profit_structure(year_month):
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
year, month = map(int, year_month.split('-'))
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 获取当月总利润
|
||
total_profit = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month
|
||
).aggregate(total=Sum('receivable_net_income'))['total'] or Decimal('0')
|
||
|
||
# 获取累计总利润
|
||
cumulative_profit = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('receivable_net_income'))['total'] or Decimal('0')
|
||
|
||
# 获取各项目类型的利润
|
||
project_types = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
start_date__year=year,
|
||
start_date__month=month
|
||
).values('project_type').annotate(total_amount=Sum('receivable_net_income'))
|
||
|
||
for project in project_types:
|
||
project_type = project['project_type']
|
||
net_receivable_income = project['total_amount']
|
||
percentage = (net_receivable_income / total_profit * 100) if total_profit > 0 else 0
|
||
|
||
cumulative_net_receivable_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
project_type=project_type,
|
||
start_date__year=year
|
||
).aggregate(total=Sum('receivable_net_income'))['total'] or Decimal('0')
|
||
|
||
cumulative_percentage = (cumulative_net_receivable_income / cumulative_profit * 100) if cumulative_profit > 0 else 0
|
||
|
||
# 更新或创建模型实例
|
||
profit_structure, created = DepartmentProfitStructure.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
year_month=year_month,
|
||
project_type=project_type,
|
||
defaults={
|
||
'net_receivable_income': net_receivable_income,
|
||
'percentage': percentage,
|
||
'cumulative_net_receivable_income': cumulative_net_receivable_income,
|
||
'cumulative_percentage': cumulative_percentage,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentProfitStructure',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_departments_profit_structure(cls, year_month):
|
||
cls.calculate_and_update_profit_structure(year_month)
|
||
|
||
|
||
# 项目经理收入完成及提成情况
|
||
class DepartmentProjectManagerIncomeCommission(models.Model):
|
||
"""
|
||
项目经理收入完成及提成情况
|
||
"""
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
name = models.CharField(max_length=255, verbose_name="姓名", help_text="项目经理的姓名")
|
||
year_month = models.CharField(max_length=7, verbose_name="年月", help_text="格式为'YYYY-MM',表示统计数据的年月")
|
||
current_month_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="当月收入", help_text="当月销售收入,按月累计,单位:元")
|
||
monthly_income_target = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="月收入目标", help_text="当月收入目标,单位:元")
|
||
monthly_target_completion_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="月目标完成率", help_text="当月收入与月收入目标的比率")
|
||
annual_accumulated_income = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年累计收入", help_text="年度累计销售收入,单位:元")
|
||
annual_target_completion_rate = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="累计目标完成率", help_text="项目经理年累计收入与部门收入目标比率")
|
||
current_month_commission = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="当月提成", help_text="当月已发放的提成金额,单位:元")
|
||
current_month_accrued_commission = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="当月计提提成", help_text="当月计提的提成金额,单位:元")
|
||
annual_accumulated_commission = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年累计提成", help_text="年度累计已发放的提成金额,单位:元")
|
||
annual_accumulated_accrued_commission = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="年累计计提提成", help_text="年度累计计提的提成金额,单位:元")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门项目经理收入完成及提成情况"
|
||
verbose_name_plural = "业务部门项目经理收入完成及提成情况"
|
||
db_table_comment = '存储业务部门项目经理收入完成及提成情况数据,包括一级部门、姓名、年月、当月收入、月收入目标、月目标完成率、年累计收入、累计目标完成率、当月提成、当月计提提成、年累计提成和年累计计提提成等'
|
||
|
||
def __str__(self):
|
||
return f"Income Commission for {self.name} in {self.year_month}"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'name': '姓名',
|
||
'year_month': '年月',
|
||
'current_month_income': '当月收入',
|
||
'monthly_income_target': '月收入目标',
|
||
'monthly_target_completion_rate': '月目标完成率',
|
||
'annual_accumulated_income': '年累计收入',
|
||
'annual_target_completion_rate': '累计目标完成率',
|
||
'current_month_commission': '当月提成',
|
||
'current_month_accrued_commission': '当月计提提成',
|
||
'annual_accumulated_commission': '年累计提成',
|
||
'annual_accumulated_accrued_commission': '年累计计提提成',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_commissions(year_month):
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
year, month = map(int, year_month.split('-'))
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 获取部门经理
|
||
managers = EmployeeInformation.objects.filter(
|
||
primary_department=primary_department,
|
||
position='项目经理',
|
||
status='在职'
|
||
)
|
||
|
||
for manager in managers:
|
||
name = manager.name
|
||
|
||
# 当月收入
|
||
current_month_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
project_manager=name,
|
||
start_date__year=year,
|
||
start_date__month=month
|
||
).aggregate(total=Sum(F('total_amount_including_tax') * F('contribution_rate')))['total'] or Decimal('0')
|
||
|
||
# 月收入目标
|
||
income_target = EmployeePerformanceTarget.objects.filter(
|
||
employee=name,
|
||
year=year
|
||
).aggregate(target=Sum('income_target'))['target'] or Decimal('0')
|
||
monthly_income_target = income_target / 12
|
||
|
||
# 月目标完成率
|
||
monthly_target_completion_rate = (current_month_income / monthly_income_target) * 100 if monthly_income_target > 0 else 0
|
||
|
||
# 年累计收入
|
||
annual_accumulated_income = ProjectLedger.objects.filter(
|
||
primary_department=primary_department,
|
||
project_manager=name,
|
||
start_date__year=year
|
||
).aggregate(total=Sum(F('total_amount_including_tax') * F('contribution_rate')))['total'] or Decimal('0')
|
||
|
||
# 累计目标完成率
|
||
annual_target_completion_rate = (annual_accumulated_income * 10000 / income_target) * 100 if income_target > 0 else 0
|
||
|
||
# 当月提成
|
||
current_month_commission = EmployeeCommissionDetail.objects.filter(
|
||
primary_department=primary_department,
|
||
employee=name,
|
||
year_month__year=year,
|
||
year_month__month=month
|
||
).aggregate(total=Sum('amount_paid'))['total'] or Decimal('0')
|
||
|
||
# 当月计提提成
|
||
current_month_accrued_commission = EmployeeCommissionDetail.objects.filter(
|
||
primary_department=primary_department,
|
||
employee=name,
|
||
year_month__year=year,
|
||
year_month__month=month
|
||
).aggregate(total=Sum('accrued_amount'))['total'] or Decimal('0')
|
||
|
||
# 年累计提成
|
||
annual_accumulated_commission = EmployeeCommissionDetail.objects.filter(
|
||
primary_department=primary_department,
|
||
employee=name,
|
||
year_month__year=year
|
||
).aggregate(total=Sum('amount_paid'))['total'] or Decimal('0')
|
||
|
||
# 年累计计提提成
|
||
annual_accumulated_accrued_commission = EmployeeCommissionDetail.objects.filter(
|
||
primary_department=primary_department,
|
||
employee=name,
|
||
year_month__year=year
|
||
).aggregate(total=Sum('accrued_amount'))['total'] or Decimal('0')
|
||
|
||
# 更新或创建模型实例
|
||
commission, created = DepartmentProjectManagerIncomeCommission.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
name=name,
|
||
year_month=year_month,
|
||
defaults={
|
||
'current_month_income': current_month_income,
|
||
'monthly_income_target': monthly_income_target,
|
||
'monthly_target_completion_rate': monthly_target_completion_rate,
|
||
'annual_accumulated_income': annual_accumulated_income,
|
||
'annual_target_completion_rate': annual_target_completion_rate,
|
||
'current_month_commission': current_month_commission,
|
||
'current_month_accrued_commission': current_month_accrued_commission,
|
||
'annual_accumulated_commission': annual_accumulated_commission,
|
||
'annual_accumulated_accrued_commission': annual_accumulated_accrued_commission,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentProjectManagerIncomeCommission',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_departments_commissions(cls, year_month):
|
||
cls.calculate_and_update_commissions(year_month)
|
||
|
||
|
||
# 出勤情况
|
||
class DepartmentAttendance(models.Model):
|
||
primary_department = models.CharField(max_length=255, verbose_name="一级部门", help_text="用于筛选、区分一级部门")
|
||
year_month = models.CharField(max_length=7, verbose_name="年月", help_text="格式为'YYYY-MM',表示统计数据的年月")
|
||
late = models.IntegerField(verbose_name="迟到", help_text="当月累计迟到次数")
|
||
early_departure = models.IntegerField(verbose_name="早退", help_text="当月累计早退次数")
|
||
absenteeism = models.IntegerField(verbose_name="旷工", help_text="当月累计旷工天数")
|
||
annual_leave = models.IntegerField(verbose_name="年假", help_text="当月使用的年假天数")
|
||
personal_leave = models.IntegerField(verbose_name="事假", help_text="当月使用的事假天数")
|
||
sick_leave = models.IntegerField(verbose_name="病假", help_text="当月使用的病假天数")
|
||
other_leave = models.IntegerField(verbose_name="其他", help_text="当月使用的其他类型假期的天数")
|
||
total_days = models.IntegerField(verbose_name="合计", help_text="当月总假期天数,包括年假、事假、病假和其他类型假期")
|
||
|
||
class Meta:
|
||
verbose_name = "业务部门出勤情况"
|
||
verbose_name_plural = "业务部门出勤情况"
|
||
db_table_comment = '存储业务部门出勤情况数据,包括一级部门、年月、迟到、早退、旷工、年假、事假、病假、其他假期和合计等'
|
||
|
||
def __str__(self):
|
||
return f"Attendance for {self.primary_department} in {self.year_month}"
|
||
|
||
@staticmethod
|
||
def get_field_labels():
|
||
return {
|
||
'primary_department': '一级部门',
|
||
'year_month': '年月',
|
||
'late': '迟到',
|
||
'early_departure': '早退',
|
||
'absenteeism': '旷工',
|
||
'annual_leave': '年假',
|
||
'personal_leave': '事假',
|
||
'sick_leave': '病假',
|
||
'other_leave': '其他',
|
||
'total_days': '合计',
|
||
}
|
||
|
||
def get_field_label(self, field_name):
|
||
field_labels = self.get_field_labels()
|
||
return field_labels.get(field_name, field_name)
|
||
|
||
@staticmethod
|
||
def calculate_and_update_attendance(year_month):
|
||
primary_departments = PrimaryDepartment.objects.all()
|
||
year, month = map(int, year_month.split('-'))
|
||
|
||
for department in primary_departments:
|
||
primary_department = department.department_name
|
||
|
||
# 聚合数据
|
||
attendance_data = EmployeeAttendanceRecord.objects.filter(
|
||
primary_department=primary_department,
|
||
year_month__year=year,
|
||
year_month__month=month
|
||
).aggregate(
|
||
total_late=Sum('late'),
|
||
total_early_departure=Sum('early_leave'),
|
||
total_absenteeism=Sum('absenteeism'),
|
||
total_annual_leave=Sum('annual_leave'),
|
||
total_personal_leave=Sum('personal_leave'),
|
||
total_sick_leave=Sum('sick_leave')
|
||
)
|
||
|
||
other_leave = EmployeeAttendanceRecord.objects.filter(
|
||
primary_department=primary_department,
|
||
year_month__year=year,
|
||
year_month__month=month
|
||
).aggregate(total=Sum('other_leave'))['total'] or 0
|
||
|
||
total_days = (
|
||
attendance_data['total_annual_leave'] or 0 +
|
||
attendance_data['total_personal_leave'] or 0 +
|
||
attendance_data['total_sick_leave'] or 0 +
|
||
other_leave
|
||
)
|
||
|
||
# 更新或创建模型实例
|
||
attendance, created = DepartmentAttendance.objects.update_or_create(
|
||
primary_department=primary_department,
|
||
year_month=year_month,
|
||
defaults={
|
||
'late': attendance_data['total_late'] or 0,
|
||
'early_departure': attendance_data['total_early_departure'] or 0,
|
||
'absenteeism': attendance_data['total_absenteeism'] or 0,
|
||
'annual_leave': attendance_data['total_annual_leave'] or 0,
|
||
'personal_leave': attendance_data['total_personal_leave'] or 0,
|
||
'sick_leave': attendance_data['total_sick_leave'] or 0,
|
||
'other_leave': other_leave,
|
||
'total_days': total_days,
|
||
}
|
||
)
|
||
|
||
# 更新或创建更新时间记录
|
||
UpdateLog.objects.update_or_create(
|
||
table_name='DepartmentAttendance',
|
||
defaults={'last_update': timezone.now().date()}
|
||
)
|
||
|
||
@classmethod
|
||
def update_all_departments_attendance(cls, year_month):
|
||
cls.calculate_and_update_attendance(year_month)
|