diff --git a/room/security/ir_rule.xml b/room/security/ir_rule.xml
index c20ade81a..7b2e0524c 100644
--- a/room/security/ir_rule.xml
+++ b/room/security/ir_rule.xml
@@ -11,6 +11,11 @@
[('company_id', 'in', company_ids)]
+
+ 预定会议多公司
+
+ [('company_id', 'in', company_ids)]
+
diff --git a/soong_workflow/models/__init__.py b/soong_workflow/models/__init__.py
index f27b21a33..4d5b4814e 100644
--- a/soong_workflow/models/__init__.py
+++ b/soong_workflow/models/__init__.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
-
+# 1.双向删除
+# 2.
from . import soong_workflow
from . import soong_workflow_node
from . import soong_workflow_link
diff --git a/soong_workflow/models/soong_workflow_mixin.py b/soong_workflow/models/soong_workflow_mixin.py
index 28068a7f3..436b4e525 100644
--- a/soong_workflow/models/soong_workflow_mixin.py
+++ b/soong_workflow/models/soong_workflow_mixin.py
@@ -332,7 +332,7 @@ class SoongWorkflowMixin(models.AbstractModel):
index = 20 # 防止死循环
break
current_department = self.department_id
- if btn_rec.link_id and btn_rec.link_id in current_node.out_link_ids:
+ if btn_rec.link_id in current_node.out_link_ids and len(current_node.out_link_ids) == 1:
matched_link = btn_rec.link_id
next_node = matched_link.node_to
matched_key = next_node.name
@@ -341,14 +341,27 @@ class SoongWorkflowMixin(models.AbstractModel):
# 筛选与当前节点部门匹配的后续节点
valid_nodes = []
for link in current_node.out_link_ids:
- target_node = link.node_to
- # 如果目标节点有部门限制,且与当前节点部门匹配
- if target_node.department_id and any(
- dept in current_department or
- current_department in self.get_all_sub_departments(dept)
- for dept in target_node.department_id
- ):
- valid_nodes.append((target_node, link))
+ if self.name_title == '业务审批':
+ category_names = self.information_categories_ids.mapped('name')
+ target_name = link.name.split('->')[-1].strip()
+ if '工会活动' in category_names:
+ if target_name == '工会主席':
+ target_node = link.node_to
+ valid_nodes.append((target_node, link))
+ else:
+ if target_name == '复核':
+ target_node = link.node_to
+ valid_nodes.append((target_node, link))
+
+ else:
+ target_node = link.node_to
+ # 如果目标节点有部门限制,且与当前节点部门匹配
+ if target_node.department_id and any(
+ dept in current_department or
+ current_department in self.get_all_sub_departments(dept)
+ for dept in target_node.department_id
+ ):
+ valid_nodes.append((target_node, link))
# 尝试父部门匹配
if not valid_nodes and current_department and current_department.parent_id:
@@ -734,8 +747,11 @@ class SoongWorkflowMixin(models.AbstractModel):
btn_exec_action_el.set("class", "oe_highlight")
if button.has_icon:
btn_exec_action_el.set("icon", button.icon)
- btn_exec_action_el.set("invisible", "state != '%s'" % node.node_name)
- btn_exec_action_el.set("context", "{'btn_key':'%s','active_model':'%s'}" % (button.btn_key, self._name),)
+ invisible_condition = "state != '%s'" % node.node_name
+ if model == 'purchase.order':
+ invisible_condition = invisible_condition.replace("询价", "draft")
+ btn_exec_action_el.set("invisible", invisible_condition)
+ btn_exec_action_el.set("context","{'btn_key':'%s','active_model':'%s'}" % (button.btn_key, self._name), )
else:
is_apostille = False
if button.btn_hide:
@@ -811,6 +827,10 @@ class SoongWorkflowMixin(models.AbstractModel):
# if button.name == "结束":
# invisible += " or True"
invisible += " or work_end"
+
+ if model == 'purchase.order':
+ invisible = invisible.replace("询价", "draft")
+
btn_exec_action_el.set("invisible", invisible)
btn_exec_action_el.set("context", "{'btn_key':'%s','active_model':'%s'}" % (button.btn_key, self._name),)
res["arch"] = etree.tostring(arch, encoding="unicode").replace("\t", "")
diff --git a/soong_workflow/models/soong_workflow_record.py b/soong_workflow/models/soong_workflow_record.py
index 150fcf4e9..37e7870d7 100644
--- a/soong_workflow/models/soong_workflow_record.py
+++ b/soong_workflow/models/soong_workflow_record.py
@@ -62,6 +62,18 @@ class SoongWorkflowRecord(models.Model):
res.append_date2(res)
return res
+ def log(self):
+ log = self.env['soong.workflow.log'].search([("model", "=", self.res_model),
+ ("res_id", "=", self.res_id)])
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': '日志',
+ 'view_mode': 'tree',
+ 'res_model': 'soong.workflow.log',
+ 'domain': [('id', 'in', log.ids)],
+ }
+
+
def restore(self):
workflow_ids = self.env["soong.workflow.record"].browse(
self._context.get('active_ids', self._context.get('active_id', [])))
diff --git a/soong_workflow/views/soong_workflow_record.xml b/soong_workflow/views/soong_workflow_record.xml
index 61edd8feb..3f04bee28 100644
--- a/soong_workflow/views/soong_workflow_record.xml
+++ b/soong_workflow/views/soong_workflow_record.xml
@@ -90,12 +90,15 @@
+
+
@@ -206,7 +209,6 @@
ir.actions.act_window
soong.workflow.record
tree,kanban,search
-
{'header_search_default_approve_state': 1, 'header_search_default_to_do':1, 'check_employee': 1}
[('users_ids', 'in', uid), ('reclaim_state', '=', False), ('soong_state', '=', 'to_do')]
diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py
index a81a1bab8..73e2b5fd6 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard.py
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py
@@ -28,6 +28,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
comment = fields.Char(compute='_compute_comment', store=True)
state_list = fields.Char(string="状态列表")
record_id = fields.Integer()
+ is_selection = fields.Boolean(string="是否自动选择")
trans_link_id = fields.Many2one('trans.link', string='转交节点')
document_ids = fields.Many2many('ir.attachment', string="附件")
return_link_id = fields.Many2one('trans.link', string='退回节点')
@@ -64,6 +65,17 @@ class SoongWorkflowCommentWizard(models.TransientModel):
store=True
)
+ @api.onchange('is_selection')
+ def _onchange_is_selection(self):
+ domain = [('id', 'in', self.employee_ids1.ids)]
+ if self.is_selection:
+ if self.is_this_company:
+ domain.append(('company_id', '=', self.company_id.id))
+ all_employees = self.env['hr.employee'].search(domain)
+ self.employee_ids = all_employees
+ else:
+ self.employee_ids = False
+
@api.onchange('employee_ids1')
def _onchange_employee_ids1(self):
if len(self.employee_ids1) == 1:
diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
index 574a92aff..2669b6e6c 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
@@ -59,6 +59,7 @@
+
diff --git a/soong_workflow/wizard/soong_workflow_record_revoke_wizard.py b/soong_workflow/wizard/soong_workflow_record_revoke_wizard.py
index f9b09b9bf..793e4435c 100644
--- a/soong_workflow/wizard/soong_workflow_record_revoke_wizard.py
+++ b/soong_workflow/wizard/soong_workflow_record_revoke_wizard.py
@@ -43,7 +43,11 @@ class SoongWorkflowRecordRevokeWizard(models.TransientModel):
])
meal_line.unlink()
-
record_to_update.write({'log_ids': [(5, 0, 0)]})
record_to_update.state = '申请人'
- self.record_id.approve_state = 'start'
\ No newline at end of file
+ self.record_id.write({
+ 'approve_state': 'start',
+ 'soong_state': 'to_do',
+ 'employee_ids': [(6, 0, [self.record_id.create_uid.employee_ids.id])],
+ 'users_ids': [(6, 0, [self.record_id.create_uid.id])]
+ })
\ No newline at end of file
diff --git a/sun_badge_menu/models/ir_ui_menu.py b/sun_badge_menu/models/ir_ui_menu.py
index 49975e359..54ef083e7 100644
--- a/sun_badge_menu/models/ir_ui_menu.py
+++ b/sun_badge_menu/models/ir_ui_menu.py
@@ -31,7 +31,7 @@ def compute_badge_count_recursive(web_menus, menu_id):
class IrUiMenu(models.Model):
_inherit = "ir.ui.menu"
- show_badge_count = fields.Boolean(string="显示菜单角标",default=True)
+ show_badge_count = fields.Boolean(string="显示菜单角标", default=True)
is_phone = fields.Boolean(string="手机菜单",default=False)
is_pc = fields.Boolean(string="PC菜单",default=True)
@@ -134,7 +134,6 @@ class IrUiMenu(models.Model):
web_menus = {}
for menu in menus.values():
if not menu['id']:
- # special root menu case
web_menus['root'] = {
"id": 'root',
"name": menu['name'],
@@ -151,14 +150,11 @@ class IrUiMenu(models.Model):
}
else:
action = menu['action']
-
if menu['id'] == menu['app_id']:
- # if it's an app take action of first (sub)child having one defined
child = menu
while child and not action:
action = child['action']
child = menus[child['children'][0]] if child['children'] else False
-
action_model, action_id = action.split(',') if action else (False, False)
action_id = int(action_id) if action_id else False
badge_count = 0
@@ -166,7 +162,6 @@ class IrUiMenu(models.Model):
# 增加 show_badge_count 限制是否显示"角标".
if action_model and action_id and menu['show_badge_count']:
action_record = self.env[action_model].browse(action_id).sudo()
-
if action_model == 'ir.actions.act_window' and action_record.view_mode != 'form':
# 不仅仅是 form 表单,获取 model
res_model = action_record.res_model
diff --git a/yuthon_account_report/views/custom.xml b/yuthon_account_report/views/custom.xml
index 741ab03bd..629769444 100644
--- a/yuthon_account_report/views/custom.xml
+++ b/yuthon_account_report/views/custom.xml
@@ -11,15 +11,16 @@
-
+
+
+
+
+
-
+
+
+
+
financial.sheet.line.tree
diff --git a/yuthon_contract/models/inherit_hr_contract.py b/yuthon_contract/models/inherit_hr_contract.py
index 57d94974e..2d5f688e2 100644
--- a/yuthon_contract/models/inherit_hr_contract.py
+++ b/yuthon_contract/models/inherit_hr_contract.py
@@ -110,6 +110,8 @@ class HrContract(models.Model):
'view_mode': 'form',
'target': 'current',
'context': {
+ 'default_work_end': False,
+ 'default_self_users_ids':[(6, 0, [self.employee_id.user_id.id])],
'default_contract_id': contract_ids.id,
'default_employee_id': contract_ids.employee_id.id
}}
diff --git a/yuthon_holiday/views/hr_leave_batch.xml b/yuthon_holiday/views/hr_leave_batch.xml
index 8487e2de7..19b0d5e4a 100644
--- a/yuthon_holiday/views/hr_leave_batch.xml
+++ b/yuthon_holiday/views/hr_leave_batch.xml
@@ -44,6 +44,7 @@
+
diff --git a/yuthon_hr_attendance/controllers/applet_attendance.py b/yuthon_hr_attendance/controllers/applet_attendance.py
index da3103d48..a21eee297 100644
--- a/yuthon_hr_attendance/controllers/applet_attendance.py
+++ b/yuthon_hr_attendance/controllers/applet_attendance.py
@@ -887,18 +887,31 @@ class AppletAttendance(Controller):
first_day_str = first_day.strftime('%Y-%m-%d')
last_day_str = last_day.strftime('%Y-%m-%d')
-
+ two_months_ago = datetime.now().date() - relativedelta(months=2)
# 去掉 数据为 0 的数据.
+ valid_archives = request.env(user=SUPERUSER_ID)['property.meter.archives'].search([
+ ('is_virtual_meter', '!=', True),
+ '|',
+ ('end_time', '=', False),
+ ('end_time', '<=', two_months_ago)
+ ])
electric_records = request.env(user=SUPERUSER_ID)['meter.archives.line'].search([
('archives_state', '!=', 'stop'),
+ ('archives_id', 'in', valid_archives.ids),
('meter_date', '>=', first_day_str),
- ('meter_date', '<=', last_day_str)
+ ('meter_date', '<=', last_day_str),
])
+ valid_water_ids = request.env(user=SUPERUSER_ID)['property.meter.water'].search([
+ '|',
+ ('end_time', '=', False),
+ ('end_time', '<=', two_months_ago)
+ ]).ids
water_records = request.env(user=SUPERUSER_ID)['meter.water.line'].search([
('water_state', '!=', 'stop'),
('meter_date', '>=', first_day_str),
- ('meter_date', '<=', last_day_str)
+ ('meter_date', '<=', last_day_str),
+ ('water_id', 'in', valid_water_ids)
])
# 接口调整, 电表,水表数据拆分.
@@ -1058,14 +1071,21 @@ class AppletAttendance(Controller):
# ('meter_date', '>=', first_day_str),
# ('meter_date', '<=', last_day_str)]
- # 去掉 state
- domain = [('epitope_values_id.name', '=', floor_name),
- ('meter_date', '>=', first_day_str),
- ('meter_date', '<=', last_day_str)]
-
+ domain = [
+ ('epitope_values_id.name', '=', floor_name),
+ ('meter_date', '>=', first_day_str),
+ ('meter_date', '<=', last_day_str)
+ ]
+ two_months_ago = datetime.now().date() - relativedelta(months=2)
if type == 'electric':
domain.append(('archives_state', '!=', 'stop'))
model = 'meter.archives.line'
+ domain.extend([
+ ('archives_id.is_virtual_meter', '!=', True),
+ '|',
+ ('archives_id.end_time', '=', False),
+ ('archives_id.end_time', '<=', two_months_ago)
+ ])
else:
domain.append(('water_state', '!=', 'stop'))
model = 'meter.water.line'
diff --git a/yuthon_hr_attendance/models/go_approval.py b/yuthon_hr_attendance/models/go_approval.py
index 0b65f52e8..5b840340f 100644
--- a/yuthon_hr_attendance/models/go_approval.py
+++ b/yuthon_hr_attendance/models/go_approval.py
@@ -19,6 +19,7 @@ class GoApprovals(models.Model):
code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('overtime_approval'))
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="部门")
+ company_id = fields.Many2one(related='users_id.employee_id.company_id', string="公司")
reason_application = fields.Char(string="事由")
is_issues = fields.Boolean(string='是否上会')
issues_result = fields.Html(string="会议结果")
@@ -41,6 +42,8 @@ class GoApprovals(models.Model):
end_day_selection = fields.Selection([('half', '上半天'), ('afternoon', '下半天')], string="天")
start_date = fields.Date(string="开始日期", default=fields.Date.today)
end_date = fields.Date(string="结束日期", default=fields.Date.today)
+ is_this_department = fields.Boolean(string='是否是本部门', default=True)
+ department_ids = fields.Many2many('hr.department', string="多部门")
def _get_default_name_title(self):
return self._description if self._description else self._name
@@ -48,6 +51,17 @@ class GoApprovals(models.Model):
name_title = fields.Char(default=_get_default_name_title)
self_users_ids = fields.Many2many('res.users', string="当前经办人", default=lambda self: [(6, 0, [self.env.user.id])])
+ @api.onchange('is_this_department')
+ def _onchange_is_this_department(self):
+ self.department_ids = [(5, 0, 0)]
+ if self.is_this_department and self.users_id:
+ employee = self.env['hr.employee'].search([('user_id', '=', self.users_id.id)], limit=1)
+ main_department = employee.department_id
+ all_departments = main_department.search([
+ ('id', 'child_of', main_department.id)
+ ])
+ self.department_ids = [(6, 0, all_departments.ids)]
+
@api.onchange('start_day_selection', 'end_day_selection')
def _onchange_selection_fields(self):
for record in self:
diff --git a/yuthon_hr_attendance/models/hr_attendance.py b/yuthon_hr_attendance/models/hr_attendance.py
index da589dcd0..7b524f468 100644
--- a/yuthon_hr_attendance/models/hr_attendance.py
+++ b/yuthon_hr_attendance/models/hr_attendance.py
@@ -83,6 +83,11 @@ class HrAttendance(models.Model):
if reminder_id:
reminder_id.state = 'done'
+ def one_time(self):
+ for att in self.env["hr.attendance"].browse(self._context.get('active_ids', self._context.get('active_id'))):
+ if att.current_data:
+ att.current_data_month = f'{att.current_data.year}-{att.current_data.month}'
+
def task_remind(self):
all_employees = self.env['hr.employee'].search([('name', 'in', ['Administrator', '叶华锋'])])
for employee in all_employees:
diff --git a/yuthon_hr_attendance/views/go_approval.xml b/yuthon_hr_attendance/views/go_approval.xml
index 86fb60055..ba490ee9e 100644
--- a/yuthon_hr_attendance/views/go_approval.xml
+++ b/yuthon_hr_attendance/views/go_approval.xml
@@ -35,7 +35,7 @@
-
+
@@ -67,8 +67,8 @@
-
-
+
+
@@ -85,8 +85,11 @@
+
-
+
+
+
diff --git a/yuthon_hr_employee/models/yuthon_hr_employee.py b/yuthon_hr_employee/models/yuthon_hr_employee.py
index c7d1b7bfe..9fc7fd241 100644
--- a/yuthon_hr_employee/models/yuthon_hr_employee.py
+++ b/yuthon_hr_employee/models/yuthon_hr_employee.py
@@ -286,6 +286,28 @@ class YuthonHrEmployee(models.Model):
else:
record.date_end = None
+ def renew(self):
+ employee_ids = self.env["hr.employee"].browse(
+ self._context.get("active_ids", self._context.get("active_id"))
+ )
+ for record in employee_ids:
+ if len(record) > 1:
+ raise UserError("只能选择一个员工续签")
+ return {
+ "name": "续签",
+ "type": "ir.actions.act_window",
+ "res_model": "yuthon.renewal.approval",
+ "view_mode": "form",
+ "context": {
+ "default_employee_id": self.id,
+ "default_current_status": self.contract_id.date_end,
+ "default_department1_id": self.department_id.id,
+ "default_contract_id": self.contract_id.id,
+ },
+ }
+
+
+
def update_social_base(self):
current_year = fields.Date.today().year
group_company = self.env['res.company'].search([('name', '=', '集团本部')], limit=1)
diff --git a/yuthon_hr_employee_approval/__manifest__.py b/yuthon_hr_employee_approval/__manifest__.py
index 975bcf01b..dca4eebeb 100644
--- a/yuthon_hr_employee_approval/__manifest__.py
+++ b/yuthon_hr_employee_approval/__manifest__.py
@@ -19,9 +19,11 @@
'data/stage_approval_data.xml',
'data/tage_approval_data.xml',
'data/leaving_retired_data.xml',
+ 'data/yuthon_contract_type_data.xml',
+ 'data/yuthon_formation_method_data.xml',
'views/inherit_hr_applicant_views.xml',
'views/inherit_room_booking_views.xml',
- 'views/inherit_hr_job_views.xml',
+ # 'views/inherit_hr_job_views.xml',
'views/inherit_hr_employee_views.xml',
'views/yuthon_message_login_views.xml',
'views/yuthon_onboard_approval_views.xml',
diff --git a/yuthon_hr_employee_approval/data/yuthon_contract_type_data.xml b/yuthon_hr_employee_approval/data/yuthon_contract_type_data.xml
new file mode 100644
index 000000000..b0fca19e8
--- /dev/null
+++ b/yuthon_hr_employee_approval/data/yuthon_contract_type_data.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+ 服务咨询合同
+
+
+
+ 投资合同
+
+
+
+ 运营合同
+
+
+
+ 采购合同
+
+
+
+ 资金合同
+
+
+
+ 战略合作协议
+
+
+
+ 其他合同
+
+
+
\ No newline at end of file
diff --git a/yuthon_hr_employee_approval/data/yuthon_formation_method_data.xml b/yuthon_hr_employee_approval/data/yuthon_formation_method_data.xml
new file mode 100644
index 000000000..58144749b
--- /dev/null
+++ b/yuthon_hr_employee_approval/data/yuthon_formation_method_data.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ 投标
+
+
+
+ 议标
+
+
+
+ 询价
+
+
+
+ 战略合作
+
+
+
+ 委托形成
+
+
+
\ No newline at end of file
diff --git a/yuthon_hr_employee_approval/models/__init__.py b/yuthon_hr_employee_approval/models/__init__.py
index de509b22a..900eecc9f 100644
--- a/yuthon_hr_employee_approval/models/__init__.py
+++ b/yuthon_hr_employee_approval/models/__init__.py
@@ -27,4 +27,5 @@ from . import yuthon_department_change
from . import yuthon_renewal_approval
from . import contract_review_approval
from . import yuthon_employee_add
-from . import yuthon_pre_examination
\ No newline at end of file
+from . import yuthon_pre_examination
+from . import yuthon_employee_setting
\ No newline at end of file
diff --git a/yuthon_hr_employee_approval/models/contract_review_approval.py b/yuthon_hr_employee_approval/models/contract_review_approval.py
index 826ea24e2..092a8ce85 100644
--- a/yuthon_hr_employee_approval/models/contract_review_approval.py
+++ b/yuthon_hr_employee_approval/models/contract_review_approval.py
@@ -13,7 +13,7 @@ class ContractReviewApproval(models.Model):
is_issues = fields.Boolean(string='是否上会')
issues_result = fields.Html(string="会议结果")
related_issues_id = fields.Many2one('issue.library', string="关联议题")
- department_id = fields.Many2one('hr.department', string='部门')
+ department_id = fields.Many2one('hr.department', string='送审部门')
amount = fields.Float(string='合同金额')
remarks = fields.Text(string='情况说明')
documents_ids = fields.Many2many('ir.attachment', string="附件")
@@ -21,6 +21,11 @@ class ContractReviewApproval(models.Model):
default='normal')
active = fields.Boolean('Active', default=True, tracking=True)
work_end = fields.Boolean(string="结束")
+ contract_type = fields.Many2one('yuthon.contract.type', string="合同类型")
+ formation_method = fields.Many2one('yuthon.contract.type', string="形成方式")
+ submitting_unit = fields.Char(string="送审单位")
+ sign_date = fields.Date(string="合同签订日期")
+ performance_term_day = fields.Integer(string='履约期限')
def _get_default_name_title(self):
return self._description if self._description else self._name
diff --git a/yuthon_hr_employee_approval/models/yuthon_employee_add.py b/yuthon_hr_employee_approval/models/yuthon_employee_add.py
index c17ee508b..655051734 100644
--- a/yuthon_hr_employee_approval/models/yuthon_employee_add.py
+++ b/yuthon_hr_employee_approval/models/yuthon_employee_add.py
@@ -60,8 +60,12 @@ class YuthonEmployeeAdd(models.Model):
@api.depends('contract_id', 'version')
def _compute_name(self):
for rec in self:
+ version_str = self.contract_id.version.lstrip('V')
+ main_version = version_str.split('.')[0]
+ new_main_version = int(main_version) + 1
+ new_version = f"V{new_main_version}.0"
if rec.contract_id:
- rec.name = rec.contract_id.name + ' ' + rec.version
+ rec.name = rec.contract_id.name + ' ' + new_version
else:
rec.name = None
diff --git a/yuthon_hr_employee_approval/models/yuthon_employee_setting.py b/yuthon_hr_employee_approval/models/yuthon_employee_setting.py
new file mode 100644
index 000000000..57df87a2c
--- /dev/null
+++ b/yuthon_hr_employee_approval/models/yuthon_employee_setting.py
@@ -0,0 +1,24 @@
+from odoo import models, fields, api
+from dateutil.relativedelta import relativedelta
+
+
+class YuthonServiceType(models.Model):
+ _name = 'yuthon.service.type'
+ _description = '服务类型'
+
+ name = fields.Char(string="名称")
+
+class YuthonServiceContractType(models.Model):
+ _name = 'yuthon.contract.type'
+ _description = '合同类型和形成方式'
+
+ name = fields.Char(string="名称", required=True)
+
+
+
+
+
+
+
+
+
diff --git a/yuthon_hr_employee_approval/models/yuthon_service_approval.py b/yuthon_hr_employee_approval/models/yuthon_service_approval.py
index 5efac9fc1..98427753e 100644
--- a/yuthon_hr_employee_approval/models/yuthon_service_approval.py
+++ b/yuthon_hr_employee_approval/models/yuthon_service_approval.py
@@ -10,20 +10,22 @@ class YuthonServiceApproval(models.Model):
name = fields.Char(string='标题')
code = fields.Char(string="编号",
default=lambda self: self.env['ir.sequence'].next_by_code('yuthon_service_approval_code'))
- service_type = fields.Selection([('done', '在职证明'), ('leaving', '离职证明'), ('income', '收入证明')], string="服务类型")
- users_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user.id)
+ service_type_id = fields.Many2one('yuthon.service.type', string="服务类型")
+ users_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user)
documents_ids = fields.Many2many('ir.attachment', string="附件")
- department_id = fields.Many2one(related='users_id.employee_id.department_id', string="部门", store=True)
- employee_id = fields.Many2one('hr.employee', string="员工姓名")
- company_id = fields.Many2one(related="users_id.employee_id.company_id", string="公司", store=True)
+ department_id = fields.Many2one(related='users_id.employee_ids.department_id', string="部门", store=True)
+ employee_id = fields.Many2one('hr.employee', string="员工姓名", default=lambda self: self.env.user.employee_id.id)
+ company_id = fields.Many2one(related="users_id.employee_ids.company_id", string="公司", store=True)
tenant_user_card = fields.Many2one('ir.attachment', string="身份证")
- onboarding_time = fields.Date(related='employee_id.open_start_time', string="入职时间")
+ onboarding_time = fields.Date(related='employee_id.open_start_time', string="入职日期")
job_id = fields.Many2one(related='employee_id.job_id', string="岗位")
+ is_turnover = fields.Boolean()
reason_issuance = fields.Char(string="开证原因")
is_issues = fields.Boolean(string='是否上会')
issues_result = fields.Html(string="会议结果")
related_issues_id = fields.Many2one('issue.library', string="关联议题")
+ separation_date = fields.Date(string="离职日期")
urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
default='normal')
active = fields.Boolean('Active', default=True, tracking=True)
@@ -50,14 +52,13 @@ class YuthonServiceApproval(models.Model):
'approval_date': fields.Datetime.now(),
})
- @api.onchange('service_type')
+ @api.onchange('service_type_id')
def _onchange_service_type(self):
- if self.service_type and self.users_id.name:
- # 创建一个映射表,将技术值映射到显示文本
- service_type_map = {
- 'done': '在职证明',
- 'leaving': '离职证明',
- 'income': '收入证明'
- }
- service_display = service_type_map.get(self.service_type, self.service_type)
- self.name = f"{self.users_id.name}的{service_display}"
\ No newline at end of file
+ if self.service_type_id and self.users_id.name:
+ self.name = f"{self.users_id.name}的{self.service_type_id.name}"
+
+ if self.service_type_id.name == '离职证明':
+ self.is_turnover = True
+ else:
+ self.is_turnover = False
+
diff --git a/yuthon_hr_employee_approval/security/ir.model.access.csv b/yuthon_hr_employee_approval/security/ir.model.access.csv
index 9bea8f0e7..14c33e4af 100644
--- a/yuthon_hr_employee_approval/security/ir.model.access.csv
+++ b/yuthon_hr_employee_approval/security/ir.model.access.csv
@@ -56,3 +56,5 @@ access_contract_review_approval,contract_review_approval,model_contract_review_a
access_awards_line, awards_line,model_awards_line,base.group_user,1,1,1,1
access_yuthon_employee_add,yuthon_employee_add,model_yuthon_employee_add,base.group_user,1,1,1,1
access_yuthon_pre_examination,yuthon_pre_examination,model_yuthon_pre_examination,base.group_user,1,1,1,1
+access_yuthon_service_type,yuthon_service_type,model_yuthon_service_type,base.group_user,1,1,1,1
+access_yuthon_contract_type,yuthon_contract_type,model_yuthon_contract_type,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/yuthon_hr_employee_approval/views/contract_review_approval_views.xml b/yuthon_hr_employee_approval/views/contract_review_approval_views.xml
index f528ae1c0..cdfa0e43f 100644
--- a/yuthon_hr_employee_approval/views/contract_review_approval_views.xml
+++ b/yuthon_hr_employee_approval/views/contract_review_approval_views.xml
@@ -42,12 +42,23 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -60,5 +71,4 @@
contract.review.approval
tree,form
-
-
+
\ No newline at end of file
diff --git a/yuthon_hr_employee_approval/views/inherit_hr_employee_views.xml b/yuthon_hr_employee_approval/views/inherit_hr_employee_views.xml
index 87cc4bbac..0a79d2fbb 100644
--- a/yuthon_hr_employee_approval/views/inherit_hr_employee_views.xml
+++ b/yuthon_hr_employee_approval/views/inherit_hr_employee_views.xml
@@ -10,6 +10,7 @@
+
diff --git a/yuthon_hr_employee_approval/views/yuthon_department_change_viwes.xml b/yuthon_hr_employee_approval/views/yuthon_department_change_viwes.xml
index f41739fcd..117be8fa1 100644
--- a/yuthon_hr_employee_approval/views/yuthon_department_change_viwes.xml
+++ b/yuthon_hr_employee_approval/views/yuthon_department_change_viwes.xml
@@ -5,9 +5,9 @@
yuthon.department.change
-
-
-
+
+
+
diff --git a/yuthon_hr_employee_approval/views/yuthon_service_approval_views.xml b/yuthon_hr_employee_approval/views/yuthon_service_approval_views.xml
index 10aa4fb62..a63fd49b8 100644
--- a/yuthon_hr_employee_approval/views/yuthon_service_approval_views.xml
+++ b/yuthon_hr_employee_approval/views/yuthon_service_approval_views.xml
@@ -52,11 +52,13 @@
-
-
+
+
+
-
+
+
diff --git a/yuthon_issue/models/inherit_room_booking.py b/yuthon_issue/models/inherit_room_booking.py
index 873e10fea..55152e641 100644
--- a/yuthon_issue/models/inherit_room_booking.py
+++ b/yuthon_issue/models/inherit_room_booking.py
@@ -1,5 +1,6 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError
+from datetime import timedelta
class RoomBooking(models.Model):
@@ -9,6 +10,17 @@ class RoomBooking(models.Model):
issue_meeting_line_ids = fields.One2many('issue.meeting.line', 'meeting_booking_id', string="关联议题明细行")
number_of_meetings = fields.Integer(string='会议次数')
+ @api.constrains('start_datetime')
+ def _check_start_datetime(self):
+ for meet in self.issue_meeting_line_ids:
+ if meet.issue_library_id:
+ if meet.issue_library_id.is_party == True:
+ meet.issue_library_id.party_date = self.start_datetime + timedelta(hours=8)
+ if meet.issue_library_id.is_class == True:
+ meet.issue_library_id.class_date = self.start_datetime + timedelta(hours=8)
+ if meet.issue_library_id.is_boss == True:
+ meet.issue_library_id.boss_date = self.start_datetime + timedelta(hours=8)
+
def bottom_meeting_approval(self):
library_data = []
for library in self.issue_meeting_line_ids:
diff --git a/yuthon_issue/models/issue_approval_decision.py b/yuthon_issue/models/issue_approval_decision.py
index 24e0085af..fe423ce41 100644
--- a/yuthon_issue/models/issue_approval_decision.py
+++ b/yuthon_issue/models/issue_approval_decision.py
@@ -11,6 +11,8 @@ class IssueApprovalDecision(models.Model):
decision_type_on_id = fields.Many2one('issue.approval.decision.type', string='事项类别上级')
sequence = fields.Char(string='序号', store=True)
specifics = fields.Text(string='具体事项')
+ by_law = fields.Selection([('yes', '是'), ('no', '否')], string='是否经过法律审核')
+ is_filing = fields.Selection([('yes', '备'), ('no', '否')], string='是否备案')
council_id = fields.Many2one('issue.library.type', string='党总委员会')
team_meet_id = fields.Many2one('issue.library.type', string='经营班子会')
board_meet_id = fields.Many2one('issue.library.type', string='董事会')
@@ -25,6 +27,7 @@ class IssueApprovalDecision(models.Model):
end_date = fields.Date(string="失效日期")
remarks = fields.Text(string='备注')
issue_approval_id = fields.Many2one('issue.approval', string="关联议题审批")
+ version = fields.Char(string="版本", default="V3.0")
def _get_default_company(self):
company = self.env['res.company'].search([('name', '=', '集团本部')], limit=1)
diff --git a/yuthon_issue/models/issue_library.py b/yuthon_issue/models/issue_library.py
index 1795dc1de..d840f30fa 100644
--- a/yuthon_issue/models/issue_library.py
+++ b/yuthon_issue/models/issue_library.py
@@ -12,18 +12,21 @@ class IssueLibrary(models.Model):
name = fields.Char(string='议题名称')
name_text = fields.Text(string='议题名称', compute='_compute_name', readonly=False)
depart_opinions = fields.Text(string='部门意见')
- topic_content = fields.Text(string='议题详细描述')
+ topic_content = fields.Text(string='事项背景')
will_based = fields.Text(string='上会依据')
+ deliberation_content = fields.Text(string='审议内容', default='建议同意')
is_invisible_workflow = fields.Boolean(string="流程隐藏的判断")
code = fields.Char(string='编号', required=True, copy=False,
default=lambda self: self.env['ir.sequence'].next_by_code('issue_library_code'))
issue_state = fields.Selection([('draft', '待提交'), ('approval', '审批中'), ('on_approval', '已审批'),
('will', '待上会'), ('on_meet', '已上会'), ('cancel', '已取消')],
default='draft', string="议题状态")
- is_party = fields.Boolean(string="党支委会", store=True)
- is_general_branch = fields.Boolean(string="党总支", store=True)
+ is_party = fields.Boolean(string="党总支", store=True)
+ party_date = fields.Datetime(string=' ')
is_class = fields.Boolean(string="班子会", store=True)
+ class_date = fields.Datetime(string=' ')
is_boss = fields.Boolean(string="董事会", store=True)
+ boss_date = fields.Datetime(string=' ')
is_note = fields.Boolean(string="上级单位", compute='_compute_issue_library_line_ids', store=True)
is_district_state = fields.Boolean(string="区国资局", compute='_compute_issue_library_line_ids', store=True)
is_district_government = fields.Boolean(string="区政府", compute='_compute_issue_library_line_ids', store=True)
@@ -278,10 +281,10 @@ class IssueLibrary(models.Model):
def unlink(self):
- for i in self:
- if i.issue_state == 'on_meet':
- raise UserError('议题已上会,不能删除')
- return super().unlink()
+ for i in self:
+ if i.issue_state == 'on_meet':
+ raise UserError('议题已上会,不能删除')
+ return super().unlink()
@api.depends('name')
def _compute_name(self):
diff --git a/yuthon_issue/views/inherit_room_booking.xml b/yuthon_issue/views/inherit_room_booking.xml
index 5bbe7979a..89f4a625c 100644
--- a/yuthon_issue/views/inherit_room_booking.xml
+++ b/yuthon_issue/views/inherit_room_booking.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/yuthon_issue/views/issue_approval_decision_views.xml b/yuthon_issue/views/issue_approval_decision_views.xml
index 639c2199f..8bc051342 100644
--- a/yuthon_issue/views/issue_approval_decision_views.xml
+++ b/yuthon_issue/views/issue_approval_decision_views.xml
@@ -10,14 +10,17 @@
+
+
+
@@ -50,7 +53,9 @@
-
+
+
+
@@ -58,6 +63,7 @@
+
diff --git a/yuthon_issue/views/issue_approval_views.xml b/yuthon_issue/views/issue_approval_views.xml
index b13167ebf..471745126 100644
--- a/yuthon_issue/views/issue_approval_views.xml
+++ b/yuthon_issue/views/issue_approval_views.xml
@@ -64,7 +64,8 @@
-
+
+
diff --git a/yuthon_issue/views/issue_library_views.xml b/yuthon_issue/views/issue_library_views.xml
index ea21a812f..913c69e7a 100644
--- a/yuthon_issue/views/issue_library_views.xml
+++ b/yuthon_issue/views/issue_library_views.xml
@@ -13,18 +13,21 @@
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
@@ -65,9 +68,10 @@
+
+
-
@@ -82,10 +86,8 @@
-
-
-
-
+
+
@@ -104,7 +106,8 @@
-
+
+
@@ -201,8 +204,9 @@
-
-
+
+
+
@@ -357,6 +361,7 @@
+
@@ -499,6 +504,7 @@
+
diff --git a/yuthon_maintain/models/processing_order_approval.py b/yuthon_maintain/models/processing_order_approval.py
index 1a425d4f1..67042f1a8 100644
--- a/yuthon_maintain/models/processing_order_approval.py
+++ b/yuthon_maintain/models/processing_order_approval.py
@@ -16,7 +16,8 @@ class ProcessingOrderApproval(models.Model):
display_name = fields.Char(string='名称', compute='_compute_name',)
code = fields.Char(string="编号",
default=lambda self: self.env['ir.sequence'].next_by_code('processing_order_approval_code'))
- applicant_id = fields.Many2one('res.users', string="申请人")
+ applicant_id = fields.Many2one('res.users', string="报修人")
+ repair_date = fields.Date(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="部门")
company_id = fields.Many2one(related='users_id.employee_id.company_id', string="公司")
@@ -99,6 +100,28 @@ class ProcessingOrderApproval(models.Model):
else:
record.contract_id = False
+ def open_record(self):
+ if self.device_id:
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': self.device_id.display_name,
+ 'res_model': 'property.device.repair',
+ 'res_id': self.device_id.id,
+ 'view_mode': 'form',
+ 'view_type': 'form',
+ 'target': 'new'
+ }
+ elif self.repair_id:
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': self.repair_id.display_name,
+ 'res_model': 'property.report.repair',
+ 'res_id': self.repair_id.id,
+ 'view_mode': 'form',
+ 'view_type': 'form',
+ 'target': 'new'
+ }
+
@api.onchange('repair_id')
def onchange_repair_id(self):
if self.repair_id:
diff --git a/yuthon_maintain/models/property_device_repair.py b/yuthon_maintain/models/property_device_repair.py
index 8e15aaf7a..44514a058 100644
--- a/yuthon_maintain/models/property_device_repair.py
+++ b/yuthon_maintain/models/property_device_repair.py
@@ -7,8 +7,7 @@ from odoo.exceptions import UserError, ValidationError
class PropertyDeviceRelief(models.Model):
_name = 'property.device.repair'
- _description = '报事报修(办公设备)'
- _inherit = ['soong.workflow.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
+ _description = '报事报修'
name = fields.Char(string='标题', compute='_compute_name', store=True)
code = fields.Char(string="报修编号",
@@ -18,8 +17,7 @@ class PropertyDeviceRelief(models.Model):
company_id = fields.Many2one(related='users_id.employee_id.company_id', string="公司")
software_processing_id = fields.Many2one('software.issues.processing', string="设备类型")
problem_description = fields.Text(string="问题描述")
- remake = fields.Text(string="问题描述")
- report_state = fields.Selection([('to', '待处理'), ('done', '已处理')], string='状态', default='to')
+ report_state = fields.Selection([('to_submitted', '待提交'), ('to', '待处理'), ('done', '已处理')], string='状态', default='to_submitted')
create_time = fields.Date(string="填报日期", default=fields.Datetime.now)
urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
default='normal')
@@ -38,15 +36,31 @@ class PropertyDeviceRelief(models.Model):
def _compute_name(self):
for rec in self:
if rec.users_id and rec.software_processing_id:
- rec.name = f" {rec.software_processing_id.name}-{rec.users_id.name}"
+ rec.name = f"{rec.users_id.name}-{rec.software_processing_id.name}-{rec.problem_description}"
+ def device_delete(self):
+ self.unlink()
+
+ def open_record(self):
+ return {
+ "type": "ir.actions.act_window",
+ "res_model": 'processing.order.approval',
+ "res_id": self.processing_order_id.id,
+ "name": '详情',
+ "view_mode": "form",
+ }
+
+ def get_no_read_count(self):
+ return self.search_count([('report_state', '=', 'to'), ('users_id', '=', self.env.user.id)])
def pull_order(self):
soong_workflow_line_list = []
+ self.report_state = 'to'
if self.env['processing.order.approval'].search([('device_id', '=', self.id)]):
raise UserError('该设备已生成处理单')
order_id = self.env['processing.order.approval'].create({
'device_id': self.id,
+ 'repair_date': self.create_time,
'applicant_id': self.users_id.id,
'name': self.problem_description,
'code': self.env['ir.sequence'].next_by_code('property_device_repair_code'),
diff --git a/yuthon_maintain/models/property_report_repair.py b/yuthon_maintain/models/property_report_repair.py
index 8cec20bbe..b51dfce9b 100644
--- a/yuthon_maintain/models/property_report_repair.py
+++ b/yuthon_maintain/models/property_report_repair.py
@@ -8,7 +8,6 @@ from odoo.exceptions import UserError
class PropertyRentRelief(models.Model):
_name = 'property.report.repair'
_description = '报事报修(物业)'
- _inherit = ['soong.workflow.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
name = fields.Char(string='标题', compute='_compute_name', store=True)
code = fields.Char(string="报修编号",
@@ -29,8 +28,6 @@ class PropertyRentRelief(models.Model):
documents_ids = fields.Many2many('ir.attachment', string="附件")
active = fields.Boolean('Active', default=True, tracking=True)
work_end = fields.Boolean(string="结束")
- self_users_ids = fields.Many2many('res.users', string="当前经办人",
- default=lambda self: [(6, 0, [self.env.user.id])])
create_time = fields.Date(string="填报日期", default=fields.Datetime.now)
processing_order_id = fields.Many2one('processing.order.approval', string="处理单")
def _get_default_name_title(self):
@@ -70,6 +67,7 @@ class PropertyRentRelief(models.Model):
raise UserError('该设备已生成处理单')
order_id = self.env['processing.order.approval'].create({
'repair_id': self.id,
+ 'repair_date': self.create_time,
'applicant_id': self.users_id.id,
'name': self.problem_description,
'problem_description': self.problem_description,
diff --git a/yuthon_maintain/views/processing_order_approval_views.xml b/yuthon_maintain/views/processing_order_approval_views.xml
index a2a1c4e9a..fd90c73fb 100644
--- a/yuthon_maintain/views/processing_order_approval_views.xml
+++ b/yuthon_maintain/views/processing_order_approval_views.xml
@@ -43,15 +43,19 @@
-
+
+
+
-
+
+
+
@@ -68,12 +72,11 @@
-
-
+
diff --git a/yuthon_maintain/views/property_device_repair_views.xml b/yuthon_maintain/views/property_device_repair_views.xml
index 012f7271a..43d3dc357 100644
--- a/yuthon_maintain/views/property_device_repair_views.xml
+++ b/yuthon_maintain/views/property_device_repair_views.xml
@@ -4,13 +4,15 @@
property.device.repair.tree
property.device.repair
-
+
-
+
+
+
@@ -18,7 +20,7 @@
property.device.repair.form
property.device.repair
-
@@ -58,7 +61,13 @@
- 报事报修(办公设备)
+ 报事报修
+ property.device.repair
+ [('users_id', '=', uid)]
+ tree,form
+
+
+ 报事报修(管理员)
property.device.repair
tree,form
diff --git a/yuthon_maintain/views/property_report_repair.xml b/yuthon_maintain/views/property_report_repair.xml
index 1f75d9501..53ea13d0d 100644
--- a/yuthon_maintain/views/property_report_repair.xml
+++ b/yuthon_maintain/views/property_report_repair.xml
@@ -49,7 +49,6 @@
-
diff --git a/yuthon_notice/models/yuthon_notice.py b/yuthon_notice/models/yuthon_notice.py
index 5c8637673..896697530 100644
--- a/yuthon_notice/models/yuthon_notice.py
+++ b/yuthon_notice/models/yuthon_notice.py
@@ -2,6 +2,7 @@
from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError, UserError
import logging
+from datetime import datetime, timedelta, date
_logger = logging.getLogger(__name__)
@@ -58,6 +59,12 @@ class YuthonNotice(models.Model):
default=lambda self: [(6, 0, [self.env.user.id])]
)
+ # @api.onchange('users_ids')
+ # def _onchange_users_ids(self):
+ # today = date.today()
+ # self.start_date = today
+ # self.create_date1 = today
+
@api.model_create_multi
def create(self, vals_list):
for i in vals_list:
diff --git a/yuthon_property/__manifest__.py b/yuthon_property/__manifest__.py
index 26741f1b2..5fb268817 100644
--- a/yuthon_property/__manifest__.py
+++ b/yuthon_property/__manifest__.py
@@ -9,6 +9,7 @@
'license': 'LGPL-3',
'data': [
'security/ir.model.access.csv',
+ 'security/bank_company_rule.xml',
'security/yuthon_property_group.xml',
'security/yuthon_accounts_group.xml',
'data/data_yuthon_resource_mgmt_config.xml',
diff --git a/yuthon_property/models/property_bank_statements.py b/yuthon_property/models/property_bank_statements.py
index b07d7991a..081af1bb7 100644
--- a/yuthon_property/models/property_bank_statements.py
+++ b/yuthon_property/models/property_bank_statements.py
@@ -39,14 +39,24 @@ class PropertyBankStatements(models.Model):
voucher_type = fields.Selection([('electronic_transfer', '电子转账凭证'), ('telegraphic_transfer', '电汇凭证')], string='凭证种类')
remake = fields.Text('备注')
registered = fields.Float('挂账')
- is_reconciliation = fields.Boolean('是否对账') # 无效
+ is_reconciliation = fields.Boolean('是否对账')
company_select = fields.Selection([('jhtz', '天河投资'), ('thwg', '天河物管'), ('thcj', '天河城建')])
property_ids = fields.Many2many('yuthon.property', string='物业地址')
bank_state = fields.Selection([('not_reconciled', '未对账'), ('reconciled', '已对账'), ('registered', '挂账'), ('other', '其他')], string='状态', default='not_reconciled')
- is_company = fields.Boolean(compute='_compute_is_company', search='_search_part_of_company', default=True)
+ company_id1 = fields.Many2one('res.company', string='公司')
change_amount = fields.Float(string='修改金额')
receivable_modify_ids = fields.One2many('receivable.modify.line', 'bank_id', string='修改应收单')
+ def update_company_id(self):
+ records = self.env['property.bank.statements'].search([])
+ for record in records:
+ if record.your_own_unit in ['天河投资', '天投城建']:
+ record.company_id1 = self.env['res.company'].search([('name', '=', '集团本部')], limit=1)
+ elif record.your_own_unit in ['天河物管']:
+ record.company_id1 = self.env['res.company'].search([('name', '=', '天河物管')], limit=1)
+ elif record.your_own_unit in ['天河粮储']:
+ record.company_id1 = self.env['res.company'].search([('name', '=', '天河粮储')], limit=1)
+
def update_record(self):
selected_records = self.env["property.bank.statements"].browse(
self._context.get('active_ids', self._context.get('active_id'))
@@ -112,43 +122,6 @@ class PropertyBankStatements(models.Model):
bank_id.change_amount = change_amount
bank_id.yes_amount = change_amount
- @api.depends_context('uid', 'company')
- @api.depends('your_own_account')
- def _compute_is_company(self):
- user_companies = self.env['res.company'].browse(self.env.companies.ids)
- user_company_names = set(user_companies.mapped('name'))
- # 预定义账号映射关系
- account_mapping = {
- '集团本部': ['天河投资', '天投城建'],
- '天河物管': ['天河物管'],
- '天河粮储': ['天河粮储']
- }
- for record in self:
- # 默认不可见
- record.is_company = False
- # 检查账号是否符合规则
- for company_name, allowed_accounts in account_mapping.items():
- if company_name in user_company_names:
- if record.your_own_unit in allowed_accounts:
- record.is_company = True
- break
-
-
- def _search_part_of_company(self, operator, value):
- if operator not in ('=', '!=') or not isinstance(value, bool):
- raise UserError(_('操作不支持'))
- user_companies = self.env['res.company'].browse(self.env.companies.ids)
- company_names = user_companies.mapped('name')
- visible_accounts = []
- if "集团本部" in company_names:
- visible_accounts.extend(['天河投资', '天投城建'])
- if "天河物管" in company_names:
- visible_accounts.append('天河物管')
- if not value:
- operator = '!=' if operator == '=' else '='
- domain = [('your_own_unit', 'in', visible_accounts)] if operator == '=' and visible_accounts else []
- return domain or [('id', '=', 0)]
-
def other(self):
bank_ids = self.env["property.bank.statements"].browse(
self._context.get('active_ids', self._context.get('active_id')))
diff --git a/yuthon_property/security/bank_company_rule.xml b/yuthon_property/security/bank_company_rule.xml
new file mode 100644
index 000000000..6f2542c87
--- /dev/null
+++ b/yuthon_property/security/bank_company_rule.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yuthon_property/views/property_bank_statements_views.xml b/yuthon_property/views/property_bank_statements_views.xml
index 32dac9d64..38357a6dc 100644
--- a/yuthon_property/views/property_bank_statements_views.xml
+++ b/yuthon_property/views/property_bank_statements_views.xml
@@ -16,7 +16,6 @@
-
@@ -45,7 +44,6 @@
-
@@ -107,9 +105,15 @@
银行流水
property.bank.statements
tree,form,search
-
{'group_by': 'bank_state'}
+
+ 更新公司
+
+
+ code
+ action = model.update_company_id()
+
\ No newline at end of file
diff --git a/yuthon_property_approval/models/property_lease_renewal.py b/yuthon_property_approval/models/property_lease_renewal.py
index 614f47a5c..3af7c4ed2 100644
--- a/yuthon_property_approval/models/property_lease_renewal.py
+++ b/yuthon_property_approval/models/property_lease_renewal.py
@@ -19,7 +19,7 @@ class PropertyLeaseRenewal(models.Model):
company_id = fields.Many2one(related='user_id.company_id', string="公司")
code = fields.Char(string="编号",
default=lambda self: self.env['ir.sequence'].next_by_code('property_lease_renewal_code'))
- renewal_type = fields.Selection([('early_checkout', '提前退租'), ('lease', '承租方变更')], string='变更类型')
+ renewal_type = fields.Selection([('early_checkout', '合同终止'), ('lease', '承租方变更')], string='变更类型')
urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
default='normal')
def _get_default_name_title(self):
diff --git a/yuthon_property_approval/wizard/penalty_line_wizard.py b/yuthon_property_approval/wizard/penalty_line_wizard.py
index 02236b8da..fb7f39025 100644
--- a/yuthon_property_approval/wizard/penalty_line_wizard.py
+++ b/yuthon_property_approval/wizard/penalty_line_wizard.py
@@ -129,10 +129,13 @@ class PenaltyLineWizard(models.Model):
# 计算剩余本金
remaining_principal = max(0, pay_line.not_collected - pay_amount)
penalty_start_date = pay_date
-
+ if is_penalty:
+ remake = f'支付违约金¥{pay_line.amount}'
+ else:
+ remake = f'支付金额¥{pay_line.amount}'
new_penalty_lines.append((0, 0, {
'date': pay_date,
- 'remake': f'支付金额¥{pay_line.amount}',
+ 'remake':remake,
'days_overdue': days_overdue,
'remaining_principal': remaining_principal,
'penalty': round(current_penalty, 2),
@@ -186,7 +189,7 @@ class PenaltyLineWizard(models.Model):
if non_realtime_lines:
prev_line = non_realtime_lines[-1]
if round(prev_line.remaining_principal or 0, 2) != 0:
- base_date = prev_line.date + relativedelta(months=1)
+ base_date = (prev_line.date + relativedelta(months=1)).replace(day=1)
days_overdue = (self.calculation_date - base_date).days - 1
days_overdue = max(0, days_overdue)
# 计算违约金
@@ -196,7 +199,7 @@ class PenaltyLineWizard(models.Model):
'date': self.calculation_date,
'days_overdue': days_overdue,
'remaining_principal': prev_line.remaining_principal,
- 'remake': f'{base_date}至{self.calculation_date}',
+ 'remake': f'违约金:{base_date}至{self.calculation_date}',
'penalty': round(current_penalty, 2),
'is_realtime': True,
}))
diff --git a/yuthon_property_approval/wizard/property_reconciliation_wizard.py b/yuthon_property_approval/wizard/property_reconciliation_wizard.py
index a25031ea2..1980fe84b 100644
--- a/yuthon_property_approval/wizard/property_reconciliation_wizard.py
+++ b/yuthon_property_approval/wizard/property_reconciliation_wizard.py
@@ -586,9 +586,13 @@ class PropertyReconciliationWizard(models.Model):
'is_write': True if line.amount != 0 else False,
'is_penalty': True,
'reconciliation_date': rec.actual_date if line.amount != 0 else None,
- 'receivable_id': receivable_id.id,
+ 'receivable_id': receivable_id[0].id,
'amount': line.amount,
})
+ # 删除多余的违约金数据
+ if len(receivable_id) > 1:
+ receivable_id = existing_record[1:]
+ receivable_id.unlink()
rec.amount_been_reconciled += line.amount
yes_amount += line.amount
@@ -607,7 +611,6 @@ class PropertyReconciliationWizard(models.Model):
if unreconciled_receivables:
remaining_contract_ids.append(contract.id)
-
class PropertyReconciliationLine(models.Model):
_name = 'property.reconciliation.line'
_description = '对账明细'
diff --git a/yuthon_purchase/__manifest__.py b/yuthon_purchase/__manifest__.py
index 09b987d3a..210bead75 100644
--- a/yuthon_purchase/__manifest__.py
+++ b/yuthon_purchase/__manifest__.py
@@ -10,6 +10,7 @@
'data': [
'security/ir.model.access.csv',
'security/company_rule.xml',
+ 'data/process_code_data.xml',
'report/purchase_workflow_report.xml',
'report/purchase_workflow_templates.xml',
'views/inherit_product_product_views.xml',
diff --git a/yuthon_purchase/data/process_code_data.xml b/yuthon_purchase/data/process_code_data.xml
index 19cda0b0e..e1c3c3916 100644
--- a/yuthon_purchase/data/process_code_data.xml
+++ b/yuthon_purchase/data/process_code_data.xml
@@ -7,4 +7,9 @@
3
+
+ 采购多公司
+
+ [('company_id', 'in', company_ids)]
+
diff --git a/yuthon_purchase/models/inherit_purchase_order.py b/yuthon_purchase/models/inherit_purchase_order.py
index e2d67aab7..6caf4fcf4 100644
--- a/yuthon_purchase/models/inherit_purchase_order.py
+++ b/yuthon_purchase/models/inherit_purchase_order.py
@@ -9,14 +9,44 @@ class InheritPurchaseOrder(models.Model):
_name = 'purchase.order'
_inherit = ['purchase.order', 'soong.workflow.mixin']
+
json_display = fields.Char(
string="物品详情",
compute='_compute_json_display',
store=True
)
+ code = fields.Char(string="流水号", default=lambda self: self.env['ir.sequence'].next_by_code('purchase_workflow_approval_code'))
+ state = fields.Selection(selection_add=[('部门经理', '部门经理'),
+ ('协办', '协办'),
+ ('分管领导', '分管领导'),
+ ('总经理', '总经理')], default='draft')
work_end = fields.Boolean(string="结束")
+ user_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user)
+ company_id = fields.Many2one(related='user_id.employee_ids.company_id', string="公司")
+ department_id = fields.Many2one(related='user_id.employee_ids.department_id', string="部门")
document_ids = fields.Many2many('ir.attachment', string="附件")
+ start_date = fields.Date(string="申请日期", default=fields.Date.today())
+ purchase_type = fields.Selection(
+ [('fixed', '固定资产'), ('low', '低值易耗'), ('service', '服务'), ('day', '日常消耗品')],
+ string="采购类型", default='fixed')
+ pay_way = fields.Selection([('onetime', '一次性'), ('installment', '分期')], string="付款方式", default='onetime')
+ reason_text = fields.Text(string="申请事由")
+ pay_line_ids = fields.One2many('purchase.order.pay.line', 'order_id', string="付款详情")
+ low_line_ids = fields.One2many('purchase.low.line', 'order_id', string="低值易耗明细")
+ service_line_ids = fields.One2many('purchase.service.line', 'order_id', string="服务明细")
+ fixed_line_ids = fields.One2many('purchase.fixed.line', 'order_id', string="日常消耗品明细")
+ def update_state(self):
+ order_ids = self.env["purchase.order"].browse(
+ self._context.get('active_ids', self._context.get('active_id')))
+ for order in order_ids:
+ order.button_cancel()
+
+
+ def end_approval(self):
+ self.button_confirm()
+ self.state = 'purchase'
+ self.write({'work_end': True})
@api.depends(
'order_line.product_id',
diff --git a/yuthon_purchase/models/purchase_workflow.py b/yuthon_purchase/models/purchase_workflow.py
index 5ea9e7a37..26b753cc6 100644
--- a/yuthon_purchase/models/purchase_workflow.py
+++ b/yuthon_purchase/models/purchase_workflow.py
@@ -24,13 +24,14 @@ class PurchaseWorkflow(models.Model):
default='normal', required=True)
pay_way = fields.Selection([('onetime', '一次性'), ('installment', '分期')], string="付款方式", default='onetime',
required=True)
+ pay_amount = fields.Float(string="付款金额")
total = fields.Float(string="合计金额", readonly=True)
document_ids = fields.Many2many('ir.attachment', string="附件")
active = fields.Boolean('启用', default=True, tracking=True)
work_end = fields.Boolean(string="审批结束", default=False, tracking=True)
purchase_order_id = fields.Many2one('purchase.order', string="采购订单", readonly=True)
- purchase_type = fields.Selection([('fixed', '固定资产'), ('low', '低值易耗'), ('service', '服务')],
+ purchase_type = fields.Selection([('fixed', '固定资产'), ('low', '低值易耗'), ('service', '服务'), ('day', '日常消耗品')],
string="采购类型", required=True, default='fixed')
service_content = fields.Text(string="服务内容")
@@ -45,6 +46,7 @@ class PurchaseWorkflow(models.Model):
service_line_ids = fields.One2many('purchase.service.line', 'service_id', string="服务明细")
pay_line_ids = fields.One2many('purchase.order.pay.line', 'purchase_id', string="付款详情")
+
@api.onchange('purchase_type')
def _onchange_purchase_type(self):
if self.purchase_type == 'fixed':
@@ -113,6 +115,7 @@ class PurchaseOrderPayLine(models.Model):
_description = "付款详情"
purchase_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
+ order_id = fields.Many2one('purchase.order', string="关联采购")
payment_stage = fields.Char(string="付款阶段")
amount = fields.Char(string="比例/金额")
payment_date = fields.Date(string="付款日期")
@@ -125,14 +128,15 @@ class PurchaseFixedLine(models.Model):
purchase_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
product_id = fields.Many2one('product.product', string="物品名称")
+ order_id = fields.Many2one('purchase.order', string="关联采购")
brand = fields.Char(string="品牌")
specs = fields.Char(string="规格")
- number = fields.Integer(string="数量",)
+ number = fields.Integer(string="数量")
name = fields.Text(string="描述")
product_packaging_id = fields.Many2one('product.packaging', string="包装")
taxes_id = fields.Many2one('account.tax', string='税项')
- unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
- price_unit = fields.Float(related='product_id.standard_price', string="单价", store=True)
+ unit_id = fields.Many2one('uom.uom', string="单位")
+ price_unit = fields.Float(string="单价", store=True)
total = fields.Float(string="合计", compute='_compute_total', store=True)
@api.depends('price_unit', 'number')
@@ -144,20 +148,25 @@ class PurchaseFixedLine(models.Model):
def _onchange_product_id(self):
if self.product_id:
self.name = self.product_id.display_name
+ self.unit_id = self.product_id.uom_id
+ self.price_unit = self.product_id.standard_price
+
class PurchaseLowLine(models.Model):
_name = 'purchase.low.line'
_description = '低值易耗采购明细'
purchase_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
+
product_id = fields.Many2one('product.product', string="物品名称")
- brand = fields.Char(related="product_id.brand", string="品牌")
- specs = fields.Char(related="product_id.specs", string="规格")
+ order_id = fields.Many2one('purchase.order', string="关联采购")
+ brand = fields.Char(string="品牌")
+ specs = fields.Char(string="规格")
name = fields.Text(string="描述")
product_packaging_id = fields.Many2one('product.packaging', string="包装")
taxes_id = fields.Many2one('account.tax', string='税项')
number = fields.Integer(string="数量")
- unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
- price = fields.Float(related='product_id.standard_price', string="单价", store=True)
+ unit_id = fields.Many2one('uom.uom', string="单位")
+ price = fields.Float(string="单价", store=True)
total = fields.Float(string="合计", compute='_compute_total', store=True)
@api.depends('price', 'number')
@@ -169,20 +178,26 @@ class PurchaseLowLine(models.Model):
def _onchange_product_id(self):
if self.product_id:
self.name = self.product_id.display_name
+ self.brand = self.product_id.brand
+ self.specs = self.product_id.specs
+ self.unit_id = self.product_id.uom_id
+ self.price = self.product_id.standard_price
+# 服务采购明细
class PurchaseServiceLine(models.Model):
_name = 'purchase.service.line'
_description = '服务采购明细'
service_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
product_id = fields.Many2one('product.product', string="服务项目")
+ order_id = fields.Many2one('purchase.order', string="关联采购")
frequency = fields.Integer(string='频次')
fee = fields.Float(string="费用")
- name = fields.Text(string="描述", default=lambda self: self.product_id.display_name if self.product_id else False )
+ name = fields.Text(string="描述")
product_packaging_id = fields.Many2one('product.packaging', string="包装")
taxes_id = fields.Many2one('account.tax', string='税项')
- unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
- price = fields.Float(related='product_id.standard_price', string="单价", store=True)
+ unit_id = fields.Many2one('uom.uom', string="单位")
+ price = fields.Float(string="单价", store=True)
total = fields.Float(string="合计", compute='_compute_total', store=True)
@api.depends('price', 'frequency')
@@ -194,6 +209,9 @@ class PurchaseServiceLine(models.Model):
def _onchange_product_id(self):
if self.product_id:
self.name = self.product_id.display_name
+ self.unit_id = self.product_id.uom_id
+ self.price = self.product_id.standard_price
+
class PurchaseFixedAssets(models.Model):
_name = 'purchase.fixed.assets'
diff --git a/yuthon_purchase/views/inherit_purchase_order_views.xml b/yuthon_purchase/views/inherit_purchase_order_views.xml
index 4245824ab..0a7550854 100644
--- a/yuthon_purchase/views/inherit_purchase_order_views.xml
+++ b/yuthon_purchase/views/inherit_purchase_order_views.xml
@@ -8,6 +8,9 @@
1
+
+ 1
+
1
@@ -22,12 +25,59 @@
+
+ purchase.order.kpis.tree
+ purchase.order
+
+
+
+ 事项
+
+
+ 1
+
+
+
+
+
+ 1
+
+
+ 1
+
+
+
purchase.order.form
purchase.order
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
@@ -35,22 +85,82 @@
[('is_employee', '=', False)]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ purchase_type != 'fixed'
+ 固定资产明细
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+ 取消
+
+
+ code
+ action = model.update_state()
+
diff --git a/yuthon_purchase/views/purchase_workflow_views.xml b/yuthon_purchase/views/purchase_workflow_views.xml
index f7b3b9aec..c122610f4 100644
--- a/yuthon_purchase/views/purchase_workflow_views.xml
+++ b/yuthon_purchase/views/purchase_workflow_views.xml
@@ -47,13 +47,14 @@
-
-
-
+
+
+
+
@@ -92,6 +93,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/yuthon_report/static/src/components/yuthon_report/receivable_report.xml b/yuthon_report/static/src/components/yuthon_report/receivable_report.xml
index f570e3741..2fe74d87f 100644
--- a/yuthon_report/static/src/components/yuthon_report/receivable_report.xml
+++ b/yuthon_report/static/src/components/yuthon_report/receivable_report.xml
@@ -8,23 +8,18 @@
-
-
+
-
-
-
+
-
+
+
-
diff --git a/yuthon_salary/__manifest__.py b/yuthon_salary/__manifest__.py
index 49be4f687..a2511b537 100644
--- a/yuthon_salary/__manifest__.py
+++ b/yuthon_salary/__manifest__.py
@@ -35,6 +35,7 @@
'wizard/yuthon_salary_wizard_views.xml',
'wizard/salary_party_wizard_views.xml',
'wizard/temporary_payslip_wizard_views.xml',
+ 'wizard/salary_import_wizard_views.xml',
'wizard/yuthon_payroll_wizard_views.xml',
'wizard/basic_pension_wizard_views.xml',
'wizard/payroll_labor_wizard_views.xml',
@@ -61,8 +62,10 @@
'yuthon_salary/static/src/js/salary_retired_button.js',
'yuthon_salary/static/src/js/salary_validation_button.js',
'yuthon_salary/static/src/js/salary_year_button.js',
+ 'yuthon_salary/static/src/js/salary_import_button.js',
'yuthon_salary/static/src/xml/salary_create_button.xml',
'yuthon_salary/static/src/xml/salary_labor_button.xml',
+ 'yuthon_salary/static/src/xml/salary_import_button.xml',
'yuthon_salary/static/src/xml/salary_retired_button.xml',
'yuthon_salary/static/src/xml/salary_payslip_button.xml',
'yuthon_salary/static/src/xml/salary_documents_button.xml',
diff --git a/yuthon_salary/models/inherit_hr_payslip.py b/yuthon_salary/models/inherit_hr_payslip.py
index 474afc099..2361a99c1 100644
--- a/yuthon_salary/models/inherit_hr_payslip.py
+++ b/yuthon_salary/models/inherit_hr_payslip.py
@@ -385,23 +385,23 @@ class InheritHrPayslip(models.Model):
res = super(InheritHrPayslip, self).create(vals_list)
return res
- @api.model
- def create(self, vals):
- """
- 为了解决部分薪资生成未生效,单独处理计算公式
- 工会会费:round(abs(payslip.base_salary * 0.005) * -1, 2) --union_dues
- :param vals:
- :return:
- """
- record = super().create(vals)
- employee_id = self.env['hr.employee'].search([('id', '=', vals['employee_id'])])
- payroll = self.env['hr.contract'].search([('employee_id', '=', employee_id.id), ('state', '=', 'open')])[-1].structure_type_id.default_struct_id
- if payroll.rule_ids.search([('name', '=', '基本工资'), ('struct_id', '=', payroll.id)]):
- base_salary = payroll.rule_ids.search([('name', '=', '基本工资'), ('struct_id', '=', payroll.id)])[-1].amount_fix
- # if record.worked_days_line_ids.search([('name', '=', '工会会费')]):
- # record.line_ids.search([('name', '=', '工会会费')]).total = round(abs(base_salary * 0.005) * -1, 2)
- record.write({'union_dues': round(abs(base_salary * 0.005) * -1, 2)})
- return record
+ # @api.model
+ # def create(self, vals):
+ # """
+ # 为了解决部分薪资生成未生效,单独处理计算公式
+ # 工会会费:round(abs(payslip.base_salary * 0.005) * -1, 2) --union_dues
+ # :param vals:
+ # :return:
+ # """
+ # record = super().create(vals)
+ # employee_id = self.env['hr.employee'].search([('id', '=', vals['employee_id'])])
+ # payroll = self.env['hr.contract'].search([('employee_id', '=', employee_id.id), ('state', '=', 'open')])[-1].structure_type_id.default_struct_id
+ # if payroll.rule_ids.search([('name', '=', '基本工资'), ('struct_id', '=', payroll.id)]):
+ # base_salary = payroll.rule_ids.search([('name', '=', '基本工资'), ('struct_id', '=', payroll.id)])[-1].amount_fix
+ # # if record.worked_days_line_ids.search([('name', '=', '工会会费')]):
+ # # record.line_ids.search([('name', '=', '工会会费')]).total = round(abs(base_salary * 0.005) * -1, 2)
+ # record.write({'union_dues': round(abs(base_salary * 0.005) * -1, 2)})
+ # return record
@api.ondelete(at_uninstall=False)
def _unlink_if_draft_or_cancel(self):
diff --git a/yuthon_salary/security/ir.model.access.csv b/yuthon_salary/security/ir.model.access.csv
index b6690aef6..bfa5c3a25 100644
--- a/yuthon_salary/security/ir.model.access.csv
+++ b/yuthon_salary/security/ir.model.access.csv
@@ -36,4 +36,5 @@ access_rank_log_line,access_rank_log_line,model_rank_log_line,base.group_user,1,
access_rank_log_wizard,access_rank_log_wizard,model_rank_log_wizard,base.group_user,1,1,1,1
access_basic_pension_wizard,access_basic_pension_wizard,model_basic_pension_wizard,base.group_user,1,1,1,1
access_yuthon_salary_party,access_yuthon_salary_party,model_yuthon_salary_party,base.group_user,1,1,1,1
-access_salary_party_wizard,access_salary_party_wizard,model_salary_party_wizard,base.group_user,1,1,1,1
\ No newline at end of file
+access_salary_party_wizard,access_salary_party_wizard,model_salary_party_wizard,base.group_user,1,1,1,1
+access_salary_import_wizard,access_salary_import_wizard,model_salary_import_wizard,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/yuthon_salary/static/src/js/salary_import_button.js b/yuthon_salary/static/src/js/salary_import_button.js
new file mode 100644
index 000000000..b3407e9c0
--- /dev/null
+++ b/yuthon_salary/static/src/js/salary_import_button.js
@@ -0,0 +1,29 @@
+/** @odoo-module */
+import { ListController } from "@web/views/list/list_controller";
+import { registry } from '@web/core/registry';
+import { listView } from '@web/views/list/list_view';
+
+export class CustomSalaryImportController extends ListController {
+ setup() {
+ super.setup();
+ }
+
+ openSalaryImportWizard() {
+ this.actionService.doAction({
+ type: 'ir.actions.act_window',
+ res_model: 'salary.import.wizard',
+ name: '薪资导入',
+ view_mode: 'form',
+ view_type: 'form',
+ views: [[false, 'form']],
+ target: 'new', // 以弹窗形式打开
+ context: {},
+ });
+ }
+}
+
+registry.category("views").add("custom_salary_import_button", {
+ ...listView,
+ Controller: CustomSalaryImportController,
+ buttonTemplate: "salary_import_module.ListView.Buttons",
+});
\ No newline at end of file
diff --git a/yuthon_salary/static/src/xml/salary_import_button.xml b/yuthon_salary/static/src/xml/salary_import_button.xml
new file mode 100644
index 000000000..aade38590
--- /dev/null
+++ b/yuthon_salary/static/src/xml/salary_import_button.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ 薪资导入
+
+
+
+
diff --git a/yuthon_salary/views/inherit_hr_payslip_views.xml b/yuthon_salary/views/inherit_hr_payslip_views.xml
index 878747f4c..b0d7e4399 100644
--- a/yuthon_salary/views/inherit_hr_payslip_views.xml
+++ b/yuthon_salary/views/inherit_hr_payslip_views.xml
@@ -242,7 +242,7 @@
hr.payslip.tree.validation.jtbb
hr.payslip
-
+
@@ -312,7 +312,7 @@
hr.payslip.tree.validation.wg
hr.payslip
-
+
@@ -369,7 +369,7 @@
hr.payslip.tree.validation_lc
hr.payslip
-
+
diff --git a/yuthon_salary/wizard/__init__.py b/yuthon_salary/wizard/__init__.py
index 4991f5c1f..c5e46fbca 100644
--- a/yuthon_salary/wizard/__init__.py
+++ b/yuthon_salary/wizard/__init__.py
@@ -14,3 +14,4 @@ from . import initialize_payroll_wizard
from . import rank_log_wizard
from . import basic_pension_wizard
from . import salary_party_wizard
+from . import salary_import_wizard
\ No newline at end of file
diff --git a/yuthon_salary/wizard/salary_import_wizard.py b/yuthon_salary/wizard/salary_import_wizard.py
new file mode 100644
index 000000000..3bc17bea4
--- /dev/null
+++ b/yuthon_salary/wizard/salary_import_wizard.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+from odoo import models, fields, api, _, SUPERUSER_ID
+from odoo.exceptions import ValidationError, UserError
+from pypinyin import pinyin, Style
+import xlrd
+import base64
+import datetime
+from datetime import datetime, timedelta
+
+class SalaryImportWizard(models.TransientModel):
+ _name = 'salary.import.wizard'
+ _description = '薪资导入弹窗'
+
+ file = fields.Binary(string='File', required=True)
+ excel_file = fields.Binary(string="上传Excel表")
+ excel_name = fields.Char(string="文件名")
+
+ def confirm(self):
+ if not self.excel_file:
+ raise ValidationError('请上传文件。')
+ book = xlrd.open_workbook(file_contents=base64.decodebytes(self.excel_file))
+ sh = book.sheet_by_index(0)
+ header_row = sh.row(0)
+ excel_headers = [str(cell.value).strip() for cell in header_row if cell.value]
+ invalid_headers = [header for header in excel_headers]
+ for rx in range(1, sh.nrows):
+ row = sh.row(rx)
+ self.salary_party_data(row, excel_headers)
+
+ def salary_party_data(self, row, excel_headers):
+ employee_name = row[0].value
+ employee = self.env['hr.employee'].search([('name', '=', employee_name)], limit=1)
+ if employee:
+ payslip_run_name = f"{2025}年-八月"
+ payslip_run_id = self.env['hr.payslip.run'].search(
+ [('name', '=', payslip_run_name), ('company_id', '=', employee.company_id.id)], limit=1)
+ payslip = self.env['hr.payslip'].search([
+ ('payslip_run_id', '=', payslip_run_id.id),
+ ('employee_id', '=', employee.id),
+ ], limit=1)
+ if not payslip:
+ payslip_vals = {
+ 'name': employee.name,
+ 'employee_id': employee.id,
+ 'contract_id': employee.contract_id.id,
+ 'payslip_run_id': payslip_run_id.id,
+ 'date_from': datetime(2025, 8, 1).date() ,
+ 'date_to': datetime(2025, 8, 31).date(),
+ 'is_salary_push': True,
+ 'is_salary_release': False
+ }
+ payslip = self.env['hr.payslip'].create(payslip_vals)
+ payslip.compute_sheet()
+ else:
+ payslip.is_salary_push = True
+ payslip.is_salary_release = False
+
+ for line in payslip.line_ids:
+ line_name = line.name
+ if line_name not in excel_headers:
+ continue
+ header_idx = excel_headers.index(line_name) + 1
+ amount = row[header_idx].value
+ if amount == 0.0:
+ continue
+ line.write({
+ 'amount': amount,
+ 'total': amount,
+ })
+
+ def _get_chinese_month(self, month):
+ chinese_months = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月',
+ '十二月']
+ return chinese_months[month - 1]
\ No newline at end of file
diff --git a/yuthon_salary/wizard/salary_import_wizard_views.xml b/yuthon_salary/wizard/salary_import_wizard_views.xml
new file mode 100644
index 000000000..bb28068e0
--- /dev/null
+++ b/yuthon_salary/wizard/salary_import_wizard_views.xml
@@ -0,0 +1,34 @@
+
+
+
+ 模板下载
+ self
+ /yuthon_salary/static/others/salary_party.xlsx
+
+
+ 弹窗
+ salary.import.wizard
+
+
+
+
+
diff --git a/yuthon_will_task/controllers/main.py b/yuthon_will_task/controllers/main.py
index 853e24822..266e9ebec 100644
--- a/yuthon_will_task/controllers/main.py
+++ b/yuthon_will_task/controllers/main.py
@@ -1,9 +1,8 @@
import base64
import json
-
from odoo import http, fields
from odoo.http import request
-from odoo.tools import float_is_zero,float_round
+from urllib.parse import quote
class YuthonWillTask(http.Controller):
@@ -56,19 +55,79 @@ class YuthonWillTask(http.Controller):
'message':'success'
})
- @http.route('/will/taks/list', methods=['POST'], type='http', auth='none', csrf=False)
- def task_list(self, **kwargs):
- employee_id = kwargs.get('id')
- data = request.env['yuthon.will.task'].sudo().search([])
+ @http.route('/will/task/list', methods=['POST'], type='http', auth='public', csrf=False)
+ def will_task_list(self, **kwargs):
+ employee_id = kwargs.get('employee_id')
+ start = kwargs.get('start')
+ request_hour_selection = request.env['yuthon.will.task'].sudo().fields_get(allfields=['request_hour_from'])['request_hour_from']['selection']
result_list = []
- for emp in data:
+ # for task in request.env['yuthon.will.task'].sudo().search(['|', ('employee_ids', 'in', [employee_id]), ('employee_id.id', '=', employee_id)]):
+ task_ids = request.env['yuthon.will.task'].sudo().search([], offset=start, limit=7)
+ for task in task_ids:
+ weekday_str = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"][task.start_date.weekday()]
result = {
- 'name': emp.name,
- 'code': emp.code,
- }
+ 'id': task.id,
+ 'name': task.name,
+ 'employee_id': task.employee_id.name,
+ 'employee_ids': ', '.join(task.employee_ids.mapped('name')),
+ 'employee_num': len(task.employee_ids),
+ 'start_date': fields.Date.to_string(task.start_date),
+ 'weekday': weekday_str,
+ 'request_hour_from': '',
+ 'request_hour_to': '',
+ }
+ hour_dict = dict(request_hour_selection)
+ result['request_hour_from'] = hour_dict.get(task.request_hour_from)
+ result['request_hour_to'] = hour_dict.get(task.request_hour_to)
result_list.append(result)
return json.dumps({
'data': result_list,
'code': 200,
'message': 'success'
})
+
+ @http.route('/will/task/record', methods=['POST'], type='http', auth='public', csrf=False)
+ def will_task_record(self, **kwargs):
+ task_id = kwargs.get('id')
+ task = request.env['yuthon.will.task'].sudo().search([('id', '=', task_id)])
+ request_hour_selection = request.env['yuthon.will.task'].sudo().fields_get(allfields=['request_hour_from'])['request_hour_from'][
+ 'selection']
+ file_list = []
+ for attach in task.document_ids:
+ attach_id = request.env['ir.attachment'].sudo().search([('id', '=', attach.id)])
+ if attach_id:
+ file_url = 'http://view.officeapps.live.com/op/view.aspx?src=' + quote(
+ 'https://oa.thtzjt.com' + '/web/content/office_preview/' + str(attach_id.id))
+ file_list.append({'file_url': file_url, 'file_name': attach_id.display_name})
+ weekday_str = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"][task.start_date.weekday()]
+ result = {
+ 'id': task.id,
+ 'name': task.name,
+ 'employee_id': task.employee_id.name,
+ 'employee_ids': ', '.join(task.employee_ids.mapped('name')),
+ 'employee_num': len(task.employee_ids),
+ 'start_date': fields.Date.to_string(task.start_date),
+ 'weekday': weekday_str,
+ 'request_hour_from': '',
+ 'request_hour_to': '',
+ 'remarks': task.remarks,
+ 'address': task.address,
+ # 'file_list': file_list,
+ 'file_list': [{
+ 'file_url':'https://view.officeapps.live.com/op/view.aspx?src=https%3A//oa.thtzjt.com/web/content/office_preview/13672',
+ 'file_name':'excel',
+ },
+ {
+ 'file_url':'https://oa.thtzjt.com/web/content/preview/13673',
+ 'file_name':'pdf',
+ }
+ ],
+ }
+ hour_dict = dict(request_hour_selection)
+ result['request_hour_from'] = hour_dict.get(task.request_hour_from)
+ result['request_hour_to'] = hour_dict.get(task.request_hour_to)
+ return json.dumps({
+ 'data': result,
+ 'code': 200,
+ 'message': 'success'
+ })
diff --git a/yuthon_will_task/models/inherit_room_booking.py b/yuthon_will_task/models/inherit_room_booking.py
index 95c6b86f2..7dc660b58 100644
--- a/yuthon_will_task/models/inherit_room_booking.py
+++ b/yuthon_will_task/models/inherit_room_booking.py
@@ -1,10 +1,28 @@
from odoo import api, fields, models
from datetime import datetime, timedelta, date
+import logging
+_logger = logging.getLogger(__name__)
class InheritRoomBooking(models.Model):
_inherit = 'room.booking'
+ def get_no_read_count(self):
+ # 1. 计算各类时间参数
+ today = date.today() + timedelta(hours=8)
+ today_start = datetime.combine(today, datetime.min.time())
+ today_end = datetime.combine(today, datetime.max.time())
+ domain = [
+ ('start_datetime', '>=', today_start),
+ ('start_datetime', '<=', today_end),
+ '|',
+ ('stop_datetime', '=', False),
+ ('stop_datetime', '>', datetime.now())
+ ]
+ matching_records = self.search(domain)
+ count = len(matching_records)
+ return count
+
@api.model
def create(self, vals):
task_time_ids = self.env['yuthon.task.time'].search([('name', '=', '30分钟')])
diff --git a/yuthon_will_task/models/yuthon_will_task.py b/yuthon_will_task/models/yuthon_will_task.py
index de03c4bf7..3241a3d9e 100644
--- a/yuthon_will_task/models/yuthon_will_task.py
+++ b/yuthon_will_task/models/yuthon_will_task.py
@@ -82,7 +82,7 @@ class YuthonWillTask(models.Model):
document_ids = fields.Many2many('ir.attachment', string="附件")
address = fields.Char(string='地点')
start_date = fields.Date(string='开始日期', default=fields.Date.today)
- task_time = fields.Char(string='任务时间', compute='_compute_task_time')
+ task_time = fields.Char(string='任务时间')
is_this_company = fields.Boolean(string='本公司', default=True)
task_state = fields.Selection([('will', '待办'), ('done', '已办'), ('cancel', '取消')], default='will', string='状态', store=True)
@@ -106,42 +106,58 @@ class YuthonWillTask(models.Model):
store=True, default=lambda self: [(6, 0, [self.env.user.id])]
)
- @api.depends('start_date', 'request_hour_from', 'request_hour_to')
- def _compute_task_time(self):
+ employee_id = fields.Many2one('hr.employee', string="经办人", default=lambda self: self.env.user.employee_id)
+ task_week = fields.Char(string="周", readonly=True, compute='_compute_task_week')
+
+ @api.depends('start_date')
+ def _compute_task_week(self):
+ weekdays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
+ for record in self:
+ if record.start_date:
+ record.task_week = weekdays[record.start_date.weekday()]
+
+ def one_time(self):
+ will_ids = self.env["yuthon.will.task"].browse(
+ self._context.get('active_ids', self._context.get('active_id')))
+ for record in will_ids:
+ record._check_task_time()
+
+ @api.constrains('start_date', 'request_hour_from', 'request_hour_to')
+ def _check_task_time(self):
for record in self:
date_str = ""
if record.start_date:
date_str = record.start_date.strftime("%Y/%m/%d")
hour_mapping = {
- '0': '0:00', '0.5': '0:30',
- '1': '01:00', '1.5': '01:30',
- '2': '02:00', '2.5': '02:30',
- '3': '03:00', '3.5': '03:30',
- '4': '04:00', '4.5': '04:30',
- '5': '05:00', '5.5': '05:30',
- '6': '06:00', '6.5': '06:30',
- '7': '07:00', '7.5': '07:30',
- '8': '08:00', '8.5': '08:30',
- '9': '09:00', '9.5': '09:30',
- '10': '10:00', '10.5': '10:30',
- '11': '11:00', '11.5': '11:30',
- '12': '12:00', '12.5': '12:30',
- '13': '13:00', '13.5': '13:30',
- '14': '14:00', '14.5': '14:30',
- '15': '15:00', '15.5': '15:30',
- '16': '16:00', '16.5': '16:30',
- '17': '17:00', '17.5': '17:30',
- '18': '18:00', '18.5': '18:30',
- '19': '19:00', '19.5': '19:30',
- '20': '20:00', '20.5': '20:30',
- '21': '21:00', '21.5': '21:30',
- '22': '22:00', '22.5': '22:30',
- '23': '23:00', '23.5': '23:30'
+ '0': '0:00', '0.25': '0:15', '0.5': '0:30', '0.75': '0:45',
+ '1': '01:00', '1.25': '01:15', '1.5': '01:30', '1.75': '01:45',
+ '2': '02:00', '2.25': '02:15', '2.5': '02:30', '2.75': '02:45',
+ '3': '03:00', '3.25': '03:15', '3.5': '03:30', '3.75': '03:45',
+ '4': '04:00', '4.25': '04:15', '4.5': '04:30', '4.75': '04:45',
+ '5': '05:00', '5.25': '05:15', '5.5': '05:30', '5.75': '05:45',
+ '6': '06:00', '6.25': '06:15', '6.5': '06:30', '6.75': '06:45',
+ '7': '07:00', '7.25': '07:15', '7.5': '07:30', '7.75': '07:45',
+ '8': '08:00', '8.25': '08:15', '8.5': '08:30', '8.75': '08:45',
+ '9': '09:00', '9.25': '09:15', '9.5': '09:30', '9.75': '09:45',
+ '10': '10:00', '10.25': '10:15', '10.5': '10:30', '10.75': '10:45',
+ '11': '11:00', '11.25': '11:15', '11.5': '11:30', '11.75': '11:45',
+ '12': '12:00', '12.25': '12:15', '12.5': '12:30', '12.75': '12:45',
+ '13': '13:00', '13.25': '13:15', '13.5': '13:30', '13.75': '13:45',
+ '14': '14:00', '14.25': '14:15', '14.5': '14:30', '14.75': '14:45',
+ '15': '15:00', '15.25': '15:15', '15.5': '15:30', '15.75': '15:45',
+ '16': '16:00', '16.25': '16:15', '16.5': '16:30', '16.75': '16:45',
+ '17': '17:00', '17.25': '17:15', '17.5': '17:30', '17.75': '17:45',
+ '18': '18:00', '18.25': '18:15', '18.5': '18:30', '18.75': '18:45',
+ '19': '19:00', '19.25': '19:15', '19.5': '19:30', '19.75': '19:45',
+ '20': '20:00', '20.25': '20:15', '20.5': '20:30', '20.75': '20:45',
+ '21': '21:00', '21.25': '21:15', '21.5': '21:30', '21.75': '21:45',
+ '22': '22:00', '22.25': '22:15', '22.5': '22:30', '22.75': '22:45',
+ '23': '23:00', '23.25': '23:15', '23.5': '23:30', '23.75': '23:45'
}
from_time = hour_mapping.get(record.request_hour_from, "")
to_time = hour_mapping.get(record.request_hour_to, "")
if date_str and from_time and to_time:
- record.task_time = f"{date_str} {from_time}"
+ record.task_time = f"{date_str} {record.task_week} {from_time}"
else:
record.task_time = ""
diff --git a/yuthon_will_task/security/yuthon_will_task_security.xml b/yuthon_will_task/security/yuthon_will_task_security.xml
index d8e1b26a8..0056a273e 100644
--- a/yuthon_will_task/security/yuthon_will_task_security.xml
+++ b/yuthon_will_task/security/yuthon_will_task_security.xml
@@ -13,5 +13,13 @@
+
+ 会议组
+
+
+ 会议管理员
+
+
+
\ No newline at end of file
diff --git a/yuthon_will_task/views/yuthon_task_menu.xml b/yuthon_will_task/views/yuthon_task_menu.xml
index 1b7b5861e..c83c199c5 100644
--- a/yuthon_will_task/views/yuthon_task_menu.xml
+++ b/yuthon_will_task/views/yuthon_task_menu.xml
@@ -23,6 +23,7 @@
name="预定会议"
action="room.room_booking_action"
parent="menu_yuthon_will_task"
+ groups="yuthon_will_task.group_room_booking_manager"
sequence="10"/>
@@ -119,22 +115,22 @@
decoration-muted = "task_state == 'cancel'"
decoration-danger="priority == 'very_urgent'"
decoration-info="priority == 'urgent'"
- decoration-success="priority == 'important'" create="false" edit="false" js_class="custom_task_tree_button">
+ decoration-success="priority == 'important'" create="false" edit="false" js_class="custom_task_tree_button" limit="15">
-
-
-
+
+
+
-
-
-
-
+
+
+
+
@@ -171,10 +167,11 @@
-
-
-
+
+
+
→
-
+
@@ -258,4 +255,11 @@
[('user_role_ids.name', 'in', ['董事长', '分管领导', '总经理', '部门副经理', '副总经理', '司机'])]
{'search_default_next_seven_days': 1}
+
+ 更新
+
+
+ code
+ action = model.one_time()
+
diff --git a/yuthon_work_brand/views/executive_manage.xml b/yuthon_work_brand/views/executive_manage.xml
index 063d5c1b8..f6e54ab14 100644
--- a/yuthon_work_brand/views/executive_manage.xml
+++ b/yuthon_work_brand/views/executive_manage.xml
@@ -38,11 +38,6 @@
name="报事报修(物业)"
action="yuthon_maintain.property_report_repair_action"
sequence="20"/>
-
-
+
+
+ sequence="7"/>
-