diff --git a/yuthon_duty_plan/models/yuthon_duty_arrangement.py b/yuthon_duty_plan/models/yuthon_duty_arrangement.py index fd9ae50f7..bbc6eb880 100644 --- a/yuthon_duty_plan/models/yuthon_duty_arrangement.py +++ b/yuthon_duty_plan/models/yuthon_duty_arrangement.py @@ -39,9 +39,11 @@ class YuthonDutyArrangement(models.Model): @api.depends('duration', 'duration_two', 'duration_three') def _compute_is_abnormal(self): for record in self: - record.is_abnormal = False - if record.start_time < fields.Date.today(): - record.is_abnormal = not all([record.duration, record.duration_two, record.duration_three]) + if record.start_time: + if record.start_time < fields.Date.today(): + record.is_abnormal = not all([record.duration, record.duration_two, record.duration_three]) + else: + record.is_abnormal = False def bottom_adjustment(self): for record in self: diff --git a/yuthon_hr_attendance/models/card_approval.py b/yuthon_hr_attendance/models/card_approval.py index b4808db7e..3f3be6ea4 100644 --- a/yuthon_hr_attendance/models/card_approval.py +++ b/yuthon_hr_attendance/models/card_approval.py @@ -12,45 +12,75 @@ class CardApprovals(models.Model): yuthon_company = fields.Selection(related='users_id.employee_id.yuthon_company', string="公司") name = fields.Char(string="标题", compute='_compute_name') - code = fields.Char(string="编号",default=lambda self: self.env['ir.sequence'].next_by_code('overtime_approval')) + code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('overtime_approval')) users_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user.id) + employee_id = fields.Many2one(related='users_id.employee_id', string="员工") department_id = fields.Many2one(related='users_id.employee_id.department_id', string="部门") is_issues = fields.Boolean(string='是否上会') related_issues_id = fields.Many2one('issue.library', string="关联议题") reason_application = fields.Html(string="申请事由") - replacement_time = fields.Selection([('work', '上班卡'), ('quitting', '下班卡'), ('all', '全天卡')], string="补卡") - actual_punch = fields.Date(string="实际打卡日期") documents_ids = fields.Many2many('ir.attachment', string="附件") + attendance_id = fields.Many2one('hr.attendance', string="补卡日期") + replacement_time = fields.Selection([('work', '上班卡'), ('quitting', '下班卡'), ('all', '全天卡')], string="补卡", + compute='_compute_replacement_time') - @api.onchange('is_issues') - def _onchange_is_issues(self): - if self.is_issues: - issue_id = self.env['issue.library'].create({'name': self.name}) - self.related_issues_id = issue_id.id - workflow_record_id = self.env["soong.workflow.record"].search( - [("res_model", "=", self._name), ("res_id", "=", self.id)]) - self.env['issue.library.approval.line'].create({ - 'issue_library_id': issue_id.id, - 'workflow_record_id': workflow_record_id.id, - 'approval_type': workflow_record_id.workflow_id.id, - 'code': self.code, - 'approval_date': fields.Datetime.now(), - }) - elif self.related_issues_id: - raise UserError("已经创建了相关的上会记录,不能取消勾选") + @api.depends('attendance_id') + def _compute_replacement_time(self): + for rep in self: + rep.replacement_time = 'all' + if rep.attendance_id.is_early_card and not rep.attendance_id.is_late_card: + rep.replacement_time = 'quitting' + if rep.attendance_id.is_late_card and not rep.attendance_id.is_early_card: + rep.replacement_time = 'work' + if rep.attendance_id.is_late_card and rep.attendance_id.is_early_card: + rep.replacement_time = 'all' + if rep.attendance_id.is_late_card and rep.attendance_id.is_no_card: + rep.replacement_time = 'all' + if rep.attendance_id.is_early_card and rep.attendance_id.is_no_card: + rep.replacement_time = 'all' - def card_approval(self): - for record in self: - hr_attendance_id = self.env['hr.attendance'].search([('employee_id', '=', record.users_id.employee_id.id), ('current_data', '=', record.actual_punch)]) - hr_attendance_id.write({'is_no_card': False}) - - @api.depends('users_id', 'replacement_time', 'actual_punch') + @api.depends('users_id', 'attendance_id') def _compute_name(self): for record in self: - if record.users_id and record.actual_punch: - record.name = f"{record.users_id.name}补卡{record.actual_punch.strftime('%Y-%m-%d')}" + record.name = "补卡" + if record.users_id and record.attendance_id: + record.name = f"{record.users_id.name}补卡{str(record.attendance_id.current_data)}" else: - record.name = False + record.name = f"{record.users_id.name}补卡" + + def confirm_approval(self): + min_hour_from = self.users_id.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) + max_hour_to = self.users_id.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) + for rec in self: + if rec.replacement_time == 'work': + rec.attendance_id.check_in = rec.attendance_id.check_in.replace(hour=min_hour, minute=min_minute) - timedelta(hours=8) + if rec.replacement_time == 'quitting': + rec.attendance_id.check_out = rec.attendance_id.check_in.replace(hour=max_hour, minute=max_minute) - timedelta(hours=8) + if rec.replacement_time == 'all': + rec.attendance_id.check_in = rec.attendance_id.check_in.replace(hour=min_hour, minute=min_minute) - timedelta(hours=8) + rec.attendance_id.check_out = rec.attendance_id.check_in.replace(hour=max_hour, minute=max_minute) - timedelta(hours=8) + rec.attendance_id.is_approval = True + + # @api.onchange('is_issues') + # def _onchange_is_issues(self): + # if self.is_issues: + # issue_id = self.env['issue.library'].create({'name': self.name}) + # self.related_issues_id = issue_id.id + # workflow_record_id = self.env["soong.workflow.record"].search( + # [("res_model", "=", self._name), ("res_id", "=", self.id)]) + # self.env['issue.library.approval.line'].create({ + # 'issue_library_id': issue_id.id, + # 'workflow_record_id': workflow_record_id.id, + # 'approval_type': workflow_record_id.workflow_id.id, + # 'code': self.code, + # 'approval_date': fields.Datetime.now(), + # }) + # elif self.related_issues_id: + # raise UserError("已经创建了相关的上会记录,不能取消勾选") diff --git a/yuthon_hr_attendance/models/hr_attendance.py b/yuthon_hr_attendance/models/hr_attendance.py index 1ead8b565..4b630242a 100644 --- a/yuthon_hr_attendance/models/hr_attendance.py +++ b/yuthon_hr_attendance/models/hr_attendance.py @@ -3,11 +3,13 @@ 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 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="缺卡", compute='_compute_attendance_flags') @@ -27,6 +29,29 @@ class HrAttendance(models.Model): ('four', '星期四'), ('five', '星期五'), ('six', '星期六'), ('seven', '星期日')], string='星期', compute='_compute_week', store=True) abnormal = fields.Integer(string="异常计算") + is_approval = fields.Boolean(string="是否审批修正") + + @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:mm"), + ) + 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"), + ) @api.depends('check_in', 'check_out') def _compute_attendance_flags(self): @@ -34,24 +59,23 @@ class HrAttendance(models.Model): record.is_no_card = False record.is_late_card = False record.is_early_card = False - calendar_attendances = self.env['resource.calendar.attendance'].search([]) - min_hour_from = min(att.hour_from for att in calendar_attendances) - if min_hour_from == 8: - min_hour_from = 9 - max_hour_to = max(att.hour_to for att in calendar_attendances) - # 迟到 晚打卡 大于上班时间 + 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) + if record.check_in: check_in = record.check_in + timedelta(hours=8) - will_datetime_start = check_in.replace(hour=int(min_hour_from), - minute=int((min_hour_from % 1) * 100), second=0) + will_datetime_start = check_in.replace(hour=min_hour, minute=min_minute) record.is_late_card = check_in > will_datetime_start else: record.is_no_card = True - # 早退,小于下班时间 + + 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) if record.check_out: check_out = record.check_out + timedelta(hours=8) - will_datetime_end = check_out.replace(hour=int(max_hour_to), - minute=int((min_hour_from % 1) * 100), second=0) + will_datetime_end = check_out.replace(hour=max_hour, minute=max_minute) record.is_early_card = will_datetime_end > check_out else: record.is_no_card = True @@ -122,22 +146,13 @@ class HrAttendance(models.Model): def button_card_approval(self): form_id = self.env.ref('yuthon_hr_attendance.card_approval_form').id - replacement_time = '' - for record in self: - if not record.check_in: - replacement_time = 'work' - elif not record.check_out: - replacement_time = 'quitting' - elif not record.check_in and not record.check_out: - replacement_time = 'all' return { "type": "ir.actions.act_window", "name": "补卡申请", "res_model": "card.approval", "views": [[form_id, "form"]], "context": { - 'default_actual_punch': self.current_data, - 'default_replacement_time': replacement_time, + 'default_attendance_id': self.id, 'default_users_id': self.employee_id.user_id.id, } } diff --git a/yuthon_hr_attendance/views/card_approval.xml b/yuthon_hr_attendance/views/card_approval.xml index 9f14406cb..c0eada149 100644 --- a/yuthon_hr_attendance/views/card_approval.xml +++ b/yuthon_hr_attendance/views/card_approval.xml @@ -7,8 +7,8 @@ - - + + @@ -18,7 +18,7 @@
-
@@ -29,29 +29,24 @@ - + + + + - - - - - - - - - - - + + + 补卡 card.approval diff --git a/yuthon_hr_attendance/views/hr_attendance_views.xml b/yuthon_hr_attendance/views/hr_attendance_views.xml index 1b131b3ac..b386d333e 100644 --- a/yuthon_hr_attendance/views/hr_attendance_views.xml +++ b/yuthon_hr_attendance/views/hr_attendance_views.xml @@ -17,6 +17,7 @@ +