diff --git a/estate/views/res_users_views.xml b/estate/views/res_users_views.xml
index f1928d5c7..c2b32c6d3 100644
--- a/estate/views/res_users_views.xml
+++ b/estate/views/res_users_views.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/many2many_tags_preview/.gitignore b/many2many_tags_preview/.gitignore
deleted file mode 100644
index 47e0bb75b..000000000
--- a/many2many_tags_preview/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-__pycache__/
-*.py[cod]
-*.pyo
-*.pyd
-*.so
\ No newline at end of file
diff --git a/many2many_tags_preview/LICENSE b/many2many_tags_preview/LICENSE
deleted file mode 100644
index 7a5c68e71..000000000
--- a/many2many_tags_preview/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Odoo Proprietary License v1.0
-
-This software and associated files (the "Software") may only be used (executed,
-modified, executed after modifications) if you have purchased a valid license
-from the authors, typically via Odoo Apps, or if you have received a written
-agreement from the authors of the Software (see the COPYRIGHT file).
-
-You may develop Odoo modules that use the Software as a library (typically
-by depending on it, importing it and using its resources), but without copying
-any source code or material from the Software. You may distribute those
-modules under the license of your choice, provided that this license is
-compatible with the terms of the Odoo Proprietary License (For example:
-LGPL, MIT, or proprietary licenses similar to this one).
-
-It is forbidden to publish, distribute, sublicense, or sell copies of the Software
-or modified copies of the Software.
-
-The above copyright notice and this permission notice must be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/many2many_tags_preview/README.md b/many2many_tags_preview/README.md
index c7a644719..c976dfb98 100644
--- a/many2many_tags_preview/README.md
+++ b/many2many_tags_preview/README.md
@@ -51,15 +51,15 @@ In your Odoo view XML file, use the widget with options:
### Form View
-
+
### List View
-
+
### Kanban View
-
+
---
diff --git a/many2many_tags_preview/many2many_tags_preview/__init__.py b/many2many_tags_preview/__init__.py
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/__init__.py
rename to many2many_tags_preview/__init__.py
diff --git a/many2many_tags_preview/many2many_tags_preview/__manifest__.py b/many2many_tags_preview/__manifest__.py
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/__manifest__.py
rename to many2many_tags_preview/__manifest__.py
diff --git a/many2many_tags_preview/many2many_tags_preview/LICENSE b/many2many_tags_preview/many2many_tags_preview/LICENSE
deleted file mode 100644
index 7a5c68e71..000000000
--- a/many2many_tags_preview/many2many_tags_preview/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Odoo Proprietary License v1.0
-
-This software and associated files (the "Software") may only be used (executed,
-modified, executed after modifications) if you have purchased a valid license
-from the authors, typically via Odoo Apps, or if you have received a written
-agreement from the authors of the Software (see the COPYRIGHT file).
-
-You may develop Odoo modules that use the Software as a library (typically
-by depending on it, importing it and using its resources), but without copying
-any source code or material from the Software. You may distribute those
-modules under the license of your choice, provided that this license is
-compatible with the terms of the Odoo Proprietary License (For example:
-LGPL, MIT, or proprietary licenses similar to this one).
-
-It is forbidden to publish, distribute, sublicense, or sell copies of the Software
-or modified copies of the Software.
-
-The above copyright notice and this permission notice must be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/many2many_tags_preview/many2many_tags_preview/README.md b/many2many_tags_preview/many2many_tags_preview/README.md
deleted file mode 100644
index c976dfb98..000000000
--- a/many2many_tags_preview/many2many_tags_preview/README.md
+++ /dev/null
@@ -1,79 +0,0 @@
-# Many2Many Tags Preview
-
-🚀 **Odoo Module** — 快速预览 Many2Many 字段的标签,提升导航效率。
-This module enhances the standard `many2many_tags` widget in Odoo, allowing instant preview and quick access to related records in **List, Form, and Kanban** views.
-
----
-
-## ✨ Features
-
-- 🔍 **Quick Preview**
- Preview related records directly from many2many tags.
-
-- ⚙️ **Custom Form View**
- Support `context={'open_form_view': 'xml_id'}` to open a specific form view.
-
-- 🔄 **Seamless Integration**
- Fully compatible with Odoo native `many2many_tags`.
-
-- 📱 **Multi-View Support**
- Works in **List**, **Form**, and **Kanban** views.
-
----
-
-## 📦 Installation
-
-1. Clone this repository into your Odoo `addons` directory
-2. Restart Odoo server.
-3. Activate developer mode.
-4. Update Apps list and install **Many2Many Tags Preview** module.
-
----
-
-## 🛠 Usage
-
-In your Odoo view XML file, use the widget with options:
-
-```xml
-
-```
-
-- `widget="many2many_tags"` → Render tags.
-- `options="{'color_field': 'color'}"` → Use the `color` field for tag coloring.
-- `context="{'open_form_view': 'xml_id'}` → Specify a custom form view (if omitted, default form opens).
-
----
-
-## 🖼 Screenshots
-
-### Form View
-
-
-
-### List View
-
-
-
-### Kanban View
-
-
-
----
-
-## 📌 Compatibility
-
-- ✅ Odoo 17.0
-- ✅ Odoo 18.0
-- ✅ Odoo 19.0
-
-Supports **Community** and **Enterprise** editions.
-
----
-
-## 📧 Contact
-
-Author: **LuckyJie12**
-Email: [2996985766@qq.com](mailto:2996985766@qq.com)
diff --git a/many2many_tags_preview/many2many_tags_preview/models/__init__.py b/many2many_tags_preview/models/__init__.py
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/models/__init__.py
rename to many2many_tags_preview/models/__init__.py
diff --git a/many2many_tags_preview/many2many_tags_preview/models/ir_ui_view.py b/many2many_tags_preview/models/ir_ui_view.py
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/models/ir_ui_view.py
rename to many2many_tags_preview/models/ir_ui_view.py
diff --git a/many2many_tags_preview/many2many_tags_preview/static/description/cover.png b/many2many_tags_preview/static/description/cover.png
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/description/cover.png
rename to many2many_tags_preview/static/description/cover.png
diff --git a/many2many_tags_preview/many2many_tags_preview/static/description/gifs/FormPreview.gif b/many2many_tags_preview/static/description/gifs/FormPreview.gif
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/description/gifs/FormPreview.gif
rename to many2many_tags_preview/static/description/gifs/FormPreview.gif
diff --git a/many2many_tags_preview/many2many_tags_preview/static/description/gifs/KanbanPreview.gif b/many2many_tags_preview/static/description/gifs/KanbanPreview.gif
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/description/gifs/KanbanPreview.gif
rename to many2many_tags_preview/static/description/gifs/KanbanPreview.gif
diff --git a/many2many_tags_preview/many2many_tags_preview/static/description/gifs/ListPreview.gif b/many2many_tags_preview/static/description/gifs/ListPreview.gif
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/description/gifs/ListPreview.gif
rename to many2many_tags_preview/static/description/gifs/ListPreview.gif
diff --git a/many2many_tags_preview/many2many_tags_preview/static/description/icon.png b/many2many_tags_preview/static/description/icon.png
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/description/icon.png
rename to many2many_tags_preview/static/description/icon.png
diff --git a/many2many_tags_preview/many2many_tags_preview/static/description/icon.svg b/many2many_tags_preview/static/description/icon.svg
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/description/icon.svg
rename to many2many_tags_preview/static/description/icon.svg
diff --git a/many2many_tags_preview/many2many_tags_preview/static/description/index.html b/many2many_tags_preview/static/description/index.html
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/description/index.html
rename to many2many_tags_preview/static/description/index.html
diff --git a/many2many_tags_preview/many2many_tags_preview/static/src/many2many_tags/kanban_many2many_tags_field.js b/many2many_tags_preview/static/src/many2many_tags/kanban_many2many_tags_field.js
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/src/many2many_tags/kanban_many2many_tags_field.js
rename to many2many_tags_preview/static/src/many2many_tags/kanban_many2many_tags_field.js
diff --git a/many2many_tags_preview/many2many_tags_preview/static/src/many2many_tags/many2many_tags_field.js b/many2many_tags_preview/static/src/many2many_tags/many2many_tags_field.js
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/src/many2many_tags/many2many_tags_field.js
rename to many2many_tags_preview/static/src/many2many_tags/many2many_tags_field.js
diff --git a/many2many_tags_preview/many2many_tags_preview/static/src/many2many_tags/many2many_tags_field.xml b/many2many_tags_preview/static/src/many2many_tags/many2many_tags_field.xml
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/src/many2many_tags/many2many_tags_field.xml
rename to many2many_tags_preview/static/src/many2many_tags/many2many_tags_field.xml
diff --git a/many2many_tags_preview/many2many_tags_preview/static/src/many2many_tags/many2many_tags_field_color_list_popover.js b/many2many_tags_preview/static/src/many2many_tags/many2many_tags_field_color_list_popover.js
similarity index 100%
rename from many2many_tags_preview/many2many_tags_preview/static/src/many2many_tags/many2many_tags_field_color_list_popover.js
rename to many2many_tags_preview/static/src/many2many_tags/many2many_tags_field_color_list_popover.js
diff --git a/yuthon_property/models/property_meter_archives.py b/yuthon_property/models/property_meter_archives.py
index 62c804b7c..cbec07928 100644
--- a/yuthon_property/models/property_meter_archives.py
+++ b/yuthon_property/models/property_meter_archives.py
@@ -6,9 +6,11 @@ from odoo.exceptions import UserError, ValidationError
class PropertyMeterArchives(models.Model):
_name = 'property.meter.archives'
_description = '电表库'
+ _order = 'number asc'
name = fields.Char(string='仪表编号')
unit_number = fields.Char(string='单元编号/用途')
+ number = fields.Char(string="序号")
installation_location = fields.Char(string='安装位置')
is_state = fields.Boolean(string='是否启用')
type = fields.Selection([('public', '公共'), ('fees', '收费')], string='类型')
diff --git a/yuthon_property/models/property_meter_water.py b/yuthon_property/models/property_meter_water.py
index 70ca7ebe5..53969d86d 100644
--- a/yuthon_property/models/property_meter_water.py
+++ b/yuthon_property/models/property_meter_water.py
@@ -5,8 +5,10 @@ from odoo.exceptions import UserError, ValidationError
class PropertyMeterWater(models.Model):
_name = 'property.meter.water'
_description = '水表库'
+ _order = 'number asc'
name = fields.Char(string='仪表编号')
+ number = fields.Char(string="序号")
unit_number = fields.Char(string='单元编号/用途')
installation_location = fields.Char(string='安装位置')
is_state = fields.Boolean(string='是否启用')
diff --git a/yuthon_property/views/property_meter_archives_views.xml b/yuthon_property/views/property_meter_archives_views.xml
index f4e0fc0eb..88827a6e4 100644
--- a/yuthon_property/views/property_meter_archives_views.xml
+++ b/yuthon_property/views/property_meter_archives_views.xml
@@ -10,6 +10,7 @@
+
diff --git a/yuthon_property/views/property_meter_water_views.xml b/yuthon_property/views/property_meter_water_views.xml
index 487f0e13d..1dbb95585 100644
--- a/yuthon_property/views/property_meter_water_views.xml
+++ b/yuthon_property/views/property_meter_water_views.xml
@@ -11,6 +11,7 @@
+
diff --git a/yuthon_property_approval/__manifest__.py b/yuthon_property_approval/__manifest__.py
index 8e7b51d08..913fb9e04 100644
--- a/yuthon_property_approval/__manifest__.py
+++ b/yuthon_property_approval/__manifest__.py
@@ -83,6 +83,7 @@
'wizard/binding_information_wizard_views.xml',
'wizard/property_rental_wizard_views.xml',
'wizard/contract_signature_wizard_viwes.xml',
+ 'wizard/penalty_line_wizard_viwes.xml',
'wizard/build_pop_wizard_viwes.xml',
'wizard/property_meeting_wizard_views.xml',
'views/property_menu_all.xml',
diff --git a/yuthon_property_approval/models/inherit_yuthon_property.py b/yuthon_property_approval/models/inherit_yuthon_property.py
index 2b3e08e8e..3ba62a3e3 100644
--- a/yuthon_property_approval/models/inherit_yuthon_property.py
+++ b/yuthon_property_approval/models/inherit_yuthon_property.py
@@ -304,6 +304,7 @@ class PropertyBankStatements(models.Model):
'default_amount_reconciled': self.no_amount,
"default_receivable_total": total_rent_month,
"dialog_size" : "extra-large",
+ "default_order": "due_date desc",
}
return {
@@ -368,6 +369,7 @@ class PropertyAccountsReceivable(models.Model):
property_ids = fields.Many2many('yuthon.property', string='物业', compute='_compute_property_ids', store=True)
property_name = fields.Text(string='物业', compute="_compute_property_name")
+ is_rent = fields.Boolean(string='是否租金', default=True, compute = '_compute_is_rent', store=True)
management_area = fields.Float(related='contract_id.total_area', string='面积')
title_deed = fields.Char(string="产权证号", compute='_compute_title_deed')
lessee_id = fields.Many2one(related='contract_id.lessee_id', string='承租方', stroe=True)
@@ -382,6 +384,23 @@ class PropertyAccountsReceivable(models.Model):
rent_owed = fields.Float(string="欠租金额")
per_day = fields.Float(string="每天违约金(元/天)")
+ @api.depends('management_type_id')
+ def _compute_is_rent(self):
+ for rec in self:
+ if rec.management_type_id.name == '租金':
+ rec.is_rent = True
+ else:
+ rec.is_rent = False
+
+ def penalty_wizard(self):
+ return {
+ 'name': '合同违约金明细',
+ 'type': 'ir.actions.act_window',
+ 'res_model': 'penalty.line.wizard',
+ 'view_mode': 'form',
+ 'target': 'new',
+ }
+
@api.depends('contract_id')
def _compute_property_name(self):
for record in self:
diff --git a/yuthon_property_approval/security/ir.model.access.csv b/yuthon_property_approval/security/ir.model.access.csv
index 938386606..29e4aa69b 100644
--- a/yuthon_property_approval/security/ir.model.access.csv
+++ b/yuthon_property_approval/security/ir.model.access.csv
@@ -105,3 +105,7 @@ access_contract_signature_wizard,contract_signature_wizard,model_contract_signat
access_payment_process,payment_process,model_payment_process,base.group_user,1,1,1,1
access_build_pop_wizard, build_pop_wizard,model_build_pop_wizard,base.group_user,1,1,1,1
+
+access_penalty_line_wizard, penalty_line_wizard,model_penalty_line_wizard,base.group_user,1,1,1,1
+access_penalty_compute_line_wizard, penalty_compute_line_wizard,model_penalty_compute_line_wizard,base.group_user,1,1,1,1
+access_penalty_pay_line, penalty_pay_line,model_penalty_pay_line,base.group_user,1,1,1,1
diff --git a/yuthon_property_approval/views/inherit_yuthon_property_views.xml b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
index 24501da26..e419f8add 100644
--- a/yuthon_property_approval/views/inherit_yuthon_property_views.xml
+++ b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
@@ -284,9 +284,11 @@
+
+
diff --git a/yuthon_property_approval/wizard/__init__.py b/yuthon_property_approval/wizard/__init__.py
index 85811fbd0..caf0f01b4 100644
--- a/yuthon_property_approval/wizard/__init__.py
+++ b/yuthon_property_approval/wizard/__init__.py
@@ -10,4 +10,5 @@ from . import click_reconciliation_wizard
from . import accounts_wizard
from . import binding_information_wizard
from . import contract_signature_wizard
-from . import build_pop_wizard
\ No newline at end of file
+from . import build_pop_wizard
+from . import penalty_line_wizard
\ No newline at end of file
diff --git a/yuthon_property_approval/wizard/penalty_line_wizard.py b/yuthon_property_approval/wizard/penalty_line_wizard.py
new file mode 100644
index 000000000..3d3292b7a
--- /dev/null
+++ b/yuthon_property_approval/wizard/penalty_line_wizard.py
@@ -0,0 +1,50 @@
+from email.policy import default
+
+from odoo import models, fields, api, _, SUPERUSER_ID
+from odoo.exceptions import ValidationError, UserError
+import xlrd
+import base64
+import datetime
+from datetime import datetime
+import pandas as pd
+
+
+class PenaltyLineWizard(models.Model):
+ _name = 'penalty.line.wizard'
+ _description = '合同违约金明细'
+
+ rent_collected = fields.Float(string='未收租金')
+ days_overdue = fields.Integer(string='逾期天数')
+ total_penalty = fields.Float(string='违约金总额')
+ collected_penalty = fields.Float(string='已收违约金')
+ uncollected_penalty = fields.Float(string='未收违约金')
+ pay_number = fields.Char(string='支付次数')
+ remake = fields.Text(string='备注')
+
+ rule_description = fields.Text(string='计算规则说明:', default = '应收月的次月1号开始计算违约金\n。违约金按每日千分之 - (0.1 %)\n计算\n。租金部分支付后,剩余部分从前一次缴费日期次日开始里新计算')
+ penalty_line_ids = fields.One2many('penalty.compute.line.wizard', 'penalty_id', string='违约金明细')
+ pay_line_ids = fields.One2many('penalty.pay.line', 'penalty_id', string='违约金支付明细')
+
+
+class PenaltyComputeLineWizard(models.Model):
+ _name = 'penalty.compute.line.wizard'
+ _description = '违约金计算明细'
+ _order = 'date desc'
+
+ penalty_id = fields.Many2one('penalty.line.wizard', string='关联违约金明细')
+ date = fields.Date(string='日期')
+ remake = fields.Text(string='说明')
+ days_overdue = fields.Integer(string='逾期天数')
+ remaining_principal = fields.Float(string='剩余本金')
+ calculation_formula = fields.Text(string='计算公式')
+
+
+class PenaltyPayLine(models.Model):
+ _name = 'penalty.pay.line'
+ _description = '支付记录明细'
+
+ penalty_id = fields.Many2one('penalty.line.wizard', string='关联违约金明细')
+ date = fields.Date(string='支付日期')
+ amount = fields.Float(string='支付金额')
+ management_type_id = fields.Many2one('yuthon.management.type', string='支付类型')
+ remake = fields.Text(string='备注')
\ No newline at end of file
diff --git a/yuthon_property_approval/wizard/penalty_line_wizard_viwes.xml b/yuthon_property_approval/wizard/penalty_line_wizard_viwes.xml
new file mode 100644
index 000000000..07f329af8
--- /dev/null
+++ b/yuthon_property_approval/wizard/penalty_line_wizard_viwes.xml
@@ -0,0 +1,58 @@
+
+
+
+ penalty.line.wizard.form
+ penalty.line.wizard
+
+
+
+
+
\ No newline at end of file
diff --git a/yuthon_property_approval/wizard/property_reconciliation_wizard.py b/yuthon_property_approval/wizard/property_reconciliation_wizard.py
index 924b539d1..280d6ff88 100644
--- a/yuthon_property_approval/wizard/property_reconciliation_wizard.py
+++ b/yuthon_property_approval/wizard/property_reconciliation_wizard.py
@@ -165,8 +165,6 @@ class PropertyReconciliationWizard(models.Model):
if line.collection_type != 'penalty'
]
self.reconciliation_line_ids = keep_lines + new_lines
- if self.reconciliation_line_ids:
- self.reconciliation_line_ids.sorted(key=lambda r: r.sequence)
all_penalties = all(line.collection_type == 'penalty' for line in self.reconciliation_line_ids)
if all_penalties and self.reconciliation_line_ids:
@@ -492,7 +490,7 @@ class PropertyReconciliationWizard(models.Model):
class PropertyReconciliationLine(models.Model):
_name = 'property.reconciliation.line'
_description = '对账明细'
- _order = 'sequence asc'
+ _order = 'collection_type desc, due_date desc'
reconciliation_id = fields.Many2one('property.reconciliation.wizard', string='关联对账单弹窗')
sequence = fields.Integer(string='顺序')
diff --git a/yuthon_property_approval/wizard/property_reconciliation_wizard_views.xml b/yuthon_property_approval/wizard/property_reconciliation_wizard_views.xml
index 42e12b42b..5473c4d62 100644
--- a/yuthon_property_approval/wizard/property_reconciliation_wizard_views.xml
+++ b/yuthon_property_approval/wizard/property_reconciliation_wizard_views.xml
@@ -33,7 +33,7 @@
-
+