""" Inventory Items Management ========================= This module manages inventory items in the database. It provides comprehensive functionality for creating, updating, retrieving and filtering inventory items. Key Features: - Creating and updating inventory items - Retrieving items by ID, name, or filters - Managing item availability status - Supporting images and categorization - Retrieving filter/category values for UI components Collection Structure: - items: Stores all inventory item records with their metadata - Required fields: Name, Ort, Beschreibung - Optional fields: Images, Filter, Filter2, Filter3, Anschaffungsjahr, Anschaffungskosten, Code_4 - Status fields: Verfuegbar, User (if currently borrowed) """ ''' Copyright 2025-2026 AIIrondev Licensed under the Inventarsystem EULA (Endbenutzer-Lizenzvertrag). See Legal/LICENSE for the full license text. Unauthorized commercial use, SaaS hosting, or removal of branding is prohibited. For commercial licensing inquiries: https://github.com/AIIrondev ''' from bson.objectid import ObjectId import datetime import Web.modules.database.settings as cfg from Web.modules.database.settings import MongoClient LIBRARY_ITEM_TYPES = ('book', 'cd', 'dvd', 'media') def _non_library_query(extra_query=None): """Build a query that excludes library media items from normal inventory.""" base_query = {'ItemType': {'$nin': list(LIBRARY_ITEM_TYPES)}} if extra_query: base_query.update(extra_query) return base_query def _active_record_query(extra_query=None): """Build a query that excludes logically deleted records.""" base_query = {'Deleted': {'$ne': True}} if extra_query: base_query.update(extra_query) return base_query # === ITEM MANAGEMENT === def add_item(name, ort, beschreibung, images=None, filter=None, filter2=None, filter3=None, ansch_jahr=None, ansch_kost=None, code_4=None, reservierbar=True, series_group_id=None, series_count=1, series_position=1, is_grouped_sub_item=False, parent_item_id=None, isbn=None, item_type='general'): """ Add a new item to the inventory. Args: name (str): Name of the item ort (str): Location of the item beschreibung (str): Description of the item images (list, optional): List of image filenames for the item filter (str, optional): Primary filter/category for the item filter2 (str, optional): Secondary filter/category for the item filter3 (str, optional): Tertiary filter/category for the item ansch_jahr (int, optional): Year of acquisition ansch_kost (float, optional): Cost of acquisition code_4 (str, optional): 4-digit identification code reservierbar (bool, optional): Whether the item can be reserved in advance series_group_id (str, optional): Shared group id for same-type batch items series_count (int, optional): Total items in the created batch series_position (int, optional): Position inside the batch (1-based) is_grouped_sub_item (bool, optional): Whether this item is hidden as sub-item parent_item_id (str, optional): Parent item id if this is a sub-item Returns: ObjectId: ID of the new item or None if failed """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] # Set default values for optional parameters if images is None: images = [] item = { 'Name': name, 'Ort': ort, 'Beschreibung': beschreibung, 'Images': images, 'Verfuegbar': True, 'Reservierbar': reservierbar, 'Filter': filter, 'Filter2': filter2, 'Filter3': filter3, 'Anschaffungsjahr': ansch_jahr, 'Anschaffungskosten': ansch_kost, 'Code_4': code_4, 'ISBN': isbn, 'ItemType': item_type, 'SeriesGroupId': series_group_id, 'SeriesCount': series_count, 'SeriesPosition': series_position, 'IsGroupedSubItem': is_grouped_sub_item, 'ParentItemId': parent_item_id, 'Created': datetime.datetime.now(), 'LastUpdated': datetime.datetime.now() } result = items.insert_one(item) item_id = result.inserted_id client.close() return item_id except Exception as e: print(f"Error adding item: {e}") return None def remove_item(id): """ Soft-delete an item from the inventory. Args: id (str): ID of the item to remove Returns: bool: True if successful, False otherwise """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] result = items.update_one( {'_id': ObjectId(id), 'Deleted': {'$ne': True}}, {'$set': { 'Deleted': True, 'DeletedAt': datetime.datetime.now(), 'LastUpdated': datetime.datetime.now(), 'Verfuegbar': False, }} ) client.close() return result.modified_count > 0 except Exception as e: print(f"Error removing item: {e}") return False def get_group_item_ids(id): """ Resolve all item ids that belong to the same grouped series as the given item. For non-grouped items, this returns only the provided id. Args: id (str): ID of any item in the group Returns: list[str]: All related item IDs (including the parent item) """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] base_item = items.find_one(_active_record_query({'_id': ObjectId(id)})) if not base_item: client.close() return [] resolved_ids = set() # Prefer SeriesGroupId because it represents the full logical group. series_group_id = base_item.get('SeriesGroupId') if series_group_id: for group_item in items.find(_active_record_query({'SeriesGroupId': series_group_id}), {'_id': 1}): resolved_ids.add(str(group_item['_id'])) else: resolved_ids.add(str(base_item['_id'])) parent_item_id = base_item.get('ParentItemId') if parent_item_id: resolved_ids.add(str(parent_item_id)) for sibling in items.find(_active_record_query({'ParentItemId': str(parent_item_id), 'IsGroupedSubItem': True}), {'_id': 1}): resolved_ids.add(str(sibling['_id'])) else: for child in items.find(_active_record_query({'ParentItemId': str(base_item['_id']), 'IsGroupedSubItem': True}), {'_id': 1}): resolved_ids.add(str(child['_id'])) client.close() return list(resolved_ids) except Exception as e: print(f"Error resolving group item IDs: {e}") return [] def update_item(id, name, ort, beschreibung, images=None, verfuegbar=True, filter=None, filter2=None, filter3=None, ansch_jahr=None, ansch_kost=None, code_4=None, reservierbar=True, isbn=None, item_type='general'): """ Update an existing inventory item. Args: id (str): ID of the item to update name (str): Name of the item ort (str): Location of the item beschreibung (str): Description of the item images (list, optional): List of image filenames for the item verfuegbar (bool, optional): Availability status of the item filter (str, optional): Primary filter/category for the item filter2 (str, optional): Secondary filter/category for the item filter3 (str, optional): Tertiary filter/category for the item ansch_jahr (int, optional): Year of acquisition ansch_kost (float, optional): Cost of acquisition code_4 (str, optional): 4-digit identification code reservierbar (bool, optional): Whether the item can be reserved in advance Returns: bool: True if successful, False otherwise """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] # Set default values for optional parameters if images is None: images = [] update_data = { 'Name': name, 'Ort': ort, 'Beschreibung': beschreibung, 'Images': images, 'Verfuegbar': verfuegbar, 'Reservierbar': reservierbar, 'Filter': filter, 'Filter2': filter2, 'Filter3': filter3, 'Anschaffungsjahr': ansch_jahr, 'Anschaffungskosten': ansch_kost, 'Code_4': code_4, 'ISBN': isbn, 'ItemType': item_type, 'LastUpdated': datetime.datetime.now() } result = items.update_one( {'_id': ObjectId(id)}, {'$set': update_data} ) client.close() return result.modified_count > 0 except Exception as e: print(f"Error updating item: {e}") return False def update_item_status(id, verfuegbar, user=None): """ Update the availability status of an inventory item. Args: id (str): ID of the item to update verfuegbar (bool): New availability status user (str, optional): Username of person who borrowed the item Returns: bool: True if successful, False otherwise """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] update_data = { 'Verfuegbar': verfuegbar, 'LastUpdated': datetime.datetime.now() } update_query = {'$set': update_data} if user is not None: update_data['User'] = user elif verfuegbar: # If item is being marked as available, clear the user field update_query['$unset'] = {'User': ""} result = items.update_one( {'_id': ObjectId(id)}, update_query ) client.close() return result.modified_count > 0 except Exception as e: print(f"Error updating item status: {e}") return False def update_item_exemplare_status(id, exemplare_status): """ Update the exemplar status of an inventory item. Args: id (str): ID of the item to update exemplare_status (list): List of status objects for each exemplar Returns: bool: True if successful, False otherwise """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] update_data = { 'ExemplareStatus': exemplare_status, 'LastUpdated': datetime.datetime.now() } result = items.update_one( {'_id': ObjectId(id)}, {'$set': update_data} ) client.close() return result.modified_count > 0 except Exception as e: print(f"Error updating exemplar status: {e}") return False def is_code_unique(code_4, exclude_id=None): """ Check if a given code is unique (not used by any other item). Args: code_4 (str): The code to check exclude_id (str, optional): ID of item to exclude from the check (for edit operations) Returns: bool: True if code is unique, False if already in use """ if not code_4 or code_4.strip() == "": # Empty codes are not considered unique return False client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] # Build query to find items with this code query = {'Code_4': code_4, 'Deleted': {'$ne': True}} # If we're editing an item, exclude it from the uniqueness check if exclude_id: query['_id'] = {'$ne': ObjectId(exclude_id)} # Check if any items with this code exist count = items.count_documents(query) client.close() return count == 0 # === ITEM RETRIEVAL === def get_items(): """ Retrieve all inventory items. Returns: list: List of all inventory item documents with string IDs """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] items_return = items.find(_active_record_query(_non_library_query())) items_list = [] for item in items_return: item['_id'] = str(item['_id']) items_list.append(item) client.close() return items_list except Exception as e: print(f"Error retrieving items: {e}") return [] def get_available_items(): """ Retrieve all available inventory items. Returns: list: List of available inventory item documents with string IDs """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] items_return = items.find(_active_record_query(_non_library_query({'Verfuegbar': True}))) items_list = [] for item in items_return: item['_id'] = str(item['_id']) items_list.append(item) client.close() return items_list except Exception as e: print(f"Error retrieving available items: {e}") return [] def get_borrowed_items(): """ Retrieve all currently borrowed inventory items. Returns: list: List of borrowed inventory item documents with string IDs """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] items_return = items.find(_active_record_query(_non_library_query({'Verfuegbar': False}))) items_list = [] for item in items_return: item['_id'] = str(item['_id']) items_list.append(item) client.close() return items_list except Exception as e: print(f"Error retrieving borrowed items: {e}") return [] def get_item(id): """ Retrieve a specific inventory item by its ID. Args: id (str): ID of the item to retrieve Returns: dict: The inventory item document or None if not found """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] item = items.find_one(_active_record_query({'_id': ObjectId(id)})) client.close() return item except Exception as e: print(f"Error retrieving item: {e}") return None def get_item_by_name(name): """ Retrieve a specific inventory item by its name. Args: name (str): Name of the item to retrieve Returns: dict: The inventory item document or None if not found """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] item = items.find_one(_active_record_query({'Name': name})) client.close() return item except Exception as e: print(f"Error retrieving item by name: {e}") return None def get_items_by_filter(filter_value): """ Retrieve inventory items matching a specific filter/category. Args: filter_value (str): Filter value to search for Returns: list: List of items matching the filter in primary, secondary, or tertiary category """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] # Use $or to find matches in any filter field query = _active_record_query(_non_library_query({ '$or': [ {'Filter': filter_value}, {'Filter2': filter_value}, {'Filter3': filter_value} ] })) results = list(items.find(query)) client.close() # Convert ObjectId to string for item in results: item['_id'] = str(item['_id']) return results except Exception as e: print(f"Error retrieving items by filter: {e}") return [] def get_filters(): """ Retrieve all unique filter/category values from the inventory. Returns: list: Combined list of all primary, secondary and tertiary filter values """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] non_library = _active_record_query(_non_library_query()) filters = items.distinct('Filter', non_library) filters2 = items.distinct('Filter2', non_library) filters3 = items.distinct('Filter3', non_library) # Combine filters and remove None/empty values all_filters = [f for f in filters + filters2 + filters3 if f] # Remove duplicates while preserving order unique_filters = [] for f in all_filters: if f not in unique_filters: unique_filters.append(f) client.close() return unique_filters except Exception as e: print(f"Error retrieving filters: {e}") return [] def get_primary_filters(): """ Retrieve all unique primary filter values. Returns: list: List of all primary filter values """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] filters = [f for f in items.distinct('Filter', _active_record_query(_non_library_query())) if f] client.close() # Add predefined values predefined = get_predefined_filter_values(1) return sorted(list(set(filters + predefined))) except Exception as e: print(f"Error retrieving primary filters: {e}") return [] def get_secondary_filters(): """ Retrieve all unique secondary filter values. Returns: list: List of all secondary filter values """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] filters = [f for f in items.distinct('Filter2', _active_record_query(_non_library_query())) if f] client.close() # Add predefined values predefined = get_predefined_filter_values(2) return sorted(list(set(filters + predefined))) except Exception as e: print(f"Error retrieving secondary filters: {e}") return [] def get_tertiary_filters(): """ Retrieve all unique tertiary filter values. Returns: list: List of all tertiary filter values """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] filters = [f for f in items.distinct('Filter3', _active_record_query(_non_library_query())) if f] client.close() # Add predefined values predefined = get_predefined_filter_values(3) return sorted(list(set(filters + predefined))) except Exception as e: print(f"Error retrieving tertiary filters: {e}") return [] def get_item_by_code_4(code_4): """ Retrieve inventory items matching a specific 4-digit code. Args: code_4 (str): 4-digit code to search for Returns: list: List of items matching the code """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] results = list(items.find(_active_record_query(_non_library_query({"Code_4": code_4})))) # Convert ObjectId to string for item in results: item['_id'] = str(item['_id']) client.close() return results except Exception as e: print(f"Error retrieving item by code: {e}") return [] # === MAINTENANCE FUNCTIONS === def unstuck_item(id): """ Remove all borrowing records for a specific item to reset its status. Used to fix problematic or stuck items. Args: id (str): ID of the item to unstick Returns: bool: True if successful, False otherwise """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] result = ausleihungen.update_many( {'Item': id, 'Status': {'$nin': ['cancelled', 'deleted']}}, {'$set': { 'Status': 'cancelled', 'CancelledReason': 'unstuck_reset', 'LastUpdated': datetime.datetime.now() }} ) # Also reset the item status items = db['items'] items.update_one( {'_id': ObjectId(id)}, { '$set': { 'Verfuegbar': True, 'LastUpdated': datetime.datetime.now() }, '$unset': {'User': ""} } ) client.close() return True except Exception as e: print(f"Error unsticking item: {e}") return False def get_predefined_filter_values(filter_num): """ Get predefined values for a specific filter. Args: filter_num (int): Filter number (1 for Unterrichtsfach, 2 for Jahrgangsstufe) Returns: list: List of predefined filter values """ client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] # Use a dedicated collection for filter presets filter_presets = db['filter_presets'] # Find the document for the specified filter filter_doc = filter_presets.find_one({'filter_num': filter_num}) client.close() if filter_doc and 'values' in filter_doc: # Sort values alphabetically return sorted(filter_doc['values']) else: # Create empty document if it doesn't exist client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] filter_presets = db['filter_presets'] filter_presets.update_one( {'filter_num': filter_num}, {'$set': {'values': []}}, upsert=True ) client.close() return [] def add_predefined_filter_value(filter_num, value): """ Add a new predefined value to a filter. Args: filter_num (int): Filter number (1 for Unterrichtsfach, 2 for Jahrgangsstufe) value (str): Value to add Returns: bool: True if value was added, False if it already existed """ client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] filter_presets = db['filter_presets'] # Check if value already exists filter_doc = filter_presets.find_one({ 'filter_num': filter_num, 'values': value }) if filter_doc: # Value already exists client.close() return False # Add the value to the filter result = filter_presets.update_one( {'filter_num': filter_num}, {'$push': {'values': value}}, upsert=True ) client.close() return result.modified_count > 0 or result.upserted_id is not None def remove_predefined_filter_value(filter_num, value): """ Remove a predefined value from a filter. Args: filter_num (int): Filter number (1 for Unterrichtsfach, 2 for Jahrgangsstufe) value (str): Value to remove Returns: bool: True if value was removed, False otherwise """ client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] filter_presets = db['filter_presets'] # Remove the value from the filter result = filter_presets.update_one( {'filter_num': filter_num}, {'$pull': {'values': value}} ) client.close() return result.modified_count > 0 def edit_predefined_filter_value(filter_num, old_value, new_value): """ Edit a predefined value from a filter and update all matching items. Args: filter_num (int): Filter number (1 for Unterrichtsfach, 2 for Jahrgangsstufe) old_value (str): Value to replace new_value (str): New value Returns: bool: True if value was updated, False otherwise """ client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] filter_presets = db['filter_presets'] # Check if the new value already exists existing = filter_presets.find_one({ 'filter_num': filter_num, 'values': new_value }) if existing and old_value != new_value: client.close() return False # Update the value in the filter result = filter_presets.update_one( {'filter_num': filter_num, 'values': old_value}, {'$set': {'values.$': new_value}} ) if result.modified_count > 0: items = db['items'] filter_field = 'Filter' if filter_num == 1 else f'Filter{filter_num}' # Also update all items that use this filter items.update_many( {filter_field: old_value}, {'$set': {filter_field: new_value}} ) client.close() return result.modified_count > 0 def get_filter_names(): """Get customized filter category names.""" client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] names_doc = db.settings.find_one({'setting_type': 'filter_names'}) client.close() if names_doc and 'names' in names_doc: return names_doc['names'] return { '1': 'Fach/Kategorie', '2': 'System/Bereich', '3': 'Typ/Art' } def set_filter_name(filter_num, name): """Set custom name for a filter category.""" client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] names = get_filter_names() names[str(filter_num)] = name db.settings.update_one( {'setting_type': 'filter_names'}, {'$set': {'names': names}}, upsert=True ) client.close() return True # === LOCATION MANAGEMENT === def get_predefined_locations(): """ Get list of all predefined locations/placement options. Returns: list: List of predefined location strings """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] # Check if settings collection exists, create if not if 'settings' not in db.list_collection_names(): db.create_collection('settings') # Get settings document or create if it doesn't exist settings_collection = db['settings'] location_settings = settings_collection.find_one({'setting_type': 'predefined_locations'}) if not location_settings: # Create default settings document if it doesn't exist settings_collection.insert_one({ 'setting_type': 'predefined_locations', 'locations': [] }) return [] # Return the predefined locations locations = location_settings.get('locations', []) client.close() return sorted(locations) except Exception as e: print(f"Error getting predefined locations: {str(e)}") return [] def add_predefined_location(location): """ Add a new predefined location. Args: location (str): Location to add Returns: bool: True if added successfully, False if already exists """ if not location or not isinstance(location, str): return False location = location.strip() if not location: return False try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] settings_collection = db['settings'] # Check if settings document exists, create if not location_settings = settings_collection.find_one({'setting_type': 'predefined_locations'}) if not location_settings: # Create with the new location settings_collection.insert_one({ 'setting_type': 'predefined_locations', 'locations': [location] }) client.close() return True # Check if location already exists (case-insensitive) current_locations = location_settings.get('locations', []) if any(loc.lower() == location.lower() for loc in current_locations): client.close() return False # Add the new location settings_collection.update_one( {'setting_type': 'predefined_locations'}, {'$push': {'locations': location}} ) client.close() return True except Exception as e: print(f"Error adding predefined location: {str(e)}") return False def remove_predefined_location(location): """ Remove a predefined location. Args: location (str): Location to remove Returns: bool: True if removed successfully """ if not location: return False try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] settings_collection = db['settings'] result = settings_collection.update_one( {'setting_type': 'predefined_locations'}, {'$pull': {'locations': location}} ) client.close() return result.modified_count > 0 except Exception as e: print(f"Error removing predefined location: {str(e)}") return False def update_item_next_appointment(item_id, appointment_data): """ Update an item with information about its next scheduled appointment. Args: item_id (str): ID of the item to update appointment_data (dict): Appointment information containing: - date: Date of the appointment - start_period: Start period number - end_period: End period number - user: Username who scheduled the appointment - notes: Optional notes - appointment_id: ID of the appointment booking Returns: bool: True if successful, False otherwise """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] # Format the appointment data for storage # Ensure date is a datetime object for MongoDB storage appointment_date = appointment_data['date'] if isinstance(appointment_date, datetime.date) and not isinstance(appointment_date, datetime.datetime): # Convert date to datetime for MongoDB compatibility appointment_date = datetime.datetime.combine(appointment_date, datetime.time()) next_appointment = { 'date': appointment_date, 'end_date': appointment_data.get('end_date', appointment_date), 'start_period': appointment_data['start_period'], 'end_period': appointment_data['end_period'], 'user': appointment_data['user'], 'notes': appointment_data.get('notes', ''), 'appointment_id': appointment_data['appointment_id'], 'scheduled_at': datetime.datetime.now() } update_data = { 'NextAppointment': next_appointment, 'LastUpdated': datetime.datetime.now() } result = items.update_one( {'_id': ObjectId(item_id)}, {'$set': update_data} ) client.close() return result.modified_count > 0 except Exception as e: print(f"Error updating item next appointment: {e}") return False def clear_item_next_appointment(item_id): """ Clear the next appointment information from an item. Args: item_id (str): ID of the item to update Returns: bool: True if successful, False otherwise """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] result = items.update_one( {'_id': ObjectId(item_id)}, {'$unset': {'NextAppointment': ""}, '$set': {'LastUpdated': datetime.datetime.now()}} ) client.close() return result.modified_count > 0 except Exception as e: print(f"Error clearing item next appointment: {e}") return False def get_items_with_appointments(): """ Retrieve all items that have scheduled appointments. Returns: list: List of items with NextAppointment field """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] items_return = items.find({'NextAppointment': {'$exists': True}, 'Deleted': {'$ne': True}}) items_list = [] for item in items_return: item['_id'] = str(item['_id']) items_list.append(item) client.close() return items_list except Exception as e: print(f"Error retrieving items with appointments: {e}") return [] def get_current_status(item_id): """ Retrieve the current status of an item, including availability and user. Args: item_id (str): ID of the item to check Returns: dict: Current status of the item or None if not found """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] items = db['items'] item = items.find_one({'_id': ObjectId(item_id)}, {'Verfuegbar': 1, 'User': 1}) if item: # Convert ObjectId to string for consistency item['_id'] = str(item['_id']) client.close() return item else: client.close() return None except Exception as e: print(f"Error retrieving current status: {e}") return None