# MYP Druckerverwaltungssystem - Cursor Rules
# Mercedes-Benz 3D-Druck-Management-Platform

## 🎯 PROJEKT-KONTEXT

Das MYP-System ist eine cyber-physische Lösung zur Verwaltung von 3D-Druckern mit Smart-Plug-Technologie für Mercedes-Benz. 

**Technischer Stack:**
- Backend: Flask + SQLAlchemy + SQLite
- Frontend: Jinja2-Templates + CSS/JS
- Hardware: Raspberry Pi + TP-Link Tapo P110
- Deployment: Air-Gapped Production Environment

## 🔑 KERN-PRINZIPIEN

### SPRACHE & DOKUMENTATION
- **Ausschließlich formales Deutsch** für alle Kommentare, Docstrings, UI-Texte und Dokumentation
- **Englisch nur für**: Code-Variablen, Funktionsnamen, Git-Commits
- Umfassende Docstrings nach deutschem Standard
- Inline-Kommentare für komplexe Logik

### QUALITÄTS-STANDARD
- **Produktionsreife** bei jedem Commit - keine experimentellen Features ohne vollständige Tests
- **Zero-Downtime-Code** - jede Änderung muss sofort funktionsfähig sein
- **Defense Programming** - umfassende Error-Handling und Validation
- **Performance-optimiert** für Raspberry Pi Hardware-Umgebung

### CASCADE-ANALYSE PROTOKOLL
Vor jeder Änderung ZWINGEND analysieren:
```python
# IMPACT-ANALYSE-TEMPLATE:
# 1. Betroffene Module: [Liste]
# 2. API-Endpunkte: [Liste] 
# 3. Datenbank-Schema: [Änderungen]
# 4. Frontend-Komponenten: [Liste]
# 5. Hardware-Integration: [Tapo/Drucker]
# 6. Session/Auth: [Auswirkungen]
# 7. Background-Jobs: [Timer/Scheduler]
```

## 📁 PROJEKTSTRUKTUR-REGELN

### CORE-DATEIEN (NIEMALS OHNE CASCADE-ANALYSE ÄNDERN)
- `backend/app.py` - Flask-Haupteinstiegspunkt
- `backend/models.py` - SQLAlchemy-Datenmodelle  
- `backend/utils/settings.py` - Zentrale Konfiguration
- `backend/blueprints/` - REST-API-Endpunkte

### DATEI-ORGANISIERUNG
- **Markdown-Dateien (.md)**: Automatisch in `docs/` speichern (außer README.md)
- **Upload-Struktur**: Hierarchisch nach Jahr/Monat
- **Logs**: Strukturiert nach Modulen in `backend/logs/`
- **Backups**: Automatisch in `database/backups/`

### KEINE WINDOWS-SPEZIFISCHEN DATEIEN
- Keine .bat, .ps1, .cmd Dateien
- Keine Windows-Registry-Zugriffe
- Linux/Unix-Shell-Scripts bevorzugen
- Cross-platform Python-Lösungen

## 🏗️ BACKEND-ENTWICKLUNG (FLASK)

### BLUEPRINT-STRUKTUR
```python
# Standard Blueprint-Template
from flask import Blueprint, request, jsonify, session
from backend.models import db, User, Printer, Job
from backend.utils.permissions import require_role
from backend.utils.logging_config import get_logger

# Deutsche Kommentare für Business-Logic
blueprint_name = Blueprint('name', __name__)
logger = get_logger(__name__)

@blueprint_name.route('/endpoint', methods=['POST'])
@require_role('admin')  # Berechtigungsprüfung
def function_name():
    """
    Funktion-Beschreibung auf Deutsch.
    
    Returns:
        dict: Antwort-Struktur mit Status und Daten
    """
    try:
        # Geschäftslogik mit deutschen Kommentaren
        pass
    except Exception as e:
        logger.error(f"Fehler in {function_name.__name__}: {str(e)}")
        return jsonify({'error': 'Detaillierte deutsche Fehlermeldung'}), 500
```

