镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

LMS - Library Management System #4443

Description

@soomrojaved15-droid

import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3

db = sqlite3.connect("library_system.db")
cursor = db.cursor()

cursor.execute("""
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
book_name TEXT NOT NULL,
quantity INTEGER NOT NULL
)
""")

cursor.execute("""
CREATE TABLE IF NOT EXISTS issued_books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
book_id INTEGER NOT NULL,
student_name TEXT NOT NULL,
person_no TEXT NOT NULL,
issue_date TEXT NOT NULL,
status TEXT NOT NULL,
FOREIGN KEY (book_id) REFERENCES books(id)
)
""")

db.commit()

window = tk.Tk()
window.title("Library Management System")
window.geometry("1150x750")
window.minsize(1000, 650)
window.configure(bg="white")

GREEN = "#16a34a"
GREEN_HOVER = "#15803d"

BLUE = "#2563eb"
BLUE_HOVER = "#1d4ed8"

RED = "#dc2626"
RED_HOVER = "#b91c1c"

DARK = "#1f2937"
GRAY = "#f3f4f6"

def create_button(parent, text, command, color, hover_color):

button = tk.Button(
    parent,
    text=text,
    command=command,
    bg=color,
    fg="white",
    activebackground=hover_color,
    activeforeground="white",
    font=("Arial", 10, "bold"),
    relief="flat",
    cursor="hand2",
    padx=15,
    pady=8
)

button.bind(
    "<Enter>",
    lambda event: button.config(bg=hover_color)
)

button.bind(
    "<Leave>",
    lambda event: button.config(bg=color)
)

return button

def refresh_inventory():

for item in inventory_table.get_children():
    inventory_table.delete(item)

cursor.execute("""
    SELECT
        books.id,
        books.book_name,
        books.quantity,
        COUNT(
            CASE
                WHEN issued_books.status = 'Issued'
                THEN 1
            END
        )
    FROM books
    LEFT JOIN issued_books
    ON books.id = issued_books.book_id
    GROUP BY
        books.id,
        books.book_name,
        books.quantity
    ORDER BY books.id
""")

books = cursor.fetchall()

for book in books:

    book_id = book[0]
    book_name = book[1]
    total_quantity = book[2]
    issued_quantity = book[3]

    available_quantity = total_quantity - issued_quantity

    inventory_table.insert(
        "",
        "end",
        values=(
            book_id,
            book_name,
            total_quantity,
            issued_quantity,
            available_quantity
        )
    )

=========================================================

SEARCH INVENTORY

=========================================================

def search_inventory():

search_text = inventory_search_var.get().strip()

if search_text == "":
    refresh_inventory()
    return

for item in inventory_table.get_children():
    inventory_table.delete(item)

cursor.execute("""
    SELECT
        books.id,
        books.book_name,
        books.quantity,
        COUNT(
            CASE
                WHEN issued_books.status = 'Issued'
                THEN 1
            END
        )
    FROM books
    LEFT JOIN issued_books
    ON books.id = issued_books.book_id
    WHERE books.book_name LIKE ?
    GROUP BY
        books.id,
        books.book_name,
        books.quantity
    ORDER BY books.id
""", (f"%{search_text}%",))

books = cursor.fetchall()

for book in books:

    book_id = book[0]
    book_name = book[1]
    total_quantity = book[2]
    issued_quantity = book[3]

    available_quantity = total_quantity - issued_quantity

    inventory_table.insert(
        "",
        "end",
        values=(
            book_id,
            book_name,
            total_quantity,
            issued_quantity,
            available_quantity
        )
    )

def refresh_issued_books():

for item in issued_table.get_children():
    issued_table.delete(item)

cursor.execute("""
    SELECT
        issued_books.id,
        books.book_name,
        issued_books.student_name,
        issued_books.person_no,
        issued_books.issue_date
    FROM issued_books
    INNER JOIN books
    ON issued_books.book_id = books.id
    WHERE issued_books.status = 'Issued'
    ORDER BY issued_books.id DESC
""")

records = cursor.fetchall()

