Compare commits

..

No commits in common. "69e133c6e3bc167390736ac431b960c844d611df" and "deafb9c440bb4174ba6b47f68913a5533981cdc7" have entirely different histories.

5 changed files with 102 additions and 191 deletions

BIN
cafe.db Normal file

Binary file not shown.

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")
@ -8,7 +7,6 @@ def setup_database():
db = connect() db = connect()
cur = db.cursor() cur = db.cursor()
# Tabel 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,59 +16,44 @@ def setup_database():
) )
""") """)
# Tabel 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,
harga REAL, harga REAL,
gambar TEXT, gambar TEXT
kategori TEXT
) )
""") """)
# Tabel Transaksi (Header nota)
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,
tanggal TEXT, nama TEXT,
total REAL, harga REAL
meja_id INTEGER,
status TEXT
) )
""") """)
# Status: 'Pending' (Masuk Dapur), 'Disajikan' (Waiter selesai), 'Lunas' (Kasir)
# Tabel Detail Transaksi (Isi makanan per nota)
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_nama TEXT, total REAL
harga REAL,
jumlah INTEGER,
subtotal REAL
) )
""") """)
# Insert Akun Default jika kosong
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"),
("waiter","waiter","waiter"), ("pemilik","pemilik","pemilik"),
("pemilik","pemilik","pemilik") ("waiter","waiter","waiter")
] ]
cur.executemany("INSERT INTO users(username,password,role) VALUES (?,?,?)", users) cur.executemany(
db.commit() "INSERT INTO users(username,password,role) VALUES (?,?,?)",
users
# 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.commit()
db.close() db.close()

View File

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

View File

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

View File

@ -1,6 +1,4 @@
import tkinter as tk import tkinter as tk
from tkinter import messagebox
from database import connect
class WaiterDashboard: class WaiterDashboard:
def __init__(self, parent): def __init__(self, parent):
@ -8,60 +6,10 @@ class WaiterDashboard:
self.frame = tk.Frame(parent) self.frame = tk.Frame(parent)
self.frame.pack(fill="both", expand=True) self.frame.pack(fill="both", expand=True)
tk.Label(self.frame, text="DASHBOARD WAITER (Dapur)", font=("Arial", 18, "bold")).pack(pady=10) tk.Label(self.frame, text="WAITER", font=("Arial", 20, "bold")).pack(pady=20)
tk.Label(self.frame, text="(Input pesanan manual)").pack()
tk.Button(self.frame, text="Logout", command=self.logout).pack(pady=5) tk.Button(self.frame, text="Logout", command=self.logout).pack(pady=10)
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): def logout(self):
self.frame.destroy() self.frame.destroy()