# Routes for Lead Management from flask import render_template, request, jsonify, redirect, url_for, flash from auth.decorators import login_required from flask import session as flask_session from . import leads_bp from .services import LeadService from .repositories import LeadRepository from db import get_db_connection from uuid import UUID import traceback # Service will be initialized per request lead_repository = None lead_service = None def get_lead_service(): """Get or create lead service instance""" global lead_repository, lead_service if lead_service is None: lead_repository = LeadRepository(get_db_connection) # Pass the function, not call it lead_service = LeadService(lead_repository) return lead_service # HTML Routes @leads_bp.route('/management') @login_required def lead_management(): """Lead Management Dashboard""" try: # Get current user current_user = flask_session.get('username', 'System') other_user = 'w@rh@mm3r' if current_user == 'rac00n' else 'rac00n' # Initialize defaults total_institutions = 0 total_contacts = 0 my_entries = 0 other_entries = 0 activities = [] with get_db_connection() as conn: cur = conn.cursor() # Get statistics cur.execute("SELECT COUNT(*) FROM lead_institutions") result = cur.fetchone() if result: total_institutions = result[0] cur.execute("SELECT COUNT(*) FROM lead_contacts") result = cur.fetchone() if result: total_contacts = result[0] # Count entries by current user cur.execute(""" SELECT COUNT(*) FROM audit_log WHERE username = %s AND entity_type IN ('lead_institution', 'lead_contact') AND action = 'CREATE' """, (current_user,)) result = cur.fetchone() if result: my_entries = result[0] # Count entries by other user cur.execute(""" SELECT COUNT(*) FROM audit_log WHERE username = %s AND entity_type IN ('lead_institution', 'lead_contact') AND action = 'CREATE' """, (other_user,)) result = cur.fetchone() if result: other_entries = result[0] # Get recent activities cur.execute(""" SELECT timestamp, username, action, entity_type, additional_info FROM audit_log WHERE entity_type IN ('lead_institution', 'lead_contact') ORDER BY timestamp DESC LIMIT 10 """) rows = cur.fetchall() if rows: for row in rows: activities.append({ 'timestamp': row[0], 'username': row[1], 'action': row[2], 'entity_type': row[3].replace('lead_', ''), 'additional_info': row[4] }) cur.close() return render_template('leads/lead_management.html', total_institutions=total_institutions, total_contacts=total_contacts, my_entries=my_entries, other_entries=other_entries, other_user=other_user, current_user=current_user, recent_activities=activities) except Exception as e: import traceback print(f"Error in lead_management: {str(e)}") print(traceback.format_exc()) flash(f'Fehler beim Laden des Dashboards: {str(e)}', 'error') current_user = flask_session.get('username', 'System') return render_template('leads/lead_management.html', total_institutions=0, total_contacts=0, my_entries=0, other_entries=0, other_user='', current_user=current_user, recent_activities=[]) @leads_bp.route('/') @login_required def institutions(): """List all institutions""" try: institutions = get_lead_service().list_institutions() return render_template('leads/institutions.html', institutions=institutions) except Exception as e: flash(f'Fehler beim Laden der Institutionen: {str(e)}', 'error') return render_template('leads/institutions.html', institutions=[]) @leads_bp.route('/institution/add', methods=['POST']) @login_required def add_institution(): """Add new institution from form""" try: name = request.form.get('name') if not name: flash('Name ist erforderlich', 'error') return redirect(url_for('leads.lead_management')) # Add institution get_lead_service().create_institution(name, flask_session.get('username', 'System')) flash(f'Institution "{name}" wurde erfolgreich hinzugefügt', 'success') except Exception as e: flash(f'Fehler beim Hinzufügen der Institution: {str(e)}', 'error') return redirect(url_for('leads.lead_management')) @leads_bp.route('/institution/') @login_required def institution_detail(institution_id): """Show institution with all contacts""" try: institution = lead_repository.get_institution_by_id(institution_id) if not institution: flash('Institution nicht gefunden', 'error') return redirect(url_for('leads.institutions')) contacts = get_lead_service().list_contacts_by_institution(institution_id) return render_template('leads/institution_detail.html', institution=institution, contacts=contacts) except Exception as e: flash(f'Fehler beim Laden der Institution: {str(e)}', 'error') return redirect(url_for('leads.institutions')) @leads_bp.route('/contact/') @login_required def contact_detail(contact_id): """Show contact details with notes""" try: contact = get_lead_service().get_contact_details(contact_id) return render_template('leads/contact_detail.html', contact=contact) except Exception as e: flash(f'Fehler beim Laden des Kontakts: {str(e)}', 'error') return redirect(url_for('leads.institutions')) @leads_bp.route('/contacts') @login_required def all_contacts(): """Show all contacts across all institutions""" try: contacts = get_lead_service().list_all_contacts() return render_template('leads/all_contacts.html', contacts=contacts) except Exception as e: flash(f'Fehler beim Laden der Kontakte: {str(e)}', 'error') return render_template('leads/all_contacts.html', contacts=[]) # API Routes @leads_bp.route('/api/institutions', methods=['POST']) @login_required def create_institution(): """Create new institution""" try: data = request.get_json() institution = get_lead_service().create_institution( data['name'], flask_session.get('username') ) return jsonify({'success': True, 'institution': institution}) except ValueError as e: return jsonify({'success': False, 'error': str(e)}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/institutions/', methods=['PUT']) @login_required def update_institution(institution_id): """Update institution""" try: data = request.get_json() institution = get_lead_service().update_institution( institution_id, data['name'], flask_session.get('username') ) return jsonify({'success': True, 'institution': institution}) except ValueError as e: return jsonify({'success': False, 'error': str(e)}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/contacts', methods=['POST']) @login_required def create_contact(): """Create new contact""" try: data = request.get_json() contact = get_lead_service().create_contact(data, flask_session.get('username')) return jsonify({'success': True, 'contact': contact}) except ValueError as e: return jsonify({'success': False, 'error': str(e)}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/contacts/', methods=['PUT']) @login_required def update_contact(contact_id): """Update contact""" try: data = request.get_json() contact = get_lead_service().update_contact( contact_id, data, flask_session.get('username') ) return jsonify({'success': True, 'contact': contact}) except ValueError as e: return jsonify({'success': False, 'error': str(e)}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/contacts//phones', methods=['POST']) @login_required def add_phone(contact_id): """Add phone to contact""" try: data = request.get_json() detail = get_lead_service().add_phone( contact_id, data['phone_number'], data.get('phone_type'), flask_session.get('username') ) return jsonify({'success': True, 'detail': detail}) except ValueError as e: return jsonify({'success': False, 'error': str(e)}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/contacts//emails', methods=['POST']) @login_required def add_email(contact_id): """Add email to contact""" try: data = request.get_json() detail = get_lead_service().add_email( contact_id, data['email'], data.get('email_type'), flask_session.get('username') ) return jsonify({'success': True, 'detail': detail}) except ValueError as e: return jsonify({'success': False, 'error': str(e)}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/details/', methods=['PUT']) @login_required def update_detail(detail_id): """Update contact detail (phone/email)""" try: data = request.get_json() detail = get_lead_service().update_contact_detail( detail_id, data['detail_value'], data.get('detail_label'), flask_session.get('username') ) return jsonify({'success': True, 'detail': detail}) except ValueError as e: return jsonify({'success': False, 'error': str(e)}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/details/', methods=['DELETE']) @login_required def delete_detail(detail_id): """Delete contact detail""" try: success = get_lead_service().delete_contact_detail( detail_id, flask_session.get('username') ) return jsonify({'success': success}) except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/contacts//notes', methods=['POST']) @login_required def add_note(contact_id): """Add note to contact""" try: data = request.get_json() note = get_lead_service().add_note( contact_id, data['note_text'], flask_session.get('username') ) return jsonify({'success': True, 'note': note}) except ValueError as e: return jsonify({'success': False, 'error': str(e)}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/notes/', methods=['PUT']) @login_required def update_note(note_id): """Update note""" try: data = request.get_json() note = get_lead_service().update_note( note_id, data['note_text'], flask_session.get('username') ) return jsonify({'success': True, 'note': note}) except ValueError as e: return jsonify({'success': False, 'error': str(e)}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @leads_bp.route('/api/notes/', methods=['DELETE']) @login_required def delete_note(note_id): """Delete note""" try: success = get_lead_service().delete_note( note_id, flask_session.get('username') ) return jsonify({'success': success}) except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 # Export Routes @leads_bp.route('/export') @login_required def export_leads(): """Export leads data as Excel/CSV""" from utils.export import create_excel_export, create_csv_export try: conn = get_db_connection() cur = conn.cursor() # Query institutions with contact counts cur.execute(""" SELECT i.id, i.name, i.type, i.website, i.address, i.created_at, i.created_by, COUNT(DISTINCT c.id) as contact_count, COUNT(DISTINCT cd.id) as contact_detail_count, COUNT(DISTINCT n.id) as note_count FROM lead_institutions i LEFT JOIN lead_contacts c ON i.id = c.institution_id LEFT JOIN lead_contact_details cd ON c.id = cd.contact_id LEFT JOIN lead_notes n ON i.id = n.institution_id GROUP BY i.id, i.name, i.type, i.website, i.address, i.created_at, i.created_by ORDER BY i.name """) # Prepare data for export data = [] columns = ['ID', 'Institution', 'Typ', 'Website', 'Adresse', 'Erstellt am', 'Erstellt von', 'Anzahl Kontakte', 'Anzahl Kontaktdetails', 'Anzahl Notizen'] for row in cur.fetchall(): data.append(list(row)) # Check format parameter format_type = request.args.get('format', 'excel').lower() if format_type == 'csv': return create_csv_export(data, columns, 'leads') else: return create_excel_export(data, columns, 'leads') except Exception as e: flash(f'Fehler beim Export: {str(e)}', 'error') return redirect(url_for('leads.institutions')) finally: cur.close() conn.close()