593 lines
21 KiB
Python
593 lines
21 KiB
Python
"""akun default buat login :
|
|
- admin / admin123 (role admin)
|
|
- kasir / kasir123 (role kasir)
|
|
- waiter / waiter123 (role waiter)
|
|
- user / user123 (role pembeli)
|
|
- owner / owner123 (role pemilik)
|
|
"""
|
|
|
|
|
|
import sqlite3
|
|
import os
|
|
import tkinter as tk
|
|
from tkinter import ttk, messagebox, filedialog
|
|
from PIL import Image, ImageTk
|
|
|
|
DB_PATH = "cafe_person1.db"
|
|
IMG_PREVIEW_SIZE = (120, 80)
|
|
|
|
|
|
|
|
|
|
|
|
# Baguan Database (ati ati)
|
|
|
|
|
|
def init_db():
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("""
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username TEXT UNIQUE,
|
|
password TEXT,
|
|
role TEXT
|
|
)
|
|
""")
|
|
c.execute("""
|
|
CREATE TABLE IF NOT EXISTS menu (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
nama TEXT NOT NULL,
|
|
kategori TEXT,
|
|
harga REAL NOT NULL,
|
|
stok INTEGER DEFAULT 0,
|
|
foto TEXT,
|
|
tersedia INTEGER DEFAULT 1,
|
|
item_discount_pct REAL DEFAULT 0 -- per item discount percent (like 10 for 10%)
|
|
)
|
|
""")
|
|
c.execute("""
|
|
CREATE TABLE IF NOT EXISTS promo (
|
|
code TEXT PRIMARY KEY,
|
|
type TEXT CHECK(type IN ('percent','fixed')),
|
|
value REAL,
|
|
min_total REAL DEFAULT 0
|
|
)
|
|
""")
|
|
conn.commit()
|
|
seed_defaults(conn)
|
|
return conn
|
|
|
|
def seed_defaults(conn):
|
|
c = conn.cursor()
|
|
defaults = [
|
|
('admin','admin123','admin'),
|
|
('kasir','kasir123','kasir'),
|
|
('waiter','waiter123','waiter'),
|
|
('user','user123','pembeli'),
|
|
('owner','owner123','pemilik'),
|
|
]
|
|
for u,p,r in defaults:
|
|
try:
|
|
c.execute("INSERT INTO users (username,password,role) VALUES (?,?,?)", (u,p,r))
|
|
except sqlite3.IntegrityError:
|
|
pass
|
|
sample = [
|
|
('Americano','Minuman',20000,10,None,1,0),
|
|
('Latte','Minuman',25000,5,None,1,10),
|
|
('Banana Cake','Dessert',30000,2,None,1,0),
|
|
('Nasi Goreng','Makanan',35000,0,None,0,0),
|
|
]
|
|
for name,kategori,harga,stok,foto,tersedia,disc in sample:
|
|
c.execute("SELECT id FROM menu WHERE nama=?", (name,))
|
|
if c.fetchone() is None:
|
|
c.execute("""INSERT INTO menu (nama,kategori,harga,stok,foto,tersedia,item_discount_pct)
|
|
VALUES (?,?,?,?,?,?,?)""", (name,kategori,harga,stok,foto,tersedia,disc))
|
|
promos = [
|
|
('CAFE10','percent',10,0),
|
|
('HEMAT5000','fixed',5000,20000),
|
|
]
|
|
for code,ptype,val,min_total in promos:
|
|
try:
|
|
c.execute("INSERT INTO promo (code,type,value,min_total) VALUES (?,?,?,?)", (code,ptype,val,min_total))
|
|
except sqlite3.IntegrityError:
|
|
pass
|
|
conn.commit()
|
|
|
|
def authenticate(username, password):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("SELECT id,username,role FROM users WHERE username=? AND password=?", (username,password))
|
|
r = c.fetchone()
|
|
conn.close()
|
|
if r:
|
|
return {'id':r[0],'username':r[1],'role':r[2]}
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Bagian Menu wel
|
|
|
|
|
|
def menu_add(nama, kategori, harga, stok, foto, item_discount_pct=0):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
tersedia = 1 if stok>0 else 0
|
|
c.execute("""INSERT INTO menu (nama,kategori,harga,stok,foto,tersedia,item_discount_pct)
|
|
VALUES (?,?,?,?,?,?,?)""", (nama,kategori,harga,stok,foto,tersedia,item_discount_pct))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def menu_update(menu_id, nama, kategori, harga, stok, foto, item_discount_pct=0):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
tersedia = 1 if stok>0 else 0
|
|
c.execute("""UPDATE menu SET nama=?,kategori=?,harga=?,stok=?,foto=?,tersedia=?,item_discount_pct=?
|
|
WHERE id=?""", (nama,kategori,harga,stok,foto,tersedia,item_discount_pct, menu_id))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def menu_delete(menu_id):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("DELETE FROM menu WHERE id=?", (menu_id,))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def menu_list(kategori=None, available_only=False, search_text=None):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
q = "SELECT id,nama,kategori,harga,stok,foto,tersedia,item_discount_pct FROM menu"
|
|
conditions = []
|
|
params = []
|
|
if kategori:
|
|
conditions.append("kategori=?")
|
|
params.append(kategori)
|
|
if available_only:
|
|
conditions.append("tersedia=1")
|
|
if search_text:
|
|
conditions.append("(nama LIKE ? OR kategori LIKE ?)")
|
|
params += [f"%{search_text}%", f"%{search_text}%"]
|
|
if conditions:
|
|
q += " WHERE " + " AND ".join(conditions)
|
|
q += " ORDER BY id ASC"
|
|
c.execute(q, params)
|
|
rows = c.fetchall()
|
|
conn.close()
|
|
return rows
|
|
|
|
def menu_get(menu_id):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("SELECT id,nama,kategori,harga,stok,foto,tersedia,item_discount_pct FROM menu WHERE id=?", (menu_id,))
|
|
r = c.fetchone()
|
|
conn.close()
|
|
return r
|
|
|
|
def menu_decrease_stock(menu_id, qty):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("SELECT stok FROM menu WHERE id=?", (menu_id,))
|
|
r = c.fetchone()
|
|
if not r:
|
|
conn.close()
|
|
return False, "Menu tidak ditemukan"
|
|
stok = r[0]
|
|
if stok < qty:
|
|
conn.close()
|
|
return False, "Stok tidak cukup"
|
|
newstok = stok - qty
|
|
tersedia = 1 if newstok>0 else 0
|
|
c.execute("UPDATE menu SET stok=?, tersedia=? WHERE id=?", (newstok, tersedia, menu_id))
|
|
conn.commit()
|
|
conn.close()
|
|
return True, newstok
|
|
|
|
|
|
|
|
# Bagian Promooo
|
|
|
|
|
|
def promo_add(code, ptype, value, min_total=0):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("INSERT INTO promo (code,type,value,min_total) VALUES (?,?,?,?)", (code,ptype,value,min_total))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def promo_update(code, ptype, value, min_total=0):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("UPDATE promo SET type=?, value=?, min_total=? WHERE code=?", (ptype,value,min_total,code))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def promo_delete(code):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("DELETE FROM promo WHERE code=?", (code,))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def promo_list():
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("SELECT code,type,value,min_total FROM promo ORDER BY code")
|
|
rows = c.fetchall()
|
|
conn.close()
|
|
return rows
|
|
|
|
def promo_get(code):
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
c.execute("SELECT code,type,value,min_total FROM promo WHERE code=?", (code,))
|
|
r = c.fetchone()
|
|
conn.close()
|
|
return r
|
|
|
|
def apply_discounts_and_promo(cart_items, promo_code=None):
|
|
"""
|
|
cart_items: list of dicts: [{'menu_id':..,'qty':..}, ...]
|
|
returns breakdown: subtotal, item_discount_total, promo_code, promo_discount, total
|
|
- uses item_discount_pct from menu table
|
|
- promo_code can be percent or fixed, with min_total
|
|
"""
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
subtotal = 0.0
|
|
item_discount_total = 0.0
|
|
for it in cart_items:
|
|
c.execute("SELECT harga,item_discount_pct FROM menu WHERE id=?", (it['menu_id'],))
|
|
r = c.fetchone()
|
|
if not r:
|
|
continue
|
|
price, item_disc_pct = r
|
|
qty = it.get('qty',1)
|
|
line = price * qty
|
|
subtotal += line
|
|
if item_disc_pct and item_disc_pct > 0:
|
|
item_discount_total += (price * qty) * (item_disc_pct/100.0)
|
|
promo_discount = 0.0
|
|
promo_applied = None
|
|
if promo_code:
|
|
c.execute("SELECT type,value,min_total FROM promo WHERE code=?", (promo_code,))
|
|
row = c.fetchone()
|
|
if row:
|
|
ptype, val, min_total = row
|
|
if subtotal >= min_total:
|
|
if ptype == 'percent':
|
|
promo_discount = (subtotal - item_discount_total) * (val/100.0)
|
|
else:
|
|
promo_discount = val
|
|
promo_applied = promo_code
|
|
total = subtotal - item_discount_total - promo_discount
|
|
if total < 0:
|
|
total = 0.0
|
|
conn.close()
|
|
return {
|
|
'subtotal': round(subtotal,2),
|
|
'item_discount': round(item_discount_total,2),
|
|
'promo_code': promo_applied,
|
|
'promo_discount': round(promo_discount,2),
|
|
'total': round(total,2)
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# wilayah UI (universitas indonesia)
|
|
|
|
|
|
|
|
class App:
|
|
def __init__(self, root):
|
|
self.root = root
|
|
self.root.title("Cafe Totoro")
|
|
self.session = None
|
|
self.img_cache = {}
|
|
self.setup_ui()
|
|
|
|
def setup_ui(self):
|
|
self.root.geometry("1000x650")
|
|
self.root.resizable(False, False)
|
|
self.login_frame()
|
|
|
|
|
|
# windah batubara
|
|
|
|
# tampilan login dan logout
|
|
|
|
def login_frame(self):
|
|
for w in self.root.winfo_children():
|
|
w.destroy()
|
|
frame = ttk.Frame(self.root, padding=20)
|
|
frame.pack(expand=True)
|
|
|
|
ttk.Label(frame, text="LOGIN", font=("Arial", 24)).grid(row=0, column=0, columnspan=2, pady=10)
|
|
|
|
ttk.Label(frame, text="Username:").grid(row=1, column=0, sticky='e', pady=5)
|
|
self.username_var = tk.StringVar()
|
|
ttk.Entry(frame, textvariable=self.username_var, width=30).grid(row=1, column=1, pady=5)
|
|
|
|
ttk.Label(frame, text="Password:").grid(row=2, column=0, sticky='e', pady=5)
|
|
self.password_var = tk.StringVar()
|
|
ttk.Entry(frame, textvariable=self.password_var, show="*", width=30).grid(row=2, column=1, pady=5)
|
|
|
|
ttk.Button(frame, text="Login", command=self.handle_login).grid(row=3, column=0, columnspan=2, pady=12)
|
|
|
|
def handle_login(self):
|
|
u = self.username_var.get().strip()
|
|
p = self.password_var.get().strip()
|
|
if not u or not p:
|
|
messagebox.showwarning("Input", "Masukkan username & password")
|
|
return
|
|
user = authenticate(u,p)
|
|
if not user:
|
|
messagebox.showerror("Gagal", "Username atau password salah")
|
|
return
|
|
self.session = user
|
|
messagebox.showinfo("Sukses", f"Login berhasil sebagai {user['role']}")
|
|
self.dashboard_frame()
|
|
|
|
|
|
def logout(self):
|
|
self.session = None
|
|
self.img_cache.clear()
|
|
self.login_frame()
|
|
|
|
|
|
|
|
|
|
# tampilan dashboard untuk admin dah ngantuk we
|
|
|
|
def dashboard_frame(self):
|
|
for w in self.root.winfo_children():
|
|
w.destroy()
|
|
top = ttk.Frame(self.root)
|
|
top.pack(fill='x')
|
|
ttk.Label(top, text=f"User: {self.session['username']} | Role: {self.session['role']}",
|
|
font=("Arial", 12)).pack(side='left', padx=10, pady=6)
|
|
ttk.Button(top, text="Logout", command=self.logout).pack(side='right', padx=10)
|
|
main = ttk.Notebook(self.root)
|
|
main.pack(fill='both', expand=True, padx=10, pady=8)
|
|
self.tab_menu_manage = ttk.Frame(main)
|
|
self.tab_menu_view = ttk.Frame(main)
|
|
self.tab_promo = ttk.Frame(main)
|
|
self.tab_tests = ttk.Frame(main)
|
|
|
|
main.add(self.tab_menu_view, text="Menu - View")
|
|
if self.session['role'] == 'admin':
|
|
main.add(self.tab_menu_manage, text="Menu - Manage")
|
|
main.add(self.tab_promo, text="Promo - Manage")
|
|
main.add(self.tab_tests, text="Admin - Tests")
|
|
else:
|
|
pass
|
|
|
|
self.build_menu_view_tab(self.tab_menu_view)
|
|
if self.session['role'] == 'admin':
|
|
self.build_menu_manage_tab(self.tab_menu_manage)
|
|
self.build_promo_tab(self.tab_promo)
|
|
self.build_tests_tab(self.tab_tests)
|
|
|
|
|
|
|
|
|
|
|
|
# Bagian Search dan Filter
|
|
|
|
|
|
def build_menu_view_tab(self, parent):
|
|
for w in parent.winfo_children():
|
|
w.destroy()
|
|
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='y', padx=6, pady=6)
|
|
|
|
filter_frame = ttk.Frame(left)
|
|
filter_frame.pack(fill='x', pady=6)
|
|
ttk.Label(filter_frame, text="Cari / Nama atau Kategori:").pack(side='left', padx=3)
|
|
self.view_search_var = tk.StringVar()
|
|
ttk.Entry(filter_frame, textvariable=self.view_search_var, width=30).pack(side='left', padx=3)
|
|
ttk.Button(filter_frame, text="Cari", command=self.reload_view_table).pack(side='left', padx=3)
|
|
ttk.Button(filter_frame, text="Reset", command=self.reset_view_filters).pack(side='left', padx=3)
|
|
ttk.Button(filter_frame, text="Hanya Tersedia", command=lambda: self.reload_view_table(available_only=True)).pack(side='left', padx=6)
|
|
|
|
cols = ("ID","Nama","Kategori","Harga","Stok","Tersedia","ItemDisc%")
|
|
self.view_tree = ttk.Treeview(left, columns=cols, show='headings', height=18)
|
|
for c in cols:
|
|
self.view_tree.heading(c, text=c)
|
|
self.view_tree.column(c, width=90 if c!="Nama" else 200)
|
|
self.view_tree.pack(fill='both', expand=True)
|
|
self.view_tree.bind("<<TreeviewSelect>>", self.on_view_select)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Preview Image
|
|
|
|
|
|
ttk.Label(right, text="Preview Item", font=("Arial", 12, "bold")).pack(pady=6)
|
|
self.preview_label = ttk.Label(right, text="Pilih menu di kiri")
|
|
self.preview_label.pack()
|
|
self.preview_img_label = ttk.Label(right)
|
|
self.preview_img_label.pack(pady=6)
|
|
self.preview_detail = tk.Text(right, width=45, height=12)
|
|
self.preview_detail.pack()
|
|
|
|
self.reload_view_table()
|
|
|
|
def reload_view_table(self, available_only=False):
|
|
s = self.view_search_var.get().strip() if hasattr(self, 'view_search_var') else ""
|
|
results = menu_list(search_text=s or None, available_only=available_only)
|
|
for r in self.view_tree.get_children():
|
|
self.view_tree.delete(r)
|
|
for row in results:
|
|
mid,nama,kategori,harga,stok,foto,tersedia,item_disc = row
|
|
self.view_tree.insert("", tk.END, values=(mid,nama,kategori,harga,stok, "Yes" if tersedia else "No", item_disc))
|
|
|
|
def reset_view_filters(self):
|
|
self.view_search_var.set("")
|
|
self.reload_view_table()
|
|
|
|
def on_view_select(self, event):
|
|
sel = self.view_tree.selection()
|
|
if not sel:
|
|
return
|
|
item = self.view_tree.item(sel)['values']
|
|
menu_id = item[0]
|
|
data = menu_get(menu_id)
|
|
if not data:
|
|
return
|
|
mid,nama,kategori,harga,stok,foto,tersedia,item_disc = data
|
|
self.preview_detail.delete('1.0', tk.END)
|
|
txt = f"ID: {mid}\nNama: {nama}\nKategori: {kategori}\nHarga: {harga}\nStok: {stok}\nTersedia: {'Yes' if tersedia else 'No'}\nItem Discount: {item_disc}%\nFoto path: {foto}\n"
|
|
self.preview_detail.insert(tk.END, txt)
|
|
if foto and os.path.exists(foto):
|
|
try:
|
|
img = Image.open(foto)
|
|
img.thumbnail(IMG_PREVIEW_SIZE)
|
|
tkimg = ImageTk.PhotoImage(img)
|
|
self.img_cache['preview'] = tkimg
|
|
self.preview_img_label.config(image=tkimg)
|
|
except Exception as e:
|
|
self.preview_img_label.config(image='')
|
|
else:
|
|
self.preview_img_label.config(image='')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# bagian menu manage khusus admin
|
|
|
|
|
|
def build_menu_manage_tab(self, parent):
|
|
for w in parent.winfo_children():
|
|
w.destroy()
|
|
topfrm = ttk.Frame(parent)
|
|
topfrm.pack(fill='x', padx=6, pady=6)
|
|
ttk.Label(topfrm, text="Kelola Menu", font=("Arial", 14, "bold")).pack(side='left')
|
|
ttk.Button(topfrm, text="Tambah Menu", command=self.open_add_menu_window).pack(side='right', padx=6)
|
|
cols = ("ID","Nama","Kategori","Harga","Stok","Tersedia","ItemDisc%")
|
|
self.manage_tree = ttk.Treeview(parent, columns=cols, show='headings', height=18)
|
|
for c in cols:
|
|
self.manage_tree.heading(c, text=c)
|
|
self.manage_tree.column(c, width=100 if c!="Nama" else 220)
|
|
self.manage_tree.pack(fill='both', padx=6, pady=6)
|
|
btnfrm = ttk.Frame(parent)
|
|
btnfrm.pack(pady=6)
|
|
ttk.Button(btnfrm, text="Edit Terpilih", command=self.open_edit_menu_window).pack(side='left', padx=6)
|
|
ttk.Button(btnfrm, text="Hapus Terpilih", command=self.delete_selected_menu).pack(side='left', padx=6)
|
|
ttk.Button(btnfrm, text="Reload", command=self.reload_manage_table).pack(side='left', padx=6)
|
|
self.reload_manage_table()
|
|
|
|
def reload_manage_table(self):
|
|
for r in self.manage_tree.get_children():
|
|
self.manage_tree.delete(r)
|
|
rows = menu_list()
|
|
for row in rows:
|
|
mid,nama,kategori,harga,stok,foto,tersedia,item_disc = row
|
|
self.manage_tree.insert("", tk.END, values=(mid,nama,kategori,harga,stok,"Yes" if tersedia else "No", item_disc))
|
|
|
|
def open_add_menu_window(self):
|
|
w = tk.Toplevel(self.root)
|
|
w.title("Tambah Menu")
|
|
frm = ttk.Frame(w,padding=10)
|
|
frm.pack()
|
|
labels = ["Nama","Kategori","Harga","Stok","Foto path","Item Discount (%)"]
|
|
vars = {}
|
|
for i,lab in enumerate(labels):
|
|
ttk.Label(frm, text=lab).grid(row=i, column=0, sticky='e', pady=4)
|
|
vars[lab] = tk.StringVar()
|
|
ttk.Entry(frm, textvariable=vars[lab], width=40).grid(row=i, column=1, pady=4)
|
|
ttk.Button(frm, text="Pilih Foto", command=lambda: self.select_file(vars["Foto path"])).grid(row=4, column=2, padx=6)
|
|
def save():
|
|
try:
|
|
nama = vars["Nama"].get().strip()
|
|
kategori = vars["Kategori"].get().strip()
|
|
harga = float(vars["Harga"].get())
|
|
stok = int(vars["Stok"].get())
|
|
foto = vars["Foto path"].get().strip() or None
|
|
item_disc = float(vars["Item Discount (%)"].get() or 0)
|
|
except Exception as e:
|
|
messagebox.showerror("Input error", "Periksa kembali input (Harga/Stok harus angka)")
|
|
return
|
|
menu_add(nama,kategori,harga,stok,foto,item_disc)
|
|
messagebox.showinfo("Sukses","Menu ditambahkan")
|
|
w.destroy()
|
|
self.reload_manage_table()
|
|
self.reload_view_table()
|
|
ttk.Button(frm, text="Simpan", command=save).grid(row=len(labels), column=1, pady=8)
|
|
|
|
def open_edit_menu_window(self):
|
|
sel = self.manage_tree.selection()
|
|
if not sel:
|
|
messagebox.showwarning("Pilih", "Pilih menu terlebih dahulu")
|
|
return
|
|
item = self.manage_tree.item(sel)['values']
|
|
menu_id = item[0]
|
|
data = menu_get(menu_id)
|
|
if not data:
|
|
messagebox.showerror("Error", "Data menu tidak ditemukan")
|
|
return
|
|
mid,nama,kategori,harga,stok,foto,tersedia,item_disc = data
|
|
w = tk.Toplevel(self.root)
|
|
w.title("Edit Menu")
|
|
frm = ttk.Frame(w,padding=10)
|
|
frm.pack()
|
|
labels = ["Nama","Kategori","Harga","Stok","Foto path","Item Discount (%)"]
|
|
vars = {}
|
|
defaults = [nama,kategori,str(harga),str(stok),foto or "",str(item_disc or 0)]
|
|
for i,lab in enumerate(labels):
|
|
ttk.Label(frm, text=lab).grid(row=i, column=0, sticky='e', pady=4)
|
|
vars[lab] = tk.StringVar(value=defaults[i])
|
|
ttk.Entry(frm, textvariable=vars[lab], width=40).grid(row=i, column=1, pady=4)
|
|
ttk.Button(frm, text="Pilih Foto", command=lambda: self.select_file(vars["Foto path"])).grid(row=4, column=2, padx=6)
|
|
def save():
|
|
try:
|
|
nama = vars["Nama"].get().strip()
|
|
kategori = vars["Kategori"].get().strip()
|
|
harga = float(vars["Harga"].get())
|
|
stok = int(vars["Stok"].get())
|
|
foto = vars["Foto path"].get().strip() or None
|
|
item_disc = float(vars["Item Discount (%)"].get() or 0)
|
|
except:
|
|
messagebox.showerror("Input error", "Periksa input")
|
|
return
|
|
menu_update(menu_id, nama, kategori, harga, stok, foto, item_disc)
|
|
messagebox.showinfo("Sukses","Menu diperbarui")
|
|
w.destroy()
|
|
self.reload_manage_table()
|
|
self.reload_view_table()
|
|
ttk.Button(frm, text="Update", command=save).grid(row=len(labels), column=1, pady=8)
|
|
|
|
def delete_selected_menu(self):
|
|
sel = self.manage_tree.selection()
|
|
if not sel:
|
|
messagebox.showwarning("Pilih", "Pilih menu untuk dihapus")
|
|
return
|
|
item = self.manage_tree.item(sel)['values']
|
|
menu_id = item[0]
|
|
if messagebox.askyesno("Konfirmasi", "Hapus menu terpilih?"):
|
|
menu_delete(menu_id)
|
|
messagebox.showinfo("Dihapus", "Menu berhasil dihapus")
|
|
self.reload_manage_table()
|
|
self.reload_view_table()
|
|
|
|
def select_file(self, var):
|
|
p = filedialog.askopenfilename(title="Pilih file gambar",
|
|
filetypes=[("Image files","*.png;*.jpg;*.jpeg;*.gif;*.bmp"),("All files","*.*")])
|
|
if p:
|
|
var.set(p)
|