Compare commits
No commits in common. "1bb52206cc86eff84b49514662e3d22255045f54" and "5400541b34bda0fa477cec556aae41de55ea7fd7" have entirely different histories.
1bb52206cc
...
5400541b34
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,129 +1,40 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import messagebox, filedialog
|
|
||||||
from database import connect
|
from database import connect
|
||||||
import os
|
from tkinter import messagebox
|
||||||
import shutil
|
|
||||||
|
|
||||||
# GANTI NAMA CLASS JADI AdminPage
|
class AdminMenu:
|
||||||
class AdminPage(tk.Frame):
|
def __init__(self, root):
|
||||||
def __init__(self, parent, controller):
|
self.root = root
|
||||||
super().__init__(parent)
|
self.frame = tk.Frame(root)
|
||||||
self.controller = controller
|
self.frame.pack()
|
||||||
self.selected_image_path = None
|
|
||||||
self.data_menu = []
|
|
||||||
|
|
||||||
# --- Header ---
|
tk.Label(
|
||||||
top = tk.Frame(self, bg="#333")
|
self.frame,
|
||||||
top.pack(fill="x")
|
text="ADMIN - KELOLA MENU",
|
||||||
tk.Label(top, text="ADMIN DASHBOARD", font=("Arial", 16, "bold"), fg="white", bg="#333").pack(side="left", padx=10, pady=10)
|
font=("Arial", 18, "bold")
|
||||||
tk.Button(top, text="Logout", bg="#ff6b6b", command=lambda: controller.show_frame("LoginPage")).pack(side="right", padx=10)
|
).pack(pady=10)
|
||||||
|
|
||||||
# --- Layout Kiri (Form) & Kanan (Tabel) ---
|
self.nama = tk.Entry(self.frame)
|
||||||
main_content = tk.Frame(self)
|
self.harga = tk.Entry(self.frame)
|
||||||
main_content.pack(fill="both", expand=True, padx=10, pady=10)
|
self.gambar = tk.Entry(self.frame)
|
||||||
|
|
||||||
# --- KIRI ---
|
for label, entry in [
|
||||||
left_frame = tk.Frame(main_content)
|
("Nama Menu", self.nama),
|
||||||
left_frame.pack(side="left", fill="y", padx=10)
|
("Harga", self.harga),
|
||||||
|
("Path Gambar", self.gambar)
|
||||||
|
]:
|
||||||
|
tk.Label(self.frame, text=label).pack()
|
||||||
|
entry.pack()
|
||||||
|
|
||||||
tk.Label(left_frame, text="Nama Menu:").pack(anchor="w")
|
tk.Button(self.frame, text="Tambah Menu", command=self.tambah).pack(pady=5)
|
||||||
self.entry_nama = tk.Entry(left_frame, width=30)
|
|
||||||
self.entry_nama.pack(pady=5)
|
|
||||||
|
|
||||||
tk.Label(left_frame, text="Harga:").pack(anchor="w")
|
|
||||||
self.entry_harga = tk.Entry(left_frame, width=30)
|
|
||||||
self.entry_harga.pack(pady=5)
|
|
||||||
|
|
||||||
tk.Label(left_frame, text="Stok Awal:").pack(anchor="w")
|
|
||||||
self.entry_stok = tk.Entry(left_frame, width=30)
|
|
||||||
self.entry_stok.insert(0, "100") # Default stok
|
|
||||||
self.entry_stok.pack(pady=5)
|
|
||||||
|
|
||||||
tk.Label(left_frame, text="Gambar:").pack(anchor="w")
|
|
||||||
self.btn_img = tk.Button(left_frame, text="Pilih Gambar", command=self.browse_image)
|
|
||||||
self.btn_img.pack(pady=5, anchor="w")
|
|
||||||
self.lbl_img_path = tk.Label(left_frame, text="Belum ada gambar", fg="gray", font=("Arial", 8))
|
|
||||||
self.lbl_img_path.pack(anchor="w")
|
|
||||||
|
|
||||||
btn_box = tk.Frame(left_frame, pady=20)
|
|
||||||
btn_box.pack()
|
|
||||||
tk.Button(btn_box, text="TAMBAH", bg="#4CAF50", fg="white", command=self.add_menu).grid(row=0, column=0, padx=5)
|
|
||||||
tk.Button(btn_box, text="HAPUS", bg="#f44336", fg="white", command=self.delete_menu).grid(row=0, column=1, padx=5)
|
|
||||||
|
|
||||||
# --- KANAN ---
|
|
||||||
right_frame = tk.Frame(main_content)
|
|
||||||
right_frame.pack(side="right", fill="both", expand=True)
|
|
||||||
|
|
||||||
tk.Label(right_frame, text="Daftar Menu:", font=("Arial", 10, "bold")).pack(anchor="w")
|
|
||||||
|
|
||||||
self.list_menu = tk.Listbox(right_frame)
|
|
||||||
self.list_menu.pack(fill="both", expand=True)
|
|
||||||
|
|
||||||
scrollbar = tk.Scrollbar(self.list_menu)
|
|
||||||
scrollbar.pack(side="right", fill="y")
|
|
||||||
self.list_menu.config(yscrollcommand=scrollbar.set)
|
|
||||||
scrollbar.config(command=self.list_menu.yview)
|
|
||||||
|
|
||||||
def update_data(self):
|
|
||||||
self.list_menu.delete(0, tk.END)
|
|
||||||
self.data_menu = []
|
|
||||||
|
|
||||||
|
def tambah(self):
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
cur.execute("SELECT id, nama, harga, stok FROM menu")
|
cur.execute(
|
||||||
rows = cur.fetchall()
|
"INSERT INTO menu(nama,harga,gambar) VALUES (?,?,?)",
|
||||||
|
(self.nama.get(), self.harga.get(), self.gambar.get())
|
||||||
|
)
|
||||||
|
db.commit()
|
||||||
db.close()
|
db.close()
|
||||||
|
messagebox.showinfo("Sukses", "Menu berhasil ditambahkan")
|
||||||
for row in rows:
|
|
||||||
self.data_menu.append(row)
|
|
||||||
self.list_menu.insert(tk.END, f"{row[1]} - Rp {int(row[2])} (Stok: {row[3]})")
|
|
||||||
|
|
||||||
def browse_image(self):
|
|
||||||
filename = filedialog.askopenfilename(title="Pilih Gambar", filetypes=[("Images", "*.png;*.jpg;*.jpeg")])
|
|
||||||
if filename:
|
|
||||||
self.selected_image_path = filename
|
|
||||||
self.lbl_img_path.config(text=os.path.basename(filename), fg="black")
|
|
||||||
|
|
||||||
def add_menu(self):
|
|
||||||
nama = self.entry_nama.get()
|
|
||||||
harga = self.entry_harga.get()
|
|
||||||
stok = self.entry_stok.get()
|
|
||||||
|
|
||||||
if not nama or not harga:
|
|
||||||
messagebox.showwarning("Warning", "Nama dan Harga wajib diisi!")
|
|
||||||
return
|
|
||||||
|
|
||||||
final_image_path = "default.png"
|
|
||||||
if self.selected_image_path:
|
|
||||||
if not os.path.exists("img"): os.makedirs("img")
|
|
||||||
destinasi = os.path.join("img", os.path.basename(self.selected_image_path))
|
|
||||||
try:
|
|
||||||
shutil.copy(self.selected_image_path, destinasi)
|
|
||||||
final_image_path = destinasi
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
db = connect()
|
|
||||||
cur = db.cursor()
|
|
||||||
try:
|
|
||||||
cur.execute("INSERT INTO menu (nama, harga, stok, gambar) VALUES (?, ?, ?, ?)",
|
|
||||||
(nama, harga, stok, final_image_path))
|
|
||||||
db.commit()
|
|
||||||
messagebox.showinfo("Sukses", "Menu berhasil ditambahkan!")
|
|
||||||
self.update_data()
|
|
||||||
except Exception as e:
|
|
||||||
messagebox.showerror("Error", str(e))
|
|
||||||
finally:
|
|
||||||
db.close()
|
|
||||||
|
|
||||||
def delete_menu(self):
|
|
||||||
idx = self.list_menu.curselection()
|
|
||||||
if not idx: return
|
|
||||||
|
|
||||||
selected = self.data_menu[idx[0]]
|
|
||||||
if messagebox.askyesno("Hapus", f"Hapus {selected[1]}?"):
|
|
||||||
db = connect()
|
|
||||||
db.cursor().execute("DELETE FROM menu WHERE id=?", (selected[0],))
|
|
||||||
db.commit()
|
|
||||||
db.close()
|
|
||||||
self.update_data()
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
BIN
project/cafe.db
BIN
project/cafe.db
Binary file not shown.
@ -1,4 +1,3 @@
|
|||||||
# File: database.py
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
def connect():
|
def connect():
|
||||||
@ -8,7 +7,7 @@ def setup_database():
|
|||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
|
|
||||||
# 1. Users
|
# Users
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS users(
|
CREATE TABLE IF NOT EXISTS users(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@ -18,57 +17,56 @@ def setup_database():
|
|||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# 2. Menu
|
# Menu
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS menu(
|
CREATE TABLE IF NOT EXISTS menu(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
nama TEXT,
|
nama TEXT,
|
||||||
kategori TEXT,
|
|
||||||
harga REAL,
|
harga REAL,
|
||||||
stok INTEGER,
|
|
||||||
gambar TEXT
|
gambar TEXT
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# 3. Transaksi
|
# Orders
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS transaksi(
|
CREATE TABLE IF NOT EXISTS orders(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
nama_pelanggan TEXT,
|
nama TEXT,
|
||||||
meja_id INTEGER,
|
total REAL
|
||||||
tanggal TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
total REAL,
|
|
||||||
metode_pembayaran TEXT,
|
|
||||||
status TEXT DEFAULT 'Pending'
|
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# 4. Detail Transaksi
|
# Pembayaran
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS detail_transaksi(
|
CREATE TABLE IF NOT EXISTS pembayaran(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
transaksi_id INTEGER,
|
order_id INTEGER,
|
||||||
menu_id INTEGER,
|
total REAL
|
||||||
jumlah INTEGER,
|
|
||||||
subtotal REAL
|
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Seeding User (Kalau kosong diisi default)
|
# User default
|
||||||
cur.execute("SELECT COUNT(*) FROM users")
|
cur.execute("SELECT COUNT(*) FROM users")
|
||||||
if cur.fetchone()[0] == 0:
|
if cur.fetchone()[0] == 0:
|
||||||
users = [
|
users = [
|
||||||
("admin","admin","admin"),
|
("admin","admin","admin"),
|
||||||
("kasir","kasir","kasir"),
|
("kasir","kasir","kasir"),
|
||||||
("pembeli","pembeli","pembeli"),
|
("pembeli","pembeli","pembeli"),
|
||||||
("pemilik","pemilik","pemilik"),
|
("pemilik","pemilik","pemilik")
|
||||||
("waiter","waiter","waiter")
|
|
||||||
]
|
]
|
||||||
cur.executemany("INSERT INTO users(username,password,role) VALUES (?,?,?)", users)
|
cur.executemany("INSERT INTO users(username,password,role) VALUES (?,?,?)", users)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
# Menu default
|
||||||
|
cur.execute("SELECT COUNT(*) FROM menu")
|
||||||
|
if cur.fetchone()[0] == 0:
|
||||||
|
menu = [
|
||||||
|
("Mie Ayam", 18000, "mie ayam.webp"),
|
||||||
|
("Mie Kuah", 10000, "mie kuah.webp"),
|
||||||
|
("Es Teh Manis", 5000, "es teh.webp"),
|
||||||
|
("Jus Jeruk", 8000, "jus jeruk.webp")
|
||||||
|
]
|
||||||
|
cur.executemany("INSERT INTO menu(nama,harga,gambar) VALUES (?,?,?)", menu)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
db.commit()
|
|
||||||
db.close()
|
db.close()
|
||||||
print("Database Ready!")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
setup_database()
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
import sqlite3
|
|
||||||
|
|
||||||
def isi_data_awal():
|
|
||||||
conn = sqlite3.connect("cafe.db")
|
|
||||||
cur = conn.cursor()
|
|
||||||
|
|
||||||
# Hapus data lama biar gak dobel (opsional, biar bersih)
|
|
||||||
cur.execute("DELETE FROM menu")
|
|
||||||
|
|
||||||
# Data Menu (Sesuaikan nama file gambar dengan yang ada di folder aset kamu)
|
|
||||||
menus = [
|
|
||||||
# (Nama, Kategori, Harga, Stok, Nama File Gambar)
|
|
||||||
("Ayam Goreng", "Makanan", 15000, 20, "ayam_goreng.jpg"),
|
|
||||||
("Bakso Urat", "Makanan", 12000, 15, "bakso.jpg"),
|
|
||||||
("Mie Ayam", "Makanan", 10000, 25, "mie_ayam.jpg"),
|
|
||||||
("Es Teh Manis", "Minuman", 3000, 50, "es_teh.jpg"),
|
|
||||||
("Jus Jeruk", "Minuman", 5000, 30, "jus_jeruk.jpg"),
|
|
||||||
]
|
|
||||||
|
|
||||||
print("Sedang mengisi data menu...")
|
|
||||||
|
|
||||||
cur.executemany("""
|
|
||||||
INSERT INTO menu (nama, kategori, harga, stok, gambar)
|
|
||||||
VALUES (?, ?, ?, ?, ?)
|
|
||||||
""", menus)
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
print("✅ Berhasil! Data menu sudah masuk database.")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
isi_data_awal()
|
|
||||||
@ -2,60 +2,73 @@ import tkinter as tk
|
|||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
from database import connect
|
from database import connect
|
||||||
|
|
||||||
class KasirPage(tk.Frame):
|
class KasirPage:
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, parent, controller):
|
||||||
super().__init__(parent)
|
self.parent = parent
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
self.frame = tk.Frame(parent)
|
||||||
|
self.frame.pack(fill="both", expand=True)
|
||||||
|
|
||||||
# Header
|
tk.Label(self.frame, text="KASIR PAGE", font=("Arial", 18, "bold")).pack(pady=10)
|
||||||
top = tk.Frame(self, bg="#ddd")
|
|
||||||
top.pack(fill="x")
|
|
||||||
tk.Button(top, text="Logout", command=lambda: controller.show_frame("LoginPage")).pack(side="right", padx=10, pady=5)
|
|
||||||
tk.Label(top, text="KASIR - PEMBAYARAN", font=("Arial", 16, "bold"), bg="#ddd").pack(side="left", padx=10)
|
|
||||||
|
|
||||||
# List Order
|
# Tombol Logout
|
||||||
tk.Label(self, text="Tagihan Belum Lunas (Status: Served):", font=("Arial", 11)).pack(pady=10)
|
tk.Button(self.frame, text="Logout", bg="#f9e79f", command=self.logout).pack(pady=5)
|
||||||
self.order_list = tk.Listbox(self, width=80, height=15, font=("Arial", 10))
|
|
||||||
self.order_list.pack(pady=5)
|
|
||||||
|
|
||||||
tk.Button(self, text="Refresh Data", command=self.update_data).pack(pady=5)
|
# Listbox untuk menampilkan order
|
||||||
tk.Button(self, text="💰 PROSES BAYAR (LUNAS)", bg="#81C784", height=2, command=self.bayar).pack(fill="x", padx=50, pady=20)
|
tk.Label(self.frame, text="Daftar Order:", font=("Arial", 12, "bold")).pack(pady=5)
|
||||||
|
self.listbox = tk.Listbox(self.frame, width=50, height=10)
|
||||||
|
self.listbox.pack(pady=5)
|
||||||
|
|
||||||
def update_data(self):
|
# Tombol bayar
|
||||||
self.order_list.delete(0, tk.END)
|
tk.Button(self.frame, text="Bayar", bg="#d1e7dd", command=self.bayar).pack(pady=5)
|
||||||
self.data_orders = []
|
|
||||||
|
|
||||||
|
self.load_orders() # Load order dari database saat awal
|
||||||
|
|
||||||
|
def load_orders(self):
|
||||||
|
self.listbox.delete(0, tk.END)
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
# Kasir melihat yang statusnya Served
|
cur.execute("SELECT id, nama, harga FROM orders")
|
||||||
cur.execute("SELECT id, nama_pelanggan, meja_id, total FROM transaksi WHERE status='Served'")
|
self.data = cur.fetchall()
|
||||||
self.data_orders = cur.fetchall()
|
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
for item in self.data_orders:
|
for order in self.data:
|
||||||
self.order_list.insert(tk.END, f"ID: {item[0]} | Meja {item[2]} | {item[1]} | Tagihan: Rp {int(item[3])}")
|
self.listbox.insert(tk.END, f"ID {order[0]}: {order[1]} - Rp {order[2]:,}")
|
||||||
|
|
||||||
def bayar(self):
|
def bayar(self):
|
||||||
idx = self.order_list.curselection()
|
idx = self.listbox.curselection()
|
||||||
if not idx:
|
if not idx:
|
||||||
messagebox.showwarning("Pilih", "Pilih tagihan yang mau dibayar!")
|
messagebox.showwarning("Pilih Order", "Pilih order yang ingin dibayar!")
|
||||||
return
|
return
|
||||||
|
|
||||||
selected = self.data_orders[idx[0]]
|
order = self.data[idx[0]]
|
||||||
transaksi_id = selected[0]
|
order_id, nama, total = order
|
||||||
nama = selected[1]
|
|
||||||
total = selected[3]
|
|
||||||
|
|
||||||
confirm = messagebox.askyesno("Konfirmasi", f"Terima pembayaran Rp {int(total)} dari {nama}?")
|
# Simpan pembayaran di database (opsional, bisa buat tabel pembayaran)
|
||||||
if confirm:
|
db = connect()
|
||||||
db = connect()
|
cur = db.cursor()
|
||||||
cur = db.cursor()
|
cur.execute("INSERT INTO pembayaran VALUES (NULL, ?, ?)", (order_id, total))
|
||||||
|
cur.execute("DELETE FROM orders WHERE id=?", (order_id,))
|
||||||
|
db.commit()
|
||||||
|
db.close()
|
||||||
|
|
||||||
# Update status jadi 'Paid' dan metode pembayaran (misal Cash default)
|
# Tampilkan struk
|
||||||
cur.execute("UPDATE transaksi SET status='Paid', metode_pembayaran='Cash' WHERE id=?", (transaksi_id,))
|
self.tampil_struk(order_id, nama, total)
|
||||||
|
|
||||||
db.commit()
|
# Update listbox
|
||||||
db.close()
|
self.load_orders()
|
||||||
|
|
||||||
messagebox.showinfo("Lunas", "Transaksi Selesai & Lunas!")
|
def tampil_struk(self, order_id, nama, total):
|
||||||
self.update_data()
|
win = tk.Toplevel(self.frame)
|
||||||
|
win.title("Struk Pembayaran")
|
||||||
|
|
||||||
|
tk.Label(win, text="STRUK PEMBAYARAN", font=("Arial",14,"bold")).pack(pady=5)
|
||||||
|
tk.Label(win, text=f"Order ID : {order_id}").pack()
|
||||||
|
tk.Label(win, text=f"Nama Menu: {nama}").pack()
|
||||||
|
tk.Label(win, text=f"Total : Rp {total:,}").pack()
|
||||||
|
tk.Label(win, text="Terima kasih 🙏").pack(pady=10)
|
||||||
|
tk.Button(win, text="Tutup", command=win.destroy).pack(pady=5)
|
||||||
|
|
||||||
|
def logout(self):
|
||||||
|
self.frame.destroy()
|
||||||
|
self.controller.show_frame("Login")
|
||||||
|
|||||||
@ -1,56 +1,46 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
from database import connect
|
from database import connect
|
||||||
|
from admin_menu import AdminMenu
|
||||||
|
from pembeli_menu import PembeliMenu
|
||||||
|
from kasir import KasirPage
|
||||||
|
from pemilik import PemilikPage
|
||||||
|
|
||||||
class LoginPage(tk.Frame):
|
class LoginPage:
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, root):
|
||||||
super().__init__(parent)
|
self.root = root
|
||||||
self.controller = controller
|
self.frame = tk.Frame(root)
|
||||||
|
self.frame.pack(expand=True)
|
||||||
|
|
||||||
# Center Content
|
tk.Label(self.frame, text="LOGIN CAFE", font=("Arial",20,"bold")).pack(pady=10)
|
||||||
center_frame = tk.Frame(self)
|
|
||||||
center_frame.place(relx=0.5, rely=0.5, anchor="center")
|
|
||||||
|
|
||||||
tk.Label(center_frame, text="LOGIN CAFE", font=("Arial", 20, "bold")).pack(pady=20)
|
self.user = tk.Entry(self.frame)
|
||||||
|
self.passw = tk.Entry(self.frame, show="*")
|
||||||
|
self.user.pack()
|
||||||
|
self.passw.pack()
|
||||||
|
|
||||||
tk.Label(center_frame, text="Username").pack(anchor="w")
|
tk.Button(self.frame, text="Login", command=self.login).pack(pady=5)
|
||||||
self.user = tk.Entry(center_frame, width=30)
|
|
||||||
self.user.pack(pady=5)
|
|
||||||
|
|
||||||
tk.Label(center_frame, text="Password").pack(anchor="w")
|
|
||||||
self.passw = tk.Entry(center_frame, show="*", width=30)
|
|
||||||
self.passw.pack(pady=5)
|
|
||||||
|
|
||||||
tk.Button(center_frame, text="Login", bg="#4CAF50", fg="white", width=20, command=self.login).pack(pady=20)
|
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
username = self.user.get()
|
|
||||||
password = self.passw.get()
|
|
||||||
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
cur.execute("SELECT role FROM users WHERE username=? AND password=?", (username, password))
|
cur.execute("SELECT role FROM users WHERE username=? AND password=?",
|
||||||
|
(self.user.get(), self.passw.get()))
|
||||||
res = cur.fetchone()
|
res = cur.fetchone()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
if not res:
|
if not res:
|
||||||
messagebox.showerror("Error", "Username/Password salah!")
|
messagebox.showerror("Error","Login gagal")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.frame.destroy()
|
||||||
role = res[0]
|
role = res[0]
|
||||||
|
|
||||||
# Reset input
|
if role=="admin":
|
||||||
self.user.delete(0, tk.END)
|
AdminMenu(self.root)
|
||||||
self.passw.delete(0, tk.END)
|
elif role=="pembeli":
|
||||||
|
PembeliMenu(self.root)
|
||||||
# Arahkan sesuai Role (Nama Class harus sama dengan di main.py)
|
elif role=="kasir":
|
||||||
if role == "admin":
|
KasirPage(self.root)
|
||||||
self.controller.show_frame("AdminPage")
|
elif role=="pemilik":
|
||||||
elif role == "pembeli":
|
PemilikPage(self.root)
|
||||||
self.controller.show_frame("PembeliMenu")
|
|
||||||
elif role == "kasir":
|
|
||||||
self.controller.show_frame("KasirPage")
|
|
||||||
elif role == "pemilik":
|
|
||||||
self.controller.show_frame("PemilikPage")
|
|
||||||
elif role == "waiter":
|
|
||||||
self.controller.show_frame("WaiterPage")
|
|
||||||
|
|||||||
@ -1,44 +1,60 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from database import setup_database
|
from database import setup_database, connect
|
||||||
|
from pembeli_menu import PembeliMenu
|
||||||
# Pastikan nama file dan nama class sesuai
|
|
||||||
from login import LoginPage
|
|
||||||
from admin_menu import AdminPage # Class diganti jadi AdminPage di file admin_menu
|
|
||||||
from pembeli_menu import PembeliMenu # Class tetap PembeliMenu
|
|
||||||
from kasir import KasirPage
|
from kasir import KasirPage
|
||||||
from pemilik import PemilikPage
|
from pemilik import PemilikPage
|
||||||
from waiter_dashboard import WaiterPage
|
from tkinter import messagebox
|
||||||
|
|
||||||
class CafeApp(tk.Tk):
|
# --- Login Screen ---
|
||||||
|
class LoginScreen:
|
||||||
|
def __init__(self, root):
|
||||||
|
self.root = root
|
||||||
|
self.frame = tk.Frame(root)
|
||||||
|
self.frame.pack(fill="both", expand=True)
|
||||||
|
|
||||||
|
tk.Label(self.frame,text="LOGIN SISTEM CAFE", font=("Arial",18,"bold")).pack(pady=20)
|
||||||
|
tk.Label(self.frame,text="Username").pack()
|
||||||
|
self.username_entry = tk.Entry(self.frame)
|
||||||
|
self.username_entry.pack()
|
||||||
|
tk.Label(self.frame,text="Password").pack()
|
||||||
|
self.password_entry = tk.Entry(self.frame, show="*")
|
||||||
|
self.password_entry.pack(pady=5)
|
||||||
|
tk.Button(self.frame,text="Login", bg="#cfe2ff", command=self.login).pack(pady=10)
|
||||||
|
|
||||||
|
def login(self):
|
||||||
|
username = self.username_entry.get()
|
||||||
|
password = self.password_entry.get()
|
||||||
|
|
||||||
|
db = connect()
|
||||||
|
cur = db.cursor()
|
||||||
|
cur.execute("SELECT role FROM users WHERE username=? AND password=?", (username,password))
|
||||||
|
result = cur.fetchone()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
if result:
|
||||||
|
role = result[0]
|
||||||
|
self.frame.destroy()
|
||||||
|
if role=="pembeli":
|
||||||
|
PembeliMenu(self.root)
|
||||||
|
elif role=="kasir":
|
||||||
|
KasirPage(self.root)
|
||||||
|
elif role=="pemilik":
|
||||||
|
PemilikPage(self.root)
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Error","Role tidak dikenali")
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Error","Username / Password salah")
|
||||||
|
|
||||||
|
# --- App ---
|
||||||
|
class App(tk.Tk):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.title("Sistem Manajemen Kafe")
|
self.title("Sistem Cafe")
|
||||||
self.geometry("1000x700")
|
self.geometry("700x600")
|
||||||
|
|
||||||
setup_database()
|
# --- Run Program ---
|
||||||
|
if __name__=="__main__":
|
||||||
self.container = tk.Frame(self)
|
setup_database()
|
||||||
self.container.pack(side="top", fill="both", expand=True)
|
app = App()
|
||||||
self.container.grid_rowconfigure(0, weight=1)
|
LoginScreen(app)
|
||||||
self.container.grid_columnconfigure(0, weight=1)
|
|
||||||
|
|
||||||
self.frames = {}
|
|
||||||
|
|
||||||
# Loop semua class halaman
|
|
||||||
for F in (LoginPage, AdminPage, PembeliMenu, KasirPage, PemilikPage, WaiterPage):
|
|
||||||
page_name = F.__name__
|
|
||||||
frame = F(parent=self.container, controller=self)
|
|
||||||
self.frames[page_name] = frame
|
|
||||||
frame.grid(row=0, column=0, sticky="nsew")
|
|
||||||
|
|
||||||
self.show_frame("LoginPage")
|
|
||||||
|
|
||||||
def show_frame(self, page_name):
|
|
||||||
frame = self.frames[page_name]
|
|
||||||
if hasattr(frame, "update_data"):
|
|
||||||
frame.update_data()
|
|
||||||
frame.tkraise()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app = CafeApp()
|
|
||||||
app.mainloop()
|
app.mainloop()
|
||||||
@ -1,177 +1,91 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import messagebox, simpledialog
|
|
||||||
from PIL import Image, ImageTk
|
from PIL import Image, ImageTk
|
||||||
import os
|
|
||||||
from database import connect
|
from database import connect
|
||||||
|
from tkinter import messagebox
|
||||||
|
|
||||||
class PembeliMenu(tk.Frame):
|
class PembeliMenu:
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, parent):
|
||||||
super().__init__(parent)
|
self.parent = parent
|
||||||
self.controller = controller
|
self.frame = tk.Frame(parent)
|
||||||
self.keranjang = [] # List untuk simpan belanjaan sementara
|
self.frame.pack(fill="both", expand=True)
|
||||||
self.image_refs = [] # Supaya gambar tidak hilang
|
|
||||||
|
|
||||||
# --- Layout Utama: Kiri (Menu) & Kanan (Keranjang) ---
|
|
||||||
|
|
||||||
# 1. Frame Kiri (Daftar Menu)
|
self.cart = [] # Simpan tuple (nama, harga)
|
||||||
self.left_frame = tk.Frame(self)
|
self.images = [] # Simpan reference gambar agar tidak dihapus GC
|
||||||
self.left_frame.pack(side="left", fill="both", expand=True)
|
|
||||||
|
|
||||||
# Header Kiri
|
# --- Judul Halaman ---
|
||||||
header = tk.Frame(self.left_frame, bg="#2c3e50", height=50)
|
tk.Label(self.frame, text="MENU PEMBELI", font=("Arial", 18, "bold")).pack(pady=10)
|
||||||
header.pack(fill="x")
|
|
||||||
tk.Label(header, text="DAFTAR MENU", font=("Arial", 14, "bold"), fg="white", bg="#2c3e50").pack(pady=10)
|
|
||||||
|
|
||||||
# Canvas untuk Scroll Menu
|
# --- Tombol Logout ---
|
||||||
self.canvas = tk.Canvas(self.left_frame)
|
tk.Button(self.frame, text="Logout", bg="#f9e79f", command=self.logout).pack(pady=5)
|
||||||
self.scrollbar = tk.Scrollbar(self.left_frame, orient="vertical", command=self.canvas.yview)
|
|
||||||
self.scrollable_frame = tk.Frame(self.canvas)
|
|
||||||
|
|
||||||
self.scrollable_frame.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))
|
# --- Frame Menu ---
|
||||||
self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
|
self.menu_frame = tk.Frame(self.frame)
|
||||||
self.canvas.configure(yscrollcommand=self.scrollbar.set)
|
self.menu_frame.pack(pady=10)
|
||||||
|
|
||||||
self.canvas.pack(side="left", fill="both", expand=True)
|
self.load_menu() # Load menu dari database
|
||||||
self.scrollbar.pack(side="right", fill="y")
|
|
||||||
|
|
||||||
# 2. Frame Kanan (Keranjang Belanja)
|
# --- Daftar Pesanan ---
|
||||||
self.right_frame = tk.Frame(self, bg="#ecf0f1", width=300)
|
tk.Label(self.frame, text="Daftar Pesanan:", font=("Arial", 12, "bold")).pack(pady=5)
|
||||||
self.right_frame.pack(side="right", fill="y")
|
self.listbox = tk.Listbox(self.frame, width=50, height=6)
|
||||||
self.right_frame.pack_propagate(False) # Agar lebar tetap 300px
|
self.listbox.pack()
|
||||||
|
|
||||||
tk.Label(self.right_frame, text="KERANJANG SAYA", font=("Arial", 12, "bold"), bg="#bdc3c7", pady=10).pack(fill="x")
|
# --- Total ---
|
||||||
|
self.total_lbl = tk.Label(self.frame, text="Total: Rp 0", font=("Arial", 12, "bold"))
|
||||||
|
self.total_lbl.pack(pady=5)
|
||||||
|
|
||||||
# Listbox Keranjang
|
# --- Tombol Checkout ---
|
||||||
self.cart_listbox = tk.Listbox(self.right_frame, font=("Arial", 10))
|
tk.Button(self.frame, text="Checkout", bg="#d1e7dd", command=self.checkout).pack(pady=5)
|
||||||
self.cart_listbox.pack(fill="both", expand=True, padx=10, pady=10)
|
|
||||||
|
|
||||||
# Label Total Harga
|
|
||||||
self.total_label = tk.Label(self.right_frame, text="Total: Rp 0", font=("Arial", 14, "bold"), bg="#ecf0f1", fg="#e74c3c")
|
|
||||||
self.total_label.pack(pady=10)
|
|
||||||
|
|
||||||
# Tombol Aksi
|
|
||||||
tk.Button(self.right_frame, text="Hapus Item Terpilih", bg="#e67e22", fg="white", command=self.hapus_item).pack(fill="x", padx=10, pady=5)
|
|
||||||
tk.Button(self.right_frame, text="CHECKOUT / BAYAR", bg="#27ae60", fg="white", font=("Arial", 10, "bold"), height=2, command=self.checkout).pack(fill="x", padx=10, pady=20)
|
|
||||||
tk.Button(self.right_frame, text="Kembali / Logout", command=lambda: controller.show_frame("LoginPage")).pack(pady=5)
|
|
||||||
|
|
||||||
def update_data(self):
|
|
||||||
"""Dipanggil saat halaman dibuka"""
|
|
||||||
self.load_menu()
|
|
||||||
self.keranjang = [] # Reset keranjang tiap login baru
|
|
||||||
self.update_keranjang_ui()
|
|
||||||
|
|
||||||
def load_menu(self):
|
def load_menu(self):
|
||||||
# Bersihkan area menu
|
|
||||||
for widget in self.scrollable_frame.winfo_children():
|
|
||||||
widget.destroy()
|
|
||||||
self.image_refs.clear()
|
|
||||||
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
cur.execute("SELECT * FROM menu")
|
cur.execute("SELECT nama, harga, gambar FROM menu")
|
||||||
items = cur.fetchall()
|
data = cur.fetchall()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
columns = 3
|
for i, (nama, harga, gambar) in enumerate(data):
|
||||||
for index, item in enumerate(items):
|
f = tk.Frame(self.menu_frame, bd=2, relief="ridge")
|
||||||
self.create_card(item, index, columns)
|
f.grid(row=i//3, column=i%3, padx=10, pady=10)
|
||||||
|
|
||||||
def create_card(self, item, index, columns):
|
try:
|
||||||
id_menu, nama, kategori, harga, stok, file_gambar = item
|
img = Image.open(gambar).resize((120, 90))
|
||||||
row = index // columns
|
photo = ImageTk.PhotoImage(img)
|
||||||
col = index % columns
|
self.images.append(photo)
|
||||||
|
tk.Label(f, image=photo).pack()
|
||||||
|
except FileNotFoundError:
|
||||||
|
tk.Label(f, text="No Image").pack()
|
||||||
|
|
||||||
card = tk.Frame(self.scrollable_frame, bd=2, relief="groove", bg="white")
|
tk.Label(f, text=nama).pack()
|
||||||
card.grid(row=row, column=col, padx=5, pady=5, sticky="nsew")
|
tk.Label(f, text=f"Rp {harga:,}").pack()
|
||||||
|
tk.Button(f, text="Pesan", bg="#cfe2ff",
|
||||||
|
command=lambda n=nama, h=harga: self.add(n, h)).pack(pady=3)
|
||||||
|
|
||||||
# Load Gambar
|
def add(self, nama, harga):
|
||||||
path = os.path.join("aset", file_gambar)
|
self.cart.append((nama, harga))
|
||||||
try:
|
self.listbox.insert(tk.END, f"{nama} - Rp {harga:,}")
|
||||||
img = Image.open(path).resize((120, 80), Image.Resampling.LANCZOS)
|
total = sum(h for _, h in self.cart)
|
||||||
photo = ImageTk.PhotoImage(img)
|
self.total_lbl.config(text=f"Total: Rp {total:,}")
|
||||||
self.image_refs.append(photo)
|
|
||||||
tk.Label(card, image=photo, bg="white").pack(pady=5)
|
|
||||||
except:
|
|
||||||
tk.Label(card, text="[No Image]", bg="#eee", height=4).pack(pady=5)
|
|
||||||
|
|
||||||
tk.Label(card, text=nama, font=("Arial", 10, "bold"), bg="white").pack()
|
|
||||||
tk.Label(card, text=f"Rp {int(harga):,}", fg="green", bg="white").pack()
|
|
||||||
|
|
||||||
# Tombol Tambah
|
|
||||||
state = "normal" if stok > 0 else "disabled"
|
|
||||||
text_btn = "Tambah" if stok > 0 else "Habis"
|
|
||||||
tk.Button(card, text=text_btn, bg="#3498db", fg="white", state=state,
|
|
||||||
command=lambda: self.tambah_ke_keranjang(item)).pack(pady=5, padx=5, fill="x")
|
|
||||||
|
|
||||||
def tambah_ke_keranjang(self, item):
|
|
||||||
# item = (id, nama, kategori, harga, stok, gambar)
|
|
||||||
self.keranjang.append(item)
|
|
||||||
self.update_keranjang_ui()
|
|
||||||
|
|
||||||
def update_keranjang_ui(self):
|
|
||||||
self.cart_listbox.delete(0, tk.END)
|
|
||||||
total = 0
|
|
||||||
for item in self.keranjang:
|
|
||||||
nama = item[1]
|
|
||||||
harga = item[3]
|
|
||||||
self.cart_listbox.insert(tk.END, f"{nama} - Rp {int(harga):,}")
|
|
||||||
total += harga
|
|
||||||
|
|
||||||
self.total_label.config(text=f"Total: Rp {int(total):,}")
|
|
||||||
|
|
||||||
def hapus_item(self):
|
|
||||||
selected = self.cart_listbox.curselection()
|
|
||||||
if not selected:
|
|
||||||
return
|
|
||||||
index = selected[0]
|
|
||||||
del self.keranjang[index]
|
|
||||||
self.update_keranjang_ui()
|
|
||||||
|
|
||||||
def checkout(self):
|
def checkout(self):
|
||||||
if not self.keranjang:
|
if not self.cart:
|
||||||
messagebox.showwarning("Kosong", "Keranjang masih kosong!")
|
messagebox.showwarning("Pesan Kosong", "Belum ada pesanan!")
|
||||||
return
|
return
|
||||||
|
|
||||||
nama_pelanggan = simpledialog.askstring("Input", "Masukkan Nama Pelanggan:")
|
|
||||||
if not nama_pelanggan: return
|
|
||||||
|
|
||||||
total_harga = sum(item[3] for item in self.keranjang)
|
|
||||||
|
|
||||||
# Simpan ke Database
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
|
for nama, harga in self.cart:
|
||||||
|
cur.execute("INSERT INTO orders VALUES (NULL, ?, ?)", (nama, harga))
|
||||||
|
db.commit()
|
||||||
|
db.close()
|
||||||
|
|
||||||
try:
|
messagebox.showinfo("Sukses", "Pesanan dikirim ke kasir")
|
||||||
# 1. Simpan Transaksi Utama
|
self.cart.clear()
|
||||||
cur.execute("""
|
self.listbox.delete(0, tk.END)
|
||||||
INSERT INTO transaksi (nama_pelanggan, total, status)
|
self.total_lbl.config(text="Total: Rp 0")
|
||||||
VALUES (?, ?, 'Pending')
|
|
||||||
""", (nama_pelanggan, total_harga))
|
|
||||||
transaksi_id = cur.lastrowid
|
|
||||||
|
|
||||||
# 2. Simpan Detail Transaksi (Looping item di keranjang)
|
def logout(self):
|
||||||
for item in self.keranjang:
|
self.frame.destroy()
|
||||||
menu_id = item[0]
|
from main import LoginScreen
|
||||||
harga = item[3]
|
LoginScreen(self.parent)
|
||||||
# Masukkan ke detail
|
|
||||||
cur.execute("""
|
|
||||||
INSERT INTO detail_transaksi (transaksi_id, menu_id, jumlah, subtotal)
|
|
||||||
VALUES (?, ?, 1, ?)
|
|
||||||
""", (transaksi_id, menu_id, harga))
|
|
||||||
|
|
||||||
# Kurangi Stok Menu
|
|
||||||
cur.execute("UPDATE menu SET stok = stok - 1 WHERE id = ?", (menu_id,))
|
|
||||||
|
|
||||||
db.commit()
|
|
||||||
messagebox.showinfo("Berhasil", "Pesanan berhasil dibuat! Silakan bayar di kasir.")
|
|
||||||
|
|
||||||
# Reset
|
|
||||||
self.keranjang = []
|
|
||||||
self.update_keranjang_ui()
|
|
||||||
self.load_menu() # Reload menu untuk update stok visual
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
db.rollback()
|
|
||||||
messagebox.showerror("Error", f"Gagal Checkout: {e}")
|
|
||||||
finally:
|
|
||||||
db.close()
|
|
||||||
@ -1,43 +1,38 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from database import connect
|
from database import connect
|
||||||
|
|
||||||
class PemilikPage(tk.Frame):
|
class PemilikPage:
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, parent, controller):
|
||||||
super().__init__(parent)
|
self.parent = parent
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
self.frame = tk.Frame(parent)
|
||||||
|
self.frame.pack(fill="both", expand=True)
|
||||||
|
|
||||||
# --- PERBAIKAN: Baris self.pack() sudah DIHAPUS ---
|
tk.Label(self.frame, text="LAPORAN PENJUALAN", font=("Arial", 18, "bold")).pack(pady=10)
|
||||||
# Kita tidak boleh packing diri sendiri karena main.py sudah mengatur posisi kita pakai Grid.
|
|
||||||
|
|
||||||
# Judul Halaman
|
# Label untuk total penjualan
|
||||||
tk.Label(self, text="LAPORAN PENJUALAN", font=("Arial", 18, "bold")).pack(pady=20)
|
self.total_lbl = tk.Label(self.frame, text="Total Penjualan: Rp 0", font=("Arial", 14, "bold"))
|
||||||
|
self.total_lbl.pack(pady=5)
|
||||||
|
|
||||||
# Label Total
|
# Tombol Refresh
|
||||||
self.total_lbl = tk.Label(self, text="Total Pendapatan: Rp 0", font=("Arial", 20, "bold"), fg="green")
|
tk.Button(self.frame, text="Refresh", bg="#cfe2ff", command=self.load).pack(pady=5)
|
||||||
self.total_lbl.pack(pady=20)
|
|
||||||
|
|
||||||
tk.Label(self, text="(Menghitung semua transaksi berstatus 'Paid')", fg="gray").pack()
|
# Tombol Logout
|
||||||
|
tk.Button(self.frame, text="Logout", bg="#f9e79f", command=self.logout).pack(pady=5)
|
||||||
|
|
||||||
# Tombol-tombol
|
# Load data awal
|
||||||
tk.Button(self, text="Refresh Laporan", bg="#cfe2ff", command=self.load).pack(pady=10)
|
|
||||||
tk.Button(self, text="Logout", bg="#f9e79f", command=lambda: controller.show_frame("LoginPage")).pack(pady=10)
|
|
||||||
|
|
||||||
def update_data(self):
|
|
||||||
"""Dipanggil otomatis saat halaman dibuka"""
|
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
"""Ambil data total penjualan dari database"""
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
|
# Jumlahkan semua total pembayaran dari tabel pembayaran
|
||||||
# Hitung sum total dari transaksi yang sudah Paid (Lunas)
|
cur.execute("SELECT SUM(total) FROM pembayaran")
|
||||||
cur.execute("SELECT SUM(total) FROM transaksi WHERE status='Paid'")
|
total = cur.fetchone()[0] or 0
|
||||||
result = cur.fetchone()[0]
|
|
||||||
|
|
||||||
# Kalau belum ada penjualan, set 0
|
|
||||||
total = result if result else 0
|
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
# Update tampilan
|
self.total_lbl.config(text=f"Total Penjualan: Rp {total:,}")
|
||||||
self.total_lbl.config(text=f"Total Pendapatan: Rp {int(total):,}")
|
|
||||||
|
def logout(self):
|
||||||
|
self.frame.destroy()
|
||||||
|
self.controller.show_frame("Login")
|
||||||
|
|||||||
@ -1,60 +1,10 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import messagebox
|
|
||||||
from database import connect
|
|
||||||
|
|
||||||
class WaiterPage(tk.Frame):
|
class WaiterDashboard(tk.Frame):
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, parent, controller):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.controller = controller
|
|
||||||
|
|
||||||
# Header
|
tk.Label(self, text="WAITER", font=("Arial", 20, "bold")).pack(pady=20)
|
||||||
top = tk.Frame(self, bg="#FF9800")
|
tk.Label(self, text="(Input pesanan manual)").pack()
|
||||||
top.pack(fill="x")
|
|
||||||
tk.Label(top, text="WAITER DASHBOARD", font=("Arial", 16, "bold"), bg="#FF9800", fg="white").pack(side="left", padx=10, pady=10)
|
|
||||||
tk.Button(top, text="Logout", command=lambda: controller.show_frame("LoginPage")).pack(side="right", padx=10)
|
|
||||||
|
|
||||||
# List Pesanan
|
tk.Button(self, text="Logout", command=lambda: controller.show_frame("Login")).pack(pady=10)
|
||||||
tk.Label(self, text="Pesanan Status: PENDING (Perlu Diantar)", font=("Arial", 12, "bold")).pack(pady=10)
|
|
||||||
|
|
||||||
self.list_orders = tk.Listbox(self, width=80, height=15, font=("Arial", 10))
|
|
||||||
self.list_orders.pack(pady=5)
|
|
||||||
|
|
||||||
btn_frame = tk.Frame(self)
|
|
||||||
btn_frame.pack(pady=10)
|
|
||||||
|
|
||||||
tk.Button(btn_frame, text="Refresh Data", command=self.update_data).pack(side="left", padx=5)
|
|
||||||
tk.Button(btn_frame, text="✅ Selesai Diantar (Served)", bg="#81C784", command=self.mark_served).pack(side="left", padx=5)
|
|
||||||
|
|
||||||
def update_data(self):
|
|
||||||
self.list_orders.delete(0, tk.END)
|
|
||||||
self.data_orders = []
|
|
||||||
|
|
||||||
db = connect()
|
|
||||||
cur = db.cursor()
|
|
||||||
# Ambil Transaksi yang statusnya Pending
|
|
||||||
cur.execute("SELECT id, nama_pelanggan, meja_id, total FROM transaksi WHERE status='Pending'")
|
|
||||||
self.data_orders = cur.fetchall()
|
|
||||||
db.close()
|
|
||||||
|
|
||||||
for item in self.data_orders:
|
|
||||||
# item: (id, nama, meja, total)
|
|
||||||
self.list_orders.insert(tk.END, f"ID Transaksi: {item[0]} | Meja: {item[2]} | A.N: {item[1]} | Total: Rp {int(item[3])}")
|
|
||||||
|
|
||||||
def mark_served(self):
|
|
||||||
idx = self.list_orders.curselection()
|
|
||||||
if not idx:
|
|
||||||
messagebox.showwarning("Pilih", "Pilih pesanan dulu!")
|
|
||||||
return
|
|
||||||
|
|
||||||
selected = self.data_orders[idx[0]]
|
|
||||||
transaksi_id = selected[0]
|
|
||||||
|
|
||||||
db = connect()
|
|
||||||
cur = db.cursor()
|
|
||||||
# Update Status Transaksi jadi Served
|
|
||||||
cur.execute("UPDATE transaksi SET status='Served' WHERE id=?", (transaksi_id,))
|
|
||||||
db.commit()
|
|
||||||
db.close()
|
|
||||||
|
|
||||||
messagebox.showinfo("Sukses", "Pesanan Meja selesai dilayani!")
|
|
||||||
self.update_data()
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user