""" Data Access Object for MaterialsToBeDeleted table. This module provides CRUD operations for the MaterialsToBeDeleted table, which tracks materials that need to be deleted by their managers. """ from typing import List, Dict, Any, Tuple, Optional from db.connection import get_connection class MaterialsToBeDeletedDAO: """Data Access Object for MaterialsToBeDeleted table CRUD operations""" def __init__(self): self.db = None def __enter__(self): """Enter context manager and establish database connection""" self.db = get_connection() self.db.connect() return self def __exit__(self, exc_type, exc_val, exc_tb): """Exit context manager and close database connection""" if self.db: self.db.disconnect() def close(self): """Close database connection""" if self.db: self.db.disconnect() # ==================== CREATE ==================== def insert_material( self, material_name: str, manager_name: str ) -> bool: """ Insert a single material record. Args: material_name: Material name manager_name: Manager name Returns: True if successful, False otherwise """ sql = """ INSERT INTO [dbo].[MaterialsToBeDeleted] ([MaterialName], [ManagerName]) VALUES (?, ?) """ try: with get_connection() as db: db.execute_update(sql, (material_name, manager_name)) return True except Exception as e: print(f"Error inserting material: {e}") return False def insert_batch(self, materials: List[Tuple[str, str]]) -> int: """ Insert multiple material records in batch. Args: materials: List of tuples (material_name, manager_name) Returns: Number of records inserted """ if not materials: return 0 sql = """ INSERT INTO [dbo].[MaterialsToBeDeleted] ([MaterialName], [ManagerName]) VALUES (?, ?) """ inserted_count = 0 try: with get_connection() as db: for material_name, manager_name in materials: db.execute_update(sql, (material_name, manager_name)) inserted_count += 1 return inserted_count except Exception as e: print(f"Error inserting batch materials: {e}") return inserted_count # ==================== READ ==================== def get_all_materials(self) -> List[Dict[str, Any]]: """ Get all material records. Returns: List of all materials with MaterialName and ManagerName """ sql = """ SELECT [MaterialName], [ManagerName] FROM [dbo].[MaterialsToBeDeleted] WHERE [MaterialName] IS NOT NULL ORDER BY [ManagerName], [MaterialName] """ with get_connection() as db: return db.execute_query(sql) def get_materials_by_manager(self, manager_name: str) -> List[Dict[str, Any]]: """ Get all materials for a specific manager. Args: manager_name: Manager name Returns: List of materials for the specified manager """ sql = """ SELECT [MaterialName], [ManagerName] FROM [dbo].[MaterialsToBeDeleted] WHERE [ManagerName] = ? AND [MaterialName] IS NOT NULL ORDER BY [MaterialName] """ with get_connection() as db: return db.execute_query(sql, (manager_name,)) def get_managers(self) -> List[str]: """ Get list of unique manager names. Returns: List of unique manager names """ sql = """ SELECT DISTINCT [ManagerName] FROM [dbo].[MaterialsToBeDeleted] WHERE [ManagerName] IS NOT NULL ORDER BY [ManagerName] """ with get_connection() as db: results = db.execute_query(sql) return [r['ManagerName'] for r in results if r.get('ManagerName')] def get_material_names_by_manager(self, manager_name: str) -> List[str]: """ Get material names for a specific manager. Args: manager_name: Manager name Returns: List of material names for the specified manager """ results = self.get_materials_by_manager(manager_name) return [r['MaterialName'] for r in results if r.get('MaterialName')] # ==================== UPDATE ==================== def update_manager( self, material_name: str, old_manager: str, new_manager: str ) -> bool: """ Update manager for a specific material. Args: material_name: Material name old_manager: Current manager name new_manager: New manager name Returns: True if successful, False otherwise """ sql = """ UPDATE [dbo].[MaterialsToBeDeleted] SET [ManagerName] = ? WHERE [MaterialName] = ? AND [ManagerName] = ? """ try: with get_connection() as db: affected = db.execute_update(sql, (new_manager, material_name, old_manager)) return affected > 0 except Exception as e: print(f"Error updating manager: {e}") return False # ==================== DELETE ==================== def delete_material( self, material_name: str, manager_name: str ) -> bool: """ Delete a specific material record. Args: material_name: Material name manager_name: Manager name Returns: True if successful, False otherwise """ sql = """ DELETE FROM [dbo].[MaterialsToBeDeleted] WHERE [MaterialName] = ? AND [ManagerName] = ? """ try: with get_connection() as db: affected = db.execute_update(sql, (material_name, manager_name)) return affected > 0 except Exception as e: print(f"Error deleting material: {e}") return False def delete_by_manager(self, manager_name: str) -> int: """ Delete all materials for a specific manager. Args: manager_name: Manager name Returns: Number of records deleted """ sql = """ DELETE FROM [dbo].[MaterialsToBeDeleted] WHERE [ManagerName] = ? """ try: with get_connection() as db: return db.execute_update(sql, (manager_name,)) except Exception as e: print(f"Error deleting by manager: {e}") return 0 def delete_all_materials(self) -> int: """ Delete all material records. Returns: Number of records deleted """ sql = "DELETE FROM [dbo].[MaterialsToBeDeleted]" try: with get_connection() as db: return db.execute_update(sql) except Exception as e: print(f"Error deleting all materials: {e}") return 0 # ==================== UTILITIES ==================== def material_exists(self, material_name: str) -> bool: """ Check if a material exists in the table. Args: material_name: Material name Returns: True if material exists, False otherwise """ sql = """ SELECT COUNT(*) as count FROM [dbo].[MaterialsToBeDeleted] WHERE [MaterialName] = ? """ with get_connection() as db: result = db.execute_query(sql, (material_name,)) return result[0]['count'] > 0 if result else False def count_by_manager(self, manager_name: str) -> int: """ Count materials for a specific manager. Args: manager_name: Manager name Returns: Number of materials for the manager """ sql = """ SELECT COUNT(*) as count FROM [dbo].[MaterialsToBeDeleted] WHERE [ManagerName] = ? """ with get_connection() as db: result = db.execute_query(sql, (manager_name,)) return result[0]['count'] if result else 0 def get_statistics(self) -> Dict[str, Any]: """ Get comprehensive statistics about the data. Returns: Dictionary with statistics including total materials, unique managers, and materials per manager """ sql = """ SELECT COUNT(*) as total_materials, COUNT(DISTINCT ManagerName) as unique_managers FROM [dbo].[MaterialsToBeDeleted] WHERE [MaterialName] IS NOT NULL """ with get_connection() as db: result = db.execute_query(sql) stats = result[0] if result else {} # Get materials per manager manager_sql = """ SELECT [ManagerName], COUNT(*) as count FROM [dbo].[MaterialsToBeDeleted] WHERE [ManagerName] IS NOT NULL GROUP BY [ManagerName] ORDER BY count DESC """ manager_results = db.execute_query(manager_sql) stats['materials_per_manager'] = [ {r['ManagerName']: r['count']} for r in manager_results ] return stats def search_materials(self, keyword: str) -> List[Dict[str, Any]]: """ Search materials by keyword (partial match). Args: keyword: Keyword to search for Returns: List of matching materials """ sql = """ SELECT [MaterialName], [ManagerName] FROM [dbo].[MaterialsToBeDeleted] WHERE [MaterialName] LIKE ? ORDER BY [ManagerName], [MaterialName] """ with get_connection() as db: return db.execute_query(sql, (f'%{keyword}%',))