Sistem Order Pembeli
This commit is contained in:
parent
1f904a2ba8
commit
5f8f54e8d2
540
main.py
540
main.py
@ -9,7 +9,7 @@
|
||||
import os
|
||||
import csv
|
||||
import tkinter as tk
|
||||
from tkinter import ttk, messagebox, filedialog
|
||||
from tkinter import ttk, messagebox, filedialog, simpledialog
|
||||
from PIL import Image, ImageTk
|
||||
|
||||
USERS_CSV = "users.csv"
|
||||
@ -365,6 +365,187 @@ def promo_get(code):
|
||||
return None
|
||||
|
||||
|
||||
# Wilayah dikuasai Transaksi
|
||||
|
||||
|
||||
def transaksi_add(user_id, nomor_meja, cart_items, promo_code=None):
|
||||
"""Simpan transaksi baru dengan status 'pending'"""
|
||||
from datetime import datetime
|
||||
|
||||
if not cart_items:
|
||||
return False, "Keranjang kosong"
|
||||
|
||||
# Hitung diskon dan total
|
||||
calc = apply_discounts_and_promo(cart_items, promo_code)
|
||||
|
||||
# Buat transaksi
|
||||
rows = read_all(TRANSAKSI_CSV)
|
||||
transaksi_id = next_int_id(rows, "id")
|
||||
tanggal = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
transaksi_row = {
|
||||
"id": transaksi_id,
|
||||
"user_id": str(user_id),
|
||||
"nomor_meja": str(nomor_meja),
|
||||
"total": str(calc['total']),
|
||||
"status": "pending",
|
||||
"promo_code": calc.get('promo_code') or "",
|
||||
"subtotal": str(calc['subtotal']),
|
||||
"item_discount": str(calc['item_discount']),
|
||||
"promo_discount": str(calc['promo_discount']),
|
||||
"tanggal": tanggal
|
||||
}
|
||||
rows.append(transaksi_row)
|
||||
write_all(TRANSAKSI_CSV, ["id", "user_id", "nomor_meja", "total", "status", "promo_code", "subtotal", "item_discount", "promo_discount", "tanggal"], rows)
|
||||
|
||||
# Simpan detail transaksi
|
||||
detail_rows = read_all(DETAIL_TRANSAKSI_CSV)
|
||||
for item in cart_items:
|
||||
detail_id = next_int_id(detail_rows, "id")
|
||||
menu_data = menu_get(item['menu_id'])
|
||||
if not menu_data:
|
||||
continue
|
||||
_, nama, kategori, harga, stok, foto, tersedia, item_disc = menu_data
|
||||
|
||||
qty = int(item['qty'])
|
||||
subtotal_item = harga * qty
|
||||
|
||||
detail_rows.append({
|
||||
"id": detail_id,
|
||||
"transaksi_id": transaksi_id,
|
||||
"menu_id": str(item['menu_id']),
|
||||
"qty": str(qty),
|
||||
"harga_satuan": str(harga),
|
||||
"subtotal_item": str(subtotal_item)
|
||||
})
|
||||
|
||||
# Kurangi stok
|
||||
success, msg = menu_decrease_stock(item['menu_id'], qty)
|
||||
if not success:
|
||||
return False, f"Gagal mengurangi stok menu ID {item['menu_id']}: {msg}"
|
||||
|
||||
write_all(DETAIL_TRANSAKSI_CSV, ["id", "transaksi_id", "menu_id", "qty", "harga_satuan", "subtotal_item"], detail_rows)
|
||||
|
||||
return True, transaksi_id
|
||||
|
||||
|
||||
def transaksi_list(status=None, user_id=None):
|
||||
"""Ambil daftar transaksi, bisa filter by status atau user_id"""
|
||||
rows = read_all(TRANSAKSI_CSV)
|
||||
out = []
|
||||
for r in rows:
|
||||
if status and r.get("status") != status:
|
||||
continue
|
||||
if user_id and r.get("user_id") != str(user_id):
|
||||
continue
|
||||
|
||||
try:
|
||||
tid = int(r.get("id") or 0)
|
||||
except:
|
||||
tid = r.get("id")
|
||||
try:
|
||||
uid = int(r.get("user_id") or 0)
|
||||
except:
|
||||
uid = r.get("user_id")
|
||||
try:
|
||||
meja = int(r.get("nomor_meja") or 0)
|
||||
except:
|
||||
meja = r.get("nomor_meja")
|
||||
try:
|
||||
total = float(r.get("total") or 0.0)
|
||||
except:
|
||||
total = 0.0
|
||||
|
||||
out.append((tid, uid, meja, total, r.get("status"), r.get("promo_code"), r.get("tanggal")))
|
||||
|
||||
out.sort(key=lambda x: int(x[0]), reverse=True)
|
||||
return out
|
||||
|
||||
|
||||
def transaksi_get(transaksi_id):
|
||||
"""Ambil detail transaksi by ID"""
|
||||
rows = read_all(TRANSAKSI_CSV)
|
||||
for r in rows:
|
||||
if r.get("id") == str(transaksi_id):
|
||||
try:
|
||||
tid = int(r.get("id") or 0)
|
||||
except:
|
||||
tid = r.get("id")
|
||||
try:
|
||||
uid = int(r.get("user_id") or 0)
|
||||
except:
|
||||
uid = r.get("user_id")
|
||||
try:
|
||||
meja = int(r.get("nomor_meja") or 0)
|
||||
except:
|
||||
meja = r.get("nomor_meja")
|
||||
try:
|
||||
total = float(r.get("total") or 0.0)
|
||||
except:
|
||||
total = 0.0
|
||||
try:
|
||||
subtotal = float(r.get("subtotal") or 0.0)
|
||||
except:
|
||||
subtotal = 0.0
|
||||
try:
|
||||
item_disc = float(r.get("item_discount") or 0.0)
|
||||
except:
|
||||
item_disc = 0.0
|
||||
try:
|
||||
promo_disc = float(r.get("promo_discount") or 0.0)
|
||||
except:
|
||||
promo_disc = 0.0
|
||||
|
||||
return (tid, uid, meja, total, r.get("status"), r.get("promo_code"), subtotal, item_disc, promo_disc, r.get("tanggal"))
|
||||
return None
|
||||
|
||||
|
||||
def transaksi_update_status(transaksi_id, new_status):
|
||||
"""Update status transaksi"""
|
||||
rows = read_all(TRANSAKSI_CSV)
|
||||
found = False
|
||||
for r in rows:
|
||||
if r.get("id") == str(transaksi_id):
|
||||
r["status"] = new_status
|
||||
found = True
|
||||
break
|
||||
|
||||
if found:
|
||||
write_all(TRANSAKSI_CSV, ["id", "user_id", "nomor_meja", "total", "status", "promo_code", "subtotal", "item_discount", "promo_discount", "tanggal"], rows)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def detail_transaksi_list(transaksi_id):
|
||||
"""Ambil semua detail item dari transaksi tertentu"""
|
||||
rows = read_all(DETAIL_TRANSAKSI_CSV)
|
||||
out = []
|
||||
for r in rows:
|
||||
if r.get("transaksi_id") == str(transaksi_id):
|
||||
try:
|
||||
did = int(r.get("id") or 0)
|
||||
except:
|
||||
did = r.get("id")
|
||||
try:
|
||||
mid = int(r.get("menu_id") or 0)
|
||||
except:
|
||||
mid = r.get("menu_id")
|
||||
try:
|
||||
qty = int(r.get("qty") or 0)
|
||||
except:
|
||||
qty = 0
|
||||
try:
|
||||
harga = float(r.get("harga_satuan") or 0.0)
|
||||
except:
|
||||
harga = 0.0
|
||||
try:
|
||||
subtotal = float(r.get("subtotal_item") or 0.0)
|
||||
except:
|
||||
subtotal = 0.0
|
||||
|
||||
out.append((did, mid, qty, harga, subtotal))
|
||||
|
||||
return out
|
||||
|
||||
|
||||
|
||||
@ -463,6 +644,8 @@ class App:
|
||||
self.root.geometry("1000x650")
|
||||
self.root.resizable(False, False)
|
||||
self.login_frame()
|
||||
style = ttk.Style()
|
||||
style.configure("Accent.TButton", font=("Arial", 11, "bold"))
|
||||
|
||||
def login_frame(self):
|
||||
for w in self.root.winfo_children():
|
||||
@ -514,7 +697,9 @@ class App:
|
||||
self.tab_menu_manage = ttk.Frame(main)
|
||||
self.tab_menu_view = ttk.Frame(main)
|
||||
self.tab_promo = ttk.Frame(main)
|
||||
self.tab_order = ttk.Frame(main)
|
||||
|
||||
main.add(self.tab_order, text="Order Menu")
|
||||
main.add(self.tab_menu_view, text="Menu - View")
|
||||
if self.session['role'] == 'admin':
|
||||
main.add(self.tab_menu_manage, text="Menu - Manage")
|
||||
@ -523,6 +708,7 @@ class App:
|
||||
pass
|
||||
|
||||
self.build_menu_view_tab(self.tab_menu_view)
|
||||
self.build_order_tab(self.tab_order)
|
||||
if self.session['role'] == 'admin':
|
||||
self.build_menu_manage_tab(self.tab_menu_manage)
|
||||
self.build_promo_tab(self.tab_promo)
|
||||
@ -867,6 +1053,358 @@ class App:
|
||||
messagebox.showinfo("Dihapus","Promo terhapus")
|
||||
self.reload_promo_table()
|
||||
|
||||
def build_order_tab(self, parent):
|
||||
"""Tab untuk order menu dengan tampilan card seperti GrabFood/Gojek"""
|
||||
for w in parent.winfo_children():
|
||||
w.destroy()
|
||||
|
||||
# Split jadi 2 panel: kiri = menu cards, kanan = cart
|
||||
left = ttk.Frame(parent, width=600)
|
||||
right = ttk.Frame(parent, width=380)
|
||||
left.pack(side='left', fill='both', expand=True, padx=6, pady=6)
|
||||
right.pack(side='right', fill='both', padx=6, pady=6)
|
||||
|
||||
# === PANEL KIRI: Daftar Menu dengan Card ===
|
||||
ttk.Label(left, text="Daftar Menu", font=("Arial", 13, "bold")).pack(pady=6)
|
||||
|
||||
# Filter search
|
||||
search_frame = ttk.Frame(left)
|
||||
search_frame.pack(fill='x', pady=4)
|
||||
ttk.Label(search_frame, text="Cari:").pack(side='left', padx=3)
|
||||
self.order_search_var = tk.StringVar()
|
||||
ttk.Entry(search_frame, textvariable=self.order_search_var, width=25).pack(side='left', padx=3)
|
||||
ttk.Button(search_frame, text="Cari", command=self.reload_order_menu_cards).pack(side='left', padx=3)
|
||||
ttk.Button(search_frame, text="Reset", command=self.reset_order_search).pack(side='left', padx=3)
|
||||
|
||||
# Scrollable frame untuk cards
|
||||
canvas = tk.Canvas(left, bg='white')
|
||||
scrollbar = ttk.Scrollbar(left, orient="vertical", command=canvas.yview)
|
||||
self.menu_cards_frame = ttk.Frame(canvas)
|
||||
|
||||
self.menu_cards_frame.bind(
|
||||
"<Configure>",
|
||||
lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
|
||||
)
|
||||
|
||||
canvas.create_window((0, 0), window=self.menu_cards_frame, anchor="nw")
|
||||
canvas.configure(yscrollcommand=scrollbar.set)
|
||||
|
||||
canvas.pack(side="left", fill="both", expand=True)
|
||||
scrollbar.pack(side="right", fill="y")
|
||||
|
||||
# Bind mouse wheel untuk scroll
|
||||
def _on_mousewheel(event):
|
||||
canvas.yview_scroll(int(-1*(event.delta/120)), "units")
|
||||
canvas.bind_all("<MouseWheel>", _on_mousewheel)
|
||||
|
||||
# === PANEL KANAN: Keranjang ===
|
||||
ttk.Label(right, text="Keranjang Belanja", font=("Arial", 13, "bold")).pack(pady=6)
|
||||
|
||||
# Treeview cart
|
||||
cart_cols = ("Menu", "Qty", "Harga", "Subtotal")
|
||||
self.cart_tree = ttk.Treeview(right, columns=cart_cols, show='headings', height=12)
|
||||
for c in cart_cols:
|
||||
self.cart_tree.heading(c, text=c)
|
||||
if c == "Menu":
|
||||
self.cart_tree.column(c, width=150)
|
||||
else:
|
||||
self.cart_tree.column(c, width=70)
|
||||
self.cart_tree.pack(fill='both', expand=True)
|
||||
|
||||
# Tombol hapus item atau kosongkan cart
|
||||
cart_btn_frame = ttk.Frame(right)
|
||||
cart_btn_frame.pack(pady=4)
|
||||
ttk.Button(cart_btn_frame, text="Hapus Item", command=self.remove_cart_item).pack(side='left', padx=3)
|
||||
ttk.Button(cart_btn_frame, text="Kosongkan", command=self.clear_cart).pack(side='left', padx=3)
|
||||
|
||||
# Info total
|
||||
self.cart_subtotal_label = ttk.Label(right, text="Subtotal: Rp 0", font=("Arial", 10))
|
||||
self.cart_subtotal_label.pack(pady=2)
|
||||
self.cart_discount_label = ttk.Label(right, text="Diskon Item: Rp 0", font=("Arial", 10))
|
||||
self.cart_discount_label.pack(pady=2)
|
||||
self.cart_promo_label = ttk.Label(right, text="Diskon Promo: Rp 0", font=("Arial", 10))
|
||||
self.cart_promo_label.pack(pady=2)
|
||||
self.cart_total_label = ttk.Label(right, text="TOTAL: Rp 0", font=("Arial", 12, "bold"))
|
||||
self.cart_total_label.pack(pady=4)
|
||||
|
||||
# Input nomor meja dan promo
|
||||
checkout_frame = ttk.Frame(right)
|
||||
checkout_frame.pack(pady=6)
|
||||
ttk.Label(checkout_frame, text="No. Meja:").grid(row=0, column=0, sticky='e', padx=3, pady=3)
|
||||
self.order_meja_var = tk.StringVar()
|
||||
ttk.Entry(checkout_frame, textvariable=self.order_meja_var, width=15).grid(row=0, column=1, pady=3)
|
||||
|
||||
ttk.Label(checkout_frame, text="Kode Promo:").grid(row=1, column=0, sticky='e', padx=3, pady=3)
|
||||
self.order_promo_var = tk.StringVar()
|
||||
ttk.Entry(checkout_frame, textvariable=self.order_promo_var, width=15).grid(row=1, column=1, pady=3)
|
||||
ttk.Button(checkout_frame, text="Terapkan", command=self.update_cart_display).grid(row=1, column=2, padx=3)
|
||||
|
||||
# Tombol checkout
|
||||
ttk.Button(right, text="🛒 CHECKOUT", command=self.checkout_order, style="Accent.TButton").pack(pady=8)
|
||||
|
||||
# Init cart data
|
||||
self.cart_items = [] # List of dict: {'menu_id': int, 'qty': int}
|
||||
|
||||
# Load menu cards
|
||||
self.reload_order_menu_cards()
|
||||
|
||||
def reload_order_menu_cards(self):
|
||||
"""Load menu dalam bentuk cards dengan gambar + tombol +/-"""
|
||||
# Clear existing cards
|
||||
for widget in self.menu_cards_frame.winfo_children():
|
||||
widget.destroy()
|
||||
|
||||
# Get menu data
|
||||
search = self.order_search_var.get().strip() or None
|
||||
results = menu_list(search_text=search, available_only=True)
|
||||
|
||||
# Buat dict untuk qty di cart
|
||||
cart_dict = {}
|
||||
for cart_item in self.cart_items:
|
||||
cart_dict[cart_item['menu_id']] = cart_item['qty']
|
||||
|
||||
# Render cards dalam grid (2 kolom)
|
||||
row = 0
|
||||
col = 0
|
||||
for menu_data in results:
|
||||
mid, nama, kategori, harga, stok, foto, tersedia, item_disc = menu_data
|
||||
|
||||
# Create card frame
|
||||
card = tk.Frame(self.menu_cards_frame, relief='ridge', borderwidth=2, bg='white', padx=10, pady=10)
|
||||
card.grid(row=row, column=col, padx=8, pady=8, sticky='nsew')
|
||||
|
||||
# Gambar
|
||||
if foto and os.path.exists(foto):
|
||||
try:
|
||||
img = Image.open(foto)
|
||||
img = img.resize((150, 100), Image.Resampling.LANCZOS)
|
||||
photo = ImageTk.PhotoImage(img)
|
||||
|
||||
# Simpan reference agar tidak di-garbage collect
|
||||
img_label = tk.Label(card, image=photo, bg='white')
|
||||
img_label.image = photo
|
||||
img_label.pack()
|
||||
except:
|
||||
tk.Label(card, text="[No Image]", bg='lightgray', width=20, height=6).pack()
|
||||
else:
|
||||
tk.Label(card, text="[No Image]", bg='lightgray', width=20, height=6).pack()
|
||||
|
||||
# Nama menu
|
||||
tk.Label(card, text=nama, font=("Arial", 11, "bold"), bg='white', wraplength=150).pack(pady=(5, 2))
|
||||
|
||||
# Kategori
|
||||
tk.Label(card, text=kategori, font=("Arial", 9), fg='gray', bg='white').pack()
|
||||
|
||||
# Harga
|
||||
harga_text = f"Rp {harga:,.0f}"
|
||||
if item_disc > 0:
|
||||
harga_text += f" (-{item_disc}%)"
|
||||
tk.Label(card, text=harga_text, font=("Arial", 10, "bold"), fg='green', bg='white').pack(pady=2)
|
||||
|
||||
# Stok info
|
||||
tk.Label(card, text=f"Stok: {stok}", font=("Arial", 8), fg='blue', bg='white').pack(pady=2)
|
||||
|
||||
# Tombol +/- atau + saja
|
||||
qty_in_cart = cart_dict.get(mid, 0)
|
||||
|
||||
btn_frame = tk.Frame(card, bg='white')
|
||||
btn_frame.pack(pady=5)
|
||||
|
||||
if qty_in_cart > 0:
|
||||
# Tampilkan - [qty] +
|
||||
tk.Button(
|
||||
btn_frame,
|
||||
text="➖",
|
||||
font=("Arial", 12, "bold"),
|
||||
bg='#FF5722',
|
||||
fg='white',
|
||||
width=3,
|
||||
command=lambda m=mid: self.decrease_from_card(m)
|
||||
).pack(side='left', padx=2)
|
||||
|
||||
tk.Label(
|
||||
btn_frame,
|
||||
text=str(qty_in_cart),
|
||||
font=("Arial", 12, "bold"),
|
||||
bg='white',
|
||||
width=3
|
||||
).pack(side='left', padx=5)
|
||||
|
||||
tk.Button(
|
||||
btn_frame,
|
||||
text="➕",
|
||||
font=("Arial", 12, "bold"),
|
||||
bg='#4CAF50',
|
||||
fg='white',
|
||||
width=3,
|
||||
command=lambda m=mid, s=stok: self.increase_from_card(m, s)
|
||||
).pack(side='left', padx=2)
|
||||
else:
|
||||
# Tampilkan tombol + aja
|
||||
tk.Button(
|
||||
btn_frame,
|
||||
text="➕ Tambah",
|
||||
font=("Arial", 10, "bold"),
|
||||
bg='#4CAF50',
|
||||
fg='white',
|
||||
width=12,
|
||||
command=lambda m=mid, s=stok: self.increase_from_card(m, s)
|
||||
).pack()
|
||||
|
||||
# Next column
|
||||
col += 1
|
||||
if col >= 2: # 2 cards per row
|
||||
col = 0
|
||||
row += 1
|
||||
|
||||
def reset_order_search(self):
|
||||
self.order_search_var.set("")
|
||||
self.reload_order_menu_cards()
|
||||
|
||||
def increase_from_card(self, menu_id, stok):
|
||||
"""Tambah qty dari tombol + di card"""
|
||||
# Cek qty saat ini
|
||||
current_qty = 0
|
||||
cart_item_found = None
|
||||
for cart_item in self.cart_items:
|
||||
if cart_item['menu_id'] == menu_id:
|
||||
current_qty = cart_item['qty']
|
||||
cart_item_found = cart_item
|
||||
break
|
||||
|
||||
# Cek stok
|
||||
if current_qty >= stok:
|
||||
messagebox.showwarning("Stok Habis", f"Stok hanya tersisa {stok}")
|
||||
return
|
||||
|
||||
# Tambah qty
|
||||
if cart_item_found:
|
||||
cart_item_found['qty'] += 1
|
||||
else:
|
||||
self.cart_items.append({'menu_id': menu_id, 'qty': 1})
|
||||
|
||||
# Update tampilan
|
||||
self.reload_order_menu_cards()
|
||||
self.update_cart_display()
|
||||
|
||||
def decrease_from_card(self, menu_id):
|
||||
"""Kurangi qty dari tombol - di card"""
|
||||
for i, cart_item in enumerate(self.cart_items):
|
||||
if cart_item['menu_id'] == menu_id:
|
||||
cart_item['qty'] -= 1
|
||||
|
||||
# Kalau qty jadi 0, hapus dari cart
|
||||
if cart_item['qty'] <= 0:
|
||||
del self.cart_items[i]
|
||||
|
||||
# Update tampilan
|
||||
self.reload_order_menu_cards()
|
||||
self.update_cart_display()
|
||||
return
|
||||
|
||||
def update_cart_display(self):
|
||||
"""Update tampilan keranjang dan hitung total"""
|
||||
|
||||
# Clear tree
|
||||
for r in self.cart_tree.get_children():
|
||||
self.cart_tree.delete(r)
|
||||
|
||||
# Tampilkan item
|
||||
for cart_item in self.cart_items:
|
||||
menu_data = menu_get(cart_item['menu_id'])
|
||||
if not menu_data:
|
||||
print(f"WARNING: Menu ID {cart_item['menu_id']} tidak ditemukan!")
|
||||
continue
|
||||
|
||||
_, nama, kategori, harga, stok, foto, tersedia, item_disc = menu_data
|
||||
qty = cart_item['qty']
|
||||
subtotal = harga * qty
|
||||
|
||||
# DEBUG
|
||||
print(f"Menambahkan ke tree: {nama} x{qty} = {subtotal}")
|
||||
|
||||
self.cart_tree.insert("", tk.END, values=(nama, qty, f"{harga:,.0f}", f"{subtotal:,.0f}"))
|
||||
|
||||
# Hitung total dengan diskon
|
||||
promo_code = self.order_promo_var.get().strip() or None
|
||||
|
||||
if self.cart_items: # PENTING: Hanya hitung kalau ada item
|
||||
calc = apply_discounts_and_promo(self.cart_items, promo_code)
|
||||
|
||||
self.cart_subtotal_label.config(text=f"Subtotal: Rp {calc['subtotal']:,.0f}")
|
||||
self.cart_discount_label.config(text=f"Diskon Item: Rp {calc['item_discount']:,.0f}")
|
||||
self.cart_promo_label.config(text=f"Diskon Promo: Rp {calc['promo_discount']:,.0f}")
|
||||
self.cart_total_label.config(text=f"TOTAL: Rp {calc['total']:,.0f}")
|
||||
else:
|
||||
# Reset label kalau cart kosong
|
||||
self.cart_subtotal_label.config(text="Subtotal: Rp 0")
|
||||
self.cart_discount_label.config(text="Diskon Item: Rp 0")
|
||||
self.cart_promo_label.config(text="Diskon Promo: Rp 0")
|
||||
self.cart_total_label.config(text="TOTAL: Rp 0")
|
||||
|
||||
|
||||
def remove_cart_item(self):
|
||||
"""Hapus item dari cart"""
|
||||
sel = self.cart_tree.selection()
|
||||
if not sel:
|
||||
messagebox.showwarning("Pilih Item", "Pilih item di keranjang")
|
||||
return
|
||||
|
||||
idx = self.cart_tree.index(sel)
|
||||
if idx >= len(self.cart_items):
|
||||
return
|
||||
|
||||
del self.cart_items[idx]
|
||||
self.update_cart_display()
|
||||
|
||||
def clear_cart(self):
|
||||
"""Kosongkan keranjang"""
|
||||
if not self.cart_items:
|
||||
return
|
||||
|
||||
if messagebox.askyesno("Konfirmasi", "Kosongkan keranjang?"):
|
||||
self.cart_items = []
|
||||
self.update_cart_display()
|
||||
|
||||
def checkout_order(self):
|
||||
"""Simpan pesanan ke database"""
|
||||
if not self.cart_items:
|
||||
messagebox.showwarning("Keranjang Kosong", "Tambahkan item terlebih dahulu")
|
||||
return
|
||||
|
||||
nomor_meja = self.order_meja_var.get().strip()
|
||||
if not nomor_meja:
|
||||
messagebox.showwarning("Input Error", "Masukkan nomor meja")
|
||||
return
|
||||
|
||||
try:
|
||||
nomor_meja = int(nomor_meja)
|
||||
except:
|
||||
messagebox.showerror("Input Error", "Nomor meja harus angka")
|
||||
return
|
||||
|
||||
promo_code = self.order_promo_var.get().strip() or None
|
||||
|
||||
# Validasi promo
|
||||
if promo_code:
|
||||
promo_data = promo_get(promo_code)
|
||||
if not promo_data:
|
||||
messagebox.showwarning("Promo Invalid", "Kode promo tidak ditemukan")
|
||||
return
|
||||
|
||||
# Simpan transaksi
|
||||
success, result = transaksi_add(self.session['id'], nomor_meja, self.cart_items, promo_code)
|
||||
|
||||
if success:
|
||||
messagebox.showinfo("Sukses", f"Pesanan berhasil! ID Transaksi: {result}\nStatus: Pending")
|
||||
# Reset
|
||||
self.cart_items = []
|
||||
self.order_meja_var.set("")
|
||||
self.order_promo_var.set("")
|
||||
self.update_cart_display()
|
||||
self.reload_order_menu() # Refresh stok
|
||||
else:
|
||||
messagebox.showerror("Error", f"Gagal menyimpan pesanan: {result}")
|
||||
|
||||
|
||||
|
||||
|
||||
4
menu.csv
4
menu.csv
@ -1,5 +1,5 @@
|
||||
id,nama,kategori,harga,stok,foto,tersedia,item_discount_pct
|
||||
1,Americano,Minuman,20000,10,,1,0
|
||||
2,Latte,Minuman,25000,5,,1,10
|
||||
3,Banana Cake,Dessert,30000,2,,1,0
|
||||
2,Latte,Minuman,25000,2,,1,10
|
||||
3,Banana Cake,Dessert,30000,1,,1,0
|
||||
4,Nasi Goreng,Makanan,35000,0,,0,0
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user