Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from abc import ABC, abstractmethod
- from datetime import datetime, timedelta
- from enum import Enum
- import uuid
- # ==============================================================================
- # Definisi Enum untuk Status
- # ==============================================================================
- class StatusItem(Enum):
- """Enum untuk status item di perpustakaan."""
- TERSEDIA = "Tersedia"
- DIPINJAM = "Dipinjam"
- HILANG = "Hilang"
- class StatusTransaksi(Enum):
- """Enum untuk status transaksi peminjaman."""
- AKTIF = "Aktif"
- SELESAI = "Selesai"
- TERLAMBAT = "Terlambat"
- # ==============================================================================
- # Hierarki Kelas Item Pustaka (LoanableItem, Buku, Majalah)
- # ==============================================================================
- class LoanableItem(ABC):
- """
- Kelas abstrak untuk semua item yang dapat dipinjam di perpustakaan.
- Ini adalah superclass (induk) untuk Buku, Majalah, dll.
- """
- def __init__(self, item_id: str, judul: str):
- self._item_id = item_id
- self._judul = judul
- self._status = StatusItem.TERSEDIA
- @abstractmethod
- def get_info(self) -> dict:
- """Metode abstrak untuk mendapatkan informasi detail dari item."""
- pass
- def ubah_status(self, status_baru: StatusItem):
- """Mengubah status ketersediaan item."""
- self._status = status_baru
- print(f"INFO: Status '{self._judul}' telah diubah menjadi {status_baru.value}.")
- @property
- def item_id(self):
- return self._item_id
- @property
- def judul(self):
- return self._judul
- @property
- def status(self):
- return self._status
- class Buku(LoanableItem):
- """Kelas turunan untuk merepresentasikan sebuah buku."""
- def __init__(self, item_id: str, judul: str, pengarang: str):
- super().__init__(item_id, judul)
- self._pengarang = pengarang
- def get_info(self) -> dict:
- """Implementasi spesifik untuk menampilkan info buku (method overriding)."""
- return {
- "ID": self._item_id,
- "Judul": self._judul,
- "Tipe": "Buku",
- "Pengarang": self._pengarang,
- "Status": self._status.value
- }
- class Majalah(LoanableItem):
- """Kelas turunan untuk merepresentasikan sebuah majalah/jurnal."""
- def __init__(self, item_id: str, judul: str, edisi: str):
- super().__init__(item_id, judul)
- self._edisi = edisi
- def get_info(self) -> dict:
- """Implementasi spesifik untuk menampilkan info majalah (method overriding)."""
- return {
- "ID": self._item_id,
- "Judul": self._judul,
- "Tipe": "Majalah",
- "Edisi": self._edisi,
- "Status": self._status.value
- }
- # ==============================================================================
- # Kelas-kelas Utama Sistem
- # ==============================================================================
- class Member:
- """Merepresentasikan anggota perpustakaan."""
- def __init__(self, nama: str, alamat: str):
- self._member_id = "MEM-" + str(uuid.uuid4())[:8].upper()
- self._nama = nama
- self._alamat = alamat
- @property
- def member_id(self):
- return self._member_id
- @property
- def nama(self):
- return self._nama
- def get_riwayat_peminjaman(self, perpus: 'Perpustakaan') -> list['Transaksi']:
- """Mendapatkan daftar transaksi yang pernah dilakukan oleh member."""
- riwayat = []
- for transaksi in perpus.daftar_transaksi:
- if transaksi.member.member_id == self._member_id:
- riwayat.append(transaksi)
- return riwayat
- class Transaksi:
- """Merepresentasikan sebuah transaksi peminjaman."""
- def __init__(self, member: Member, item: LoanableItem):
- self._transaksi_id = "TRX-" + str(uuid.uuid4())[:8].upper()
- self._member = member
- self._item = item
- self._tgl_pinjam = datetime.now()
- self._tgl_kembali = self._tgl_pinjam + timedelta(days=14) # Batas peminjaman 14 hari
- self._status = StatusTransaksi.AKTIF
- self._denda = 0.0
- @property
- def transaksi_id(self):
- return self._transaksi_id
- @property
- def member(self):
- return self._member
- @property
- def item(self):
- return self._item
- @property
- def status(self):
- return self._status
- def hitung_denda(self) -> float:
- """Menghitung denda jika pengembalian terlambat."""
- if datetime.now() > self._tgl_kembali:
- terlambat = (datetime.now() - self._tgl_kembali).days
- self._denda = float(terlambat * 1000) # Denda 1000 per hari
- self._status = StatusTransaksi.TERLAMBAT
- return self._denda
- def selesaikan_transaksi(self):
- self.hitung_denda()
- if self._status != StatusTransaksi.TERLAMBAT:
- self._status = StatusTransaksi.SELESAI
- class Perpustakaan:
- """Kelas utama yang mengelola seluruh sistem perpustakaan."""
- def __init__(self):
- self._daftar_item = []
- self._daftar_member = []
- self._daftar_transaksi = []
- print("Sistem Perpustakaan berhasil dibuat.")
- @property
- def daftar_item(self):
- return self._daftar_item
- @property
- def daftar_member(self):
- return self._daftar_member
- @property
- def daftar_transaksi(self):
- return self._daftar_transaksi
- def tambah_item(self, item: LoanableItem):
- """Menambahkan item baru (buku/majalah) ke perpustakaan."""
- self._daftar_item.append(item)
- print(f"ITEM DITAMBAHKAN: '{item.judul}' ({item.__class__.__name__}) telah ditambahkan ke koleksi.")
- def tambah_member(self, nama: str, alamat: str) -> Member:
- """Mendaftarkan anggota baru."""
- member_baru = Member(nama, alamat)
- self._daftar_member.append(member_baru)
- print(f"MEMBER BARU: {nama} dengan ID {member_baru.member_id} berhasil terdaftar.")
- return member_baru
- def cari_item(self, item_id: str) -> LoanableItem | None:
- """Mencari item berdasarkan ID."""
- for item in self._daftar_item:
- if item.item_id == item_id:
- return item
- return None
- def cari_member(self, member_id: str) -> Member | None:
- """Mencari member berdasarkan ID."""
- for member in self._daftar_member:
- if member.member_id == member_id:
- return member
- return None
- def cari_transaksi(self, transaksi_id: str) -> Transaksi | None:
- """Mencari transaksi berdasarkan ID."""
- for trx in self._daftar_transaksi:
- if trx.transaksi_id == transaksi_id:
- return trx
- return None
- def pinjamkan_item(self, member_id: str, item_id: str) -> Transaksi:
- """Memproses peminjaman item oleh member."""
- member = self.cari_member(member_id)
- item = self.cari_item(item_id)
- if not member:
- raise Exception("ERROR: Member tidak ditemukan.")
- if not item:
- raise Exception("ERROR: Item tidak ditemukan.")
- if item.status != StatusItem.TERSEDIA:
- raise Exception(f"ERROR: Item '{item.judul}' sedang tidak tersedia.")
- transaksi_baru = Transaksi(member, item)
- self._daftar_transaksi.append(transaksi_baru)
- item.ubah_status(StatusItem.DIPINJAM)
- print(f"TRANSAKSI PEMINJAMAN: '{item.judul}' dipinjam oleh {member.nama}. ID Transaksi: {transaksi_baru.transaksi_id}")
- return transaksi_baru
- def terima_pengembalian(self, transaksi_id: str):
- """Memproses pengembalian item."""
- transaksi = self.cari_transaksi(transaksi_id)
- if not transaksi:
- raise Exception("ERROR: Transaksi tidak ditemukan.")
- if transaksi.status != StatusTransaksi.AKTIF:
- raise Exception("ERROR: Transaksi ini sudah tidak aktif.")
- transaksi.selesaikan_transaksi()
- item = transaksi.item
- item.ubah_status(StatusItem.TERSEDIA)
- denda = transaksi.hitung_denda()
- print(f"TRANSAKSI PENGEMBALIAN: '{item.judul}' telah dikembalikan oleh {transaksi.member.nama}.")
- if denda > 0:
- print(f" -> Dikenakan denda sebesar: Rp{denda:,.2f}")
- else:
- print(" -> Pengembalian tepat waktu.")
- # Modifikasi Kelas Pustakawan
- class Pustakawan:
- """Merepresentasikan pustakawan yang mengelola perpustakaan."""
- def __init__(self, pustakawan_id: str, nama: str):
- self._pustakawan_id = pustakawan_id
- self._nama = nama
- def lakukan_pendaftaran(self, perpus: Perpustakaan, nama: str, alamat: str) -> Member:
- """Wrapper method untuk mendaftarkan member."""
- print(f"\n[Aksi Pustakawan: {self._nama}] Mendaftarkan anggota baru...")
- return perpus.tambah_member(nama, alamat)
- # Ubah metode tambah_item_ke_koleksi
- # def tambah_item_ke_koleksi(self, perpus: Perpustakaan, item: LoanableItem):
- # """Wrapper method untuk menambah item baru."""
- # print(f"\n[Aksi Pustakawan: {self._nama}] Menambahkan item ke koleksi...")
- # perpus.tambah_item(item)
- # Versi Baru dengan Factory
- def tambah_item_ke_koleksi(self, perpus: Perpustakaan, item_type: str, item_id: str, judul: str, **kwargs):
- """Wrapper method untuk menambah item baru menggunakan Factory."""
- print(f"\n[Aksi Pustakawan: {self._nama}] Meminta pembuatan dan penambahan item '{judul}'...")
- try:
- # Panggil Factory untuk membuat objek
- item_baru = ItemFactory.create_item(item_type, item_id, judul, **kwargs)
- # Tambahkan objek yang sudah jadi ke perpustakaan
- perpus.tambah_item(item_baru)
- except ValueError as e:
- print(f"ERROR saat menambah item: {e}")
- except Exception as e:
- print(f"ERROR tidak terduga: {e}")
- def lakukan_peminjaman(self, perpus: Perpustakaan, member_id: str, item_id: str) -> Transaksi:
- """Wrapper method untuk melakukan peminjaman."""
- print(f"\n[Aksi Pustakawan: {self._nama}] Memproses peminjaman...")
- return perpus.pinjamkan_item(member_id, item_id)
- def lakukan_pengembalian(self, perpus: Perpustakaan, transaksi_id: str):
- """Wrapper method untuk melakukan pengembalian."""
- print(f"\n[Aksi Pustakawan: {self._nama}] Memproses pengembalian...")
- perpus.terima_pengembalian(transaksi_id)
- # Kelas Baru: ItemFactory
- class ItemFactory:
- """Kelas Factory untuk membuat instance LoanableItem."""
- @staticmethod
- def create_item(item_type: str, item_id: str, judul: str, **kwargs) -> LoanableItem:
- """
- Membuat objek Buku atau Majalah berdasarkan item_type.
- kwargs bisa berisi 'pengarang' untuk Buku atau 'edisi' untuk Majalah.
- """
- if item_type.lower() == "buku":
- pengarang = kwargs.get('pengarang', 'N/A') # Ambil pengarang, default N/A
- if pengarang == 'N/A':
- print("WARNING: Pengarang tidak disediakan untuk buku.")
- return Buku(item_id, judul, pengarang)
- elif item_type.lower() == "majalah":
- edisi = kwargs.get('edisi', 'N/A') # Ambil edisi, default N/A
- if edisi == 'N/A':
- print("WARNING: Edisi tidak disediakan untuk majalah.")
- return Majalah(item_id, judul, edisi)
- # Bisa tambahkan tipe lain di sini (misal: Artikel)
- # elif item_type.lower() == "artikel":
- # volume = kwargs.get('volume', 0)
- # return Artikel(item_id, judul, volume)
- else:
- raise ValueError(f"Tipe item tidak dikenal: {item_type}")
- # ==============================================================================
- # CONTOH PENGGUNAAN PROGRAM (MAIN)
- # ==============================================================================
- if __name__ == "__main__":
- print("===== MEMULAI SIMULASI SISTEM PERPUSTAKAAN =====")
- # 1. Inisialisasi sistem
- perpustakaan_utama = Perpustakaan()
- # 2. Menambahkan pustakawan
- pustakawan_andi = Pustakawan("P-001", "Andi")
- # 3. Pustakawan mendaftarkan member baru
- member_budi = pustakawan_andi.lakukan_pendaftaran(perpustakaan_utama, "Budi Santoso", "Jl. Merdeka No. 10")
- member_citra = pustakawan_andi.lakukan_pendaftaran(perpustakaan_utama, "Citra Lestari", "Jl. Pahlawan No. 5")
- # 4. Pustakawan menambahkan item baru (Buku dan Majalah)
- # Kode sebelumnya:
- # buku_oop = Buku("BK-001", "Pemrograman Berorientasi Objek dengan Python", "Dr. Inovatif")
- # majalah_sains = Majalah("MGZ-001", "Quanta Magazine", "Edisi Oktober 2025")
- # buku_data = Buku("BK-002", "Sains Data untuk Pemula", "Prof. Analitika")
- # pustakawan_andi.tambah_item_ke_koleksi(perpustakaan_utama, buku_oop)
- # pustakawan_andi.tambah_item_ke_koleksi(perpustakaan_utama, majalah_sains)
- # pustakawan_andi.tambah_item_ke_koleksi(perpustakaan_utama, buku_data)
- # Kode baru penggunaan factory:
- pustakawan_andi.tambah_item_ke_koleksi(perpustakaan_utama, "Buku", "BK-001", "OOP Python", pengarang="Dr. Inovatif")
- pustakawan_andi.tambah_item_ke_koleksi(perpustakaan_utama, "Majalah", "MGZ-001", "Quanta", edisi="Okt 2025")
- pustakawan_andi.tambah_item_ke_koleksi(perpustakaan_utama, "Buku", "BK-002", "Sains Data", pengarang="Prof. Analitika")
- # Coba tambahkan tipe yang salah
- pustakawan_andi.tambah_item_ke_koleksi(perpustakaan_utama, "Artikel", "ART-001", "Artikel Ilmiah", volume=5)
- print("\n===== STATUS AWAL KOLEKSI DAN MEMBER =====")
- print("--- Daftar Item ---")
- # Contoh polimorfisme saat menampilkan info
- for item in perpustakaan_utama.daftar_item:
- print(item.get_info())
- print("\n--- Daftar Member ---")
- for member in perpustakaan_utama.daftar_member:
- print(f"ID: {member.member_id}, Nama: {member.nama}")
- # 5. Simulasi Transaksi Peminjaman
- print("\n===== SIMULASI TRANSAKSI =====")
- try:
- # Budi meminjam buku OOP
- transaksi1 = pustakawan_andi.lakukan_peminjaman(perpustakaan_utama, member_budi.member_id, "BK-001")
- # Citra meminjam majalah sains
- transaksi2 = pustakawan_andi.lakukan_peminjaman(perpustakaan_utama, member_citra.member_id, "MGZ-001")
- # Budi mencoba meminjam buku yang sama lagi (akan gagal)
- pustakawan_andi.lakukan_peminjaman(perpustakaan_utama, member_budi.member_id, "BK-001")
- except Exception as e:
- print(e)
- print("\n===== STATUS SETELAH PEMINJAMAN =====")
- for item in perpustakaan_utama.daftar_item:
- print(f"Judul: {item.judul}, Status: {item.status.value}")
- # 6. Simulasi Transaksi Pengembalian
- try:
- # Budi mengembalikan buku OOP
- pustakawan_andi.lakukan_pengembalian(perpustakaan_utama, transaksi1.transaksi_id)
- # Citra mencoba mengembalikan majalah (simulasi terlambat dengan "memajukan" waktu)
- transaksi2._tgl_kembali = datetime.now() - timedelta(days=3) # Anggap terlambat 3 hari
- pustakawan_andi.lakukan_pengembalian(perpustakaan_utama, transaksi2.transaksi_id)
- except Exception as e:
- print(e)
- print("\n===== STATUS AKHIR SETELAH PENGEMBALIAN =====")
- for item in perpustakaan_utama.daftar_item:
- print(f"Judul: {item.judul}, Status: {item.status.value}")
- print("\n===== RIWAYAT PEMINJAMAN BUDI =====")
- riwayat_budi = member_budi.get_riwayat_peminjaman(perpustakaan_utama)
- for trx in riwayat_budi:
- print(f"ID: {trx.transaksi_id}, Item: '{trx.item.judul}', Status: {trx.status.value}")
- print("\n===== SIMULASI SELESAI =====")
Advertisement