From f2bb1f3eb8c43a5927547a43dc24eb1358c6727e Mon Sep 17 00:00:00 2001 From: zhouzhou <123@qq.com> Date: Thu, 5 Dec 2024 20:30:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_duty_plan/models/yuthon_duty_plan.py | 2 +- .../models/planning_template_inherit.py | 21 ++ .../models/yuthon_run_planning.py | 231 ++++++++++++++---- .../models/yuthon_shift_planning.py | 31 +-- .../inherit_planning_slot_template_views.xml | 12 +- .../views/inherit_planning_slot_views.xml | 3 + .../views/yuthon_run_planning_views.xml | 124 ++++++++-- yuthon_work_brand/views/attendance_menu.xml | 17 +- 8 files changed, 348 insertions(+), 93 deletions(-) diff --git a/yuthon_duty_plan/models/yuthon_duty_plan.py b/yuthon_duty_plan/models/yuthon_duty_plan.py index 1f200fd28..905c86594 100644 --- a/yuthon_duty_plan/models/yuthon_duty_plan.py +++ b/yuthon_duty_plan/models/yuthon_duty_plan.py @@ -24,7 +24,7 @@ class YuthonDutyPlan(models.Model): duty_lines = [] current_date = first_day_of_month while current_date <= last_day_of_month: - for line in self.plan_line_ids: + for line in self.plan_line_ids.sorted('sequence'): for employee in line.employee_ids: duty_lines.append({ 'employee_id': employee.id, diff --git a/yuthon_hr_attendance/models/planning_template_inherit.py b/yuthon_hr_attendance/models/planning_template_inherit.py index 6054f1e18..09c5d43a1 100644 --- a/yuthon_hr_attendance/models/planning_template_inherit.py +++ b/yuthon_hr_attendance/models/planning_template_inherit.py @@ -6,11 +6,18 @@ from datetime import datetime, timedelta, time, date from odoo import api, fields, models, _ from odoo.tools import format_time +from random import randint, shuffle class PlanningTemplate(models.Model): _inherit = 'planning.slot.template' + def _get_default_color(self): + return randint(1, 11) + + planning_name = fields.Char(string='名称') + color = fields.Integer("颜色", default=_get_default_color) + def _compute_name(self): super()._compute_name() user_tz = pytz.timezone(self.env['planning.slot']._get_tz()) @@ -38,10 +45,24 @@ class PlanningTemplate(models.Model): duration_days = math.ceil((end_datetime - start_datetime).total_seconds() / (3600 * 24)) return duration_days, timedelta(hours=end_datetime.hour, minutes=end_datetime.minute).total_seconds() / 3600 + @api.depends("planning_name") + def _compute_display_name(self): + super()._compute_display_name() + for record in self: + record.display_name = f"{record.name} {record.role_id.name}{record.planning_name}" + class Planning(models.Model): _inherit = 'planning.slot' + department_id = fields.Many2one('hr.department', string='部门') + color = fields.Integer("Color", compute='_compute_color') + + @api.depends('template_id.color') + def _compute_color(self): + for slot in self: + slot.color = slot.template_id.color + # 修改原生自动安排函数 @api.model def auto_plan_ids(self, view_domain): diff --git a/yuthon_hr_attendance/models/yuthon_run_planning.py b/yuthon_hr_attendance/models/yuthon_run_planning.py index 286e3b5e0..a05e1ff12 100644 --- a/yuthon_hr_attendance/models/yuthon_run_planning.py +++ b/yuthon_hr_attendance/models/yuthon_run_planning.py @@ -13,65 +13,56 @@ class YuthonRunPlanning(models.Model): high_run_ids = fields.One2many('yuthon.high.run.line', 'engineering_planning_id', string='关联高压班排班明细') all_run_ids = fields.One2many('yuthon.all.run.line', 'engineering_planning_id', string='关联综合部排班明细') other_run_ids = fields.One2many('yuthon.other.line', 'engineering_planning_id', string='关联其他明细') - - def confirm(self): - run_lines_list = [self.engineering_run_ids, self.high_run_ids, self.all_run_ids] + department_run_id = fields.Many2one("hr.department", string="部门", required=True, default=lambda self: self.env['hr.department'].search([('name', '=', '运行班')])) + department_high_id = fields.Many2one("hr.department", string="部门", required=True, default=lambda self: self.env['hr.department'].search([('name', '=', '高压班')])) + department_integrated_id = fields.Many2one("hr.department", string="部门", required=True, default=lambda self: self.env['hr.department'].search([('name', '=', '综合班')])) + # 运行班 + def run_confirm(self): today = datetime.today().date() first_day_of_month = today.replace(day=1) if today.month < 12: last_day_of_month = (today.replace(month=today.month + 1, day=1) - timedelta(days=1)) else: last_day_of_month = (today.replace(year=today.year + 1, month=1, day=1) - timedelta(days=1)) - role_a = self.env['planning.role'].search([('name', '=', '工程部白班')], limit=1) - start_time = int(self.env['planning.slot.template'].search([('role_id', '=', role_a.id)]).start_time) - end_time = int(self.env['planning.slot.template'].search([('role_id', '=', role_a.id)]).end_time) - run = 0 - for run_lines in run_lines_list: - if not run_lines: - continue - run += 1 - for employee in run_lines: - current_date = first_day_of_month - while current_date <= last_day_of_month: - resource_id = employee.employee_id.resource_id - self.env['planning.slot'].create({ - 'resource_id': resource_id.id, - 'start_datetime': datetime(current_date.year, current_date.month, current_date.day, start_time) + timedelta(hours=16), - 'end_datetime': datetime(current_date.year, current_date.month, current_date.day, end_time) + timedelta(hours=16), - 'role_id': role_a.id, - 'allocated_hours': 8, - }) - current_date += timedelta(days=1) - if current_date > last_day_of_month: - break - role_b = self.env['planning.role'].search([('name', '=', '工程部中值夜班')], limit=1) - start_time2 = int(self.env['planning.slot.template'].search([('role_id', '=', role_b.id)]).start_time) - end_time2 = int(self.env['planning.slot.template'].search([('role_id', '=', role_b.id)]).end_time) - if run == 1: - all_slot = self.env['planning.slot'].search([('department_id.name', '=', '运行班')]) - elif run == 2: - all_slot = self.env['planning.slot'].search([('department_id.name', '=', '高压班')]) - elif run == 3: - all_slot = self.env['planning.slot'].search([('department_id.name', '=', '综合班')]) - + role_a = self.env['planning.role'].search([('name', '=', '工程部')], limit=1) + start_time = int(self.env['planning.slot.template'].search([('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).start_time) + end_time = int(self.env['planning.slot.template'].search([('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).end_time) + for employee in self.engineering_run_ids: current_date = first_day_of_month - i = -1 while current_date <= last_day_of_month: - for employee in range(0, len(run_lines)): - i = i + 1 - slot_id = all_slot.search([('resource_id', '=', run_lines[employee].employee_id.resource_id.id)]).sorted('start_datetime')[i] - slot_id.sudo().write({ - 'template_id': self.env['planning.slot.template'].search([('role_id', '=', role_b.id)]).id, - 'start_datetime': datetime(current_date.year, current_date.month, current_date.day, - start_time2) + timedelta(hours=16), - 'end_datetime': datetime(current_date.year, current_date.month, current_date.day, - end_time2) + timedelta(days=1, hours=16), - 'role_id': role_b.id, - 'allocated_hours': 8, - }) - current_date += timedelta(days=1) - if current_date > last_day_of_month: - break + resource_id = employee.employee_id.resource_id + self.env['planning.slot'].create({ + 'template_id': self.env['planning.slot.template'].search([('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).id, + 'resource_id': resource_id.id, + 'start_datetime': datetime(current_date.year, current_date.month, current_date.day, start_time) + timedelta(hours=16), + 'end_datetime': datetime(current_date.year, current_date.month, current_date.day, end_time) + timedelta(hours=16), + 'role_id': role_a.id, + 'allocated_hours': 8, + }) + current_date += timedelta(days=1) + if current_date > last_day_of_month: + break + start_time2 = int(self.env['planning.slot.template'].search([('planning_name', '=', '中值夜班'), ('role_id', '=', role_a.id)]).start_time) + end_time2 = int(self.env['planning.slot.template'].search([('planning_name', '=', '中值夜班'), ('role_id', '=', role_a.id)]).end_time) + all_slot = self.env['planning.slot'].search([('department_id.name', '=', '运行班')]) + current_date = first_day_of_month + i = -1 + while current_date <= last_day_of_month: + for employee in range(0, len(self.engineering_run_ids)): + i = i + 1 + slot_id = all_slot.search([('resource_id', '=', self.engineering_run_ids[employee].employee_id.resource_id.id)]).sorted('start_datetime')[i] + slot_id.sudo().write({ + 'template_id': self.env['planning.slot.template'].search([('role_id', '=', role_a.id), ('planning_name', '=', '中值夜班')]).id, + 'start_datetime': datetime(current_date.year, current_date.month, current_date.day, + start_time2) + timedelta(hours=16), + 'end_datetime': datetime(current_date.year, current_date.month, current_date.day, + end_time2) + timedelta(days=1, hours=16), + 'role_id': role_a.id, + 'allocated_hours': 8, + }) + current_date += timedelta(days=1) + if current_date > last_day_of_month: + break other_data = {} for other in self.other_run_ids: @@ -92,18 +83,19 @@ class YuthonRunPlanning(models.Model): pass else: self.env['planning.slot'].create({ + 'template_id': self.env['planning.slot.template'].search([('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).id, 'resource_id': resource_id.id, 'start_datetime': datetime(current_date.year, current_date.month, current_date.day, start_time) + timedelta(hours=16), 'end_datetime': datetime(current_date.year, current_date.month, current_date.day, end_time) + timedelta(hours=16), 'role_id': role_a.id, + '' 'allocated_hours': 8, }) current_date += timedelta(days=1) if current_date > last_day_of_month: break - return { 'type': 'ir.actions.client', 'tag': 'display_notification', @@ -113,7 +105,140 @@ class YuthonRunPlanning(models.Model): 'sticky': False, } } + # 高压班 + def high_confirm(self): + today = datetime.today().date() + first_day_of_month = today.replace(day=1) + if today.month < 12: + last_day_of_month = (today.replace(month=today.month + 1, day=1) - timedelta(days=1)) + else: + last_day_of_month = (today.replace(year=today.year + 1, month=1, day=1) - timedelta(days=1)) + role_a = self.env['planning.role'].search([('name', '=', '工程部')], limit=1) + start_time = int(self.env['planning.slot.template'].search( + [('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).start_time) + end_time = int(self.env['planning.slot.template'].search( + [('role_id', '=', role_a.id), ('planning_name', '=', '白夜班')]).end_time) + for employee in self.high_run_ids: + current_date = first_day_of_month + while current_date <= last_day_of_month: + resource_id = employee.employee_id.resource_id + self.env['planning.slot'].create({ + 'template_id': self.env['planning.slot.template'].search( + [('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).id, + 'resource_id': resource_id.id, + 'start_datetime': datetime(current_date.year, current_date.month, current_date.day, + start_time) + timedelta(hours=16), + 'end_datetime': datetime(current_date.year, current_date.month, current_date.day, + end_time) + timedelta(hours=16), + 'role_id': role_a.id, + 'allocated_hours': 8, + }) + current_date += timedelta(days=1) + if current_date > last_day_of_month: + break + start_time2 = int(self.env['planning.slot.template'].search( + [('planning_name', '=', '中值夜班'), ('role_id', '=', role_a.id)]).start_time) + end_time2 = int(self.env['planning.slot.template'].search( + [('planning_name', '=', '中值夜班'), ('role_id', '=', role_a.id)]).end_time) + all_slot = self.env['planning.slot'].search([('department_id.name', '=', '高压班')]) + current_date = first_day_of_month + i = -1 + while current_date <= last_day_of_month: + for employee in range(0, len(self.high_run_ids)): + i = i + 1 + slot_id = all_slot.search( + [('resource_id', '=', self.high_run_ids[employee].employee_id.resource_id.id)]).sorted( + 'start_datetime')[i] + slot_id.sudo().write({ + 'template_id': self.env['planning.slot.template'].search( + [('role_id', '=', role_a.id), ('planning_name', '=', '中值夜班')]).id, + 'start_datetime': datetime(current_date.year, current_date.month, current_date.day, + start_time2) + timedelta(hours=16), + 'end_datetime': datetime(current_date.year, current_date.month, current_date.day, + end_time2) + timedelta(days=1, hours=16), + 'role_id': role_a.id, + 'allocated_hours': 8, + }) + current_date += timedelta(days=1) + if current_date > last_day_of_month: + break + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'type': 'success', + 'message': '排班安排已完成', + 'sticky': False, + } + } + # 综合班 + def integrated_confirm(self): + today = datetime.today().date() + first_day_of_month = today.replace(day=1) + if today.month < 12: + last_day_of_month = (today.replace(month=today.month + 1, day=1) - timedelta(days=1)) + else: + last_day_of_month = (today.replace(year=today.year + 1, month=1, day=1) - timedelta(days=1)) + role_a = self.env['planning.role'].search([('name', '=', '工程部')], limit=1) + start_time = int(self.env['planning.slot.template'].search( + [('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).start_time) + end_time = int(self.env['planning.slot.template'].search( + [('role_id', '=', role_a.id), ('planning_name', '=', '白夜班')]).end_time) + for employee in self.all_run_ids: + current_date = first_day_of_month + while current_date <= last_day_of_month: + resource_id = employee.employee_id.resource_id + self.env['planning.slot'].create({ + 'template_id': self.env['planning.slot.template'].search( + [('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).id, + 'resource_id': resource_id.id, + 'start_datetime': datetime(current_date.year, current_date.month, current_date.day, + start_time) + timedelta(hours=16), + 'end_datetime': datetime(current_date.year, current_date.month, current_date.day, + end_time) + timedelta(hours=16), + 'role_id': role_a.id, + 'allocated_hours': 8, + }) + current_date += timedelta(days=1) + if current_date > last_day_of_month: + break + start_time2 = int(self.env['planning.slot.template'].search( + [('planning_name', '=', '中值夜班'), ('role_id', '=', role_a.id)]).start_time) + end_time2 = int(self.env['planning.slot.template'].search( + [('planning_name', '=', '中值夜班'), ('role_id', '=', role_a.id)]).end_time) + + all_slot = self.env['planning.slot'].search([('department_id.name', '=', '综合班')]) + current_date = first_day_of_month + i = -1 + while current_date <= last_day_of_month: + for employee in range(0, len(self.all_run_ids)): + i = i + 1 + slot_id = all_slot.search( + [('resource_id', '=', self.all_run_ids[employee].employee_id.resource_id.id)]).sorted( + 'start_datetime')[i] + slot_id.sudo().write({ + 'template_id': self.env['planning.slot.template'].search( + [('role_id', '=', role_a.id), ('planning_name', '=', '中值夜班')]).id, + 'start_datetime': datetime(current_date.year, current_date.month, current_date.day, + start_time2) + timedelta(hours=16), + 'end_datetime': datetime(current_date.year, current_date.month, current_date.day, + end_time2) + timedelta(days=1, hours=16), + 'role_id': role_a.id, + 'allocated_hours': 8, + }) + current_date += timedelta(days=1) + if current_date > last_day_of_month: + break + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'type': 'success', + 'message': '排班安排已完成', + 'sticky': False, + } + } class YuthonEngineeringRunLine(models.Model): _name = 'yuthon.engineering.run.line' @@ -150,7 +275,7 @@ class YuthonOtherLine(models.Model): ('four', '星期四'), ('five', '星期五'), ('six', '星期六'), ('seven', '星期日')], string='固定休息日') employee_id = fields.Many2one('hr.employee', string='人员', - domain=lambda self: [('department_id.name', 'in', ['综合班', '高压班', '运行班'])]) + domain=lambda self: [('department_id.name', 'in', ['运行班'])]) sequence = fields.Integer(string='序号') engineering_planning_id = fields.Many2one('yuthon.run.planning', string='关联工程部排班计划') diff --git a/yuthon_hr_attendance/models/yuthon_shift_planning.py b/yuthon_hr_attendance/models/yuthon_shift_planning.py index b88612d5c..f4d0a1ed0 100644 --- a/yuthon_hr_attendance/models/yuthon_shift_planning.py +++ b/yuthon_hr_attendance/models/yuthon_shift_planning.py @@ -16,12 +16,13 @@ class YuthonShiftPlanning(models.Model): planning_ever_noon_ids = fields.One2many('yuthon.shift.ever.noon.line', 'shift_planning_id', string='关联常中班') def confirm(self): - start_date = datetime.now().replace(day=1) # 获取本月第一天零点 - end_date = (start_date + timedelta(days=32)).replace(day=1) # 获取下个月第一天零点 - role_a = self.env['planning.role'].search([('name', '=', '保安部白班')], limit=1) - role_b = self.env['planning.role'].search([('name', '=', '保安部中班')], limit=1) - role_c = self.env['planning.role'].search([('name', '=', '保安部夜班')], limit=1) - role = [role_a, role_b, role_c] + start_date = datetime.today().replace(day=1) # 获取本月日期 + end_date = (start_date + timedelta(days=32)).replace(day=1) # 获取下个月第一天日期 + role_a = self.env['planning.role'].search([('name', '=', '保安部')], limit=1) + role_template_a = self.env['planning.slot.template'].search([('planning_name', '=', '白班'), ('role_id', '=', role_a.id)]) + role_template_b = self.env['planning.slot.template'].search([('planning_name', '=', '中班'), ('role_id', '=', role_a.id)]) + role_template_c = self.env['planning.slot.template'].search([('planning_name', '=', '夜班'), ('role_id', '=', role_a.id)]) + role = [role_template_a, role_template_b, role_template_c] planning_groups = { 'planning_a_ids': range(len(role)), # 默认顺序: 早 -> 中 -> 夜 'planning_b_ids': [1, 2, 0], # 中 -> 夜 -> 早 @@ -59,9 +60,9 @@ class YuthonShiftPlanning(models.Model): if resource_id in ever_holidays and current_weekday in ever_holidays[resource_id]: pass # 跳过休息日 else: - role_template = self.env['planning.slot.template'].search( - [('role_id', '=', role[role_index].id)], limit=1) - self.create_planning_slot(record, role[role_index], role_template, current_date) + # role_template = self.env['planning.slot.template'].search( + # [('role_id', '=', role[role_index].id)], limit=1) + self.create_planning_slot(record, role_a, role[role_index], current_date) current_date += timedelta(days=1) if current_date >= end_date: break @@ -99,9 +100,7 @@ class YuthonShiftPlanning(models.Model): if resource_id in ever_holidays and current_weekday in ever_holidays[resource_id]: pass # 跳过休息日 else: - role_template = self.env['planning.slot.template'].search( - [('role_id', '=', role_item.id)], limit=1) - self.create_planning_slot(record, role_item, role_template, current_date) # 确保这个方法存在 + self.create_planning_slot(record, role_a,role_item, current_date) # 确保这个方法存在 current_date += timedelta(days=1) # 为白班员工创建排班 create_shifts_for_group(self.planning_ever_white_ids, role[0]) @@ -112,13 +111,15 @@ class YuthonShiftPlanning(models.Model): def create_planning_slot(self, record,role,role_template,current_date): start_hour = int(role_template.start_time) end_hour = int(role_template.end_time) - start_time = current_date.replace(hour=start_hour)+ timedelta(hours=16) + current_datetime = datetime.combine(current_date, time(0, 0, 0)) + start_time = current_datetime.replace(hour=start_hour)+ timedelta(hours=16) if role_template.end_time < role_template.start_time: - end_time = current_date.replace(hour=end_hour)+ timedelta(days=1, hours=16) + end_time = current_datetime.replace(hour=end_hour)+ timedelta(days=1, hours=16) else: - end_time = current_date.replace(hour=end_hour)+ timedelta(hours=16) + end_time = current_datetime.replace(hour=end_hour)+ timedelta(hours=16) self.env['planning.slot'].create({ 'resource_id': record.employee_id.resource_id.id, + 'template_id':role_template.id, 'role_id':role.id, 'start_datetime': start_time, 'end_datetime': end_time, diff --git a/yuthon_hr_attendance/views/inherit_planning_slot_template_views.xml b/yuthon_hr_attendance/views/inherit_planning_slot_template_views.xml index 0f8c42c10..51f9c1fd2 100644 --- a/yuthon_hr_attendance/views/inherit_planning_slot_template_views.xml +++ b/yuthon_hr_attendance/views/inherit_planning_slot_template_views.xml @@ -2,20 +2,28 @@ planning.slot.template.tree.inherit planning.slot.template - + + + + + planning.slot.template.form.inherit planning.slot.template - + + + + + diff --git a/yuthon_hr_attendance/views/inherit_planning_slot_views.xml b/yuthon_hr_attendance/views/inherit_planning_slot_views.xml index a67561425..b9c0ea139 100644 --- a/yuthon_hr_attendance/views/inherit_planning_slot_views.xml +++ b/yuthon_hr_attendance/views/inherit_planning_slot_views.xml @@ -26,6 +26,9 @@ + + + diff --git a/yuthon_hr_attendance/views/yuthon_run_planning_views.xml b/yuthon_hr_attendance/views/yuthon_run_planning_views.xml index 7f43825d1..8b900f1a7 100644 --- a/yuthon_hr_attendance/views/yuthon_run_planning_views.xml +++ b/yuthon_hr_attendance/views/yuthon_run_planning_views.xml @@ -10,6 +10,7 @@ + yuthon.run.planning.form yuthon.run.planning @@ -17,11 +18,12 @@
-
+ @@ -32,25 +34,7 @@ - - - - - - - - - - - - - - - - - - - + @@ -64,9 +48,107 @@
+ + + yuthon.integrated.planning.tree + yuthon.run.planning + + + + + + + + + yuthon.integrated.planning.form + yuthon.run.planning + +
+ +
+
+ + + + + + + + + + + + + + +
+
+
+
+ + + yuthon.high.planning.tree + yuthon.run.planning + + + + + + + + + yuthon.high.planning.form + yuthon.run.planning + +
+ +
+
+ + + + + + + + + + + + + + +
+
+
+
- 排班安排 + 运行班安排 yuthon.run.planning tree,form + [('department_run_id.name', '=', '运行班')] + + + + 综合部安排 + yuthon.run.planning + tree,form + [('department_high_id.name', '=', '综合班')] + + + + 高压部安排 + yuthon.run.planning + tree,form + [('department_integrated_id.name', '=', '高压班')] + diff --git a/yuthon_work_brand/views/attendance_menu.xml b/yuthon_work_brand/views/attendance_menu.xml index f72609deb..435aee322 100644 --- a/yuthon_work_brand/views/attendance_menu.xml +++ b/yuthon_work_brand/views/attendance_menu.xml @@ -75,11 +75,26 @@ name="工程部计划" parent="hr_attendance_root_board" sequence="7"/> - + + + +