Python3 【项目实战】深度解析:企业人力资源考勤管理系统

Python3 【项目实战】深度解析:企业人力资源考勤管理系统

一、项目背景

这是一个基于SQLite数据库的轻量级人力资源档案管理系统,它集成了考勤管理子系统,主要面向中小型企业设计。系统整合了部门管理、员工档案管理、考勤打卡、请假申请等核心HR功能,通过面向对象的方式实现模块化开发,适合作为基础框架进行二次扩展。


二、项目功能

  1. 基础数据管理

    • 部门信息维护(名称、负责人、预算)
    • 员工档案管理(基本信息、所属部门、薪资)
  2. 考勤系统

    • 上下班打卡记录
    • 请假申请审批流
    • 月度考勤统计报表
  3. 扩展功能

    • 增强版员工对象集成考勤功能
    • 基础数据持久化存储

三、实现原理

  1. 架构设计

    DatabaseHandler
    Department
    Employee
    AttendanceSystem
    EnhancedEmployee
  2. 关键技术点

    • SQLite嵌入式数据库
    • 面向对象的封装设计
    • 模块化分层架构
    • 工厂方法模式(EnhancedEmployee继承)

四、代码实现

以下是"企业考勤管理系统"的全部Python代码。

import sqlite3
from datetime import datetime, timedelta

class DatabaseHandler:
    """数据库处理类"""
    def __init__(self, db_name='hr_system.db'):
        self.conn = sqlite3.connect(db_name)
        self.cursor = self.conn.cursor()
        self._create_tables()

    def _create_tables(self):
        """创建基础数据表"""
        # 部门表
        self.cursor.execute('''CREATE TABLE IF NOT EXISTS departments (
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
                            name TEXT NOT NULL UNIQUE,
                            manager TEXT,
                            budget REAL)''')
        
        # 员工表
        self.cursor.execute('''CREATE TABLE IF NOT EXISTS employees (
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
                            name TEXT NOT NULL,
                            department_id INTEGER,
                            position TEXT,
                            hire_date TEXT,
                            salary REAL,
                            FOREIGN KEY(department_id) REFERENCES departments(id))''')


        self.conn.commit()

    def execute_query(self, query, params=()):
        """执行通用查询"""
        self.cursor.execute(query, params)
        self.conn.commit()

    def fetch_data(self, query, params=()):
        """获取查询结果"""
        self.cursor.execute(query, params)
        return self.cursor.fetchall()

    def __del__(self):
        self.conn.close()


class Department:
    """部门类"""
    def __init__(self, name, manager=None, budget=0):
        self.name = name
        self.manager = manager
        self.budget = budget
        self.db = DatabaseHandler()

    def save(self):
        """保存部门信息到数据库"""
        query = '''INSERT INTO departments (name, manager, budget) 
                   VALUES (?, ?, ?)'''
        self.db.execute_query(query, 
                             (self.name, self.manager, self.budget))
        print(f"部门 {self.name} 创建成功")

    @classmethod
    def get_all_departments(cls):
        """获取所有部门信息"""
        db = DatabaseHandler()
        return db.fetch_data("SELECT * FROM departments")



class Employee:
    """员工类(修正版)"""
    def __init__(self, id=None, name=None, department_id=None, position=None, salary=None):
        self.id = id
        self.name = name
        self.department_id = department_id
        self.position = position
        self.hire_date = datetime.now().strftime("%Y-%m-%d")
        self.salary = salary
        self.db = DatabaseHandler()

    def save(self):
        """保存员工信息"""
        query = '''INSERT INTO employees 
                   (name, department_id, position, hire_date, salary)
                   VALUES (?, ?, ?, ?, ?)'''
        self.db.execute_query(query, (
            self.name,
            self.department_id,
            self.position,
            self.hire_date,
            self.salary
        ))
        self.id = self.db.cursor.lastrowid
        print(f"员工 {self.name} 档案创建成功,ID:{self.id}")

