From 0f3c86fca34270e8343075ea8e5feda84c6d8b05 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: Sat, 7 Feb 2026 17:31:19 +0800
Subject: [PATCH] =?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_mixin.py | 17 +++++--
soong_workflow/models/soong_workflow_node.py | 6 ++-
.../views/soong_workflow_node_views.xml | 5 ++-
.../models/hr_attendance_detail_wechat.py | 2 +-
.../models/yuthon_medical_manage.py | 20 +++++++++
.../views/yuthon_medical_manage_views.xml | 44 ++++++++++++++-----
.../models/property_accounts_receivable.py | 7 +++
.../property_accounts_receivable_views.xml | 10 ++++-
yuthon_property_approval/__manifest__.py | 1 +
.../models/property_fee_spending.py | 35 +++++++++++++++
.../security/ir.model.access.csv | 4 +-
.../views/inherit_yuthon_property_views.xml | 8 ++++
.../views/property_fee_spending_view.xml | 19 ++++++++
yuthon_property_approval/wizard/__init__.py | 3 +-
.../wizard/build_fee_wizard.py | 24 ++++++++++
.../wizard/build_fee_wizard_views.xml | 21 +++++++++
yuthon_work_brand/views/hr_menus.xml | 6 +++
17 files changed, 210 insertions(+), 22 deletions(-)
create mode 100644 yuthon_property_approval/wizard/build_fee_wizard.py
create mode 100644 yuthon_property_approval/wizard/build_fee_wizard_views.xml
diff --git a/soong_workflow/models/soong_workflow_mixin.py b/soong_workflow/models/soong_workflow_mixin.py
index 8f8d6329a..4f1e8b2f3 100644
--- a/soong_workflow/models/soong_workflow_mixin.py
+++ b/soong_workflow/models/soong_workflow_mixin.py
@@ -564,10 +564,19 @@ class SoongWorkflowMixin(models.AbstractModel):
is_supervising = False
if self.name_title in ['行政发文']:
is_supervising = self.is_supervising
- if btn_rec.node_id.comment_id:
- comment_note_id = btn_rec.node_id.comment_id.id
- else:
- comment_note_id = False
+
+ comment_field_map = {
+ '转交': 'transfer_comment_id',
+ '退回': 'return_comment_id',
+ '确认': 'confirm_comment_id',
+ '结束': 'end_comment_id'
+ }
+ comment_note_id = False
+ if btn_rec.name in comment_field_map:
+ target_field = comment_field_map[btn_rec.name]
+ if hasattr(btn_rec.node_id, target_field) and btn_rec.node_id[target_field]:
+ comment_note_id = btn_rec.node_id[target_field].id
+
# 加签人员过滤
if self.log_ids:
log_node_ids = self.log_ids.mapped('node_id.id')
diff --git a/soong_workflow/models/soong_workflow_node.py b/soong_workflow/models/soong_workflow_node.py
index e109d7363..5a3c5dd1e 100644
--- a/soong_workflow/models/soong_workflow_node.py
+++ b/soong_workflow/models/soong_workflow_node.py
@@ -112,7 +112,11 @@ class SoongWorkflowNode(models.Model):
column1="node_id",
column2="transfer_department_id"
)
- comment_id = fields.Many2one('soong.note', string="固定意见")
+ transfer_comment_id = fields.Many2one('soong.note', string="转交固定意见")
+ return_comment_id = fields.Many2one('soong.note', string="退回固定意见")
+ confirm_comment_id = fields.Many2one('soong.note', string="确认固定意见")
+ end_comment_id = fields.Many2one('soong.note', string="结束固定意见")
+
approval_concatenation = fields.Selection([('chuan', '串申'), ('bing', '并申')], string="审批形式", default="bing",
help='并:任何人均给意见,最后一个完成的人转交到下一节点.'
'串:都会收到消息,但任意一个人转交后,即到下一节点,其他人将不再显示,相当于收回.')
diff --git a/soong_workflow/views/soong_workflow_node_views.xml b/soong_workflow/views/soong_workflow_node_views.xml
index 9229e5aba..943e40d48 100644
--- a/soong_workflow/views/soong_workflow_node_views.xml
+++ b/soong_workflow/views/soong_workflow_node_views.xml
@@ -13,7 +13,10 @@
-
+
+
+
+
diff --git a/yuthon_hr_attendance/models/hr_attendance_detail_wechat.py b/yuthon_hr_attendance/models/hr_attendance_detail_wechat.py
index ddd2a0309..06a33a526 100644
--- a/yuthon_hr_attendance/models/hr_attendance_detail_wechat.py
+++ b/yuthon_hr_attendance/models/hr_attendance_detail_wechat.py
@@ -97,7 +97,7 @@ class HrAttendanceDetail(models.Model):
@api.model
def create(self, vals):
record = super(HrAttendanceDetail, self).create(vals)
- if record.employee_id.name != '龙春球':
+ if record.employee_id.name not in ['龙春球', 'Administrator']:
resource_user_ids = record.employee_id.resource_calendar_id.resource_user_ids.ids
is_resource_user = True if record.employee_id.id in resource_user_ids else False
if record.employee_id and record.checkin_time and record.source == 'iot' and not is_resource_user:
diff --git a/yuthon_hr_employee/models/yuthon_medical_manage.py b/yuthon_hr_employee/models/yuthon_medical_manage.py
index 7e8354da8..43b8aeed8 100644
--- a/yuthon_hr_employee/models/yuthon_medical_manage.py
+++ b/yuthon_hr_employee/models/yuthon_medical_manage.py
@@ -196,4 +196,24 @@ class YuthonMedicalLine(models.Model):
medical_date = fields.Date(string="报销日期")
medical_fee = fields.Float(string="金额")
enable = fields.Boolean(string="启用", default=True)
+ remake = fields.Text(string="备注")
+
+ @api.constrains('employee_id', 'medical_date')
+ def _check_duplicate_medical_line(self):
+ for rec in self:
+ domain = [
+ ('employee_id', '=', rec.employee_id.id),
+ ('medical_date', '=', rec.medical_date),
+ ('id', '!=', rec.id)
+ ]
+ duplicate_rec = self.search(domain, limit=1)
+ if duplicate_rec:
+ if not self.env.context.get('confirm_update_medical_line'):
+ raise UserError(_(
+ f"检测到员工【{rec.employee_id.name}】在【{rec.medical_date}】已有体检费记录,请重新选择日期"
+
+ ))
+
+
+
diff --git a/yuthon_hr_employee/views/yuthon_medical_manage_views.xml b/yuthon_hr_employee/views/yuthon_medical_manage_views.xml
index 124fba646..aea562e51 100644
--- a/yuthon_hr_employee/views/yuthon_medical_manage_views.xml
+++ b/yuthon_hr_employee/views/yuthon_medical_manage_views.xml
@@ -6,11 +6,12 @@
-
+
@@ -28,14 +29,32 @@
体检报销费
yuthon.medical.line
-
+
+
+
+ 体检报销费
+ yuthon.medical.line
+
+
+
+
体检报销费搜索
yuthon.medical.line
@@ -45,7 +64,8 @@
-
+
@@ -56,12 +76,12 @@
-
@@ -79,10 +99,10 @@
action = model.medical_manage_wizard()
- 体检报销费
- yuthon.medical.line
- tree
- {'search_default_group_by_medical_year': 1}
+ 体检报销费
+ yuthon.medical.line
+ tree,form
+ {'search_default_group_by_medical_year': 1}
diff --git a/yuthon_property/models/property_accounts_receivable.py b/yuthon_property/models/property_accounts_receivable.py
index d8cf09e44..b2fd7bbdc 100644
--- a/yuthon_property/models/property_accounts_receivable.py
+++ b/yuthon_property/models/property_accounts_receivable.py
@@ -52,6 +52,13 @@ class PropertyAccountsReceivable(models.Model):
bank_id = fields.Many2one('property.bank.statements', string='流水记录')
receivable_log = fields.Text(string='应收日志')
+ def update_is_invalid(self):
+ record_ids = self.env["property.accounts.receivable"].browse(
+ self._context.get("active_ids", self._context.get("active_id"))
+ )
+ for record in record_ids:
+ record.void_date = fields.Date.today()
+ record.is_invalid = True
def update_due_date_end(self):
record_ids = self.env["property.accounts.receivable"].browse(
diff --git a/yuthon_property/views/property_accounts_receivable_views.xml b/yuthon_property/views/property_accounts_receivable_views.xml
index 9cda09ccb..9180f2c38 100644
--- a/yuthon_property/views/property_accounts_receivable_views.xml
+++ b/yuthon_property/views/property_accounts_receivable_views.xml
@@ -3,7 +3,8 @@
property.accounts.receivable.tree
property.accounts.receivable
-
+
@@ -75,6 +76,13 @@
+
+ 批量作废
+
+
+ code
+ action = model.update_is_invalid()
+
导入应收初始化数据
diff --git a/yuthon_property_approval/__manifest__.py b/yuthon_property_approval/__manifest__.py
index e882079be..9e5c01b70 100644
--- a/yuthon_property_approval/__manifest__.py
+++ b/yuthon_property_approval/__manifest__.py
@@ -95,6 +95,7 @@
'wizard/contract_signature_wizard_viwes.xml',
'wizard/penalty_line_wizard_viwes.xml',
'wizard/build_pop_wizard_viwes.xml',
+ 'wizard/build_fee_wizard_views.xml',
'wizard/action_refuse_wizard_views.xml',
'wizard/property_bills_wizard_views.xml',
'wizard/property_meeting_wizard_views.xml',
diff --git a/yuthon_property_approval/models/property_fee_spending.py b/yuthon_property_approval/models/property_fee_spending.py
index 461f01ac2..8ad95529a 100644
--- a/yuthon_property_approval/models/property_fee_spending.py
+++ b/yuthon_property_approval/models/property_fee_spending.py
@@ -15,6 +15,9 @@ class PropertyFeeSpending(models.Model):
property_address = fields.Text(string="物业地址")
users_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user.id)
department_id = fields.Many2one(related='users_id.employee_id.department_id', string="部门")
+ approve_state = fields.Selection([("start", "草稿"), ("pending", "审批中"), ("end", "结束")], default="start",
+ string="状态", compute="_compute_approve_state")
+
company_id = fields.Many2one(related='users_id.employee_id.company_id',string="公司")
code = fields.Char(string="编号",
default=lambda self: self.env['ir.sequence'].next_by_code('property_fee_spending_code'))
@@ -32,6 +35,7 @@ class PropertyFeeSpending(models.Model):
pay_date = fields.Date(string="支付日期")
expenses_type = fields.Many2one('yuthon.expenses.type', string="支出类型")
creart_datetime = fields.Datetime(string="创建日期", default=fields.Datetime.now)
+ spending_ids = fields.One2many('property.fee.spending.line', 'fee_id', string="物业明细")
remake = fields.Text(string="备注")
def _get_default_name_title(self):
@@ -41,6 +45,37 @@ class PropertyFeeSpending(models.Model):
self_users_ids = fields.Many2many('res.users', string="当前经办人", default=lambda self: [(6, 0, [self.env.user.id])])
+ def build_pop(self):
+ return {
+ 'name': '添加物业',
+ 'type': 'ir.actions.act_window',
+ 'res_model': 'build.fee.wizard',
+ 'view_mode': 'form',
+ 'target': 'new',
+ 'context': {
+ 'default_fee_id': self.id,
+ }
+ }
+
+ @api.depends('code')
+ def _compute_approve_state(self):
+ for rec in self:
+ workflow_record_id = self.env['soong.workflow.record'].search([('code', '=', rec.code)])
+ if workflow_record_id:
+ rec.approve_state = workflow_record_id.approve_state
+ else:
+ rec.approve_state = False
+
+class PropertyFeeSpendingLine(models.Model):
+ _name = 'property.fee.spending.line'
+ _description = '物业列表明细行'
+
+ fee_id = fields.Many2one('property.fee.spending', string="关联费用支出")
+ address_id = fields.Many2one('yuthon.property', string="物业地址")
+ tax = fields.Float(related='address_id.tax',string="税率")
+ admin_line_id = fields.Many2one(related='address_id.admin_id', string="管理员", store=True)
+ property_area = fields.Float(related='address_id.rent_area', string="可租面积", store=True)
+
class YuthonExpensesType(models.Model):
_name = 'yuthon.expenses.type'
diff --git a/yuthon_property_approval/security/ir.model.access.csv b/yuthon_property_approval/security/ir.model.access.csv
index f87f5c550..5afac0137 100644
--- a/yuthon_property_approval/security/ir.model.access.csv
+++ b/yuthon_property_approval/security/ir.model.access.csv
@@ -129,4 +129,6 @@ access_property_management_line2,property_management_line2,model_property_manage
access_yuthon_expenses_type,yuthon.expenses.type,model_yuthon_expenses_type,base.group_user,1,1,1,1
-access_property_fee_spending,property_fee_spending,model_property_fee_spending,base.group_user,1,1,1,1
\ No newline at end of file
+access_property_fee_spending,property_fee_spending,model_property_fee_spending,base.group_user,1,1,1,1
+access_property_fee_spending_line,property_fee_spending_line,model_property_fee_spending_line,base.group_user,1,1,1,1
+access_build_fee_wizard,build_fee_wizard,model_build_fee_wizard,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/yuthon_property_approval/views/inherit_yuthon_property_views.xml b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
index c5e202e37..7d4e4e946 100644
--- a/yuthon_property_approval/views/inherit_yuthon_property_views.xml
+++ b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
@@ -495,6 +495,14 @@
{'search_default_group_by_contract_id': True}
+
+
+ 违约金列表
+ property.accounts.receivable
+ tree
+ [('management_type_id.name','=', '违约金')]
+
+
押金列表
diff --git a/yuthon_property_approval/views/property_fee_spending_view.xml b/yuthon_property_approval/views/property_fee_spending_view.xml
index 4c1530257..8ddd65745 100644
--- a/yuthon_property_approval/views/property_fee_spending_view.xml
+++ b/yuthon_property_approval/views/property_fee_spending_view.xml
@@ -5,11 +5,15 @@
property.fee.spending
+
+
@@ -70,6 +74,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/yuthon_property_approval/wizard/__init__.py b/yuthon_property_approval/wizard/__init__.py
index 8766209c3..886624a8c 100644
--- a/yuthon_property_approval/wizard/__init__.py
+++ b/yuthon_property_approval/wizard/__init__.py
@@ -15,4 +15,5 @@ from . import penalty_line_wizard
from . import print_payment_wizard
from . import property_bills_wizard
from . import action_refuse_wizard
-from . import property_deposit_wizard
\ No newline at end of file
+from . import property_deposit_wizard
+from . import build_fee_wizard
\ No newline at end of file
diff --git a/yuthon_property_approval/wizard/build_fee_wizard.py b/yuthon_property_approval/wizard/build_fee_wizard.py
new file mode 100644
index 000000000..0fbe666ee
--- /dev/null
+++ b/yuthon_property_approval/wizard/build_fee_wizard.py
@@ -0,0 +1,24 @@
+from odoo import models, fields, api, _, SUPERUSER_ID
+from odoo.exceptions import UserError, ValidationError
+
+
+class BuildFeeWizard(models.TransientModel):
+ _name = 'build.fee.wizard'
+ _description = '添加物业弹窗'
+
+ property_ids = fields.Many2many('yuthon.property', string='物业')
+ fee_id = fields.Many2one('property.fee.spending', string='费用')
+
+ def confirm(self):
+ property_addresses = [
+ prop.name
+ for prop in self.property_ids
+ if prop.name
+ ]
+ concatenated_address = ', '.join(property_addresses)
+ self.fee_id.property_address = concatenated_address
+ for prop in self.property_ids:
+ self.env['property.fee.spending.line'].create({
+ 'fee_id': self.fee_id.id,
+ 'address_id': prop.id,
+ })
diff --git a/yuthon_property_approval/wizard/build_fee_wizard_views.xml b/yuthon_property_approval/wizard/build_fee_wizard_views.xml
new file mode 100644
index 000000000..dc2ba05da
--- /dev/null
+++ b/yuthon_property_approval/wizard/build_fee_wizard_views.xml
@@ -0,0 +1,21 @@
+
+
+
+ build.fee.wizard.form
+ build.fee.wizard
+
+
+
+
+
diff --git a/yuthon_work_brand/views/hr_menus.xml b/yuthon_work_brand/views/hr_menus.xml
index a27873dc2..0debf23f0 100644
--- a/yuthon_work_brand/views/hr_menus.xml
+++ b/yuthon_work_brand/views/hr_menus.xml
@@ -905,6 +905,12 @@
name="应付账单"
action="yuthon_property_approval.view_property_bills_list_action"
sequence="4"/>
+