Files
gzth/yuthon_report/models/total_received_report.py
T
2026-06-22 19:25:07 +08:00

138 lines
5.6 KiB
Python

import datetime
import calendar
from odoo import api, models
from .report_utils import _id_list
class TotalReceivedReport(models.Model):
_inherit = 'receivable.modify.line'
@api.model
def get_total_received_report(self, params):
"""本月实收总额 = 归属本月实收 + 本月预收
取数逻辑:收款日期(reconciliation_date)在查询月内的所有收款记录,金额取 amount
"""
summary_only = params.get("summary_only", False)
domain = [
('reconciliation_date', '!=', False),
('receivable_id.is_invalid', '!=', True),
]
# 收款日期在查询月内
if params.get('date_start'):
query_date = datetime.datetime.fromisoformat(params['date_start']).date()
month_start = query_date.replace(day=1)
last_day = calendar.monthrange(query_date.year, query_date.month)[1]
month_end = query_date.replace(day=last_day)
domain += [
('reconciliation_date', '>=', month_start),
('reconciliation_date', '<=', month_end),
]
if params.get('keyword'):
keyword = params['keyword']
domain += ['|', '|',
('receivable_id.lessee_id.name', 'ilike', keyword),
('receivable_id.property_name', 'ilike', keyword),
('receivable_id.contract_id.contract_code', 'ilike', keyword),
]
condition = params.get('condition')
# 多选标准化:partner_id 统一为列表,配合 'in' 操作符
partner_id = _id_list(params.get('partner_id'))
company_id = _id_list(params.get('company_id'))
management_type_id = params.get('management_type_id')
property_id = params.get('property_id')
lessee_id = params.get('lessee_id')
contract_id = params.get('contract_id')
if condition:
domain.append(('receivable_id.tenure_type', '=', condition))
# 片区管理员:多选,用 'in' 操作符
if partner_id:
domain.append(('receivable_id.precinct_id', 'in', partner_id))
if company_id:
domain.append(('receivable_id.company_id', 'in', company_id))
# 经营收入只统计租金类,排除押金、违约金
exclude_types = ['押金', '违约金']
if management_type_id:
domain.append(('receivable_id.management_type_id', '=', management_type_id))
else:
domain.append(('receivable_id.management_type_id.name', 'not in', exclude_types))
if property_id:
domain.append(('receivable_id.property_ids', 'in', [property_id]))
if lessee_id:
domain.append(('receivable_id.lessee_id', '=', lessee_id))
if contract_id:
domain.append(('receivable_id.contract_id', '=', contract_id))
lines = self.search(domain, order='reconciliation_date asc')
if summary_only:
total_amount = sum(round(line.amount or 0.0, 2) for line in lines)
stats = [{'name': '合计', 'amount': round(total_amount, 2)}]
return {'rows': [], 'stats': stats}
rows = []
total_amount = 0.0
for idx, line in enumerate(lines, start=1):
rec = line.receivable_id
contract = rec.contract_id if rec else None
amount = round(line.amount or 0.0, 2)
total_amount += amount
# 物业穿透
property_val = ''
if contract and contract.lease_ids and contract.lease_ids[0].address_id:
prop = contract.lease_ids[0].address_id
property_val = {
'model': 'yuthon.property',
'id': prop.id,
'display_name': rec.property_name or prop.name,
}
elif rec:
property_val = rec.property_name or ''
# 合同穿透
contract_val = ''
if contract:
contract_val = {
'model': 'property.lease.contract',
'id': contract.id,
'display_name': contract.contract_code or '',
}
# 承租方穿透
lessee_val = ''
if rec and rec.lessee_id:
lessee_val = {
'model': 'property.tenant.information',
'id': rec.lessee_id.id,
'display_name': rec.lessee_id.name,
}
# 应收金额 = original_amount - discount_amount
receivable_amount = round((rec.original_amount or 0.0) - (rec.discount_amount or 0.0), 2)
rows.append({
'序号': idx,
'物业名称': property_val,
'合同编号': contract_val,
'承租方名称': lessee_val,
'收款类型': rec.management_type_id.name if rec and rec.management_type_id else '',
'应收开始': rec.due_date.strftime('%Y-%m-%d') if rec and rec.due_date else '',
'应收结束': rec.due_date_end.strftime('%Y-%m-%d') if rec and rec.due_date_end else '',
'金额': amount,
'应收金额': receivable_amount,
'所属公司': contract.lessor_id.name if contract and contract.lessor_id else '',
'管理员': {
'model': 'res.users',
'id': rec.admin_id.id,
'display_name': rec.admin_id.name,
} if rec.admin_id else '',
})
stats = [{'name': '合计', 'amount': round(total_amount, 2)}]
return {'rows': rows, 'stats': stats}