for record in records:

    issued_table.insert(
        "",
        "end",
        values=record
    )

def search_issued_books():

book_search = issued_book_search_var.get().strip()
person_search = person_search_var.get().strip()

for item in issued_table.get_children():
    issued_table.delete(item)

cursor.execute("""
    SELECT
        issued_books.id,
        books.book_name,
        issued_books.student_name,
        issued_books.person_no,
        issued_books.issue_date
    FROM issued_books
    INNER JOIN books
    ON issued_books.book_id = books.id
    WHERE issued_books.status = 'Issued'
    AND books.book_name LIKE ?
    AND issued_books.person_no LIKE ?
    ORDER BY issued_books.id DESC
""", (
    f"%{book_search}%",
    f"%{person_search}%"
))

records = cursor.fetchall()

for record in records:

    issued_table.insert(
        "",
        "end",
        values=record
    )

=========================================================

ADD BOOK WINDOW

=========================================================

def open_add_book_window():

add_window = tk.Toplevel(window)

add_window.title("Add Books")
add_window.geometry("750x550")
add_window.configure(bg="white")
add_window.resizable(False, False)

title = tk.Label(
    add_window,
    text="Add Books",
    font=("Arial", 20, "bold"),
    bg="white",
    fg=DARK
)

title.pack(pady=(20, 15))


# -------------------------
# FORM
# -------------------------

form_frame = tk.Frame(
    add_window,
    bg="white"
)

form_frame.pack(pady=5)


tk.Label(
    form_frame,
    text="Book Name",
    font=("Arial", 11, "bold"),
    bg="white"
).grid(
    row=0,
    column=0,
    padx=10,
    pady=8,
    sticky="w"
)


book_name_entry = tk.Entry(
    form_frame,
    font=("Arial", 11),
    width=35,
    relief="solid",
    bd=1
)

book_name_entry.grid(
    row=0,
    column=1,
    padx=10,
    pady=8
)


tk.Label(
    form_frame,
    text="Quantity",
    font=("Arial", 11, "bold"),
    bg="white"
).grid(
    row=1,
    column=0,
    padx=10,
    pady=8,
    sticky="w"
)


quantity_entry = tk.Entry(
    form_frame,
    font=("Arial", 11),
    width=35,
    relief="solid",
    bd=1
)

quantity_entry.grid(
    row=1,
    column=1,
    padx=10,
    pady=8
)




def show_books():

    for item in books_table.get_children():
        books_table.delete(item)

    cursor.execute("""
        SELECT id, book_name, quantity
        FROM books
        ORDER BY id DESC
    """)

    books = cursor.fetchall()

    for book in books:

        books_table.insert(
            "",
            "end",
            values=book
        )


def save_book():

    name = book_name_entry.get().strip()
    quantity = quantity_entry.get().strip()


    if name == "":
        messagebox.showerror(
            "Error",
            "Please enter book name."
        )
        return


    if quantity == "":
        messagebox.showerror(
            "Error",
            "Please enter quantity."
        )
        return


    try:
        quantity = int(quantity)

    except ValueError:

        messagebox.showerror(
            "Error",
            "Quantity must be a number."
        )
        return


    if quantity <= 0:

        messagebox.showerror(
            "Error",
            "Quantity must be greater than 0."
        )
        return


    cursor.execute("""
        INSERT INTO books (
            book_name,
            quantity
        )
        VALUES (?, ?)
    """, (
        name,
        quantity
    ))

    db.commit()


    book_name_entry.delete(0, tk.END)
    quantity_entry.delete(0, tk.END)

    show_books()
    refresh_inventory()

    messagebox.showinfo(
        "Success",
        "Book added successfully!"
    )


add_button = create_button(
    add_window,
    "+ ADD BOOK",
    save_book,
    GREEN,
    GREEN_HOVER
)

add_button.pack(pady=15)


books_table = ttk.Treeview(
    add_window,
    columns=(
        "ID",
        "Book Name",
        "Quantity"
    ),
    show="headings",
    height=10
)


books_table.heading(
    "ID",
    text="ID"
)

books_table.heading(
    "Book Name",
    text="Book Name"
)

books_table.heading(
    "Quantity",
    text="Quantity"
)


books_table.column(
    "ID",
    width=70,
    anchor="center"
)

books_table.column(
    "Book Name",
    width=400
)

books_table.column(
    "Quantity",
    width=150,
    anchor="center"
)


books_table.pack(
    fill="x",
    padx=30,
    pady=10
)


close_button = tk.Button(
    add_window,
    text="CLOSE",
    command=add_window.destroy,
    bg=GRAY,
    fg=DARK,
    font=("Arial", 10, "bold"),
    relief="flat",
    padx=20,
    pady=7,
    cursor="hand2"
)

close_button.pack(pady=10)


show_books()

book_name_entry.focus()

def open_issue_book_window():

issue_window = tk.Toplevel(window)

issue_window.title("Issue Book")
issue_window.geometry("650x430")
issue_window.configure(bg="white")
issue_window.resizable(False, False)


title = tk.Label(
    issue_window,
    text="Issue Book",
    font=("Arial", 20, "bold"),
    bg="white",
    fg=DARK
)

title.pack(pady=(20, 15))


form_frame = tk.Frame(
    issue_window,
    bg="white"
)

form_frame.pack()




tk.Label(
    form_frame,
    text="Book",
    font=("Arial", 11, "bold"),
    bg="white"
).grid(
    row=0,
    column=0,
    padx=10,
    pady=10,
    sticky="w"
)


book_combo = ttk.Combobox(
    form_frame,
    state="readonly",
    width=38,
    font=("Arial", 11)
)

book_combo.grid(
    row=0,
    column=1,
    padx=10,
    pady=10
)


tk.Label(
    form_frame,
    text="Student Name",
    font=("Arial", 11, "bold"),
    bg="white"
).grid(
    row=1,
    column=0,
    padx=10,
    pady=10,
    sticky="w"
)


student_entry = tk.Entry(
    form_frame,
    font=("Arial", 11),
    width=40,
    relief="solid",
    bd=1
)

student_entry.grid(
    row=1,
    column=1,
    padx=10,
    pady=10
)


tk.Label(
    form_frame,
    text="P. No",
    font=("Arial", 11, "bold"),
    bg="white"
).grid(
    row=2,
    column=0,
    padx=10,
    pady=10,
    sticky="w"
)


person_no_entry = tk.Entry(
    form_frame,
    font=("Arial", 11),
    width=40,
    relief="solid",
    bd=1
)

person_no_entry.grid(
    row=2,
    column=1,
    padx=10,
    pady=10
)


# =====================================================
# ISSUE DATE
# =====================================================

tk.Label(
    form_frame,
    text="Issue Date",
    font=("Arial", 11, "bold"),
    bg="white"
).grid(
    row=3,
    column=0,
    padx=10,
    pady=10,
    sticky="w"
)


issue_date_entry = tk.Entry(
    form_frame,
    font=("Arial", 11),
    width=40,
    relief="solid",
    bd=1
)

issue_date_entry.grid(
    row=3,
    column=1,
    padx=10,
    pady=10
)


def load_books():

    cursor.execute("""
        SELECT
            books.id,
            books.book_name,
            books.quantity,
            COUNT(
                CASE
                    WHEN issued_books.status = 'Issued'
                    THEN 1
                END
            )
        FROM books
        LEFT JOIN issued_books
        ON books.id = issued_books.book_id
        GROUP BY
            books.id,
            books.book_name,
            books.quantity
    """)

    books = cursor.fetchall()

    values = []

    for book in books:

        book_id = book[0]
        book_name = book[1]
        total = book[2]
        issued = book[3]

        available = total - issued

        if available > 0:

            values.append(
                f"{book_id} - {book_name} ({available} available)"
            )

    book_combo["values"] = values



