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)