Dự án tốt nghiệp - Hệ thống Quản lý Cửa hàng Mini!

Chào mừng các kiến trúc sư dữ liệu nhí đến với Trận chiến cuối cùng: Dự án tốt nghiệp - Hệ thống Quản lý Cửa hàng Mini! Dự án này sẽ tổng hợp toàn bộ các "phép thuật" mà ta đã học từ đầu đến giờ: Tạo bảng, liên kết Khóa ngoại, Thêm (Create), Đọc (Read), và Cập nhật (Update) dữ liệu.

Để phần mềm này thực sự giống một ứng dụng ngoài đời, chúng ta sẽ xây dựng một Hệ thống Menu tương tác ngay trên Terminal. Người dùng  chỉ cần gõ số 1, 2, 3, 4 để ra lệnh cho phần mềm.

🏗️ THIẾT KẾ HỆ THỐNG

Cửa hàng của chúng ta sẽ sử dụng file cơ sở dữ liệu kho_hang_tot_nghiep.db gồm 2 bảng có mối quan hệ Một - Nhiều ($1:N$):

  1. Bảng danh_muc: Lưu các nhóm hàng (Ví dụ: 1. Trái cây, 2. Bánh kẹo).

  2. Bảng san_pham: Lưu chi tiết mặt hàng, có cột danh_muc_id nối sang bảng trên, cùng với so_luong (hàng tồn kho) và gia_ban.

💻 TOÀN BỘ MÃ NGUỒN DỰ ÁN TỐT NGHIỆP

Tạo một file lớn tên là du_an_tot_nghiep.py và gõ thật cẩn thận đoạn code hệ thống này nhé. Code được chia làm các hàm (Function) rất rõ ràng để các con dễ quản lý:

import sqlite3

# =====================================================================
# BƯỚC 1: KHỞI TẠO HỆ THỐNG (Chạy ngầm khi vừa bật app)
# =====================================================================
def khoi_tao_database():
    ket_noi = sqlite3.connect("kho_hang_tot_nghiep.db")
    nguoi_tho = ket_noi.cursor()
    nguoi_tho.execute("PRAGMA foreign_keys = ON;")
    
    # Tạo bảng danh mục
    nguoi_tho.execute("""
    CREATE TABLE IF NOT EXISTS danh_muc (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        ten_danh_muc TEXT NOT NULL UNIQUE
    )
    """)
    
    # Tạo bảng sản phẩm
    nguoi_tho.execute("""
    CREATE TABLE IF NOT EXISTS san_pham (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        ten_san_pham TEXT NOT NULL,
        so_luong INTEGER DEFAULT 0,
        gia_ban INTEGER DEFAULT 0,
        danh_muc_id INTEGER,
        FOREIGN KEY (danh_muc_id) REFERENCES danh_muc(id)
    )
    """)
    
    # Nạp sẵn một số danh mục mẫu nếu bảng đang trống
    nguoi_tho.execute("SELECT COUNT(*) FROM danh_muc")
    if nguoi_tho.fetchone()[0] == 0:
        nguoi_tho.executemany("INSERT INTO danh_muc (ten_danh_muc) VALUES (?)", [
            ('Trái cây tươi',), ('Bánh kẹo',), ('Nước giải khát',)
        ])
    
    ket_noi.commit()
    ket_noi.close()

# =====================================================================
# BƯỚC 2: CÁC PHÉP THUẬT XỬ LÝ DỮ LIỆU (CRUD)
# =====================================================================

# Chức năng 1: Xem toàn bộ kho hàng (Dùng phép JOIN đồ họa ở Bài 4)
def xem_kho_hang():
    ket_noi = sqlite3.connect("kho_hang_tot_nghiep.db")
    nguoi_tho = ket_noi.cursor()
    
    cau_lenh = """
    SELECT sp.id, sp.ten_san_pham, sp.so_luong, sp.gia_ban, dm.ten_danh_muc
    FROM san_pham sp
    INNER JOIN danh_muc dm ON sp.danh_muc_id = dm.id
    """
    nguoi_tho.execute(cau_lenh)
    cac_mat_hang = nguoi_tho.fetchall()
    
    print("\n📦 === DANH SÁCH HÀNG TỒN KHO ===")
    if not cac_mat_hang:
        print("(Kho đang trống trơn, bố hãy thêm sản phẩm mới nhé!)")
    else:
        print(f"{'ID':<5}{'Tên sản phẩm':<20}{'Số lượng':<10}{'Giá bán':<12}{'Danh mục':<15}")
        print("-" * 65)
        for sp in cac_mat_hang:
            print(f"{sp[0]:<5}{sp[1]:<20}{sp[2]:<10}{sp[3]:<12,Format}đ  {sp[4]:<15}")
    ket_noi.close()

