!12371 累计欠收

Merge pull request !12371 from 李鹏宇/dev_wang
This commit is contained in:
李鹏宇
2026-07-08 08:38:28 +00:00
committed by Gitee
+71 -9
View File
@@ -1,9 +1,12 @@
import calendar
import datetime
import logging
from odoo import api, models
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
_logger = logging.getLogger(__name__)
class CumArrearsReport(models.Model):
_inherit = 'receivable.modify.line'
@@ -11,15 +14,16 @@ class CumArrearsReport(models.Model):
@api.model
def get_cum_arrears_report(self, params):
"""
累计欠收报表(数据源:receivable.modify.line):
- 查询条件的日期对应应收账单的 due_date(应收日期在查询月及之前,包含查询月)
- 欠收条件:
- 收款日期在查询月及之后(查询月时点还没收到钱)
- 或者 not_collected > 0 (部分收款,还没交完)
- 金额取值:
- 如果 not_collected > 0,取 not_collected (当前还欠的金额)
- 否则取 amount (已收金额)
- 按应收账单聚合,每张账单只出一行(汇总该账单下所有欠收收款金额)
累计欠收报表(两路取数):
- Part1: receivable.modify.line — 有收款记录但欠收的账单
- due_date <= query_month_end(含查询月)
- 欠收条件: reconciliation_date >= 查询月1号 且 (reconciliation_date > 查询月末 或 not_collected > 0)
- 金额取值: not_collected > 0 取 not_collected,否则取 amount
- Part2: property.accounts.receivable — 从未对账且从未收款的账单
- is_reconciliation=False, payout_date=False, due_date <= query_month_end
- 金额取值: submitted(未收金额)
- 排除 Part1 已覆盖的 receivable_id
- 按应收账单聚合,每张账单只出一行
"""
today = datetime.date.today()
this_month_first = today.replace(day=1)
@@ -101,6 +105,64 @@ class CumArrearsReport(models.Model):
if line.reconciliation_date:
rec_map[rid]['reconciliation_dates'].append(line.reconciliation_date)
# ============================================================
# 第二部分:从 property.accounts.receivable 取 is_reconciliation=False 的记录
# 即:未对过账且未收款(payout_date为空)的应收账单,due_date <= query_month_end(含查询月)
# 这类账单没有 modify.line 收款记录,Part1 查不到,需要补充
# 欠收金额取 submitted(未收金额字段)
# ============================================================
covered_ids = list(rec_map.keys()) # Part1 已覆盖的 receivable_id
receivable_domain = [
('is_reconciliation', '=', False), # 未对过账
('due_date', '<=', query_month_end), # 累计欠收:含查询月
('payout_date', '=', False), # 从未收款
('is_invalid', '!=', True), # 排除作废
]
if covered_ids:
receivable_domain.append(('id', 'not in', list(covered_ids))) # 排除 Part1 已有的
# 同样的筛选条件(去掉 receivable_id. 前缀,直接查 accounts.receivable 自身字段)
if keyword:
receivable_domain += [
'|', '|',
('contract_id.contract_code', 'ilike', keyword),
('property_name', 'ilike', keyword),
('lessee_id.name', 'ilike', keyword),
]
if condition:
receivable_domain.append(('tenure_type', '=', condition))
if partner_id:
receivable_domain.append(('precinct_id', 'in', partner_id)) # 多选:片区管理员用 in 操作符
if company_id:
receivable_domain.append(('company_id', 'in', company_id))
if property_id:
receivable_domain.append(('property_ids', 'in', [property_id]))
if lessee_id:
receivable_domain.append(('lessee_id', '=', lessee_id))
if contract_id:
receivable_domain.append(('contract_id', '=', contract_id))
if management_type_id:
receivable_domain.append(('management_type_id', '=', management_type_id))
else:
receivable_domain.append(('management_type_id.name', 'not in', ['押金', '违约金']))
unreconciled_receivables = self.env['property.accounts.receivable'].sudo().search(
receivable_domain, order="due_date asc")
_logger.info("[CUM_ARREARS] Part2 从 accounts.receivable(is_reconciliation=False) 补充 %d 条", len(unreconciled_receivables))
for rec in unreconciled_receivables:
rid = rec.id
# 未对过账的应收账单,欠收金额 = submitted
rec_map[rid] = {
'rec': rec,
'amount': rec.submitted or 0.0,
'reconciliation_dates': [],
}
# ============================================================
# 构建返回数据
# ============================================================
rows = []
total_amount = 0.0
if summary_only: