diff --git a/src/importer/book/book_importer.py b/src/importer/book/book_importer.py index ed22482..a1ce7cc 100644 --- a/src/importer/book/book_importer.py +++ b/src/importer/book/book_importer.py @@ -79,41 +79,58 @@ class BookImporter: def save_books(self, books: List[Book]): """Saves a list of books to the database.""" try: - with DatabaseManager.get_session() as session: + # Get a session instance + session = DatabaseManager.get_session() + + # Use no_autoflush as a context manager + with session.no_autoflush: + processed_categories = {} # Cache for processed categories by name + for book in books: + self.logger.debug(f"Attempting to save {book.title}") + # Check if the author exists, otherwise add existing_author = session.query(Author).filter_by( first_name=book.author.first_name, last_name=book.author.last_name - ).first() - if existing_author: + ).one_or_none() + + if existing_author is not None: + self.logger.debug(f"Author {existing_author.first_name} {existing_author.last_name} already exists. Reusing") book.author = existing_author - else: + else: + self.logger.debug(f"Creating new author: {book.author.first_name} {book.author.last_name}") session.add(book.author) - session.commit() # Handle categories - new_categories = [] + filtered_categories = [] for category in book.categories: - existing_category = session.query(BookCategory).filter_by(name=category.name).first() - if existing_category: - new_categories.append(existing_category) + existing_category = session.query(BookCategory).filter_by(name=category.name).one_or_none() + + if existing_category is not None: + self.logger.debug(f"Category {existing_category.name} already exists. Reusing") + filtered_categories.append(session.merge(existing_category)) + else: self.logger.debug(f"Adding new category: {category.name}") - session.add(category) - session.commit() - new_categories.append(category) - # Replace book categories with the resolved categories - book.categories = new_categories + session.add(category) # Add new category to the session + filtered_categories.append(category) # Use the new category + + book.categories = filtered_categories + # Check if the book already exists existing_book = session.query(Book).filter_by(isbn=book.isbn).first() if not existing_book: session.add(book) else: - self.logger.warning(f"Book with ISBN {book.isbn} already exists. Skipping.") + self.logger.warning(f"ISBN {book.isbn} already exists. Skipping.") + continue # Commit all changes session.commit() except IntegrityError as e: raise ImportError(f"An error occurred when importing books: {e}") from e + finally: + # Clean up the session + session.close() diff --git a/src/ui/dashboard/dashboard.py b/src/ui/dashboard/dashboard.py index d149fea..cbc1532 100644 --- a/src/ui/dashboard/dashboard.py +++ b/src/ui/dashboard/dashboard.py @@ -43,16 +43,9 @@ class LibraryDashboard(QWidget): # Align the cards to the top self.scroll_layout.setAlignment(Qt.AlignTop) - - # Example cards - self.books = self.fetch_books_from_db() + self.books = [] self.book_cards = [] - - for book in self.books: - card = BookCard(book) - - self.scroll_layout.addWidget(card) - self.book_cards.append(card) + self.redraw_cards() self.scroll_widget.setLayout(self.scroll_layout) self.scroll_area.setWidget(self.scroll_widget) @@ -83,6 +76,30 @@ class LibraryDashboard(QWidget): QMessageBox.information(self, "Add Borrow Record", "Open dialog to add a borrow record.") + def clear_layout(self, layout): + while layout.count(): + item = layout.takeAt(0) + widget = item.widget() + if widget is not None: + widget.deleteLater() + else: + sub_layout = item.layout() + if sub_layout is not None: + self.clear_layout(sub_layout) + del item + + def redraw_cards(self): + self.clear_layout(self.scroll_layout) + self.book_cards = [] + + self.books = self.fetch_books_from_db() + + for book in self.books: + card = BookCard(book) + + self.scroll_layout.addWidget(card) + self.book_cards.append(card) + def fetch_books_from_db(self): """Fetch all books from the database.""" try: diff --git a/src/ui/window.py b/src/ui/window.py index db249fb..e1d30dc 100644 --- a/src/ui/window.py +++ b/src/ui/window.py @@ -37,7 +37,9 @@ class LibraryWindow(QtWidgets.QMainWindow): central_widget = QtWidgets.QTabWidget() self.setCentralWidget(central_widget) - central_widget.addTab(LibraryDashboard(), "Dashboard") + + self.dashboard = LibraryDashboard() + central_widget.addTab(self.dashboard, "Dashboard") central_widget.addTab(MemberEditor(), "Members") self.file_types = { @@ -198,6 +200,7 @@ class LibraryWindow(QtWidgets.QMainWindow): importer.save_books(new_books) QMessageBox.information( self, "Success", "Books imported successfully!", QMessageBox.Ok) + self.dashboard.redraw_cards() else: QMessageBox.information( self, "Canceled", "Import was canceled.", QMessageBox.Ok) diff --git a/src/utils/database.py b/src/utils/database.py index 2aa5359..18d98d9 100644 --- a/src/utils/database.py +++ b/src/utils/database.py @@ -30,7 +30,7 @@ class DatabaseManager(): database_config.name), pool_pre_ping=True) if self.test_connection(): - self.session_local = sessionmaker(bind=self.engine) + self.Session = sessionmaker(bind=self.engine) def cleanup(self) -> None: self.logger.debug("Closing connection") @@ -49,4 +49,4 @@ class DatabaseManager(): @classmethod def get_session(cls) -> Session: - return DatabaseManager._instance.session_local() + return DatabaseManager._instance.Session()