添加功能

This commit is contained in:
zhou
2025-03-10 20:51:46 +08:00
parent cd8d3bd7ba
commit 86ea68e66d
8 changed files with 229 additions and 28 deletions
+1
View File
@@ -21,6 +21,7 @@
'data/hr_attendance_time.xml',
'data/attendance_code_data.xml',
'data/attendance_time_data.xml',
'data/attendance_month_date.xml',
'data/mail_template.xml',
'views/hr_attendance_views.xml',
'views/resource_calendar_leaves_views.xml',
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data noupdate="1">
<record forcecreate="True" id="attendance_month_data" model="ir.cron">
<field name="name">定时任务:考勤统计</field>
<field name="model_id" ref="model_hr_attendance_month_wizard"/>
<field name="state">code</field>
<field name="code">model.button_attendance_month()</field>
<field eval="True" name="active"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_type">months</field>
<field name="interval_number">1</field>
<field name="nextcall" eval="(DateTime.now()).strftime('%Y-%m-%d 12:00:00')"/>
<field name="numbercall">-1</field>
<field eval="False" name="doall"/>
</record>
<record forcecreate="True" id="attendance_month_data" model="ir.cron">
<field name="name">定时任务:触发考勤统计然后发送</field>
<field name="model_id" ref="model_hr_attendance_month_detail"/>
<field name="state">code</field>
<field name="code">model.button_all_attendance_month()</field>
<field eval="True" name="active"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_type">months</field>
<field name="interval_number">1</field>
<field name="nextcall" eval="(DateTime.now()).strftime('%Y-%m-%d 12:00:00')"/>
<field name="numbercall">-1</field>
<field eval="False" name="doall"/>
</record>
<record forcecreate="True" id="attendance_month_detail" model="ir.cron">
<field name="name">定时任务:确认字段</field>
<field name="model_id" ref="model_hr_attendance_month_detail"/>
<field name="state">code</field>
<field name="code">model.attendance_month_detail()</field>
<field eval="True" name="active"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_type">months</field>
<field name="interval_number">1</field>
<field name="nextcall" eval="(DateTime.now()).strftime('%Y-%m-%d 12:30:00')"/>
<field name="numbercall">-1</field>
<field eval="False" name="doall"/>
</record>
</data>
</odoo>
@@ -41,7 +41,7 @@ class HrAttendanceMonth(models.Model):
is_statistics = fields.Boolean(string="是否已统计", store=True, default=False)
statistics_time = fields.Datetime(string="统计时间")
attendance_month_detail_ids = fields.One2many(string="出勤月度汇总明细", comodel_name='hr.attendance.month.detail', inverse_name='hr_attendance_month_id')
company_id = fields.Many2one('res.company', string="公司名称", default=lambda self: self.env.company)
yuthon_company = fields.Selection([('thtz', '天河投资集团'), ('thwg', '天河物管'), ('thlc', '天河粮储')],string='公司')
def _compute_name(self):
for record in self:
@@ -128,7 +128,8 @@ class HrAttendanceMonthDetail(models.Model):
note = fields.Char(string='备注')
hr_attendance_month_id = fields.Many2one('hr.attendance.month', string="出勤月度汇总", ondelete="cascade", readonly=True)
company_id = fields.Many2one(related="hr_attendance_month_id.company_id")
yuthon_company = fields.Selection([('thtz', '天河投资集团'), ('thwg', '天河物管'), ('thlc', '天河粮储')],
string='公司')
signature = fields.Image(string="签名", copy=False, attachment=True, max_width=1024, max_height=1024)
signed_by = fields.Char(string="签名者", copy=False)
signed_on = fields.Datetime(string="签名时间", copy=False)
@@ -373,11 +374,131 @@ class HrAttendanceMonthDetail(models.Model):
record.analysis_attendance_month_detail()
def button_put(self):
pass
menu_id = self.env['ir.ui.menu'].search([('name', '=', '我的确认'), ('parent_id', '!=', False)])
str = 'https://oa.thtzjt.com/web#id={}&cids=1&menu_id={}&action={}&model=hr.attendance.month.detail&view_type=list'.format(
self.id, menu_id.id, menu_id.action.id)
we_id = self.env['hr.employee'].search([('id', '=', self.employee_id)]).wecom_userid
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='attendance', user_id=we_id, title="考勤确认",
description=self.employee_id.name + '请确认你的考勤:',
url=str, btntxt="详细信息")
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'type': 'success',
'message': '确认通知已发送',
'sticky': False,
}
}
def button_all_put(self):
pass
detail_ids = self.env["hr.attendance.month.detail"].browse(self._context.get('active_ids', self._context.get('active_id')))
for detail in detail_ids:
menu_id = self.env['ir.ui.menu'].search([('name', '=', '我的确认'), ('parent_id', '!=', False)])
str = 'https://oa.thtzjt.com/web#id={}&cids=1&menu_id={}&action={}&model=hr.attendance.month.detail&view_type=list'.format(
self.id, menu_id.id, menu_id.action.id)
we_id = self.env['hr.employee'].search([('id', '=', detail.employee_id)]).wecom_userid
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='attendance', user_id=we_id, title="考勤确认",
description=detail.employee_id.name + '请确认你的考勤:',
url=str, btntxt="详细信息")
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'type': 'success',
'message': '确认通知已发送',
'sticky': False,
}
}
def button_confirm(self):
for record in self:
record.state = 'confirmed'
record.state = 'confirmed'
def _get_attendance_month_obj(self):
"""
获取出勤月度汇总记录结果表
:return: obj
"""
self.ensure_one()
yuthon_company = self.yuthon_company
attendance_month_obj = self.env["hr.attendance.month"].search([
('current_year', '=', self.current_year),
('current_month', '=', self.current_month),
('yuthon_company', '=', yuthon_company),
], limit=1)
if not attendance_month_obj:
attendance_month_obj = self.env["hr.attendance.month"].sudo().create({
"attendance_year_id": self.attendance_year_id.id,
"current_year": self.current_year,
"current_month": self.current_month,
"is_statistics": True,
"statistics_time": fields.Datetime.now(),
"yuthon_company": yuthon_company,
})
return attendance_month_obj
def _get_attendance_month_detail(self, employee):
"""
判断当前是否已经创建了考勤明细
:param employee: 员工
:return: 考情明细
"""
self.ensure_one()
yuthon_company = self.yuthon_company
attendance_month_detail_obj = self.env["hr.attendance.month.detail"].search(
[('employee_id', '=', employee.id),
('current_year', '=', self.current_year),
('current_month', '=', self.current_month),
('yuthon_company', '=', yuthon_company)
], limit=1)
if not attendance_month_detail_obj:
attendance_month_detail_obj = self.env["hr.attendance.month.detail"].sudo().create({
"employee_id": employee.id,
"attendance_year_id": self.attendance_year_id.id,
"current_year": self.current_year,
"current_month": self.current_month,
"yuthon_company": yuthon_company
})
return attendance_month_detail_obj
def button_compute_all(self):
self.ensure_one()
attendance_month_obj = self._get_attendance_month_obj()
# 查询所有的当前员工? 是否需要判断当前员工是否关联企业微信??预留
calendars = self.env['resource.calendar'].search([])
all_employee_ids = set()
for calendar in calendars:
all_employee_ids.update(calendar.resource_user_ids.ids)
all_employee_ids = list(all_employee_ids)
detail_ids = self.env["hr.attendance.month.detail"].browse(self._context.get('active_ids', self._context.get('active_id')))
for detail_id in detail_ids:
if detail_id.employee_id not in all_employee_ids:
# 判断当前是否已经创建了考勤明细
attendance_month_detail_obj = self._get_attendance_month_detail(detail_id.employee_id)
attendance_month_detail_obj.hr_attendance_month_id = attendance_month_obj.id
# 判断当前用户是否已经确认签字,签字后不再更新
if attendance_month_detail_obj.state == 'confirmed' and attendance_month_detail_obj.signature:
continue
# 更新用户的考勤明细
attendance_month_detail_obj.analysis_attendance_month_detail()
# 返回action动作
action = self._hr_attendance_month_detail_action()
return action
def attendance_month_detail(self):
attendance_details = self.env['hr.attendance.month.detail'].search([])
for detail in attendance_details:
detail.write({'state': 'confirmed'})
def button_all_attendance_month(self):
attendance_details = self.env['hr.attendance.month.detail'].search([])
for detail in attendance_details:
menu_id = self.env['ir.ui.menu'].search([('name', '=', '我的确认'), ('parent_id', '!=', False)])
str = 'https://oa.thtzjt.com/web#id={}&cids=1&menu_id={}&action={}&model=hr.attendance.month.detail&view_type=list'.format(
self.id, menu_id.id, menu_id.action.id)
we_id = self.env['hr.employee'].search([('id', '=', detail.employee_id)]).wecom_userid
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='attendance', user_id=we_id, title="考勤确认",
description=detail .employee_id.name + '请确认你的考勤:',
url=str, btntxt="详细信息")
@@ -11,8 +11,8 @@
parent="hr_attendance_root_board"
groups="group_he_attendance_manager"
sequence="4"/>
<!-- <menuitem id="menu_hr_attendance_month_wizard" name="考勤统计" parent="menu_hr_attendance_month_board"-->
<!-- action="action_hr_attendance_month_wizard"/>-->
<menuitem id="menu_hr_attendance_month_wizard" name="考勤统计" parent="menu_hr_attendance_month_board"
action="action_hr_attendance_month_wizard"/>
<menuitem id="menu_hr_attendance_month_view_attendances" name="报表" parent="menu_hr_attendance_month_board"
sequence="30" action="hr_attendance_month_action"/>
<menuitem id="menu_hr_attendance_year_view_attendances" name="出勤年份维护" parent="menu_hr_attendance_month_board"
@@ -25,7 +25,7 @@
<field name="current_month" />
<field name="is_statistics"/>
<field name="statistics_time"/>
<field name="company_id" />
<field name="yuthon_company" />
<button name="action_show_details" string="汇总明细" type="object" title="Show Details" icon="fa-list"/>
</tree>
</field>
@@ -34,7 +34,7 @@
<field name="name">hr.attendance.month.form</field>
<field name="model">hr.attendance.month</field>
<field name="arch" type="xml">
<form string="hr attendance month" create="0">
<form string="hr attendance month">
<sheet>
<group>
<field name="current_year" />
@@ -94,7 +94,7 @@
<!-- 其他-->
<field name="holiday_id"/>
<field name="note"/>
<field name="company_id"/>
<field name="yuthon_company"/>
<field name="state" widget="badge" decoration-info="state == 'unconfirmed'" decoration-success="state == 'confirmed'"/>
<button name="button_put" string="发送" type="object" class="oe_highlight"/>
</tree>
@@ -137,7 +137,7 @@
<!-- 其他-->
<field name="holiday_id"/>
<field name="note"/>
<field name="company_id"/>
<field name="yuthon_company"/>
<field name="state" widget="badge" decoration-info="state == 'unconfirmed'" decoration-success="state == 'confirmed'"/>
<button name="button_confirm" string="确认" type="object" class="oe_highlight"/>
</tree>
@@ -168,7 +168,7 @@
<field name="work_overtime"/>
<field name="statutory_leave"/>
<field name="note"/>
<field name="company_id"/>
<field name="yuthon_company"/>
<field name="state" />
</group>
</group>
@@ -237,4 +237,11 @@
<field name="state">code</field>
<field name="code">action = model.button_all_put()</field>
</record>
<record id="all_data_attendance_month_compute" model="ir.actions.server">
<field name="name">批量计算</field>
<field name="model_id" ref="yuthon_hr_attendance.model_hr_attendance_month_detail"/>
<field name="binding_model_id" ref="yuthon_hr_attendance.model_hr_attendance_month_detail"/>
<field name="state">code</field>
<field name="code">action = model.button_compute_all()</field>
</record>
</odoo>
@@ -25,7 +25,15 @@ class HrAttendanceMonthWizard(models.TransientModel):
('11', '11月份'),
('12', '12月份')
], string="考勤月份")
company_id = fields.Many2one('res.company', default=lambda self: self.env.company)
yuthon_company = fields.Selection([('thtz', '天河投资集团'), ('thwg', '天河物管'), ('thlc', '天河粮储')],
string='公司', default=lambda self: self._get_default_yuthon_company())
def _get_default_yuthon_company(self):
current_user = self.env.user
employee = self.env['hr.employee'].search([('user_id', '=', current_user.id)], limit=1)
if employee and employee.yuthon_company:
return employee.yuthon_company
return False
def _get_attendance_month_obj(self):
"""
@@ -33,11 +41,11 @@ class HrAttendanceMonthWizard(models.TransientModel):
:return: obj
"""
self.ensure_one()
company_id = self.company_id.id or self.env.company.id
yuthon_company = self.yuthon_company
attendance_month_obj = self.env["hr.attendance.month"].search([
('current_year', '=', self.current_year),
('current_month', '=', self.current_month),
('company_id', '=', company_id),
('yuthon_company', '=', yuthon_company),
], limit=1)
if not attendance_month_obj:
attendance_month_obj = self.env["hr.attendance.month"].sudo().create({
@@ -46,8 +54,8 @@ class HrAttendanceMonthWizard(models.TransientModel):
"current_month": self.current_month,
"is_statistics": True,
"statistics_time": fields.Datetime.now(),
"company_id": company_id,
})
"yuthon_company": yuthon_company,
})
return attendance_month_obj
def _get_attendance_month_detail(self, employee):
@@ -57,17 +65,20 @@ class HrAttendanceMonthWizard(models.TransientModel):
:return: 考情明细
"""
self.ensure_one()
yuthon_company = self.yuthon_company
attendance_month_detail_obj = self.env["hr.attendance.month.detail"].search(
[('employee_id', '=', employee.id),
('current_year', '=', self.current_year),
('current_month', '=', self.current_month)
('current_month', '=', self.current_month),
('yuthon_company', '=', yuthon_company)
], limit=1)
if not attendance_month_detail_obj:
attendance_month_detail_obj = self.env["hr.attendance.month.detail"].sudo().create({
"employee_id": employee.id,
"attendance_year_id": self.attendance_year_id.id,
"current_year": self.current_year,
"current_month": self.current_month
"current_month": self.current_month,
"yuthon_company": yuthon_company
})
return attendance_month_detail_obj
@@ -77,7 +88,7 @@ class HrAttendanceMonthWizard(models.TransientModel):
:return: ir.actions.act_window 视图 view_hr_attendance_month_detail_tree
"""
self.ensure_one()
company_id = self.company_id.id or self.env.company.id
yuthon_company = self.yuthon_company
action = {
'type': 'ir.actions.act_window',
'res_model': 'hr.attendance.month.detail',
@@ -87,12 +98,12 @@ class HrAttendanceMonthWizard(models.TransientModel):
'context': {
"current_year": self.current_year,
"current_month": self.current_month,
"company_id": company_id
"yuthon_company": yuthon_company
},
'domain': [
('current_year', '=', self.current_year),
('current_month', '=', self.current_month),
('company_id', '=', company_id),
('yuthon_company', '=', yuthon_company),
],
'target': 'main',
'views': [[self.env.ref('yuthon_hr_attendance.view_hr_attendance_month_detail_tree').id, 'list'],
@@ -109,13 +120,13 @@ class HrAttendanceMonthWizard(models.TransientModel):
attendance_month_obj = self._get_attendance_month_obj()
# 查询所有的当前员工? 是否需要判断当前员工是否关联企业微信??预留
user_obj = self.env['res.users'].sudo().search([])
company_id = self.company_id.id or self.env.company.id
yuthon_company = self.yuthon_company
calendars = self.env['resource.calendar'].search([])
all_employee_ids = set()
for calendar in calendars:
all_employee_ids.update(calendar.resource_user_ids.ids)
all_employee_ids = list(all_employee_ids)
hr_employee_obj = self.env['hr.employee'].sudo().search([("user_id", "in", user_obj.ids), ("company_id", "=", company_id)])
hr_employee_obj = self.env['hr.employee'].sudo().search([("user_id", "in", user_obj.ids), ("yuthon_company", "=", yuthon_company)])
# 循环所有员工对每个人进行统计
for employee in hr_employee_obj:
if employee.id not in all_employee_ids:
@@ -130,3 +141,20 @@ class HrAttendanceMonthWizard(models.TransientModel):
# 返回action动作
action = self._hr_attendance_month_detail_action()
return action
# 考勤定时任务
def button_attendance_month(self):
now = datetime.datetime.now()
year = now.year
month = str(now.month)
company_options = ['thtz', 'thwg', 'thlc']
attendance_year = self.env['hr.attendance.year'].search([('year', '=', str(year))], limit=1)
if not attendance_year:
attendance_year = self.env['hr.attendance.year'].create({'year': str(year)})
for option in company_options:
wizard = self.create({
'attendance_year_id': attendance_year.id,
'current_month': month,
'yuthon_company':option
})
wizard.search_attendance_month()
@@ -8,7 +8,7 @@
<group>
<field name="attendance_year_id"/>
<field name="current_month" />
<field name="company_id" string="公司名称" invisible="1"/>
<field name="yuthon_company" string="公司名称"/>
</group>
<footer>
<button name="search_attendance_month" id="search_attendance_month" string="开始统计" type="object" class="btn-primary"/>
+3 -3
View File
@@ -120,9 +120,9 @@ class YuthonNotice(models.Model):
'state': 'no',
})
we_id = self.env['hr.employee'].search([('id', '=', employee_id)]).wecom_userid
# self.sudo().env["wecom.apps"].sync_send_message_textcard(category='notice', user_id=we_id, title="通知公告",
# description=self.name + '发布人:' + self.users_id.name,
# url=str, btntxt="详细信息")
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='notice', user_id=we_id, title="通知公告",
description=self.name + '发布人:' + self.users_id.name,
url=str, btntxt="详细信息")
return {
'type': 'ir.actions.client',
'tag': 'display_notification',