Python3 【项目实战】深度解析:企业人力资源考勤管理系统
一、项目背景
这是一个基于SQLite数据库的轻量级人力资源档案管理系统,它集成了考勤管理子系统,主要面向中小型企业设计。系统整合了部门管理、员工档案管理、考勤打卡、请假申请等核心HR功能,通过面向对象的方式实现模块化开发,适合作为基础框架进行二次扩展。
二、项目功能
-
基础数据管理
- 部门信息维护(名称、负责人、预算)
- 员工档案管理(基本信息、所属部门、薪资)
-
考勤系统
- 上下班打卡记录
- 请假申请审批流
- 月度考勤统计报表
-
扩展功能
- 增强版员工对象集成考勤功能
- 基础数据持久化存储
三、实现原理
-
架构设计
-
关键技术点
- 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]}")
五、代码解析
- 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__
方法关闭连接) - 统一异常处理(虽然当前版本未显式实现)
- 复用游标提升性能
- 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约束保证
- 删除部门前需检查关联员工(当前版本未实现)
- 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
- AttendanceSystem 考勤系统
核心作用:考勤记录与统计
数据结构:
类结构:
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] == '迟到')
}
- 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
八、项目优化
-
架构优化
- 采用数据库连接池替代频繁创建连接
- 增加索引优化查询性能:
CREATE INDEX idx_attendance_employee ON attendance(employee_id)
-
功能增强
- 添加考勤异常检测逻辑
def _check_late(check_in_time): return datetime.strptime(check_in_time, "%H:%M:%S") > datetime(9,30,0)
- 实现真正的缺勤计算逻辑
- 添加考勤异常检测逻辑
-
代码改进
- 使用上下文管理器管理数据库连接
- 增加事务处理保证数据一致性
- 添加类型注解提升可读性
九、项目展望
-
功能扩展方向
- 薪资计算模块
- 绩效考核系统
- 招聘管理功能
-
技术演进路径
- 迁移到PostgreSQL等企业级数据库
- 增加REST API接口
- 开发Web管理界面
- 集成人脸识别打卡
-
架构升级
- 微服务化改造
- 增加消息队列处理异步任务
- 实现多租户架构
十、项目总结
该项目构建了一个可扩展的HR系统基础框架,通过模块化设计实现了核心人力资源及考勤子系统功能。后续可通过加强异常处理、优化数据库访问、完善业务逻辑等方向进行深度开发,最终打造成为功能完备的企业级人力资源解决方案。