914 lines
47 KiB
Python
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错误
|