This commit is contained in:
Nathan 2025-12-15 01:10:04 +07:00
commit 40a0ed8d5b
5 changed files with 191 additions and 102 deletions

BIN
cafe.db

Binary file not shown.

View File

@ -1,4 +1,5 @@
import sqlite3
import datetime
def connect():
return sqlite3.connect("cafe.db")
@ -7,6 +8,7 @@ def setup_database():
db = connect()
cur = db.cursor()
# Tabel Users
cur.execute("""
CREATE TABLE IF NOT EXISTS users(
id INTEGER PRIMARY KEY AUTOINCREMENT,
@ -16,44 +18,59 @@ def setup_database():
)
""")
# Tabel Menu
cur.execute("""
CREATE TABLE IF NOT EXISTS menu(
id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT,
harga REAL,
gambar TEXT
gambar TEXT,
kategori TEXT
)
""")
# Tabel Transaksi (Header nota)
cur.execute("""
CREATE TABLE IF NOT EXISTS orders(
CREATE TABLE IF NOT EXISTS transaksi(
id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT,
harga REAL
tanggal TEXT,
total REAL,
meja_id INTEGER,
status TEXT
)
""")
# Status: 'Pending' (Masuk Dapur), 'Disajikan' (Waiter selesai), 'Lunas' (Kasir)
# Tabel Detail Transaksi (Isi makanan per nota)
cur.execute("""
CREATE TABLE IF NOT EXISTS pembayaran(
CREATE TABLE IF NOT EXISTS detail_transaksi(
id INTEGER PRIMARY KEY AUTOINCREMENT,
order_id INTEGER,
total REAL
transaksi_id INTEGER,
menu_nama TEXT,
harga REAL,
jumlah INTEGER,
subtotal REAL
)
""")
# Insert Akun Default jika kosong
cur.execute("SELECT COUNT(*) FROM users")
if cur.fetchone()[0] == 0:
users = [
("admin","admin","admin"),
("kasir","kasir","kasir"),
("pembeli","pembeli","pembeli"),
("pemilik","pemilik","pemilik"),
("waiter","waiter","waiter")
("waiter","waiter","waiter"),
("pemilik","pemilik","pemilik")
]
cur.executemany(
"INSERT INTO users(username,password,role) VALUES (?,?,?)",
users
)
cur.executemany("INSERT INTO users(username,password,role) VALUES (?,?,?)", users)
db.commit()
# Insert Menu Dummy jika kosong
cur.execute("SELECT COUNT(*) FROM menu")
if cur.fetchone()[0] == 0:
cur.execute("INSERT INTO menu (nama, harga, gambar) VALUES ('Mie Ayam', 15000, 'mie_ayam.webp')")
cur.execute("INSERT INTO menu (nama, harga, gambar) VALUES ('Es Teh', 5000, 'es_teh.webp')")
db.commit()
db.close()

View File

