DB to CSV

This commit is contained in:
Bluwww 2025-12-03 15:42:08 +07:00
parent b1f67c9a3f
commit 388d55be6a
4 changed files with 384 additions and 249 deletions

579
main.py
View File

@ -6,60 +6,70 @@
- owner / owner123 (role pemilik) - owner / owner123 (role pemilik)
""" """
import sqlite3
import os import os
import csv
import tkinter as tk import tkinter as tk
from tkinter import ttk, messagebox, filedialog from tkinter import ttk, messagebox, filedialog
from PIL import Image, ImageTk from PIL import Image, ImageTk
DB_PATH = "cafe_person1.db" USERS_CSV = "users.csv"
MENU_CSV = "menu.csv"
PROMO_CSV = "promo.csv"
IMG_PREVIEW_SIZE = (120, 80) IMG_PREVIEW_SIZE = (120, 80)
def ensure_file(path, fieldnames):
if not os.path.exists(path):
with open(path, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
def read_all(path):
if not os.path.exists(path):
return []
with open(path, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
return list(reader)
def write_all(path, fieldnames, rows):
with open(path, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
def next_int_id(rows, id_field="id"):
max_id = 0
for r in rows:
try:
v = int(r.get(id_field, 0) or 0)
if v > max_id:
max_id = v
except:
continue
return str(max_id + 1)
# Baguan Database (ati ati) def init_db_csv():
ensure_file(USERS_CSV, ["id", "username", "password", "role"])
ensure_file(MENU_CSV, ["id", "nama", "kategori", "harga", "stok", "foto", "tersedia", "item_discount_pct"])
ensure_file(PROMO_CSV, ["code", "type", "value", "min_total"])
seed_defaults()
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()
# buat masukin data/sample ke database csv
def seed_defaults():
users = read_all(USERS_CSV)
if not users:
defaults = [ defaults = [
('admin','admin123','admin'), ('admin','admin123','admin'),
('kasir','kasir123','kasir'), ('kasir','kasir123','kasir'),
@ -67,41 +77,63 @@ def seed_defaults(conn):
('user','user123','pembeli'), ('user','user123','pembeli'),
('owner','owner123','pemilik'), ('owner','owner123','pemilik'),
] ]
for u,p,r in defaults: rows = []
try: for i,(u,p,r) in enumerate(defaults, start=1):
c.execute("INSERT INTO users (username,password,role) VALUES (?,?,?)", (u,p,r)) rows.append({"id": str(i), "username": u, "password": p, "role": r})
except sqlite3.IntegrityError: write_all(USERS_CSV, ["id","username","password","role"], rows)
pass
menu_rows = read_all(MENU_CSV)
if not menu_rows:
sample = [ sample = [
('Americano','Minuman',20000,10,None,1,0), ('Americano','Minuman',20000,10,None,1,0),
('Latte','Minuman',25000,5,None,1,10), ('Latte','Minuman',25000,5,None,1,10),
('Banana Cake','Dessert',30000,2,None,1,0), ('Banana Cake','Dessert',30000,2,None,1,0),
('Nasi Goreng','Makanan',35000,0,None,0,0), ('Nasi Goreng','Makanan',35000,0,None,0,0),
] ]
for name,kategori,harga,stok,foto,tersedia,disc in sample: rows = []
c.execute("SELECT id FROM menu WHERE nama=?", (name,)) for i,(name,kategori,harga,stok,foto,tersedia,disc) in enumerate(sample, start=1):
if c.fetchone() is None: rows.append({
c.execute("""INSERT INTO menu (nama,kategori,harga,stok,foto,tersedia,item_discount_pct) "id": str(i),
VALUES (?,?,?,?,?,?,?)""", (name,kategori,harga,stok,foto,tersedia,disc)) "nama": name,
"kategori": kategori,
"harga": str(harga),
"stok": str(stok),
"foto": foto or "",
"tersedia": str(tersedia),
"item_discount_pct": str(disc)
})
write_all(MENU_CSV, ["id","nama","kategori","harga","stok","foto","tersedia","item_discount_pct"], rows)
promo_rows = read_all(PROMO_CSV)
if not promo_rows:
promos = [ promos = [
('CAFE10','percent',10,0), ('PARDEDE','percent',10,0),
('HEMAT5000','fixed',5000,20000), ('BOTAK','fixed',5000,20000),
] ]
rows = []
for code,ptype,val,min_total in promos: for code,ptype,val,min_total in promos:
try: rows.append({
c.execute("INSERT INTO promo (code,type,value,min_total) VALUES (?,?,?,?)", (code,ptype,val,min_total)) "code": code,
except sqlite3.IntegrityError: "type": ptype,
pass "value": str(val),
conn.commit() "min_total": str(min_total)
})
write_all(PROMO_CSV, ["code","type","value","min_total"], rows)
def authenticate(username, password): def authenticate(username, password):
conn = sqlite3.connect(DB_PATH) rows = read_all(USERS_CSV)
c = conn.cursor() for r in rows:
c.execute("SELECT id,username,role FROM users WHERE username=? AND password=?", (username,password)) if r.get("username") == username and r.get("password") == password:
r = c.fetchone() return {'id': int(r.get("id")), 'username': r.get("username"), 'role': r.get("role")}
conn.close()
if r:
return {'id':r[0],'username':r[1],'role':r[2]}
return None return None
@ -110,170 +142,291 @@ def authenticate(username, password):
# Bagian Menu wel
# Wilayah dikuasai Menu
def menu_add(nama, kategori, harga, stok, foto, item_discount_pct=0): def menu_add(nama, kategori, harga, stok, foto, item_discount_pct=0):
conn = sqlite3.connect(DB_PATH) rows = read_all(MENU_CSV)
c = conn.cursor() new_id = next_int_id(rows, "id")
tersedia = 1 if stok>0 else 0 tersedia = "1" if int(stok) > 0 else "0"
c.execute("""INSERT INTO menu (nama,kategori,harga,stok,foto,tersedia,item_discount_pct) rows.append({
VALUES (?,?,?,?,?,?,?)""", (nama,kategori,harga,stok,foto,tersedia,item_discount_pct)) "id": new_id,
conn.commit() "nama": nama,
conn.close() "kategori": kategori,
"harga": str(float(harga)),
"stok": str(int(stok)),
"foto": foto or "",
"tersedia": tersedia,
"item_discount_pct": str(float(item_discount_pct))
})
write_all(MENU_CSV, ["id","nama","kategori","harga","stok","foto","tersedia","item_discount_pct"], rows)
def menu_update(menu_id, nama, kategori, harga, stok, foto, item_discount_pct=0): def menu_update(menu_id, nama, kategori, harga, stok, foto, item_discount_pct=0):
conn = sqlite3.connect(DB_PATH) rows = read_all(MENU_CSV)
c = conn.cursor() found = False
tersedia = 1 if stok>0 else 0 for r in rows:
c.execute("""UPDATE menu SET nama=?,kategori=?,harga=?,stok=?,foto=?,tersedia=?,item_discount_pct=? if r.get("id") == str(menu_id):
WHERE id=?""", (nama,kategori,harga,stok,foto,tersedia,item_discount_pct, menu_id)) r["nama"] = nama
conn.commit() r["kategori"] = kategori
conn.close() r["harga"] = str(float(harga))
r["stok"] = str(int(stok))
r["foto"] = foto or ""
r["tersedia"] = "1" if int(stok) > 0 else "0"
r["item_discount_pct"] = str(float(item_discount_pct))
found = True
break
if found:
write_all(MENU_CSV, ["id","nama","kategori","harga","stok","foto","tersedia","item_discount_pct"], rows)
else:
raise ValueError("Menu id tidak ditemukan")
def menu_delete(menu_id): def menu_delete(menu_id):
conn = sqlite3.connect(DB_PATH) rows = read_all(MENU_CSV)
c = conn.cursor() newrows = [r for r in rows if r.get("id") != str(menu_id)]
c.execute("DELETE FROM menu WHERE id=?", (menu_id,)) write_all(MENU_CSV, ["id","nama","kategori","harga","stok","foto","tersedia","item_discount_pct"], newrows)
conn.commit()
conn.close()
def menu_list(kategori=None, available_only=False, search_text=None): def menu_list(kategori=None, available_only=False, search_text=None):
conn = sqlite3.connect(DB_PATH) rows = read_all(MENU_CSV)
c = conn.cursor() out = []
q = "SELECT id,nama,kategori,harga,stok,foto,tersedia,item_discount_pct FROM menu" for r in rows:
conditions = [] if kategori and r.get("kategori") != kategori:
params = [] continue
if kategori: if available_only and r.get("tersedia") != "1":
conditions.append("kategori=?") continue
params.append(kategori)
if available_only:
conditions.append("tersedia=1")
if search_text: if search_text:
conditions.append("(nama LIKE ? OR kategori LIKE ?)") s = search_text.lower()
params += [f"%{search_text}%", f"%{search_text}%"] if s not in (r.get("nama","").lower() or "") and s not in (r.get("kategori","").lower() or ""):
if conditions: continue
q += " WHERE " + " AND ".join(conditions) try:
q += " ORDER BY id ASC" mid = int(r.get("id") or 0)
c.execute(q, params) except:
rows = c.fetchall() mid = r.get("id")
conn.close() try:
return rows harga = float(r.get("harga") or 0.0)
except:
harga = 0.0
try:
stok = int(float(r.get("stok") or 0))
except:
stok = 0
foto = r.get("foto") or None
tersedia = 1 if r.get("tersedia") == "1" else 0
try:
item_disc = float(r.get("item_discount_pct") or 0.0)
except:
item_disc = 0.0
out.append((mid, r.get("nama"), r.get("kategori"), harga, stok, foto, tersedia, item_disc))
out.sort(key=lambda x: int(x[0]))
return out
def menu_get(menu_id): def menu_get(menu_id):
conn = sqlite3.connect(DB_PATH) rows = read_all(MENU_CSV)
c = conn.cursor() for r in rows:
c.execute("SELECT id,nama,kategori,harga,stok,foto,tersedia,item_discount_pct FROM menu WHERE id=?", (menu_id,)) if r.get("id") == str(menu_id):
r = c.fetchone() try:
conn.close() mid = int(r.get("id") or 0)
return r except:
mid = r.get("id")
try:
harga = float(r.get("harga") or 0.0)
except:
harga = 0.0
try:
stok = int(float(r.get("stok") or 0))
except:
stok = 0
foto = r.get("foto") or None
tersedia = 1 if r.get("tersedia") == "1" else 0
try:
item_disc = float(r.get("item_discount_pct") or 0.0)
except:
item_disc = 0.0
return (mid, r.get("nama"), r.get("kategori"), harga, stok, foto, tersedia, item_disc)
return None
def menu_decrease_stock(menu_id, qty): def menu_decrease_stock(menu_id, qty):
conn = sqlite3.connect(DB_PATH) rows = read_all(MENU_CSV)
c = conn.cursor() found = False
c.execute("SELECT stok FROM menu WHERE id=?", (menu_id,)) for r in rows:
r = c.fetchone() if r.get("id") == str(menu_id):
if not r: found = True
conn.close() try:
return False, "Menu tidak ditemukan" stok = int(float(r.get("stok") or 0))
stok = r[0] except:
stok = 0
if stok < qty: if stok < qty:
conn.close()
return False, "Stok tidak cukup" return False, "Stok tidak cukup"
newstok = stok - qty newstok = stok - qty
tersedia = 1 if newstok>0 else 0 r["stok"] = str(newstok)
c.execute("UPDATE menu SET stok=?, tersedia=? WHERE id=?", (newstok, tersedia, menu_id)) r["tersedia"] = "1" if newstok > 0 else "0"
conn.commit() break
conn.close() if not found:
return False, "Menu tidak ditemukan"
write_all(MENU_CSV, ["id","nama","kategori","harga","stok","foto","tersedia","item_discount_pct"], rows)
return True, newstok return True, newstok
# Bagian Promooo
# Reza balap liar
# wilayah dikuasai promo
def promo_add(code, ptype, value, min_total=0): def promo_add(code, ptype, value, min_total=0):
conn = sqlite3.connect(DB_PATH) rows = read_all(PROMO_CSV)
c = conn.cursor() for r in rows:
c.execute("INSERT INTO promo (code,type,value,min_total) VALUES (?,?,?,?)", (code,ptype,value,min_total)) if r.get("code") == code:
conn.commit() raise ValueError("Kode promo sudah ada")
conn.close() rows.append({
"code": code,
"type": ptype,
"value": str(float(value)),
"min_total": str(float(min_total))
})
write_all(PROMO_CSV, ["code","type","value","min_total"], rows)
def promo_update(code, ptype, value, min_total=0): def promo_update(code, ptype, value, min_total=0):
conn = sqlite3.connect(DB_PATH) rows = read_all(PROMO_CSV)
c = conn.cursor() found = False
c.execute("UPDATE promo SET type=?, value=?, min_total=? WHERE code=?", (ptype,value,min_total,code)) for r in rows:
conn.commit() if r.get("code") == code:
conn.close() r["type"] = ptype
r["value"] = str(float(value))
r["min_total"] = str(float(min_total))
found = True
break
if not found:
raise ValueError("Promo tidak ditemukan")
write_all(PROMO_CSV, ["code","type","value","min_total"], rows)
def promo_delete(code): def promo_delete(code):
conn = sqlite3.connect(DB_PATH) rows = read_all(PROMO_CSV)
c = conn.cursor() newrows = [r for r in rows if r.get("code") != code]
c.execute("DELETE FROM promo WHERE code=?", (code,)) write_all(PROMO_CSV, ["code","type","value","min_total"], newrows)
conn.commit()
conn.close()
def promo_list(): def promo_list():
conn = sqlite3.connect(DB_PATH) rows = read_all(PROMO_CSV)
c = conn.cursor() out = []
c.execute("SELECT code,type,value,min_total FROM promo ORDER BY code") for r in rows:
rows = c.fetchall() try:
conn.close() val = float(r.get("value") or 0.0)
return rows except:
val = 0.0
try:
mt = float(r.get("min_total") or 0.0)
except:
mt = 0.0
out.append((r.get("code"), r.get("type"), val, mt))
out.sort(key=lambda x: x[0] or "")
return out
def promo_get(code): def promo_get(code):
conn = sqlite3.connect(DB_PATH) rows = read_all(PROMO_CSV)
c = conn.cursor() for r in rows:
c.execute("SELECT code,type,value,min_total FROM promo WHERE code=?", (code,)) if r.get("code") == code:
r = c.fetchone() try:
conn.close() val = float(r.get("value") or 0.0)
return r except:
val = 0.0
try:
mt = float(r.get("min_total") or 0.0)
except:
mt = 0.0
return (r.get("code"), r.get("type"), val, mt)
return None
# 19 juta lapangan badmin
# Buat logika diskon + promok
def apply_discounts_and_promo(cart_items, promo_code=None): 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 subtotal = 0.0
item_discount_total = 0.0 item_discount_total = 0.0
menu_rows = read_all(MENU_CSV)
menu_dict = {r["id"]: r for r in menu_rows}
for it in cart_items: for it in cart_items:
c.execute("SELECT harga,item_discount_pct FROM menu WHERE id=?", (it['menu_id'],)) mid = str(it.get('menu_id'))
r = c.fetchone() r = menu_dict.get(mid)
if not r: if not r:
continue continue
price, item_disc_pct = r try:
qty = it.get('qty',1) price = float(r.get("harga") or 0.0)
except:
price = 0.0
try:
item_disc_pct = float(r.get("item_discount_pct") or 0.0)
except:
item_disc_pct = 0.0
qty = int(it.get('qty', 1))
line = price * qty line = price * qty
subtotal += line subtotal += line
if item_disc_pct and item_disc_pct > 0: if item_disc_pct and item_disc_pct > 0:
item_discount_total += (price * qty) * (item_disc_pct/100.0) item_discount_total += (price * qty) * (item_disc_pct / 100.0)
promo_discount = 0.0 promo_discount = 0.0
promo_applied = None promo_applied = None
if promo_code: if promo_code:
c.execute("SELECT type,value,min_total FROM promo WHERE code=?", (promo_code,)) p = promo_get(promo_code)
row = c.fetchone() if p:
if row: _, ptype, val, min_total = p
ptype, val, min_total = row if subtotal >= (min_total or 0.0):
if subtotal >= min_total:
if ptype == 'percent': if ptype == 'percent':
promo_discount = (subtotal - item_discount_total) * (val/100.0) promo_discount = (subtotal - item_discount_total) * (val / 100.0)
else: else:
promo_discount = val promo_discount = val
promo_applied = promo_code promo_applied = promo_code
total = subtotal - item_discount_total - promo_discount total = subtotal - item_discount_total - promo_discount
if total < 0: if total < 0:
total = 0.0 total = 0.0
conn.close()
return { return {
'subtotal': round(subtotal,2), 'subtotal': round(subtotal, 2),
'item_discount': round(item_discount_total,2), 'item_discount': round(item_discount_total, 2),
'promo_code': promo_applied, 'promo_code': promo_applied,
'promo_discount': round(promo_discount,2), 'promo_discount': round(promo_discount, 2),
'total': round(total,2) 'total': round(total, 2)
} }
@ -281,14 +434,23 @@ def apply_discounts_and_promo(cart_items, promo_code=None):
# wilayah UI (universitas indonesia)
# Wilayah dikuasai UI
class App: class App:
def __init__(self, root): def __init__(self, root):
self.root = root self.root = root
self.root.title("Cafe Totoro") self.root.title("Cafe Totoro Mania")
self.session = None self.session = None
self.img_cache = {} self.img_cache = {}
self.setup_ui() self.setup_ui()
@ -298,18 +460,13 @@ class App:
self.root.resizable(False, False) self.root.resizable(False, False)
self.login_frame() self.login_frame()
# windah batubara
# tampilan login dan logout
def login_frame(self): def login_frame(self):
for w in self.root.winfo_children(): for w in self.root.winfo_children():
w.destroy() w.destroy()
frame = ttk.Frame(self.root, padding=20) frame = ttk.Frame(self.root, padding=20)
frame.pack(expand=True) 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="Login kak", 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) ttk.Label(frame, text="Username:").grid(row=1, column=0, sticky='e', pady=5)
self.username_var = tk.StringVar() self.username_var = tk.StringVar()
@ -335,17 +492,11 @@ class App:
messagebox.showinfo("Sukses", f"Login berhasil sebagai {user['role']}") messagebox.showinfo("Sukses", f"Login berhasil sebagai {user['role']}")
self.dashboard_frame() self.dashboard_frame()
def logout(self): def logout(self):
self.session = None self.session = None
self.img_cache.clear() self.img_cache.clear()
self.login_frame() self.login_frame()
# tampilan dashboard untuk admin dah ngantuk we
def dashboard_frame(self): def dashboard_frame(self):
for w in self.root.winfo_children(): for w in self.root.winfo_children():
w.destroy() w.destroy()
@ -372,13 +523,6 @@ class App:
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)
# Bagian Search dan Filter
def build_menu_view_tab(self, parent): def build_menu_view_tab(self, parent):
for w in parent.winfo_children(): for w in parent.winfo_children():
w.destroy() w.destroy()
@ -404,14 +548,6 @@ class App:
self.view_tree.pack(fill='both', expand=True) self.view_tree.pack(fill='both', expand=True)
self.view_tree.bind("<<TreeviewSelect>>", self.on_view_select) self.view_tree.bind("<<TreeviewSelect>>", self.on_view_select)
# Preview Image
ttk.Label(right, text="Preview Item", font=("Arial", 12, "bold")).pack(pady=6) 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 = ttk.Label(right, text="Pilih menu di kiri")
self.preview_label.pack() self.preview_label.pack()
@ -460,15 +596,6 @@ class App:
else: else:
self.preview_img_label.config(image='') self.preview_img_label.config(image='')
# bagian menu manage khusus admin
def build_menu_manage_tab(self, parent): def build_menu_manage_tab(self, parent):
for w in parent.winfo_children(): for w in parent.winfo_children():
w.destroy() w.destroy()
@ -588,16 +715,6 @@ class App:
if p: if p:
var.set(p) var.set(p)
# Promo manage Khusus Admin
def build_promo_tab(self, parent): def build_promo_tab(self, parent):
for w in parent.winfo_children(): for w in parent.winfo_children():
w.destroy() w.destroy()
@ -671,12 +788,11 @@ class App:
messagebox.showinfo("Sukses", "Promo ditambahkan") messagebox.showinfo("Sukses", "Promo ditambahkan")
w.destroy() w.destroy()
self.reload_promo_table() self.reload_promo_table()
except sqlite3.IntegrityError: except Exception as e:
messagebox.showerror("Error", "Kode promo sudah ada") messagebox.showerror("Error", f"Kode promo sudah ada atau error: {e}")
ttk.Button(frm, text="Simpan", command=save).grid(row=4, column=1, pady=12) ttk.Button(frm, text="Simpan", command=save).grid(row=4, column=1, pady=12)
def open_edit_promo(self): def open_edit_promo(self):
sel = self.promo_tree.selection() sel = self.promo_tree.selection()
if not sel: if not sel:
@ -736,7 +852,6 @@ class App:
ttk.Button(frm, text="Update", command=save).grid(row=4, column=1, pady=12) ttk.Button(frm, text="Update", command=save).grid(row=4, column=1, pady=12)
def delete_selected_promo(self): def delete_selected_promo(self):
sel = self.promo_tree.selection() sel = self.promo_tree.selection()
if not sel: if not sel:
@ -750,10 +865,16 @@ class App:
# Done
if __name__ == "__main__": if __name__ == "__main__":
init_conn = init_db() init_db_csv()
init_conn.close()
root = tk.Tk() root = tk.Tk()
app = App(root) app = App(root)
root.mainloop() root.mainloop()

5
menu.csv Normal file
View File

@ -0,0 +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
4,Nasi Goreng,Makanan,35000,0,,0,0
1 id nama kategori harga stok foto tersedia item_discount_pct
2 1 Americano Minuman 20000 10 1 0
3 2 Latte Minuman 25000 5 1 10
4 3 Banana Cake Dessert 30000 2 1 0
5 4 Nasi Goreng Makanan 35000 0 0 0

3
promo.csv Normal file
View File

@ -0,0 +1,3 @@
code,type,value,min_total
PARDEDE,percent,10,0
BOTAK,fixed,5000,20000
1 code type value min_total
2 PARDEDE percent 10 0
3 BOTAK fixed 5000 20000

6
users.csv Normal file
View File

@ -0,0 +1,6 @@
id,username,password,role
1,admin,admin123,admin
2,kasir,kasir123,kasir
3,waiter,waiter123,waiter
4,user,user123,pembeli
5,owner,owner123,pemilik
1 id username password role
2 1 admin admin123 admin
3 2 kasir kasir123 kasir
4 3 waiter waiter123 waiter
5 4 user user123 pembeli
6 5 owner owner123 pemilik