🎉 Improved cursor rules and expanded logging system across backend files. 🖥️📝
This commit is contained in:
672
.cursorrules
672
.cursorrules
@@ -1 +1,671 @@
|
||||
|
||||
# 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
|
Reference in New Issue
Block a user