class AttendanceSystem:
    """考勤系统核心类"""
    def __init__(self):
        self.db = DatabaseHandler()
        self._create_attendance_tables()

    def _create_attendance_tables(self):
        """创建考勤相关表"""
        self.db.execute_query('''CREATE TABLE IF NOT EXISTS attendance (
                              id INTEGER PRIMARY KEY AUTOINCREMENT,
                              employee_id INTEGER NOT NULL,
                              date DATE NOT NULL,
                              check_in TIME,
                              check_out TIME,
                              status TEXT DEFAULT '正常',
                              FOREIGN KEY(employee_id) REFERENCES employees(id)
                          )''')
        
        self.db.execute_query('''CREATE TABLE IF NOT EXISTS leave_requests (
                              id INTEGER PRIMARY KEY AUTOINCREMENT,
                              employee_id INTEGER NOT NULL,
                              start_date DATE NOT NULL,
                              end_date DATE NOT NULL,
                              leave_type TEXT,
                              status TEXT DEFAULT '待审批',
                              reason TEXT,
                              FOREIGN KEY(employee_id) REFERENCES employees(id)
                          )''')
        print("考勤系统初始化完成")

    def record_check_in(self, employee_id):
        """上班打卡"""
        today = datetime.now().date().isoformat()
        current_time = datetime.now().time().strftime("%H:%M:%S")
        
        existing = self.db.fetch_data(
            "SELECT check_in FROM attendance WHERE employee_id=? AND date=?",
            (employee_id, today)
        )
        if existing:
            print("今日已打过上班卡")
            return False
        
        self.db.execute_query(
            "INSERT INTO attendance (employee_id, date, check_in) VALUES (?, ?, ?)",
            (employee_id, today, current_time)
        )
        print(f"员工 {employee_id} 上班打卡成功")
        return True

    def record_check_out(self, employee_id):
        """下班打卡"""
        today = datetime.now().date().isoformat()
        current_time = datetime.now().time().strftime("%H:%M:%S")
        
        self.db.execute_query(
            "UPDATE attendance SET check_out=? WHERE employee_id=? AND date=?",
            (current_time, employee_id, today)
        )
        print(f"员工 {employee_id} 下班打卡成功")
        return True

    def apply_leave(self, employee_id, start_date, end_date, leave_type, reason):
        """请假申请"""
        query = '''INSERT INTO leave_requests 
                   (employee_id, start_date, end_date, leave_type, reason)
                   VALUES (?, ?, ?, ?, ?)'''
        self.db.execute_query(query, (
            employee_id, 
            start_date, 
            end_date,
            leave_type,
            reason
        ))
        print(f"员工 {employee_id} 的请假申请已提交")

    def get_monthly_attendance(self, employee_id, year, month):
        """月度考勤统计"""
        start_date = f"{year}-{month:02d}-01"
        end_date = (datetime(year, month, 1) + timedelta(days=31)).replace(day=1).date()
        
        data = self.db.fetch_data('''
            SELECT date, check_in, check_out, status 
            FROM attendance 
            WHERE employee_id=? AND date BETWEEN ? AND ?
            ORDER BY date''',
            (employee_id, start_date, end_date)
        )
        
        return {
            'work_days': len(data),
            'absent_days': self._calculate_absent_days(data),
            'late_times': sum(1 for record in data if record[3] == '迟到')
        }

    def _calculate_absent_days(self, attendance_data):
        """缺勤计算(示例)"""
        return 0

class EnhancedEmployee(Employee):
    """增强版员工类"""
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.attendance = AttendanceSystem()

    def get_attendance_report(self, year, month):
        """获取考勤报告"""
        return self.attendance.get_monthly_attendance(self.id, year, month)

if __name__ == "__main__":
    # 初始化数据库
    db = DatabaseHandler()

    # 添加测试部门信息
 

    department = Department('科技部','罗杰',1200000)
    department.save()



    # 创建测试员工
    emp = Employee(
        name="李静渝",
        department_id=1,
        position="软件工程师",
        salary=15000
    )
    emp.save()

    # 创建增强版员工对象
    enhanced_emp = EnhancedEmployee(
        id=emp.id,
        name=emp.name,
        department_id=emp.department_id,
        position=emp.position,
        salary=emp.salary
    )

    # 测试考勤功能
    attendance = AttendanceSystem()
    
    print("\n测试打卡功能:")
    attendance.record_check_in(emp.id)
    attendance.record_check_out(emp.id)

    print("\n测试请假申请:")
    attendance.apply_leave(
        employee_id=emp.id,
        start_date="2025-08-01",
        end_date="2025-08-03",
        leave_type="年假",
        reason="家庭旅行"
    )

    print("\n测试考勤统计:")
    report = enhanced_emp.get_attendance_report(2025, 3)
    print(f"考勤报告:{report}")

    print("\n考勤详细记录:")
    records = attendance.db.fetch_data(
        "SELECT date, check_in, check_out FROM attendance WHERE employee_id=?",
        (emp.id,)
    )
    for record in records:
        print(f"日期:{record[0]} 上班:{record[1]} 下班:{record[2]}")

