""" Ausleihungssystem (Borrowing System) ==================================== Dieses Modul verwaltet sämtliche Ausleihungen im Inventarsystem. Es bietet alle Funktionen, um Ausleihungen zu planen, zu aktivieren, zu beenden und zu stornieren. Hauptfunktionen: - Erstellen neuer Ausleihungen (geplant oder sofort aktiv) - Aktualisieren von Ausleihungsdaten - Abschließen von Ausleihungen (Rückgabe) - Suchen und Abrufen von Ausleihungen nach verschiedenen Kriterien - Verwaltung des Ausleihungs-Lebenszyklus Sammlungsstruktur: - ausleihungen: Speichert alle Ausleihungsdatensätze mit ihrem Status - Status-Werte: 'planned' (geplant), 'active' (aktiv), 'completed' (abgeschlossen), 'cancelled' (storniert) """ ''' 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, InvalidId import datetime from dateutil import parser import os import json import Web.modules.database.settings as cfg from Web.modules.database.settings import MongoClient import Web.modules.inventarsystem.data_protection as dp def _get_client(): """Hilfsfunktion für die Erstellung einer MongoClient-Instanz.""" return MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) # Add this helper function after imports def ensure_timezone_aware(dt): """Ensures a datetime is timezone-aware, using UTC if naive""" if dt is None: return None if dt.tzinfo is None: # Treat naive datetimes as UTC return dt.replace(tzinfo=None) return dt def get_current_status(ausleihung, log_changes=False, user=None): """ Ermittelt den aktuellen Status einer Ausleihung basierend auf den Zeitstempeln und dem gespeicherten Status. Diese Funktion berücksichtigt das aktuelle Datum und aktualisiert den Status entsprechend dem realen Zustand. Status-Werte: - 'planned': Eine zukünftige Ausleihung, die noch nicht begonnen hat - 'active': Eine aktive Ausleihung, die gerade läuft - 'completed': Eine beendete Ausleihung - 'cancelled': Eine stornierte Ausleihung Args: ausleihung (dict): Der Ausleihungsdatensatz log_changes (bool): Ob Statusänderungen protokolliert werden sollen user (str): Der Benutzer, der die Prüfung durchführt (für Logs) Returns: str: Der aktuelle Status ('planned', 'active', 'completed', 'cancelled') """ # Speichern Sie den ursprünglichen Status für Logging-Zwecke original_status = ausleihung.get('Status', 'unknown') # Bei stornierten Ausleihungen bleibt der Status immer storniert if original_status == 'cancelled': return 'cancelled' # Wenn die Ausleihung bereits abgeschlossen ist, bleibt sie es if original_status == 'completed': return 'completed' current_time = datetime.datetime.now() start_time = ausleihung.get('Start') end_time = ausleihung.get('End') # Wenn kein Startdatum vorhanden ist, Status auf 'planned' setzen if not start_time: new_status = 'planned' # Wenn die aktuelle Zeit vor dem Startdatum liegt, ist die Ausleihung geplant elif current_time < start_time: # DEBUG: Log info wenn Booking noch lange in der Zukunft ist time_until_start = (start_time - current_time).total_seconds() if time_until_start > 3600: # Mehr als 1 Stunde entfernt ausleihung_id = str(ausleihung.get('_id', 'unknown'))[:12] print(f"[DEBUG] Ausleihe {ausleihung_id} startet in {time_until_start/3600:.1f} Stunden ({start_time}), noch geplant") new_status = 'planned' # Wenn kein Enddatum gesetzt ist oder die aktuelle Zeit vor dem Enddatum liegt, # ist die Ausleihung aktiv elif not end_time or current_time < end_time: new_status = 'active' # Wenn die aktuelle Zeit nach dem Enddatum liegt, ist die Ausleihung beendet else: new_status = 'completed' # Protokollieren Sie Statusänderungen, wenn aktiviert und eine Änderung stattgefunden hat if log_changes and new_status != original_status and '_id' in ausleihung: try: # Importieren Sie das Modul nur bei Bedarf, um zirkuläre Importe zu vermeiden import Web.modules.log.ausleihung_log as ausleihung_log ausleihung_log.log_status_change( str(ausleihung['_id']), original_status, new_status, dp.encrypt_text(user) ) except Exception as e: print(f"Fehler beim Protokollieren der Statusänderung: {e}") return new_status def create_backup_database(): """ Erstellt eine Sicherungskopie der Ausleihungsdatenbank. Returns: bool: True wenn Backup erfolgreich erstellt wurde, sonst False """ try: # Verbindung zur Datenbank herstellen client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] # Backup-Verzeichnis erstellen, falls es nicht existiert backup_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'backups') if not os.path.exists(backup_dir): os.makedirs(backup_dir) # Aktuelles Datum für den Dateinamen current_date = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') backup_file = os.path.join(backup_dir, f'ausleihungen_backup_{current_date}.json') # Ausleihungen abrufen und als JSON speichern all_ausleihungen = list(ausleihungen.find({})) # ObjectId in String umwandeln für JSON-Serialisierung for ausleihung in all_ausleihungen: ausleihung['_id'] = str(ausleihung['_id']) if 'Start' in ausleihung and ausleihung['Start']: ausleihung['Start'] = ausleihung['Start'].isoformat() if 'End' in ausleihung and ausleihung['End']: ausleihung['End'] = ausleihung['End'].isoformat() if 'LastUpdated' in ausleihung and ausleihung['LastUpdated']: ausleihung['LastUpdated'] = ausleihung['LastUpdated'].isoformat() with open(backup_file, 'w', encoding='utf-8') as f: json.dump(all_ausleihungen, f, ensure_ascii=False, indent=4) # Log-Eintrag erstellen log_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'logs') if not os.path.exists(log_dir): os.makedirs(log_dir) log_file = os.path.join(log_dir, 'ausleihungen_backup.log') with open(log_file, 'a', encoding='utf-8') as f: f.write(f"{current_date}: Backup erstellt: {backup_file}, {len(all_ausleihungen)} Einträge\n") client.close() return True except Exception as e: # Fehler protokollieren log_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'logs') if not os.path.exists(log_dir): os.makedirs(log_dir) log_file = os.path.join(log_dir, 'ausleihungen_error.log') with open(log_file, 'a', encoding='utf-8') as f: f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}: Backup-Fehler: {str(e)}\n") print(f"Fehler beim Erstellen des Backups: {e}") return False # === AUSLEIHUNG MANAGEMENT === def add_ausleihung(item_id, user, start_date, end_date=None, notes="", status="active", period=None, exemplar_data=None): """ Add a new borrowing record for an item. Args: item_id (str): ID of the item borrowed user (str): Username of the borrower start_date (datetime): Start date and time of the borrowing end_date (datetime, optional): End date and time if already returned notes (str, optional): Additional notes about the borrowing status (str, optional): Status of the borrowing (active, completed, planned) period (str, optional): School period for the borrowing exemplar_data (dict, optional): Information about specific exemplar borrowed Returns: ObjectId: ID of the new borrowing record or None if failed """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] ausleihung = { 'Item': item_id, 'User': dp.encrypt_text(user), 'Start': start_date, 'Status': status } if end_date: ausleihung['End'] = end_date if notes: ausleihung['Notes'] = notes if period: ausleihung['Period'] = period if exemplar_data: ausleihung['ExemplarData'] = exemplar_data result = ausleihungen.insert_one(ausleihung) ausleihung_id = result.inserted_id client.close() return ausleihung_id except Exception as e: print(f"Error adding ausleihung: {e}") return None def update_ausleihung(id, item_id=None, user_id=None, start=None, end=None, notes=None, status=None, period=None): try: # ID-Validierung try: doc_id = ObjectId(id) if isinstance(id, str) else id except InvalidId: print(f"Ungültiges ObjectId-Format: {id}") return False client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] update_data = {} if item_id is not None: update_data['Item'] = item_id if user_id is not None: # WICHTIG: Gleiche Verschlüsselung wie in add_ausleihung nutzen! update_data['User'] = dp.encrypt_text(user_id) if hasattr(dp, 'encrypt_text') else user_id if start is not None: update_data['Start'] = ensure_timezone_aware(start) if end is not None: update_data['End'] = ensure_timezone_aware(end) if notes is not None: update_data['Notes'] = notes if status is not None: update_data['Status'] = status if period is not None: update_data['Period'] = period # Keine leeren Updates ausführen (falls nur None-Parameter übergeben wurden) if not update_data: client.close() return True # UTC Zeitstempel nutzen update_data['LastUpdated'] = datetime.datetime.now(datetime.timezone.utc) result = ausleihungen.update_one( {'_id': doc_id}, {'$set': update_data} ) client.close() # Prüfen ob das Dokument überhaupt gefunden wurde (matched_count) return result.matched_count > 0 except Exception as e: print(f"Error updating ausleihung: {e}") return False def complete_ausleihung(id, end_time=None): """ Markiert eine Ausleihe als abgeschlossen, indem das Enddatum gesetzt und der Status auf 'completed' geändert wird. Args: id (str): ID des abzuschließenden Ausleihungsdatensatzes end_time (datetime, optional): Endzeitpunkt (Standard: aktuelle Zeit) Returns: bool: True bei Erfolg, sonst False """ try: if end_time is None: end_time = datetime.datetime.now() client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] item = db['items'] result = ausleihungen.update_one( {'_id': ObjectId(id)}, {'$set': { 'End': end_time, 'Status': 'completed', 'LastUpdated': datetime.datetime.now() }} ) item.update_one( {'_id': ObjectId(id)}, {'$set': { 'Verfuegbar': True, 'LastUpdated': datetime.datetime.now() }} ) client.close() return result.modified_count > 0 except Exception as e: # print(f"Error completing ausleihung: {e}") # Log the error return False def cancel_ausleihung(id): """ Storniert eine geplante Ausleihe durch Änderung des Status auf 'cancelled'. Args: id (str): ID der zu stornierenden Ausleihe Returns: bool: True bei Erfolg, sonst False """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] # Mark the booking as cancelled result = ausleihungen.update_one( {'_id': ObjectId(id)}, {'$set': { 'Status': 'cancelled', 'LastUpdated': datetime.datetime.now() }} ) client.close() return result.modified_count > 0 except Exception as e: # print(f"Error cancelling ausleihung: {e}") # Log the error return False def remove_ausleihung(id): """ Markiert einen Ausleihungsdatensatz als gelöscht (Soft-Delete). Args: id (str): ID des zu entfernenden Ausleihungsdatensatzes Returns: bool: True bei Erfolg, sonst False """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] now = datetime.datetime.now() result = ausleihungen.update_one( {'_id': ObjectId(id), 'Status': {'$ne': 'deleted'}}, {'$set': { 'Status': 'deleted', 'DeletedAt': now, 'LastUpdated': now, }} ) client.close() return result.modified_count > 0 except Exception as e: # print(f"Error removing ausleihung: {e}") # Log the error return False # === AUSLEIHUNG RETRIEVAL === def get_ausleihung(id): """ Ruft einen bestimmten Ausleihungsdatensatz anhand seiner ID ab. Args: id (str): ID des abzurufenden Ausleihungsdatensatzes Returns: dict: Der Ausleihungsdatensatz oder None, wenn nicht gefunden """ try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] ausleihung = ausleihungen.find_one({'_id': ObjectId(id)}) client.close() return ausleihung except Exception as e: # print(f"Error retrieving ausleihung: {e}") # Log the error return None def get_ausleihungen(status=None, start=None, end=None, date_filter='overlap'): try: client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] collection = db['ausleihungen'] query = {'Status': {'$ne': 'deleted'}} # Status-Filter if status is not None: if isinstance(status, list): allowed_status = [s for s in status if s != 'deleted'] query['Status'] = {'$in': allowed_status} else: query['Status'] = status if status != 'deleted' else '__blocked_deleted_status__' # Datums-Parsing if isinstance(start, str): try: start = parser.parse(start) except Exception: start = None if isinstance(end, str): try: end = parser.parse(end) except Exception: end = None # Datumsfilter-Logik if start is not None and end is not None: if date_filter == 'overlap': query['$and'] = [ {'Start': {'$lte': end}}, {'$or': [ {'End': {'$gte': start}}, {'End': None} ]} ] elif date_filter == 'start_in': query['Start'] = {'$gte': start, '$lte': end} elif date_filter == 'end_in': query['End'] = {'$gte': start, '$lte': end} elif date_filter == 'contained': query['Start'] = {'$gte': start} query['End'] = {'$exists': True, '$lte': end} elif start is not None: # Nur Startdatum angegeben -> alles was ab/nach start aktiv ist query['$or'] = [{'End': {'$gte': start}}, {'End': None}] elif end is not None: # Nur Enddatum angegeben -> alles was vor end begonnen hat query['Start'] = {'$lte': end} results = list(collection.find(query)) client.close() return results except Exception as e: # Sinnvolles Logging einbauen return [] def get_active_ausleihungen(start=None, end=None): """ Ruft alle aktiven (laufenden) Ausleihungen ab. Args: start (str/datetime, optional): Startdatum für Datumsfilterung end (str/datetime, optional): Enddatum für Datumsfilterung Returns: list: Liste aktiver Ausleihungsdatensätze """ return get_ausleihungen(status='active', start=start, end=end) def get_planned_ausleihungen(start=None, end=None): """ Ruft alle geplanten Ausleihungen (Reservierungen) ab. Args: start (str/datetime, optional): Startdatum für Datumsfilterung end (str/datetime, optional): Enddatum für Datumsfilterung Returns: list: Liste geplanter Ausleihungsdatensätze """ return get_ausleihungen(status='planned', start=start, end=end) def get_completed_ausleihungen(start=None, end=None): """ Ruft alle abgeschlossenen Ausleihungen ab. Args: start (str/datetime, optional): Startdatum für Datumsfilterung end (str/datetime, optional): Enddatum für Datumsfilterung Returns: list: Liste abgeschlossener Ausleihungsdatensätze """ return get_ausleihungen(status='completed', start=start, end=end) def get_cancelled_ausleihungen(start=None, end=None): """ Ruft alle stornierten Ausleihungen ab. Args: start (str/datetime, optional): Startdatum für Datumsfilterung end (str/datetime, optional): Enddatum für Datumsfilterung Returns: list: Liste stornierter Ausleihungsdatensätze """ return get_ausleihungen(status='cancelled', start=start, end=end) # === SEARCH FUNCTIONS === def get_ausleihung_by_user(user_id, status=None, use_client_side_verification=True): """Ruft Ausleihungen für einen bestimmten Benutzer ab.""" try: with _get_client() as client: db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] # Ensure proper encrypted query string if user IDs are encrypted in DB search_user = dp.encrypt_text(user_id) if hasattr(dp, 'encrypt_text') else user_id query = {'User': search_user, 'Status': {'$ne': 'deleted'}} if not use_client_side_verification: if status is not None: if isinstance(status, list): query['Status'] = {'$in': status} else: query['Status'] = status else: query['Status'] = {'$ne': 'cancelled'} return list(ausleihungen.find(query)) all_ausleihungen = list(ausleihungen.find(query)) for record in all_ausleihungen: current_status = get_current_status(record) if 'get_current_status' in globals() else record.get( 'Status') record['VerifiedStatus'] = current_status if status is None: return all_ausleihungen filtered_results = [] target_statuses = status if isinstance(status, list) else [status] for record in all_ausleihungen: v_status = record.get('VerifiedStatus') if v_status in target_statuses and v_status != 'deleted': filtered_results.append(record) return filtered_results except Exception as e: print(f"Error retrieving ausleihungen for user {user_id}: {e}") return [] def get_ausleihung_by_item(item_id, status=None, include_history=False): """Get most recent ausleihung record for a specific item.""" try: with _get_client() as client: db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] query = {'Item': item_id, 'Status': {'$ne': 'deleted'}} if status and not include_history: query['Status'] = status record = ausleihungen.find_one(query, sort=[('Start', -1)]) if record: record['_id'] = str(record['_id']) return record except Exception as e: print(f"Error getting ausleihung by item: {e}") return None def get_ausleihungen_by_date_range(start_date, end_date, status=None): """Ruft Ausleihungen ab, die in einem bestimmten Zeitraum aktiv waren.""" return get_ausleihungen(status=status, start=start_date, end=end_date) def check_ausleihung_conflict(item_id, start_date, end_date, period=None): """Prüft, ob es Konflikte mit bestehenden Ausleihungen oder aktiven Ausleihen gibt.""" try: start_date = ensure_timezone_aware(start_date) end_date = ensure_timezone_aware(end_date) with _get_client() as client: db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] booking_date = start_date.date() all_bookings = list(ausleihungen.find({ 'Item': item_id, 'Status': {'$in': ['planned', 'active']} })) if period is not None: period_int = int(period) for booking in all_bookings: booking_start = ensure_timezone_aware(booking.get('Start')) if booking_start and booking_start.date() == booking_date: booking_period = booking.get('Period') if booking_period is not None and int(booking_period) == period_int: return True for booking in all_bookings: b_start = ensure_timezone_aware(booking.get('Start')) if not b_start: continue b_end = ensure_timezone_aware(booking.get('End')) or (b_start + datetime.timedelta(hours=1)) # Simplified and standard time range collision check if start_date < b_end and end_date > b_start: return True return False except Exception as e: print(f"Error checking booking conflicts: {e}") return True # Return conflict on exception for safety def check_booking_period_range_conflict(item_id, start_date, end_date, period=None, period_end=None): """Checks for conflicts with existing bookings, supporting period ranges.""" try: start_date = ensure_timezone_aware(start_date) end_date = ensure_timezone_aware(end_date) with _get_client() as client: db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] booking_date = start_date.date() all_bookings = list(ausleihungen.find({ 'Item': item_id, 'Status': {'$in': ['planned', 'active']} })) if period is not None: period_start = int(period) periods_to_check = [period_start] if period_end is not None: periods_to_check = list(range(period_start, int(period_end) + 1)) for booking in all_bookings: b_start = ensure_timezone_aware(booking.get('Start')) if b_start and b_start.date() == booking_date: booking_period = booking.get('Period') try: booking_period_int = int(booking_period) if booking_period is not None else None except Exception: booking_period_int = None if booking_period_int in periods_to_check: return True for booking in all_bookings: b_start = ensure_timezone_aware(booking.get('Start')) if not b_start: continue b_end = ensure_timezone_aware(booking.get('End')) or (b_start + datetime.timedelta(hours=1)) if start_date < b_end and end_date > b_start: return True return False except Exception as e: print(f"Error checking booking range conflicts: {e}") return True def get_ausleihungen_starting_now(current_time): """Ruft Ausleihungen ab, die jetzt beginnen sollen.""" try: current_time = ensure_timezone_aware(current_time) start_time = current_time - datetime.timedelta(hours=3) end_time = current_time + datetime.timedelta(hours=1) today = current_time.date() with _get_client() as client: db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] query = { 'Status': 'planned', '$or': [ {'Start': {'$lte': end_time, '$gte': start_time}}, { 'Period': {'$exists': True}, 'Start': { '$gte': datetime.datetime.combine(today, datetime.time.min, tzinfo=datetime.timezone.utc), '$lt': datetime.datetime.combine(today + datetime.timedelta(days=1), datetime.time.min, tzinfo=datetime.timezone.utc) } } ] } return list(ausleihungen.find(query)) except Exception as e: print(f"Error in get_ausleihungen_starting_now: {e}") return [] def get_ausleihungen_ending_now(current_time): """Ruft Ausleihungen ab, die jetzt enden sollen.""" try: current_time = ensure_timezone_aware(current_time) start_time = current_time - datetime.timedelta(minutes=15) end_time = current_time + datetime.timedelta(minutes=5) today = current_time.date() with _get_client() as client: db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] query = { 'Status': 'active', '$or': [ {'End': {'$gte': start_time, '$lte': end_time}}, { 'Period': {'$exists': True}, 'Start': { '$gte': datetime.datetime.combine(today, datetime.time.min, tzinfo=datetime.timezone.utc), '$lt': datetime.datetime.combine(today + datetime.timedelta(days=1), datetime.time.min, tzinfo=datetime.timezone.utc) } } ] } return list(ausleihungen.find(query)) except Exception as e: print(f"Error in get_ausleihungen_ending_now: {e}") return [] def activate_ausleihung(id): """Aktiviert eine geplante Ausleihe.""" try: doc_id = ObjectId(id) if isinstance(id, str) else id with _get_client() as client: db = client[cfg.MONGODB_DB] ausleihungen = db['ausleihungen'] result = ausleihungen.update_one( {'_id': doc_id, 'Status': 'planned'}, {'$set': { 'Status': 'active', 'LastUpdated': datetime.datetime.now(datetime.timezone.utc) }} ) return result.modified_count > 0 except Exception as e: print(f"Error activating ausleihung: {e}") return False def reset_item_completely(item_id): """Setzt den Ausleihstatus eines Items vollständig zurück.""" try: doc_id = ObjectId(item_id) if isinstance(item_id, str) else item_id with _get_client() as client: db = client[cfg.MONGODB_DB] items_collection = db['items'] ausleihungen_collection = db['ausleihungen'] item = items_collection.find_one({'_id': doc_id}) if not item: return {'success': False, 'message': 'Item nicht gefunden'} item_name = item.get('Name', 'Unbekannt') now_utc = datetime.datetime.now(datetime.timezone.utc) # 1. Bulk update active borrowings update_res = ausleihungen_collection.update_many( { 'Item': str(item_id), 'Status': {'$in': ['active', 'planned']} }, { '$set': { 'Status': 'completed', 'End': now_utc, 'LastUpdated': now_utc, 'CompletedBy': 'System Reset' } } ) completed_count = update_res.modified_count # 2. Reset Item document with valid PyMongo update query format update_query = { '$set': { 'Verfuegbar': True, 'LastUpdated': now_utc } } unsets = {} if 'User' in item: unsets['User'] = '' if 'BorrowerInfo' in item: unsets['BorrowerInfo'] = '' if 'ExemplareStatus' in item: unsets['ExemplareStatus'] = '' if unsets: update_query['$unset'] = unsets result = items_collection.update_one({'_id': doc_id}, update_query) return { 'success': True, 'message': f'Item "{item_name}" wurde erfolgreich zurückgesetzt', 'details': { 'completed_borrowings': completed_count, 'item_reset': result.modified_count > 0 } } except Exception as e: print(f"Error resetting item: {e}") return {'success': False, 'message': f'Fehler beim Zurücksetzen: {e}'} # === KOMPATIBILITÄTSFUNKTIONEN === def add_planned_booking(item_id, user, start_date, end_date, notes="", period=None): return add_ausleihung(item_id, user, start_date, end_date, notes, status='planned', period=period) def check_booking_conflict(item_id, start_date, end_date, period=None): return check_ausleihung_conflict(item_id, start_date, end_date, period) def mark_booking_active(booking_id, ausleihung_id=None): try: doc_id = ObjectId(booking_id) if isinstance(booking_id, str) else booking_id update_data = { 'Status': 'active', 'LastUpdated': datetime.datetime.now(datetime.timezone.utc) } if ausleihung_id: update_data['AusleihungId'] = ausleihung_id with _get_client() as client: db = client[cfg.MONGODB_DB] res = db['ausleihungen'].update_one({'_id': doc_id}, {'$set': update_data}) return res.matched_count > 0 except Exception as e: print(f"Error activating booking: {e}") return activate_ausleihung(booking_id) def get_bookings_starting_now(current_time): return get_ausleihungen_starting_now(current_time) def get_bookings_ending_now(current_time): return get_ausleihungen_ending_now(current_time)