diff --git a/ylhc_list/__init__.py b/ylhc_list/__init__.py
new file mode 100644
index 000000000..40a96afc6
--- /dev/null
+++ b/ylhc_list/__init__.py
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/ylhc_list/__manifest__.py b/ylhc_list/__manifest__.py
new file mode 100644
index 000000000..3d1d2b275
--- /dev/null
+++ b/ylhc_list/__manifest__.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': "ylhc_list",
+
+ 'summary': "advance list for odoo",
+
+ 'description': """
+ advance list
+ fixed column list
+ """,
+
+ 'author': "crax",
+ 'website': "https://www.ylhc.com",
+
+ 'category': 'apps/list',
+ 'version': '17.0.0.1',
+
+ 'depends': ['base', 'web'],
+ 'price': 9999,
+
+ 'data': [],
+
+ 'assets': {
+ 'web.assets_backend': [
+ 'ylhc_list/static/src/*.*'
+ ]
+ }
+}
+
diff --git a/ylhc_list/security/ir.model.access.csv b/ylhc_list/security/ir.model.access.csv
new file mode 100644
index 000000000..416457828
--- /dev/null
+++ b/ylhc_list/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_xc_list_xc_list,xc_list.xc_list,model_xc_list_xc_list,base.group_user,1,1,1,1
diff --git a/ylhc_list/static/description/icon.png b/ylhc_list/static/description/icon.png
new file mode 100644
index 000000000..bcbdbf091
Binary files /dev/null and b/ylhc_list/static/description/icon.png differ
diff --git a/ylhc_list/static/src/ylhc_list_controller.js b/ylhc_list/static/src/ylhc_list_controller.js
new file mode 100644
index 000000000..ed845f066
--- /dev/null
+++ b/ylhc_list/static/src/ylhc_list_controller.js
@@ -0,0 +1,9 @@
+/** @odoo-module **/
+
+import { _t } from "@web/core/l10n/translation";
+import { ListController } from "@web/views/list/list_controller";
+
+export class YlhcListController extends ListController {
+
+}
+
diff --git a/ylhc_list/static/src/ylhc_list_renderer.js b/ylhc_list/static/src/ylhc_list_renderer.js
new file mode 100644
index 000000000..88e8806a0
--- /dev/null
+++ b/ylhc_list/static/src/ylhc_list_renderer.js
@@ -0,0 +1,136 @@
+/** @odoo-module **/
+
+import { ListRenderer } from "@web/views/list/list_renderer";
+import { _t } from "@web/core/l10n/translation";
+import { xml } from "@odoo/owl";
+
+export class YlhcListRenderer extends ListRenderer {
+
+ setup() {
+ super.setup();
+
+ this.hasExpander = this._hasExpander();
+ this.subRowTemplate = this.getSubRowTemplate();
+ }
+
+ /**
+ * check if tree_column in column option
+ */
+ isTreeColumn(column) {
+ return column.options.tree_column;
+ }
+
+ isExpanderColumn(column) {
+ return column.options.expander;
+ }
+
+ _hasExpander() {
+ let columns = this.state.columns || [];
+ for (let i = 0; i < columns.length; i++) {
+ if (this.isExpanderColumn(columns[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ getSubRowTemplate() {
+ let columns = this.state.columns || [];
+ for (let i = 0; i < columns.length; i++) {
+ if (this.isExpanderColumn(columns[i])) {
+ let sub_row_template = columns[i].options.sub_row_template;
+ if (columns[i].options.sub_row_template) {
+ return sub_row_template;
+ }
+ }
+ }
+ return xml`
can find the sub rwo template !!!
`;
+ }
+
+ getSubRowColumnSpan() {
+ let columns = this.state.columns || [];
+ if (this.hasSelectors) {
+ return columns.length + 1;
+ }
+ return columns.length;
+ }
+
+ /**
+ * parent_path is used to check if the column is a tree column
+ */
+ checkParentPath() {
+ let columns = this.state.columns || [];
+ // find parent path
+ let parentPath = columns.find(column => column.name == 'parent_path');
+ if (parentPath) {
+ return true;
+ }
+ return false;
+ }
+
+ getTreeLevel(record) {
+ let parentPath = record.data.parent_path;
+ if (parentPath) {
+ return parentPath.split('/').length;
+ }
+ return 0;
+ }
+
+ /**
+ * get children of a record
+ * @param {*} record
+ * */
+ hasChildren(record) {
+ let records = this.props.list.records;
+ let index = records.indexOf(record);
+ let parent_path = record.data.parent_path;
+ for (let i = index + 1; i < records.length; i++) {
+ if (records[i].data.parent_path.startsWith(parent_path)) {
+ return true
+ } else {
+ break;
+ }
+ }
+ return false;
+ }
+
+ getChildren(record) {
+ let records = this.props.list.records;
+ let index = records.indexOf(record);
+ let parent_path = record.data.parent_path;
+ let children = [];
+ for (let i = index + 1; i < records.length; i++) {
+ if (records[i].data.parent_path.startsWith(parent_path)) {
+ children.push(records[i]);
+ } else {
+ break;
+ }
+ }
+ return children;
+ }
+
+ /**
+ * click the expand button
+ **/
+ toggleRecord(record) {
+ let children = this.getChildren(record);
+ if (record.folded) {
+ for (let i = 0; i < children.length; i++) {
+ children[i].hide = false;
+ }
+ } else {
+ for (let i = 0; i < children.length; i++) {
+ children[i].hide = true;
+ }
+ }
+ record.folded = !record.folded;
+ this.render();
+ }
+
+ toggleExpander(record) {
+ record.sub_row_folded = !record.sub_row_folded;
+ this.render();
+ }
+}
+
+YlhcListRenderer.recordRowTemplate = "ylhc_list.ListRenderer.RecordRow";
diff --git a/ylhc_list/static/src/ylhc_list_renderer.xml b/ylhc_list/static/src/ylhc_list_renderer.xml
new file mode 100644
index 000000000..940a22779
--- /dev/null
+++ b/ylhc_list/static/src/ylhc_list_renderer.xml
@@ -0,0 +1,154 @@
+
+
+
+
+
+ |
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+ |
+
+
+
+
+ |
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+ |
+
+ |
+
+
+
+ |
+
+ |
+
+
+
+
+
+
+
Product Information
+
+
+ | Product Name |
+ Example Product |
+
+
+ | Product Description |
+ This is an example product used for demonstration purposes. |
+
+
+ | Main Features |
+ Feature 1, Feature 2, Feature 3 |
+
+
+ | Price |
+ $100 |
+
+
+ | Stock Quantity |
+ 50 |
+
+
+ | Product Image |
+  |
+
+
+ | Additional Information |
+ Any additional information can go here. |
+
+
+
+
+
+
diff --git a/ylhc_list/static/src/ylhc_list_view.js b/ylhc_list/static/src/ylhc_list_view.js
new file mode 100644
index 000000000..e60674cec
--- /dev/null
+++ b/ylhc_list/static/src/ylhc_list_view.js
@@ -0,0 +1,21 @@
+/** @odoo-module */
+
+import { registry } from "@web/core/registry";
+import { ListArchParser } from "@web/views/list/list_arch_parser";
+import { listView } from "@web/views/list/list_view";
+
+import { YlhcListController } from "./ylhc_list_controller";
+import { YlhcListRenderer } from "./ylhc_list_renderer";
+import { YlhcRelationalModel } from "./ylhc_relation_model";
+
+export const YlhcListView = {
+ ...listView,
+
+ Controller: YlhcListController,
+ Renderer: YlhcListRenderer,
+
+ ArchParser: ListArchParser,
+ Model: YlhcRelationalModel,
+};
+
+registry.category("views").add("ylhc_list_view", YlhcListView);
diff --git a/ylhc_list/static/src/ylhc_list_view.scss b/ylhc_list/static/src/ylhc_list_view.scss
new file mode 100644
index 000000000..b3bbdb6e6
--- /dev/null
+++ b/ylhc_list/static/src/ylhc_list_view.scss
@@ -0,0 +1,9 @@
+
+.tree_toggle {
+ display: inline-block;
+ text-align: right;
+}
+
+.expander_toggle {
+ display: inline-block;
+}
\ No newline at end of file
diff --git a/ylhc_list/static/src/ylhc_record.js b/ylhc_list/static/src/ylhc_record.js
new file mode 100644
index 000000000..b4c29eb83
--- /dev/null
+++ b/ylhc_list/static/src/ylhc_record.js
@@ -0,0 +1,21 @@
+/* @odoo-module */
+
+import { _t } from "@web/core/l10n/translation";
+import { Record } from "@web/model/relational_model/record";
+
+export class YlhcRecord extends Record {
+ /**
+ * @param {any} env
+ * @param {any} model
+ * @param {any} id
+ * @param {any} fields
+ * @param {any} options
+ */
+ constructor(env, model, id, fields, options) {
+ super(env, model, id, fields, options);
+ this._isYlhcRecord = true;
+ this.folded = false;
+ this.sub_row_folded = true;
+ this.hide = false;
+ }
+}
diff --git a/ylhc_list/static/src/ylhc_relation_model.js b/ylhc_list/static/src/ylhc_relation_model.js
new file mode 100644
index 000000000..80a9c960c
--- /dev/null
+++ b/ylhc_list/static/src/ylhc_relation_model.js
@@ -0,0 +1,23 @@
+/* @odoo-module */
+
+import { RelationalModel } from "@web/model/relational_model/relational_model";
+import { YlhcRecord } from "./ylhc_record";
+
+
+export class YlhcRelationalModel extends RelationalModel {
+
+ static Record = YlhcRecord;
+
+ /**
+ * @param {any} env
+ * @param {any} modelInfo
+ * @param {any} params
+ */
+ constructor(env, modelInfo, params) {
+ super(env, modelInfo, params);
+ this._isYlhcRelationalModel = true;
+ }
+}
+
+
+
diff --git a/yuthon_property/models/yuthon_property.py b/yuthon_property/models/yuthon_property.py
index c437043e1..64c805d64 100644
--- a/yuthon_property/models/yuthon_property.py
+++ b/yuthon_property/models/yuthon_property.py
@@ -48,6 +48,7 @@ class YuthonProperty(models.Model):
management_area = fields.Float(string="管理面积")
rentable_area = fields.Float(string="可租面积")
is_meter = fields.Boolean(string="是否支持多个水表")
+
is_electricity_meter = fields.Boolean(string="是否支持多个电表")
is_hvac = fields.Boolean(string="是否中央空调")
manage_standard = fields.Char(string="物业管理费标准")