This commit is contained in:
Nathan 2025-12-15 01:21:00 +07:00
commit f62c4904cd
2 changed files with 78 additions and 39 deletions

View File

@ -1,5 +1,4 @@
import sqlite3 import sqlite3
import datetime
def connect(): def connect():
return sqlite3.connect("cafe.db") return sqlite3.connect("cafe.db")
@ -24,12 +23,11 @@ def setup_database():
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT, nama TEXT,
harga REAL, harga REAL,
gambar TEXT, gambar TEXT
kategori TEXT
) )
""") """)
# Tabel Transaksi (Header nota) # Tabel 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,
@ -39,9 +37,8 @@ def setup_database():
status TEXT status TEXT
) )
""") """)
# Status: 'Pending' (Masuk Dapur), 'Disajikan' (Waiter selesai), 'Lunas' (Kasir)
# Tabel Detail Transaksi (Isi makanan per nota) # Tabel Detail Transaksi
cur.execute(""" cur.execute("""
CREATE TABLE IF NOT EXISTS detail_transaksi( CREATE TABLE IF NOT EXISTS detail_transaksi(
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@ -53,7 +50,7 @@ def setup_database():
) )
""") """)
# Insert Akun Default jika kosong # Insert Akun 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 = [
@ -66,11 +63,18 @@ def setup_database():
cur.executemany("INSERT INTO users(username,password,role) VALUES (?,?,?)", users) cur.executemany("INSERT INTO users(username,password,role) VALUES (?,?,?)", users)
db.commit() db.commit()
# Insert Menu Dummy jika kosong # --- UPDATE DAFTAR MENU SESUAI FOLDER ASET ---
cur.execute("SELECT COUNT(*) FROM menu") cur.execute("SELECT COUNT(*) FROM menu")
if cur.fetchone()[0] == 0: if cur.fetchone()[0] == 0:
cur.execute("INSERT INTO menu (nama, harga, gambar) VALUES ('Mie Ayam', 15000, 'mie_ayam.webp')") menus = [
cur.execute("INSERT INTO menu (nama, harga, gambar) VALUES ('Es Teh', 5000, 'es_teh.webp')") ('Ayam Goreng', 20000, 'aset/ayam_goreng.jpg'),
('Bakso', 15000, 'aset/bakso.jpg'),
('Es Teh', 5000, 'aset/es_teh.jpg'),
('Es Teler', 15000, 'aset/es_teler.jpg'),
('Jus Jeruk', 8000, 'aset/jus_jeruk.jpg'),
('Mie Ayam', 12000, 'aset/mie_ayam.jpg')
]
cur.executemany("INSERT INTO menu (nama, harga, gambar) VALUES (?,?,?)", menus)
db.commit() db.commit()
db.close() db.close()

View File