@ -5,72 +5,60 @@ from database import connect
class KasirPage:
def __init__(self, parent, controller):
self.parent = parent
self.controller = controller
self.frame = tk.Frame(parent)
self.frame.pack(fill="both", expand=True)
tk.Label(self.frame, text="KASIR PAGE", font=("Arial", 18, "bold")).pack(pady=10)
# Tombol Logout
tk.Label(self.frame, text="KASIR - PEMBAYARAN", font=("Arial", 18, "bold")).pack(pady=10)
tk.Button(self.frame, text="Logout", bg="#f9e79f", command=self.logout).pack(pady=5)
tk.Button(self.frame, text="Refresh", command=self.load_tagihan).pack()
# Listbox untuk menampilkan order
tk.Label(self.frame, text="Daftar Order:", font=("Arial", 12, "bold")).pack(pady=5)
self.listbox = tk.Listbox(self.frame, width=50, height=10)
tk.Label(self.frame, text="Daftar Tagihan (Status: Disajikan):", font=("Arial", 12)).pack(pady=5)
self.listbox = tk.Listbox(self.frame, width=60, height=10)
self.listbox.pack(pady=5)
# Tombol bayar
tk.Button(self.frame, text="Bayar", bg="#d1e7dd", command=self.bayar).pack(pady=5)
tk.Button(self.frame, text="Proses Pembayaran", bg="#d1e7dd", command=self.bayar).pack(pady=5)
self.load_orders() # Load order dari database saat awal
self.transaksi_data = []
self.load_tagihan()
def load_orders(self):
def load_tagihan(self):
self.listbox.delete(0, tk.END)
self.transaksi_data = []
db = connect()
cur = db.cursor()
cur.execute("SELECT id, nama, harga FROM orders")
self.data = cur.fetchall()
# Kasir hanya melihat yang sudah disajikan waiter
cur.execute("SELECT id, meja_id, total FROM transaksi WHERE status='Disajikan'")
rows = cur.fetchall()
db.close()
for order in self.data:
self.listbox.insert(tk.END, f"ID {order[0]}: {order[1]} - Rp {order[2]:,}")
for row in rows:
t_id, meja, total = row
self.listbox.insert(tk.END, f"Meja {meja} - ID Transaksi: {t_id} - Total: Rp {total:,.0f}")
self.transaksi_data.append(row)
def bayar(self):
idx = self.listbox.curselection()
if not idx:
messagebox.showwarning("Pilih Order", "Pilih order yang ingin dibayar!")
messagebox.showwarning("Pilih", "Pilih tagihan yang akan dibayar!")
return
order = self.data[idx[0]]
order_id, nama, total = order
t_id, meja, total = self.transaksi_data[idx[0]]
# Simpan pembayaran di database (opsional, bisa buat tabel pembayaran)
# Konfirmasi pembayaran
confirm = messagebox.askyesno("Konfirmasi", f"Bayar tagihan Meja {meja} sebesar Rp {total:,.0f}?")
if confirm:
db = connect()
cur = db.cursor()
cur.execute("INSERT INTO pembayaran VALUES (NULL, ?, ?)", (order_id, total))
cur.execute("DELETE FROM orders WHERE id=?", (order_id,))
# Ubah status menjadi Lunas
cur.execute("UPDATE transaksi SET status='Lunas' WHERE id=?", (t_id,))
db.commit()
db.close()
# Tampilkan struk
self.tampil_struk(order_id, nama, total)
# Update listbox
self.load_orders()
def tampil_struk(self, order_id, nama, total):
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)
messagebox.showinfo("Sukses", "Pembayaran Berhasil! Struk dicetak.")
self.load_tagihan()
def logout(self):
self.frame.destroy()
from main import LoginScreen
LoginScreen(self.parent)

View File

@ -1,7 +1,8 @@
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
from database import connect
from tkinter import messagebox
import datetime
class PembeliMenu:
def __init__(self, parent):
@ -9,33 +10,38 @@ class PembeliMenu:
self.frame = tk.Frame(parent)
self.frame.pack(fill="both", expand=True)
self.cart = [] # List dictionary: {'nama':, 'harga':, 'jumlah':}
self.images = []
self.cart = [] # Simpan tuple (nama, harga)
self.images = [] # Simpan reference gambar agar tidak dihapus GC
# Header
tk.Label(self.frame, text="MENU PELANGGAN", font=("Arial", 18, "bold")).pack(pady=10)
# --- Judul Halaman ---
tk.Label(self.frame, text="MENU PEMBELI", font=("Arial", 18, "bold")).pack(pady=10)
# --- INPUT NOMOR MEJA (Fitur Baru) ---
frame_meja = tk.Frame(self.frame)
frame_meja.pack(pady=5)
tk.Label(frame_meja, text="Nomor Meja: ").pack(side=tk.LEFT)
self.entry_meja = tk.Entry(frame_meja, width=5)
self.entry_meja.pack(side=tk.LEFT)
# --- Tombol Logout ---
# Logout
tk.Button(self.frame, text="Logout", bg="#f9e79f", command=self.logout).pack(pady=5)
# --- Frame Menu ---
# Area Menu & Cart
self.menu_frame = tk.Frame(self.frame)
self.menu_frame.pack(pady=10)
self.menu_frame.pack(pady=10, fill="both", expand=True)
self.load_menu() # Load menu dari database
# Load Menu
self.load_menu()
# --- Daftar Pesanan ---
tk.Label(self.frame, text="Daftar Pesanan:", font=("Arial", 12, "bold")).pack(pady=5)
# Listbox Keranjang
tk.Label(self.frame, text="Keranjang Pesanan:").pack()
self.listbox = tk.Listbox(self.frame, width=50, height=6)
self.listbox.pack()
# --- Total ---
self.total_lbl = tk.Label(self.frame, text="Total: Rp 0", font=("Arial", 12, "bold"))
self.total_lbl.pack(pady=5)
# --- Tombol Checkout ---
tk.Button(self.frame, text="Checkout", bg="#d1e7dd", command=self.checkout).pack(pady=5)
tk.Button(self.frame, text="PESAN SEKARANG", bg="#d1e7dd", command=self.checkout).pack(pady=10)
def load_menu(self):
db = connect()
@ -44,48 +50,74 @@ class PembeliMenu:
data = cur.fetchall()
db.close()
row_frame = None
for i, (nama, harga, gambar) in enumerate(data):
f = tk.Frame(self.menu_frame, bd=2, relief="ridge")
f.grid(row=i//3, column=i%3, padx=10, pady=10)
if i % 3 == 0:
row_frame = tk.Frame(self.menu_frame)
row_frame.pack()
f = tk.Frame(row_frame, bd=2, relief="ridge", padx=5, pady=5)
f.pack(side=tk.LEFT, padx=5)
try:
img = Image.open(gambar).resize((120, 90))
# Pastikan nama file gambar sesuai dengan yang ada di folder project/
img = Image.open(gambar).resize((100, 80))
photo = ImageTk.PhotoImage(img)
self.images.append(photo)
tk.Label(f, image=photo).pack()
except FileNotFoundError:
tk.Label(f, text="No Image").pack()
except:
tk.Label(f, text="[No Image]").pack()
tk.Label(f, text=nama).pack()
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)
tk.Label(f, text=nama, font=("Arial",10,"bold")).pack()
tk.Label(f, text=f"Rp {harga:,.0f}").pack()
tk.Button(f, text="Tambah", command=lambda n=nama, h=harga: self.add_to_cart(n, h)).pack()
def add(self, nama, harga):
self.cart.append((nama, harga))
self.listbox.insert(tk.END, f"{nama} - Rp {harga:,}")
total = sum(h for _, h in self.cart)
self.total_lbl.config(text=f"Total: Rp {total:,}")
def add_to_cart(self, nama, harga):
self.cart.append({'nama': nama, 'harga': harga})
self.refresh_cart()
def refresh_cart(self):
self.listbox.delete(0, tk.END)
total = 0
for item in self.cart:
self.listbox.insert(tk.END, f"{item['nama']} - Rp {item['harga']:,.0f}")
total += item['harga']
self.total_lbl.config(text=f"Total: Rp {total:,.0f}")
def checkout(self):
if not self.cart:
messagebox.showwarning("Pesan Kosong", "Belum ada pesanan!")
meja = self.entry_meja.get()
if not meja:
messagebox.showwarning("Peringatan", "Isi nomor meja dulu!")
return
if not self.cart:
messagebox.showwarning("Kosong", "Pilih menu dulu!")
return
total_belanja = sum(item['harga'] for item in self.cart)
tanggal = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
db = connect()
cur = db.cursor()
for nama, harga in self.cart:
cur.execute("INSERT INTO orders VALUES (NULL, ?, ?)", (nama, harga))
# 1. Buat Header Transaksi (Status = Pending)
cur.execute("INSERT INTO transaksi (tanggal, total, meja_id, status) VALUES (?, ?, ?, ?)",
(tanggal, total_belanja, meja, "Pending"))
transaksi_id = cur.lastrowid # Ambil ID transaksi yang baru dibuat
# 2. Masukkan Detail Item
for item in self.cart:
cur.execute("INSERT INTO detail_transaksi (transaksi_id, menu_nama, harga, jumlah, subtotal) VALUES (?, ?, ?, ?, ?)",
(transaksi_id, item['nama'], item['harga'], 1, item['harga']))
db.commit()
db.close()
messagebox.showinfo("Sukses", "Pesanan dikirim ke kasir")
messagebox.showinfo("Berhasil", "Pesanan terkirim ke Dapur/Waiter!")
self.cart.clear()
self.listbox.delete(0, tk.END)
self.total_lbl.config(text="Total: Rp 0")
self.refresh_cart()
self.entry_meja.delete(0, tk.END)
def logout(self):
self.frame.destroy()
from main import LoginScreen
LoginScreen(self.parent)

View File

@ -1,4 +1,6 @@
import tkinter as tk
from tkinter import messagebox
from database import connect
class WaiterDashboard:
def __init__(self, parent):
@ -6,10 +8,60 @@ class WaiterDashboard:
self.frame = tk.Frame(parent)
self.frame.pack(fill="both", expand=True)
tk.Label(self.frame, text="WAITER", font=("Arial", 20, "bold")).pack(pady=20)
tk.Label(self.frame, text="(Input pesanan manual)").pack()
tk.Label(self.frame, text="DASHBOARD WAITER (Dapur)", font=("Arial", 18, "bold")).pack(pady=10)
tk.Button(self.frame, text="Logout", command=self.logout).pack(pady=10)
tk.Button(self.frame, text="Logout", command=self.logout).pack(pady=5)
tk.Button(self.frame, text="Refresh Data", bg="#cfe2ff", command=self.load_orders).pack(pady=5)
# List Pesanan Masuk
self.listbox = tk.Listbox(self.frame, width=80, height=15)
self.listbox.pack(pady=10)
tk.Button(self.frame, text="Selesai Disajikan / Validasi", bg="#d1e7dd", command=self.validasi_layanan).pack(pady=10)
self.order_ids = [] # Untuk menyimpan ID transaksi sesuai urutan listbox
self.load_orders()
def load_orders(self):
self.listbox.delete(0, tk.END)
self.order_ids = []
db = connect()
cur = db.cursor()
# Ambil pesanan yang statusnya 'Pending'
cur.execute("SELECT id, meja_id, total, status FROM transaksi WHERE status='Pending'")
rows = cur.fetchall()
for row in rows:
t_id, meja, total, status = row
# Ambil detail menu untuk ditampilkan
cur.execute("SELECT menu_nama FROM detail_transaksi WHERE transaksi_id=?", (t_id,))
menus = [r[0] for r in cur.fetchall()]
menu_str = ", ".join(menus)
display_text = f"[Meja {meja}] ID:{t_id} | Menu: {menu_str} | Status: {status}"
self.listbox.insert(tk.END, display_text)
self.order_ids.append(t_id)
db.close()
def validasi_layanan(self):
idx = self.listbox.curselection()
if not idx:
messagebox.showwarning("Pilih", "Pilih pesanan yang sudah disajikan")
return
selected_id = self.order_ids[idx[0]]
db = connect()
cur = db.cursor()
# Ubah status jadi 'Disajikan' agar muncul di kasir
cur.execute("UPDATE transaksi SET status='Disajikan' WHERE id=?", (selected_id,))
db.commit()
db.close()
messagebox.showinfo("Sukses", "Pesanan selesai disajikan. Pelanggan bisa bayar di kasir.")
self.load_orders()
def logout(self):
self.frame.destroy()