Загрузка данных


import sqlite3
from datetime import datetime, timedelta

class LibraryDB:
    def __init__(self, db_file='library.db'):
        # Подключаемся к базе и обязательно включаем поддержку внешних ключей
        self.conn = sqlite3.connect(db_file)
        self.conn.execute("PRAGMA foreign_keys = ON")
        # Чтобы получать результаты в виде словарей, а не кортежей
        self.conn.row_factory = sqlite3.Row 

    # --- 1. ДОБАВЛЕНИЕ СУЩНОСТЕЙ ---

    def add_reader(self, full_name, phone):
        """Регистрация нового читателя."""
        with self.conn:
            cursor = self.conn.cursor()
            cursor.execute(
                "INSERT INTO readers (full_name, phone) VALUES (?, ?)", 
                (full_name, phone)
            )
            return cursor.lastrowid

    def add_book(self, title, author, year):
        """Добавление нового произведения в каталог."""
        with self.conn:
            cursor = self.conn.cursor()
            cursor.execute(
                "INSERT INTO books (title, author, publication_year) VALUES (?, ?, ?)", 
                (title, author, year)
            )
            return cursor.lastrowid

    def add_copy(self, book_id, inventory_number):
        """Добавление физического экземпляра книги (приёмка)."""
        with self.conn:
            cursor = self.conn.cursor()
            cursor.execute(
                "INSERT INTO copies (book_id, inventory_number) VALUES (?, ?)", 
                (book_id, inventory_number)
            )
            return cursor.lastrowid

    # --- 2. ОПЕРАЦИИ С КНИГАМИ ---

    def issue_copy(self, copy_id, reader_id, days=14):
        """Выдача книги: пишем в журнал и меняем статус экземпляра."""
        issue_date = datetime.now().date()
        due_date = issue_date + timedelta(days=days)
        
        with self.conn:
            cursor = self.conn.cursor()
            # 1. Проверяем, свободна ли книга
            cursor.execute("SELECT status FROM copies WHERE copy_id = ?", (copy_id,))
            res = cursor.fetchone()
            if not res or res['status'] != 'В наличии':
                raise ValueError("Книга недоступна для выдачи (выдана или списана).")

            # 2. Создаем запись о выдаче
            cursor.execute('''
                INSERT INTO loans (copy_id, reader_id, issue_date, due_date)
                VALUES (?, ?, ?, ?)
            ''', (copy_id, reader_id, issue_date, due_date))
            
            # 3. Меняем статус физической копии
            cursor.execute("UPDATE copies SET status = 'Выдана' WHERE copy_id = ?", (copy_id,))
            print(f"Экземпляр {copy_id} успешно выдан читателю {reader_id} до {due_date}.")

    def return_copy(self, copy_id):
        """Возврат книги: закрываем запись в журнале и освобождаем экземпляр."""
        return_date = datetime.now().date()
        
        with self.conn:
            cursor = self.conn.cursor()
            # 1. Ставим дату возврата в активной выдаче
            cursor.execute('''
                UPDATE loans SET return_date = ? 
                WHERE copy_id = ? AND return_date IS NULL
            ''', (return_date, copy_id))
            
            if cursor.rowcount == 0:
                raise ValueError("Эта книга не числится выданной.")

            # 2. Возвращаем книгу в фонд
            cursor.execute("UPDATE copies SET status = 'В наличии' WHERE copy_id = ?", (copy_id,))
            print(f"Экземпляр {copy_id} возвращен в библиотеку.")

    def write_off_copy(self, copy_id):
        """Списание пришедшего в негодность экземпляра."""
        with self.conn:
            self.conn.execute("UPDATE copies SET status = 'Списана' WHERE copy_id = ?", (copy_id,))
            print(f"Экземпляр {copy_id} списан.")

    # --- 3. КОНТРОЛЬ ДОЛЖНИКОВ ---

    def get_debtors(self):
        """Возвращает список читателей, просрочивших возврат."""
        cursor = self.conn.cursor()
        cursor.execute('''
            SELECT 
                r.full_name, r.phone, 
                b.title, c.inventory_number, 
                l.issue_date, l.due_date
            FROM loans l
            JOIN readers r ON l.reader_id = r.reader_id
            JOIN copies c ON l.copy_id = c.copy_id
            JOIN books b ON c.book_id = b.book_id
            WHERE l.return_date IS NULL AND l.due_date < date('now', 'localtime')
        ''')
        return [dict(row) for row in cursor.fetchall()]

    def close(self):
        self.conn.close()