### DATENBANK-PATTERNS
```python
# SQLAlchemy-Modell-Standard
class ModelName(db.Model):
    """Deutsche Modell-Beschreibung."""
    
    __tablename__ = 'table_name'
    
    # Felder mit deutschen Kommentaren
    id = db.Column(db.Integer, primary_key=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    def to_dict(self):
        """Konvertierung zu Dictionary für JSON-Serialisierung."""
        return {
            'id': self.id,
            'created_at': self.created_at.isoformat() if self.created_at else None
        }
    
    @classmethod
    def create_with_validation(cls, **kwargs):
        """Factory-Methode mit Validierung."""
        # Validierungslogik
        pass
```

### HARDWARE-INTEGRATION (TAPO)
```python
# Tapo-Controller-Pattern
from backend.utils.tapo_controller import TapoController

async def control_printer_power(printer_id: int, action: str):
    """
    Steuerung der Drucker-Stromversorgung über Smart-Plug.
    
    Args:
        printer_id: Eindeutige Drucker-ID
        action: 'on', 'off', 'status'
        
    Returns:
        dict: Status und Ergebnis der Operation
    """
    try:
        controller = TapoController()
        result = await controller.execute_action(printer_id, action)
        
        # Logging für Hardware-Operationen
        logger.info(f"Drucker {printer_id}: {action} - Status: {result}")
        
        return {'success': True, 'data': result}
    except Exception as e:
        logger.error(f"Tapo-Steuerung fehlgeschlagen: {str(e)}")
        return {'success': False, 'error': str(e)}
```

## 🎨 FRONTEND-ENTWICKLUNG (JINJA2)

### TEMPLATE-STRUKTUR
```html
<!-- Standard Template-Header -->
{% extends "base.html" %}
{% set page_title = "Deutsche Seitentitel" %}
{% set page_description = "Deutsche Beschreibung" %}

{% block content %}
<div class="container-fluid">
    <!-- Deutsche UI-Texte -->
    <h1>{{ page_title }}</h1>
    
    <!-- Form-Validation mit deutschen Meldungen -->
    {% with messages = get_flashed_messages(with_categories=true) %}
        {% if messages %}
            {% for category, message in messages %}
                <div class="alert alert-{{ 'danger' if category == 'error' else category }}">
                    {{ message }}
                </div>
            {% endfor %}
        {% endif %}
    {% endwith %}
</div>
{% endblock %}

{% block scripts %}
<script>
// Deutsche JavaScript-Kommentare für UI-Logik
document.addEventListener('DOMContentLoaded', function() {
    // Initialisierung mit Error-Handling
});
</script>
{% endblock %}
```

### CSS/STYLING-REGELN
- **Mercedes-Designsprache** befolgen
- **Responsive Design** für Touch-Interfaces (Kiosk-Modus)
- **Accessibility** (WCAG 2.1 AA)
- **Performance** für Raspberry Pi optimiert

## 🔧 UTILITY-ENTWICKLUNG

### LOGGING-STANDARD
```python
from backend.utils.logging_config import get_logger

logger = get_logger(__name__)

def business_function():
    """Deutsche Funktionsbeschreibung."""
    logger.info("Vorgang gestartet: {function_name}")
    
    try:
        # Geschäftslogik
        logger.debug("Zwischenschritt erfolgreich")
        
    except ValidationError as e:
        logger.warning(f"Validierungsfehler: {str(e)}")
        raise
        
    except Exception as e:
        logger.error(f"Unerwarteter Fehler in {function_name}: {str(e)}")
        # Error-Recovery-Logik
        raise
        
    finally:
        logger.info("Vorgang abgeschlossen: {function_name}")
```

### PERMISSION-SYSTEM
```python
from functools import wraps
from flask import session, abort

def require_role(required_role: str):
    """Decorator für rollenbasierte Zugriffskontrolle."""
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if 'user_id' not in session:
                abort(401)  # Nicht authentifiziert
                
            user = User.query.get(session['user_id'])
            if not user or user.role != required_role:
                logger.warning(f"Unauthorisierter Zugriff: {session.get('username', 'Unknown')} -> {f.__name__}")
                abort(403)  # Nicht autorisiert
                
            return f(*args, **kwargs)
        return decorated_function
    return decorator
```

## 📊 DATENBANK-STANDARDS