def issue_book():

    selected_book = book_combo.get()
    student = student_entry.get().strip()
    person_no = person_no_entry.get().strip()
    issue_date = issue_date_entry.get().strip()


    if selected_book == "":
        messagebox.showerror(
            "Error",
            "Please select a book."
        )
        return


    if student == "":
        messagebox.showerror(
            "Error",
            "Please enter student name."
        )
        return


    if person_no == "":
        messagebox.showerror(
            "Error",
            "Please enter P. No."
        )
        return


    if issue_date == "":
        messagebox.showerror(
            "Error",
            "Please enter issue date."
        )
        return


    # Get Book ID

    book_id = selected_book.split(" - ")[0]


    # Get total quantity

    cursor.execute("""
        SELECT quantity
        FROM books
        WHERE id = ?
    """, (book_id,))

    book = cursor.fetchone()


    if book is None:

        messagebox.showerror(
            "Error",
            "Book not found."
        )
        return


    total_quantity = book[0]


    # Count currently issued copies

    cursor.execute("""
        SELECT COUNT(*)
        FROM issued_books
        WHERE book_id = ?
        AND status = 'Issued'
    """, (book_id,))

    issued_quantity = cursor.fetchone()[0]


    available_quantity = total_quantity - issued_quantity


    if available_quantity <= 0:

        messagebox.showerror(
            "Error",
            "This book is not available."
        )

        load_books()
        return


    # Save issue record

    cursor.execute("""
        INSERT INTO issued_books (
            book_id,
            student_name,
            person_no,
            issue_date,
            status
        )
        VALUES (?, ?, ?, ?, ?)
    """, (
        book_id,
        student,
        person_no,
        issue_date,
        "Issued"
    ))


    db.commit()




    book_combo.set("")
    student_entry.delete(0, tk.END)
    person_no_entry.delete(0, tk.END)
    issue_date_entry.delete(0, tk.END)


    load_books()
    refresh_inventory()
    refresh_issued_books()


    messagebox.showinfo(
        "Success",
        "Book issued successfully!"
    )

issue_button = create_button(
    issue_window,
    "ISSUE BOOK",
    issue_book,
    BLUE,
    BLUE_HOVER
)

issue_button.pack(pady=20)


load_books()

student_entry.focus()

def return_book():

selected = issued_table.selection()


if not selected:

    messagebox.showerror(
        "Error",
        "Please select an issued book first."
    )

    return


item = issued_table.item(selected[0])

issued_id = item["values"][0]


confirm = messagebox.askyesno(
    "Return Book",
    "Is this book being returned?"
)


if not confirm:
    return


cursor.execute("""
    UPDATE issued_books
    SET status = 'Returned'
    WHERE id = ?
""", (issued_id,))


db.commit()


refresh_inventory()
refresh_issued_books()


messagebox.showinfo(
    "Success",
    "Book returned successfully!"
)

header_frame = tk.Frame(
window,
bg="white"
)

header_frame.pack(
fill="x",
padx=30,
pady=(25, 15)
)

title = tk.Label(
header_frame,
text="📚 Library Management System",
font=("Arial", 24, "bold"),
bg="white",
fg=DARK
)

title.pack(side="left")

button_frame = tk.Frame(
header_frame,
bg="white"
)

button_frame.pack(side="right")

ADD BOOK

add_book_button = create_button(
button_frame,
"+ ADD BOOK",
open_add_book_window,
GREEN,
GREEN_HOVER
)

add_book_button.pack(
side="left",
padx=5
)

ISSUE BOOK

issue_book_button = create_button(
button_frame,
"ISSUE BOOK",
open_issue_book_window,
BLUE,
BLUE_HOVER
)

issue_book_button.pack(
side="left",
padx=5
)

inventory_frame = tk.Frame(
window,
bg="white"
)

inventory_frame.pack(
fill="both",
expand=True,
padx=30,
pady=5
)

inventory_heading_frame = tk.Frame(
inventory_frame,
bg="white"
)

inventory_heading_frame.pack(
fill="x"
)

inventory_title = tk.Label(
inventory_heading_frame,
text="Book Inventory",
font=("Arial", 16, "bold"),
bg="white",
fg=DARK
)

inventory_title.pack(
side="left"
)

inventory_search_var = tk.StringVar()

inventory_search_entry = tk.Entry(
inventory_heading_frame,
textvariable=inventory_search_var,
font=("Arial", 11),
width=30,
relief="solid",
bd=1
)

