diff --git a/yuthon_hr_attendance/__manifest__.py b/yuthon_hr_attendance/__manifest__.py
index 67f7d648a..ac2b082be 100644
--- a/yuthon_hr_attendance/__manifest__.py
+++ b/yuthon_hr_attendance/__manifest__.py
@@ -81,6 +81,7 @@
'wizard/yuthon_delete_planning_wizard_views.xml',
'wizard/attendance_controls_wizard.xml',
'wizard/attendance_correct_wizard.xml',
+ 'wizard/customer_create_wizard_views.xml',
'wizard/vacation_put_wizard_views.xml',
'wizard/vacation_reports_wizard.xml',
'wizard/vacation_confirm_wizard_views.xml',
@@ -104,6 +105,8 @@
'yuthon_hr_attendance/static/src/xml/button_attendance_month.xml',
'yuthon_hr_attendance/static/src/js/button_detail_wechat.js',
'yuthon_hr_attendance/static/src/xml/button_detail_wechat.xml',
+ 'yuthon_hr_attendance/static/src/js/button_customer_confirm.js',
+ 'yuthon_hr_attendance/static/src/xml/button_customer_confirm.xml',
'yuthon_hr_attendance/static/src/components/*/*.xml',
'yuthon_hr_attendance/static/src/css/*.css',
'yuthon_hr_attendance/static/src/js/button_meal_confirm.js',
diff --git a/yuthon_hr_attendance/models/yuthon_customer_planning.py b/yuthon_hr_attendance/models/yuthon_customer_planning.py
index c006ca9f7..c6db1be24 100644
--- a/yuthon_hr_attendance/models/yuthon_customer_planning.py
+++ b/yuthon_hr_attendance/models/yuthon_customer_planning.py
@@ -5,88 +5,11 @@ from odoo.exceptions import UserError
class YuthonCustomerPlanning(models.Model):
_name = 'yuthon.customer.planning'
- _description = '客户排班计划'
+ _description = '客服值班计划'
- name = fields.Char(string='计划名称', required=True)
- start_index_time = fields.Date(string='生效时间', default=fields.Date.today())
- end_index_time = fields.Date(string='失效时间')
- is_enable = fields.Boolean(string="启用", default=True)
- plan_line_ids = fields.One2many('customer.plan.line', 'customer_plan_id', string='关联计划明细')
- notice = fields.Text(string='计划说明')
- select_time = fields.Selection([('1', '一月'), ('2', '二月'), ('3', '三月'), ('4', '四月'),
- ('5', '五月'), ('6', '六月'), ('7', '七月'), ('8', '八月'),
- ('9', '九月'), ('10', '十月'), ('11', '十一月'),
- ('12', '十二月')], string='选择月份', default=lambda self: self._get_default_month())
+ employee_ids = fields.Many2many('hr.employee', string="员工")
+ date = fields.Date(string='日期')
- def auto_customer_plan(self, next_date=False):
- selected_month = int(self.select_time)
- year = datetime.now().year
- if not next_date:
- start_date = datetime(year, selected_month, 1)
- # 计算结束日期(下个月的第一天)
- next_month = (selected_month % 12) + 1
- next_year = year + (1 if next_month == 1 else 0) # 如果是12月,年份加1
- end_date = datetime(next_year, next_month, 1)
- existing_slots = self.env['planning.slot'].search([
- ('role_id.name', '=', '客服中心'),
- ('start_datetime', '>=', start_date),
- ('start_datetime', '<=', end_date),
- ])
- if len(existing_slots) > 0:
- raise UserError(f"该月已经有排程,请选择其他时间。")
- else:
- next_month = (selected_month % 12) + 1
- next_year = year + (1 if next_month == 1 else 0)
- start_date = datetime(next_year, next_month, 1)
- next_next_month = (next_month % 12) + 1
- next_next_year = next_year + (1 if next_next_month == 1 else 0)
- end_date = datetime(next_next_year, next_next_month, 1)
- existing_slots = self.env['planning.slot'].search([
- ('role_id.name', '=', '客服中心'),
- ('start_datetime', '>=', start_date),
- ('start_datetime', '<=', end_date),
- ])
- if len(existing_slots) > 0:
- raise UserError(f"该月已经有排程,请选择其他时间。")
-
- 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)])
- current_date = start_date
- while current_date < end_date:
- day_of_week = current_date.weekday()
- if day_of_week < 6:
- if day_of_week < 5:
- for employee in self.plan_line_ids:
- self.create_planning_slot(employee, role_a, role_template_a, current_date)
- elif day_of_week == 5:
- current_employee = self.plan_line_ids[current_date.day % len(self.plan_line_ids)]
- self.create_planning_slot(current_employee, role_a, role_template_b, current_date)
- current_date += timedelta(days=1)
-
- def customer_next_plan(self):
- self.auto_customer_plan(next_date=True)
-
- 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)
- current_datetime = datetime.combine(current_date, time(0, 0, 0))
- start_time = current_datetime.replace(hour=start_hour) + timedelta(hours=16) - timedelta(days=1)
- if role_template.end_time < role_template.start_time:
- end_time = current_datetime.replace(hour=end_hour) + timedelta(days=1, hours=16) - timedelta(days=1)
- else:
- end_time = current_datetime.replace(hour=end_hour) + timedelta(hours=16) - timedelta(days=1)
- 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,
- 'allocated_hours': 8,
- })
- def _get_default_month(self):
- current_month = datetime.now().month
- return str(current_month) # 返回字符串类型的月份
class CustomerPlanLine(models.Model):
_name = 'customer.plan.line'
diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py
index 98cd7c1e5..7d4cb2a5f 100644
--- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py
+++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py
@@ -145,6 +145,9 @@ class YuthonVacationReports(models.Model):
duty_schedule_env = self.env['duty.adjustment.schedule']
planning_slot_env = self.env['planning.slot']
+ # 新增:客服值班计划模型
+ customer_planning_env = self.env['yuthon.customer.planning']
+
for record in self:
if not record.employee_id or not record.vacation_date:
record.duty_ids = False
@@ -157,29 +160,32 @@ class YuthonVacationReports(models.Model):
last_day = calendar.monthrange(year, month)[1]
month_end = date(year, month, last_day)
+ # ====================== 原有逻辑 ======================
+ # 1. 删除非调休的 duty 记录
all_duty_records = duty_schedule_env.search([
('vacation_id', '=', record.id),
('duty_date', '>=', month_start),
('duty_date', '<=', month_end)
])
- # 过滤出:非已调休的记录 → 批量删除
non_adjusted_duties = all_duty_records.filtered(lambda d: not d.is_adjustment)
if non_adjusted_duties:
non_adjusted_duties.unlink()
+ # 2. 从 planning.slot 白值生成值班记录
white_duty_slots = planning_slot_env.search([
('employee_id', '=', emp_id),
('planning_name', '=', '白值'),
('start_datetime', '>=', datetime.combine(month_start, datetime.min.time())),
('start_datetime', '<=', datetime.combine(month_end, datetime.max.time()))
])
- existing_duty_dates = {
- d.duty_date for d in duty_schedule_env.search([
- ('vacation_id', '=', record.id),
- ('duty_date', '>=', month_start),
- ('duty_date', '<=', month_end)
- ])
- }
+
+ # 已存在的日期
+ existing_duty_dates = {d.duty_date for d in duty_schedule_env.search([
+ ('vacation_id', '=', record.id),
+ ('duty_date', '>=', month_start),
+ ('duty_date', '<=', month_end)
+ ])}
+
create_vals = []
for slot in white_duty_slots:
if not slot.start_datetime:
@@ -193,8 +199,27 @@ class YuthonVacationReports(models.Model):
'duty_date': duty_date,
'is_adjustment': False
})
+
+ # 从客服值班计划取日期
+ customer_planning_records = customer_planning_env.search([
+ ('date', '>=', month_start),
+ ('date', '<=', month_end),
+ ('employee_ids', 'in', emp_id),
+ ])
+ for plan in customer_planning_records:
+ duty_date = plan.date
+ if duty_date in existing_duty_dates:
+ continue
+ create_vals.append({
+ 'employee_id': emp_id,
+ 'vacation_id': record.id,
+ 'duty_date': duty_date,
+ 'is_adjustment': False
+ })
+
if create_vals:
duty_schedule_env.create(create_vals)
+
record.duty_ids = duty_schedule_env.search([
('vacation_id', '=', record.id),
('duty_date', '>=', month_start),
diff --git a/yuthon_hr_attendance/security/ir.model.access.csv b/yuthon_hr_attendance/security/ir.model.access.csv
index b179dbd83..3259b634b 100644
--- a/yuthon_hr_attendance/security/ir.model.access.csv
+++ b/yuthon_hr_attendance/security/ir.model.access.csv
@@ -102,4 +102,5 @@ access_overtime_carryover_line,overtime.carryover.line,model_overtime_carryover_
access_yuthon_meal_line,yuthon.meal.line,model_yuthon_meal_line,base.group_user,1,1,1,1
access_vacation_meal_active_wizard,vacation.meal.active.wizard,model_vacation_meal_active_wizard,base.group_user,1,1,1,1
-access_vacation_overtime_active_wizard,vacation.overtime.active.wizard,model_vacation_overtime_active_wizard,base.group_user,1,1,1,1
\ No newline at end of file
+access_vacation_overtime_active_wizard,vacation.overtime.active.wizard,model_vacation_overtime_active_wizard,base.group_user,1,1,1,1
+access_customer_create_wizard,customer.create.wizard,model_customer_create_wizard,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/yuthon_hr_attendance/static/src/js/button_customer_confirm.js b/yuthon_hr_attendance/static/src/js/button_customer_confirm.js
new file mode 100644
index 000000000..44e037c0b
--- /dev/null
+++ b/yuthon_hr_attendance/static/src/js/button_customer_confirm.js
@@ -0,0 +1,29 @@
+/** @odoo-module */
+import { ListController } from "@web/views/list/list_controller";
+import { registry } from '@web/core/registry';
+import { listView } from '@web/views/list/list_view';
+
+export class CustomAttendanceCustomerConfirmController extends ListController {
+ setup() {
+ super.setup();
+ }
+
+ openCustomerWizard() {
+ this.actionService.doAction({
+ type: 'ir.actions.act_window',
+ res_model: 'customer.create.wizard',
+ name: '客服排班生成',
+ view_mode: 'form',
+ view_type: 'form',
+ views: [[false, 'form']],
+ target: 'new', // 以弹窗形式打开
+ context: {},
+ });
+ }
+}
+
+registry.category("views").add("custom_customer_confirm_button", {
+ ...listView,
+ Controller: CustomAttendanceCustomerConfirmController,
+ buttonTemplate: "customer_confirm_module.ListView.Buttons",
+});
\ No newline at end of file
diff --git a/yuthon_hr_attendance/static/src/xml/button_customer_confirm.xml b/yuthon_hr_attendance/static/src/xml/button_customer_confirm.xml
new file mode 100644
index 000000000..a7d9d8e6a
--- /dev/null
+++ b/yuthon_hr_attendance/static/src/xml/button_customer_confirm.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yuthon_hr_attendance/views/all_attendance_menu.xml b/yuthon_hr_attendance/views/all_attendance_menu.xml
index 620d0b59c..285b45122 100644
--- a/yuthon_hr_attendance/views/all_attendance_menu.xml
+++ b/yuthon_hr_attendance/views/all_attendance_menu.xml
@@ -158,11 +158,6 @@
-
-
-
-
-
+