### MIGRATION-PATTERN
```python
# Sichere Schema-Änderungen
def upgrade_database():
    """Database-Schema-Upgrade mit Backup."""
    try:
        # 1. Backup erstellen
        backup_manager.create_backup()
        
        # 2. Schema-Änderungen
        db.engine.execute("ALTER TABLE...")
        
        # 3. Daten-Migration
        migrate_existing_data()
        
        # 4. Validierung
        validate_schema_integrity()
        
        logger.info("Database-Upgrade erfolgreich")
        
    except Exception as e:
        logger.error(f"Database-Upgrade fehlgeschlagen: {str(e)}")
        # Rollback-Mechanismus
        backup_manager.restore_latest()
        raise
```

### CONNECTION-MANAGEMENT
```python
# SQLite-optimiert für Air-Gapped-Umgebung
def get_db_connection():
    """Thread-safe Database-Connection mit Connection-Pooling."""
    return db.engine.connect()

@contextmanager
def transaction_scope():
    """Transaction-Manager mit automatischem Rollback."""
    connection = get_db_connection()
    trans = connection.begin()
    try:
        yield connection
        trans.commit()
    except Exception:
        trans.rollback()
        raise
    finally:
        connection.close()
```

## 🚀 DEPLOYMENT & PRODUCTION

### SYSTEMD-SERVICE-PATTERN
```ini
# Produktions-Service-Template
[Unit]
Description=MYP Druckerverwaltungssystem
After=network.target

[Service]
Type=notify
User=myp
Group=myp
WorkingDirectory=/opt/myp
Environment=FLASK_ENV=production
ExecStart=/opt/myp/venv/bin/python app.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

### KIOSK-MODUS-SETUP
```bash
#!/bin/bash
# Raspberry Pi Kiosk-Setup
# Deutsche Kommentare für Setup-Scripts

# Display-Konfiguration für Touch-Interface
export DISPLAY=:0
xset s off
xset -dpms
xset s noblank

# Browser-Start mit MYP-Interface
chromium-browser \
    --kiosk \
    --disable-infobars \
    --disable-session-crashed-bubble \
    https://localhost/kiosk
```

## 🧪 TESTING-STANDARDS

### UNIT-TEST-TEMPLATE
```python
import pytest
from backend.app import create_app
from backend.models import db, User, Printer

class TestDruckerVerwaltung:
    """Test-Suite für Drucker-Management-Funktionen."""
    
    def setup_method(self):
        """Test-Environment-Setup."""
        self.app = create_app('testing')
        self.client = self.app.test_client()
        
        with self.app.app_context():
            db.create_all()
            self.create_test_data()
    
    def test_drucker_erstellen(self):
        """Test: Neuen Drucker erfolgreich erstellen."""
        # Given: Test-Daten
        drucker_daten = {
            'name': 'Test-Drucker-001',
            'standort': 'Berlin-Marienfelde',
            'tapo_ip': '192.168.1.100'
        }
        
        # When: API-Aufruf
        response = self.client.post('/api/printers', json=drucker_daten)
        
        # Then: Erfolgreiche Erstellung
        assert response.status_code == 201
        assert 'id' in response.json
        
    def teardown_method(self):
        """Test-Environment-Cleanup."""
        with self.app.app_context():
            db.drop_all()
```

## 🔒 SECURITY-REQUIREMENTS

### AUTHENTICATION-FLOW
```python
# Sichere Session-Verwaltung
@auth_bp.route('/login', methods=['POST'])
def login():
    """Benutzer-Authentifizierung mit Rate-Limiting."""
    
    # Rate-Limiting für Brute-Force-Schutz
    if not rate_limiter.check_limit(request.remote_addr):
        logger.warning(f"Rate-Limit erreicht: {request.remote_addr}")
        return jsonify({'error': 'Zu viele Anmeldeversuche'}), 429
    
    # Credential-Validierung
    username = request.json.get('username')
    password = request.json.get('password')
    
    user = User.authenticate(username, password)
    if not user:
        logger.warning(f"Fehlgeschlagene Anmeldung: {username}")
        return jsonify({'error': 'Ungültige Anmeldedaten'}), 401
    
    # Session-Erstellung mit CSRF-Token
    session['user_id'] = user.id
    session['csrf_token'] = generate_csrf_token()
    
    logger.info(f"Erfolgreiche Anmeldung: {username}")
    return jsonify({'success': True, 'user': user.to_dict()})
```

### INPUT-VALIDATION
```python
from marshmallow import Schema, fields, validate

