677 lines
19 KiB
Plaintext
677 lines
19 KiB
Plaintext
---
|
|
description: "Formale Projektrichtlinien für das Mercedes-Benz 3D-Druck-Management-System mit Fokus auf Codequalität, deutscher Dokumentation und hardwareoptimierter Implementierung"
|
|
globs: ["*.py", "*.html", "*.js", "*.sql", "*.md"]
|
|
alwaysApply: true
|
|
---
|
|
|
|
# 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 |