Files
gzth/yuthon_hr_attendance/models/hr_attendance.py
T
2025-08-12 18:09:02 +08:00

914 lines
47 KiB
Python

# -*- coding: utf-8 -*-
from datetime import datetime, time
from odoo import models, fields, api, exceptions, _
from datetime import timedelta
from dateutil.relativedelta import relativedelta
from odoo.tools import format_datetime, format_duration
import logging
from odoo.exceptions import UserError, ValidationError
import calendar
_logger = logging.getLogger(__name__)
class HrAttendance(models.Model):
_inherit = "hr.attendance"
_description = "Attendance"
_rec_name = 'current_data'
is_clock_card = fields.Boolean(string="外勤")
is_no_card = fields.Boolean(string="缺卡", group_operator='count_true')
is_early_card = fields.Boolean(string="早退", group_operator='count_true')
is_late_card = fields.Boolean(string="迟到", group_operator='count_true')
is_abnormal = fields.Boolean(string="异常", group_operator='count_true')
is_approval_no = fields.Boolean()
is_approval_early = fields.Boolean()
is_approval_late = fields.Boolean()
is_approval_abnormal = fields.Boolean()
user_id = fields.Many2one(related='employee_id.user_id', store=True)
absenteeism_card = fields.Boolean(string="旷工", group_operator='count_true')
is_approval_abs = fields.Boolean()
work_time_type = fields.Selection([('close_day', '休息日'), ('work_day', '工作日')], string="工作时间类型")
company_id = fields.Many2one(related='employee_id.company_id', string='公司', index=True, store=True)
on_card_location = fields.Char(string="上班打卡地点")
down_card_location = fields.Char(string="下班打卡地点")
out_card_time = fields.Datetime(string="外出打卡时间")
out_card_location = fields.Char(string="外出打卡地点")
department_id = fields.Many2one(related='employee_id.department_id', string="部门", store=True)
work_hours = fields.Float(string="工作时长")
current_data = fields.Date(string='打卡日期', tracking=True)
week = fields.Selection([('one', '一'), ('two', '二'), ('three', '三'),
('four', '四'), ('five', '五'), ('six', '六'),
('seven', '日')], string='星期', compute='_compute_week', store=True)
abnormal = fields.Integer(string="异常计算")
shift_id = fields.Many2one('planning.slot', string="班次", store=True)
shift_name = fields.Char(string="班次", related="shift_id.template_id.planning_name", store=True)
noon_duty = fields.Datetime(string="中值")
night_duty = fields.Datetime(string="晚值")
is_approval = fields.Boolean(string="是否审批修正", default=False)
is_check_in_red = fields.Boolean(string="是否上班打卡异常")
is_check_out_red = fields.Boolean(string="是否下班打卡异常")
is_warning = fields.Boolean(compute='_compute_is_warning', string="警告", store=True)
approval_check_in = fields.Datetime(string="修正前上班打卡时间")
approval_check_out = fields.Datetime(string="修正前下班打卡时间")
is_workflow = fields.Boolean(string="是否是流程", default=False)
workflow_id = fields.Many2one('soong.workflow.record', string="流程")
is_month = fields.Boolean(string="是否为本月数据", compute='_compute_month_status', store=True)
is_last_month = fields.Boolean(string="是否为上月数据", compute='_compute_month_status', store=True)
@api.depends('is_no_card', 'is_early_card', 'is_late_card', 'is_abnormal', 'absenteeism_card')
def _compute_is_warning(self):
for record in self:
record.is_warning = (
record.is_no_card or
record.is_early_card or
record.is_late_card or
record.is_abnormal or
record.absenteeism_card
)
def button_workflow(self):
self.ensure_one()
return {
'name': '流程',
'type': 'ir.actions.act_window',
'view_mode': 'tree',
'res_model': 'soong.workflow.record',
'domain': [('id', '=', self.workflow_id.id)],
}
def compute_attendance_ids(self):
for att in self.env["hr.attendance"].browse(self._context.get('active_ids', self._context.get('active_id'))):
now_time = fields.Datetime.to_datetime(att.current_data) + timedelta(hours=8, days=1)
start_time = now_time - timedelta(days=2)
self.env["hr.attendance.detail"].get_hr_attendance_time(att.employee_id, now_time, start_time)
@api.depends('current_data')
def _compute_month_status(self):
today = fields.Date.today()
# 获取本月第一天和最后一天
first_day_this_month = today.replace(day=1)
last_day_this_month = today.replace(day=calendar.monthrange(today.year, today.month)[1])
# 获取上月第一天和最后一天
first_day_last_month = first_day_this_month - relativedelta(months=1)
last_day_last_month = first_day_this_month - relativedelta(days=1)
for record in self:
if not record.current_data:
record.is_month = False
record.is_last_month = False
continue
# 判断是否为本月
record.is_month = (first_day_this_month <= record.current_data <= last_day_this_month)
# 判断是否为上月
record.is_last_month = (first_day_last_month <= record.current_data <= last_day_last_month)
def compute_company_id(self):
all_attendances = self.env['hr.attendance'].search([])
for record in all_attendances:
if record.employee_id:
record.company_id = record.employee_id.company_id
else:
record.company_id = False
# @api.model
# def web_read_group(self, domain, fields, groupby, limit=None, offset=0, orderby=False, lazy=True):
# result = super().web_read_group(domain, fields, groupby, limit, offset, orderby, lazy)
# fields_dict = self.fields_get(fields)
# for group in result.get('groups'):
# for field in fields:
# if fields_dict[field].get('type') == 'boolean':
# group[field] = len([r for r in self.search_read(group['__domain'], fields=[field]) if r.get(field)])
# return result
@api.constrains('check_in', 'check_out')
def _check_validity_check_in_check_out(self):
""" verifies if check_in is earlier than check_out. """
for attendance in self:
if attendance.check_in and attendance.check_out:
if attendance.check_out < attendance.check_in:
print('------------------------------修改源码后期优化')
# raise exceptions.ValidationError(_('"Check Out" time cannot be earlier than "Check In" time.'))
#考勤异常提醒
def card_remind(self):
menu_id = self.env['ir.ui.menu'].search([('name', '=', '我的异常')])
all_employees = self.env['hr.employee'].search([('name', '=', '叶华锋')])
current_date = fields.Date.today()
month_start = current_date.replace(day=1)
month_end = (month_start + relativedelta(months=1) - relativedelta(days=1))
for employee in all_employees:
domain = [
('shift_name', '=', '行政班次'),
('employee_id', '=', employee.id),
('current_data', '>=', month_start),
('current_data', '<=', month_end)
]
is_no_card = 0
is_early_card = 0
is_late_card = 0
is_abnormal = 0
absenteeism_card = 0
attend_records = self.env['hr.attendance'].search(domain)
has_abnormal = False
for record in attend_records:
if record.is_no_card or record.is_early_card or record.is_late_card or record.is_abnormal or record.absenteeism_card:
has_abnormal = True
if record.is_no_card:
is_no_card += 1
if record.is_early_card:
is_early_card += 1
if record.is_late_card:
is_late_card += 1
if record.is_abnormal:
is_abnormal += 1
if record.absenteeism_card:
absenteeism_card += 1
if has_abnormal:
url = (f'https://oa.thtzjt.com/web?login={employee.user_id.login}&oauth_uid={employee.wecom_userid}&cids=2&action={menu_id.action.id}&menu_id={menu_id.id}&model={self._name}'
f'&view_type=list#action={menu_id.action.id}&model={self._name}&view_type=list&menu_id={menu_id.id}')
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='att', user_id=employee.wecom_userid, title="打卡异常提醒",
description="本月迟到: {}\n本月缺卡: {}\n本月早退: {}\n本月异常:{}\n 本月旷工: {}\n"
.format(is_late_card, is_no_card, is_early_card, is_abnormal, absenteeism_card),
url=url, btntxt="详细信息")
@api.depends('employee_id', 'check_in', 'check_out')
def _compute_display_name(self):
for attendance in self:
is_early_card = '早退' if attendance.is_early_card else ''
is_late_card = '迟到' if attendance.is_late_card else ''
if not attendance.check_out:
attendance.display_name = _(
str(attendance.current_data) + " 上午:%s" + is_late_card + " -下午缺卡",
format_datetime(self.env, attendance.check_in, dt_format="HH:mrm"),
)
elif not attendance.check_in:
attendance.display_name = _(
str(attendance.current_data) + " 上午:缺卡-下午%s" + is_early_card,
format_datetime(self.env, attendance.check_out, dt_format="HH:mm"),
)
else:
attendance.display_name = _(
str(attendance.current_data) + " 上午:%s" + is_late_card + "-下午:%s" + is_early_card,
format_datetime(self.env, attendance.check_in, dt_format="HH:mm"),
format_datetime(self.env, attendance.check_out, dt_format="HH:mm"),
)
def add_comment(self):
self.ensure_one()
menu_id = self.env['ir.ui.menu'].search([('name', '=', '我的异常')])
for rec in self:
current_date = datetime.today()
month_start = current_date.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
month_end = (current_date.replace(day=1, hour=0, minute=0, second=0, microsecond=0) + relativedelta(months=1)) - timedelta(seconds=1)
domain = [
('employee_id.user_id', '=', rec.employee_id.user_id.id),
('check_in', '>=', month_start),
('check_in', '<=', month_end),
('week', 'not in', ['seven', 'six'])
]
is_no_card = 0
is_early_card = 0
is_late_card = 0
for i in self.search(domain):
if i.is_no_card:
is_no_card += 1
if i.is_no_card:
is_early_card += 1
if i.is_no_card:
is_late_card += 1
url = f'https://oa.thtzjt.com/web#id={self.id}&cids=2&action={menu_id.action.id}&model=hr.attendance&view_type=from&menu_id={menu_id.id}'
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='att', user_id=rec.employee_id.wecom_userid,
title="打卡异常提醒", description="本月迟到: {}\n本月缺卡: {}\n本月早退: {}\n".format(is_late_card, is_no_card, is_early_card),
url=url, btntxt="详细信息")
def button_controls_wizard(self):
return {
"type": "ir.actions.act_window",
"name": "操作弹窗",
"res_model": "attendance.controls.wizard",
"view_mode": "form",
"target": "new",
"context": {
"default_attendance_id": self.id
}
}
def revoke(self):
self.check_in = self.approval_check_in
self.check_out = self.approval_check_out
self.is_no_card = self.is_approval_no
self.is_early_card = self.is_approval_early
self.is_late_card = self.is_approval_late
self.is_abnormal = self.is_approval_abnormal
self.absenteeism_card = self.is_approval_abs
self.is_approval = False
if self.is_check_in_red == True:
self.is_check_in_red = False
if self.is_check_out_red == True:
self.is_check_out_red = False
def button_correct_wizard(self):
self.approval_check_in = self.check_in
self.approval_check_out = self.check_out
self.is_approval_no = self.is_no_card
self.is_approval_early = self.is_early_card
self.is_approval_late = self.is_late_card
self.is_approval_abnormal = self.is_abnormal
self.is_approval_abs = self.absenteeism_card
return {
"type": "ir.actions.act_window",
"name": "修正弹窗",
"res_model": "attendance.correct.wizard",
"view_mode": "form",
"target": "new",
"context": {
"default_attendance_id": self.id
}
}
def button_compensatory_leave(self):
form_id = self.env.ref('yuthon_hr_attendance.view_yuthon_adjustments_approval_form').id
return {
"type": "ir.actions.act_window",
"name": "调休申请",
"res_model": "yuthon.adjustments.approval",
"views": [[form_id, "form"]],
"context": {
'default_users_id': self.employee_id.user_id.id,
}
}
def button_source(self):
employee_id = self.employee_id.id
current_date = self.current_data
local_start = datetime.combine(current_date, datetime.min.time())
local_end = local_start + timedelta(days=1)
utc_start = local_start - timedelta(hours=8)
utc_end = local_end - timedelta(hours=8)
domain = [
("exception_type", "!=", "未打卡"),
('employee_id', '=', employee_id),
('checkin_time', '>=', fields.Datetime.to_string(utc_start)),
('checkin_time', '<', fields.Datetime.to_string(utc_end))
]
attendance_records = self.env['hr.attendance.detail'].search(domain)
if attendance_records:
action = {
'name': '考勤记录列表',
'type': 'ir.actions.act_window',
'res_model': 'hr.attendance.detail',
'view_mode': 'tree',
'domain': domain,
}
return action
else:
raise ValidationError("该员工当天没有考勤记录!")
def button_card_approval(self):
form_id = self.env.ref('yuthon_hr_attendance.card_approval_form').id
if self.is_approval:
raise ValidationError("该补卡已提交申请!")
else:
self.is_approval = True
return {
"type": "ir.actions.act_window",
"name": "补卡申请",
"res_model": "card.approval",
"views": [[form_id, "form"]],
"context": {
'default_attendance_id': self.id,
'default_users_id': self.employee_id.user_id.id,
'default_shift_id':self.shift_id.id
}
}
def button_duty_approval(self):
form_id = self.env.ref('yuthon_hr_attendance.go_approval_form').id
return {
"type": "ir.actions.act_window",
"name": "外出申请",
"res_model": "go.approval",
"views": [[form_id, "form"]],
"context": {
'default_is_day': True,
'default_statr_date': self.current_data,
'default_end_date': self.current_data,
'default_users_id': self.employee_id.user_id.id,
}
}
def button_correct_approval(self):
for record in self:
if not record.shift_id:
year = record.current_data.year
month = record.current_data.month
day = record.current_data.day
current_date = datetime.today()
min_hour_from = record.employee_id.resource_id.calendar_id.attendance_ids[0].hour_from
min_hour = int(min_hour_from)
min_minute = int(min_hour_from * 10 % min_hour_from)
will_datetime_start = current_date.replace(year=year, month=month, day=day, hour=min_hour, minute=min_minute) - timedelta(hours=8)
record.write({'check_in': will_datetime_start, 'is_approval': True, 'is_abnormal':False, 'is_no_card':False, 'is_early_card':False, 'is_late_card':False})
max_hour_to = record.employee_id.resource_id.calendar_id.attendance_ids[-1].hour_to
max_hour = int(max_hour_to)
max_minute = int(max_hour_to * 10 % max_hour_to)
will_datetime_end = current_date.replace(year=year, month=month, day=day, hour=max_hour, minute=max_minute) - timedelta(hours=8)
record.write({'check_out': will_datetime_end, 'is_approval': True, 'is_abnormal':False, 'is_no_card':False, 'is_early_card':False, 'is_late_card':False, 'absenteeism_card':False})
else:
check_in_start = record.shift_id.template_id.check_in_start
check_out_end = record.shift_id.template_id.check_out_end
date = record.current_data
start_hour = int(check_in_start)
start_minute = int((check_in_start - start_hour) * 60)
end_hour = int(check_out_end)
end_minute = int((check_out_end - end_hour) * 60)
# 拼接成 datetime 对象
start_datetime = datetime.combine(date, datetime.min.time()).replace(
hour=start_hour, minute=start_minute, second=0, microsecond=0
)
end_datetime = datetime.combine(date, datetime.min.time()).replace(
hour=end_hour, minute=end_minute, second=0, microsecond=0
)
if record.shift_id.template_id.day2 == '次日':
end_datetime = end_datetime + timedelta(days=1)
record.write(
{'check_out': end_datetime, 'check_in':start_datetime, 'is_approval': True, 'is_abnormal': False, 'is_no_card': False,
'is_early_card': False, 'is_late_card': False, 'absenteeism_card':False})
def button_batch_correct(self):
attendance_ids = self.env["hr.attendance"].browse(self._context.get('active_ids', self._context.get('active_id')))
for record in attendance_ids:
if not record.shift_id:
year = record.current_data.year
month = record.current_data.month
day = record.current_data.day
current_date = datetime.today()
min_hour_from = record.employee_id.resource_id.calendar_id.attendance_ids[0].hour_from
min_hour = int(min_hour_from)
min_minute = int(min_hour_from * 10 % min_hour_from)
will_datetime_start = current_date.replace(year=year, month=month, day=day, hour=min_hour,
minute=min_minute) - timedelta(hours=8)
record.write({'check_in': will_datetime_start, 'is_approval': True, 'is_abnormal':False, 'is_no_card':False, 'is_early_card':False, 'is_late_card':False})
max_hour_to = record.employee_id.resource_id.calendar_id.attendance_ids[-1].hour_to
max_hour = int(max_hour_to)
max_minute = int(max_hour_to * 10 % max_hour_to)
will_datetime_end = current_date.replace(year=year, month=month, day=day, hour=max_hour,
minute=max_minute) - timedelta(hours=8)
record.write({'check_out': will_datetime_end, 'is_approval': True, 'is_abnormal':False, 'is_no_card':False, 'is_early_card':False, 'is_late_card':False})
else:
check_in_start = record.shift_id.template_id.check_in_start
check_out_end = record.shift_id.template_id.check_out_end
date = record.current_data
start_hour = int(check_in_start)
start_minute = int((check_in_start - start_hour) * 60)
end_hour = int(check_out_end)
end_minute = int((check_out_end - end_hour) * 60)
# 拼接成 datetime 对象
start_datetime = datetime.combine(date, datetime.min.time()).replace(
hour=start_hour, minute=start_minute, second=0, microsecond=0
)
end_datetime = datetime.combine(date, datetime.min.time()).replace(
hour=end_hour, minute=end_minute, second=0, microsecond=0
)
if record.shift_id.template_id.day2 == '次日':
end_datetime = end_datetime + timedelta(days=1)
record.write(
{'check_out': end_datetime, 'check_in': start_datetime, 'is_approval': True, 'is_abnormal': False,
'is_no_card': False,
'is_early_card': False, 'is_late_card': False})
@api.depends('current_data')
def _compute_week(self):
for record in self:
if record.current_data:
weekday = (record.current_data + timedelta(hours=8)).weekday()
weekdays_cn = {0: 'one', 1: 'two', 2: 'three',
3: 'four', 4: 'five', 5: 'six',
6: 'seven'}
record.week = weekdays_cn[weekday]
else:
record.week = False
# 行政异常提醒
def admin_comment_abnormal(self):
week = (fields.date.today() + timedelta(hours=8)).weekday()
if week < 5:
employee_ids = self.env['hr.employee'].search([('department_id.name', '=', '办公室')])
menu_id = self.env['ir.ui.menu'].search([('name', '=', '我的异常')])
for employee_id in employee_ids:
url = f'https://oa.thtzjt.com/web#id={self.id}&cids=2&action={menu_id.action.id}&model=hr.attendance&view_type=from&menu_id={menu_id.id}'
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='att',
user_id=employee_id.wecom_userid,
title="打卡异常提醒", description="异常提醒",
url=url, btntxt="详细信息")
# 保安部 - 白班
def ba_card_white_up(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '早班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name)
def ba_card_white_down(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '早班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name)
# 保安部 - 中班
def ba_card_mid_up(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '中班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name)
def ba_card_mid_down(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '中班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name)
# 保安部 - 夜班
def ba_card_night_up(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '夜班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name)
def ba_card_night_down(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '保安部'), ('template_id.planning_name', '=', '夜班')])
for user in ba_up_users:
if user.end_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name)
# 工程部 - 白班
def gc_white_in_remind(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name)
def gc_white_shift_remind(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白值')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_duty_remind(user.resource_id.employee_id)
def gc_white_out_remind(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name)
# 工程部 - 白值
def gc_white_remind_in(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白值')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name)
def gc_white_remind_out(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '白值')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name)
# 工程部-中值夜
def gc_night_remind_in(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '中夜')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name)
def gc_night_remind_shift(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '中夜')])
for user in ba_up_users:
if user.end_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_duty_remind(user.resource_id.employee_id)
def gc_night_remind_out(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '工程部'), ('template_id.planning_name', '=', '中夜')])
for user in ba_up_users:
if user.end_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name)
# 粮储-白班
def card_lc_remind_in(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id,user.template_id.planning_name)
def card_lc_remind_out(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time':datetime.now(),
'shift':user.template_id.planning_name,
'department': user.department_id.name,})
self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name)
# 粮储-值班
def card_lc_shift_remind_in(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白值')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name)
def card_lc_shift_remind(self):
ba_up_users = self.env['planning.slot'].search(
[('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白值')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_duty_remind(user.resource_id.employee_id)
def card_lc_shift_remind_out(self):
ba_up_users = self.env['planning.slot'].search([('role_id.name', '=', '联安粮库'), ('template_id.planning_name', '=', '白值')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_out_comment(user.resource_id.employee_id,user.template_id.planning_name)
def card_lc_shift_remind_on_administrative(self):
ba_up_users = self.env['planning.slot'].search([('template_id.planning_name', '=', '保安计划行政')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name)
def card_lc_shift_remind_out_administrative(self):
ba_up_users = self.env['planning.slot'].search([('template_id.planning_name', '=', '保安计划行政')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name)
# 客服上班消息提醒
def card_customer_service_shift_remind_on(self):
ba_up_users = self.env['planning.slot'].search([('role_id.name', '=', '客服中心'), ('template_id.planning_name', '=', '白班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_in_comment(user.resource_id.employee_id, user.template_id.planning_name)
# 客服下班消息提醒
def card_customer_service_shift_remind_out(self):
ba_up_users = self.env['planning.slot'].search([('role_id.name', '=', '客服中心'), ('template_id.planning_name', '=', '白班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_out_comment(user.resource_id.employee_id, user.template_id.planning_name)
# 客服值班消息提醒
def card_customer_service_stand_remind(self):
ba_up_users = self.env['planning.slot'].search([('role_id.name', '=', '客服中心'), ('template_id.planning_name', '=', '值班')])
for user in ba_up_users:
if user.start_datetime.date() == fields.date.today():
self.env['card.remind.form'].create({
'name': user.resource_id.employee_id.name,
'start_time': datetime.now(),
'shift': user.template_id.planning_name,
'department': user.department_id.name, })
self.card_duty_remind(user.resource_id.employee_id)
def card_in_comment(self, employee_id, planning_name):
data = f"您的班次是{planning_name},还有10分钟上班,记得打卡"
url = '#小程序://天投云/XttsPpKg3MEpY7h'
self.sudo().env["wecom.apps"].sync_send_message(category='att', user_id=employee_id.wecom_userid,
description=data,
title="打卡提醒",
url=url, btntxt="详细信息")
def card_out_comment(self, employee_id, planning_name):
data = f"您的班次是{planning_name},您该下班了,记得打卡"
url = '#小程序://天投云/XttsPpKg3MEpY7h'
self.sudo().env["wecom.apps"].sync_send_message(category='att', user_id=employee_id.wecom_userid,
description=data,
title="打卡提醒",
url=url, btntxt="详细信息")
def card_duty_remind(self, employee_id):
data = "今天您值班,记得打卡"
url = '#小程序://天投云/XttsPpKg3MEpY7h'
self.sudo().env["wecom.apps"].sync_send_message(category='att', user_id=employee_id.wecom_userid,
description=data,
title="打卡提醒",
url=url, btntxt="详细信息")
# @api.depends('employee_id')
# def compute_shift_id(self):
# target_departments = ['工程部', '保安部', '联安粮库']
# departments = self.env['hr.department'].search([('name', 'in', target_departments)])
# all_child_departments = self.env['hr.department'].search([('id', 'child_of', departments.ids)])
# employees = self.env['hr.employee'].search([('department_id', 'in', all_child_departments.ids)])
#
# for employee in employees:
# planning_slots = self.env['planning.slot'].search([('resource_id', '=', employee.resource_id.id)])
# for slot in planning_slots:
# start_date = slot.start_datetime.date()
# attendance = self.env['hr.attendance'].search([
# ('employee_id', '=', employee.id),
# ('current_data', '=', start_date)
# ])
# if attendance:
# attendance.write({'shift_id': slot.shift_id.id})
def update_attendance(self):
self.browse(self._context.get('active_ids', self._context.get('active_id'))).write({'check_in': False})
def update_shift(self):
attendance_ids = self.env["hr.attendance"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for attendance_id in attendance_ids:
if not attendance_id.shift_id:
attendance_id.shift_name = '行政班次'
def update_id(self):
attendance_ids = self.env["hr.attendance"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for attendance_id in attendance_ids:
attendance_id.userid = attendance_id.employee_id.user_id.id
@api.model
def create(self, vals):
if 'current_data' in vals:
current_data = fields.Date.to_date(vals['current_data'])
today = fields.Date.today()
if current_data > today:
return self.env['hr.attendance']
record = super(HrAttendance, self).create(vals)
if not record.shift_id:
shift_days_list = []
is_shift_replacement = False
is_leave_day = False
is_weekend = False
if record.current_data:
# 查询休假记录
leave_records = self.env['resource.calendar.leaves'].search([("calendar_id", "=", "行政考勤工作日")])
# 检查是否存在匹配的休假日期
for leave in leave_records:
if leave.date_from and leave.date_to:
# 提取休假记录的月日范围
from_date = fields.Date.to_date(leave.date_from)+ timedelta(days=1)
to_date = fields.Date.to_date(leave.date_to)+ timedelta(days=1)
if from_date <= record.current_data <= to_date:
is_leave_day = True
if leave.shift_replacement_day:
shift_days_list.extend(leave.shift_replacement_day.split(',')) # 调班补班
target_day_str = f"{record.current_data.month}月{record.current_data.day}日"
if target_day_str in shift_days_list:
is_shift_replacement = True
weekday = record.current_data.isoweekday()
if weekday in [6, 7]:
is_weekend = True
if is_leave_day:
record.shift_name = ''
elif is_shift_replacement:
record.shift_name = '行政班次'
elif is_weekend:
record.shift_name = ''
else:
record.shift_name = '行政班次'
return record
def button_all(self):
attendance_ids = self.env["hr.attendance"].browse(self._context.get('active_ids', self._context.get('active_id')))
for record in attendance_ids:
if not record.shift_id:
shift_days_list = []
is_shift_replacement = False
is_leave_day = False
is_weekend = False
if record.current_data:
# 查询休假记录
leave_records = self.env['resource.calendar.leaves'].search(
[("calendar_id", "=", "行政考勤工作日")])
# 检查是否存在匹配的休假日期
for leave in leave_records:
if leave.date_from and leave.date_to:
# 提取休假记录的月日范围
from_date = fields.Date.to_date(leave.date_from) + timedelta(days=1)
to_date = fields.Date.to_date(leave.date_to) + timedelta(days=1)
if from_date <= record.current_data <= to_date:
is_leave_day = True
if leave.shift_replacement_day:
shift_days_list.extend(leave.shift_replacement_day.split(',')) # 调班补班
target_day_str = f"{record.current_data.month}月{record.current_data.day}日"
if target_day_str in shift_days_list:
is_shift_replacement = True
weekday = record.current_data.isoweekday()
if weekday in [6, 7]:
is_weekend = True
if is_leave_day:
record.shift_name = ''
elif is_shift_replacement:
record.shift_name = '行政班次'
elif is_weekend:
record.shift_name = ''
else:
record.shift_name = '行政班次'
def labor_update(self):
start_date = fields.Date.to_date('2025-05-01')
end_date = fields.Date.to_date('2025-05-05')
# 搜索符合条件的考勤记录
attendance_records = self.search([
('current_data', '>=', start_date),
('current_data', '<=', end_date),
('shift_id', '=', False),
])
if attendance_records:
for record in attendance_records:
record.write({
'is_no_card': False,
'is_early_card': False,
'is_late_card': False,
'is_abnormal': False,
'is_approval': True,
})
class card_remind_form(models.Model):
_name = 'card.remind.form'
_description = '测试表单'
name = fields.Char(string='姓名')
start_time = fields.Datetime(string='时间')
shift = fields.Char(string='班次')
department = fields.Char(string='部门')
class MedicalRulesSetting(models.Model):
_name = 'medical.rules.setting' # 数据库keyerror错误