Compare commits
No commits in common. "2bc30165e2d8654de91438542c7dc55ab4404d85" and "1bb52206cc86eff84b49514662e3d22255045f54" have entirely different histories.
2bc30165e2
...
1bb52206cc
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.
@ -4,21 +4,27 @@ from database import connect
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
class AdminPage(tk.Frame): # Ganti nama class jadi AdminPage
|
# GANTI NAMA CLASS JADI AdminPage
|
||||||
|
class AdminPage(tk.Frame):
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, parent, controller):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.selected_image_path = None
|
self.selected_image_path = None
|
||||||
|
self.data_menu = []
|
||||||
|
|
||||||
# --- Header ---
|
# --- Header ---
|
||||||
top = tk.Frame(self, bg="#333")
|
top = tk.Frame(self, bg="#333")
|
||||||
top.pack(fill="x")
|
top.pack(fill="x")
|
||||||
tk.Label(top, text="ADMIN DASHBOARD", font=("Arial", 16, "bold"), fg="white", bg="#333").pack(side="left", padx=10, pady=10)
|
tk.Label(top, text="ADMIN DASHBOARD", font=("Arial", 16, "bold"), fg="white", bg="#333").pack(side="left", padx=10, pady=10)
|
||||||
tk.Button(top, text="Logout", bg="#ff6b6b", command=lambda: self.controller.show_frame("LoginPage")).pack(side="right", padx=10)
|
tk.Button(top, text="Logout", bg="#ff6b6b", command=lambda: controller.show_frame("LoginPage")).pack(side="right", padx=10)
|
||||||
|
|
||||||
# --- Form Input (Kiri) ---
|
# --- Layout Kiri (Form) & Kanan (Tabel) ---
|
||||||
left_frame = tk.Frame(self, padx=10, pady=10)
|
main_content = tk.Frame(self)
|
||||||
left_frame.pack(side="left", fill="y")
|
main_content.pack(fill="both", expand=True, padx=10, pady=10)
|
||||||
|
|
||||||
|
# --- KIRI ---
|
||||||
|
left_frame = tk.Frame(main_content)
|
||||||
|
left_frame.pack(side="left", fill="y", padx=10)
|
||||||
|
|
||||||
tk.Label(left_frame, text="Nama Menu:").pack(anchor="w")
|
tk.Label(left_frame, text="Nama Menu:").pack(anchor="w")
|
||||||
self.entry_nama = tk.Entry(left_frame, width=30)
|
self.entry_nama = tk.Entry(left_frame, width=30)
|
||||||
@ -30,6 +36,7 @@ class AdminPage(tk.Frame): # Ganti nama class jadi AdminPage
|
|||||||
|
|
||||||
tk.Label(left_frame, text="Stok Awal:").pack(anchor="w")
|
tk.Label(left_frame, text="Stok Awal:").pack(anchor="w")
|
||||||
self.entry_stok = tk.Entry(left_frame, width=30)
|
self.entry_stok = tk.Entry(left_frame, width=30)
|
||||||
|
self.entry_stok.insert(0, "100") # Default stok
|
||||||
self.entry_stok.pack(pady=5)
|
self.entry_stok.pack(pady=5)
|
||||||
|
|
||||||
tk.Label(left_frame, text="Gambar:").pack(anchor="w")
|
tk.Label(left_frame, text="Gambar:").pack(anchor="w")
|
||||||
@ -38,17 +45,16 @@ class AdminPage(tk.Frame): # Ganti nama class jadi AdminPage
|
|||||||
self.lbl_img_path = tk.Label(left_frame, text="Belum ada gambar", fg="gray", font=("Arial", 8))
|
self.lbl_img_path = tk.Label(left_frame, text="Belum ada gambar", fg="gray", font=("Arial", 8))
|
||||||
self.lbl_img_path.pack(anchor="w")
|
self.lbl_img_path.pack(anchor="w")
|
||||||
|
|
||||||
# Tombol Aksi
|
|
||||||
btn_box = tk.Frame(left_frame, pady=20)
|
btn_box = tk.Frame(left_frame, pady=20)
|
||||||
btn_box.pack()
|
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="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)
|
tk.Button(btn_box, text="HAPUS", bg="#f44336", fg="white", command=self.delete_menu).grid(row=0, column=1, padx=5)
|
||||||
|
|
||||||
# --- Tabel Menu (Kanan) ---
|
# --- KANAN ---
|
||||||
right_frame = tk.Frame(self, padx=10, pady=10)
|
right_frame = tk.Frame(main_content)
|
||||||
right_frame.pack(side="right", fill="both", expand=True)
|
right_frame.pack(side="right", fill="both", expand=True)
|
||||||
|
|
||||||
tk.Label(right_frame, text="Daftar Menu Database:", font=("Arial", 10, "bold")).pack(anchor="w")
|
tk.Label(right_frame, text="Daftar Menu:", font=("Arial", 10, "bold")).pack(anchor="w")
|
||||||
|
|
||||||
self.list_menu = tk.Listbox(right_frame)
|
self.list_menu = tk.Listbox(right_frame)
|
||||||
self.list_menu.pack(fill="both", expand=True)
|
self.list_menu.pack(fill="both", expand=True)
|
||||||
@ -73,7 +79,7 @@ class AdminPage(tk.Frame): # Ganti nama class jadi AdminPage
|
|||||||
self.list_menu.insert(tk.END, f"{row[1]} - Rp {int(row[2])} (Stok: {row[3]})")
|
self.list_menu.insert(tk.END, f"{row[1]} - Rp {int(row[2])} (Stok: {row[3]})")
|
||||||
|
|
||||||
def browse_image(self):
|
def browse_image(self):
|
||||||
filename = filedialog.askopenfilename(title="Pilih Gambar", filetypes=[("Image Files", "*.png;*.jpg;*.jpeg")])
|
filename = filedialog.askopenfilename(title="Pilih Gambar", filetypes=[("Images", "*.png;*.jpg;*.jpeg")])
|
||||||
if filename:
|
if filename:
|
||||||
self.selected_image_path = filename
|
self.selected_image_path = filename
|
||||||
self.lbl_img_path.config(text=os.path.basename(filename), fg="black")
|
self.lbl_img_path.config(text=os.path.basename(filename), fg="black")
|
||||||
@ -90,21 +96,20 @@ class AdminPage(tk.Frame): # Ganti nama class jadi AdminPage
|
|||||||
final_image_path = "default.png"
|
final_image_path = "default.png"
|
||||||
if self.selected_image_path:
|
if self.selected_image_path:
|
||||||
if not os.path.exists("img"): os.makedirs("img")
|
if not os.path.exists("img"): os.makedirs("img")
|
||||||
nama_file_asli = os.path.basename(self.selected_image_path)
|
destinasi = os.path.join("img", os.path.basename(self.selected_image_path))
|
||||||
destinasi = os.path.join("img", nama_file_asli)
|
try:
|
||||||
shutil.copy(self.selected_image_path, destinasi)
|
shutil.copy(self.selected_image_path, destinasi)
|
||||||
final_image_path = destinasi
|
final_image_path = destinasi
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
try:
|
try:
|
||||||
cur.execute("INSERT INTO menu (nama, harga, stok, gambar) VALUES (?, ?, ?, ?)",
|
cur.execute("INSERT INTO menu (nama, harga, stok, gambar) VALUES (?, ?, ?, ?)",
|
||||||
(nama, harga, stok if stok else 0, final_image_path))
|
(nama, harga, stok, final_image_path))
|
||||||
db.commit()
|
db.commit()
|
||||||
messagebox.showinfo("Sukses", "Menu berhasil ditambahkan!")
|
messagebox.showinfo("Sukses", "Menu berhasil ditambahkan!")
|
||||||
self.entry_nama.delete(0, tk.END)
|
|
||||||
self.entry_harga.delete(0, tk.END)
|
|
||||||
self.entry_stok.delete(0, tk.END)
|
|
||||||
self.update_data()
|
self.update_data()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
messagebox.showerror("Error", str(e))
|
messagebox.showerror("Error", str(e))
|
||||||
@ -113,14 +118,12 @@ class AdminPage(tk.Frame): # Ganti nama class jadi AdminPage
|
|||||||
|
|
||||||
def delete_menu(self):
|
def delete_menu(self):
|
||||||
idx = self.list_menu.curselection()
|
idx = self.list_menu.curselection()
|
||||||
if not idx:
|
if not idx: return
|
||||||
messagebox.showwarning("Pilih", "Pilih menu dulu!")
|
|
||||||
return
|
|
||||||
|
|
||||||
id_menu = self.data_menu[idx[0]][0]
|
selected = self.data_menu[idx[0]]
|
||||||
if messagebox.askyesno("Hapus", "Yakin hapus menu ini?"):
|
if messagebox.askyesno("Hapus", f"Hapus {selected[1]}?"):
|
||||||
db = connect()
|
db = connect()
|
||||||
db.cursor().execute("DELETE FROM menu WHERE id=?", (id_menu,))
|
db.cursor().execute("DELETE FROM menu WHERE id=?", (selected[0],))
|
||||||
db.commit()
|
db.commit()
|
||||||
db.close()
|
db.close()
|
||||||
self.update_data()
|
self.update_data()
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
# File: database.py
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
def connect():
|
def connect():
|
||||||
@ -29,7 +30,7 @@ def setup_database():
|
|||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# 3. Transaksi (Header)
|
# 3. Transaksi
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS transaksi(
|
CREATE TABLE IF NOT EXISTS transaksi(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@ -41,7 +42,6 @@ def setup_database():
|
|||||||
status TEXT DEFAULT 'Pending'
|
status TEXT DEFAULT 'Pending'
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
# Status Flow: 'Pending' (Dipesan) -> 'Served' (Diantar Waiter) -> 'Paid' (Dibayar di Kasir)
|
|
||||||
|
|
||||||
# 4. Detail Transaksi
|
# 4. Detail Transaksi
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
@ -54,7 +54,7 @@ def setup_database():
|
|||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Seeding Data User Dummy
|
# Seeding User (Kalau kosong diisi 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 = [
|
||||||
@ -68,7 +68,7 @@ def setup_database():
|
|||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
db.close()
|
db.close()
|
||||||
print("Database Ready bos!")
|
print("Database Ready!")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
setup_database()
|
setup_database()
|
||||||
@ -1,49 +1,32 @@
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
import os
|
|
||||||
# PERHATIKAN: Ini harus setup_database, BUKAN init_db
|
|
||||||
from database import setup_database
|
|
||||||
|
|
||||||
def isi_data_awal():
|
def isi_data_awal():
|
||||||
# 1. Pastikan database dan tabel sudah dibuat
|
conn = sqlite3.connect("cafe.db")
|
||||||
setup_database()
|
|
||||||
|
|
||||||
db_name = "cafe.db"
|
|
||||||
|
|
||||||
# 2. Cek folder aset
|
|
||||||
# Pastikan kamu punya folder bernama 'aset' dan di dalamnya ada gambar-gambarnya
|
|
||||||
if not os.path.exists("aset"):
|
|
||||||
print("❌ WADUH! Folder 'aset' gak ketemu. Pastikan nama folder di kiri adalah 'aset'.")
|
|
||||||
return
|
|
||||||
|
|
||||||
conn = sqlite3.connect(db_name)
|
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
|
|
||||||
print("♻️ Membersihkan data lama...")
|
# Hapus data lama biar gak dobel (opsional, biar bersih)
|
||||||
cur.execute("DELETE FROM menu")
|
cur.execute("DELETE FROM menu")
|
||||||
cur.execute("DELETE FROM sqlite_sequence WHERE name='menu'") # Reset ID jadi 1
|
|
||||||
|
|
||||||
# 3. Data Menu (Path gambar pakai 'aset/')
|
# Data Menu (Sesuaikan nama file gambar dengan yang ada di folder aset kamu)
|
||||||
menus = [
|
menus = [
|
||||||
("Ayam Goreng", "Makanan", 15000, 20, "aset/ayam_goreng.jpg"),
|
# (Nama, Kategori, Harga, Stok, Nama File Gambar)
|
||||||
("Bakso Urat", "Makanan", 12000, 15, "aset/bakso.jpg"),
|
("Ayam Goreng", "Makanan", 15000, 20, "ayam_goreng.jpg"),
|
||||||
("Mie Ayam", "Makanan", 10000, 25, "aset/mie_ayam.jpg"),
|
("Bakso Urat", "Makanan", 12000, 15, "bakso.jpg"),
|
||||||
("Es Teh Manis", "Minuman", 3000, 50, "aset/es_teh.jpg"),
|
("Mie Ayam", "Makanan", 10000, 25, "mie_ayam.jpg"),
|
||||||
("Jus Jeruk", "Minuman", 5000, 30, "aset/jus_jeruk.jpg"),
|
("Es Teh Manis", "Minuman", 3000, 50, "es_teh.jpg"),
|
||||||
|
("Jus Jeruk", "Minuman", 5000, 30, "jus_jeruk.jpg"),
|
||||||
]
|
]
|
||||||
|
|
||||||
print("📥 Sedang mengisi data menu...")
|
print("Sedang mengisi data menu...")
|
||||||
|
|
||||||
try:
|
|
||||||
cur.executemany("""
|
cur.executemany("""
|
||||||
INSERT INTO menu (nama, kategori, harga, stok, gambar)
|
INSERT INTO menu (nama, kategori, harga, stok, gambar)
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?)
|
||||||
""", menus)
|
""", menus)
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
print("✅ MANTAP! Data menu berhasil masuk. Sekarang jalankan main.py!")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Error: {e}")
|
|
||||||
finally:
|
|
||||||
conn.close()
|
conn.close()
|
||||||
|
print("✅ Berhasil! Data menu sudah masuk database.")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
isi_data_awal()
|
isi_data_awal()
|
||||||
@ -13,13 +13,13 @@ class KasirPage(tk.Frame):
|
|||||||
tk.Button(top, text="Logout", command=lambda: controller.show_frame("LoginPage")).pack(side="right", padx=10, pady=5)
|
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)
|
tk.Label(top, text="KASIR - PEMBAYARAN", font=("Arial", 16, "bold"), bg="#ddd").pack(side="left", padx=10)
|
||||||
|
|
||||||
# List
|
# List Order
|
||||||
tk.Label(self, text="Tagihan Belum Bayar (Status: Served):", font=("Arial", 11)).pack(pady=10)
|
tk.Label(self, text="Tagihan Belum Lunas (Status: Served):", font=("Arial", 11)).pack(pady=10)
|
||||||
self.order_list = tk.Listbox(self, width=80, height=15)
|
self.order_list = tk.Listbox(self, width=80, height=15, font=("Arial", 10))
|
||||||
self.order_list.pack(pady=5)
|
self.order_list.pack(pady=5)
|
||||||
|
|
||||||
tk.Button(self, text="Refresh Data", command=self.update_data).pack(pady=5)
|
tk.Button(self, text="Refresh Data", command=self.update_data).pack(pady=5)
|
||||||
tk.Button(self, text="💰 PROSES BAYAR & LUNAS", bg="#81C784", height=2, command=self.bayar).pack(fill="x", padx=20, pady=20)
|
tk.Button(self, text="💰 PROSES BAYAR (LUNAS)", bg="#81C784", height=2, command=self.bayar).pack(fill="x", padx=50, pady=20)
|
||||||
|
|
||||||
def update_data(self):
|
def update_data(self):
|
||||||
self.order_list.delete(0, tk.END)
|
self.order_list.delete(0, tk.END)
|
||||||
@ -27,33 +27,32 @@ class KasirPage(tk.Frame):
|
|||||||
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
# Kasir melihat yang sudah diantar (Served) tapi belum bayar
|
# Kasir melihat yang statusnya Served
|
||||||
cur.execute("SELECT id, nama_pelanggan, meja_id, total FROM transaksi WHERE status='Served'")
|
cur.execute("SELECT id, nama_pelanggan, meja_id, total FROM transaksi WHERE status='Served'")
|
||||||
self.data_orders = cur.fetchall()
|
self.data_orders = cur.fetchall()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
for item in self.data_orders:
|
for item in self.data_orders:
|
||||||
self.order_list.insert(tk.END, f"ID Transaksi: {item[0]} | Meja {item[2]} | {item[1]} | Tagihan: Rp {int(item[3]):,}")
|
self.order_list.insert(tk.END, f"ID: {item[0]} | Meja {item[2]} | {item[1]} | Tagihan: Rp {int(item[3])}")
|
||||||
|
|
||||||
def bayar(self):
|
def bayar(self):
|
||||||
idx = self.order_list.curselection()
|
idx = self.order_list.curselection()
|
||||||
if not idx:
|
if not idx:
|
||||||
messagebox.showwarning("Pilih", "Pilih tagihan dulu!")
|
messagebox.showwarning("Pilih", "Pilih tagihan yang mau dibayar!")
|
||||||
return
|
return
|
||||||
|
|
||||||
selected = self.data_orders[idx[0]]
|
selected = self.data_orders[idx[0]]
|
||||||
trans_id = selected[0]
|
transaksi_id = selected[0]
|
||||||
|
nama = selected[1]
|
||||||
total = selected[3]
|
total = selected[3]
|
||||||
|
|
||||||
# Konfirmasi
|
confirm = messagebox.askyesno("Konfirmasi", f"Terima pembayaran Rp {int(total)} dari {nama}?")
|
||||||
if not messagebox.askyesno("Konfirmasi", f"Terima pembayaran sebesar Rp {int(total):,}?"):
|
if confirm:
|
||||||
return
|
|
||||||
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
|
|
||||||
# Update status jadi 'Paid'
|
# Update status jadi 'Paid' dan metode pembayaran (misal Cash default)
|
||||||
cur.execute("UPDATE transaksi SET status='Paid', metode_pembayaran='CASH' WHERE id=?", (trans_id,))
|
cur.execute("UPDATE transaksi SET status='Paid', metode_pembayaran='Cash' WHERE id=?", (transaksi_id,))
|
||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
db.close()
|
db.close()
|
||||||
|
|||||||
@ -2,57 +2,52 @@ import tkinter as tk
|
|||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
from database import connect
|
from database import connect
|
||||||
|
|
||||||
# Pastikan import ini sesuai
|
|
||||||
from admin_menu import AdminPage
|
|
||||||
from pembeli_menu import PembeliPage
|
|
||||||
from kasir import KasirPage
|
|
||||||
from pemilik import PemilikPage
|
|
||||||
from waiter_dashboard import WaiterPage
|
|
||||||
|
|
||||||
class LoginPage(tk.Frame):
|
class LoginPage(tk.Frame):
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, parent, controller):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
|
||||||
tk.Label(self, text="LOGIN SYSTEM", font=("Arial", 20, "bold")).pack(pady=40)
|
# Center Content
|
||||||
|
center_frame = tk.Frame(self)
|
||||||
|
center_frame.place(relx=0.5, rely=0.5, anchor="center")
|
||||||
|
|
||||||
frame_login = tk.Frame(self)
|
tk.Label(center_frame, text="LOGIN CAFE", font=("Arial", 20, "bold")).pack(pady=20)
|
||||||
frame_login.pack()
|
|
||||||
|
|
||||||
tk.Label(frame_login, text="Username:").pack()
|
tk.Label(center_frame, text="Username").pack(anchor="w")
|
||||||
self.user = tk.Entry(frame_login)
|
self.user = tk.Entry(center_frame, width=30)
|
||||||
self.user.pack(pady=5)
|
self.user.pack(pady=5)
|
||||||
|
|
||||||
tk.Label(frame_login, text="Password:").pack()
|
tk.Label(center_frame, text="Password").pack(anchor="w")
|
||||||
self.passw = tk.Entry(frame_login, show="*")
|
self.passw = tk.Entry(center_frame, show="*", width=30)
|
||||||
self.passw.pack(pady=5)
|
self.passw.pack(pady=5)
|
||||||
|
|
||||||
tk.Button(frame_login, text="LOGIN", command=self.login, width=20, bg="#2196F3", fg="white").pack(pady=20)
|
tk.Button(center_frame, text="Login", bg="#4CAF50", fg="white", width=20, command=self.login).pack(pady=20)
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
u = self.user.get()
|
username = self.user.get()
|
||||||
p = self.passw.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=?", (u, p))
|
cur.execute("SELECT role FROM users WHERE username=? AND password=?", (username, password))
|
||||||
res = cur.fetchone()
|
res = cur.fetchone()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
if not res:
|
if not res:
|
||||||
messagebox.showerror("Gagal", "Username/Password salah!")
|
messagebox.showerror("Error", "Username/Password salah!")
|
||||||
return
|
return
|
||||||
|
|
||||||
role = res[0]
|
role = res[0]
|
||||||
|
|
||||||
# Reset input
|
# Reset input
|
||||||
self.user.delete(0, tk.END)
|
self.user.delete(0, tk.END)
|
||||||
self.passw.delete(0, tk.END)
|
self.passw.delete(0, tk.END)
|
||||||
|
|
||||||
# Redirect sesuai Role
|
# Arahkan sesuai Role (Nama Class harus sama dengan di main.py)
|
||||||
if role == "admin":
|
if role == "admin":
|
||||||
self.controller.show_frame("AdminPage")
|
self.controller.show_frame("AdminPage")
|
||||||
elif role == "pembeli":
|
elif role == "pembeli":
|
||||||
self.controller.show_frame("PembeliPage")
|
self.controller.show_frame("PembeliMenu")
|
||||||
elif role == "kasir":
|
elif role == "kasir":
|
||||||
self.controller.show_frame("KasirPage")
|
self.controller.show_frame("KasirPage")
|
||||||
elif role == "pemilik":
|
elif role == "pemilik":
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from database import setup_database
|
from database import setup_database
|
||||||
|
|
||||||
# Import class yang sudah kita benerin namanya
|
# Pastikan nama file dan nama class sesuai
|
||||||
from login import LoginPage
|
from login import LoginPage
|
||||||
from admin_menu import AdminPage
|
from admin_menu import AdminPage # Class diganti jadi AdminPage di file admin_menu
|
||||||
from pembeli_menu import PembeliPage
|
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 waiter_dashboard import WaiterPage
|
||||||
@ -12,10 +12,10 @@ from waiter_dashboard import WaiterPage
|
|||||||
class CafeApp(tk.Tk):
|
class CafeApp(tk.Tk):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.title("Sistem Manajemen Kafe Python")
|
self.title("Sistem Manajemen Kafe")
|
||||||
self.geometry("1000x700")
|
self.geometry("1000x700")
|
||||||
|
|
||||||
setup_database() # Auto bikin tabel
|
setup_database()
|
||||||
|
|
||||||
self.container = tk.Frame(self)
|
self.container = tk.Frame(self)
|
||||||
self.container.pack(side="top", fill="both", expand=True)
|
self.container.pack(side="top", fill="both", expand=True)
|
||||||
@ -24,8 +24,8 @@ class CafeApp(tk.Tk):
|
|||||||
|
|
||||||
self.frames = {}
|
self.frames = {}
|
||||||
|
|
||||||
# Loop semua halaman
|
# Loop semua class halaman
|
||||||
for F in (LoginPage, AdminPage, PembeliPage, KasirPage, PemilikPage, WaiterPage):
|
for F in (LoginPage, AdminPage, PembeliMenu, KasirPage, PemilikPage, WaiterPage):
|
||||||
page_name = F.__name__
|
page_name = F.__name__
|
||||||
frame = F(parent=self.container, controller=self)
|
frame = F(parent=self.container, controller=self)
|
||||||
self.frames[page_name] = frame
|
self.frames[page_name] = frame
|
||||||
|
|||||||
@ -1,169 +1,177 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import messagebox, ttk
|
from tkinter import messagebox, simpledialog
|
||||||
|
from PIL import Image, ImageTk
|
||||||
|
import os
|
||||||
from database import connect
|
from database import connect
|
||||||
|
|
||||||
class PembeliPage(tk.Frame): # Ganti nama class jadi PembeliPage
|
class PembeliMenu(tk.Frame):
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, parent, controller):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.cart = {}
|
self.keranjang = [] # List untuk simpan belanjaan sementara
|
||||||
self.nama_pelanggan = ""
|
self.image_refs = [] # Supaya gambar tidak hilang
|
||||||
self.no_meja = ""
|
|
||||||
|
|
||||||
self.login_frame = tk.Frame(self)
|
# --- Layout Utama: Kiri (Menu) & Kanan (Keranjang) ---
|
||||||
self.menu_frame = tk.Frame(self)
|
|
||||||
self.show_login_ui()
|
|
||||||
|
|
||||||
# --- UI 1: LOGIN PEMBELI ---
|
# 1. Frame Kiri (Daftar Menu)
|
||||||
def show_login_ui(self):
|
self.left_frame = tk.Frame(self)
|
||||||
self.menu_frame.pack_forget()
|
self.left_frame.pack(side="left", fill="both", expand=True)
|
||||||
self.login_frame.pack(fill="both", expand=True)
|
|
||||||
|
|
||||||
for w in self.login_frame.winfo_children(): w.destroy()
|
# Header Kiri
|
||||||
|
header = tk.Frame(self.left_frame, bg="#2c3e50", height=50)
|
||||||
|
header.pack(fill="x")
|
||||||
|
tk.Label(header, text="DAFTAR MENU", font=("Arial", 14, "bold"), fg="white", bg="#2c3e50").pack(pady=10)
|
||||||
|
|
||||||
tk.Label(self.login_frame, text="SELAMAT DATANG", font=("Arial", 20, "bold")).pack(pady=50)
|
# Canvas untuk Scroll Menu
|
||||||
|
self.canvas = tk.Canvas(self.left_frame)
|
||||||
|
self.scrollbar = tk.Scrollbar(self.left_frame, orient="vertical", command=self.canvas.yview)
|
||||||
|
self.scrollable_frame = tk.Frame(self.canvas)
|
||||||
|
|
||||||
box = tk.Frame(self.login_frame, bd=2, relief="groove", padx=20, pady=20)
|
self.scrollable_frame.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))
|
||||||
box.pack()
|
self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
|
||||||
|
self.canvas.configure(yscrollcommand=self.scrollbar.set)
|
||||||
|
|
||||||
tk.Label(box, text="Nama Anda:").pack(anchor="w")
|
self.canvas.pack(side="left", fill="both", expand=True)
|
||||||
self.entry_nama = tk.Entry(box, width=30)
|
self.scrollbar.pack(side="right", fill="y")
|
||||||
self.entry_nama.pack(pady=5)
|
|
||||||
|
|
||||||
tk.Label(box, text="Nomor Meja:").pack(anchor="w")
|
# 2. Frame Kanan (Keranjang Belanja)
|
||||||
self.combo_meja = ttk.Combobox(box, values=[str(i) for i in range(1, 21)], state="readonly")
|
self.right_frame = tk.Frame(self, bg="#ecf0f1", width=300)
|
||||||
self.combo_meja.current(0)
|
self.right_frame.pack(side="right", fill="y")
|
||||||
self.combo_meja.pack(pady=5)
|
self.right_frame.pack_propagate(False) # Agar lebar tetap 300px
|
||||||
|
|
||||||
tk.Button(box, text="MULAI PESAN", bg="#4CAF50", fg="white", command=self.validate_login).pack(pady=20, fill="x")
|
tk.Label(self.right_frame, text="KERANJANG SAYA", font=("Arial", 12, "bold"), bg="#bdc3c7", pady=10).pack(fill="x")
|
||||||
tk.Button(self.login_frame, text="Kembali", command=lambda: self.controller.show_frame("LoginPage")).pack(pady=10)
|
|
||||||
|
|
||||||
def validate_login(self):
|
# Listbox Keranjang
|
||||||
if not self.entry_nama.get():
|
self.cart_listbox = tk.Listbox(self.right_frame, font=("Arial", 10))
|
||||||
messagebox.showwarning("Oops", "Nama wajib diisi!")
|
self.cart_listbox.pack(fill="both", expand=True, padx=10, pady=10)
|
||||||
return
|
|
||||||
self.nama_pelanggan = self.entry_nama.get()
|
|
||||||
self.no_meja = self.combo_meja.get()
|
|
||||||
self.show_menu_ui()
|
|
||||||
|
|
||||||
# --- UI 2: MENU MAKANAN ---
|
# Label Total Harga
|
||||||
def show_menu_ui(self):
|
self.total_label = tk.Label(self.right_frame, text="Total: Rp 0", font=("Arial", 14, "bold"), bg="#ecf0f1", fg="#e74c3c")
|
||||||
self.login_frame.pack_forget()
|
self.total_label.pack(pady=10)
|
||||||
self.menu_frame.pack(fill="both", expand=True)
|
|
||||||
|
|
||||||
# Bersihkan frame lama biar gak numpuk
|
# Tombol Aksi
|
||||||
for w in self.menu_frame.winfo_children(): w.destroy()
|
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)
|
||||||
|
|
||||||
# Header
|
def update_data(self):
|
||||||
top = tk.Frame(self.menu_frame, bg="#eee", pady=10)
|
"""Dipanggil saat halaman dibuka"""
|
||||||
top.pack(fill="x")
|
self.load_menu()
|
||||||
tk.Label(top, text=f"👤 {self.nama_pelanggan} | Meja {self.no_meja}", font=("Arial", 12)).pack(side="left", padx=20)
|
self.keranjang = [] # Reset keranjang tiap login baru
|
||||||
tk.Button(top, text="Keluar", bg="#ff6b6b", fg="white", command=self.logout).pack(side="right", padx=20)
|
self.update_keranjang_ui()
|
||||||
|
|
||||||
content = tk.Frame(self.menu_frame)
|
def load_menu(self):
|
||||||
content.pack(fill="both", expand=True, padx=10, pady=10)
|
# Bersihkan area menu
|
||||||
|
for widget in self.scrollable_frame.winfo_children():
|
||||||
# Kiri: Daftar Menu
|
widget.destroy()
|
||||||
left_frame = tk.LabelFrame(content, text=" Menu Tersedia ")
|
self.image_refs.clear()
|
||||||
left_frame.pack(side="left", fill="both", expand=True)
|
|
||||||
|
|
||||||
canvas = tk.Canvas(left_frame)
|
|
||||||
scrollbar = tk.Scrollbar(left_frame, orient="vertical", command=canvas.yview)
|
|
||||||
self.scroll_frame = tk.Frame(canvas)
|
|
||||||
|
|
||||||
self.scroll_frame.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
|
|
||||||
canvas.create_window((0, 0), window=self.scroll_frame, anchor="nw")
|
|
||||||
canvas.configure(yscrollcommand=scrollbar.set)
|
|
||||||
|
|
||||||
canvas.pack(side="left", fill="both", expand=True)
|
|
||||||
scrollbar.pack(side="right", fill="y")
|
|
||||||
|
|
||||||
# Kanan: Keranjang
|
|
||||||
right_frame = tk.LabelFrame(content, text=" Keranjang ")
|
|
||||||
right_frame.pack(side="right", fill="both", width=300, padx=5)
|
|
||||||
|
|
||||||
self.cart_list = tk.Listbox(right_frame)
|
|
||||||
self.cart_list.pack(fill="both", expand=True, padx=5, pady=5)
|
|
||||||
|
|
||||||
self.lbl_total = tk.Label(right_frame, text="Total: Rp 0", font=("Arial", 14, "bold"), fg="red")
|
|
||||||
self.lbl_total.pack(pady=5)
|
|
||||||
|
|
||||||
tk.Button(right_frame, text="PESAN SEKARANG", bg="green", fg="white", height=2, command=self.checkout).pack(fill="x", padx=5, pady=5)
|
|
||||||
|
|
||||||
self.load_menu_items()
|
|
||||||
|
|
||||||
def load_menu_items(self):
|
|
||||||
for w in self.scroll_frame.winfo_children(): w.destroy()
|
|
||||||
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
cur.execute("SELECT id, nama, harga, stok FROM menu WHERE stok > 0")
|
cur.execute("SELECT * FROM menu")
|
||||||
items = cur.fetchall()
|
items = cur.fetchall()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
row, col = 0, 0
|
columns = 3
|
||||||
for item in items:
|
for index, item in enumerate(items):
|
||||||
m_id, nama, harga, stok = item
|
self.create_card(item, index, columns)
|
||||||
card = tk.Frame(self.scroll_frame, bd=2, relief="ridge", padx=5, pady=5)
|
|
||||||
|
def create_card(self, item, index, columns):
|
||||||
|
id_menu, nama, kategori, harga, stok, file_gambar = item
|
||||||
|
row = index // columns
|
||||||
|
col = index % columns
|
||||||
|
|
||||||
|
card = tk.Frame(self.scrollable_frame, bd=2, relief="groove", bg="white")
|
||||||
card.grid(row=row, column=col, padx=5, pady=5, sticky="nsew")
|
card.grid(row=row, column=col, padx=5, pady=5, sticky="nsew")
|
||||||
|
|
||||||
tk.Label(card, text=nama, font=("Arial", 10, "bold")).pack()
|
# Load Gambar
|
||||||
tk.Label(card, text=f"Rp {int(harga):,}", fg="green").pack()
|
path = os.path.join("aset", file_gambar)
|
||||||
tk.Button(card, text="Tambah +", command=lambda i=m_id, n=nama, h=harga: self.add_to_cart(i, n, h)).pack(pady=2)
|
try:
|
||||||
|
img = Image.open(path).resize((120, 80), Image.Resampling.LANCZOS)
|
||||||
|
photo = ImageTk.PhotoImage(img)
|
||||||
|
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)
|
||||||
|
|
||||||
col += 1
|
tk.Label(card, text=nama, font=("Arial", 10, "bold"), bg="white").pack()
|
||||||
if col > 2:
|
tk.Label(card, text=f"Rp {int(harga):,}", fg="green", bg="white").pack()
|
||||||
col = 0
|
|
||||||
row += 1
|
|
||||||
|
|
||||||
def add_to_cart(self, m_id, nama, harga):
|
# Tombol Tambah
|
||||||
if m_id in self.cart:
|
state = "normal" if stok > 0 else "disabled"
|
||||||
self.cart[m_id]['qty'] += 1
|
text_btn = "Tambah" if stok > 0 else "Habis"
|
||||||
else:
|
tk.Button(card, text=text_btn, bg="#3498db", fg="white", state=state,
|
||||||
self.cart[m_id] = {'nama': nama, 'harga': harga, 'qty': 1}
|
command=lambda: self.tambah_ke_keranjang(item)).pack(pady=5, padx=5, fill="x")
|
||||||
self.refresh_cart()
|
|
||||||
|
|
||||||
def refresh_cart(self):
|
def tambah_ke_keranjang(self, item):
|
||||||
self.cart_list.delete(0, tk.END)
|
# 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
|
total = 0
|
||||||
for m_id, item in self.cart.items():
|
for item in self.keranjang:
|
||||||
sub = item['harga'] * item['qty']
|
nama = item[1]
|
||||||
total += sub
|
harga = item[3]
|
||||||
self.cart_list.insert(tk.END, f"{item['qty']}x {item['nama']} = {sub:,}")
|
self.cart_listbox.insert(tk.END, f"{nama} - Rp {int(harga):,}")
|
||||||
self.lbl_total.config(text=f"Total: Rp {int(total):,}")
|
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.cart: return
|
if not self.keranjang:
|
||||||
|
messagebox.showwarning("Kosong", "Keranjang masih kosong!")
|
||||||
|
return
|
||||||
|
|
||||||
total_val = int(self.lbl_total.cget("text").replace("Total: Rp ","").replace(",",""))
|
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()
|
||||||
|
|
||||||
# Simpan ke tabel TRANSAKSI (Bukan orders)
|
try:
|
||||||
cur.execute("INSERT INTO transaksi (nama_pelanggan, meja_id, total, status) VALUES (?, ?, ?, 'Pending')",
|
# 1. Simpan Transaksi Utama
|
||||||
(self.nama_pelanggan, self.no_meja, total_val))
|
cur.execute("""
|
||||||
trans_id = cur.lastrowid
|
INSERT INTO transaksi (nama_pelanggan, total, status)
|
||||||
|
VALUES (?, ?, 'Pending')
|
||||||
|
""", (nama_pelanggan, total_harga))
|
||||||
|
transaksi_id = cur.lastrowid
|
||||||
|
|
||||||
# Simpan Detail
|
# 2. Simpan Detail Transaksi (Looping item di keranjang)
|
||||||
for m_id, item in self.cart.items():
|
for item in self.keranjang:
|
||||||
sub = item['harga'] * item['qty']
|
menu_id = item[0]
|
||||||
cur.execute("INSERT INTO detail_transaksi (transaksi_id, menu_id, jumlah, subtotal) VALUES (?,?,?,?)",
|
harga = item[3]
|
||||||
(trans_id, m_id, item['qty'], sub))
|
# Masukkan ke detail
|
||||||
# Kurangi Stok
|
cur.execute("""
|
||||||
cur.execute("UPDATE menu SET stok = stok - ? WHERE id=?", (item['qty'], m_id))
|
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()
|
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()
|
db.close()
|
||||||
|
|
||||||
messagebox.showinfo("Sukses", "Pesanan terkirim! Mohon tunggu.")
|
|
||||||
self.cart = {}
|
|
||||||
self.refresh_cart()
|
|
||||||
self.load_menu_items()
|
|
||||||
|
|
||||||
def logout(self):
|
|
||||||
self.cart = {}
|
|
||||||
self.show_login_ui()
|
|
||||||
|
|
||||||
def update_data(self):
|
|
||||||
self.show_login_ui()
|
|
||||||
@ -1,36 +1,43 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from database import connect
|
from database import connect
|
||||||
|
|
||||||
class PemilikPage(tk.Frame): # HARUS inherit tk.Frame
|
class PemilikPage(tk.Frame):
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, parent, controller):
|
||||||
super().__init__(parent) # Init parent class
|
super().__init__(parent)
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
|
||||||
tk.Label(self, text="LAPORAN PENJUALAN (OWNER)", font=("Arial", 18, "bold")).pack(pady=20)
|
# --- PERBAIKAN: Baris self.pack() sudah DIHAPUS ---
|
||||||
|
# Kita tidak boleh packing diri sendiri karena main.py sudah mengatur posisi kita pakai Grid.
|
||||||
|
|
||||||
self.box = tk.Frame(self, bd=2, relief="groove", padx=40, pady=40)
|
# Judul Halaman
|
||||||
self.box.pack()
|
tk.Label(self, text="LAPORAN PENJUALAN", font=("Arial", 18, "bold")).pack(pady=20)
|
||||||
|
|
||||||
# Label Total
|
# Label Total
|
||||||
self.total_lbl = tk.Label(self.box, text="Total Pendapatan: Rp 0", font=("Arial", 20, "bold"), fg="green")
|
self.total_lbl = tk.Label(self, text="Total Pendapatan: Rp 0", font=("Arial", 20, "bold"), fg="green")
|
||||||
self.total_lbl.pack(pady=10)
|
self.total_lbl.pack(pady=20)
|
||||||
|
|
||||||
self.count_lbl = tk.Label(self.box, text="Jumlah Transaksi: 0", font=("Arial", 12))
|
tk.Label(self, text="(Menghitung semua transaksi berstatus 'Paid')", fg="gray").pack()
|
||||||
self.count_lbl.pack(pady=5)
|
|
||||||
|
|
||||||
tk.Button(self, text="Refresh Laporan", bg="#cfe2ff", command=self.update_data).pack(pady=10)
|
# Tombol-tombol
|
||||||
tk.Button(self, text="Logout", bg="#f9e79f", command=lambda: controller.show_frame("LoginPage")).pack(pady=5)
|
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):
|
def update_data(self):
|
||||||
|
"""Dipanggil otomatis saat halaman dibuka"""
|
||||||
|
self.load()
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
"""Ambil data total penjualan dari database"""
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
# Hitung total dari transaksi yang statusnya 'Paid'
|
|
||||||
cur.execute("SELECT SUM(total), COUNT(id) FROM transaksi WHERE status='Paid'")
|
# Hitung sum total dari transaksi yang sudah Paid (Lunas)
|
||||||
res = cur.fetchone()
|
cur.execute("SELECT SUM(total) FROM transaksi WHERE status='Paid'")
|
||||||
|
result = cur.fetchone()[0]
|
||||||
|
|
||||||
|
# Kalau belum ada penjualan, set 0
|
||||||
|
total = result if result else 0
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
total_duit = res[0] if res[0] else 0
|
# Update tampilan
|
||||||
total_transaksi = res[1] if res[1] else 0
|
self.total_lbl.config(text=f"Total Pendapatan: Rp {int(total):,}")
|
||||||
|
|
||||||
self.total_lbl.config(text=f"Total Pendapatan: Rp {int(total_duit):,}")
|
|
||||||
self.count_lbl.config(text=f"Jumlah Transaksi Sukses: {total_transaksi}")
|
|
||||||
@ -13,16 +13,16 @@ class WaiterPage(tk.Frame):
|
|||||||
tk.Label(top, text="WAITER DASHBOARD", font=("Arial", 16, "bold"), bg="#FF9800", fg="white").pack(side="left", padx=10, pady=10)
|
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)
|
tk.Button(top, text="Logout", command=lambda: controller.show_frame("LoginPage")).pack(side="right", padx=10)
|
||||||
|
|
||||||
# Content
|
# List Pesanan
|
||||||
tk.Label(self, text="Pesanan Pending (Perlu Diantar):", font=("Arial", 12)).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)
|
self.list_orders = tk.Listbox(self, width=80, height=15, font=("Arial", 10))
|
||||||
self.list_orders.pack(pady=5)
|
self.list_orders.pack(pady=5)
|
||||||
|
|
||||||
btn_frame = tk.Frame(self)
|
btn_frame = tk.Frame(self)
|
||||||
btn_frame.pack(pady=10)
|
btn_frame.pack(pady=10)
|
||||||
|
|
||||||
tk.Button(btn_frame, text="Refresh", command=self.update_data).pack(side="left", padx=5)
|
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)
|
tk.Button(btn_frame, text="✅ Selesai Diantar (Served)", bg="#81C784", command=self.mark_served).pack(side="left", padx=5)
|
||||||
|
|
||||||
def update_data(self):
|
def update_data(self):
|
||||||
@ -31,14 +31,14 @@ class WaiterPage(tk.Frame):
|
|||||||
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
# Ambil transaksi yang statusnya 'Pending'
|
# Ambil Transaksi yang statusnya Pending
|
||||||
cur.execute("SELECT id, nama_pelanggan, meja_id, total FROM transaksi WHERE status='Pending'")
|
cur.execute("SELECT id, nama_pelanggan, meja_id, total FROM transaksi WHERE status='Pending'")
|
||||||
self.data_orders = cur.fetchall()
|
self.data_orders = cur.fetchall()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
for item in self.data_orders:
|
for item in self.data_orders:
|
||||||
# item = (id, nama, meja, total)
|
# item: (id, nama, meja, total)
|
||||||
self.list_orders.insert(tk.END, f"ID: {item[0]} | Meja: {item[2]} | A.N: {item[1]} | Total: Rp {int(item[3]):,}")
|
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):
|
def mark_served(self):
|
||||||
idx = self.list_orders.curselection()
|
idx = self.list_orders.curselection()
|
||||||
@ -46,14 +46,15 @@ class WaiterPage(tk.Frame):
|
|||||||
messagebox.showwarning("Pilih", "Pilih pesanan dulu!")
|
messagebox.showwarning("Pilih", "Pilih pesanan dulu!")
|
||||||
return
|
return
|
||||||
|
|
||||||
trans_id = self.data_orders[idx[0]][0]
|
selected = self.data_orders[idx[0]]
|
||||||
|
transaksi_id = selected[0]
|
||||||
|
|
||||||
db = connect()
|
db = connect()
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
# Update status jadi 'Served' biar muncul di Kasir
|
# Update Status Transaksi jadi Served
|
||||||
cur.execute("UPDATE transaksi SET status='Served' WHERE id=?", (trans_id,))
|
cur.execute("UPDATE transaksi SET status='Served' WHERE id=?", (transaksi_id,))
|
||||||
db.commit()
|
db.commit()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
messagebox.showinfo("Sukses", "Pesanan Meja ini sudah dilayani!")
|
messagebox.showinfo("Sukses", "Pesanan Meja selesai dilayani!")
|
||||||
self.update_data()
|
self.update_data()
|
||||||
Loading…
x
Reference in New Issue
Block a user