diff --git a/yuthon_report/__manifest__.py b/yuthon_report/__manifest__.py
index 06ad0c92e..064eda116 100644
--- a/yuthon_report/__manifest__.py
+++ b/yuthon_report/__manifest__.py
@@ -13,6 +13,7 @@
'views/penalty_arrears_report.xml',
'views/penalty_month_received_report.xml',
'views/penalty_year_cum_report.xml',
+ 'views/deposit_reports.xml',
'views/menu.xml',
'views/ledger_report_views.xml',
'views/receivable_report_views.xml',
diff --git a/yuthon_report/models/__init__.py b/yuthon_report/models/__init__.py
index 0753b36b8..c8387fbad 100644
--- a/yuthon_report/models/__init__.py
+++ b/yuthon_report/models/__init__.py
@@ -37,4 +37,7 @@ from . import pre_arrears_report
from . import pre_advance_report
from . import penalty_arrears_report
from . import penalty_month_received_report
-from . import penalty_year_cum_report
\ No newline at end of file
+from . import penalty_year_cum_report
+from . import deposit_month_receivable_report
+from . import deposit_pre_received_report
+from . import deposit_month_received_report
\ No newline at end of file
diff --git a/yuthon_report/models/deposit_month_receivable_report.py b/yuthon_report/models/deposit_month_receivable_report.py
new file mode 100644
index 000000000..ea92d597a
--- /dev/null
+++ b/yuthon_report/models/deposit_month_receivable_report.py
@@ -0,0 +1,87 @@
+import datetime
+
+from odoo import api, models
+
+
+class DepositMonthReceivableReport(models.Model):
+ _inherit = 'property.accounts.receivable'
+
+ @api.model
+ def get_deposit_month_receivable_report(self, params):
+ """
+ 押金本月应收报表:
+ - 管理费用类型为"押金"
+ - due_date 在本月范围内
+ - is_invalid = False
+ - 每条记录单独一行,金额 = original_amount
+ """
+ today = datetime.date.today()
+ this_month_first = today.replace(day=1)
+ if today.month == 12:
+ next_month_first = today.replace(year=today.year + 1, month=1, day=1)
+ else:
+ next_month_first = today.replace(month=today.month + 1, day=1)
+ this_month_last = next_month_first - datetime.timedelta(days=1)
+
+ deposit_type = self.env['yuthon.management.type'].search([('name', '=', '押金')], limit=1)
+
+ domain = [
+ ('due_date', '>=', this_month_first),
+ ('due_date', '<=', this_month_last),
+ ('is_invalid', '=', False),
+ ]
+ if deposit_type:
+ domain.append(('management_type_id', '=', deposit_type.id))
+
+ keyword = params.get("keyword")
+ if keyword:
+ domain += ['|', '|',
+ ('contract_id.contract_code', 'ilike', keyword),
+ ('property_name', 'ilike', keyword),
+ ('lessee_id.name', 'ilike', keyword),
+ ]
+
+ condition = params.get('condition')
+ partner_id = params.get('partner_id')
+ company_id = params.get('company_id')
+ 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")
+
+ rows = []
+ total_amount = 0.0
+ for idx, rec in enumerate(receivables, start=1):
+ amount = round(rec.original_amount or 0.0, 2)
+ total_amount += amount
+ rows.append({
+ "序号": idx,
+ "合同编号": {
+ 'model': 'property.lease.contract',
+ 'id': rec.contract_id.id,
+ 'display_name': rec.contract_id.contract_code,
+ } if rec.contract_id else "",
+ "物业名称": rec.property_name or "",
+ "承租方名称": {
+ 'model': 'property.tenant.information',
+ 'id': rec.lessee_id.id,
+ 'display_name': rec.lessee_id.name,
+ } if rec.lessee_id else "",
+ "金额": amount,
+ "所属公司": rec.company_id.name if rec.company_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}
diff --git a/yuthon_report/models/deposit_month_received_report.py b/yuthon_report/models/deposit_month_received_report.py
new file mode 100644
index 000000000..eb5403cd4
--- /dev/null
+++ b/yuthon_report/models/deposit_month_received_report.py
@@ -0,0 +1,87 @@
+import datetime
+
+from odoo import api, models
+
+
+class DepositMonthReceivedReport(models.Model):
+ _inherit = 'property.accounts.receivable'
+
+ @api.model
+ def get_deposit_month_received_report(self, params):
+ """
+ 押金本月实收报表:
+ - 管理费用类型为"押金"
+ - payout_date 在本月范围内(本月有收款)
+ - is_invalid = False
+ - 每条记录单独一行,金额 = delivered1
+ """
+ today = datetime.date.today()
+ this_month_first = today.replace(day=1)
+ if today.month == 12:
+ next_month_first = today.replace(year=today.year + 1, month=1, day=1)
+ else:
+ next_month_first = today.replace(month=today.month + 1, day=1)
+ this_month_last = next_month_first - datetime.timedelta(days=1)
+
+ deposit_type = self.env['yuthon.management.type'].search([('name', '=', '押金')], limit=1)
+
+ domain = [
+ ('payout_date', '>=', this_month_first),
+ ('payout_date', '<=', this_month_last),
+ ('is_invalid', '=', False),
+ ]
+ if deposit_type:
+ domain.append(('management_type_id', '=', deposit_type.id))
+
+ keyword = params.get("keyword")
+ if keyword:
+ domain += ['|', '|',
+ ('contract_id.contract_code', 'ilike', keyword),
+ ('property_name', 'ilike', keyword),
+ ('lessee_id.name', 'ilike', keyword),
+ ]
+
+ condition = params.get('condition')
+ partner_id = params.get('partner_id')
+ company_id = params.get('company_id')
+ 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")
+
+ rows = []
+ total_amount = 0.0
+ for idx, rec in enumerate(receivables, start=1):
+ amount = round(rec.delivered1 or 0.0, 2)
+ total_amount += amount
+ rows.append({
+ "序号": idx,
+ "合同编号": {
+ 'model': 'property.lease.contract',
+ 'id': rec.contract_id.id,
+ 'display_name': rec.contract_id.contract_code,
+ } if rec.contract_id else "",
+ "物业名称": rec.property_name or "",
+ "承租方名称": {
+ 'model': 'property.tenant.information',
+ 'id': rec.lessee_id.id,
+ 'display_name': rec.lessee_id.name,
+ } if rec.lessee_id else "",
+ "金额": amount,
+ "所属公司": rec.company_id.name if rec.company_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}
diff --git a/yuthon_report/models/deposit_pre_received_report.py b/yuthon_report/models/deposit_pre_received_report.py
new file mode 100644
index 000000000..98d7e70eb
--- /dev/null
+++ b/yuthon_report/models/deposit_pre_received_report.py
@@ -0,0 +1,83 @@
+import datetime
+
+from odoo import api, models
+
+
+class DepositPreReceivedReport(models.Model):
+ _inherit = 'property.accounts.receivable'
+
+ @api.model
+ def get_deposit_pre_received_report(self, params):
+ """
+ 押金前期实收报表:
+ - 管理费用类型为"押金"
+ - due_date < 本月第一天(前期账单)
+ - delivered1 > 0(有实收记录)
+ - is_invalid = False
+ - 每条记录单独一行,金额 = delivered1
+ """
+ today = datetime.date.today()
+ this_month_first = today.replace(day=1)
+
+ deposit_type = self.env['yuthon.management.type'].search([('name', '=', '押金')], limit=1)
+
+ domain = [
+ ('due_date', '<', this_month_first),
+ ('delivered1', '>', 0),
+ ('is_invalid', '=', False),
+ ]
+ if deposit_type:
+ domain.append(('management_type_id', '=', deposit_type.id))
+
+ keyword = params.get("keyword")
+ if keyword:
+ domain += ['|', '|',
+ ('contract_id.contract_code', 'ilike', keyword),
+ ('property_name', 'ilike', keyword),
+ ('lessee_id.name', 'ilike', keyword),
+ ]
+
+ condition = params.get('condition')
+ partner_id = params.get('partner_id')
+ company_id = params.get('company_id')
+ 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")
+
+ rows = []
+ total_amount = 0.0
+ for idx, rec in enumerate(receivables, start=1):
+ amount = round(rec.delivered1 or 0.0, 2)
+ total_amount += amount
+ rows.append({
+ "序号": idx,
+ "合同编号": {
+ 'model': 'property.lease.contract',
+ 'id': rec.contract_id.id,
+ 'display_name': rec.contract_id.contract_code,
+ } if rec.contract_id else "",
+ "物业名称": rec.property_name or "",
+ "承租方名称": {
+ 'model': 'property.tenant.information',
+ 'id': rec.lessee_id.id,
+ 'display_name': rec.lessee_id.name,
+ } if rec.lessee_id else "",
+ "金额": amount,
+ "所属公司": rec.company_id.name if rec.company_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}
diff --git a/yuthon_report/views/deposit_reports.xml b/yuthon_report/views/deposit_reports.xml
new file mode 100644
index 000000000..e94784054
--- /dev/null
+++ b/yuthon_report/views/deposit_reports.xml
@@ -0,0 +1,89 @@
+
+
+
+
+ 押金本月应收
+ receivable_report_client
+
+ {
+ "sideBar": true,
+ "report_config": {
+ "model": "property.accounts.receivable",
+ "method": "get_deposit_month_receivable_report",
+ "columns": [
+ {"headerName": "序号", "field": "序号", "flex": 0.5},
+ {"headerName": "合同编号", "field": "合同编号", "flex": 1.2},
+ {"headerName": "物业名称", "field": "物业名称", "flex": 2.5},
+ {"headerName": "承租方名称", "field": "承租方名称", "flex": 1.4},
+ {"headerName": "金额", "field": "金额", "flex": 1, "type": "number"},
+ {"headerName": "所属公司", "field": "所属公司", "flex": 1},
+ {"headerName": "管理员", "field": "管理员", "flex": 1}
+ ]
+ }
+ }
+
+
+
+
+ 押金前期实收
+ receivable_report_client
+
+ {
+ "sideBar": true,
+ "report_config": {
+ "model": "property.accounts.receivable",
+ "method": "get_deposit_pre_received_report",
+ "columns": [
+ {"headerName": "序号", "field": "序号", "flex": 0.5},
+ {"headerName": "合同编号", "field": "合同编号", "flex": 1.2},
+ {"headerName": "物业名称", "field": "物业名称", "flex": 2.5},
+ {"headerName": "承租方名称", "field": "承租方名称", "flex": 1.4},
+ {"headerName": "金额", "field": "金额", "flex": 1, "type": "number"},
+ {"headerName": "所属公司", "field": "所属公司", "flex": 1},
+ {"headerName": "管理员", "field": "管理员", "flex": 1}
+ ]
+ }
+ }
+
+
+
+
+ 押金本月实收
+ receivable_report_client
+
+ {
+ "sideBar": true,
+ "report_config": {
+ "model": "property.accounts.receivable",
+ "method": "get_deposit_month_received_report",
+ "columns": [
+ {"headerName": "序号", "field": "序号", "flex": 0.5},
+ {"headerName": "合同编号", "field": "合同编号", "flex": 1.2},
+ {"headerName": "物业名称", "field": "物业名称", "flex": 2.5},
+ {"headerName": "承租方名称", "field": "承租方名称", "flex": 1.4},
+ {"headerName": "金额", "field": "金额", "flex": 1, "type": "number"},
+ {"headerName": "所属公司", "field": "所属公司", "flex": 1},
+ {"headerName": "管理员", "field": "管理员", "flex": 1}
+ ]
+ }
+ }
+
+
+
+
+
+
+
+
diff --git a/yuthon_report/views/menu.xml b/yuthon_report/views/menu.xml
index 894760da4..7fc3212b5 100644
--- a/yuthon_report/views/menu.xml
+++ b/yuthon_report/views/menu.xml
@@ -131,7 +131,7 @@
sequence="1"
name="本月应收"
parent="yuthon_property_deposit_menu"
- action="action_current_receivable_rent_report"/>
+ action="action_deposit_month_receivable_report"/>
+ action="action_deposit_month_received_report"/>