@ -1,8 +1,9 @@
import tkinter as tk import tkinter as tk
from tkinter import messagebox from tkinter import messagebox, ttk # Tambahkan ttk untuk Dropdown
from PIL import Image, ImageTk from PIL import Image, ImageTk
from database import connect from database import connect
import datetime import datetime
import os
class PembeliMenu: class PembeliMenu:
def __init__(self, parent): def __init__(self, parent):
@ -10,8 +11,8 @@ class PembeliMenu:
self.frame = tk.Frame(parent) self.frame = tk.Frame(parent)
self.frame.pack(fill="both", expand=True) self.frame.pack(fill="both", expand=True)
self.cart = [] # List untuk menyimpan belanjaan sementara self.cart = []
self.images = [] # List untuk reference gambar agar tidak hilang self.images = []
# --- Header --- # --- Header ---
tk.Label(self.frame, text="SELAMAT DATANG", font=("Arial", 18, "bold")).pack(pady=10) tk.Label(self.frame, text="SELAMAT DATANG", font=("Arial", 18, "bold")).pack(pady=10)
@ -24,9 +25,19 @@ class PembeliMenu:
self.entry_nama = tk.Entry(info_frame) self.entry_nama = tk.Entry(info_frame)
self.entry_nama.grid(row=0, column=1, padx=5) self.entry_nama.grid(row=0, column=1, padx=5)
tk.Label(info_frame, text="No. Meja:").grid(row=0, column=2, sticky="e") # --- LOGIKA PILIHAN MEJA (Update Disini) ---
self.entry_meja = tk.Entry(info_frame, width=5) tk.Label(info_frame, text="Pilih Meja:").grid(row=0, column=2, sticky="e")
self.entry_meja.grid(row=0, column=3, padx=5)
# 1. Siapkan variabel untuk dropdown
self.meja_var = tk.StringVar()
self.combo_meja = ttk.Combobox(info_frame, textvariable=self.meja_var, state="readonly", width=5)
self.combo_meja.grid(row=0, column=3, padx=5)
# 2. Isi dropdown dengan meja yang KOSONG saja
self.refresh_available_tables()
# Tombol Refresh Meja (jika kasir baru saja menyelesaikan pembayaran meja lain)
tk.Button(info_frame, text="🔄", command=self.refresh_available_tables, bd=1).grid(row=0, column=4, padx=2)
# Tombol Kembali # Tombol Kembali
tk.Button(self.frame, text="Kembali ke Utama", bg="#f9e79f", command=self.logout).pack(pady=5) tk.Button(self.frame, text="Kembali ke Utama", bg="#f9e79f", command=self.logout).pack(pady=5)
@ -41,7 +52,7 @@ class PembeliMenu:
self.listbox = tk.Listbox(self.frame, width=50, height=6) self.listbox = tk.Listbox(self.frame, width=50, height=6)
self.listbox.pack() self.listbox.pack()
# [BARU] Tombol Hapus Item # Tombol Hapus Item
tk.Button(self.frame, text="❌ Hapus Item Terpilih", fg="red", font=("Arial", 9), command=self.hapus_item_cart).pack(pady=2) tk.Button(self.frame, text="❌ Hapus Item Terpilih", fg="red", font=("Arial", 9), command=self.hapus_item_cart).pack(pady=2)
self.total_lbl = tk.Label(self.frame, text="Total: Rp 0", font=("Arial", 12, "bold")) self.total_lbl = tk.Label(self.frame, text="Total: Rp 0", font=("Arial", 12, "bold"))
@ -49,6 +60,30 @@ class PembeliMenu:
tk.Button(self.frame, text="✅ KIRIM PESANAN", bg="#d1e7dd", font=("Arial", 11, "bold"), command=self.checkout).pack(pady=10) tk.Button(self.frame, text="✅ KIRIM PESANAN", bg="#d1e7dd", font=("Arial", 11, "bold"), command=self.checkout).pack(pady=10)
# --- FUNGSI BARU: CEK MEJA KOSONG ---
def refresh_available_tables(self):
# Anggap kita punya Meja nomor 1 sampai 10
total_meja = [str(i) for i in range(1, 11)]
db = connect()
cur = db.cursor()
# Cari meja yang statusnya BELUM 'Selesai' (artinya masih ada orang)
# Kita cek status != 'Selesai' agar yang 'Pending' atau 'Dimasak' dianggap terisi
cur.execute("SELECT DISTINCT meja_id FROM transaksi WHERE status != 'Selesai'")
terisi = [str(row[0]) for row in cur.fetchall()]
db.close()
# Filter: Meja yang tersedia adalah Total Meja dikurangi Meja Terisi
tersedia = [m for m in total_meja if m not in terisi]
if not tersedia:
self.combo_meja['values'] = ["Penuh"]
self.combo_meja.set("Penuh")
else:
self.combo_meja['values'] = tersedia
self.combo_meja.current(0) # Pilih otomatis yang pertama tersedia
def load_menu(self): def load_menu(self):
db = connect() db = connect()
cur = db.cursor() cur = db.cursor()
@ -66,12 +101,15 @@ class PembeliMenu:
f.pack(side=tk.LEFT, padx=5) f.pack(side=tk.LEFT, padx=5)
try: try:
if os.path.exists(gambar):
img = Image.open(gambar).resize((100, 80)) img = Image.open(gambar).resize((100, 80))
photo = ImageTk.PhotoImage(img) photo = ImageTk.PhotoImage(img)
self.images.append(photo) self.images.append(photo)
tk.Label(f, image=photo).pack() tk.Label(f, image=photo).pack()
except: else:
tk.Label(f, text="[No Image]").pack() tk.Label(f, text="[Img Not Found]").pack()
except Exception as e:
tk.Label(f, text="Error").pack()
tk.Label(f, text=nama, font=("Arial",10,"bold")).pack() tk.Label(f, text=nama, font=("Arial",10,"bold")).pack()
tk.Label(f, text=f"Rp {harga:,.0f}").pack() tk.Label(f, text=f"Rp {harga:,.0f}").pack()
@ -81,22 +119,14 @@ class PembeliMenu:
self.cart.append({'nama': nama, 'harga': harga}) self.cart.append({'nama': nama, 'harga': harga})
self.refresh_cart() self.refresh_cart()
# [BARU] Fungsi Logic Hapus
def hapus_item_cart(self): def hapus_item_cart(self):
# Ambil index item yang dipilih di listbox
idx = self.listbox.curselection() idx = self.listbox.curselection()
if not idx: if not idx:
messagebox.showwarning("Peringatan", "Pilih menu di keranjang yang ingin dihapus!") messagebox.showwarning("Peringatan", "Pilih menu di keranjang yang ingin dihapus!")
return return
index = idx[0] index = idx[0]
# Hapus data dari list cart self.cart.pop(index)
item_removed = self.cart.pop(index)
# Update tampilan listbox dan total harga
self.refresh_cart() self.refresh_cart()
# Opsional: Tampilkan pesan kecil di console atau status bar (disini saya skip biar tidak ganggu user)
def refresh_cart(self): def refresh_cart(self):
self.listbox.delete(0, tk.END) self.listbox.delete(0, tk.END)
@ -108,10 +138,13 @@ class PembeliMenu:
def checkout(self): def checkout(self):
nama_pemesan = self.entry_nama.get() nama_pemesan = self.entry_nama.get()
meja = self.entry_meja.get() meja = self.combo_meja.get() # Ambil dari dropdown
if not nama_pemesan or not meja: if not nama_pemesan:
messagebox.showwarning("Data Kurang", "Mohon isi Nama dan Nomor Meja!") messagebox.showwarning("Data Kurang", "Mohon isi Nama Anda!")
return
if not meja or meja == "Penuh":
messagebox.showwarning("Penuh", "Mohon maaf, meja penuh atau belum dipilih.")
return return
if not self.cart: if not self.cart:
messagebox.showwarning("Kosong", "Pilih menu dulu!") messagebox.showwarning("Kosong", "Pilih menu dulu!")
@ -123,10 +156,10 @@ class PembeliMenu:
db = connect() db = connect()
cur = db.cursor() cur = db.cursor()
# Menyimpan nama pemesan di dalam string tanggal (Trik agar tidak ubah struktur DB) # Simpan nama pemesan di string tanggal agar terlihat di Kasir
# Format: "2023-12-15 10:00:00 (Budi)"
tanggal_custom = f"{tanggal} ({nama_pemesan})" tanggal_custom = f"{tanggal} ({nama_pemesan})"
# Status 'Pending' berarti meja ini sekarang TERISI (Occupied)
cur.execute("INSERT INTO transaksi (tanggal, total, meja_id, status) VALUES (?, ?, ?, ?)", cur.execute("INSERT INTO transaksi (tanggal, total, meja_id, status) VALUES (?, ?, ?, ?)",
(tanggal_custom, total_belanja, meja, "Pending")) (tanggal_custom, total_belanja, meja, "Pending"))
@ -139,11 +172,13 @@ class PembeliMenu:
db.commit() db.commit()
db.close() db.close()
messagebox.showinfo("Berhasil", f"Pesanan a.n {nama_pemesan} berhasil dikirim ke Dapur!") messagebox.showinfo("Berhasil", f"Pesanan a.n {nama_pemesan} di Meja {meja} berhasil dikirim!")
self.cart.clear() self.cart.clear()
self.refresh_cart() self.refresh_cart()
self.entry_nama.delete(0, tk.END) self.entry_nama.delete(0, tk.END)
self.entry_meja.delete(0, tk.END)
# Refresh lagi mejanya supaya Meja yang baru dipakai langsung hilang dari daftar
self.refresh_available_tables()
def logout(self): def logout(self):
self.frame.destroy() self.frame.destroy()