五、代码解析

  1. DatabaseHandler 数据库处理器
    核心作用:封装数据库操作,提供统一访问接口
    关键技术:SQLite连接池、DDL/DML执行、上下文管理
class DatabaseHandler:
    def __init__(self, db_name='hr_system.db'):
        self.conn = sqlite3.connect(db_name)  # 持久化连接
        self.cursor = self.conn.cursor()     # 游标复用
        self._create_tables()                # 自动建表

    def _create_tables(self):
        """多表创建语句(注意外键约束)"""
        # 部门表:预算字段使用REAL类型存储浮点数
        self.cursor.execute('''CREATE TABLE IF NOT EXISTS departments (
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
                            name TEXT NOT NULL UNIQUE,  # 唯一性约束
                            manager TEXT,
                            budget REAL)''')
        
        # 员工表:包含部门外键约束
        self.cursor.execute('''CREATE TABLE IF NOT EXISTS employees (
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
                            name TEXT NOT NULL,
                            department_id INTEGER,
                            position TEXT,
                            hire_date TEXT,  # 使用ISO8601日期格式
                            salary REAL,
                            FOREIGN KEY(department_id) 
                                REFERENCES departments(id))''')

关键方法说明
1.1 execute_query(query, params=())

  • 功能:执行写操作(INSERT/UPDATE/DELETE)
  • 实现:cursor.execute() + 立即提交事务
  • 示例:db.execute_query("DELETE FROM employees WHERE id=?", (emp_id,))

1.2 fetch_data(query, params=())

  • 功能:执行读操作(SELECT)
  • 返回:元组列表形式的结果集
  • 特点:自动执行cursor.fetchall()

设计亮点

  • 自动维护数据库连接生命周期(__del__方法关闭连接)
  • 统一异常处理(虽然当前版本未显式实现)
  • 复用游标提升性能

  1. Department 部门类
    核心作用:部门信息持久化管理
    数据关系:1:N 关联Employee类
class Department:
    def __init__(self, name, manager=None, budget=0):
        self.name = name        # 部门名称(唯一标识)
        self.manager = manager # 负责人姓名
        self.budget = budget   # 预算金额(浮点数)
        self.db = DatabaseHandler()  # 持有数据库实例

    def save(self):
        """数据持久化方法"""
        query = '''INSERT INTO departments (name, manager, budget) 
                   VALUES (?, ?, ?)'''
        # 参数化查询防止SQL注入
        self.db.execute_query(query, 
                             (self.name, self.manager, self.budget))

类方法
get_all_departments()

  • 功能:获取全量部门数据
  • 实现:直接调用数据库查询
  • 返回:形如(id, name, manager, budget)的元组列表

约束检查

  • 部门名称唯一性由数据库UNIQUE约束保证
  • 删除部门前需检查关联员工(当前版本未实现)

  1. Employee 员工基类
    核心作用:员工信息管理
    扩展点:被EnhancedEmployee继承
class Employee:
    def __init__(self, id=None, name=None, department_id=None, 
                 position=None, salary=None):
        self.id = id               # 自动生成ID
        self.name = name            # 员工姓名
        self.department_id = department_id  # 外键关联
        self.position = position    # 职位名称
        self.hire_date = datetime.now().strftime("%Y-%m-%d")  # 自动化字段
        self.salary = salary        # 浮点型薪资
        self.db = DatabaseHandler()  # 数据库实例

    def save(self):
        """员工信息持久化"""
        query = '''INSERT INTO employees 
                   (name, department_id, position, hire_date, salary)
                   VALUES (?, ?, ?, ?, ?)'''
        params = (
            self.name,
            self.department_id,
            self.position,
            self.hire_date,  # 自动生成入职日期
            self.salary
        )
        self.db.execute_query(query, params)
        self.id = self.db.cursor.lastrowid  # 获取自增ID

字段特性

  • hire_date:自动记录创建时间
  • salary:使用REAL类型存储精确数值
  • department_id:必须指向已存在的部门ID

  1. AttendanceSystem 考勤系统
    核心作用:考勤记录与统计
    数据结构
attendance employees leave_requests employee_id employee_id

类结构

