This commit is contained in:
pengyuthon
2026-05-08 14:31:21 +08:00
24 changed files with 320 additions and 76 deletions
+2 -1
View File
@@ -8,6 +8,7 @@
'license': 'LGPL-3',
'data': [
'security/ir.model.access.csv',
'data/res_users_data.xml',
'views/system_version_views.xml',
'views/system_logs_views.xml',
'views/ir_cron_act_views.xml',
@@ -25,7 +26,7 @@
]
},
'demo': [],
'depends': ['hr', 'mail', 'base', 'survey'],
'depends': ['hr', 'mail', 'base', 'survey', 'account'],
'installable': True,
'application': True,
}
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="0">
<!-- 从默认用户模板中移除财务管理员权限组,新建用户不再默认带这些权限 -->
<record id="base.default_user" model="res.users">
<field name="groups_id" eval="[
(3, ref('account.group_account_manager')),
(3, ref('account.group_account_invoice')),
]"/>
</record>
</odoo>
+3 -1
View File
@@ -7,4 +7,6 @@ from . import yuthon_timed_tasks
from . import yuthon_phone_lottery
from . import res_partner
from . import base_month_year
from . import system_logs
from . import system_logs
from . import res_users
from . import mail_thread
+43
View File
@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
# from odoo import models
# import json
#
#
# class MailThread(models.AbstractModel):
# _inherit = "mail.thread"
#
# def _notify_by_web_push(self, message, recipients_data, msg_vals=False):
# """
# 重写 Web Push 通知方法,强制使用异步发送方式,
# 避免同步发送导致的请求阻塞问题(如加班审批转交按钮反应慢)。
# """
# msg_vals = dict(msg_vals or {})
# partner_ids = self._extract_partner_ids_for_notifications(message, msg_vals, recipients_data)
# if not partner_ids:
# return
#
# partner_devices_sudo = self.env['mail.partner.device'].sudo()
# devices = partner_devices_sudo.search([
# ('partner_id', 'in', partner_ids)
# ])
# if not devices:
# return
#
# ir_parameter_sudo = self.env['ir.config_parameter'].sudo()
# vapid_private_key = ir_parameter_sudo.get_param('mail.web_push_vapid_private_key')
# vapid_public_key = ir_parameter_sudo.get_param('mail.web_push_vapid_public_key')
# if not vapid_private_key or not vapid_public_key:
# return
#
# payload = self._notify_by_web_push_prepare_payload(message, msg_vals=msg_vals)
# payload = self._truncate_payload(payload)
#
# # 强制使用异步发送方式
# # 不再同步调用 push_to_end_point,避免阻塞请求
# self.env['mail.notification.web.push'].sudo().create([{
# 'user_device': device.id,
# 'payload': json.dumps(payload),
# } for device in devices])
# self.env.ref('mail.ir_cron_web_push_notification')._trigger()
+33
View File
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
import logging
from odoo import api, models
_logger = logging.getLogger(__name__)
class ResUsers(models.Model):
_inherit = 'res.users'
@api.model_create_multi
def create(self, vals_list):
_logger.info("====== [yuthon_base] res.users.create 被调用,准备创建 %d 个用户 ======", len(vals_list))
users = super().create(vals_list)
# 新建用户后确保移除财务和薪资管理员权限组
groups_to_remove = []
group_refs = [
'account.group_account_manager',
'account.group_account_invoice',
'hr_payroll.group_hr_payroll_manager',
]
for ref in group_refs:
group = self.env.ref(ref, raise_if_not_found=False)
if group:
groups_to_remove.append((3, group.id))
_logger.info("====== [yuthon_base] 找到组 %s (id=%d),将移除 ======", ref, group.id)
else:
_logger.warning("====== [yuthon_base] 未找到组 %s ======", ref)
if groups_to_remove:
_logger.info("====== [yuthon_base] 对用户 %s 移除 %d 个组 ======", users.mapped('login'), len(groups_to_remove))
users.sudo().write({'groups_id': groups_to_remove})
_logger.info("====== [yuthon_base] res.users.create 完成 ======")
return users
@@ -12,6 +12,7 @@ class YuthonCateringConf(models.Model):
effective_date = fields.Date(string='生效日期')
expiry_date = fields.Date(string='失效日期')
is_active = fields.Integer(string='是否生效', compute='_compute_is_active', store=True)
note = fields.Text(string='备注')
@api.depends('employee_ids')
def _compute_employee_count(self):
@@ -12,6 +12,7 @@
<field name="employee_count"/>
<field name="effective_date"/>
<field name="expiry_date"/>
<field name="note"/>
<field name="is_active" column_invisible="1"/>
<button name="action_change_employees" string="变更员工" type="object" class="btn btn-primary" invisible="expiry_date != False"/>
<button name="action_fix_null_effective_date" string="修复日期" type="object" class="btn btn-secondary"/>
@@ -22,10 +22,25 @@ class CateringConfChangeWizard(models.TransientModel):
res['employee_ids'] = [(6, 0, conf.employee_ids.ids)]
return res
def _compute_change_note(self):
"""计算增减员备注"""
old_ids = set(self.conf_id.employee_ids.ids)
new_ids = set(self.employee_ids.ids)
added_ids = new_ids - old_ids
removed_ids = old_ids - new_ids
parts = []
if added_ids:
added_names = self.env['hr.employee'].browse(list(added_ids)).mapped('name')
parts.append('增员:' + '、'.join(added_names))
if removed_ids:
removed_names = self.env['hr.employee'].browse(list(removed_ids)).mapped('name')
parts.append('减员:' + '、'.join(removed_names))
return '\n'.join(parts) if parts else ''
def action_confirm(self):
"""确认:旧记录加失效日期,生成新记录"""
today = fields.Date.today()
# 旧记录加失效日期(跳过write覆写,直接用super)
note = self._compute_change_note()
from odoo.models import Model
Model.write(self.conf_id, {'expiry_date': today})
# 生成新记录
@@ -33,6 +48,7 @@ class CateringConfChangeWizard(models.TransientModel):
'company_id': self.conf_id.company_id.id,
'employee_ids': [(6, 0, self.employee_ids.ids)],
'effective_date': today,
'note': note,
})
return {'type': 'ir.actions.act_window_close'}
@@ -42,6 +58,10 @@ class CateringConfChangeWizard(models.TransientModel):
def action_modify(self):
"""仅修改当前记录员工,不生成新记录,不更新日期"""
note = self._compute_change_note()
from odoo.models import Model
Model.write(self.conf_id, {'employee_ids': [(6, 0, self.employee_ids.ids)]})
Model.write(self.conf_id, {
'employee_ids': [(6, 0, self.employee_ids.ids)],
'note': note,
})
return {'type': 'ir.actions.act_window_close'}
+5 -5
View File
@@ -1217,19 +1217,19 @@ class HolidaysRequestBatch(models.Model):
if leave_type_name not in leave_type_mapping or leave_days <= 0:
continue
type_config = leave_type_mapping[leave_type_name]
remaining_hours = leave_days * 8
remaining_hours = leave_days * 8
if type_config['prev']:
prev_balance = leave_balance[type_config['prev']]
prev_balance = leave_balance[type_config['prev']] * 8
if prev_balance > 0:
deduct = round(min(remaining_hours, prev_balance), 1)
leave_balance[type_config['prev']] = round(leave_balance[type_config['prev']] - deduct, 1)
leave_balance[type_config['prev']] = round((prev_balance - deduct) / 8, 1)
remaining_hours = round(remaining_hours - deduct, 1)
if remaining_hours > 0 and type_config['curr']:
curr_balance = leave_balance[type_config['curr']]
curr_balance = leave_balance[type_config['curr']] * 8
deduct = round(min(remaining_hours, curr_balance), 1)
leave_balance[type_config['curr']] = round(leave_balance[type_config['curr']] - deduct, 1)
leave_balance[type_config['curr']] = round((curr_balance - deduct) / 8, 1)
remaining_hours = round(remaining_hours - deduct, 1)
if type_config['prev']:
+2 -2
View File
@@ -1181,8 +1181,8 @@ class HrAttendance(models.Model):
# 检查是否为节假日
for leave in leave_records:
if leave.date_from and leave.date_to:
from_date = fields.Date.to_date(leave.date_from)
to_date = fields.Date.to_date(leave.date_to)
from_date = fields.Date.to_date(leave.date_from + timedelta(hours=8))
to_date = fields.Date.to_date(leave.date_to + timedelta(hours=8))
if from_date <= record.current_data <= to_date:
is_holiday = True # 标记为节假日
@@ -130,11 +130,11 @@ class HrAttendanceDetail(models.Model):
category='att', user_id=employee_id.wecom_userid,
message=message,
)
if record.employee_id.name == '蒋彬':
self.sudo().env["wecom.apps"].sync_send_message(
category='att', user_id='18562027762',
message=message + f'管理员测试管理员测试{vals}',
)
# if record.employee_id.name == '蒋彬':
# self.sudo().env["wecom.apps"].sync_send_message(
# category='att', user_id='18562027762',
# message=message + f'管理员测试管理员测试{vals}',
# )
self.write({'remark': message})
_logger.info(message)
else:
@@ -208,16 +208,16 @@ class HrAttendanceDetail(models.Model):
if checkin_datetime > sch_check_out_time:
message = f"打卡成功!今日下班时间:{record.checkin_time + timedelta(hours=8)}: {employee_id.name},祝您归途平安!"
if record.employee_id.name not in ['蒋彬', '麦丽娜']:
self.sudo().env["wecom.apps"].sync_send_message(
category='att', user_id=employee_id.wecom_userid,
message=message,
)
if record.employee_id.name in ['蒋彬', '麦丽娜']:
self.sudo().env["wecom.apps"].sync_send_message(
category='att', user_id='18562027762',
message=message + f'管理员测试管理员测试{vals}',
)
# if record.employee_id.name not in ['蒋彬', '麦丽娜']:
self.sudo().env["wecom.apps"].sync_send_message(
category='att', user_id=employee_id.wecom_userid,
message=message,
)
# if record.employee_id.name in ['蒋彬', '麦丽娜']:
# self.sudo().env["wecom.apps"].sync_send_message(
# category='att', user_id='18562027762',
# message=message + f'管理员测试管理员测试{vals}',
# )
self.write({'remark': message})
_logger.info(message)
@@ -29,27 +29,27 @@
groups="yuthon_hr_attendance.group_he_attendance_sign_manager"
confirm="确定要删除选中的记录吗?" />
</header>
<field name="employee_id" class="list_current_data" options="{'no_create': True}" />
<field name="employee_id" options="{'no_create': True}"/>
<field name="is_expatriation" column_invisible="1"/>
<field name="current_data" optional="show" class="list_current_data" />
<field name="week" optional="show" class="list_ids_width" />
<field name="current_data" optional="show"/>
<field name="week" optional="show"/>
<field name="check_in" optional="show" widget="time"
decoration-danger="is_check_in_red == 1" />
<field name="check_out" optional="show" widget="time" class="list_current_data"
<field name="check_out" optional="show" widget="time"
decoration-danger="is_check_out_red == 1" />
<field name="shift_id" column_invisible="1"/>
<field name="shift_name" optional="show" class="list_current_data" />
<field name="shift_name" optional="show"/>
<field name="is_week" column_invisible="1" />
<field name="is_holiday" column_invisible="1" />
<field name="create_date" />
<field name="user_id" column_invisible="1" />
<field name="is_clock_card" column_invisible="1" />
<field name="department_id" column_invisible="1" />
<field name="is_no_card" optional="show" class="list_ids_width" />
<field name="is_early_card" optional="show" class="list_ids_width" />
<field name="is_late_card" optional="show" class="list_ids_width" />
<field name="absenteeism_card" optional="show" class="list_ids_width" string="旷工" />
<field name="is_abnormal" optional="show" class="list_ids_width" string="异常" />
<field name="is_no_card" optional="show"/>
<field name="is_early_card" optional="show"/>
<field name="is_late_card" optional="show"/>
<field name="absenteeism_card" optional="show" string="旷工" />
<field name="is_abnormal" optional="show" string="异常" />
<field name="abnormal" column_invisible="1" />
<field name="work_time_type" column_invisible="1" />
<field name="is_approval" column_invisible="1" />
@@ -69,7 +69,7 @@
<button name="revoke" type="object" string="撤销" class="btn btn-blue"
invisible="not (is_check_out_red or is_check_in_red)"
groups="yuthon_hr_attendance.group_he_attendance_sign_manager" />
<button name="button_workflow" type="object" string="流程" class="oe_highlight"
<button name="button_workflow" type="object" string="流程" class="btn btn-blue"
invisible="not is_workflow" />
<button name="button_source" type="object" string="详情" class="btn btn-blue"
groups="yuthon_hr_attendance.group_he_attendance_sign_manager" />
@@ -87,21 +87,21 @@
<!-- <button name="compute_company_id" string="公司更新" type="object" class="btn
btn-primary"/>-->
<!-- </header>-->
<field name="current_data" optional="show" class="list_current_data" />
<field name="week" optional="show" class="list_ids_width" />
<field name="current_data" optional="show"/>
<field name="week" optional="show"/>
<field name="check_in" optional="show" widget="time" />
<field name="check_out" optional="show" widget="time" class="list_current_data" />
<field name="check_out" optional="show" widget="time"/>
<field name="shift_id" column_invisible="1"/>
<field name="shift_name" optional="show" class="list_current_data" />
<field name="shift_name" optional="show" />
<field name="create_date" column_invisible="1" />
<field name="user_id" column_invisible="1" />
<field name="is_clock_card" column_invisible="1" />
<field name="department_id" column_invisible="1" />
<field name="is_no_card" optional="show" class="list_ids_width" />
<field name="is_early_card" optional="show" class="list_ids_width" />
<field name="is_late_card" optional="show" class="list_ids_width" />
<field name="absenteeism_card" optional="show" class="list_ids_width" string="旷工" />
<field name="is_abnormal" optional="show" class="list_ids_width" string="异常" />
<field name="is_no_card" optional="show" />
<field name="is_early_card" optional="show" />
<field name="is_late_card" optional="show" />
<field name="absenteeism_card" optional="show" string="旷工" />
<field name="is_abnormal" optional="show" string="异常" />
<field name="is_late_allowed" column_invisible="1"/>
<field name="abnormal" optional="show" column_invisible="1" />
<field name="work_time_type" column_invisible="1" />
@@ -111,6 +111,9 @@
<field name="is_warning" column_invisible="1"/>
<field name="is_check_in_red" column_invisible="1" />
<field name="is_check_out_red" column_invisible="1" />
<field name="is_warning" column_invisible="1"/>
<field name="is_workflow" column_invisible="1"/>
<field name="workflow_id" column_invisible="1"/>
<button name="button_controls_wizard" type="object" string="操作" class="btn btn-blue"
invisible="not (is_abnormal or is_early_card or is_late_card or absenteeism_card or is_no_card)" />
<button name="button_correct_wizard" type="object" string="修正"
@@ -120,6 +123,8 @@
<button name="revoke" type="object" string="撤销" class="btn btn-blue"
invisible="not (is_check_out_red or is_check_in_red)"
groups="yuthon_hr_attendance.group_he_attendance_sign_manager" />
<button name="button_workflow" type="object" string="流程" class="btn-link text-danger"
invisible="not is_workflow" />
<button name="button_source" type="object" string="详情" class="btn btn-blue"
groups="yuthon_hr_attendance.group_he_attendance_sign_manager" />
</tree>
+1
View File
@@ -13,4 +13,5 @@ from . import inherit_res_groups
from . import soong_user_role
from . import yuthon_medical_manage
from . import yuthon_medical_rule
from . import res_users
@@ -46,7 +46,9 @@ class ResGroups(models.Model):
if not department:
return valid_user_ids
dept_id = department.id if isinstance(department, models.Model) else int(department)
# 处理虚拟记录(onchange时可能出现)
dept_id = department.id.origin if hasattr(department.id, 'origin') else department.id
dept_id = int(dept_id) if isinstance(dept_id, str) else dept_id
# 当前部门员工
employees = self.env['hr.employee'].search([('department_id', '=', dept_id)])
+29
View File
@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
import werkzeug.urls
from urllib.parse import urlparse
import urllib.request
import requests
import json
from odoo import api, fields, models
class ResUsers(models.Model):
_inherit = 'res.users'
@api.model
def create(self, vals):
user = super().create(vals)
# 2. 定义要强制移除的 Payroll 权限组 ID
remove_group_ids = [
184, # 工资 / 管理员(人事专员)
728, # 管理员(本部财务) (会计)
609, # 管理员(财务)
]
user.write({
'groups_id': [(3, gid) for gid in remove_group_ids]
})
user.write({
'sel_groups_732_760': False, # 库存 选择框
'sel_groups_678_679': False, # 采购 选择框
})
return user
@@ -51,13 +51,19 @@
<group col="2" string="审批详情">
<group colspan="2">
<field name="name" string="标题"/>
<field name="is_back" invisible="1"/>
<field name="users_id" options="{'no_create': True}"/>
<field name="department_id" invisible="1"/>
<field name="end_date"/>
<field name="work_end" invisible="1"/>
<field name="documents_id" widget="preview_many2one"/>
</group>
<field name="is_back" invisible="1"/>
<field name="users_id" options="{'no_create': True}"/>
<field name="department_id" invisible="1"/>
<field name="end_date"/>
<field name="work_end" invisible="1"/>
<field name="documents_id" widget="preview_many2one"/>
<!-- <field name="is_back" invisible="1"/>-->
<!-- <field name="users_id" options="{'no_create': True}"/>-->
<!-- <field name="department_id" invisible="1"/>-->
<!-- <field name="end_date"/>-->
<!-- <field name="work_end" invisible="1"/>-->
<!-- <field name="documents_id" widget="preview_many2one"/>-->
</group>
<group string="考核详情">
<group>
@@ -77,7 +77,7 @@
<field name="secret_level"/>
<field name="official_type_id" options="{'no_create': True}"/>
<field name="is_chapter"/>
<field name="type_stamp_ids" widget="many2many_tags" options="{'no_create': True, 'no_open': True}}"/>
<field name="type_stamp_ids" widget="many2many_tags" options="{'no_create': True, 'no_open': True}}" required="is_chapter"/>
</group>
<group>
<field name="is_cold"/>
@@ -2603,12 +2603,24 @@ class PropertyManagementBreakdownLine(models.Model):
management_monthly_amount = fields.Float(string="金额", digits=(16, 2))
start_data = fields.Date(string="开始日期")
end_data = fields.Date(string="结束日期")
management_month_number = fields.Integer(string="期间月数")
management_month_number = fields.Float(string="期间月数", digits=(16, 2))
management_period_rent = fields.Float(string="期间费用", digits=(16, 2))
@api.onchange('management_monthly_amount', 'month_number')
@api.onchange('start_data', 'end_data')
def _onchange_management_month_number(self):
if self.start_data and self.end_data:
if self.end_data >= self.start_data:
total_days = (self.end_data - self.start_data).days + 1
start_month_days = calendar.monthrange(self.start_data.year, self.start_data.month)[1]
self.management_month_number = round(total_days / start_month_days, 2)
else:
self.management_month_number = 0
else:
self.management_month_number = 0
@api.onchange('management_monthly_amount', 'management_month_number')
def _onchange_management_amount(self):
self.management_period_rent = self.management_monthly_amount * self.management_month_number
self.management_period_rent = round(self.management_monthly_amount * self.management_month_number, 2)
class PropertyWaterFeeLine(models.Model):
@@ -94,7 +94,7 @@
</group>
</group>
<group>
<field name="handling_opinions" invisible="contract_sort != 'property'"/>
<field name="handling_opinions"/>
</group>
<!-- 隐藏字段单独放一个不占布局的分组 -->
<group>
+1
View File
@@ -14,6 +14,7 @@
'data': [
'security/ir.model.access.csv',
'security/salary_security_rule.xml',
'data/res_users_data.xml',
'data/rank_log_time.xml',
'data/meal_cron.xml',
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="0">
<!-- 从默认用户模板中移除薪资管理员权限组,新建用户不再默认带此权限 -->
<record id="base.default_user" model="res.users">
<field name="groups_id" eval="[(3, ref('hr_payroll.group_hr_payroll_manager'))]"/>
</record>
</odoo>
+65 -5
View File
@@ -1,5 +1,5 @@
from odoo import api, fields, models
from datetime import datetime
from datetime import datetime, timedelta
import calendar
@@ -90,6 +90,54 @@ class YuthonMealExpenses(models.Model):
current_month = datetime.now().month
return str(current_month)
def _remove_leading_zero(self, date_str):
"""去掉日期字符串的前导零,如 '01月01日' -> '1月1日'"""
month, day = date_str.split('月')
day = day.replace('日', '')
return f"{int(month)}月{int(day)}日"
def _is_chinese_workday(self, check_date=None):
"""判断给定日期是否为中国工作日(考虑法定节假日和调休)"""
if check_date is None:
check_date = datetime.now()
# 获取当年行政考勤工作日的节假日数据
current_year = check_date.year
query_start = datetime(current_year, 1, 1, 0, 0, 0) - timedelta(hours=8)
query_end = datetime(current_year, 12, 31, 23, 59, 59) - timedelta(hours=8)
calendar_leaves = self.env['resource.calendar.leaves'].sudo().search([
("calendar_id.name", "=", "行政考勤工作日"),
("date_from", ">=", query_start),
("date_from", "<=", query_end)
])
holidays_list = []
shift_days_list = []
for leave in calendar_leaves:
if leave.holidays:
holidays_list.extend(leave.holidays.split(','))
if leave.alternate_rest_day:
holidays_list.extend(leave.alternate_rest_day.split(','))
if leave.shift_replacement_day:
shift_days_list.extend(leave.shift_replacement_day.split(','))
holidays_list = [self._remove_leading_zero(d) for d in holidays_list]
shift_days_list = [self._remove_leading_zero(d) for d in shift_days_list]
date_str = self._remove_leading_zero(check_date.strftime('%m月%d日'))
if date_str in shift_days_list:
# 调休补班日,强制算工作日
return True
if date_str in holidays_list:
# 法定节假日或调休休息日,算非工作日
return False
# 没有特殊安排的,按周末判断
return check_date.weekday() < 5
def send_meal(self):
return {
'type': 'ir.actions.act_window',
@@ -112,6 +160,18 @@ class YuthonMealExpenses(models.Model):
def cron_send_meal_reminder(self):
"""定时任务:给状态为已发送且缴费状态为待缴的记录发送缴费提醒"""
# 节假日不发送
if not self._is_chinese_workday():
self.env['ir.logging'].sudo().create({
'name': '餐费缴费提醒',
'type': 'server',
'message': f'今天{datetime.now().strftime("%Y-%m-%d")}是节假日或周末,跳过发送餐费缴费提醒',
'path': __name__,
'func': 'cron_send_meal_reminder',
'line': 0,
})
return True
# 找出所有 已发送 且 仍然 待缴 的餐费记录
meals = self.sudo().search([
('meal_state', '=', 'done'),
@@ -253,15 +313,15 @@ class YuthonMealExpenses(models.Model):
"""定时任务:每月第一个工作日发送餐费缴费提醒"""
from datetime import datetime, timedelta
import calendar
# 检查是否是工作日
# 检查是否是中国工作日(含法定节假日和调休判断)
today = datetime.now()
if today.weekday() >= 5: # 0-4是工作日,5-6是周末
if not self._is_chinese_workday(today):
# 记录日志
self.env['ir.logging'].sudo().create({
'name': '餐费缴费提醒',
'type': 'server',
'message': f'今天{today.strftime("%Y-%m-%d")}是周末,跳过发送餐费缴费提醒',
'message': f'今天{today.strftime("%Y-%m-%d")}是节假日或周末,跳过发送餐费缴费提醒',
'path': __name__,
'func': 'cron_send_monthly_meal_reminder',
'line': 0,
+10
View File
@@ -179,6 +179,16 @@ class ResUsers(models.Model):
try:
with self.env.cr.savepoint():
user_id = template_user.sudo().with_context(no_reset_password=True).copy(values)
# 移除财务管理员权限组
groups_to_remove = []
group_manager = self.env.ref('account.group_account_manager', raise_if_not_found=False)
group_invoice = self.env.ref('account.group_account_invoice', raise_if_not_found=False)
if group_manager:
groups_to_remove.append((3, group_manager.id))
if group_invoice:
groups_to_remove.append((3, group_invoice.id))
if groups_to_remove:
user_id.sudo().write({'groups_id': groups_to_remove})
return user_id
except Exception as e:
_logger.exception("OAuth Wechat: 微信访问用户【UserId:%s】自动创建失败【Odoo错误:%s】!" % (userid, ustr(e)))
+13 -13
View File
@@ -777,25 +777,25 @@
<!--我的-->
<menuitem id="holiday_manage_menu_root_board" name="我的" web_icon="yuthon_work_brand,static/description/holiday.png" sequence="3">
<menuitem id="menu_workflow_approval_request_new" name="新建流程" action="soong_workflow.action_kklw_workflow_approval_request" sequence="5"/>
<menuitem id="menu_soong_workflow_todo_record" name="待办流程" action="soong_workflow.soong_workflow_record_todo_action" sequence="10"/>
<menuitem id="menu_soong_workflow_done_record" name="已办流程" action="soong_workflow.soong_workflow_record_done_action" sequence="15"/>
<menuitem id="menu_soong_workflow_department_record" name="流程查询" action="soong_workflow.soong_workflow_department_record_action" sequence="20"/>
<menuitem id="menu_workflow_approval_request_new" name="新建流程" action="soong_workflow.action_kklw_workflow_approval_request" sequence="5" groups="base.group_user"/>
<menuitem id="menu_soong_workflow_todo_record" name="待办流程" action="soong_workflow.soong_workflow_record_todo_action" sequence="10" groups="base.group_user"/>
<menuitem id="menu_soong_workflow_done_record" name="已办流程" action="soong_workflow.soong_workflow_record_done_action" sequence="15" groups="base.group_user"/>
<menuitem id="menu_soong_workflow_department_record" name="流程查询" action="soong_workflow.soong_workflow_department_record_action" sequence="20" groups="base.group_user"/>
<menuitem id="menu_workflow_approval_request_admin" name="流程监控" action="soong_workflow.soong_workflow_record_action_admin" sequence="25"/>
<menuitem id="menu_soong_workflow_hr_employee" name="人力资源流程" action="soong_workflow.soong_workflow_hr_employee_action" sequence="30" groups="soong_workflow.group_soong_workflow_hr"/>
<menuitem id="yuthon_official_incoming_normal" name="行政收文" action="yuthon_official.yuthon_official_incoming_normal_action" sequence="32"/>
<menuitem id="yuthon_file_processing_menu" name="文件处理" action="yuthon_official.yuthon_file_processing_action" sequence="35"/>
<menuitem id="yuthon_sub_enterprises" name="文件处理(子企业)" action="yuthon_official.view_yuthon_sub_enterprises_action" sequence="40"/>
<menuitem id="yuthon_notice_menu1_board" name="通知公告" action="yuthon_notice.approval_notice_action" sequence="45"/>
<menuitem id="menu_soong_workflow_task" name="我的任务" action="project_todo.project_task_action_todo" sequence="50"/>
<menuitem id='menu_yuthon_will_task_root' name='我的日程' action='yuthon_will_task.view_yuthon_will_task_action' sequence='55'/>
<menuitem id="yuthon_notice_menu1_board" name="通知公告" action="yuthon_notice.approval_notice_action" sequence="45" groups="base.group_user"/>
<menuitem id="menu_soong_workflow_task" name="我的任务" action="project_todo.project_task_action_todo" sequence="50" groups="base.group_user"/>
<menuitem id='menu_yuthon_will_task_root' name='我的日程' action='yuthon_will_task.view_yuthon_will_task_action' sequence='55' groups="base.group_user"/>
<menuitem id="yuthon_salary_party_my_board" name="党费" action="yuthon_salary.view_my_yuthon_salary_party_action" sequence="60"/>
<menuitem id="menu_hr_attendance_my_record_board" name="我的考勤" action="yuthon_hr_attendance.hr_attendance_action1" sequence="65"/>
<menuitem id="menu_hr_attendance_my_abnormal_board" name="我的异常" action="yuthon_hr_attendance.hr_attendance_my_abnormal" sequence="70"/>
<menuitem id="yuthon_vacation_reports_my" name="考勤确认单" action="yuthon_hr_attendance.action_server_open_my_vacation_form1" sequence="75"/>
<menuitem id="yuthon_salary_active_my2" name="工资条" action="yuthon_salary.yuthon_salary_active_my_action" sequence="80"/>
<menuitem id="yuthon_meal_expenses_my_board" name="餐费" action="yuthon_salary.view_my_yuthon_meal_expenses_action" sequence="85"/>
<menuitem id="property_device_repair_action_brand" name="报事报修" action="yuthon_maintain.property_device_repair_action" sequence="90"/>
<menuitem id="menu_hr_attendance_my_record_board" name="我的考勤" action="yuthon_hr_attendance.hr_attendance_action1" sequence="65" groups="base.group_user"/>
<menuitem id="menu_hr_attendance_my_abnormal_board" name="我的异常" action="yuthon_hr_attendance.hr_attendance_my_abnormal" sequence="70" groups="base.group_user"/>
<menuitem id="yuthon_vacation_reports_my" name="考勤确认单" action="yuthon_hr_attendance.action_server_open_my_vacation_form1" sequence="75" groups="base.group_user"/>
<menuitem id="yuthon_salary_active_my2" name="工资条" action="yuthon_salary.yuthon_salary_active_my_action" sequence="80" groups="base.group_user"/>
<menuitem id="yuthon_meal_expenses_my_board" name="餐费" action="yuthon_salary.view_my_yuthon_meal_expenses_action" sequence="85" groups="base.group_user"/>
<menuitem id="property_device_repair_action_brand" name="报事报修" action="yuthon_maintain.property_device_repair_action" sequence="90" groups="base.group_user"/>
<menuitem id="property_device_repair_action_brand_all" name="报事报修(管理员)" action="yuthon_maintain.property_device_repair_all_action" groups="base.group_system" sequence="95"/>
<menuitem id="salary_view_Individual" name="个税计算" action="yuthon_salary.action_view_hr_payslip_month_form2" sequence="100"/>
</menuitem>