From 6a7f51a327ee80873305e98b666d7fba3568c66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Mon, 9 Mar 2026 17:32:40 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E9=A4=90=E9=A5=AE=E6=8A=A5=E8=A1=A8=20=20?= =?UTF-8?q?=E6=8C=89=E4=BA=BA=E6=95=B0=E7=BB=9F=E8=AE=A1=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_catering/models/yuthon_catering.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yuthon_catering/models/yuthon_catering.py b/yuthon_catering/models/yuthon_catering.py index 932765730..3eb3dfd5e 100644 --- a/yuthon_catering/models/yuthon_catering.py +++ b/yuthon_catering/models/yuthon_catering.py @@ -10,8 +10,8 @@ class YuthonCatering(models.Model): week_day = fields.Char(string='星期', compute='_compute_week_day', store=True) dept_id = fields.Many2one(string='部门', comodel_name='hr.department', related='employee_id.department_id', store=True) employee_id = fields.Many2one(string='员工', comodel_name='hr.employee', required=True) - breakfast = fields.Boolean(string='早餐', default=False) - lunch = fields.Boolean(string='午餐', default=False) + breakfast = fields.Boolean(string='早餐', default=False, group_operator='count_true') + lunch = fields.Boolean(string='午餐', default=False, group_operator='count_true') menu_day_id = fields.Many2one('yuthon.menu.setting', string='菜单') amount = fields.Float(string='结算费用', compute='_compute_amount', store=True) From 107a9116b6625d6a14e3608d181b512c552f309c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Mon, 9 Mar 2026 18:06:06 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E4=BC=9A=E8=AE=AE=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=97=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- room/models/room_booking.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/room/models/room_booking.py b/room/models/room_booking.py index 9bde7b31b..4701e5d1a 100644 --- a/room/models/room_booking.py +++ b/room/models/room_booking.py @@ -303,6 +303,29 @@ class RoomBooking(models.Model): room_name=booking.room_id.name )) + @api.model + def create(self, vals): + """创建会议后同步生成日程""" + booking = super(RoomBooking, self).create(vals) + # 同步生成yuthon.will.task记录 + if booking: + # 提取参会人员(从room_users_ids转换为hr.employee) + employee_records = self.env['hr.employee'].search([('user_id', 'in', booking.room_users_ids.ids)]) + # 创建日程记录 + self.env['yuthon.will.task'].create({ + 'name': booking.name, + 'start_date': booking.start_datetime.date(), + 'task_type': 'meet', + 'room_booking_id': booking.id, + 'employee_ids': [(6, 0, employee_records.ids)] if employee_records else [(5, 0, 0)], + 'task_state': 'will', + 'address': booking.room_id.name, + 'remarks': booking.meeting_data or '', + 'users_ids': [(6, 0, booking.room_users_ids.ids)] if booking.room_users_ids else [(5, 0, 0)], + 'self_users_ids': [(6, 0, booking.self_users_ids.ids)] if booking.self_users_ids else [(5, 0, 0)], + }) + return booking + # ------------------------------------------------------ # CRUD / ORM # ------------------------------------------------------ From 630e7eecac74a71b6e938223bbd5b7c56d6756f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Mon, 9 Mar 2026 18:22:06 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E4=BC=9A=E8=AE=AE=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=97=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- room/models/room_booking.py | 58 +++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/room/models/room_booking.py b/room/models/room_booking.py index 4701e5d1a..912ef15fe 100644 --- a/room/models/room_booking.py +++ b/room/models/room_booking.py @@ -306,24 +306,52 @@ class RoomBooking(models.Model): @api.model def create(self, vals): """创建会议后同步生成日程""" + import logging + _logger = logging.getLogger(__name__) + booking = super(RoomBooking, self).create(vals) # 同步生成yuthon.will.task记录 if booking: - # 提取参会人员(从room_users_ids转换为hr.employee) - employee_records = self.env['hr.employee'].search([('user_id', 'in', booking.room_users_ids.ids)]) - # 创建日程记录 - self.env['yuthon.will.task'].create({ - 'name': booking.name, - 'start_date': booking.start_datetime.date(), - 'task_type': 'meet', - 'room_booking_id': booking.id, - 'employee_ids': [(6, 0, employee_records.ids)] if employee_records else [(5, 0, 0)], - 'task_state': 'will', - 'address': booking.room_id.name, - 'remarks': booking.meeting_data or '', - 'users_ids': [(6, 0, booking.room_users_ids.ids)] if booking.room_users_ids else [(5, 0, 0)], - 'self_users_ids': [(6, 0, booking.self_users_ids.ids)] if booking.self_users_ids else [(5, 0, 0)], - }) + try: + # 处理所有可能为空的字段 + if not booking.start_datetime: + _logger.error('会议开始时间为空,无法创建日程') + return booking + + # 提取参会人员(从room_users_ids转换为hr.employee) + employee_records = self.env['hr.employee'].search([('user_id', 'in', booking.room_users_ids.ids)]) if booking.room_users_ids else self.env['hr.employee'] + + # 确保name字段有值 + task_name = booking.name or f'会议_{booking.start_datetime.date()}' + + # 确保room_id有值 + address = booking.room_id.name if booking.room_id else '' + + # 确保meeting_data有值 + remarks = booking.meeting_data or '' + + # 确保room_users_ids有值 + room_users_ids = booking.room_users_ids.ids if booking.room_users_ids else [] + + # 确保self_users_ids有值 + self_users_ids = booking.self_users_ids.ids if booking.self_users_ids else [] + + # 创建日程记录 + task = self.env['yuthon.will.task'].create({ + 'name': task_name, + 'start_date': booking.start_datetime.date(), + 'task_type': 'meet', + 'room_booking_id': booking.id, + 'employee_ids': [(6, 0, employee_records.ids)] if employee_records else [(5, 0, 0)], + 'task_state': 'will', + 'address': address, + 'remarks': remarks, + 'users_ids': [(6, 0, room_users_ids)] if room_users_ids else [(5, 0, 0)], + 'self_users_ids': [(6, 0, self_users_ids)] if self_users_ids else [(5, 0, 0)], + }) + _logger.info('日程创建成功,ID: %s, 会议ID: %s', task.id, booking.id) + except Exception as e: + _logger.error('创建日程失败: %s', str(e)) return booking # ------------------------------------------------------ From 6d94650475a322dab598c2d4dfacc33191764b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= <9664676+pengyuthon@user.noreply.gitee.com> Date: Mon, 9 Mar 2026 18:34:58 +0800 Subject: [PATCH 4/6] =?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_hr_attendance/models/yuthon_shift_approval.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yuthon_hr_attendance/models/yuthon_shift_approval.py b/yuthon_hr_attendance/models/yuthon_shift_approval.py index ede47b299..e54ac70e3 100644 --- a/yuthon_hr_attendance/models/yuthon_shift_approval.py +++ b/yuthon_hr_attendance/models/yuthon_shift_approval.py @@ -111,11 +111,12 @@ class YuthonShiftApproval(models.Model): def _get_slot(self, resource_id, date): if not resource_id or not date: return False - return self.env['planning.slot'].search([ + slot = self.env['planning.slot'].search([ ('resource_id', '=', resource_id), ('start_datetime', '>=', f"{date} 00:00:00"), ('end_datetime', '<=', f"{date} 23:59:59") ], limit=1) + return slot @api.onchange('is_issues') def _onchange_is_issues(self): From 144ad1e420a4a884ec6468569c11dfa8141d6686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= <9664676+pengyuthon@user.noreply.gitee.com> Date: Mon, 9 Mar 2026 18:35:10 +0800 Subject: [PATCH 5/6] =?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 --- .../controllers/applet_attendance.py | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/yuthon_hr_attendance/controllers/applet_attendance.py b/yuthon_hr_attendance/controllers/applet_attendance.py index dd8b73067..d43a24ea7 100644 --- a/yuthon_hr_attendance/controllers/applet_attendance.py +++ b/yuthon_hr_attendance/controllers/applet_attendance.py @@ -941,8 +941,7 @@ class AppletAttendance(Controller): # 电表数据 electric_result_dict = {} - - # 处理电表 + duplicate_checker = {} # 用于记录已处理的 (code, building, floor, room) 组合 for electric in electric_records: property_infos = electric.yuthon_property_ids if electric.yuthon_property_ids else [None] for property_info in property_infos: @@ -959,28 +958,38 @@ class AppletAttendance(Controller): room = '' address = '' employee_name = '' - state = electric.state - electric_value = { - 'id': electric.id, - 'current_read': electric.current_read, - 'code': electric.archives_id.name or '', - 'last_dosage': electric.last_dosage or 0, - 'mater_data': str(electric.meter_date) if electric.meter_date else '', - 'last_mater_data': str(electric.last_meter) if electric.last_meter else '', - 'meter_type': 'electric', - 'employee_name': employee_name, - 'address': address, - 'building': '天河商贸大厦', - 'floor': floor, - 'room': room, - 'epitope_values': electric.epitope_values_id.name, - 'unit_number': electric.unit_number, - 'state': electric.state, # 状态 reading unreading - 'last_read': electric.last_read, - } - electric_result_dict.setdefault(state, {}).setdefault(building, {}).setdefault(floor, []).append( - electric_value) + state = electric.state + code = electric.archives_id.name or '' + # 构建唯一标识键(核心去重逻辑) + unique_key = (code, building, floor, room) + # 检查是否已处理过该唯一键,未处理过才添加 + if unique_key not in duplicate_checker: + # 标记为已处理 + duplicate_checker[unique_key] = True + electric_value = { + 'id': electric.id, + 'current_read': electric.current_read, + 'code': code, + 'last_dosage': electric.last_dosage or 0, + 'mater_data': str(electric.meter_date) if electric.meter_date else '', + 'last_mater_data': str(electric.last_meter) if electric.last_meter else '', + 'meter_type': 'electric', + 'employee_name': employee_name, + 'address': address, + 'building': building, + 'floor': floor, + 'room': room, + 'epitope_values': electric.epitope_values_id.name if electric.epitope_values_id else '', + 'unit_number': electric.unit_number, + 'state': state, + 'last_read': electric.last_read, + } + + # 按层级添加到结果字典 + electric_result_dict.setdefault(state, {}) \ + .setdefault(building, {}) \ + .setdefault(floor, []).append(electric_value) electric_result = [] for state, building_dict in electric_result_dict.items(): From 6b3985a6a1f2b0f8902c052f39d6fab6f7b1f951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= <9664676+pengyuthon@user.noreply.gitee.com> Date: Mon, 9 Mar 2026 18:41:16 +0800 Subject: [PATCH 6/6] =?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_hr_attendance/controllers/applet_attendance.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yuthon_hr_attendance/controllers/applet_attendance.py b/yuthon_hr_attendance/controllers/applet_attendance.py index d43a24ea7..08bfde929 100644 --- a/yuthon_hr_attendance/controllers/applet_attendance.py +++ b/yuthon_hr_attendance/controllers/applet_attendance.py @@ -941,7 +941,7 @@ class AppletAttendance(Controller): # 电表数据 electric_result_dict = {} - duplicate_checker = {} # 用于记录已处理的 (code, building, floor, room) 组合 + duplicate_checker = {} # 用于记录已处理的 (code, unit_number) 组合 for electric in electric_records: property_infos = electric.yuthon_property_ids if electric.yuthon_property_ids else [None] for property_info in property_infos: @@ -961,8 +961,9 @@ class AppletAttendance(Controller): state = electric.state code = electric.archives_id.name or '' + unit_number = electric.unit_number or '' # 构建唯一标识键(核心去重逻辑) - unique_key = (code, building, floor, room) + unique_key = (code, unit_number) # 检查是否已处理过该唯一键,未处理过才添加 if unique_key not in duplicate_checker: # 标记为已处理