Merge pull request !6774 from 李鹏宇/dev
This commit is contained in:
李鹏宇
2025-12-01 09:24:23 +00:00
committed by Gitee
10 changed files with 361 additions and 6 deletions
@@ -7,8 +7,8 @@
<tree string="财务数据表项目配置" editable="bottom">
<field name="sequence"/>
<field name="name"/>
<field name="employee_ids" widget="many2many_tags"/>
<field name="user_role_ids" widget="many2many_tags"/>
<field name="employee_ids" widget="many2many_tags" options="{'no_create': True}"/>
<field name="user_role_ids" widget="many2many_tags" options="{'no_create': True}"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="is_enable"/>
@@ -27,8 +27,8 @@
<tree string="信息汇总表项目配置" editable="bottom">
<field name="sequence"/>
<field name="name"/>
<field name="employee_ids" widget="many2many_tags"/>
<field name="user_role_ids" widget="many2many_tags"/>
<field name="employee_ids" widget="many2many_tags" options="{'no_create': True}"/>
<field name="user_role_ids" widget="many2many_tags" options="{'no_create': True}"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="is_enable"/>
@@ -47,6 +47,17 @@ class PropertyBankStatements(models.Model):
change_amount = fields.Float(string='修改金额')
receivable_modify_ids = fields.One2many('receivable.modify.line', 'bank_id', string='修改应收单')
@api.onchange('extract')
def _onchange_extract_set_bank_state(self):
for rec in self:
if rec.extract and '结息' in rec.extract:
rec.bank_state = 'other'
@api.onchange('remake')
def _onchange_remake_set_bank_state(self):
for rec in self:
if rec.remake and '党费' in rec.remake:
rec.bank_state = 'other'
@api.depends('yes_amount', 'original_amount')
def _compute_no_amount(self):
@@ -209,6 +209,7 @@ class PropertyLeaseContract(models.Model):
number = fields.Integer(string="次数", default=0)
total_area = fields.Float(string="总面积", digits=(16, 4))
not_received = fields.Float(string="未收", compute="_compute_contract_count")
month_received = fields.Float(string="本月已收")
actual_receivable = fields.Float(string="实际应收")
now_receivable = fields.Float(string="当期应收")
total_receivable = fields.Float(string="总已收")
@@ -584,7 +584,7 @@ class PropertyReconciliationWizard(models.Model):
})
if existing_record:
receivable_id = existing_record.id
receivable_id = existing_record
self.env['receivable.modify.line'].create({
'bank_id': rec.bank_id.id,
'not_collected': line.rent,
+3
View File
@@ -12,6 +12,7 @@
'views/ledger_report_views.xml',
'views/receivable_report_views.xml',
'views/receivables_message_report_views.xml',
'views/yuthon_contract_report_views.xml',
'views/yuthon_report_res_partner.xml',
],
'installable': True,
@@ -33,6 +34,8 @@
'yuthon_report/static/src/components/yuthon_report/yuthon_report.js',
'yuthon_report/static/src/components/yuthon_report/yuthon_report.xml',
'yuthon_report/static/src/components/yuthon_report/yuthon_contract_report.js',
'yuthon_report/static/src/components/yuthon_report/yuthon_contract_report.xml',
'yuthon_report/static/src/components/yuthon_report/receivable_message_report.js',
'yuthon_report/static/src/components/yuthon_report/receivable_message.xml',
'yuthon_report/static/src/components/yuthon_report/yuthon_report.scss',
+2 -1
View File
@@ -2,4 +2,5 @@
from . import res_partner
from . import ledger_report
from . import receivable_report
from . import receivables_message_report
from . import receivables_message_report
from . import yuthon_contract_report
@@ -0,0 +1,81 @@
import datetime
from odoo import fields, models, api
class YuthonContractReport(models.Model):
_inherit = 'property.lease.contract'
_description = '合同信息报表'
@api.model
def get_contract_info_report(self, params):
"""
生成合同信息报表
:param params: 筛选参数(keyword/date_start/date_end/company_id/manager_id等)
:return: 合同信息列表
"""
domain = []
if params.get("date_start"):
date_start = datetime.datetime.fromisoformat(params.get("date_start")).date()
domain.append(("actual_start_time", ">=", date_start))
if params.get("date_end"):
date_end = datetime.datetime.fromisoformat(params.get("date_end")).date()
domain.append(("actual_end_time", "<=", date_end))
if params.get('lessor_id'):
domain.append(('lessor_id', '=', params['lessor_id']))
if params.get("precinct_id"):
domain.append(("precinct_id", "=", params.get("precinct_id")))
contracts = self.search(domain, limit=1000)
report_data = []
for rec in contracts:
rent_free_month = rec.rent_free_period_month or 0
rent_free_days = rec.rent_free_period_days or 0
if rent_free_month > 0 and rent_free_days > 0:
rent_free_text = f"{rent_free_month}月{rent_free_days}天"
elif rent_free_month > 0:
rent_free_text = f"{rent_free_month}月"
elif rent_free_days > 0:
rent_free_text = f"{rent_free_days}天"
else:
rent_free_text = "0个月"
if rec.term_start_time and rec.term_end_time:
contract_tenure = f"{rec.term_start_time.strftime('%Y-%m-%d')} 至 {rec.term_end_time.strftime('%Y-%m-%d')}"
elif rec.term_start_time:
contract_tenure = f"{rec.term_start_time.strftime('%Y-%m-%d')} 至 未设置结束时间"
elif rec.term_end_time:
contract_tenure = f"未设置开始时间 至 {rec.term_end_time.strftime('%Y-%m-%d')}"
else:
contract_tenure = "未设置租期"
if rec.actual_start_time and rec.actual_end_time:
actual_tenure = f"{rec.actual_start_time.strftime('%Y-%m-%d')} 至 {rec.actual_end_time.strftime('%Y-%m-%d')}"
elif rec.actual_start_time:
actual_tenure = f"{rec.actual_start_time.strftime('%Y-%m-%d')} 至 未结束"
elif rec.actual_end_time:
actual_tenure = f"未设置实际开始时间 至 {rec.actual_end_time.strftime('%Y-%m-%d')}"
else:
actual_tenure = "未设置实际租期"
report_data.append({
"物业名称": rec.property_name or "",
"承租方": rec.lessee_id.name or "" if rec.lessee_id else "",
"递增规律": rec.increment_percentage or "",
"免租期": rent_free_text,
"面积": f"{rec.total_area} ㎡" if rec.total_area else "0 ㎡",
"押金": rec.deposit or 0.0,
"租金": rec.rent or 0.0,
"未收": round(rec.not_received, 2),
"本月已收": rec.month_received,
"违约金": rec.percentage_damages or 0.0,
"实际租期": actual_tenure,
"合同租期": contract_tenure,
"所属公司": rec.lessor_id.name or "" if rec.lessor_id else "",
"负责人": rec.admin_id.name if rec.admin_id else " ",
"合同编号": rec.contract_code or ""
})
return report_data
@@ -0,0 +1,137 @@
/** @odoo-module */
import {registry} from "@web/core/registry";
import {Component, onMounted, useRef, useState} from "@odoo/owl";
import {useService} from "@web/core/utils/hooks";
import {standardActionServiceProps} from "@web/webclient/actions/action_service";
import {DateTimeInput} from "@web/core/datetime/datetime_input";
import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
import {formatDate} from "@web/core/l10n/dates";
const {DateTime} = luxon;
class ContractInfoReport extends Component {
setup() {
this.gridRef = useRef("grid");
console.log("合同信息报表配置:", this.props.action.context.report_config);
this.serviceOrm = useService("orm");
this.notification = useService("notification");
this.state = useState({
startDate: DateTime.now().startOf("month"),
endDate: DateTime.now().endOf("month"),
selectLessor: {},
selectPrecinct: {},
});
this.config = this.props.action.context.report_config || {};
onMounted(async () => {
this.gridOptions = {
localeText: AG_GRID_LOCALE_CN,
theme: agGrid?.themeMaterial || "ag-theme-alpine",
columnDefs: this.config.columns || [],
rowData: [],
sideBar: this.config.sideBar !== false,
enableCharts: true, // 启用图表功能
cellSelection: true, // 支持单元格选择
defaultColDef: {
sortable: true, // 支持排序
filter: true, // 支持筛选
width: 200,
minWidth: 150,
flex: false,
resizable: false
},
getContextMenuItems: (params) => {
const items = params.defaultItems.slice();
items.push("chartRange");
return items;
},
};
if (this.gridRef.el) {
this.grid = agGrid.createGrid(this.gridRef.el, this.gridOptions);
await this.onSearch();
}
});
}
// -------------------------- 筛选器配置 --------------------------
getDomainLessor() {
return [];
}
// 所属片区筛选域
getDomainPrecinct() {
return [];
}
// -------------------------- 筛选事件处理 --------------------------
async onUpdateLessor(v) {
console.log("选择所属公司:", v);
this.state.selectLessor = v[0] || {};
}
async onUpdatePrecinct(v) {
console.log("选择所属片区:", v);
this.state.selectPrecinct = v[0] || {};
}
async onChangeStartDate(date) {
console.log("实际开始日期变更:", date);
this.state.startDate = date || false;
}
async onChangeEndDate(date) {
console.log("实际结束日期变更:", date);
this.state.endDate = date || false;
}
// -------------------------- 核心业务逻辑 --------------------------
async onSearch() {
console.log("筛选参数:", this.state);
const startDate = this.state.startDate
? formatDate(this.state.startDate, {format: "yyyy-MM-dd"})
: false;
const endDate = this.state.endDate
? formatDate(this.state.endDate, {format: "yyyy-MM-dd"})
: false;
const params = {
date_start: startDate,
date_end: endDate,
lessor_id: this.state.selectLessor?.id || false,
precinct_id: this.state.selectPrecinct?.id || false,
};
try {
const result = await this.serviceOrm.call(
this.config.model,
this.config.method,
[params]
);
this.grid.setGridOption('rowData', result);
} catch (e) {
console.error("获取收款信息表数据失败:", e);
}
}
onExportExcel() {
this.grid.exportDataAsExcel({
fileName: "合同信息报表.xlsx",
sheetName: "合同台账"
});
}
}
// -------------------------- 组件配置 --------------------------
ContractInfoReport.props = {...standardActionServiceProps};
ContractInfoReport.template = "yuthon_report.ContractInfoReport"; // 模板名需与XML模板ID一致
ContractInfoReport.components = {
DateTimeInput,
Many2XAutocomplete
};
registry.category("actions").add("contract_info_report_client", ContractInfoReport);
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="yuthon_report.ContractInfoReport">
<div class="container-fluid d-flex flex-column h-100 mt-2 pb-3">
<div class="card mb-2">
<div class="card-body">
<div class="row mb-2" t-ref="search_area">
<!--日期 -->
<div class="col-3">
<label>日期范围</label>
<div class="d-flex align-items-center gap-2">
<DateTimeInput
range="true"
value="state.startDate"
type="'date'"
placeholder="fromPlaceholder"
onChange="(date) => this.onChangeStartDate(date)"
/>
<i class="oi oi-arrow-right"></i>
<DateTimeInput
range="true"
value="state.endDate"
type="'date'"
placeholder="toPlaceholder"
onChange="(date) => this.onChangeEndDate(date)"
/>
</div>
</div>
<!-- 所属公司 -->
<div class="col-3">
<label>所属公司</label>
<Many2XAutocomplete
value="state.selectLessor?.display_name"
getDomain="getDomainLessor"
resModel="'yuthon.property.company'"
fieldString="'所属公司'"
activeActions="{}"
update.bind="onUpdateLessor"
/>
</div>
<div class="col-3">
<label>负责人</label>
<Many2XAutocomplete
value="state.selectPrecinct?.display_name"
getDomain="getDomainPrecinct"
resModel="'yuthon.precinct.message'"
fieldString="'负责人'"
activeActions="{}"
update.bind="onUpdatePrecinct"
/>
</div>
<div class="col-12 mt-3 d-flex justify-content-end gap-2">
<button class="btn btn-primary" t-on-click="onSearch">搜索</button>
<button class="btn btn-success" t-on-click="onExportExcel">导出</button>
</div>
</div>
</div>
</div>
<div class="row flex-grow-1">
<div class="col-12 h-100">
<div class="ag-theme-alpine w-100 h-100" t-ref="grid"></div>
</div>
</div>
</div>
</t>
</templates>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_yuthon_contract_report_report" model="ir.actions.client">
<field name="name">合同信息报表</field>
<field name="tag">contract_info_report_client</field>
<field name="context">
{
"sideBar": true,
"report_config": {
"model": "property.lease.contract",
"method": "get_contract_info_report",
"columns": [
{"headerName": "物业名称", "field": "物业名称", "flex": 1},
{"headerName": "承租方", "field": "承租方", "flex": 1},
{"headerName": "递增规律", "field": "递增规律", "flex": 1},
{"headerName": "免租期", "field": "免租期", "flex": 1},
{"headerName": "面积(㎡)", "field": "面积", "flex": 1},
{"headerName": "押金", "field": "押金", "flex": 1, "type": "number"},
{"headerName": "租金", "field": "租金", "flex": 1, "type": "number"},
{"headerName": "未收", "field": "未收", "flex": 1, "type": "number"},
{"headerName": "本月已收", "field": "本月已收", "flex": 1, "type": "number"},
{"headerName": "违约金", "field": "违约金", "flex": 1, "type": "number"},
{"headerName": "实际租期", "field": "实际租期", "flex": 1.5},
{"headerName": "合同租期", "field": "合同租期", "flex": 1.5},
{"headerName": "所属公司", "field": "所属公司", "flex": 1},
{"headerName": "负责人", "field": "负责人", "flex": 1},
{"headerName": "合同编号", "field": "合同编号", "flex": 1}
],
"filters": [
{"name": "date_start", "label": "合同开始日期", "type": "date"},
{"name": "date_end", "label": "合同结束日期", "type": "date"},
{"name": "lessor_id", "label": "所属公司", "type": "many2one", "model": "yuthon.property.company"},
{"name": "admin_id", "label": "负责人", "type": "many2one", "model": "res.users"}
]
}
}
</field>
</record>
<menuitem
id="menu_yuthon_contract_report"
name="合同信息报表"
parent="yuthon_property_approval.property_approval_report_menu"
action="action_yuthon_contract_report_report"
sequence="10"/>
</data>
</odoo>