diff --git a/backend/app/services/employee_sync_service.py b/backend/app/services/employee_sync_service.py index 0c04336..906ae4d 100644 --- a/backend/app/services/employee_sync_service.py +++ b/backend/app/services/employee_sync_service.py @@ -333,6 +333,7 @@ class EmployeeSyncService: 'users_created': 0, 'users_existing': 0, 'users_restored': 0, + 'users_departed': 0, 'users_skipped': 0, 'teams_created': 0, 'positions_created': 0, @@ -408,7 +409,29 @@ class EmployeeSyncService: stats['errors'].append(error_msg) continue - # 3. 提交所有更改 + # 3. 处理离职员工(软删除) + dingtalk_phones = {emp.get('phone') for emp in employees if emp.get('phone')} + + # 获取系统中所有活跃用户(排除 admin) + stmt = select(User).where( + User.is_deleted == False, + User.is_active == True, + User.username != 'admin', + User.role != 'admin' + ) + result = await self.db.execute(stmt) + system_users = result.scalars().all() + + # 找出离职员工(系统有但钉钉没有) + for user in system_users: + if user.phone and user.phone not in dingtalk_phones: + # 软删除:标记为离职 + user.is_active = False + user.is_deleted = True + stats['users_departed'] += 1 + logger.info(f"🚪 标记离职员工: {user.full_name} ({user.phone})") + + # 4. 提交所有更改 await self.db.commit() logger.info("✅ 数据库事务已提交") @@ -422,14 +445,15 @@ class EmployeeSyncService: stats['end_time'] = datetime.now() stats['duration'] = (stats['end_time'] - stats['start_time']).total_seconds() - # 4. 输出统计信息 + # 5. 输出统计信息 logger.info("=" * 60) logger.info("同步完成统计") logger.info("=" * 60) - logger.info(f"总员工数: {stats['total_employees']}") + logger.info(f"钉钉在职员工: {stats['total_employees']}") logger.info(f"新增用户: {stats['users_created']}") logger.info(f"已存在用户: {stats['users_existing']}") logger.info(f"恢复用户: {stats['users_restored']}") + logger.info(f"离职处理: {stats['users_departed']}") logger.info(f"跳过用户: {stats['users_skipped']}") logger.info(f"耗时: {stats['duration']:.2f}秒") @@ -696,53 +720,36 @@ class EmployeeSyncService: stats['errors'].append(error_msg) continue - # 5. 删除离职员工(物理删除) - # 先flush之前的新增操作,避免与删除操作冲突 + # 5. 处理离职员工(软删除) + # 先flush之前的新增操作 await self.db.flush() - # 收集需要删除的用户ID - users_to_delete = [] + # 标记离职员工 for user in system_users: if user.phone and user.phone in phones_to_delete: # 双重保护:确保不删除admin if user.username == 'admin' or user.role == 'admin': - logger.warning(f"⚠️ 跳过删除管理员账户: {user.username}") + logger.warning(f"⚠️ 跳过处理管理员账户: {user.username}") continue - users_to_delete.append({ - 'id': user.id, - 'full_name': user.full_name, - 'phone': user.phone, - 'username': user.username - }) - - # 批量删除用户及其关联数据 - for user_info in users_to_delete: - try: - user_id = user_info['id'] - - # 先清理关联数据(外键约束) - await self._cleanup_user_related_data(user_id) - - # 用SQL直接删除用户(避免ORM的级联操作冲突) - await self.db.execute( - text("DELETE FROM users WHERE id = :user_id"), - {"user_id": user_id} - ) - - stats['deleted_users'].append({ - 'full_name': user_info['full_name'], - 'phone': user_info['phone'], - 'username': user_info['username'] - }) - stats['deleted_count'] += 1 - logger.info(f"🗑️ 删除离职员工: {user_info['full_name']} ({user_info['phone']})") - - except Exception as e: - error_msg = f"删除员工 {user_info['full_name']} 失败: {str(e)}" - logger.error(error_msg) - stats['errors'].append(error_msg) - continue + try: + # 软删除:标记为离职 + user.is_active = False + user.is_deleted = True + + stats['deleted_users'].append({ + 'full_name': user.full_name, + 'phone': user.phone, + 'username': user.username + }) + stats['deleted_count'] += 1 + logger.info(f"🚪 标记离职员工: {user.full_name} ({user.phone})") + + except Exception as e: + error_msg = f"处理离职员工 {user.full_name} 失败: {str(e)}" + logger.error(error_msg) + stats['errors'].append(error_msg) + continue # 6. 提交所有更改 await self.db.commit() @@ -763,7 +770,7 @@ class EmployeeSyncService: logger.info("增量同步完成统计") logger.info("=" * 60) logger.info(f"新增员工: {stats['added_count']}") - logger.info(f"删除员工: {stats['deleted_count']}") + logger.info(f"离职处理: {stats['deleted_count']}") logger.info(f"跳过员工: {stats['skipped_count']}") logger.info(f"耗时: {stats['duration']:.2f}秒") diff --git a/frontend/src/views/admin/system-settings.vue b/frontend/src/views/admin/system-settings.vue index d01795a..ab4132b 100644 --- a/frontend/src/views/admin/system-settings.vue +++ b/frontend/src/views/admin/system-settings.vue @@ -348,12 +348,14 @@ const triggerSync = async () => { const created = data.users_created || 0 const existing = data.users_existing || 0 const restored = data.users_restored || 0 + const departed = data.users_departed || 0 const skipped = data.users_skipped || 0 - let msg = `同步完成!共处理 ${data.total_employees || 0} 名员工` + let msg = `同步完成!钉钉在职 ${data.total_employees || 0} 人` if (created > 0) msg += `,新增 ${created} 人` if (existing > 0) msg += `,已存在 ${existing} 人` if (restored > 0) msg += `,恢复 ${restored} 人` + if (departed > 0) msg += `,离职 ${departed} 人` if (skipped > 0) msg += `,跳过 ${skipped} 人` ElMessage.success(msg)