报表
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import datetime
|
||||
import re
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
@@ -75,8 +76,9 @@ class ReceivableFlowReport(models.Model):
|
||||
wizard_map = {} # {receivable_id: [wizards]}
|
||||
for wz in all_wizards:
|
||||
wizard_map.setdefault(wz.receivable_id.id, []).append(wz)
|
||||
# 预取所有 pay_line_ids
|
||||
# 预取所有 pay_line_ids 和 penalty_line_ids
|
||||
all_pay_lines = all_wizards.mapped('pay_line_ids')
|
||||
all_wizards.mapped('penalty_line_ids') # 预加载违约金计算明细
|
||||
# 按 wizard_id 分组
|
||||
pay_line_map = {} # {wizard_id: [pay_lines]}
|
||||
for pl in all_pay_lines:
|
||||
@@ -108,54 +110,32 @@ class ReceivableFlowReport(models.Model):
|
||||
if rec.submitted == 0:
|
||||
charge_status = "已收"
|
||||
|
||||
# 计算违约金相关信息
|
||||
# 计算欠租金额(直接使用合同的rent字段,即月租金)
|
||||
rent_owed = 0.0
|
||||
if rec.contract_id:
|
||||
rent_owed = rec.contract_id.rent or 0.0
|
||||
rent_owed = rent_owed or rec.rent_owed or 0.0
|
||||
|
||||
# 计算每天违约金(欠租金额 × 违约金比例)
|
||||
per_day = 0.0
|
||||
if rent_owed > 0 and rec.contract_id and rec.contract_id.percentage_liquidated_damages:
|
||||
penalty_ratio = rec.contract_id.percentage_liquidated_damages.name or "0"
|
||||
try:
|
||||
penalty_ratio = float(penalty_ratio)
|
||||
per_day = rent_owed * penalty_ratio
|
||||
except ValueError:
|
||||
per_day = 0.0
|
||||
per_day = per_day or rec.difference_amount or rec.per_day or 0.0
|
||||
|
||||
# 计算违约金金额(每天违约金 × 违约天数)
|
||||
penalty_amount = 0.0
|
||||
billing_period = rec.charging_range or ""
|
||||
days_diff = 0
|
||||
|
||||
if billing_period:
|
||||
try:
|
||||
# 兼容中文“到”和英文“~”两种分隔符
|
||||
if ' 到 ' in billing_period:
|
||||
date_parts = billing_period.split(' 到 ')
|
||||
elif ' ~ ' in billing_period:
|
||||
date_parts = billing_period.split(' ~ ')
|
||||
else:
|
||||
date_parts = []
|
||||
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:
|
||||
billing_period = rec.charging_range or ""
|
||||
days_diff = 0
|
||||
|
||||
# 计算违约金金额
|
||||
penalty_amount = round(days_diff * per_day, 2)
|
||||
|
||||
# 获取违约金收款信息(从预加载字典取)
|
||||
# 从 penalty.line.wizard 取违约金信息(唯一数据源)
|
||||
wz_list = wizard_map.get(rec.id, [])
|
||||
|
||||
# 违约金字段:有 wizard 才显示,否则全为空/0
|
||||
billing_period = ""
|
||||
days_diff = 0
|
||||
penalty_amount = 0.0
|
||||
if wz_list:
|
||||
wz = wz_list[0]
|
||||
days_diff = wz.days_overdue or 0
|
||||
penalty_amount = round(wz.total_penalty or 0.0, 2)
|
||||
# 计算时间:取 penalty > 0 的明细行,从每行的 remake 解析起止日期
|
||||
penalty_lines = [pl for pl in wz.penalty_line_ids if pl.penalty > 0]
|
||||
if penalty_lines:
|
||||
# remake 格式: "违约金:2026-02-22至2026-03-23"
|
||||
# 每行 remake 都包含起止日期,收集所有行的日期取最早和最晚
|
||||
all_dates = []
|
||||
for pl in penalty_lines:
|
||||
dates_in_remake = re.findall(r'(\d{4}-\d{2}-\d{2})', pl.remake or '')
|
||||
for d in dates_in_remake:
|
||||
try:
|
||||
all_dates.append(datetime.datetime.strptime(d, '%Y-%m-%d').date())
|
||||
except ValueError:
|
||||
pass
|
||||
if all_dates:
|
||||
billing_period = f"{min(all_dates).strftime('%Y-%m-%d')} ~ {max(all_dates).strftime('%Y-%m-%d')}"
|
||||
penalty_pay_lines = []
|
||||
for wz in wz_list:
|
||||
penalty_pay_lines.extend(pay_line_map.get(wz.id, []))
|
||||
|
||||
Reference in New Issue
Block a user