class DruckerCreateSchema(Schema):
    """Validierungsschema für Drucker-Erstellung."""
    
    name = fields.Str(required=True, validate=validate.Length(min=3, max=50))
    standort = fields.Str(required=True, validate=validate.Length(min=5, max=100))
    tapo_ip = fields.IP(required=True)
    beschreibung = fields.Str(validate=validate.Length(max=500))

def validate_drucker_data(data):
    """Zentrale Validierung für Drucker-Daten."""
    schema = DruckerCreateSchema()
    errors = schema.validate(data)
    
    if errors:
        logger.warning(f"Validierungsfehler: {errors}")
        raise ValidationError(errors)
    
    return schema.load(data)
```

## ⚡ PERFORMANCE-OPTIMIERUNG

### DATABASE-QUERIES
```python
# Optimierte Queries für Raspberry Pi
def get_active_jobs_optimized():
    """Performance-optimierte Abfrage aktiver Jobs."""
    return db.session.query(Job)\
        .options(joinedload(Job.printer))\
        .options(joinedload(Job.user))\
        .filter(Job.status.in_(['running', 'scheduled']))\
        .order_by(Job.start_time.asc())\
        .limit(50)\
        .all()

# Caching für häufige Abfragen
from functools import lru_cache

@lru_cache(maxsize=128)
def get_drucker_statistics(drucker_id: int):
    """Gecachte Drucker-Statistiken."""
    return db.session.query(Job)\
        .filter(Job.printer_id == drucker_id)\
        .filter(Job.status == 'completed')\
        .count()
```

### FRONTEND-PERFORMANCE
```javascript
// Optimiertes JavaScript für Touch-Interface
class MYPDashboard {
    constructor() {
        this.updateInterval = 30000; // 30 Sekunden
        this.maxRetries = 3;
        this.retryCount = 0;
        
        this.initializeEventListeners();
        this.startAutoUpdate();
    }
    
    async updateDashboard() {
        try {
            const response = await fetch('/api/dashboard-data');
            const data = await response.json();
            
            this.renderDashboardData(data);
            this.retryCount = 0; // Reset bei Erfolg
            
        } catch (error) {
            console.error('Dashboard-Update fehlgeschlagen:', error);
            this.handleUpdateError();
        }
    }
    
    handleUpdateError() {
        this.retryCount++;
        if (this.retryCount < this.maxRetries) {
            // Exponential Backoff
            setTimeout(() => this.updateDashboard(), 
                      Math.pow(2, this.retryCount) * 1000);
        } else {
            this.showOfflineMode();
        }
    }
}
```

## 📝 DOKUMENTATIONS-STANDARD

### FUNCTION-DOCSTRINGS
```python
def schedule_print_job(drucker_id: int, start_time: datetime, 
                      duration_minutes: int, user_id: int) -> Dict[str, Any]:
    """
    Planen eines Druckauftrags mit automatischer Smart-Plug-Steuerung.
    
    Diese Funktion erstellt einen neuen Druckauftrag und konfiguriert
    die automatische Ein-/Ausschaltung des zugeordneten Druckers über
    das Tapo-Smart-Plug-System.
    
    Args:
        drucker_id: Eindeutige ID des Zieldruckers
        start_time: Geplanter Start des Druckauftrags (UTC)
        duration_minutes: Geschätzte Druckdauer in Minuten
        user_id: ID des anfragenden Benutzers
        
    Returns:
        dict: Enthält Job-ID, Status und Scheduler-Informationen
            {
                'job_id': int,
                'status': str,
                'scheduled_power_on': datetime,
                'scheduled_power_off': datetime,
                'tapo_status': str
            }
            
    Raises:
        ValidationError: Bei ungültigen Eingabedaten
        ConflictError: Bei Zeitkonflikten mit anderen Jobs
        HardwareError: Bei Tapo-Kommunikationsfehlern
        
    Example:
        >>> result = schedule_print_job(
        ...     drucker_id=1,
        ...     start_time=datetime(2025, 1, 15, 14, 0),
        ...     duration_minutes=120,
        ...     user_id=42
        ... )
        >>> print(result['job_id'])
        157
    """
```

## 🚨 ERROR-HANDLING-STANDARD

### EXCEPTION-HIERARCHY
```python
# Projekt-spezifische Exception-Klassen
class MYPBaseException(Exception):
    """Basis-Exception für MYP-System."""
    def __init__(self, message: str, error_code: str = None):
        self.message = message
        self.error_code = error_code
        super().__init__(self.message)