# Chức năng 2: Thêm sản phẩm mới vào kho (Dùng dấu ? bảo mật)
def them_san_pham():
    ket_noi = sqlite3.connect("kho_hang_tot_nghiep.db")
    nguoi_tho = ket_noi.cursor()
    
    print("\n➕ === THÊM SẢN PHẨM MỚI ===")
    ten = input("Nhập tên sản phẩm: ")
    sl = int(input("Nhập số lượng nhập kho: "))
    gia = int(input("Nhập giá bán (đại diện tiền): "))
    
    # Hiện danh mục cho người dùng chọn
    nguoi_tho.execute("SELECT * FROM danh_muc")
    cac_dm = nguoi_tho.fetchall()
    print("Chọn nhóm danh mục:")
    for dm in cac_dm:
        print(f"  {dm[0]}. {dm[1]}")
    dm_id = int(input("Nhập số ID danh mục đã chọn: "))
    
    nguoi_tho.execute("""
    INSERT INTO san_pham (ten_san_pham, so_luong, gia_ban, danh_muc_id)
    VALUES (?, ?, ?, ?)
    """, (ten, sl, gia, dm_id))
    
    ket_noi.commit()
    print(f"🎉 Đã nhập thành công mặt hàng '{ten}' vào kho!")
    ket_noi.close()

# Chức năng 3: Bán hàng (Trừ bớt số lượng tồn kho - Phép UPDATE)
def ban_hang():
    ket_noi = sqlite3.connect("kho_hang_tot_nghiep.db")
    nguoi_tho = ket_noi.cursor()
    
    print("\n🛒 === ĐƠN HÀNG MỚI (BÁN HÀNG) ===")
    sp_id = int(input("Nhập ID sản phẩm khách muốn mua: "))
    sl_mua = int(input("Nhập số lượng khách mua: "))
    
    # Kiểm tra số lượng tồn kho xem có đủ bán không
    nguoi_tho.execute("SELECT ten_san_pham, so_luong, gia_ban FROM san_pham WHERE id = ?", (sp_id,))
    thong_tin = nguoi_tho.fetchone()
    
    if thong_tin is None:
        print("❌ Lỗi: Không tìm thấy sản phẩm có ID này!")
    elif thong_tin[1] < sl_mua:
        print(f"❌ Lỗi: Trong kho chỉ còn {thong_tin[1]} sản phẩm, không đủ bán!")
    else:
        # Tính tiền
        tong_tien = sl_mua * thong_tin[2]
        # Cập nhật trừ kho
        so_luong_moi = thong_tin[1] - sl_mua
        nguoi_tho.execute("UPDATE san_pham SET so_luong = ? WHERE id = ?", (so_luong_moi, sp_id))
        
        ket_noi.commit()
        print(f"💵 Khách mua thành công: {thong_tin[0]} x{sl_mua}")
        print(f"💰 TỔNG TIỀN THU VỀ: {tong_tien:,}đ")
        print(f"📉 Đã tự động trừ kho, hiện tại còn tồn: {so_luong_moi}")
        
    ket_noi.close()

# =====================================================================
# BƯỚC 3: TRUNG TÂM ĐIỀU KHIỂN (MENU VÒNG LẶP WHILE)
# =====================================================================
def giao_dien_chinh():
    khoi_tao_database()
    
    while True:
        print("\n" + "="*40)
        print("🏪 PHẦN MỀM QUẢN LÝ CỬA HÀNG MINI 🏪")
        print("="*40)
        print("1. Xem danh sách hàng tồn kho")
        print("2. Thêm sản phẩm mới vào kho")
        print("3. Tạo đơn bán hàng (Trừ tồn kho)")
        print("4. Thoát chương trình")
        print("="*40)
        
        lua_chon = input("Mời bố và các con nhập lựa chọn (1-4): ")
        
        if lua_chon == "1":
            xem_kho_hang()
        elif lua_chon == "2":
            them_san_pham()
        elif lua_chon == "3":
            ban_hang()
        elif lua_chon == "4":
            print("👋 Tạm biệt các kiến trúc sư dữ liệu nhí! Hẹn gặp lại!")
            break
        else:
            print("❌ Lựa chọn không hợp lệ, vui lòng gõ lại từ 1 đến 4.")

# Chạy chương trình
giao_dien_chinh()

🎁 HƯỚNG DẪN NGHIỆM THU DỰ ÁN TỐT NGHIỆP:

Hãy bấm Run để khởi động cửa hàng mini. Thực hiện một kịch bản vận hành thực tế như sau:

  1. Bước 1: Gõ số 1 để xem kho hàng $\rightarrow$ Hệ thống báo kho trống.

  2. Bước 2: Gõ số 2 để nhập một vài món hàng ngon lành:

    • Tên: Dừa xiêm Bến Tre | Số lượng: 50 | Giá: 15000 | Danh mục: 1 (Trái cây tươi)

    • Tên: Bánh quy Bơ | Số lượng: 20 | Giá: 30000 | Danh mục: 2 (Bánh kẹo)

  3. Bước 3: Gõ số 1 lần nữa $\rightarrow$ Wow! Bảng kho hàng hiện ra siêu đẹp mắt và thẳng hàng.

  4. Bước 4 (Thử thách thăng hoa): Gõ số 3 để giả định có khách vào mua 10 quả Dừa xiêm (Nhập ID của dừa là 1). Xem máy tính có tính ra đúng số tiền và tự trừ tồn kho của quả dừa từ 50 xuống 40 không nhé!

Sau khi chạy thử mượt mà, hãy : Sử dụng PyInstaller để đóng gói file code này thành file .exe duy nhất.

Khi đó, ta sẽ sở hữu một phần mềm quản lý kho hàng "chính chủ" có thể mang đi cài đặt cho cửa hàng hoặc nhà xưởng thực tế luôn! Chúc các bạn nhỏ bảo vệ đồ án tốt nghiệp xuất sắc nhé.