diff --git a/yuthon_report/__manifest__.py b/yuthon_report/__manifest__.py index 0add3096f..0dd3c1ccd 100644 --- a/yuthon_report/__manifest__.py +++ b/yuthon_report/__manifest__.py @@ -11,6 +11,7 @@ 'views/pre_arrears_report.xml', 'views/pre_advance_report.xml', 'views/month_receivable_report.xml', + 'views/total_received_report.xml', 'views/penalty_arrears_report.xml', 'views/penalty_month_received_report.xml', 'views/penalty_year_cum_report.xml', diff --git a/yuthon_report/models/__init__.py b/yuthon_report/models/__init__.py index a5840c504..d2816f2c3 100644 --- a/yuthon_report/models/__init__.py +++ b/yuthon_report/models/__init__.py @@ -17,6 +17,7 @@ from . import staff_position_report from . import pre_arrears_report from . import pre_advance_report from . import month_receivable_report +from . import total_received_report from . import penalty_arrears_report from . import penalty_month_received_report from . import penalty_year_cum_report diff --git a/yuthon_report/models/total_received_report.py b/yuthon_report/models/total_received_report.py new file mode 100644 index 000000000..85fc4a5b2 --- /dev/null +++ b/yuthon_report/models/total_received_report.py @@ -0,0 +1,90 @@ +import datetime +import calendar + +from odoo import api, models + + +class TotalReceivedReport(models.Model): + _inherit = 'receivable.modify.line' + + @api.model + def get_total_received_report(self, params): + """实收总额:查询月当月,应收类型不为押金和违约金的已对金额""" + domain = [('reconciliation_date', '!=', False)] + + # 单月日期过滤 + 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), + ] + + # 排除押金和违约金 + domain += [ + ('receivable_id.management_type_id.name', 'not in', ['押金', '违约金']), + ] + + 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), + ] + + lines = self.search(domain, order='reconciliation_date asc') + + 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.original_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, + } + + rows.append({ + '序号': idx, + '物业名称': property_val, + '合同编号': contract_val, + '承租方名称': lessee_val, + '金额': amount, + '所属公司': contract.lessor_id.name if contract and contract.lessor_id else '', + '管理员': contract.admin_id.name if contract and contract.admin_id else '', + }) + + stats = [{'name': '合计', 'amount': round(total_amount, 2)}] + return {'rows': rows, 'stats': stats} diff --git a/yuthon_report/views/menu.xml b/yuthon_report/views/menu.xml index b4d3c14af..0a2159aa3 100644 --- a/yuthon_report/views/menu.xml +++ b/yuthon_report/views/menu.xml @@ -45,9 +45,9 @@ action="action_month_receivable_report"/> + action="action_total_received_report"/> + + + + 实收总额 + receivable_report_client + + { + "sideBar": true, + "report_config": { + "model": "receivable.modify.line", + "method": "get_total_received_report", + "dateMode": "single", + "columns": [ + {"headerName": "序号", "field": "序号", "width": 45, "flex": 0, "pinned": "left"}, + {"headerName": "物业名称", "field": "物业名称", "flex": 2.5}, + {"headerName": "合同编号", "field": "合同编号", "flex": 1.2}, + {"headerName": "承租方名称", "field": "承租方名称", "flex": 1.6}, + {"headerName": "金额", "field": "金额", "flex": 1, "type": "number"}, + {"headerName": "所属公司", "field": "所属公司", "flex": 1.2}, + {"headerName": "管理员", "field": "管理员", "flex": 1} + ] + } + } + + + +