class HardwareError(MYPBaseException):
    """Fehler bei Hardware-Kommunikation (Tapo, Drucker)."""
    pass

class SchedulingConflictError(MYPBaseException):
    """Zeitkonflikt bei Job-Planung."""
    pass

class ValidationError(MYPBaseException):
    """Eingabe-Validierungsfehler."""
    pass

# Global Error Handler
@app.errorhandler(Exception)
def handle_global_exception(error):
    """Globaler Exception-Handler mit Logging."""
    logger.error(f"Unbehandelte Exception: {str(error)}", exc_info=True)
    
    if isinstance(error, MYPBaseException):
        return jsonify({
            'error': error.message,
            'error_code': error.error_code
        }), 400
    
    # Generischer Server-Fehler
    return jsonify({
        'error': 'Ein unerwarteter Fehler ist aufgetreten.',
        'error_code': 'INTERNAL_ERROR'
    }), 500
```

## 🔄 SELF-VERIFICATION-CHECKLIST

Nach jeder größeren Änderung ZWINGEND prüfen:

### ✅ FUNKTIONALE KORREKTHEIT
- [ ] Alle API-Endpunkte reagieren korrekt
- [ ] Datenbank-Operationen funktionieren
- [ ] Frontend lädt ohne JavaScript-Fehler
- [ ] Hardware-Integration (Tapo) erreichbar

### ✅ STRUKTURELLE INTEGRITÄT
- [ ] Imports funktionieren in allen Modulen
- [ ] Keine zirkulären Dependencies
- [ ] Database-Schema konsistent
- [ ] Session-Management intakt

### ✅ VOLLSTÄNDIGE DOKUMENTATION
- [ ] Deutsche Docstrings für neue Funktionen
- [ ] Inline-Kommentare für komplexe Logik
- [ ] API-Dokumentation aktualisiert
- [ ] Changelog-Einträge

### ✅ CASCADE-KONSISTENZ
- [ ] Alle abhängigen Module getestet
- [ ] Berechtigungen weiterhin gültig
- [ ] Logging funktioniert in allen Bereichen
- [ ] Error-Handling vollständig

## 🎯 ZUSÄTZLICHE REGELN

### GIT-WORKFLOW
- **Commit-Messages**: Englisch, aussagekräftig
- **Branch-Naming**: `feature/deutsche-beschreibung`, `bugfix/issue-nummer`
- **Pull-Requests**: Mit deutscher Beschreibung und Impact-Analyse

### CODE-REVIEW-KRITERIEN
- Deutsche Kommentare und Dokumentation
- Performance-Impact für Raspberry Pi
- Security-Implications
- Hardware-Integration-Auswirkungen
- Offline-Funktionalität erhalten

### EMERGENCY-PROCEDURES
```python
# Notfall-Shutdown-Prozedur
def emergency_shutdown():
    """Kontrolliertes System-Shutdown bei kritischen Fehlern."""
    logger.critical("NOTFALL-SHUTDOWN initiiert")
    
    # 1. Alle aktiven Jobs sicher beenden
    active_jobs = Job.query.filter(Job.status == 'running').all()
    for job in active_jobs:
        job.force_complete_with_reason("Notfall-Shutdown")
    
    # 2. Smart-Plugs ausschalten
    tapo_controller.emergency_power_off_all()
    
    # 3. Database-Backup erstellen
    backup_manager.create_emergency_backup()
    
    # 4. System-Status auf Wartung setzen
    system_status.set_maintenance_mode(True)
    
    logger.critical("NOTFALL-SHUTDOWN abgeschlossen")
```

---

## 🏆 QUALITÄTSZIELE

**Code-Qualität**: Produktionsreif, keine Experimente
**Performance**: Optimiert für Raspberry Pi 4
**Reliability**: 99.9% Uptime in Air-Gapped-Umgebung  
**Security**: Keine Schwachstellen, umfassende Validierung
**Maintainability**: Selbstdokumentierend, modular aufgebaut
**User Experience**: Intuitive deutsche Benutzerführung

---

**Version**: 1.0.0
**Gültig für**: MYP Druckerverwaltungssystem v2.0+
**Letzte Aktualisierung**: $(date +%Y-%m-%d)
**Entwicklungsstandard**: IHK-Projektarbeit Mercedes-Benz 