Files
gzth/yuthon_report/models/parking_fee_yearly_report.py
T
2026-06-22 17:25:54 +08:00

158 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import calendar
import datetime
from odoo import api, models
from .report_utils import _id_list
class ParkingFeeYearlyReport(models.Model):
_inherit = 'receivable.modify.line'
@api.model
def get_parking_fee_yearly_report(self, params):
"""
停车费本年累计(数据源:receivable.modify.line):
- 查询范围:年初(1月1日)到查询月末
例如查3月 → 1月1日 ~ 3月31日;查6月 → 1月1日 ~ 6月30日
- 用 reconciliation_date(收款行对账日期)判断已收
- 取每行的 amount(已对金额)
- 应收类型只取"停车费"
其余逻辑同累计收入(cum_income_report)
"""
today = datetime.date.today()
date_start = params.get("date_start")
summary_only = params.get("summary_only", False)
# 取查询日所在年份和月份
if date_start:
query_date = datetime.datetime.fromisoformat(date_start).date()
else:
query_date = today
year = query_date.year
query_month = query_date.month
# 查询范围:年初到查询月末
year_start = datetime.date(year, 1, 1)
last_day = calendar.monthrange(year, query_month)[1]
query_month_end = datetime.date(year, query_month, last_day)
# 停车费类型固定过滤:只取应收类型 = '停车费'
parking_type = self.env['yuthon.management.type'].sudo().search(
[('name', '=', '停车费')], limit=1)
# 用 reconciliation_date(收款行自身的对账日期)做时间范围筛选
domain = [
('reconciliation_date', '>=', year_start),
('reconciliation_date', '<=', query_month_end),
('receivable_id.is_invalid', '!=', True),
]
# 固定只取停车费
if parking_type:
domain.append(('receivable_id.management_type_id', '=', parking_type.id))
keyword = params.get("keyword")
if keyword:
domain += [
'|', '|',
('receivable_id.contract_id.contract_code', 'ilike', keyword),
('receivable_id.property_name', 'ilike', keyword),
('receivable_id.lessee_id.name', 'ilike', keyword),
]
condition = params.get('condition')
partner_id = _id_list(params.get('partner_id'))
company_id = _id_list(params.get('company_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))
if partner_id:
domain.append(('receivable_id.precinct_id', 'in', partner_id))
if company_id:
domain.append(('receivable_id.company_id', 'in', company_id))
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': len(lines)},
{'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.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': len(rows)},
{'name': '本年累计', 'amount': round(total_amount, 2)},
]
return {"rows": rows, "stats": stats}