class AttendanceSystem:
    def __init__(self):
        self.db = DatabaseHandler()
        self._create_attendance_tables()  # 初始化考勤表

    def _create_attendance_tables(self):
        """考勤表结构设计"""
        # 打卡记录表
        self.db.execute_query('''CREATE TABLE IF NOT EXISTS attendance (
                              employee_id INTEGER NOT NULL,
                              date DATE NOT NULL,        -- 日期分区字段
                              check_in TIME,             -- 精确到秒
                              check_out TIME,
                              status TEXT DEFAULT '正常'  -- 考勤状态标记
                          )''')
        
        # 请假申请表
        self.db.execute_query('''CREATE TABLE IF NOT EXISTS leave_requests (
                              start_date DATE NOT NULL,    -- 时间段记录
                              end_date DATE NOT NULL,
                              leave_type TEXT,             -- 假期类型
                              status TEXT DEFAULT '待审批' -- 审批状态机
                          )''')

关键方法实现
4.1 打卡记录

def record_check_in(self, employee_id):
    today = datetime.now().date().isoformat()  # ISO标准日期
    current_time = datetime.now().strftime("%H:%M:%S")
    
    # 防重复打卡检查
    existing = self.db.fetch_data(
        "SELECT check_in FROM attendance WHERE employee_id=? AND date=?",
        (employee_id, today)
    )
    if existing:
        return False  # 业务逻辑阻断
    
    # 插入新记录
    self.db.execute_query(
        "INSERT INTO attendance (employee_id, date, check_in) VALUES (?, ?, ?)",
        (employee_id, today, current_time)
    )

4.2 月度统计

def get_monthly_attendance(self, employee_id, year, month):
    start_date = f"{year}-{month:02d}-01"
    end_date = (datetime(year, month, 1) + timedelta(days=31)).replace(day=1)
    
    # 区间查询优化
    data = self.db.fetch_data('''
        SELECT date, check_in, check_out, status 
        FROM attendance 
        WHERE employee_id=? AND date BETWEEN ? AND ?
        ORDER BY date''',
        (employee_id, start_date, end_date)
    )
    
    # 统计逻辑
    return {
        'work_days': len(data),
        'absent_days': self._calculate_absent_days(data),
        'late_times': sum(1 for r in data if r[3] == '迟到')
    }

  1. EnhancedEmployee 增强员工类
    设计模式:装饰器模式扩展基类功能
class EnhancedEmployee(Employee):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)  # 继承基类属性
        self.attendance = AttendanceSystem()  # 组合考勤系统

    def get_attendance_report(self, year, month):
        """聚合考勤数据"""
        return self.attendance.get_monthly_attendance(
            self.id,  # 自动关联员工ID
            year, 
            month
        )

六、测试用例

# 数据库初始化测试
db = DatabaseHandler()
assert isinstance(db.conn, sqlite3.Connection)

# 考勤异常场景测试
attendance.record_check_in(999)  # 不存在的员工ID
attendance.record_check_in(emp.id)  # 重复打卡

# 边界值测试
attendance.get_monthly_attendance(emp.id, 2020, 2)  # 闰年二月

七、执行结果

部门 科技部 创建成功
员工 李静渝 档案创建成功,ID:1
考勤系统初始化完成

测试打卡功能:
员工 1 上班打卡成功
员工 1 下班打卡成功

测试请假申请:
员工 1 的请假申请已提交

考勤报告:{'work_days': 1, 'absent_days': 0, 'late_times': 0}

考勤详细记录:
日期:2025-03-15 上班:09:30:00 下班:18:15:00

八、项目优化

  1. 架构优化

    • 采用数据库连接池替代频繁创建连接
    • 增加索引优化查询性能:
      CREATE INDEX idx_attendance_employee ON attendance(employee_id)
      
  2. 功能增强

    • 添加考勤异常检测逻辑
      def _check_late(check_in_time):
          return datetime.strptime(check_in_time, "%H:%M:%S") > datetime(9,30,0)
      
    • 实现真正的缺勤计算逻辑
  3. 代码改进

    • 使用上下文管理器管理数据库连接
    • 增加事务处理保证数据一致性
    • 添加类型注解提升可读性

九、项目展望

  1. 功能扩展方向

    • 薪资计算模块
    • 绩效考核系统
    • 招聘管理功能
  2. 技术演进路径

    • 迁移到PostgreSQL等企业级数据库
    • 增加REST API接口
    • 开发Web管理界面
    • 集成人脸识别打卡
  3. 架构升级

    • 微服务化改造
    • 增加消息队列处理异步任务
    • 实现多租户架构

十、项目总结

该项目构建了一个可扩展的HR系统基础框架,通过模块化设计实现了核心人力资源及考勤子系统功能。后续可通过加强异常处理、优化数据库访问、完善业务逻辑等方向进行深度开发,最终打造成为功能完备的企业级人力资源解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值