inventory_search_entry.pack(
side="right",
padx=5,
pady=5
)

inventory_search_label = tk.Label(
inventory_heading_frame,
text="🔍 Search Book:",
font=("Arial", 10, "bold"),
bg="white",
fg=DARK
)

inventory_search_label.pack(
side="right",
padx=5
)

inventory_search_entry.bind(
"",
lambda event: search_inventory()
)

inventory_table = ttk.Treeview(
inventory_frame,
columns=(
"ID",
"Book Name",
"Total Quantity",
"Issued",
"Available"
),
show="headings",
height=9
)

inventory_table.heading("ID", text="ID")
inventory_table.heading("Book Name", text="Book Name")
inventory_table.heading("Total Quantity", text="Total Quantity")
inventory_table.heading("Issued", text="Issued")
inventory_table.heading("Available", text="Available")

inventory_table.column(
"ID",
width=70,
anchor="center"
)

inventory_table.column(
"Book Name",
width=400
)

inventory_table.column(
"Total Quantity",
width=150,
anchor="center"
)

inventory_table.column(
"Issued",
width=120,
anchor="center"
)

inventory_table.column(
"Available",
width=120,
anchor="center"
)

inventory_table.pack(
fill="x",
pady=(5, 20)
)

issued_title_frame = tk.Frame(
window,
bg="white"
)

issued_title_frame.pack(
fill="x",
padx=30
)

issued_title = tk.Label(
issued_title_frame,
text="Currently Issued Books",
font=("Arial", 16, "bold"),
bg="white",
fg=DARK
)

issued_title.pack(
side="left"
)

issued_search_frame = tk.Frame(
window,
bg="white"
)

issued_search_frame.pack(
fill="x",
padx=30,
pady=(5, 8)
)

BOOK SEARCH

tk.Label(
issued_search_frame,
text="🔍 Book:",
font=("Arial", 10, "bold"),
bg="white",
fg=DARK
).pack(
side="left",
padx=(0, 5)
)

issued_book_search_var = tk.StringVar()

issued_book_search_entry = tk.Entry(
issued_search_frame,
textvariable=issued_book_search_var,
font=("Arial", 11),
width=28,
relief="solid",
bd=1
)

issued_book_search_entry.pack(
side="left",
padx=(0, 25)
)

P.NO SEARCH

tk.Label(
issued_search_frame,
text="👤 P. No:",
font=("Arial", 10, "bold"),
bg="white",
fg=DARK
).pack(
side="left",
padx=(0, 5)
)

person_search_var = tk.StringVar()

person_search_entry = tk.Entry(
issued_search_frame,
textvariable=person_search_var,
font=("Arial", 11),
width=22,
relief="solid",
bd=1
)

person_search_entry.pack(
side="left"
)

issued_book_search_entry.bind(
"",
lambda event: search_issued_books()
)

person_search_entry.bind(
"",
lambda event: search_issued_books()
)

=========================================================

ISSUED BOOK TABLE

=========================================================

issued_table = ttk.Treeview(
window,
columns=(
"ID",
"Book",
"Student Name",
"P. No",
"Issue Date"
),
show="headings",
height=8
)

issued_table.heading("ID", text="ID")
issued_table.heading("Book", text="Book")
issued_table.heading("Student Name", text="Student Name")
issued_table.heading("P. No", text="P. No")
issued_table.heading("Issue Date", text="Issue Date")

issued_table.column(
"ID",
width=60,
anchor="center"
)

issued_table.column(
"Book",
width=300
)

issued_table.column(
"Student Name",
width=250
)

issued_table.column(
"P. No",
width=120,
anchor="center"
)

issued_table.column(
"Issue Date",
width=150,
anchor="center"
)

issued_table.pack(
fill="x",
padx=30
)

return_button = create_button(
window,
"✓ RETURN SELECTED BOOK",
return_book,
RED,
RED_HOVER
)

return_button.pack(
pady=15
)

refresh_inventory()
refresh_issued_books()

window.mainloop()

db.close()

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions