diff --git a/yuthon_report/models/penalty_arrears_report.py b/yuthon_report/models/penalty_arrears_report.py index 661ff72ba..c70b41810 100644 --- a/yuthon_report/models/penalty_arrears_report.py +++ b/yuthon_report/models/penalty_arrears_report.py @@ -61,11 +61,10 @@ class PenaltyArrearsReport(models.Model): total_penalty = total_collected = total_uncollected = 0.0 for idx, rec in enumerate(receivables, start=1): - # 计算欠租金额(合同的未收租金) + # 计算欠租金额(直接使用合同的rent字段,即月租金) rent_owed = 0.0 if rec.contract_id: - # 尝试从合同中获取欠租金额 - rent_owed = rec.contract_id.total_area * rec.contract_id.rent or 0.0 + rent_owed = rec.contract_id.rent or 0.0 # 如果合同中没有,则使用原始金额 rent_owed = rent_owed or rec.rent_owed or 0.0 @@ -85,8 +84,96 @@ class PenaltyArrearsReport(models.Model): # 如果无法计算,则使用现有字段 per_day = per_day or rec.difference_amount or rec.per_day or 0.0 - penalty_amount = rec.penalty or rec.original_amount or 0.0 - penalty_days = round(penalty_amount / per_day, 2) if per_day else 0.0 + # 计算违约金金额(每天违约金 × 违约天数) + penalty_amount = 0.0 + # 尝试从charging_range字段获取时间区间 + billing_period = rec.charging_range or "" + days_diff = 0 + + if billing_period: + # 尝试从charging_range中提取天数 + try: + # 假设charging_range格式为"2026-02-01 ~ 2026-02-28" + date_parts = billing_period.split(" ~ ") + if len(date_parts) == 2: + start_date_str = date_parts[0].strip() + end_date_str = date_parts[1].strip() + start_date = datetime.datetime.strptime(start_date_str, "%Y-%m-%d").date() + end_date = datetime.datetime.strptime(end_date_str, "%Y-%m-%d").date() + days_diff = (end_date - start_date).days + 1 + # 构建标准格式的时间区间字符串 + billing_period = f"{days_diff} {start_date_str} ~ {end_date_str}" + except Exception: + # 如果解析失败,使用默认计算 + if rec.due_date: + # 固定开始日期为当月第一天 + start_date = rec.due_date.replace(day=1) + # 确定结束日期 + if rec.payout_date: + # 已缴费,结束日期为缴费日期 + end_date = rec.payout_date + else: + # 未缴费,结束日期为查询月的最后一天 + if date_end: + end_date_obj = datetime.datetime.fromisoformat(date_end).date() + # 获取查询月的最后一天 + if end_date_obj.month == 12: + last_day = datetime.date(end_date_obj.year, 12, 31) + else: + last_day = datetime.date(end_date_obj.year, end_date_obj.month + 1, 1) - datetime.timedelta(days=1) + end_date = last_day + else: + # 无查询日期,使用当前月最后一天 + today = datetime.date.today() + if today.month == 12: + last_day = datetime.date(today.year, 12, 31) + else: + last_day = datetime.date(today.year, today.month + 1, 1) - datetime.timedelta(days=1) + end_date = last_day + + # 计算违约天数 + days_diff = (end_date - start_date).days + 1 # 包含开始和结束日期 + + # 构建时间区间字符串 + billing_period = f"{days_diff} {start_date.strftime('%Y-%m-%d')} ~ {end_date.strftime('%Y-%m-%d')}" + else: + # 如果charging_range为空,使用默认计算 + if rec.due_date: + # 固定开始日期为当月第一天 + start_date = rec.due_date.replace(day=1) + # 确定结束日期 + if rec.payout_date: + # 已缴费,结束日期为缴费日期 + end_date = rec.payout_date + else: + # 未缴费,结束日期为查询月的最后一天 + if date_end: + end_date_obj = datetime.datetime.fromisoformat(date_end).date() + # 获取查询月的最后一天 + if end_date_obj.month == 12: + last_day = datetime.date(end_date_obj.year, 12, 31) + else: + last_day = datetime.date(end_date_obj.year, end_date_obj.month + 1, 1) - datetime.timedelta(days=1) + end_date = last_day + else: + # 无查询日期,使用当前月最后一天 + today = datetime.date.today() + if today.month == 12: + last_day = datetime.date(today.year, 12, 31) + else: + last_day = datetime.date(today.year, today.month + 1, 1) - datetime.timedelta(days=1) + end_date = last_day + + # 计算违约天数 + days_diff = (end_date - start_date).days + 1 # 包含开始和结束日期 + + # 构建时间区间字符串 + billing_period = f"{days_diff} {start_date.strftime('%Y-%m-%d')} ~ {end_date.strftime('%Y-%m-%d')}" + + # 计算违约金金额 + penalty_amount = days_diff * per_day + # 如果计算结果为0,使用现有字段 + penalty_amount = penalty_amount or rec.penalty or rec.original_amount or 0.0 amount = rec.original_amount or 0.0 @@ -97,40 +184,6 @@ class PenaltyArrearsReport(models.Model): total_collected += collected total_uncollected += uncollected - # 计算违约计算时间区间 - billing_period = "" - if rec.due_date: - # 固定开始日期为当月第一天 - start_date = rec.due_date.replace(day=1) - # 确定结束日期 - if rec.payout_date: - # 已缴费,结束日期为缴费日期 - end_date = rec.payout_date - else: - # 未缴费,结束日期为查询月的最后一天 - if date_end: - end_date_obj = datetime.datetime.fromisoformat(date_end).date() - # 获取查询月的最后一天 - if end_date_obj.month == 12: - last_day = datetime.date(end_date_obj.year, 12, 31) - else: - last_day = datetime.date(end_date_obj.year, end_date_obj.month + 1, 1) - datetime.timedelta(days=1) - end_date = last_day - else: - # 无查询日期,使用当前月最后一天 - today = datetime.date.today() - if today.month == 12: - last_day = datetime.date(today.year, 12, 31) - else: - last_day = datetime.date(today.year, today.month + 1, 1) - datetime.timedelta(days=1) - end_date = last_day - - # 计算违约天数 - days_diff = (end_date - start_date).days + 1 # 包含开始和结束日期 - - # 构建时间区间字符串 - billing_period = f"{days_diff} {start_date.strftime('%Y-%m-%d')} ~ {end_date.strftime('%Y-%m-%d')}" - rows.append({ "序号": idx, "合同编号": {