This commit is contained in:
李鹏宇
2026-06-16 18:43:25 +08:00
parent a30a53738f
commit a67e28ee8e
7 changed files with 299 additions and 9 deletions
+2
View File
@@ -41,6 +41,8 @@
'views/receivable_flow_report.xml',
'views/text_summary_report.xml',
'views/yuthon_dashboard_views.xml',
'views/management_fee_report.xml',
'views/management_fee_yearly_report.xml',
],
'installable': True,
'application': True,
+3 -1
View File
@@ -35,4 +35,6 @@ from . import hydropower_report
from . import receivable_filter_domains
from . import text_summary_report
from . import bank_statements_report
from . import yuthon_dashboard
from . import yuthon_dashboard
from . import management_fee_monthly_report
from . import management_fee_yearly_report
@@ -0,0 +1,107 @@
import datetime
import calendar
import logging
from odoo import api, models
_logger = logging.getLogger(__name__)
class PropertyBillsList(models.Model):
_inherit = 'property.bills.list'
@api.model
def get_management_fee_monthly_report(self, params):
"""管理费本月支出报表。
数据源:property.bills.list
过滤条件:
- management_type_id.name = '管理费'
- actual_date(实付日期)在查询月本月范围内(月初~月末)
字段:应付日期、实付日期、应付、实付、标题
"""
# ========== 一、参数解析 ==========
date_start = params.get("date_start")
keyword = params.get("keyword")
# ========== 二、查询日期解析 ==========
if date_start:
try:
query_date = datetime.datetime.fromisoformat(date_start.split(' ')[0]).date()
except Exception:
query_date = datetime.date.today()
else:
query_date = datetime.date.today()
# 计算查询月月初和月末
month_first = query_date.replace(day=1)
_, last_day = calendar.monthrange(query_date.year, query_date.month)
month_last = query_date.replace(day=last_day)
# ========== 三、构建domain ==========
domain = [
('management_type_id.name', '=', '管理费'),
('actual_date', '>=', month_first),
('actual_date', '<=', month_last),
]
# 关键字过滤
if keyword:
domain += ['|', '|', '|',
('name', 'ilike', keyword),
('contract_id.contract_code', 'ilike', keyword),
('lessee_id.name', 'ilike', keyword),
('property_name', 'ilike', keyword),
]
# 公司/片区过滤
company_id = params.get('company_id')
partner_id = params.get('partner_id')
if company_id:
domain.append(('lessor_id', '=', int(company_id)))
if partner_id:
domain += ['|',
('contract_id.precinct_id', '=', int(partner_id)),
('receivables_id.precinct_id', '=', int(partner_id)),
]
# 查询记录
records = self.sudo().search(domain)
# ========== 四、构建报表行 ==========
rows = []
total_amount = 0.0 # 应付合计
total_amount_actual = 0.0 # 实付合计
for idx, rec in enumerate(records, start=1):
due_date_str = rec.due_date.strftime("%Y-%m-%d") if rec.due_date else ""
actual_date_str = rec.actual_date.strftime("%Y-%m-%d") if rec.actual_date else ""
amount_val = round(rec.amount or 0.0, 2)
amount_actual_val = round(rec.amount_actual or 0.0, 2)
total_amount += amount_val
total_amount_actual += amount_actual_val
rows.append({
"序号": idx,
"应付日期": due_date_str,
"实付日期": actual_date_str,
"应付": amount_val,
"实付": amount_actual_val,
"标题": rec.name or "",
})
# ========== 五、构建统计汇总数据 ==========
stats = [
{'name': '记录总数', 'amount': len(rows)},
{'name': '应付合计', 'amount': round(total_amount, 2)},
{'name': '实付合计', 'amount': round(total_amount_actual, 2)},
]
_logger.info(
"[MANAGEMENT_FEE_MONTHLY] query_date=%s, month_range=[%s, %s], rows=%d, "
"total_amount=%.2f, total_amount_actual=%.2f",
query_date, month_first, month_last, len(rows), total_amount, total_amount_actual,
)
return {"rows": rows, "stats": stats}
@@ -0,0 +1,107 @@
import datetime
import calendar
import logging
from odoo import api, models
_logger = logging.getLogger(__name__)
class PropertyBillsList(models.Model):
_inherit = 'property.bills.list'
@api.model
def get_management_fee_yearly_report(self, params):
"""管理费本年累计报表。
数据源:property.bills.list
过滤条件:
- management_type_id.name = '管理费'
- actual_date(实付日期)在查询月所在年的1月1日~查询月末
字段:应付日期、实付日期、应付、实付、标题
"""
# ========== 一、参数解析 ==========
date_start = params.get("date_start")
keyword = params.get("keyword")
# ========== 二、查询日期解析 ==========
if date_start:
try:
query_date = datetime.datetime.fromisoformat(date_start.split(' ')[0]).date()
except Exception:
query_date = datetime.date.today()
else:
query_date = datetime.date.today()
# 计算查询范围:年初(1月1日)到查询月末
year_start = query_date.replace(month=1, day=1)
_, last_day = calendar.monthrange(query_date.year, query_date.month)
month_last = query_date.replace(day=last_day)
# ========== 三、构建domain ==========
domain = [
('management_type_id.name', '=', '管理费'),
('actual_date', '>=', year_start),
('actual_date', '<=', month_last),
]
# 关键字过滤
if keyword:
domain += ['|', '|', '|',
('name', 'ilike', keyword),
('contract_id.contract_code', 'ilike', keyword),
('lessee_id.name', 'ilike', keyword),
('property_name', 'ilike', keyword),
]
# 公司/片区过滤
company_id = params.get('company_id')
partner_id = params.get('partner_id')
if company_id:
domain.append(('lessor_id', '=', int(company_id)))
if partner_id:
domain += ['|',
('contract_id.precinct_id', '=', int(partner_id)),
('receivables_id.precinct_id', '=', int(partner_id)),
]
# 查询记录
records = self.sudo().search(domain)
# ========== 四、构建报表行 ==========
rows = []
total_amount = 0.0 # 应付合计
total_amount_actual = 0.0 # 实付合计
for idx, rec in enumerate(records, start=1):
due_date_str = rec.due_date.strftime("%Y-%m-%d") if rec.due_date else ""
actual_date_str = rec.actual_date.strftime("%Y-%m-%d") if rec.actual_date else ""
amount_val = round(rec.amount or 0.0, 2)
amount_actual_val = round(rec.amount_actual or 0.0, 2)
total_amount += amount_val
total_amount_actual += amount_actual_val
rows.append({
"序号": idx,
"应付日期": due_date_str,
"实付日期": actual_date_str,
"应付": amount_val,
"实付": amount_actual_val,
"标题": rec.name or "",
})
# ========== 五、构建统计汇总数据 ==========
stats = [
{'name': '记录总数', 'amount': len(rows)},
{'name': '应付合计', 'amount': round(total_amount, 2)},
{'name': '实付合计', 'amount': round(total_amount_actual, 2)},
]
_logger.info(
"[MANAGEMENT_FEE_YEARLY] query_date=%s, year_range=[%s, %s], rows=%d, "
"total_amount=%.2f, total_amount_actual=%.2f",
query_date, year_start, month_last, len(rows), total_amount, total_amount_actual,
)
return {"rows": rows, "stats": stats}
+26 -8
View File
@@ -352,14 +352,32 @@ class YuthonDashboard(models.Model):
year_receivables = self.env['property.accounts.receivable'].sudo().search(year_domain)
year_total = sum((r.original_amount or 0.0) for r in year_receivables)
cards.append({
'label': f'{label}·本月支出', 'value': round(month_total, 2),
'is_negative': False, 'action': '', 'action_context': {},
})
cards.append({
'label': f'{label}·本年累计', 'value': round(year_total, 2),
'is_negative': False, 'action': '', 'action_context': {},
})
# 本月支出卡片:管理费绑定报表,其他费用暂不绑定
if label == '管理费':
cards.append({
'label': f'{label}·本月支出', 'value': round(month_total, 2),
'is_negative': False,
'action': 'yuthon_report.action_management_fee_monthly_report',
'action_context': {},
})
else:
cards.append({
'label': f'{label}·本月支出', 'value': round(month_total, 2),
'is_negative': False, 'action': '', 'action_context': {},
})
# 本年累计卡片:管理费绑定报表,其他费用暂不绑定
if label == '管理费':
cards.append({
'label': f'{label}·本年累计', 'value': round(year_total, 2),
'is_negative': False,
'action': 'yuthon_report.action_management_fee_yearly_report',
'action_context': {},
})
else:
cards.append({
'label': f'{label}·本年累计', 'value': round(year_total, 2),
'is_negative': False, 'action': '', 'action_context': {},
})
row_labels.append(label)
# 说明信息
desc = f"{label}本月{month_total:.2f}元"
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_management_fee_monthly_report" model="ir.actions.client">
<field name="name">管理费本月支出</field>
<field name="tag">receivable_report_client</field>
<field name="context">
{
"sideBar": true,
"report_config": {
"model": "property.bills.list",
"method": "get_management_fee_monthly_report",
"dateMode": "single",
"columns": [
{"headerName": "序号", "field": "序号", "width": 45, "flex": 0, "pinned": "left"},
{"headerName": "应付日期", "field": "应付日期", "flex": 1.2},
{"headerName": "实付日期", "field": "实付日期", "flex": 1.2},
{"headerName": "应付", "field": "应付", "flex": 1, "type": "number"},
{"headerName": "实付", "field": "实付", "flex": 1, "type": "number"},
{"headerName": "标题", "field": "标题", "flex": 2.5}
]
}
}
</field>
</record>
</data>
</odoo>
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_management_fee_yearly_report" model="ir.actions.client">
<field name="name">管理费本年累计</field>
<field name="tag">receivable_report_client</field>
<field name="context">
{
"sideBar": true,
"report_config": {
"model": "property.bills.list",
"method": "get_management_fee_yearly_report",
"dateMode": "single",
"columns": [
{"headerName": "序号", "field": "序号", "width": 45, "flex": 0, "pinned": "left"},
{"headerName": "应付日期", "field": "应付日期", "flex": 1.2},
{"headerName": "实付日期", "field": "实付日期", "flex": 1.2},
{"headerName": "应付", "field": "应付", "flex": 1, "type": "number"},
{"headerName": "实付", "field": "实付", "flex": 1, "type": "number"},
{"headerName": "标题", "field": "标题", "flex": 2.5}
]
}
}
</field>
</record>
</data>
</odoo>