diff --git a/yuthon_report/models/receivable_flow_report.py b/yuthon_report/models/receivable_flow_report.py index e09235fb5..0d1fd9ce7 100644 --- a/yuthon_report/models/receivable_flow_report.py +++ b/yuthon_report/models/receivable_flow_report.py @@ -36,6 +36,9 @@ class ReceivableFlowReport(models.Model): condition = params.get('condition') partner_id = params.get('partner_id') company_id = 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(('tenure_type', '=', condition)) @@ -43,6 +46,12 @@ class ReceivableFlowReport(models.Model): domain.append(('precinct_id', '=', partner_id)) if company_id: domain.append(('company_id', '=', company_id)) + if property_id: + domain.append(('property_ids', 'in', [property_id])) + if lessee_id: + domain.append(('lessee_id', '=', lessee_id)) + if contract_id: + domain.append(('contract_id', '=', contract_id)) receivables = self.sudo().search(domain, order="id asc") rec_ids = receivables.ids @@ -209,8 +218,18 @@ class ReceivableFlowReport(models.Model): "序号": idx, "租金id": rec.id, "应收日期": rec.due_date.strftime("%Y-%m-%d") if rec.due_date else "", - "应收金额": round(rec.original_amount, 2), - "收款总金额": round(total_collected, 2), + "应收金额": { + 'model': 'property.accounts.receivable', + 'display_name': str(round(rec.original_amount, 2)), + 'view_mode': 'tree', + 'domain': [('id', '=', rec.id)], + }, + "收款总金额": { + 'model': 'receivable.modify.line', + 'display_name': str(round(total_collected, 2)), + 'view_mode': 'tree', + 'domain': [('receivable_id', '=', rec.id), ('reconciliation_date', '!=', False)], + }, "未收": round(rec.submitted, 2), "收款金额": round(payment_amount, 2), "收款时间": payment_date.strftime("%Y-%m-%d") if payment_date else "", @@ -218,7 +237,12 @@ class ReceivableFlowReport(models.Model): "状态": charge_status, "违约金计算时间": billing_period, "违约天数": days_diff, - "违约金金额": round(penalty_amount, 2), + "违约金金额": { + 'model': 'property.accounts.receivable', + 'display_name': str(round(penalty_amount, 2)), + 'view_mode': 'tree', + 'domain': [('id', '=', rec.id)], + }, "违约金收款时间": penalty_payment_date.strftime("%Y-%m-%d") if penalty_payment_date else "", "违约金收款金额": round(total_penalty_collected, 2), "合同编号": { @@ -226,7 +250,11 @@ class ReceivableFlowReport(models.Model): 'id': rec.contract_id.id if rec.contract_id else None, 'display_name': rec.contract_id.contract_code if rec.contract_id else "", } if rec.contract_id else "", - "物业名称": rec.property_name or "", + "物业名称": { + 'model': 'yuthon.property', + 'id': rec.contract_id.lease_ids[0].address_id.id if rec.contract_id and rec.contract_id.lease_ids and rec.contract_id.lease_ids[0].address_id else None, + 'display_name': rec.property_name or "", + } if rec.contract_id and rec.contract_id.lease_ids and rec.contract_id.lease_ids[0].address_id else rec.property_name or "", "承租方名称": { 'model': 'property.tenant.information', 'id': rec.lessee_id.id if rec.lessee_id else None, @@ -236,8 +264,8 @@ class ReceivableFlowReport(models.Model): stats = [ {'name': '记录总数', 'amount': len(rows)}, - {'name': '应收总额', 'amount': round(sum(row["应收金额"] for row in rows), 2)}, - {'name': '已收总额', 'amount': round(sum(row["收款总金额"] for row in rows), 2)}, + {'name': '应收总额', 'amount': round(sum(float(row["应收金额"]['display_name']) for row in rows), 2)}, + {'name': '已收总额', 'amount': round(sum(float(row["收款总金额"]['display_name']) for row in rows), 2)}, {'name': '未收总额', 'amount': round(sum(row["未收"] for row in rows), 2)}, ] diff --git a/yuthon_report/static/src/components/yuthon_report/receivable_report.js b/yuthon_report/static/src/components/yuthon_report/receivable_report.js index 284006f51..4224bad25 100644 --- a/yuthon_report/static/src/components/yuthon_report/receivable_report.js +++ b/yuthon_report/static/src/components/yuthon_report/receivable_report.js @@ -33,6 +33,9 @@ class ReceivableReport extends Component { selectPartner: {}, selectCompany: {}, selectManagementType: {}, + selectProperty: {}, + selectLessee: {}, + selectContract: {}, condition: false, conditions: [ {'name': '', 'value': ''}, @@ -142,13 +145,15 @@ class ReceivableReport extends Component { * 穿透渲染器:将对象格式的字段渲染为可点击的链接 * 如果字段值是对象(包含 model、id、display_name),则渲染为可点击链接 * 否则直接显示原值 + * 支持 view_mode: 'tree' + domain 打开 tree 弹窗 + * 支持 view_mode: 'form' 或默认打开 form 弹窗 */ linkRender(params) { if (!params.value) return ''; - // 如果是对象格式(包含 model 和 id),渲染为可点击链接 - if (typeof params.value === 'object' && params.value.model && params.value.id) { - const { model, id, display_name } = params.value; + // 如果是对象格式(包含 model),渲染为可点击链接 + if (typeof params.value === 'object' && params.value.model) { + const { model, id, display_name, view_mode, domain, view_id } = params.value; const el = document.createElement('div'); el.className = 'o_record_cell'; @@ -156,13 +161,25 @@ class ReceivableReport extends Component { el.classList.add('btn'); el.classList.add('btn-link'); el.onclick = () => { - params.context.actionService.doAction({ - type: 'ir.actions.act_window', - res_model: model, - res_id: id, - views: [[false, 'form'], [false, 'search']], - target: 'new' - }); + if (view_mode === 'tree') { + // tree 弹窗:用 domain 过滤多条记录 + params.context.actionService.doAction({ + type: 'ir.actions.act_window', + res_model: model, + views: [[view_id || false, 'tree']], + domain: domain || [], + target: 'new', + }); + } else { + // form 弹窗:打开单条记录 + params.context.actionService.doAction({ + type: 'ir.actions.act_window', + res_model: model, + res_id: id, + views: [[false, 'form'], [false, 'search']], + target: 'new' + }); + } }; return el; @@ -292,6 +309,9 @@ class ReceivableReport extends Component { partner_id: this.state.selectPartner?.id, company_id: this.state.selectCompany?.id, management_type_id: this.state.selectManagementType?.id || false, + property_id: this.state.selectProperty?.id || false, + lessee_id: this.state.selectLessee?.id || false, + contract_id: this.state.selectContract?.id || false, }; } else { let startDate = formatDate(this.state.startDate, {format: "yyyy-MM-dd"}) @@ -304,6 +324,9 @@ class ReceivableReport extends Component { partner_id: this.state.selectPartner?.id, company_id: this.state.selectCompany?.id, management_type_id: this.state.selectManagementType?.id || false, + property_id: this.state.selectProperty?.id || false, + lessee_id: this.state.selectLessee?.id || false, + contract_id: this.state.selectContract?.id || false, }; } const result = await this.serviceOrm.call( @@ -376,6 +399,21 @@ class ReceivableReport extends Component { this._applyManagementTypeFilter(); } + async onUpdateProperty(v) { + this.state.selectProperty = v[0] || {}; + await this.onSearch(); + } + + async onUpdateLessee(v) { + this.state.selectLessee = v[0] || {}; + await this.onSearch(); + } + + async onUpdateContract(v) { + this.state.selectContract = v[0] || {}; + await this.onSearch(); + } + _applyManagementTypeFilter() { if (!this.grid) return; const typeName = this.state.selectManagementType?.display_name || ''; diff --git a/yuthon_report/static/src/components/yuthon_report/receivable_report.xml b/yuthon_report/static/src/components/yuthon_report/receivable_report.xml index cc576b665..9229e82a8 100644 --- a/yuthon_report/static/src/components/yuthon_report/receivable_report.xml +++ b/yuthon_report/static/src/components/yuthon_report/receivable_report.xml @@ -109,6 +109,45 @@ /> + +