# 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 institutions with contact counts institutions = get_lead_service().list_institutions() # Get all contacts with institution names all_contacts = get_lead_service().list_all_contacts() # Calculate totals total_institutions = len(institutions) total_contacts = len(all_contacts) return render_template('leads/lead_management.html', total_institutions=total_institutions, total_contacts=total_contacts, institutions=institutions, all_contacts=all_contacts) 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, institutions=[], all_contacts=[]) @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('/contact/add', methods=['POST']) @login_required def add_contact(): """Add new contact from form""" try: data = { 'institution_id': request.form.get('institution_id'), 'first_name': request.form.get('first_name'), 'last_name': request.form.get('last_name'), 'position': request.form.get('position') } # Validate required fields if not data['institution_id'] or not data['first_name'] or not data['last_name']: flash('Institution, Vorname und Nachname sind erforderlich', 'error') return redirect(url_for('leads.lead_management')) # Create contact contact = get_lead_service().create_contact(data, flask_session.get('username', 'System')) # Add email if provided email = request.form.get('email') if email: get_lead_service().add_email(contact['id'], email, 'Primär', flask_session.get('username', 'System')) # Add phone if provided phone = request.form.get('phone') if phone: get_lead_service().add_phone(contact['id'], phone, 'Primär', flask_session.get('username', 'System')) flash(f'Kontakt "{data["first_name"]} {data["last_name"]}" wurde erfolgreich hinzugefügt', 'success') except Exception as e: flash(f'Fehler beim Hinzufügen des Kontakts: {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: # Get institution through repository service = get_lead_service() institution = service.repo.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()