📚 Improved configuration files & documentation 📚
This commit is contained in:
parent
47d0e291fb
commit
5aa7da2aa9
Binary file not shown.
@ -26,7 +26,7 @@ class Config:
|
|||||||
SESSION_COOKIE_SAMESITE = 'Lax'
|
SESSION_COOKIE_SAMESITE = 'Lax'
|
||||||
|
|
||||||
# Database configuration
|
# Database configuration
|
||||||
DATABASE_URL = os.environ.get('DATABASE_URL') or f'sqlite:///{os.path.join(PROJECT_ROOT, "data", "myp_platform.db")}'
|
DATABASE_URL = os.environ.get('DATABASE_URL') or f'sqlite:///{os.path.join(PROJECT_ROOT, "database", "myp.db")}'
|
||||||
SQLALCHEMY_DATABASE_URI = DATABASE_URL
|
SQLALCHEMY_DATABASE_URI = DATABASE_URL
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
SQLALCHEMY_ENGINE_OPTIONS = {
|
SQLALCHEMY_ENGINE_OPTIONS = {
|
||||||
|
Binary file not shown.
Binary file not shown.
118
backend/docs/DATENBANK_KONFIGURATION.md
Normal file
118
backend/docs/DATENBANK_KONFIGURATION.md
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# Datenbank-Konfiguration MYP Platform
|
||||||
|
|
||||||
|
## Übersicht
|
||||||
|
|
||||||
|
Die MYP Platform verwendet **ausschließlich** eine SQLite-Datenbank:
|
||||||
|
|
||||||
|
```
|
||||||
|
database/myp.db
|
||||||
|
```
|
||||||
|
|
||||||
|
## Konfiguration
|
||||||
|
|
||||||
|
### Haupt-Konfiguration
|
||||||
|
- **Datei**: `config/settings.py`
|
||||||
|
- **Variable**: `DATABASE_PATH = os.path.join(BASE_DIR, "database", "myp.db")`
|
||||||
|
- **Engine**: SQLite mit WAL-Modus (Write-Ahead Logging)
|
||||||
|
|
||||||
|
### Sichergestellte Konsistenz
|
||||||
|
|
||||||
|
Alle folgenden Dateien wurden korrigiert, um ausschließlich `database/myp.db` zu verwenden:
|
||||||
|
|
||||||
|
#### ✅ Konfigurationsdateien
|
||||||
|
- `config/settings.py` - Haupt-Konfiguration
|
||||||
|
- `config/app_config.py` - Alternative Flask-Konfiguration (korrigiert)
|
||||||
|
|
||||||
|
#### ✅ Model- und Datenbankdateien
|
||||||
|
- `models.py` - Hauptmodelle und Engine-Konfiguration
|
||||||
|
- `database/db_manager.py` - Datenbank-Manager
|
||||||
|
|
||||||
|
#### ✅ Utilities und Tools
|
||||||
|
- `utils/migrate_db.py` - Datenbank-Migration (Legacy-Fallbacks entfernt)
|
||||||
|
- `utils/quick_fix.py` - Schnelle Reparatur-Tools (korrigiert)
|
||||||
|
- `utils/debug_drucker_erkennung.py` - Debug-Tools (korrigiert)
|
||||||
|
- `utils/database_utils.py` - Backup und Wartung
|
||||||
|
- `utils/database_cleanup.py` - Cleanup-Manager
|
||||||
|
- `utils/database_schema_migration.py` - Schema-Migration
|
||||||
|
|
||||||
|
### Entfernte/Korrigierte Inkonsistenzen
|
||||||
|
|
||||||
|
#### 🗑️ Gelöschte Dateien
|
||||||
|
- `database/production.db` (leer, 0KB) - entfernt
|
||||||
|
|
||||||
|
#### 🔧 Korrigierte Fallbacks
|
||||||
|
- **Entfernt**: Referenzen zu `app.db`, `database.db`, `data/myp_platform.db`
|
||||||
|
- **Korrigiert**: Tabellennamen von `printer` zu `printers`
|
||||||
|
- **Vereinheitlicht**: Alle Import-Pfade verwenden `config.settings.DATABASE_PATH`
|
||||||
|
|
||||||
|
## Verwendung
|
||||||
|
|
||||||
|
### Datenbank initialisieren
|
||||||
|
```python
|
||||||
|
from models import init_db
|
||||||
|
init_db()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Session verwenden
|
||||||
|
```python
|
||||||
|
from models import get_cached_session
|
||||||
|
|
||||||
|
with get_cached_session() as session:
|
||||||
|
# Datenbankoperationen
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup erstellen
|
||||||
|
```python
|
||||||
|
from utils.database_utils import DatabaseBackupManager
|
||||||
|
|
||||||
|
backup_manager = DatabaseBackupManager()
|
||||||
|
backup_manager.create_backup()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Optimierungen
|
||||||
|
|
||||||
|
Die Datenbank ist für Produktionsumgebung optimiert:
|
||||||
|
|
||||||
|
- **WAL-Modus**: Write-Ahead Logging für bessere Performance
|
||||||
|
- **Connection Pooling**: Optimierte Verbindungsverwaltung
|
||||||
|
- **Caching**: Intelligent caching system für häufige Abfragen
|
||||||
|
- **Auto-Vacuum**: Automatische Speicherbereinigung
|
||||||
|
- **Indizierung**: Optimierte Indizes für bessere Performance
|
||||||
|
|
||||||
|
## Wartung
|
||||||
|
|
||||||
|
### Automatische Wartung
|
||||||
|
- WAL-Checkpoints alle 1000 Seiten
|
||||||
|
- Incremental Vacuum alle 60 Minuten
|
||||||
|
- Statistik-Updates alle 30 Minuten
|
||||||
|
|
||||||
|
### Manuelle Wartung
|
||||||
|
```bash
|
||||||
|
# Migration ausführen
|
||||||
|
python utils/migrate_db.py
|
||||||
|
|
||||||
|
# Schnelle Reparatur
|
||||||
|
python utils/quick_fix.py
|
||||||
|
|
||||||
|
# Diagnose
|
||||||
|
python utils/debug_drucker_erkennung.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Wichtige Hinweise
|
||||||
|
|
||||||
|
⚠️ **NUR `database/myp.db` verwenden!**
|
||||||
|
|
||||||
|
- Keine anderen Datenbankdateien verwenden
|
||||||
|
- Alle Tools und Scripts sind auf diese Datei konfiguriert
|
||||||
|
- Bei Problemen: Backup aus `database/backups/` verwenden
|
||||||
|
|
||||||
|
🔒 **Backup-Strategie**
|
||||||
|
- Automatische Backups in `database/backups/`
|
||||||
|
- Vor größeren Operationen manuelles Backup erstellen
|
||||||
|
- WAL- und SHM-Dateien gehören zur Datenbank (nicht löschen!)
|
||||||
|
|
||||||
|
📊 **Monitoring**
|
||||||
|
- Log-Dateien in `logs/app/`
|
||||||
|
- Performance-Monitoring via `utils/database_utils.py`
|
||||||
|
- Health-Checks über API-Endpunkte verfügbar
|
119
backend/docs/WINDOWS_INSTALLATION.md
Normal file
119
backend/docs/WINDOWS_INSTALLATION.md
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# MYP Platform - Windows Installation
|
||||||
|
|
||||||
|
## Überblick
|
||||||
|
Das MYP (Multi-User-Print) System ist ein Flask-basiertes Backend für Druckerverwaltung, das vollständig auf Windows kompatibel ist.
|
||||||
|
|
||||||
|
## Systemanforderungen
|
||||||
|
- Windows 10/11
|
||||||
|
- Python 3.8+
|
||||||
|
- Git (optional)
|
||||||
|
- Internetverbindung für Paketinstallation
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### 1. Python-Abhängigkeiten installieren
|
||||||
|
```powershell
|
||||||
|
# Im Projektverzeichnis
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Datenbank initialisieren
|
||||||
|
```powershell
|
||||||
|
python -c "from models import init_database, create_initial_admin; init_database(); create_initial_admin()"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Anwendung starten
|
||||||
|
```powershell
|
||||||
|
python app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Automatischer Start (Windows Service)
|
||||||
|
|
||||||
|
### Service-Wrapper erstellen
|
||||||
|
Das System kann als Windows-Service installiert werden.
|
||||||
|
|
||||||
|
### PowerShell-Skript für automatischen Start
|
||||||
|
```powershell
|
||||||
|
# start-myp.ps1
|
||||||
|
$env:FLASK_ENV = "production"
|
||||||
|
$env:FLASK_APP = "app.py"
|
||||||
|
python app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verfügbare Endpunkte
|
||||||
|
- **Frontend**: http://localhost:5000
|
||||||
|
- **API**: http://localhost:5000/api/
|
||||||
|
- **Admin**: http://localhost:5000/admin
|
||||||
|
|
||||||
|
## Standard-Login
|
||||||
|
- **Benutzername**: admin@admin.de
|
||||||
|
- **Passwort**: admin
|
||||||
|
|
||||||
|
## Konfiguration
|
||||||
|
|
||||||
|
### Ports anpassen
|
||||||
|
In `app.py` am Ende der Datei:
|
||||||
|
```python
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host="0.0.0.0", port=5000, debug=False)
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSL/HTTPS aktivieren
|
||||||
|
```python
|
||||||
|
# SSL-Kontext für HTTPS
|
||||||
|
ssl_context = ('cert.pem', 'key.pem')
|
||||||
|
app.run(host="0.0.0.0", port=443, ssl_context=ssl_context)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fehlerbehebung
|
||||||
|
|
||||||
|
### Port bereits in Verwendung
|
||||||
|
```powershell
|
||||||
|
# Prozess finden und beenden
|
||||||
|
netstat -ano | findstr :5000
|
||||||
|
taskkill /PID [PID] /F
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python-Module fehlen
|
||||||
|
```powershell
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt --force-reinstall
|
||||||
|
```
|
||||||
|
|
||||||
|
### Datenbankfehler
|
||||||
|
```powershell
|
||||||
|
# Datenbank zurücksetzen
|
||||||
|
del database\myp.db
|
||||||
|
python -c "from models import init_database, create_initial_admin; init_database(); create_initial_admin()"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Entwicklungsmodus
|
||||||
|
```powershell
|
||||||
|
$env:FLASK_ENV = "development"
|
||||||
|
$env:FLASK_DEBUG = "1"
|
||||||
|
python app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logs
|
||||||
|
- **Anwendung**: `logs/app/`
|
||||||
|
- **Authentifizierung**: `logs/auth/`
|
||||||
|
- **Fehler**: `logs/errors/`
|
||||||
|
- **Jobs**: `logs/jobs/`
|
||||||
|
|
||||||
|
## Windows-spezifische Features
|
||||||
|
- Automatische Windows-Kompatibilitätsfixes
|
||||||
|
- WMI-Integration für Systemüberwachung
|
||||||
|
- Windows-Event-Log-Integration
|
||||||
|
- Windows-Service-Support
|
||||||
|
|
||||||
|
## Sicherheit
|
||||||
|
- CSRF-Schutz aktiviert
|
||||||
|
- Rate-Limiting implementiert
|
||||||
|
- Sichere Session-Verwaltung
|
||||||
|
- SQL-Injection-Schutz
|
||||||
|
|
||||||
|
## Performance-Optimierung
|
||||||
|
- SQLite-Optimierungen für Windows
|
||||||
|
- Caching-Strategien
|
||||||
|
- Asynchrone Task-Verarbeitung
|
||||||
|
- Memory-Management
|
@ -84026,3 +84026,4 @@ WHERE printers.active = 1 AND printers.status = ?) AS anon_1]
|
|||||||
2025-06-01 01:59:51 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int'
|
2025-06-01 01:59:51 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int'
|
||||||
2025-06-01 02:00:01 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range
|
2025-06-01 02:00:01 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range
|
||||||
2025-06-01 02:01:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range
|
2025-06-01 02:01:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range
|
||||||
|
2025-06-01 02:03:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int'
|
||||||
|
@ -1840,3 +1840,4 @@ WHERE printers.active = 1 AND printers.status = ?) AS anon_1]
|
|||||||
2025-06-01 01:59:51 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int'
|
2025-06-01 01:59:51 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int'
|
||||||
2025-06-01 02:00:01 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range
|
2025-06-01 02:00:01 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range
|
||||||
2025-06-01 02:01:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range
|
2025-06-01 02:01:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für online_printers: tuple index out of range
|
||||||
|
2025-06-01 02:03:31 - myp.dashboard - ERROR - Fehler beim Laden der Widget-Daten für system_alerts: '>' not supported between instances of 'NoneType' and 'int'
|
||||||
|
@ -47,7 +47,7 @@ __all__ = ['User', 'Printer', 'Job', 'Stats', 'SystemLog', 'Base', 'GuestRequest
|
|||||||
|
|
||||||
# ===== DATENBANK-KONFIGURATION MIT WAL UND OPTIMIERUNGEN =====
|
# ===== DATENBANK-KONFIGURATION MIT WAL UND OPTIMIERUNGEN =====
|
||||||
|
|
||||||
def configure_sqlite_for_production(dbapi_connection, connection_record):
|
def configure_sqlite_for_production(dbapi_connection, _connection_record):
|
||||||
"""
|
"""
|
||||||
Konfiguriert SQLite für Produktionsumgebung mit WAL-Modus und Optimierungen.
|
Konfiguriert SQLite für Produktionsumgebung mit WAL-Modus und Optimierungen.
|
||||||
"""
|
"""
|
||||||
|
@ -30,40 +30,47 @@ def test_database_connection():
|
|||||||
log_message("Teste Datenbankverbindung...")
|
log_message("Teste Datenbankverbindung...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Versuche SQLite-Datenbank zu öffnen
|
# Pfad zur App hinzufügen für korrekten Import
|
||||||
db_files = ['database.db', 'app.db', 'myp.db']
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
for db_file in db_files:
|
try:
|
||||||
if os.path.exists(db_file):
|
from config.settings import DATABASE_PATH
|
||||||
log_message(f"Gefundene Datenbankdatei: {db_file}")
|
db_file = DATABASE_PATH
|
||||||
|
except ImportError:
|
||||||
conn = sqlite3.connect(db_file)
|
# Fallback für lokale Ausführung
|
||||||
cursor = conn.cursor()
|
db_file = os.path.join('database', 'myp.db')
|
||||||
|
|
||||||
# Prüfe ob Printer-Tabelle existiert
|
if os.path.exists(db_file):
|
||||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='printer';")
|
log_message(f"Gefundene Datenbankdatei: {db_file}")
|
||||||
if cursor.fetchone():
|
|
||||||
log_message("✅ Printer-Tabelle gefunden")
|
conn = sqlite3.connect(db_file)
|
||||||
|
cursor = conn.cursor()
|
||||||
# Zähle Drucker
|
|
||||||
cursor.execute("SELECT COUNT(*) FROM printer;")
|
# Prüfe ob Printers-Tabelle existiert
|
||||||
count = cursor.fetchone()[0]
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='printers';")
|
||||||
log_message(f"📊 Anzahl Drucker in Datenbank: {count}")
|
if cursor.fetchone():
|
||||||
|
log_message("✅ Printers-Tabelle gefunden")
|
||||||
# Zeige Drucker-Details
|
|
||||||
cursor.execute("SELECT id, name, plug_ip, status FROM printer;")
|
# Zähle Drucker
|
||||||
printers = cursor.fetchall()
|
cursor.execute("SELECT COUNT(*) FROM printers;")
|
||||||
|
count = cursor.fetchone()[0]
|
||||||
for printer in printers:
|
log_message(f"📊 Anzahl Drucker in Datenbank: {count}")
|
||||||
log_message(f" Drucker {printer[0]}: {printer[1]} ({printer[2]}) - Status: {printer[3]}")
|
|
||||||
|
# Zeige Drucker-Details
|
||||||
conn.close()
|
cursor.execute("SELECT id, name, plug_ip, status FROM printers;")
|
||||||
return True
|
printers = cursor.fetchall()
|
||||||
else:
|
|
||||||
log_message("❌ Printer-Tabelle nicht gefunden")
|
for printer in printers:
|
||||||
conn.close()
|
log_message(f" Drucker {printer[0]}: {printer[1]} ({printer[2]}) - Status: {printer[3]}")
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
log_message("❌ Printers-Tabelle nicht gefunden")
|
||||||
|
conn.close()
|
||||||
|
else:
|
||||||
|
log_message(f"❌ Datenbankdatei nicht gefunden: {db_file}")
|
||||||
|
|
||||||
log_message("❌ Keine gültige Datenbank gefunden")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -125,17 +132,21 @@ def test_network_connectivity():
|
|||||||
|
|
||||||
# Lade Drucker aus Datenbank
|
# Lade Drucker aus Datenbank
|
||||||
try:
|
try:
|
||||||
db_files = ['database.db', 'app.db', 'myp.db']
|
# Verwende konfigurierten Datenbankpfad
|
||||||
|
try:
|
||||||
|
from config.settings import DATABASE_PATH
|
||||||
|
db_file = DATABASE_PATH
|
||||||
|
except ImportError:
|
||||||
|
db_file = os.path.join('database', 'myp.db')
|
||||||
|
|
||||||
printers = []
|
printers = []
|
||||||
|
|
||||||
for db_file in db_files:
|
if os.path.exists(db_file):
|
||||||
if os.path.exists(db_file):
|
conn = sqlite3.connect(db_file)
|
||||||
conn = sqlite3.connect(db_file)
|
cursor = conn.cursor()
|
||||||
cursor = conn.cursor()
|
cursor.execute("SELECT name, plug_ip FROM printers WHERE plug_ip IS NOT NULL;")
|
||||||
cursor.execute("SELECT name, plug_ip FROM printer WHERE plug_ip IS NOT NULL;")
|
printers = cursor.fetchall()
|
||||||
printers = cursor.fetchall()
|
conn.close()
|
||||||
conn.close()
|
|
||||||
break
|
|
||||||
|
|
||||||
if not printers:
|
if not printers:
|
||||||
log_message("❌ Keine Drucker mit IP-Adressen gefunden")
|
log_message("❌ Keine Drucker mit IP-Adressen gefunden")
|
||||||
@ -194,17 +205,21 @@ def test_tapo_connections():
|
|||||||
|
|
||||||
# Lade Drucker aus Datenbank
|
# Lade Drucker aus Datenbank
|
||||||
try:
|
try:
|
||||||
db_files = ['database.db', 'app.db', 'myp.db']
|
# Verwende konfigurierten Datenbankpfad
|
||||||
|
try:
|
||||||
|
from config.settings import DATABASE_PATH
|
||||||
|
db_file = DATABASE_PATH
|
||||||
|
except ImportError:
|
||||||
|
db_file = os.path.join('database', 'myp.db')
|
||||||
|
|
||||||
printers = []
|
printers = []
|
||||||
|
|
||||||
for db_file in db_files:
|
if os.path.exists(db_file):
|
||||||
if os.path.exists(db_file):
|
conn = sqlite3.connect(db_file)
|
||||||
conn = sqlite3.connect(db_file)
|
cursor = conn.cursor()
|
||||||
cursor = conn.cursor()
|
cursor.execute("SELECT id, name, plug_ip, plug_username, plug_password FROM printers WHERE plug_ip IS NOT NULL;")
|
||||||
cursor.execute("SELECT id, name, plug_ip, plug_username, plug_password FROM printer WHERE plug_ip IS NOT NULL;")
|
printers = cursor.fetchall()
|
||||||
printers = cursor.fetchall()
|
conn.close()
|
||||||
conn.close()
|
|
||||||
break
|
|
||||||
|
|
||||||
if not printers:
|
if not printers:
|
||||||
log_message("❌ Keine Drucker mit Tapo-Konfiguration gefunden")
|
log_message("❌ Keine Drucker mit Tapo-Konfiguration gefunden")
|
||||||
|
@ -34,12 +34,7 @@ def get_database_path():
|
|||||||
os.path.join('database', 'myp.db'),
|
os.path.join('database', 'myp.db'),
|
||||||
'myp.db',
|
'myp.db',
|
||||||
'../database/myp.db',
|
'../database/myp.db',
|
||||||
'./database/myp.db',
|
'./database/myp.db'
|
||||||
# Legacy-Pfade für Rückwärtskompatibilität
|
|
||||||
os.path.join('database', 'app.db'),
|
|
||||||
'app.db',
|
|
||||||
'../database/app.db',
|
|
||||||
'./database/app.db'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for path in alternative_paths:
|
for path in alternative_paths:
|
||||||
|
@ -5,10 +5,17 @@ Schnelle Datenbank-Reparatur für kritische Fehler
|
|||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
# Datenbankpfad
|
# Pfad zur App hinzufügen
|
||||||
DATABASE_PATH = "database/myp.db"
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
try:
|
||||||
|
from config.settings import DATABASE_PATH
|
||||||
|
except ImportError:
|
||||||
|
# Fallback falls Import fehlschlägt
|
||||||
|
DATABASE_PATH = "database/myp.db"
|
||||||
|
|
||||||
def quick_fix_database():
|
def quick_fix_database():
|
||||||
"""Behebt die kritischsten Datenbankprobleme sofort"""
|
"""Behebt die kritischsten Datenbankprobleme sofort"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user