From da34be52d637c56d8f51f7300457f52c0a0ce452 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?=
<9664676+pengyuthon@user.noreply.gitee.com>
Date: Tue, 3 Mar 2026 18:52:56 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../models/property_accounts_receivable.py | 7 ++
yuthon_property/models/property_rent_list.py | 9 ++
.../property_accounts_receivable_views.xml | 1 +
.../views/property_rent_list_views.xml | 8 ++
.../models/inherit_yuthon_property.py | 1 +
.../views/inherit_yuthon_property_views.xml | 7 ++
.../wizard/penalty_line_wizard.py | 2 +-
.../wizard/property_reconciliation_wizard.py | 114 +-----------------
8 files changed, 38 insertions(+), 111 deletions(-)
diff --git a/yuthon_property/models/property_accounts_receivable.py b/yuthon_property/models/property_accounts_receivable.py
index df45bc916..c8f07fed1 100644
--- a/yuthon_property/models/property_accounts_receivable.py
+++ b/yuthon_property/models/property_accounts_receivable.py
@@ -14,6 +14,7 @@ class PropertyAccountsReceivable(models.Model):
_description = '应收账单'
payout_date = fields.Date(string='收款日期')
+ is_liquidated_damages = fields.Boolean(string='生成违约金', default=True)
rent_month = fields.Float(string='当月租金')
tax = fields.Float(string='税率')
title_certificate = fields.Char(sting="产权证号")
@@ -54,6 +55,12 @@ class PropertyAccountsReceivable(models.Model):
bank_id = fields.Many2one('property.bank.statements', string='流水记录')
receivable_log = fields.Text(string='应收日志')
+ def update_is_liquidated_damages(self):
+ rent_ids = self.env["property.accounts.receivable"].browse(
+ self._context.get('active_ids', self._context.get('active_id')))
+ for rent in rent_ids:
+ rent.is_liquidated_damages = False
+
def update_is_invalid(self):
record_ids = self.env["property.accounts.receivable"].browse(
self._context.get("active_ids", self._context.get("active_id"))
diff --git a/yuthon_property/models/property_rent_list.py b/yuthon_property/models/property_rent_list.py
index 3f7b86ea5..384552704 100644
--- a/yuthon_property/models/property_rent_list.py
+++ b/yuthon_property/models/property_rent_list.py
@@ -1,3 +1,5 @@
+from email.policy import default
+
from odoo import models, fields, api
@@ -6,6 +8,7 @@ class PropertyRentList(models.Model):
_description = '租金列表'
property_id = fields.Many2one('yuthon.property', string='物业')
+ is_liquidated_damages = fields.Boolean(string='生成违约金', default=True)
lessee_id = fields.Many2one('property.tenant.information', string='承租方', store=True)
admin_id = fields.Many2one(related='property_id.admin_id', string="片区管理员", store=True)
rent_month = fields.Float(string='当月租金')
@@ -37,6 +40,12 @@ class PropertyRentList(models.Model):
management_type_id = fields.Many2one('yuthon.management.type', string='应收类型')
last_update_time = fields.Datetime(string='最后修改时间')
+ def update_is_liquidated_damages(self):
+ rent_ids = self.env["property.rent.list"].browse(
+ self._context.get('active_ids', self._context.get('active_id')))
+ for rent in rent_ids:
+ rent.is_liquidated_damages = False
+
def get_no_read_count(self):
return self.env['property.rent.list'].search_count([('is_push', '=', False)])
diff --git a/yuthon_property/views/property_accounts_receivable_views.xml b/yuthon_property/views/property_accounts_receivable_views.xml
index 2c05e23b6..73a93a0dd 100644
--- a/yuthon_property/views/property_accounts_receivable_views.xml
+++ b/yuthon_property/views/property_accounts_receivable_views.xml
@@ -34,6 +34,7 @@
+
diff --git a/yuthon_property/views/property_rent_list_views.xml b/yuthon_property/views/property_rent_list_views.xml
index 8a43f48b9..565b9f5f7 100644
--- a/yuthon_property/views/property_rent_list_views.xml
+++ b/yuthon_property/views/property_rent_list_views.xml
@@ -7,6 +7,7 @@
+
@@ -25,6 +26,13 @@
+
+ 批量不生成违约金
+
+
+ code
+ action = model.update_is_liquidated_damages()
+
diff --git a/yuthon_property_approval/models/inherit_yuthon_property.py b/yuthon_property_approval/models/inherit_yuthon_property.py
index ac31804ca..5790d7fdf 100644
--- a/yuthon_property_approval/models/inherit_yuthon_property.py
+++ b/yuthon_property_approval/models/inherit_yuthon_property.py
@@ -1050,6 +1050,7 @@ class PropertyRentList(models.Model):
'contract_id': contract.id if contract else False,
'lessee_id': contract.lessee_id.id if contract and contract.lessee_id else None,
'original_amount': rec.original_amount,
+ 'is_liquidated_damages': rec.is_liquidated_damages,
'due_date': due_date,
'acc_type': rec.acc_type,
'charging_range': f"{due_date} 到 {due_date_end}",
diff --git a/yuthon_property_approval/views/inherit_yuthon_property_views.xml b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
index eb74fa542..2e49b7629 100644
--- a/yuthon_property_approval/views/inherit_yuthon_property_views.xml
+++ b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
@@ -646,6 +646,13 @@
code
action = model.all_penalty_date()
+
+ 批量不生成违约金
+
+
+ code
+ action = model.update_is_liquidated_damages()
+
批量退回
diff --git a/yuthon_property_approval/wizard/penalty_line_wizard.py b/yuthon_property_approval/wizard/penalty_line_wizard.py
index 36f96323a..fa03d00cf 100644
--- a/yuthon_property_approval/wizard/penalty_line_wizard.py
+++ b/yuthon_property_approval/wizard/penalty_line_wizard.py
@@ -177,7 +177,7 @@ class PenaltyLineWizard(models.Model):
@api.onchange('calculation_date')
def _onchange_calculation_date(self):
- if self.receivable_id.management_type_id.name != '押金':
+ if self.receivable_id.management_type_id.name != '押金' and self.receivable_id.is_liquidated_damages == True:
realtime_lines = self.penalty_line_ids.filtered(lambda l: l.is_realtime)
non_realtime_lines = self.penalty_line_ids - realtime_lines
update_commands = []
diff --git a/yuthon_property_approval/wizard/property_reconciliation_wizard.py b/yuthon_property_approval/wizard/property_reconciliation_wizard.py
index 6703779d0..428943396 100644
--- a/yuthon_property_approval/wizard/property_reconciliation_wizard.py
+++ b/yuthon_property_approval/wizard/property_reconciliation_wizard.py
@@ -167,6 +167,8 @@ class PropertyReconciliationWizard(models.Model):
])
for contract_receivables in contract_receivables_ids:
if contract_receivables:
+ if not contract_receivables.is_liquidated_damages:
+ continue
# 计算应收日期的下月1号
if not contract_receivables.due_date:
raise UserError(f'合同{contract_id.name}类型为{contract_receivables.management_type_id.name}的应收日期为空,请先填写应收日期')
@@ -204,6 +206,8 @@ class PropertyReconciliationWizard(models.Model):
])
if unpaid_rent_recs:
for rent in unpaid_rent_recs:
+ if not rent.is_liquidated_damages: # 跳过不生成违约金的租金
+ continue
if rent.payout_date <= rent.due_date: # 跳过预收的租金
continue
first_day = (rent.payout_date + timedelta(days=1))
@@ -239,116 +243,6 @@ class PropertyReconciliationWizard(models.Model):
total = sum(line.rent for line in self.reconciliation_line_ids)
self.receivable_total = total
- # all_due_dates = []
- # for line in self.reconciliation_line_ids:
- # if line.collection_type == 'rent' and line.due_date:
- # all_due_dates.append(fields.Date.from_string(line.due_date))
- # # 2. 找到最早的到期日期
- # if all_due_dates:
- # earliest_due_date = min(all_due_dates)
- # # 获取实际日期(假设actual_date是日期对象,如果是字符串需要先转换)
- # actual_date = fields.Date.from_string(self.actual_date) if isinstance(self.actual_date,
- # str) else self.actual_date
- #
- # # 计算起始月份(最早到期日的月份)和结束月份(实际日期的月份)
- # start_month = earliest_due_date + relativedelta(months=1)
- # end_month = actual_date - relativedelta(months=1)
- #
- # temp_rent_set = set()
- # target_rent_months = []
- #
- # # 遍历从起始月到结束月的所有月份
- # current_month = start_month
- # while current_month <= end_month:
- # due_month = current_month.strftime('%Y-%m')
- # # 为每个租金行添加当前月份的记录(去重)
- # for line in self.reconciliation_line_ids:
- # if line.collection_type == 'rent':
- # unique_key = (
- # line.contract_id.id if line.contract_id else None,
- # due_month
- # )
- # if unique_key not in temp_rent_set:
- # temp_rent_set.add(unique_key)
- # target_rent_months.append({
- # 'contract_id': line.contract_id,
- # 'due_month': due_month
- # })
- # # 移动到下个月
- # if current_month.month == 12:
- # current_month = current_month.replace(year=current_month.year + 1, month=1, day=1)
- # else:
- # current_month = current_month.replace(month=current_month.month + 1, day=1)
- # else:
- # 没有符合条件的明细行时,返回空列表
- target_rent_months = []
-
- # if target_rent_months:
- # existing_penalty_months = set()
- # for line in self.reconciliation_line_ids:
- # if line.collection_type == 'penalty' and line.due_date:
- # penalty_month = fields.Date.from_string(line.due_date).strftime('%Y-%m')
- # penalty_key = (
- # line.contract_id.id if line.contract_id else None,
- # penalty_month
- # )
- # existing_penalty_months.add(penalty_key)
- #
- # # # 3. 补全缺失的跨月违约金(按合同+年月匹配,缺失则新增)
- # # missing_penalty_lines = []
- # # for rent_info in target_rent_months:
- # # contract = rent_info['contract_id']
- # # due_month = rent_info['due_month']
- # #
- # # # 构建待检查的违约金key(合同+年月)
- # # check_key = (
- # # contract.id if contract else None,
- # # due_month
- # # )
- # #
- # # if check_key not in existing_penalty_months:
- # # year, month = map(int, due_month.split('-'))
- # # first_day = datetime(year, month, 1).date()
- # # penalty_days = (self.actual_date - first_day).days + 1
- # #
- # # # 计算补全违约金的日期范围:当月1号 ~ 当月最后1天
- # # # 查找上个月的租金明细行
- # # if month == 1:
- # # last_month_year = year - 1
- # # last_month = 12
- # # else:
- # # last_month_year = year
- # # last_month = month - 1
- # # last_month_str = f"{last_month_year}-{last_month:02d}"
- # #
- # # last_month_rent_line = next((
- # # line for line in self.reconciliation_line_ids
- # # if line.collection_type == 'rent'
- # # and line.contract_id == contract
- # # and line.due_date # 有到期日期
- # # and fields.Date.from_string(line.due_date).strftime('%Y-%m') == last_month_str
- # # ), None)
- # # # 提取上个月租金的rent金额
- # # last_month_rent = last_month_rent_line.rent if last_month_rent_line else 0.0
- # # penalty_amount = penalty_days * round(
- # # last_month_rent * float(contract.percentage_liquidated_damages.name), 2
- # # ) if (contract and last_month_rent > 0) else 0.0
- # #
- # # if penalty_amount > 0:
- # # missing_penalty_lines.append((0, 0, {
- # # 'contract_id': contract.id if contract else None,
- # # 'rent_month': 0,
- # # 'due_date': fields.Date.to_string(first_day),
- # # 'rent': penalty_amount,
- # # 'amount': 0,
- # # 'collection_type': 'penalty',
- # # 'remake': f'违约金({fields.Date.to_string(first_day)}至{fields.Date.to_string(self.actual_date)},共{penalty_days}天',
- # # }))
- # #
- # # # 添加缺失的违约金记录
- # # if missing_penalty_lines:
- # # self.write({'reconciliation_line_ids': missing_penalty_lines})
-
self.create_reconciliation_vals()
line_types = []
for line in self.reconciliation_line_ids:
From e1da44c9306d8e4c82ba2852e39ee0e48c5f17cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?=
<9664676+pengyuthon@user.noreply.gitee.com>
Date: Tue, 3 Mar 2026 18:53:43 +0800
Subject: [PATCH 2/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
soong_workflow/models/soong_workflow_record.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/soong_workflow/models/soong_workflow_record.py b/soong_workflow/models/soong_workflow_record.py
index 1abc35fb9..ad615f64f 100644
--- a/soong_workflow/models/soong_workflow_record.py
+++ b/soong_workflow/models/soong_workflow_record.py
@@ -623,8 +623,8 @@ class SoongWorkflowRecord(models.Model):
local_time = current_utc_time + timedelta(hours=8)
h = local_time.hour
m = local_time.minute
- if not (h == 17 and 25 <= m <= 35):
- return
+ # if not (h == 17 and 25 <= m <= 35):
+ # return
menu_id = self.env['ir.ui.menu'].search([('name', '=', '待办流程')])
target_url = f'https://oa.thtzjt.com/web#aciton=4299&model=soong.workflow.record&view_type=list&cids=1-2-3-4&menu_id={menu_id.id}'
rec_ids = self.env["soong.workflow.record"].search([