import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
from datetime import datetime
from openpyxl import Workbook
class AdvancedHRMS:
def __init__(self, root):
self.root = root
self.root.title("نظام إدارة الموارد البشرية المتقدم")
self.root.geometry("1400x900")
self.create_database()
self.create_widgets()
self.load_initial_data()
self.current_emp_id = None
def create_database(self):
self.conn = sqlite3.connect('advanced_hrms.db')
self.cursor = self.conn.cursor()
tables = [
'''CREATE TABLE IF NOT EXISTS employees (
id TEXT PRIMARY KEY,
name TEXT,
dob TEXT,
nationality TEXT,
hire_date TEXT,
department TEXT,
salary REAL)''',
'''CREATE TABLE IF NOT EXISTS attendance (
id INTEGER PRIMARY KEY AUTOINCREMENT,
emp_id TEXT,
date TEXT,
check_in TEXT,
check_out TEXT)''',
'''CREATE TABLE IF NOT EXISTS salaries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
emp_id TEXT,
month TEXT,
basic REAL,
deductions REAL,
allowances REAL,
net REAL)''',
'''CREATE TABLE IF NOT EXISTS leaves (
id INTEGER PRIMARY KEY AUTOINCREMENT,
emp_id TEXT,
start_date TEXT,
end_date TEXT,
type TEXT,
status TEXT DEFAULT 'معلق')''',
'''CREATE TABLE IF NOT EXISTS performance (
id INTEGER PRIMARY KEY AUTOINCREMENT,
emp_id TEXT,
date TEXT,
productivity REAL,
teamwork REAL,
comments TEXT)'''
]
for table in tables:
self.cursor.execute(table)
self.conn.commit()
def create_widgets(self):
toolbar = ttk.Frame(self.root)
toolbar
.pack(side
='top', fill
='x')
self.emp_selector = ttk.Combobox(toolbar, postcommand=self.update_emp_list)
self.emp_selector
.pack(side
='left', padx
=5, pady
=5) self.emp_selector.bind('<<ComboboxSelected>>', self.select_employee)
ttk
.Button
(toolbar
, text
="تصدير Excel", command
=self.export_to_excel
).pack(side
='right', padx
=5)
self.tab_control = ttk.Notebook(self.root)
self.tab_employees = self.create_employee_tab()
self.tab_control.add(self.tab_employees, text='الموظفين')
self.tab_attendance = self.create_attendance_tab()
self.tab_control.add(self.tab_attendance, text='الحضور')
self.tab_salaries = self.create_salary_tab()
self.tab_control.add(self.tab_salaries, text='الرواتب')
self.tab_leaves = self.create_leave_tab()
self.tab_control.add(self.tab_leaves, text='الإجازات')
self.tab_performance = self.create_performance_tab()
self.tab_control.add(self.tab_performance, text='التقييم')
self.tab_control
.pack(expand
=1, fill
='both')
def create_employee_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the employee tab code - same as before)
return tab
def create_attendance_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the attendance tab code - same as before)
return tab
def create_salary_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the salary tab code - same as before)
return tab
def create_leave_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the leave tab code - same as before)
return tab
def create_performance_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the performance tab code - same as before)
return tab
def export_to_excel(self):
try:
wb = Workbook()
# تصدير الموظفين
ws_emp = wb.active
ws_emp.title = "الموظفين"
ws_emp.append(['الرقم الوظيفي', 'الاسم', 'تاريخ الميلاد', 'الجنسية', 'تاريخ التعيين', 'القسم', 'الراتب']) # Include all columns
employees = self.cursor.execute("SELECT id, name, dob, nationality, hire_date, department, salary FROM employees").fetchall() # Select all columns
for emp in employees:
ws_emp.append(emp)
# تصدير الرواتب
ws_sal = wb.create_sheet("الرواتب")
ws_sal.append(['الشهر', 'الأساسي', 'الخصومات', 'المكافآت', 'الصافي'])
salaries = self.cursor.execute("SELECT month, basic, deductions, allowances, net FROM salaries").fetchall()
for sal in salaries:
ws_sal.append(sal)
# ... (Export other tables - attendance, leaves, performance)
wb.save("hr_export.xlsx")
messagebox.showinfo("نجاح", "تم التصدير إلى hr_export.xlsx")
except Exception as e:
messagebox.showerror("خطأ", f"خطأ في التصدير: {str(e)}")
def update_emp_list(self):
try:
self.emp_selector['values'] = [row[0] for row in self.cursor.execute("SELECT id FROM employees").fetchall()]
except Exception as e:
messagebox.showerror("خطأ", str(e))
def select_employee(self, event):
self.current_emp_id = self.emp_selector.get()
# ... (Load and display details for the selected employee in the appropriate tabs) ...
def load_initial_data(self):
self.update_emp_list() # Load employee list at start
self.refresh_employee_table() # Refresh the employee table
def refresh_employee_table(self):
try:
self.employee_tree.delete(*self.employee_tree.get_children()) # Clear existing data
employees = self.cursor.execute("SELECT id, name, dob, nationality, hire_date, department, salary FROM employees").fetchall()
for employee in employees:
self.employee_tree
.insert
("", tk
.END, values
=employee
) except Exception as e:
messagebox.showerror("Error", str(e))
# ... (Add other data loading/refresh functions for attendance, salaries, etc.)
def add_employee(self):
try:
data = [self.entries[label].get() for label in ['الرقم الوظيفي', 'الاسم', 'تاريخ الميلاد', 'الجنسية', 'تاريخ التعيين', 'القسم', 'الراتب']]
self.cursor.execute("INSERT INTO employees VALUES (?, ?, ?, ?, ?, ?, ?)", data)
self.conn.commit()
self.refresh_employee_table() # Refresh the table after adding
messagebox.showinfo("نجاح", "تمت إضافة الموظف.")
# Clear the entry fields after adding (optional)
for entry in self.entries.values():
except Exception as e:
self.conn.rollback()
messagebox.showerror("خطأ", str(e))
# ... (Implement update_employee, delete_employee, check_in, check_out, calculate_salary, submit_leave, save_performance)
if __name__ == "__main__":
root = tk.Tk()
app = AdvancedHRMS(root)
root.mainloop()
aW1wb3J0IHRraW50ZXIgYXMgdGsKZnJvbSB0a2ludGVyIGltcG9ydCB0dGssIG1lc3NhZ2Vib3gKaW1wb3J0IHNxbGl0ZTMKZnJvbSBkYXRldGltZSBpbXBvcnQgZGF0ZXRpbWUKZnJvbSBvcGVucHl4bCBpbXBvcnQgV29ya2Jvb2sKCmNsYXNzIEFkdmFuY2VkSFJNUzoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCByb290KToKICAgICAgICBzZWxmLnJvb3QgPSByb290CiAgICAgICAgc2VsZi5yb290LnRpdGxlKCLZhti42KfZhSDYpdiv2KfYsdipINin2YTZhdmI2KfYsdivINin2YTYqNi02LHZitipINin2YTZhdiq2YLYr9mFIikKICAgICAgICBzZWxmLnJvb3QuZ2VvbWV0cnkoIjE0MDB4OTAwIikKCiAgICAgICAgc2VsZi5jcmVhdGVfZGF0YWJhc2UoKQogICAgICAgIHNlbGYuY3JlYXRlX3dpZGdldHMoKQogICAgICAgIHNlbGYubG9hZF9pbml0aWFsX2RhdGEoKQoKICAgICAgICBzZWxmLmN1cnJlbnRfZW1wX2lkID0gTm9uZQoKICAgIGRlZiBjcmVhdGVfZGF0YWJhc2Uoc2VsZik6CiAgICAgICAgc2VsZi5jb25uID0gc3FsaXRlMy5jb25uZWN0KCdhZHZhbmNlZF9ocm1zLmRiJykKICAgICAgICBzZWxmLmN1cnNvciA9IHNlbGYuY29ubi5jdXJzb3IoKQoKICAgICAgICB0YWJsZXMgPSBbCiAgICAgICAgICAgICcnJ0NSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIGVtcGxveWVlcyAoCiAgICAgICAgICAgICAgICBpZCBURVhUIFBSSU1BUlkgS0VZLAogICAgICAgICAgICAgICAgbmFtZSBURVhULAogICAgICAgICAgICAgICAgZG9iIFRFWFQsCiAgICAgICAgICAgICAgICBuYXRpb25hbGl0eSBURVhULAogICAgICAgICAgICAgICAgaGlyZV9kYXRlIFRFWFQsCiAgICAgICAgICAgICAgICBkZXBhcnRtZW50IFRFWFQsCiAgICAgICAgICAgICAgICBzYWxhcnkgUkVBTCknJycsCgogICAgICAgICAgICAnJydDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyBhdHRlbmRhbmNlICgKICAgICAgICAgICAgICAgIGlkIElOVEVHRVIgUFJJTUFSWSBLRVkgQVVUT0lOQ1JFTUVOVCwKICAgICAgICAgICAgICAgIGVtcF9pZCBURVhULAogICAgICAgICAgICAgICAgZGF0ZSBURVhULAogICAgICAgICAgICAgICAgY2hlY2tfaW4gVEVYVCwKICAgICAgICAgICAgICAgIGNoZWNrX291dCBURVhUKScnJywKCiAgICAgICAgICAgICcnJ0NSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIHNhbGFyaWVzICgKICAgICAgICAgICAgICAgIGlkIElOVEVHRVIgUFJJTUFSWSBLRVkgQVVUT0lOQ1JFTUVOVCwKICAgICAgICAgICAgICAgIGVtcF9pZCBURVhULAogICAgICAgICAgICAgICAgbW9udGggVEVYVCwKICAgICAgICAgICAgICAgIGJhc2ljIFJFQUwsCiAgICAgICAgICAgICAgICBkZWR1Y3Rpb25zIFJFQUwsCiAgICAgICAgICAgICAgICBhbGxvd2FuY2VzIFJFQUwsCiAgICAgICAgICAgICAgICBuZXQgUkVBTCknJycsCgogICAgICAgICAgICAnJydDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyBsZWF2ZXMgKAogICAgICAgICAgICAgICAgaWQgSU5URUdFUiBQUklNQVJZIEtFWSBBVVRPSU5DUkVNRU5ULAogICAgICAgICAgICAgICAgZW1wX2lkIFRFWFQsCiAgICAgICAgICAgICAgICBzdGFydF9kYXRlIFRFWFQsCiAgICAgICAgICAgICAgICBlbmRfZGF0ZSBURVhULAogICAgICAgICAgICAgICAgdHlwZSBURVhULAogICAgICAgICAgICAgICAgc3RhdHVzIFRFWFQgREVGQVVMVCAn2YXYudmE2YInKScnJywKCiAgICAgICAgICAgICcnJ0NSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIHBlcmZvcm1hbmNlICgKICAgICAgICAgICAgICAgIGlkIElOVEVHRVIgUFJJTUFSWSBLRVkgQVVUT0lOQ1JFTUVOVCwKICAgICAgICAgICAgICAgIGVtcF9pZCBURVhULAogICAgICAgICAgICAgICAgZGF0ZSBURVhULAogICAgICAgICAgICAgICAgcHJvZHVjdGl2aXR5IFJFQUwsCiAgICAgICAgICAgICAgICB0ZWFtd29yayBSRUFMLAogICAgICAgICAgICAgICAgY29tbWVudHMgVEVYVCknJycKICAgICAgICBdCgogICAgICAgIGZvciB0YWJsZSBpbiB0YWJsZXM6CiAgICAgICAgICAgIHNlbGYuY3Vyc29yLmV4ZWN1dGUodGFibGUpCiAgICAgICAgc2VsZi5jb25uLmNvbW1pdCgpCgogICAgZGVmIGNyZWF0ZV93aWRnZXRzKHNlbGYpOgogICAgICAgIHRvb2xiYXIgPSB0dGsuRnJhbWUoc2VsZi5yb290KQogICAgICAgIHRvb2xiYXIucGFjayhzaWRlPSd0b3AnLCBmaWxsPSd4JykKCiAgICAgICAgc2VsZi5lbXBfc2VsZWN0b3IgPSB0dGsuQ29tYm9ib3godG9vbGJhciwgcG9zdGNvbW1hbmQ9c2VsZi51cGRhdGVfZW1wX2xpc3QpCiAgICAgICAgc2VsZi5lbXBfc2VsZWN0b3IucGFjayhzaWRlPSdsZWZ0JywgcGFkeD01LCBwYWR5PTUpCiAgICAgICAgc2VsZi5lbXBfc2VsZWN0b3IuYmluZCgnPDxDb21ib2JveFNlbGVjdGVkPj4nLCBzZWxmLnNlbGVjdF9lbXBsb3llZSkKCiAgICAgICAgdHRrLkJ1dHRvbih0b29sYmFyLCB0ZXh0PSLYqti12K/ZitixIEV4Y2VsIiwgY29tbWFuZD1zZWxmLmV4cG9ydF90b19leGNlbCkucGFjayhzaWRlPSdyaWdodCcsIHBhZHg9NSkKCiAgICAgICAgc2VsZi50YWJfY29udHJvbCA9IHR0ay5Ob3RlYm9vayhzZWxmLnJvb3QpCgogICAgICAgIHNlbGYudGFiX2VtcGxveWVlcyA9IHNlbGYuY3JlYXRlX2VtcGxveWVlX3RhYigpCiAgICAgICAgc2VsZi50YWJfY29udHJvbC5hZGQoc2VsZi50YWJfZW1wbG95ZWVzLCB0ZXh0PSfYp9mE2YXZiNi42YHZitmGJykKCiAgICAgICAgc2VsZi50YWJfYXR0ZW5kYW5jZSA9IHNlbGYuY3JlYXRlX2F0dGVuZGFuY2VfdGFiKCkKICAgICAgICBzZWxmLnRhYl9jb250cm9sLmFkZChzZWxmLnRhYl9hdHRlbmRhbmNlLCB0ZXh0PSfYp9mE2K3YttmI2LEnKQoKICAgICAgICBzZWxmLnRhYl9zYWxhcmllcyA9IHNlbGYuY3JlYXRlX3NhbGFyeV90YWIoKQogICAgICAgIHNlbGYudGFiX2NvbnRyb2wuYWRkKHNlbGYudGFiX3NhbGFyaWVzLCB0ZXh0PSfYp9mE2LHZiNin2KrYqCcpCgogICAgICAgIHNlbGYudGFiX2xlYXZlcyA9IHNlbGYuY3JlYXRlX2xlYXZlX3RhYigpCiAgICAgICAgc2VsZi50YWJfY29udHJvbC5hZGQoc2VsZi50YWJfbGVhdmVzLCB0ZXh0PSfYp9mE2KXYrNin2LLYp9iqJykKCiAgICAgICAgc2VsZi50YWJfcGVyZm9ybWFuY2UgPSBzZWxmLmNyZWF0ZV9wZXJmb3JtYW5jZV90YWIoKQogICAgICAgIHNlbGYudGFiX2NvbnRyb2wuYWRkKHNlbGYudGFiX3BlcmZvcm1hbmNlLCB0ZXh0PSfYp9mE2KrZgtmK2YrZhScpCgogICAgICAgIHNlbGYudGFiX2NvbnRyb2wucGFjayhleHBhbmQ9MSwgZmlsbD0nYm90aCcpCgogICAgZGVmIGNyZWF0ZV9lbXBsb3llZV90YWIoc2VsZik6CiAgICAgICAgdGFiID0gdHRrLkZyYW1lKHNlbGYudGFiX2NvbnRyb2wpCgogICAgICAgICMgLi4uIChSZXN0IG9mIHRoZSBlbXBsb3llZSB0YWIgY29kZSAtIHNhbWUgYXMgYmVmb3JlKQoKICAgICAgICByZXR1cm4gdGFiCgogICAgZGVmIGNyZWF0ZV9hdHRlbmRhbmNlX3RhYihzZWxmKToKICAgICAgICB0YWIgPSB0dGsuRnJhbWUoc2VsZi50YWJfY29udHJvbCkKCiAgICAgICAgIyAuLi4gKFJlc3Qgb2YgdGhlIGF0dGVuZGFuY2UgdGFiIGNvZGUgLSBzYW1lIGFzIGJlZm9yZSkKCiAgICAgICAgcmV0dXJuIHRhYgoKICAgIGRlZiBjcmVhdGVfc2FsYXJ5X3RhYihzZWxmKToKICAgICAgICB0YWIgPSB0dGsuRnJhbWUoc2VsZi50YWJfY29udHJvbCkKCiAgICAgICAgIyAuLi4gKFJlc3Qgb2YgdGhlIHNhbGFyeSB0YWIgY29kZSAtIHNhbWUgYXMgYmVmb3JlKQoKICAgICAgICByZXR1cm4gdGFiCgogICAgZGVmIGNyZWF0ZV9sZWF2ZV90YWIoc2VsZik6CiAgICAgICAgdGFiID0gdHRrLkZyYW1lKHNlbGYudGFiX2NvbnRyb2wpCgogICAgICAgICMgLi4uIChSZXN0IG9mIHRoZSBsZWF2ZSB0YWIgY29kZSAtIHNhbWUgYXMgYmVmb3JlKQoKICAgICAgICByZXR1cm4gdGFiCgogICAgZGVmIGNyZWF0ZV9wZXJmb3JtYW5jZV90YWIoc2VsZik6CiAgICAgICAgdGFiID0gdHRrLkZyYW1lKHNlbGYudGFiX2NvbnRyb2wpCgogICAgICAgICMgLi4uIChSZXN0IG9mIHRoZSBwZXJmb3JtYW5jZSB0YWIgY29kZSAtIHNhbWUgYXMgYmVmb3JlKQoKICAgICAgICByZXR1cm4gdGFiCgoKICAgIGRlZiBleHBvcnRfdG9fZXhjZWwoc2VsZik6CiAgICAgICAgdHJ5OgogICAgICAgICAgICB3YiA9IFdvcmtib29rKCkKCiAgICAgICAgICAgICMg2KrYtdiv2YrYsSDYp9mE2YXZiNi42YHZitmGCiAgICAgICAgICAgIHdzX2VtcCA9IHdiLmFjdGl2ZQogICAgICAgICAgICB3c19lbXAudGl0bGUgPSAi2KfZhNmF2YjYuNmB2YrZhiIKICAgICAgICAgICAgd3NfZW1wLmFwcGVuZChbJ9in2YTYsdmC2YUg2KfZhNmI2LjZitmB2YonLCAn2KfZhNin2LPZhScsICfYqtin2LHZitiuINin2YTZhdmK2YTYp9ivJywgJ9in2YTYrNmG2LPZitipJywgJ9iq2KfYsdmK2K4g2KfZhNiq2LnZitmK2YYnLCAn2KfZhNmC2LPZhScsICfYp9mE2LHYp9iq2KgnXSkgICMgSW5jbHVkZSBhbGwgY29sdW1ucwogICAgICAgICAgICBlbXBsb3llZXMgPSBzZWxmLmN1cnNvci5leGVjdXRlKCJTRUxFQ1QgaWQsIG5hbWUsIGRvYiwgbmF0aW9uYWxpdHksIGhpcmVfZGF0ZSwgZGVwYXJ0bWVudCwgc2FsYXJ5IEZST00gZW1wbG95ZWVzIikuZmV0Y2hhbGwoKSAjIFNlbGVjdCBhbGwgY29sdW1ucwogICAgICAgICAgICBmb3IgZW1wIGluIGVtcGxveWVlczoKICAgICAgICAgICAgICAgIHdzX2VtcC5hcHBlbmQoZW1wKQoKICAgICAgICAgICAgIyDYqti12K/ZitixINin2YTYsdmI2KfYqtioCiAgICAgICAgICAgIHdzX3NhbCA9IHdiLmNyZWF0ZV9zaGVldCgi2KfZhNix2YjYp9iq2KgiKQogICAgICAgICAgICB3c19zYWwuYXBwZW5kKFsn2KfZhNi02YfYsScsICfYp9mE2KPYs9in2LPZiicsICfYp9mE2K7YtdmI2YXYp9iqJywgJ9in2YTZhdmD2KfZgdii2KonLCAn2KfZhNi12KfZgdmKJ10pCiAgICAgICAgICAgIHNhbGFyaWVzID0gc2VsZi5jdXJzb3IuZXhlY3V0ZSgiU0VMRUNUIG1vbnRoLCBiYXNpYywgZGVkdWN0aW9ucywgYWxsb3dhbmNlcywgbmV0IEZST00gc2FsYXJpZXMiKS5mZXRjaGFsbCgpCiAgICAgICAgICAgIGZvciBzYWwgaW4gc2FsYXJpZXM6CiAgICAgICAgICAgICAgICB3c19zYWwuYXBwZW5kKHNhbCkKCiAgICAgICAgICAgICMgLi4uIChFeHBvcnQgb3RoZXIgdGFibGVzIC0gYXR0ZW5kYW5jZSwgbGVhdmVzLCBwZXJmb3JtYW5jZSkKCiAgICAgICAgICAgIHdiLnNhdmUoImhyX2V4cG9ydC54bHN4IikKICAgICAgICAgICAgbWVzc2FnZWJveC5zaG93aW5mbygi2YbYrNin2K0iLCAi2KrZhSDYp9mE2KrYtdiv2YrYsSDYpdmE2YkgaHJfZXhwb3J0Lnhsc3giKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgbWVzc2FnZWJveC5zaG93ZXJyb3IoItiu2LfYoyIsIGYi2K7Yt9ijINmB2Yog2KfZhNiq2LXYr9mK2LE6IHtzdHIoZSl9IikKCiAgICBkZWYgdXBkYXRlX2VtcF9saXN0KHNlbGYpOgogICAgICAgIHRyeToKICAgICAgICAgICAgc2VsZi5lbXBfc2VsZWN0b3JbJ3ZhbHVlcyddID0gW3Jvd1swXSBmb3Igcm93IGluIHNlbGYuY3Vyc29yLmV4ZWN1dGUoIlNFTEVDVCBpZCBGUk9NIGVtcGxveWVlcyIpLmZldGNoYWxsKCldCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICBtZXNzYWdlYm94LnNob3dlcnJvcigi2K7Yt9ijIiwgc3RyKGUpKQoKICAgIGRlZiBzZWxlY3RfZW1wbG95ZWUoc2VsZiwgZXZlbnQpOgogICAgICAgIHNlbGYuY3VycmVudF9lbXBfaWQgPSBzZWxmLmVtcF9zZWxlY3Rvci5nZXQoKQogICAgICAgICMgLi4uIChMb2FkIGFuZCBkaXNwbGF5IGRldGFpbHMgZm9yIHRoZSBzZWxlY3RlZCBlbXBsb3llZSBpbiB0aGUgYXBwcm9wcmlhdGUgdGFicykgLi4uCgogICAgZGVmIGxvYWRfaW5pdGlhbF9kYXRhKHNlbGYpOgogICAgICAgIHNlbGYudXBkYXRlX2VtcF9saXN0KCkgICMgTG9hZCBlbXBsb3llZSBsaXN0IGF0IHN0YXJ0CiAgICAgICAgc2VsZi5yZWZyZXNoX2VtcGxveWVlX3RhYmxlKCkgIyBSZWZyZXNoIHRoZSBlbXBsb3llZSB0YWJsZQoKICAgIGRlZiByZWZyZXNoX2VtcGxveWVlX3RhYmxlKHNlbGYpOgogICAgICAgIHRyeToKICAgICAgICAgICAgc2VsZi5lbXBsb3llZV90cmVlLmRlbGV0ZSgqc2VsZi5lbXBsb3llZV90cmVlLmdldF9jaGlsZHJlbigpKSAgIyBDbGVhciBleGlzdGluZyBkYXRhCiAgICAgICAgICAgIGVtcGxveWVlcyA9IHNlbGYuY3Vyc29yLmV4ZWN1dGUoIlNFTEVDVCBpZCwgbmFtZSwgZG9iLCBuYXRpb25hbGl0eSwgaGlyZV9kYXRlLCBkZXBhcnRtZW50LCBzYWxhcnkgRlJPTSBlbXBsb3llZXMiKS5mZXRjaGFsbCgpCiAgICAgICAgICAgIGZvciBlbXBsb3llZSBpbiBlbXBsb3llZXM6CiAgICAgICAgICAgICAgICBzZWxmLmVtcGxveWVlX3RyZWUuaW5zZXJ0KCIiLCB0ay5FTkQsIHZhbHVlcz1lbXBsb3llZSkKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIG1lc3NhZ2Vib3guc2hvd2Vycm9yKCJFcnJvciIsIHN0cihlKSkKCiAgICAjIC4uLiAoQWRkIG90aGVyIGRhdGEgbG9hZGluZy9yZWZyZXNoIGZ1bmN0aW9ucyBmb3IgYXR0ZW5kYW5jZSwgc2FsYXJpZXMsIGV0Yy4pCgogICAgZGVmIGFkZF9lbXBsb3llZShzZWxmKToKICAgICAgICB0cnk6CiAgICAgICAgICAgIGRhdGEgPSBbc2VsZi5lbnRyaWVzW2xhYmVsXS5nZXQoKSBmb3IgbGFiZWwgaW4gWyfYp9mE2LHZgtmFINin2YTZiNi42YrZgdmKJywgJ9in2YTYp9iz2YUnLCAn2KrYp9ix2YrYriDYp9mE2YXZitmE2KfYrycsICfYp9mE2KzZhtiz2YrYqScsICfYqtin2LHZitiuINin2YTYqti52YrZitmGJywgJ9in2YTZgtiz2YUnLCAn2KfZhNix2KfYqtioJ11dCiAgICAgICAgICAgIHNlbGYuY3Vyc29yLmV4ZWN1dGUoIklOU0VSVCBJTlRPIGVtcGxveWVlcyBWQUxVRVMgKD8sID8sID8sID8sID8sID8sID8pIiwgZGF0YSkKICAgICAgICAgICAgc2VsZi5jb25uLmNvbW1pdCgpCiAgICAgICAgICAgIHNlbGYucmVmcmVzaF9lbXBsb3llZV90YWJsZSgpICAjIFJlZnJlc2ggdGhlIHRhYmxlIGFmdGVyIGFkZGluZwogICAgICAgICAgICBtZXNzYWdlYm94LnNob3dpbmZvKCLZhtis2KfYrSIsICLYqtmF2Kog2KXYttin2YHYqSDYp9mE2YXZiNi42YEuIikKICAgICAgICAgICAgIyBDbGVhciB0aGUgZW50cnkgZmllbGRzIGFmdGVyIGFkZGluZyAob3B0aW9uYWwpCiAgICAgICAgICAgIGZvciBlbnRyeSBpbiBzZWxmLmVudHJpZXMudmFsdWVzKCk6CiAgICAgICAgICAgICAgICBlbnRyeS5kZWxldGUoMCwgdGsuRU5EKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgc2VsZi5jb25uLnJvbGxiYWNrKCkKICAgICAgICAgICAgbWVzc2FnZWJveC5zaG93ZXJyb3IoItiu2LfYoyIsIHN0cihlKSkKCiAgICAjIC4uLiAoSW1wbGVtZW50IHVwZGF0ZV9lbXBsb3llZSwgZGVsZXRlX2VtcGxveWVlLCBjaGVja19pbiwgY2hlY2tfb3V0LCBjYWxjdWxhdGVfc2FsYXJ5LCBzdWJtaXRfbGVhdmUsIHNhdmVfcGVyZm9ybWFuY2UpCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgcm9vdCA9IHRrLlRrKCkKICAgIGFwcCA9IEFkdmFuY2VkSFJNUyhyb290KQogICAgcm9vdC5tYWlubG9vcCgpCgo=
import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
from datetime import datetime
from openpyxl import Workbook
class AdvancedHRMS:
def __init__(self, root):
self.root = root
self.root.title("نظام إدارة الموارد البشرية المتقدم")
self.root.geometry("1400x900")
self.create_database()
self.create_widgets()
self.load_initial_data()
self.current_emp_id = None
def create_database(self):
self.conn = sqlite3.connect('advanced_hrms.db')
self.cursor = self.conn.cursor()
tables = [
'''CREATE TABLE IF NOT EXISTS employees (
id TEXT PRIMARY KEY,
name TEXT,
dob TEXT,
nationality TEXT,
hire_date TEXT,
department TEXT,
salary REAL)''',
'''CREATE TABLE IF NOT EXISTS attendance (
id INTEGER PRIMARY KEY AUTOINCREMENT,
emp_id TEXT,
date TEXT,
check_in TEXT,
check_out TEXT)''',
'''CREATE TABLE IF NOT EXISTS salaries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
emp_id TEXT,
month TEXT,
basic REAL,
deductions REAL,
allowances REAL,
net REAL)''',
'''CREATE TABLE IF NOT EXISTS leaves (
id INTEGER PRIMARY KEY AUTOINCREMENT,
emp_id TEXT,
start_date TEXT,
end_date TEXT,
type TEXT,
status TEXT DEFAULT 'معلق')''',
'''CREATE TABLE IF NOT EXISTS performance (
id INTEGER PRIMARY KEY AUTOINCREMENT,
emp_id TEXT,
date TEXT,
productivity REAL,
teamwork REAL,
comments TEXT)'''
]
for table in tables:
self.cursor.execute(table)
self.conn.commit()
def create_widgets(self):
toolbar = ttk.Frame(self.root)
toolbar.pack(side='top', fill='x')
self.emp_selector = ttk.Combobox(toolbar, postcommand=self.update_emp_list)
self.emp_selector.pack(side='left', padx=5, pady=5)
self.emp_selector.bind('<<ComboboxSelected>>', self.select_employee)
ttk.Button(toolbar, text="تصدير Excel", command=self.export_to_excel).pack(side='right', padx=5)
self.tab_control = ttk.Notebook(self.root)
self.tab_employees = self.create_employee_tab()
self.tab_control.add(self.tab_employees, text='الموظفين')
self.tab_attendance = self.create_attendance_tab()
self.tab_control.add(self.tab_attendance, text='الحضور')
self.tab_salaries = self.create_salary_tab()
self.tab_control.add(self.tab_salaries, text='الرواتب')
self.tab_leaves = self.create_leave_tab()
self.tab_control.add(self.tab_leaves, text='الإجازات')
self.tab_performance = self.create_performance_tab()
self.tab_control.add(self.tab_performance, text='التقييم')
self.tab_control.pack(expand=1, fill='both')
def create_employee_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the employee tab code - same as before)
return tab
def create_attendance_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the attendance tab code - same as before)
return tab
def create_salary_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the salary tab code - same as before)
return tab
def create_leave_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the leave tab code - same as before)
return tab
def create_performance_tab(self):
tab = ttk.Frame(self.tab_control)
# ... (Rest of the performance tab code - same as before)
return tab
def export_to_excel(self):
try:
wb = Workbook()
# تصدير الموظفين
ws_emp = wb.active
ws_emp.title = "الموظفين"
ws_emp.append(['الرقم الوظيفي', 'الاسم', 'تاريخ الميلاد', 'الجنسية', 'تاريخ التعيين', 'القسم', 'الراتب']) # Include all columns
employees = self.cursor.execute("SELECT id, name, dob, nationality, hire_date, department, salary FROM employees").fetchall() # Select all columns
for emp in employees:
ws_emp.append(emp)
# تصدير الرواتب
ws_sal = wb.create_sheet("الرواتب")
ws_sal.append(['الشهر', 'الأساسي', 'الخصومات', 'المكافآت', 'الصافي'])
salaries = self.cursor.execute("SELECT month, basic, deductions, allowances, net FROM salaries").fetchall()
for sal in salaries:
ws_sal.append(sal)
# ... (Export other tables - attendance, leaves, performance)
wb.save("hr_export.xlsx")
messagebox.showinfo("نجاح", "تم التصدير إلى hr_export.xlsx")
except Exception as e:
messagebox.showerror("خطأ", f"خطأ في التصدير: {str(e)}")
def update_emp_list(self):
try:
self.emp_selector['values'] = [row[0] for row in self.cursor.execute("SELECT id FROM employees").fetchall()]
except Exception as e:
messagebox.showerror("خطأ", str(e))
def select_employee(self, event):
self.current_emp_id = self.emp_selector.get()
# ... (Load and display details for the selected employee in the appropriate tabs) ...
def load_initial_data(self):
self.update_emp_list() # Load employee list at start
self.refresh_employee_table() # Refresh the employee table
def refresh_employee_table(self):
try:
self.employee_tree.delete(*self.employee_tree.get_children()) # Clear existing data
employees = self.cursor.execute("SELECT id, name, dob, nationality, hire_date, department, salary FROM employees").fetchall()
for employee in employees:
self.employee_tree.insert("", tk.END, values=employee)
except Exception as e:
messagebox.showerror("Error", str(e))
# ... (Add other data loading/refresh functions for attendance, salaries, etc.)
def add_employee(self):
try:
data = [self.entries[label].get() for label in ['الرقم الوظيفي', 'الاسم', 'تاريخ الميلاد', 'الجنسية', 'تاريخ التعيين', 'القسم', 'الراتب']]
self.cursor.execute("INSERT INTO employees VALUES (?, ?, ?, ?, ?, ?, ?)", data)
self.conn.commit()
self.refresh_employee_table() # Refresh the table after adding
messagebox.showinfo("نجاح", "تمت إضافة الموظف.")
# Clear the entry fields after adding (optional)
for entry in self.entries.values():
entry.delete(0, tk.END)
except Exception as e:
self.conn.rollback()
messagebox.showerror("خطأ", str(e))
# ... (Implement update_employee, delete_employee, check_in, check_out, calculate_salary, submit_leave, save_performance)
if __name__ == "__main__":
root = tk.Tk()
app = AdvancedHRMS(root)
root.mainloop()