saindras

pbo-pertemuan-11-gui_app.py

Nov 11th, 2025
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 24.31 KB | None | 0 0
  1. # gui_app.py
  2. import tkinter as tk
  3. from tkinter import messagebox, ttk
  4. # Import kelas-kelas backend kita
  5. # Pastikan file perpustakaan_backend.py ada di folder yang sama
  6. from perpustakaan_backend import Perpustakaan, Pustakawan, StatusItem, StatusTransaksi
  7.  
  8. class AppPerpustakaan:
  9. # ... (kode __init__ dan buat_tampilan_utama tetap sama) ...
  10.     """
  11.    Kelas utama untuk aplikasi GUI Sistem Perpustakaan.
  12.    Ini bertindak sebagai 'View' dan 'Controller' sederhana.
  13.    """
  14.     def __init__(self, root):
  15.         self.root = root
  16.         self.root.title("Sistem Manajemen Perpustakaan")
  17.         self.root.geometry("900x1200")
  18.  
  19.         # 1. Inisialisasi Backend
  20.         # Kita buat satu objek perpustakaan dan pustakawan yang akan dipakai
  21.         try:
  22.             nama_file_db = "Tkinter/perpus_data.pkl"
  23.             self.perpustakaan_utama = Perpustakaan(nama_file_db) # Muat data jika ada
  24.         except Exception as e:
  25.             messagebox.showerror("Startup Error", f"Gagal memuat data: {e}")
  26.             self.perpustakaan_utama = Perpustakaan(nama_file_db) # Coba buat baru
  27.            
  28.         self.pustakawan_andi = Pustakawan("P-001", "Andi")
  29.        
  30.         # Inisialisasi data awal jika perpustakaan kosong (untuk demo)
  31.         if not self.perpustakaan_utama.daftar_item:
  32.             print("INFO: Menambahkan data item awal untuk demo...")
  33.             self.pustakawan_andi.tambah_item_ke_koleksi(self.perpustakaan_utama, "Buku", "BK-001", "OOP Python", pengarang="Dr. Inovatif")
  34.             self.pustakawan_andi.tambah_item_ke_koleksi(self.perpustakaan_utama, "Majalah", "MGZ-001", "Quanta", edisi="Okt 2025")
  35.             self.pustakawan_andi.tambah_item_ke_koleksi(self.perpustakaan_utama, "Buku", "BK-002", "Sains Data", pengarang="Prof. Analitika")
  36.  
  37.         # 2. Setup Tampilan Utama
  38.         self.buat_tampilan_utama()
  39.  
  40.     def buat_tampilan_utama(self):
  41.         # Judul Utama
  42.         judul = tk.Label(self.root, text="Sistem Perpustakaan", font=("Helvetica", 18, "bold"))
  43.         judul.pack(pady=10) # Pack untuk judul
  44.  
  45.         # Buat Notebook (Tabs) untuk memisahkan fungsionalitas
  46.         self.tab_kontrol = ttk.Notebook(self.root)
  47.        
  48.         self.tab1 = ttk.Frame(self.tab_kontrol)
  49.         self.tab2 = ttk.Frame(self.tab_kontrol)
  50.        
  51.         self.tab_kontrol.add(self.tab1, text='Manajemen Koleksi & Member')
  52.         self.tab_kontrol.add(self.tab2, text='Transaksi Peminjaman')
  53.        
  54.         self.tab_kontrol.pack(expand=True, fill="both", padx=10, pady=10)
  55.  
  56.         # Panggil fungsi untuk membangun konten tiap tab
  57.         self.buat_tab_manajemen(self.tab1)
  58.         self.buat_tab_transaksi(self.tab2)
  59.  
  60.         # Tombol Simpan & Keluar
  61.         # Kita letakkan di bawah, jadi kita buat framenya dulu
  62.         frame_bawah = tk.Frame(self.root)
  63.         frame_bawah.pack(side=tk.BOTTOM, fill="x", pady=10)
  64.        
  65.         tombol_simpan = tk.Button(frame_bawah, text="Simpan Data & Keluar", command=self.simpan_dan_keluar)
  66.         tombol_simpan.pack(pady=5, padx=10)
  67.  
  68.     def buat_tab_manajemen(self, tab):
  69. # ... (kode buat_tab_manajemen tetap sama) ...
  70.         """Membangun konten untuk Tab 1."""
  71.        
  72.         # --- Frame Atas (Form Member & Daftar Item) ---
  73.         frame_atas = tk.Frame(tab)
  74.         frame_atas.pack(side=tk.TOP, fill="x", pady=5)
  75.  
  76.         # Buat frame kiri untuk menampung dua form
  77.         frame_kiri_forms = tk.Frame(frame_atas)
  78.         frame_kiri_forms.pack(side=tk.LEFT, fill="y", padx=5, anchor='n')
  79.  
  80.         # --- Frame Kiri Atas: Form Tambah Anggota ---
  81.         frame_tambah_member = tk.LabelFrame(frame_kiri_forms, text="Form Tambah Anggota Baru", padx=10, pady=10)
  82.         frame_tambah_member.pack(side=tk.TOP, fill="y", padx=5, anchor='n')
  83.  
  84.         # Layout .grid() untuk form
  85.         label_nama = tk.Label(frame_tambah_member, text="Nama:")
  86.         label_nama.grid(row=0, column=0, sticky="e", padx=5)
  87.         self.entry_nama = tk.Entry(frame_tambah_member, width=30)
  88.         self.entry_nama.grid(row=0, column=1, padx=5, pady=5)
  89.  
  90.         label_alamat = tk.Label(frame_tambah_member, text="Alamat:")
  91.         label_alamat.grid(row=1, column=0, sticky="e", padx=5)
  92.         self.entry_alamat = tk.Entry(frame_tambah_member, width=30)
  93.         self.entry_alamat.grid(row=1, column=1, padx=5, pady=5)
  94.  
  95.         tombol_submit_member = tk.Button(frame_tambah_member, text="Daftarkan", command=self.daftar_member_baru)
  96.         tombol_submit_member.grid(row=2, column=1, sticky="w", padx=5, pady=10)
  97.  
  98.         # --- Frame Kiri Bawah: Form Tambah Item ---
  99.         frame_tambah_item = tk.LabelFrame(frame_kiri_forms, text="Form Tambah Item Baru", padx=10, pady=10)
  100.         frame_tambah_item.pack(side=tk.TOP, fill="y", padx=5, anchor='n', pady=10)
  101.  
  102.         # Widget untuk form tambah item
  103.         label_tipe = tk.Label(frame_tambah_item, text="Tipe Item:")
  104.         label_tipe.grid(row=0, column=0, sticky="e", padx=5)
  105.         self.combo_tipe_item = ttk.Combobox(frame_tambah_item, values=["Buku", "Majalah"], width=27, state="readonly")
  106.         self.combo_tipe_item.grid(row=0, column=1, padx=5, pady=5)
  107.         self.combo_tipe_item.bind("<<ComboboxSelected>>", self.on_tipe_item_changed)
  108.        
  109.         label_item_id = tk.Label(frame_tambah_item, text="ID Item:")
  110.         label_item_id.grid(row=1, column=0, sticky="e", padx=5)
  111.         self.entry_item_id = tk.Entry(frame_tambah_item, width=30)
  112.         self.entry_item_id.grid(row=1, column=1, padx=5, pady=5)
  113.        
  114.         label_item_judul = tk.Label(frame_tambah_item, text="Judul:")
  115.         label_item_judul.grid(row=2, column=0, sticky="e", padx=5)
  116.         self.entry_item_judul = tk.Entry(frame_tambah_item, width=30)
  117.         self.entry_item_judul.grid(row=2, column=1, padx=5, pady=5)
  118.        
  119.         # Label dan Entry dinamis (Pengarang/Edisi)
  120.         self.label_khusus = tk.Label(frame_tambah_item, text="Pengarang/Edisi:")
  121.         self.label_khusus.grid(row=3, column=0, sticky="e", padx=5)
  122.         self.entry_khusus = tk.Entry(frame_tambah_item, width=30)
  123.         self.entry_khusus.grid(row=3, column=1, padx=5, pady=5)
  124.        
  125.         tombol_submit_item = tk.Button(frame_tambah_item, text="Tambahkan Item", command=self.tambah_item_baru)
  126.         tombol_submit_item.grid(row=4, column=1, sticky="w", padx=5, pady=10)
  127.        
  128.         # Panggil on_tipe_item_changed untuk set default
  129.         self.combo_tipe_item.set("Buku") # Set default
  130.         self.on_tipe_item_changed(None) # Panggil manual untuk set label
  131.  
  132.         # --- Frame Kanan Atas: Daftar Koleksi Item ---
  133.         frame_daftar_koleksi_item = tk.LabelFrame(frame_atas, text="Daftar Koleksi Item", padx=10, pady=10)
  134.         frame_daftar_koleksi_item.pack(side=tk.LEFT, fill="both", expand=True, padx=5)
  135.  
  136.         tombol_refresh_daftar_koleksi_item = tk.Button(frame_daftar_koleksi_item, text="Refresh Daftar Buku", command=self.refresh_daftar_buku)
  137.         tombol_refresh_daftar_koleksi_item.pack(pady=5, anchor='w')
  138.  
  139.         self.tree_buku = ttk.Treeview(frame_daftar_koleksi_item, columns=("ID", "Judul", "Status"), show="headings")
  140.         self.tree_buku.heading("ID", text="ID Item")
  141.         self.tree_buku.heading("Judul", text="Judul")
  142.         self.tree_buku.heading("Status", text="Status")
  143.         self.tree_buku.column("ID", width=80)
  144.         self.tree_buku.column("Judul", width=200)
  145.         self.tree_buku.column("Status", width=100)
  146.         self.tree_buku.pack(fill="both", expand=True)
  147.  
  148.         # --- Frame Tengah (Daftar Member) ---
  149.         frame_daftar_member = tk.LabelFrame(tab, text="Daftar Member", padx=10, pady=10)
  150.         frame_daftar_member.pack(side=tk.TOP, fill="both", expand=True, pady=10)
  151.        
  152.         frame_tombol_member = tk.Frame(frame_daftar_member)
  153.         frame_tombol_member.pack(fill="x")
  154.        
  155.         tombol_refresh_member = tk.Button(frame_tombol_member, text="Refresh Daftar Member", command=self.refresh_daftar_member)
  156.         tombol_refresh_member.pack(side=tk.LEFT, pady=5, anchor='w')
  157.  
  158.         tombol_riwayat_member = tk.Button(frame_tombol_member, text="Tampilkan Riwayat Member Terpilih", command=self.tampilkan_riwayat_terpilih)
  159.         tombol_riwayat_member.pack(side=tk.LEFT, pady=5, padx=10, anchor='w')
  160.  
  161.         self.tree_member = ttk.Treeview(frame_daftar_member, columns=("ID", "Nama", "Alamat"), show="headings")
  162.         self.tree_member.heading("ID", text="ID Member")
  163.         self.tree_member.heading("Nama", text="Nama")
  164.         self.tree_member.heading("Alamat", text="Alamat")
  165.         self.tree_member.column("ID", width=120)
  166.         self.tree_member.column("Nama", width=200)
  167.         self.tree_member.column("Alamat", width=300)
  168.         self.tree_member.pack(fill="both", expand=True)
  169.        
  170.         # --- Frame Bawah (Riwayat Transaksi) ---
  171.         frame_riwayat = tk.LabelFrame(tab, text="Riwayat Transaksi Member", padx=10, pady=10)
  172.         frame_riwayat.pack(side=tk.BOTTOM, fill="both", expand=True, pady=5)
  173.        
  174.         self.label_riwayat_member = tk.Label(frame_riwayat, text="Pilih member dari tabel di atas dan klik 'Tampilkan Riwayat'", font=("Helvetica", 9, "italic"))
  175.         self.label_riwayat_member.pack(anchor='w')
  176.        
  177.         self.tree_riwayat = ttk.Treeview(frame_riwayat, columns=("ID Trx", "Item", "Tgl Pinjam", "Tgl Kembali", "Status", "Denda"), show="headings")
  178.         self.tree_riwayat.heading("ID Trx", text="ID Transaksi")
  179.         self.tree_riwayat.heading("Item", text="Judul Item")
  180.         self.tree_riwayat.heading("Tgl Pinjam", text="Tgl Pinjam")
  181.         self.tree_riwayat.heading("Tgl Kembali", text="Batas Kembali")
  182.         self.tree_riwayat.heading("Status", text="Status")
  183.         self.tree_riwayat.heading("Denda", text="Denda")
  184.         self.tree_riwayat.column("ID Trx", width=120)
  185.         self.tree_riwayat.column("Item", width=200)
  186.         self.tree_riwayat.column("Tgl Pinjam", width=100)
  187.         self.tree_riwayat.column("Tgl Kembali", width=100)
  188.         self.tree_riwayat.column("Status", width=80)
  189.         self.tree_riwayat.column("Denda", width=100)
  190.         self.tree_riwayat.pack(fill="both", expand=True, pady=5)
  191.  
  192.         # Langsung refresh data saat tab dibuat
  193.         self.refresh_daftar_buku()
  194.         self.refresh_daftar_member()
  195.        
  196.     def buat_tab_transaksi(self, tab):
  197.         """Membangun konten untuk Tab 2."""
  198.        
  199.         # Tambahkan tombol refresh di atas
  200.         frame_atas_trx = tk.Frame(tab)
  201.         frame_atas_trx.pack(fill="x", padx=5, pady=5)
  202.         tombol_refresh_trx = tk.Button(frame_atas_trx, text="Refresh Semua List Transaksi", command=self.refresh_list_transaksi)
  203.         tombol_refresh_trx.pack(anchor='w')
  204.  
  205.         # Gunakan PanedWindow agar bisa di-resize
  206.         pane = ttk.PanedWindow(tab, orient=tk.HORIZONTAL)
  207.         pane.pack(fill="both", expand=True, padx=5, pady=5)
  208.  
  209.         # --- Frame Kiri: Peminjaman ---
  210.         frame_pinjam = tk.LabelFrame(pane, text="Form Peminjaman", padx=10, pady=10)
  211.         pane.add(frame_pinjam, weight=1)
  212.        
  213.         label_pinjam_member = tk.Label(frame_pinjam, text="Pilih ID Member:")
  214.         label_pinjam_member.grid(row=0, column=0, sticky="e", padx=5)
  215.         # Ubah Entry menjadi Combobox
  216.         self.combo_pinjam_member_id = ttk.Combobox(frame_pinjam, width=27, state="readonly")
  217.         self.combo_pinjam_member_id.grid(row=0, column=1, padx=5, pady=5)
  218.        
  219.         label_pinjam_item = tk.Label(frame_pinjam, text="Pilih ID Item (Tersedia):")
  220.         label_pinjam_item.grid(row=1, column=0, sticky="e", padx=5)
  221.         # Ubah Entry menjadi Combobox
  222.         self.combo_pinjam_item_id = ttk.Combobox(frame_pinjam, width=27, state="readonly")
  223.         self.combo_pinjam_item_id.grid(row=1, column=1, padx=5, pady=5)
  224.        
  225.         tombol_pinjam = tk.Button(frame_pinjam, text="Pinjamkan Item", command=self.lakukan_peminjaman)
  226.         tombol_pinjam.grid(row=2, column=1, sticky="w", padx=5, pady=10)
  227.  
  228.         # --- Frame Kanan: Pengembalian ---
  229.         frame_kembali = tk.LabelFrame(pane, text="Form Pengembalian", padx=10, pady=10)
  230.         pane.add(frame_kembali, weight=1)
  231.        
  232.         label_kembali_trx = tk.Label(frame_kembali, text="Pilih ID Transaksi (Aktif):")
  233.         label_kembali_trx.grid(row=0, column=0, sticky="e", padx=5)
  234.         # Ubah Entry menjadi Combobox
  235.         self.combo_kembali_trx_id = ttk.Combobox(frame_kembali, width=27, state="readonly")
  236.         self.combo_kembali_trx_id.grid(row=0, column=1, padx=5, pady=5)
  237.        
  238.         tombol_kembali = tk.Button(frame_kembali, text="Kembalikan Item", command=self.lakukan_pengembalian)
  239.         tombol_kembali.grid(row=2, column=1, sticky="w", padx=5, pady=10)
  240.        
  241.         # Panggil refresh list saat tab dibuat
  242.         self.refresh_list_transaksi()
  243.  
  244.     def daftar_member_baru(self):
  245.         """Callback untuk tombol 'Daftarkan'."""
  246.         print("DEBUG: Tombol Daftar Member Ditekan")
  247.        
  248.         # 1. Ambil data dari widget Entry
  249.         nama = self.entry_nama.get()
  250.         alamat = self.entry_alamat.get()
  251.  
  252.         # 2. Validasi input (sederhana)
  253.         if not nama or not alamat:
  254.             messagebox.showwarning("Input Tidak Lengkap", "Nama dan Alamat tidak boleh kosong!")
  255.             return # Hentikan fungsi
  256.  
  257.         # 3. Panggil logika backend (dari perpustakaan_backend.py)
  258.         try:
  259.             # Ini adalah inti integrasi: GUI memanggil method backend
  260.             # Menggunakan self.perpustakaan_utama (dari __init__) bukan self.perpus
  261.             member_baru = self.pustakawan_andi.lakukan_pendaftaran(self.perpustakaan_utama, nama, alamat)
  262.            
  263.             # 4. Beri umpan balik ke pengguna
  264.             messagebox.showinfo("Pendaftaran Berhasil",
  265.                                 f"Member baru berhasil ditambahkan!\n"
  266.                                 f"Nama: {member_baru.nama}\n"
  267.                                 f"ID: {member_baru.member_id}")
  268.            
  269.             # 5. Kosongkan form
  270.             self.entry_nama.delete(0, tk.END)
  271.             self.entry_alamat.delete(0, tk.END)
  272.            
  273.             # 6. Refresh daftar member
  274.             self.refresh_daftar_member()
  275.             # Refresh juga combobox member di tab transaksi
  276.             self.refresh_list_transaksi()
  277.  
  278.         except Exception as e:
  279.             messagebox.showerror("Pendaftaran Gagal", f"Terjadi error: {e}")
  280.    
  281.     def refresh_daftar_buku(self):
  282. # ... (kode refresh_daftar_buku tetap sama) ...
  283.         """Callback untuk me-refresh data di Treeview."""
  284.         # Hapus data lama
  285.         for i in self.tree_buku.get_children():
  286.             self.tree_buku.delete(i)
  287.        
  288.         # Ambil data baru dari backend dan masukkan ke treeview
  289.         # Menggunakan self.perpustakaan_utama (dari __init__) bukan self.perpus
  290.         for item in self.perpustakaan_utama.daftar_item:
  291.             info = item.get_info()
  292.             self.tree_buku.insert("", tk.END, values=(info["ID"], info["Judul"], info["Status"]))
  293.  
  294.     def refresh_daftar_member(self):
  295. # ... (kode refresh_daftar_member tetap sama) ...
  296.         """Callback untuk me-refresh data di Treeview Member."""
  297.         # Hapus data lama
  298.         for i in self.tree_member.get_children():
  299.             self.tree_member.delete(i)
  300.        
  301.         # Ambil data baru dari backend dan masukkan ke treeview
  302.         for member in self.perpustakaan_utama.daftar_member:
  303.             # Mengambil _alamat, idealnya ada getter
  304.             self.tree_member.insert("", tk.END, values=(member.member_id, member.nama, member._alamat))
  305.  
  306.     def lakukan_peminjaman(self):
  307.         """Callback untuk tombol Pinjamkan Item."""
  308.         # Ambil data dari Combobox
  309.         member_id = self.combo_pinjam_member_id.get()
  310.         item_id = self.combo_pinjam_item_id.get()
  311.        
  312.         if not member_id or not item_id:
  313.             messagebox.showwarning("Input Tidak Lengkap", "ID Member dan ID Item harus diisi.")
  314.             return
  315.  
  316.         try:
  317.             trx_baru = self.pustakawan_andi.lakukan_peminjaman(self.perpustakaan_utama, member_id, item_id)
  318.             messagebox.showinfo("Peminjaman Berhasil",
  319.                                 f"Transaksi {trx_baru.transaksi_id} sukses.\n"
  320.                                 f"Item '{trx_baru.item.judul}' dipinjam oleh {trx_baru.member.nama}.")
  321.             # Kosongkan form
  322.             # Gunakan .set('') untuk Combobox
  323.             self.combo_pinjam_member_id.set('')
  324.             self.combo_pinjam_item_id.set('')
  325.             # Refresh daftar buku karena statusnya berubah
  326.             self.refresh_daftar_buku()
  327.             # Refresh list transaksi
  328.             self.refresh_list_transaksi()
  329.         except Exception as e:
  330.             messagebox.showerror("Peminjaman Gagal", f"Terjadi error: {e}")
  331.  
  332.     def lakukan_pengembalian(self):
  333.         """Callback untuk tombol Kembalikan Item."""
  334.         # Ambil data dari Combobox
  335.         trx_id = self.combo_kembali_trx_id.get()
  336.        
  337.         if not trx_id:
  338.             messagebox.showwarning("Input Tidak Lengkap", "ID Transaksi harus diisi.")
  339.             return
  340.  
  341.         try:
  342.             # Cek denda sebelum transaksi diselesaikan
  343.             transaksi = self.perpustakaan_utama.cari_transaksi(trx_id)
  344.             if not transaksi:
  345.                 raise Exception(f"Transaksi {trx_id} tidak ditemukan.")
  346.             if transaksi.status != StatusTransaksi.AKTIF:
  347.                  raise Exception(f"Transaksi {trx_id} sudah tidak aktif/selesai.")
  348.                  
  349.             # Hitung denda
  350.             denda = transaksi.hitung_denda()
  351.            
  352.             # Lakukan pengembalian
  353.             self.pustakawan_andi.lakukan_pengembalian(self.perpustakaan_utama, trx_id)
  354.            
  355.             pesan_denda = f"Denda: Rp {denda:,.2f}" if denda > 0 else "Tidak ada denda."
  356.             messagebox.showinfo("Pengembalian Berhasil",
  357.                                 f"Transaksi {trx_id} sukses dikembalikan.\n{pesan_denda}")
  358.  
  359.             # Gunakan .set('') untuk Combobox
  360.             self.combo_kembali_trx_id.set('')
  361.             # Refresh daftar buku karena statusnya berubah
  362.             self.refresh_daftar_buku()
  363.             # Refresh list transaksi
  364.             self.refresh_list_transaksi()
  365.             # Refresh riwayat jika sedang ditampilkan
  366.             self.tampilkan_riwayat_terpilih(auto_refresh=True)
  367.            
  368.         except Exception as e:
  369.             messagebox.showerror("Pengembalian Gagal", f"Terjadi error: {e}")
  370.  
  371.     def tampilkan_riwayat_terpilih(self, auto_refresh=False):
  372. # ... (kode tampilkan_riwayat_terpilih tetap sama) ...
  373.         """Callback untuk tombol Tampilkan Riwayat."""
  374.        
  375.         selected_item = self.tree_member.focus()
  376.         if not selected_item:
  377.             # Jika auto_refresh (dipanggil dari fungsi lain) dan tidak ada yg dipilih, abaikan
  378.             if not auto_refresh:
  379.                 messagebox.showwarning("Pilihan Kosong", "Pilih salah satu member dari tabel untuk melihat riwayat.")
  380.             return
  381.  
  382.         item_data = self.tree_member.item(selected_item)
  383.         member_id = item_data['values'][0]
  384.         member_nama = item_data['values'][1]
  385.        
  386.         member = self.perpustakaan_utama.cari_member(member_id)
  387.         if not member:
  388.             messagebox.showerror("Error", f"Data member {member_id} tidak ditemukan di backend.")
  389.             return
  390.  
  391.         # Update label riwayat
  392.         self.label_riwayat_member.config(text=f"Menampilkan riwayat untuk: {member_nama} (ID: {member_id})")
  393.        
  394.         # Bersihkan tree riwayat
  395.         for i in self.tree_riwayat.get_children():
  396.             self.tree_riwayat.delete(i)
  397.            
  398.         # Ambil data riwayat
  399.         riwayat = member.get_riwayat_peminjaman(self.perpustakaan_utama)
  400.         if not riwayat:
  401.             self.tree_riwayat.insert("", tk.END, values=("", "Tidak ada riwayat peminjaman.", "", "", "", ""))
  402.             return
  403.            
  404.         # Tampilkan data riwayat baru
  405.         for trx in riwayat:
  406.             item = trx.item
  407.             # Pastikan denda ter-update
  408.             denda = trx.hitung_denda() if trx.status == StatusTransaksi.TERLAMBAT else trx._denda
  409.            
  410.             self.tree_riwayat.insert("", tk.END, values=(
  411.                 trx.transaksi_id,
  412.                 item.judul,
  413.                 trx._tgl_pinjam.strftime('%Y-%m-%d'),
  414.                 trx._tgl_kembali.strftime('%Y-%m-%d'),
  415.                 trx.status.value,
  416.                 f"Rp{denda:,.2f}"
  417.             ))
  418.  
  419.     def on_tipe_item_changed(self, event):
  420.         """Mengubah label form berdasarkan pilihan Combobox."""
  421.         tipe_terpilih = self.combo_tipe_item.get()
  422.         if tipe_terpilih == "Buku":
  423.             self.label_khusus.config(text="Pengarang:")
  424.         elif tipe_terpilih == "Majalah":
  425.             self.label_khusus.config(text="Edisi:")
  426.         self.entry_khusus.delete(0, tk.END)
  427.  
  428.     def tambah_item_baru(self):
  429.         """Callback untuk tombol 'Tambahkan Item'."""
  430.         print("DEBUG: Tombol Tambah Item Ditekan")
  431.        
  432.         # 1. Ambil data dari form
  433.         tipe = self.combo_tipe_item.get()
  434.         item_id = self.entry_item_id.get()
  435.         judul = self.entry_item_judul.get()
  436.         khusus = self.entry_khusus.get()
  437.  
  438.         # 2. Validasi input
  439.         if not all([tipe, item_id, judul, khusus]):
  440.             messagebox.showwarning("Input Tidak Lengkap", "Semua field harus diisi!")
  441.             return
  442.  
  443.         # 3. Siapkan kwargs untuk factory
  444.         kwargs = {}
  445.         if tipe == "Buku":
  446.             kwargs['pengarang'] = khusus
  447.         elif tipe == "Majalah":
  448.             kwargs['edisi'] = khusus
  449.  
  450.         # 4. Panggil logika backend
  451.         try:
  452.             self.pustakawan_andi.tambah_item_ke_koleksi(
  453.                 self.perpustakaan_utama,
  454.                 tipe.lower(),
  455.                 item_id,
  456.                 judul,
  457.                 **kwargs
  458.             )
  459.            
  460.             # 5. Beri umpan balik
  461.             messagebox.showinfo("Penambahan Berhasil", f"{tipe} '{judul}' berhasil ditambahkan ke koleksi.")
  462.            
  463.             # 6. Kosongkan form
  464.             self.entry_item_id.delete(0, tk.END)
  465.             self.entry_item_judul.delete(0, tk.END)
  466.             self.entry_khusus.delete(0, tk.END)
  467.            
  468.             # 7. Refresh daftar buku
  469.             self.refresh_daftar_buku()
  470.             # Refresh juga combobox item di tab transaksi
  471.             self.refresh_list_transaksi()
  472.  
  473.         except Exception as e:
  474.             messagebox.showerror("Penambahan Gagal", f"Terjadi error: {e}")
  475.  
  476.     def update_combobox_member(self):
  477.         """Mengambil semua ID member dan mengupdate combobox peminjaman."""
  478.         try:
  479.             member_ids = [member.member_id for member in self.perpustakaan_utama.daftar_member]
  480.             self.combo_pinjam_member_id['values'] = member_ids
  481.         except Exception as e:
  482.             print(f"Error updating member combobox: {e}")
  483.  
  484.     def update_combobox_item_tersedia(self):
  485.         """Mengambil semua ID item yang TERSEDIA dan mengupdate combobox peminjaman."""
  486.         try:
  487.             item_ids = [item.item_id for item in self.perpustakaan_utama.daftar_item if item.status == StatusItem.TERSEDIA]
  488.             self.combo_pinjam_item_id['values'] = item_ids
  489.         except Exception as e:
  490.             print(f"Error updating item combobox: {e}")
  491.  
  492.     def update_combobox_transaksi_aktif(self):
  493.         """Mengambil semua ID transaksi yang AKTIF dan mengupdate combobox pengembalian."""
  494.         try:
  495.             trx_ids = [trx.transaksi_id for trx in self.perpustakaan_utama.daftar_transaksi if trx.status == StatusTransaksi.AKTIF]
  496.             self.combo_kembali_trx_id['values'] = trx_ids
  497.         except Exception as e:
  498.             print(f"Error updating transaksi combobox: {e}")
  499.  
  500.     def refresh_list_transaksi(self):
  501.         """Satu fungsi untuk me-refresh semua combobox di tab transaksi."""
  502.         print("DEBUG: Merefresh semua list transaksi...")
  503.         self.update_combobox_member()
  504.         self.update_combobox_item_tersedia()
  505.         self.update_combobox_transaksi_aktif()
  506.        
  507.     def simpan_dan_keluar(self):
  508. # ... (kode simpan_dan_keluar tetap sama) ...
  509.         """Callback untuk tombol simpan."""
  510.         try:
  511.             self.perpustakaan_utama.simpan_data()
  512.             messagebox.showinfo("Sukses", "Data berhasil disimpan!")
  513.             self.root.destroy() # Menutup jendela
  514.         except Exception as e:
  515.             messagebox.showerror("Gagal Menyimpan", f"Terjadi error: {e}")
  516.  
  517. # --- Titik Mulai Eksekusi ---
  518. if __name__ == "__main__":
  519.     root_window = tk.Tk()
  520.     app = AppPerpustakaan(root_window)
  521.     root_window.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment