Neuer Kunde anlegen ohne Lizenz
Dieser Commit ist enthalten in:
@@ -2185,6 +2185,61 @@ def edit_customer(customer_id):
|
|||||||
|
|
||||||
return render_template("edit_customer.html", customer=customer, licenses=licenses, username=session.get('username'))
|
return render_template("edit_customer.html", customer=customer, licenses=licenses, username=session.get('username'))
|
||||||
|
|
||||||
|
@app.route("/customer/create", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
|
def create_customer():
|
||||||
|
"""Erstellt einen neuen Kunden ohne Lizenz"""
|
||||||
|
if request.method == "POST":
|
||||||
|
name = request.form.get('name')
|
||||||
|
email = request.form.get('email')
|
||||||
|
is_test = request.form.get('is_test') == 'on'
|
||||||
|
|
||||||
|
if not name or not email:
|
||||||
|
flash("Name und E-Mail sind Pflichtfelder!", "error")
|
||||||
|
return render_template("create_customer.html", username=session.get('username'))
|
||||||
|
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Prüfen ob E-Mail bereits existiert
|
||||||
|
cur.execute("SELECT id, name FROM customers WHERE email = %s", (email,))
|
||||||
|
existing = cur.fetchone()
|
||||||
|
if existing:
|
||||||
|
flash(f"Ein Kunde mit der E-Mail '{email}' existiert bereits: {existing[1]}", "error")
|
||||||
|
return render_template("create_customer.html", username=session.get('username'))
|
||||||
|
|
||||||
|
# Kunde erstellen
|
||||||
|
cur.execute("""
|
||||||
|
INSERT INTO customers (name, email, created_at, is_test)
|
||||||
|
VALUES (%s, %s, %s, %s) RETURNING id
|
||||||
|
""", (name, email, datetime.now(), is_test))
|
||||||
|
|
||||||
|
customer_id = cur.fetchone()[0]
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Audit-Log
|
||||||
|
log_audit('CREATE', 'customer', customer_id,
|
||||||
|
new_values={
|
||||||
|
'name': name,
|
||||||
|
'email': email,
|
||||||
|
'is_test': is_test
|
||||||
|
})
|
||||||
|
|
||||||
|
flash(f"Kunde '{name}' wurde erfolgreich angelegt!", "success")
|
||||||
|
return redirect(f"/customer/edit/{customer_id}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
conn.rollback()
|
||||||
|
flash(f"Fehler beim Anlegen des Kunden: {str(e)}", "error")
|
||||||
|
return render_template("create_customer.html", username=session.get('username'))
|
||||||
|
finally:
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
# GET Request - Formular anzeigen
|
||||||
|
return render_template("create_customer.html", username=session.get('username'))
|
||||||
|
|
||||||
@app.route("/customer/delete/<int:customer_id>", methods=["POST"])
|
@app.route("/customer/delete/<int:customer_id>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_customer(customer_id):
|
def delete_customer(customer_id):
|
||||||
|
|||||||
74
v2_adminpanel/templates/create_customer.html
Normale Datei
74
v2_adminpanel/templates/create_customer.html
Normale Datei
@@ -0,0 +1,74 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Neuer Kunde{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<h2>👤 Neuer Kunde anlegen</h2>
|
||||||
|
<div>
|
||||||
|
<a href="/" class="btn btn-secondary">📊 Dashboard</a>
|
||||||
|
<a href="/customers" class="btn btn-secondary">👥 Zurück zur Übersicht</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="post" action="/customer/create" accept-charset="UTF-8">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="name" class="form-label">Kundenname <span class="text-danger">*</span></label>
|
||||||
|
<input type="text" class="form-control" id="name" name="name"
|
||||||
|
placeholder="Firmenname oder Vor- und Nachname"
|
||||||
|
accept-charset="UTF-8" required autofocus>
|
||||||
|
<div class="form-text">Der Name des Kunden oder der Firma</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="email" class="form-label">E-Mail <span class="text-danger">*</span></label>
|
||||||
|
<input type="email" class="form-control" id="email" name="email"
|
||||||
|
placeholder="kunde@beispiel.de"
|
||||||
|
accept-charset="UTF-8" required>
|
||||||
|
<div class="form-text">Kontakt-E-Mail-Adresse des Kunden</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check mt-3">
|
||||||
|
<input class="form-check-input" type="checkbox" id="isTest" name="is_test">
|
||||||
|
<label class="form-check-label" for="isTest">
|
||||||
|
<i class="fas fa-flask"></i> Als Testdaten markieren
|
||||||
|
<small class="text-muted">(Kunde wird von der Software ignoriert)</small>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="alert alert-info mt-4" role="alert">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
<strong>Hinweis:</strong> Nach dem Anlegen des Kunden können Sie direkt Lizenzen für diesen Kunden erstellen.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<button type="submit" class="btn btn-primary">💾 Kunde anlegen</button>
|
||||||
|
<a href="/customers" class="btn btn-secondary">Abbrechen</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Flash Messages -->
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% if messages %}
|
||||||
|
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="toast show align-items-center text-white bg-{{ 'danger' if category == 'error' else 'success' }} border-0" role="alert">
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="toast-body">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
{% endblock %}
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
<i class="bi bi-layout-split"></i> Kombinierte Ansicht
|
<i class="bi bi-layout-split"></i> Kombinierte Ansicht
|
||||||
</a>
|
</a>
|
||||||
<a href="/" class="btn btn-secondary">📊 Dashboard</a>
|
<a href="/" class="btn btn-secondary">📊 Dashboard</a>
|
||||||
|
<a href="/customer/create" class="btn btn-primary">👤 Neuer Kunde</a>
|
||||||
<a href="/create" class="btn btn-primary">➕ Neue Lizenz</a>
|
<a href="/create" class="btn btn-primary">➕ Neue Lizenz</a>
|
||||||
<a href="/batch" class="btn btn-primary">🔑 Batch-Lizenzen</a>
|
<a href="/batch" class="btn btn-primary">🔑 Batch-Lizenzen</a>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<h2>👥 Kunden & Lizenzen</h2>
|
<h2>👥 Kunden & Lizenzen</h2>
|
||||||
<div>
|
<div>
|
||||||
|
<a href="/customer/create" class="btn btn-primary">👤 Neuer Kunde</a>
|
||||||
<a href="/create" class="btn btn-success">➕ Neue Lizenz</a>
|
<a href="/create" class="btn btn-success">➕ Neue Lizenz</a>
|
||||||
<a href="/batch" class="btn btn-primary">🔑 Batch-Lizenzen</a>
|
<a href="/batch" class="btn btn-primary">🔑 Batch-Lizenzen</a>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren