Dashboard waiter
This commit is contained in:
parent
5f8f54e8d2
commit
85c2f3158c
205
main.py
205
main.py
@ -698,9 +698,12 @@ class App:
|
|||||||
self.tab_menu_view = ttk.Frame(main)
|
self.tab_menu_view = ttk.Frame(main)
|
||||||
self.tab_promo = ttk.Frame(main)
|
self.tab_promo = ttk.Frame(main)
|
||||||
self.tab_order = ttk.Frame(main)
|
self.tab_order = ttk.Frame(main)
|
||||||
|
self.tab_waiter = ttk.Frame(main)
|
||||||
|
|
||||||
main.add(self.tab_order, text="Order Menu")
|
main.add(self.tab_order, text="Order Menu")
|
||||||
main.add(self.tab_menu_view, text="Menu - View")
|
main.add(self.tab_menu_view, text="Menu - View")
|
||||||
|
if self.session['role'] in ['waiter', 'admin']:
|
||||||
|
main.add(self.tab_waiter, text="Waiter - Pesanan")
|
||||||
if self.session['role'] == 'admin':
|
if self.session['role'] == 'admin':
|
||||||
main.add(self.tab_menu_manage, text="Menu - Manage")
|
main.add(self.tab_menu_manage, text="Menu - Manage")
|
||||||
main.add(self.tab_promo, text="Promo - Manage")
|
main.add(self.tab_promo, text="Promo - Manage")
|
||||||
@ -709,6 +712,8 @@ class App:
|
|||||||
|
|
||||||
self.build_menu_view_tab(self.tab_menu_view)
|
self.build_menu_view_tab(self.tab_menu_view)
|
||||||
self.build_order_tab(self.tab_order)
|
self.build_order_tab(self.tab_order)
|
||||||
|
if self.session['role'] in ['waiter', 'admin']:
|
||||||
|
self.build_waiter_tab(self.tab_waiter)
|
||||||
if self.session['role'] == 'admin':
|
if self.session['role'] == 'admin':
|
||||||
self.build_menu_manage_tab(self.tab_menu_manage)
|
self.build_menu_manage_tab(self.tab_menu_manage)
|
||||||
self.build_promo_tab(self.tab_promo)
|
self.build_promo_tab(self.tab_promo)
|
||||||
@ -1408,6 +1413,206 @@ class App:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Wilayah dikuasai Waiter
|
||||||
|
|
||||||
|
|
||||||
|
def build_waiter_tab(self, parent):
|
||||||
|
"""Tab untuk waiter mengelola pesanan"""
|
||||||
|
for w in parent.winfo_children():
|
||||||
|
w.destroy()
|
||||||
|
|
||||||
|
# Header
|
||||||
|
header = ttk.Frame(parent)
|
||||||
|
header.pack(fill='x', padx=10, pady=8)
|
||||||
|
ttk.Label(header, text="Dashboard Waiter - Kelola Pesanan", font=("Arial", 14, "bold")).pack(side='left')
|
||||||
|
ttk.Button(header, text="🔄 Refresh", command=self.reload_waiter_orders).pack(side='right', padx=6)
|
||||||
|
|
||||||
|
# Filter status
|
||||||
|
filter_frame = ttk.Frame(parent)
|
||||||
|
filter_frame.pack(fill='x', padx=10, pady=6)
|
||||||
|
ttk.Label(filter_frame, text="Filter Status:").pack(side='left', padx=6)
|
||||||
|
ttk.Button(filter_frame, text="Semua", command=lambda: self.reload_waiter_orders(None)).pack(side='left', padx=3)
|
||||||
|
ttk.Button(filter_frame, text="Pending", command=lambda: self.reload_waiter_orders('pending')).pack(side='left', padx=3)
|
||||||
|
ttk.Button(filter_frame, text="Menunggu", command=lambda: self.reload_waiter_orders('menunggu')).pack(side='left', padx=3)
|
||||||
|
ttk.Button(filter_frame, text="Diproses", command=lambda: self.reload_waiter_orders('diproses')).pack(side='left', padx=3)
|
||||||
|
ttk.Button(filter_frame, text="Selesai", command=lambda: self.reload_waiter_orders('selesai')).pack(side='left', padx=3)
|
||||||
|
|
||||||
|
# Treeview pesanan
|
||||||
|
cols = ("ID", "User ID", "No.Meja", "Total", "Status", "Promo", "Tanggal")
|
||||||
|
self.waiter_tree = ttk.Treeview(parent, columns=cols, show='headings', height=12)
|
||||||
|
|
||||||
|
self.waiter_tree.heading("ID", text="ID")
|
||||||
|
self.waiter_tree.heading("User ID", text="User ID")
|
||||||
|
self.waiter_tree.heading("No.Meja", text="No.Meja")
|
||||||
|
self.waiter_tree.heading("Total", text="Total")
|
||||||
|
self.waiter_tree.heading("Status", text="Status")
|
||||||
|
self.waiter_tree.heading("Promo", text="Promo")
|
||||||
|
self.waiter_tree.heading("Tanggal", text="Tanggal")
|
||||||
|
|
||||||
|
self.waiter_tree.column("ID", width=40)
|
||||||
|
self.waiter_tree.column("User ID", width=60)
|
||||||
|
self.waiter_tree.column("No.Meja", width=70)
|
||||||
|
self.waiter_tree.column("Total", width=100)
|
||||||
|
self.waiter_tree.column("Status", width=90)
|
||||||
|
self.waiter_tree.column("Promo", width=80)
|
||||||
|
self.waiter_tree.column("Tanggal", width=140)
|
||||||
|
|
||||||
|
self.waiter_tree.pack(fill='both', expand=True, padx=10, pady=6)
|
||||||
|
|
||||||
|
# Detail pesanan (muncul saat pilih row)
|
||||||
|
detail_frame = ttk.LabelFrame(parent, text="Detail Pesanan", padding=10)
|
||||||
|
detail_frame.pack(fill='x', padx=10, pady=6)
|
||||||
|
|
||||||
|
self.waiter_detail_text = tk.Text(detail_frame, height=8, width=80)
|
||||||
|
self.waiter_detail_text.pack(fill='both', expand=True)
|
||||||
|
|
||||||
|
# Bind event saat pilih pesanan
|
||||||
|
self.waiter_tree.bind("<<TreeviewSelect>>", self.on_waiter_select)
|
||||||
|
|
||||||
|
# Tombol aksi
|
||||||
|
action_frame = ttk.Frame(parent)
|
||||||
|
action_frame.pack(pady=10)
|
||||||
|
|
||||||
|
ttk.Button(action_frame, text="✅ Terima Pesanan (Pending → Menunggu)",
|
||||||
|
command=lambda: self.update_order_status('menunggu'),
|
||||||
|
width=35).pack(pady=3)
|
||||||
|
ttk.Button(action_frame, text="🍳 Proses Pesanan (Menunggu → Diproses)",
|
||||||
|
command=lambda: self.update_order_status('diproses'),
|
||||||
|
width=35).pack(pady=3)
|
||||||
|
ttk.Button(action_frame, text="🍽️ Selesai Disajikan (Diproses → Selesai)",
|
||||||
|
command=lambda: self.update_order_status('selesai'),
|
||||||
|
width=35).pack(pady=3)
|
||||||
|
ttk.Button(action_frame, text="💰 Selesai Dilayani (Selesai → Dibayar)",
|
||||||
|
command=lambda: self.update_order_status('dibayar'),
|
||||||
|
width=35).pack(pady=3)
|
||||||
|
|
||||||
|
# Load data
|
||||||
|
self.reload_waiter_orders()
|
||||||
|
|
||||||
|
def reload_waiter_orders(self, status_filter=None):
|
||||||
|
"""Load pesanan untuk waiter"""
|
||||||
|
# Clear tree
|
||||||
|
for r in self.waiter_tree.get_children():
|
||||||
|
self.waiter_tree.delete(r)
|
||||||
|
|
||||||
|
# Get transaksi
|
||||||
|
if status_filter:
|
||||||
|
orders = transaksi_list(status=status_filter)
|
||||||
|
else:
|
||||||
|
# Tampilkan semua kecuali yang sudah dibayar
|
||||||
|
all_orders = transaksi_list()
|
||||||
|
orders = [o for o in all_orders if o[4] != 'dibayar']
|
||||||
|
|
||||||
|
# Insert ke tree
|
||||||
|
for order in orders:
|
||||||
|
tid, uid, meja, total, status, promo_code, tanggal = order
|
||||||
|
promo_display = promo_code if promo_code else "-"
|
||||||
|
self.waiter_tree.insert("", tk.END, values=(
|
||||||
|
tid, uid, meja, f"Rp {total:,.0f}", status, promo_display, tanggal
|
||||||
|
))
|
||||||
|
|
||||||
|
def on_waiter_select(self, event):
|
||||||
|
"""Tampilkan detail pesanan saat dipilih"""
|
||||||
|
sel = self.waiter_tree.selection()
|
||||||
|
if not sel:
|
||||||
|
return
|
||||||
|
|
||||||
|
item = self.waiter_tree.item(sel)['values']
|
||||||
|
transaksi_id = item[0]
|
||||||
|
|
||||||
|
# Get detail transaksi
|
||||||
|
transaksi_data = transaksi_get(transaksi_id)
|
||||||
|
if not transaksi_data:
|
||||||
|
return
|
||||||
|
|
||||||
|
tid, uid, meja, total, status, promo_code, subtotal, item_disc, promo_disc, tanggal = transaksi_data
|
||||||
|
|
||||||
|
# Get detail items
|
||||||
|
detail_items = detail_transaksi_list(transaksi_id)
|
||||||
|
|
||||||
|
# Format detail
|
||||||
|
detail_text = f"═══════════════════════════════════════════════\n"
|
||||||
|
detail_text += f"TRANSAKSI ID: {tid}\n"
|
||||||
|
detail_text += f"═══════════════════════════════════════════════\n\n"
|
||||||
|
detail_text += f"User ID : {uid}\n"
|
||||||
|
detail_text += f"Nomor Meja : {meja}\n"
|
||||||
|
detail_text += f"Status : {status.upper()}\n"
|
||||||
|
detail_text += f"Tanggal : {tanggal}\n"
|
||||||
|
detail_text += f"Kode Promo : {promo_code if promo_code else '-'}\n\n"
|
||||||
|
|
||||||
|
detail_text += f"───────────────────────────────────────────────\n"
|
||||||
|
detail_text += f"ITEM PESANAN:\n"
|
||||||
|
detail_text += f"───────────────────────────────────────────────\n"
|
||||||
|
|
||||||
|
for detail in detail_items:
|
||||||
|
did, mid, qty, harga, subtotal_item = detail
|
||||||
|
|
||||||
|
# Get nama menu
|
||||||
|
menu_data = menu_get(mid)
|
||||||
|
if menu_data:
|
||||||
|
_, nama, kategori, _, _, _, _, _ = menu_data
|
||||||
|
detail_text += f"• {nama} ({kategori})\n"
|
||||||
|
detail_text += f" {qty} x Rp {harga:,.0f} = Rp {subtotal_item:,.0f}\n\n"
|
||||||
|
|
||||||
|
detail_text += f"───────────────────────────────────────────────\n"
|
||||||
|
detail_text += f"Subtotal : Rp {subtotal:,.0f}\n"
|
||||||
|
detail_text += f"Diskon Item : Rp {item_disc:,.0f}\n"
|
||||||
|
detail_text += f"Diskon Promo : Rp {promo_disc:,.0f}\n"
|
||||||
|
detail_text += f"───────────────────────────────────────────────\n"
|
||||||
|
detail_text += f"TOTAL BAYAR : Rp {total:,.0f}\n"
|
||||||
|
detail_text += f"═══════════════════════════════════════════════\n"
|
||||||
|
|
||||||
|
# Tampilkan di text widget
|
||||||
|
self.waiter_detail_text.delete('1.0', tk.END)
|
||||||
|
self.waiter_detail_text.insert('1.0', detail_text)
|
||||||
|
|
||||||
|
def update_order_status(self, new_status):
|
||||||
|
"""Update status pesanan yang dipilih"""
|
||||||
|
sel = self.waiter_tree.selection()
|
||||||
|
if not sel:
|
||||||
|
messagebox.showwarning("Pilih Pesanan", "Pilih pesanan terlebih dahulu")
|
||||||
|
return
|
||||||
|
|
||||||
|
item = self.waiter_tree.item(sel)['values']
|
||||||
|
transaksi_id = item[0]
|
||||||
|
current_status = item[4]
|
||||||
|
|
||||||
|
# Validasi flow status
|
||||||
|
valid_transitions = {
|
||||||
|
'pending': ['menunggu'],
|
||||||
|
'menunggu': ['diproses'],
|
||||||
|
'diproses': ['selesai'],
|
||||||
|
'selesai': ['dibayar']
|
||||||
|
}
|
||||||
|
|
||||||
|
if current_status not in valid_transitions:
|
||||||
|
messagebox.showerror("Error", f"Status '{current_status}' tidak bisa diubah lagi")
|
||||||
|
return
|
||||||
|
|
||||||
|
if new_status not in valid_transitions[current_status]:
|
||||||
|
messagebox.showwarning("Invalid",
|
||||||
|
f"Tidak bisa ubah dari '{current_status}' ke '{new_status}'.\n"
|
||||||
|
f"Status berikutnya: {', '.join(valid_transitions[current_status])}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Konfirmasi
|
||||||
|
if not messagebox.askyesno("Konfirmasi",
|
||||||
|
f"Ubah status pesanan #{transaksi_id}\n"
|
||||||
|
f"dari '{current_status}' ke '{new_status}'?"):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Update status
|
||||||
|
success = transaksi_update_status(transaksi_id, new_status)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
messagebox.showinfo("Sukses", f"Status diubah menjadi '{new_status}'")
|
||||||
|
self.reload_waiter_orders()
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Error", "Gagal update status")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
6
menu.csv
6
menu.csv
@ -1,5 +1,5 @@
|
|||||||
id,nama,kategori,harga,stok,foto,tersedia,item_discount_pct
|
id,nama,kategori,harga,stok,foto,tersedia,item_discount_pct
|
||||||
1,Americano,Minuman,20000,10,,1,0
|
1,Americano,Minuman,20000,8,,1,0
|
||||||
2,Latte,Minuman,25000,2,,1,10
|
2,Latte,Minuman,25000,1,,1,10
|
||||||
3,Banana Cake,Dessert,30000,1,,1,0
|
3,Banana Cake,Dessert,30000,0,,0,0
|
||||||
4,Nasi Goreng,Makanan,35000,0,,0,0
|
4,Nasi Goreng,Makanan,35000,0,,0,0
|
||||||
|
|||||||
|
Loading…
x
Reference in New Issue
Block a user