176 lines
7.1 KiB
Python
176 lines
7.1 KiB
Python
import datetime
|
|
|
|
from odoo import fields, models, api
|
|
|
|
|
|
class YuthonProperty(models.Model):
|
|
_inherit = 'property.accounts.receivable'
|
|
|
|
# 固定费用类型列(用于报表横向展示)
|
|
FEE_COLUMNS = ['租金', '管理费', '水费', '电费', '违约金', '其他费用']
|
|
|
|
def _get_tax_rate_display(self, rec):
|
|
"""从合同获取税率显示字符串"""
|
|
try:
|
|
tr = rec.contract_id.tax_rate.name if rec.contract_id and rec.contract_id.tax_rate else None
|
|
if tr and str(tr).replace('%', '').strip():
|
|
v = float(str(tr).replace('%', '').strip())
|
|
return f"{v:.1f}%"
|
|
except (ValueError, TypeError):
|
|
pass
|
|
return "0.0%"
|
|
|
|
def _classify_fee_type(self, type_name):
|
|
"""将应收类型归类到固定列"""
|
|
if not type_name:
|
|
return '其他费用'
|
|
if '租' in type_name:
|
|
return '租金'
|
|
elif '管理' in type_name or '管' in type_name:
|
|
return '管理费'
|
|
elif '水' in type_name:
|
|
return '水费'
|
|
elif '电' in type_name:
|
|
return '电费'
|
|
elif '违约' in type_name:
|
|
return '违约金'
|
|
else:
|
|
return '其他费用'
|
|
|
|
@api.model
|
|
def get_placeholder(self, params):
|
|
"""通用占位方法,用于尚未开发的菜单"""
|
|
return []
|
|
|
|
@api.model
|
|
def get_complete_ledger_report(self, params):
|
|
summary_only = params.get("summary_only", False)
|
|
domain = [('is_invalid', '!=', True)]
|
|
if params.get("keyword"):
|
|
keyword = params["keyword"]
|
|
domain += [
|
|
'|', '|',
|
|
('lessee_id.name', 'ilike', keyword),
|
|
('property_name', 'ilike', keyword),
|
|
('title_deed', 'ilike', keyword)
|
|
]
|
|
|
|
if params.get("date_start"):
|
|
date_start = datetime.datetime.fromisoformat(params.get("date_start")).date()
|
|
domain.append(("due_date", ">=", date_start))
|
|
if params.get("date_end"):
|
|
date_end = datetime.datetime.fromisoformat(params.get("date_end")).date()
|
|
domain.append(("due_date", "<=", date_end))
|
|
|
|
condition = params.get('condition', False)
|
|
partner_id = params.get('partner_id', False)
|
|
company_id = params.get('company_id', False)
|
|
|
|
if condition:
|
|
domain.append(('tenure_type', '=', condition))
|
|
if partner_id:
|
|
domain.append(('precinct_id', '=', partner_id))
|
|
if company_id:
|
|
domain.append(('company_id', '=', company_id))
|
|
|
|
receivables = self.search(domain, order="contract_id asc, due_date asc")
|
|
|
|
# 按合同分组
|
|
contract_map = {}
|
|
for rec in receivables:
|
|
cid = rec.contract_id.id if rec.contract_id else 0
|
|
if cid not in contract_map:
|
|
contract_map[cid] = {
|
|
'recs': [],
|
|
'info_rec': rec, # 取第一条记录作为基础信息
|
|
}
|
|
contract_map[cid]['recs'].append(rec)
|
|
|
|
rows = []
|
|
total_fees = {col: 0.0 for col in self.FEE_COLUMNS}
|
|
total_subtotal = 0.0
|
|
idx = 1
|
|
|
|
if summary_only:
|
|
for cid, data in contract_map.items():
|
|
for rec in data['recs']:
|
|
type_name = rec.management_type_id.name if rec.management_type_id else ''
|
|
col = self._classify_fee_type(type_name)
|
|
total_fees[col] += (rec.original_amount or 0.0) - (rec.discount_amount or 0.0)
|
|
subtotal = sum((rec.original_amount or 0.0) - (rec.discount_amount or 0.0) for rec in data['recs'])
|
|
total_subtotal += subtotal
|
|
summary_stats = []
|
|
for col in self.FEE_COLUMNS:
|
|
summary_stats.append({'name': col, 'amount': round(total_fees[col], 2)})
|
|
summary_stats.append({'name': '小计合计', 'amount': round(total_subtotal, 2)})
|
|
return {"rows": [], "stats": summary_stats}
|
|
|
|
for cid, data in contract_map.items():
|
|
info_rec = data['info_rec']
|
|
fee_row = {col: 0.0 for col in self.FEE_COLUMNS}
|
|
|
|
# 归类费用
|
|
for rec in data['recs']:
|
|
type_name = rec.management_type_id.name if rec.management_type_id else ''
|
|
col = self._classify_fee_type(type_name)
|
|
fee_row[col] += (rec.original_amount or 0.0) - (rec.discount_amount or 0.0)
|
|
|
|
subtotal = sum(fee_row.values())
|
|
for col in self.FEE_COLUMNS:
|
|
total_fees[col] += fee_row[col]
|
|
total_subtotal += subtotal
|
|
|
|
row = {
|
|
"序号": idx,
|
|
"应收开始": info_rec.due_date.strftime("%Y-%m-%d") if info_rec.due_date else "",
|
|
"应收结束": info_rec.due_date_end.strftime("%Y-%m-%d") if info_rec.due_date_end else "",
|
|
"合同编号": {
|
|
'model': 'property.lease.contract',
|
|
'id': info_rec.contract_id.id,
|
|
'display_name': info_rec.contract_id.contract_code,
|
|
} if info_rec.contract_id else "",
|
|
"承租方": {
|
|
'model': 'property.tenant.information',
|
|
'id': info_rec.lessee_id.id,
|
|
'display_name': info_rec.lessee_id.name,
|
|
} if info_rec.lessee_id else "",
|
|
"物业名称": {
|
|
'model': 'yuthon.property',
|
|
'id': info_rec.contract_id.lease_ids[0].address_id.id,
|
|
'display_name': info_rec.property_name,
|
|
} if info_rec.contract_id and info_rec.contract_id.lease_ids and info_rec.contract_id.lease_ids[0].address_id else info_rec.property_name or "",
|
|
"产权证号": info_rec.title_deed or "",
|
|
"发票类型": info_rec.lessee_id.invoicing_ids[0].invoicing_type_id.name if info_rec.lessee_id and info_rec.lessee_id.invoicing_ids else "",
|
|
"税率": self._get_tax_rate_display(info_rec),
|
|
}
|
|
# 加入各费用列
|
|
for col in self.FEE_COLUMNS:
|
|
row[col] = round(fee_row[col], 2) if fee_row[col] else ""
|
|
row["应收金额"] = round(subtotal, 2)
|
|
row["小计"] = round(subtotal, 2)
|
|
rows.append(row)
|
|
idx += 1
|
|
|
|
# 合计行
|
|
summary_stats = []
|
|
for col in self.FEE_COLUMNS:
|
|
summary_stats.append({'name': col, 'amount': round(total_fees[col], 2)})
|
|
summary_stats.append({'name': '小计合计', 'amount': round(total_subtotal, 2)})
|
|
|
|
return {"rows": rows, "stats": summary_stats}
|
|
|
|
@api.model
|
|
def get_domain(self, start_date=False, end_date=False, company_id=False):
|
|
if not start_date or not end_date:
|
|
return []
|
|
if not company_id:
|
|
return []
|
|
|
|
# 这里进行条件的修改
|
|
property_records = self.env['yuthon.property'].search([('company_id', '=', company_id)])
|
|
|
|
user_ids = set()
|
|
for property_record in property_records:
|
|
user_ids.add(property_record.precinct_id.id)
|
|
|
|
return list(user_ids) |