Unnötige Reddis und Rabbit MQ entfernt
Dieser Commit ist enthalten in:
@@ -25,40 +25,6 @@ services:
|
|||||||
cpus: '2'
|
cpus: '2'
|
||||||
memory: 4g
|
memory: 4g
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
container_name: redis-cache
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
TZ: Europe/Berlin
|
|
||||||
networks:
|
|
||||||
- internal_net
|
|
||||||
volumes:
|
|
||||||
- redis_data:/data
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.5'
|
|
||||||
memory: 512m
|
|
||||||
|
|
||||||
rabbitmq:
|
|
||||||
image: rabbitmq:3-management
|
|
||||||
container_name: rabbitmq
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-admin}
|
|
||||||
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASS:-admin}
|
|
||||||
TZ: Europe/Berlin
|
|
||||||
networks:
|
|
||||||
- internal_net
|
|
||||||
volumes:
|
|
||||||
- rabbitmq_data:/var/lib/rabbitmq
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '1'
|
|
||||||
memory: 1g
|
|
||||||
|
|
||||||
license-server:
|
license-server:
|
||||||
build:
|
build:
|
||||||
context: ../v2_lizenzserver
|
context: ../v2_lizenzserver
|
||||||
@@ -68,11 +34,8 @@ services:
|
|||||||
env_file: .env
|
env_file: .env
|
||||||
environment:
|
environment:
|
||||||
TZ: Europe/Berlin
|
TZ: Europe/Berlin
|
||||||
REDIS_URL: redis://redis:6379/0
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
- redis
|
|
||||||
- rabbitmq
|
|
||||||
networks:
|
networks:
|
||||||
- internal_net
|
- internal_net
|
||||||
deploy:
|
deploy:
|
||||||
@@ -199,5 +162,3 @@ networks:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
redis_data:
|
|
||||||
rabbitmq_data:
|
|
||||||
|
|||||||
72
v2_adminpanel/migrations/add_fake_constraint.sql
Normale Datei
72
v2_adminpanel/migrations/add_fake_constraint.sql
Normale Datei
@@ -0,0 +1,72 @@
|
|||||||
|
-- Add constraint to ensure licenses always inherit is_fake from their customer
|
||||||
|
-- This migration adds a trigger to automatically sync is_fake status
|
||||||
|
|
||||||
|
-- Function to sync is_fake status
|
||||||
|
CREATE OR REPLACE FUNCTION sync_license_fake_status()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
-- When inserting or updating a license, get is_fake from customer
|
||||||
|
IF TG_OP = 'INSERT' OR (TG_OP = 'UPDATE' AND NEW.customer_id != OLD.customer_id) THEN
|
||||||
|
SELECT is_fake INTO NEW.is_fake
|
||||||
|
FROM customers
|
||||||
|
WHERE id = NEW.customer_id;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Trigger for licenses table
|
||||||
|
DROP TRIGGER IF EXISTS sync_license_fake_before_insert_update ON licenses;
|
||||||
|
CREATE TRIGGER sync_license_fake_before_insert_update
|
||||||
|
BEFORE INSERT OR UPDATE ON licenses
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION sync_license_fake_status();
|
||||||
|
|
||||||
|
-- Function to update licenses when customer is_fake changes
|
||||||
|
CREATE OR REPLACE FUNCTION sync_customer_fake_to_licenses()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
-- When customer is_fake changes, update all their licenses
|
||||||
|
IF TG_OP = 'UPDATE' AND NEW.is_fake != OLD.is_fake THEN
|
||||||
|
UPDATE licenses
|
||||||
|
SET is_fake = NEW.is_fake
|
||||||
|
WHERE customer_id = NEW.id;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Trigger for customers table
|
||||||
|
DROP TRIGGER IF EXISTS sync_customer_fake_after_update ON customers;
|
||||||
|
CREATE TRIGGER sync_customer_fake_after_update
|
||||||
|
AFTER UPDATE ON customers
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION sync_customer_fake_to_licenses();
|
||||||
|
|
||||||
|
-- Verify current data is consistent (should return 0)
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
mismatch_count INTEGER;
|
||||||
|
BEGIN
|
||||||
|
SELECT COUNT(*) INTO mismatch_count
|
||||||
|
FROM licenses l
|
||||||
|
JOIN customers c ON l.customer_id = c.id
|
||||||
|
WHERE l.is_fake != c.is_fake;
|
||||||
|
|
||||||
|
IF mismatch_count > 0 THEN
|
||||||
|
RAISE NOTICE 'Found % mismatches. Fixing...', mismatch_count;
|
||||||
|
|
||||||
|
-- Fix any existing mismatches
|
||||||
|
UPDATE licenses l
|
||||||
|
SET is_fake = c.is_fake
|
||||||
|
FROM customers c
|
||||||
|
WHERE l.customer_id = c.id
|
||||||
|
AND l.is_fake != c.is_fake;
|
||||||
|
|
||||||
|
RAISE NOTICE 'Fixed all mismatches.';
|
||||||
|
ELSE
|
||||||
|
RAISE NOTICE 'No mismatches found. Data is consistent.';
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
@@ -37,7 +37,8 @@ def api_customers():
|
|||||||
for customer in paginated_customers:
|
for customer in paginated_customers:
|
||||||
results.append({
|
results.append({
|
||||||
'id': customer['id'],
|
'id': customer['id'],
|
||||||
'text': f"{customer['name']} ({customer['email'] or 'keine E-Mail'})"
|
'text': f"{customer['name']} ({customer['email'] or 'keine E-Mail'})",
|
||||||
|
'is_fake': customer.get('is_fake', False) # Include the is_fake field
|
||||||
})
|
})
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -913,7 +914,7 @@ def global_search():
|
|||||||
|
|
||||||
# Suche in Kunden
|
# Suche in Kunden
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT id, name, email
|
SELECT id, name, email, is_fake
|
||||||
FROM customers
|
FROM customers
|
||||||
WHERE name ILIKE %s OR email ILIKE %s
|
WHERE name ILIKE %s OR email ILIKE %s
|
||||||
LIMIT 10
|
LIMIT 10
|
||||||
@@ -923,7 +924,8 @@ def global_search():
|
|||||||
results['customers'].append({
|
results['customers'].append({
|
||||||
'id': row[0],
|
'id': row[0],
|
||||||
'name': row[1],
|
'name': row[1],
|
||||||
'email': row[2]
|
'email': row[2],
|
||||||
|
'is_fake': row[3]
|
||||||
})
|
})
|
||||||
|
|
||||||
# Suche in Ressourcen
|
# Suche in Ressourcen
|
||||||
|
|||||||
@@ -42,20 +42,21 @@ def batch_create():
|
|||||||
valid_from = request.form['valid_from']
|
valid_from = request.form['valid_from']
|
||||||
valid_until = request.form['valid_until']
|
valid_until = request.form['valid_until']
|
||||||
device_limit = int(request.form['device_limit'])
|
device_limit = int(request.form['device_limit'])
|
||||||
is_fake = 'is_fake' in request.form
|
|
||||||
|
|
||||||
# Validierung
|
# Validierung
|
||||||
if count < 1 or count > 100:
|
if count < 1 or count > 100:
|
||||||
flash('Anzahl muss zwischen 1 und 100 liegen!', 'error')
|
flash('Anzahl muss zwischen 1 und 100 liegen!', 'error')
|
||||||
return redirect(url_for('batch.batch_create'))
|
return redirect(url_for('batch.batch_create'))
|
||||||
|
|
||||||
# Hole Kundendaten
|
# Hole Kundendaten inkl. is_fake Status
|
||||||
cur.execute("SELECT name, email FROM customers WHERE id = %s", (customer_id,))
|
cur.execute("SELECT name, email, is_fake FROM customers WHERE id = %s", (customer_id,))
|
||||||
customer = cur.fetchone()
|
customer = cur.fetchone()
|
||||||
if not customer:
|
if not customer:
|
||||||
flash('Kunde nicht gefunden!', 'error')
|
flash('Kunde nicht gefunden!', 'error')
|
||||||
return redirect(url_for('batch.batch_create'))
|
return redirect(url_for('batch.batch_create'))
|
||||||
|
|
||||||
|
# Lizenz erbt immer den is_fake Status vom Kunden
|
||||||
|
is_fake = customer[2]
|
||||||
|
|
||||||
created_licenses = []
|
created_licenses = []
|
||||||
|
|
||||||
# Erstelle Lizenzen
|
# Erstelle Lizenzen
|
||||||
@@ -315,21 +316,27 @@ def batch_import():
|
|||||||
if not customer:
|
if not customer:
|
||||||
# Erstelle neuen Kunden
|
# Erstelle neuen Kunden
|
||||||
name = row.get('customer_name', email.split('@')[0])
|
name = row.get('customer_name', email.split('@')[0])
|
||||||
|
# Neue Kunden werden immer als Fake erstellt in der Testphase
|
||||||
|
# TODO: Nach Testphase muss hier die Business-Logik angepasst werden
|
||||||
|
is_fake = True
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
INSERT INTO customers (name, email, created_at)
|
INSERT INTO customers (name, email, is_fake, created_at)
|
||||||
VALUES (%s, %s, %s)
|
VALUES (%s, %s, %s, %s)
|
||||||
RETURNING id
|
RETURNING id
|
||||||
""", (name, email, datetime.now()))
|
""", (name, email, is_fake, datetime.now()))
|
||||||
customer_id = cur.fetchone()[0]
|
customer_id = cur.fetchone()[0]
|
||||||
customer_name = name
|
customer_name = name
|
||||||
else:
|
else:
|
||||||
customer_id = customer[0]
|
customer_id = customer[0]
|
||||||
customer_name = customer[1]
|
customer_name = customer[1]
|
||||||
|
# Hole is_fake Status vom existierenden Kunden
|
||||||
|
cur.execute("SELECT is_fake FROM customers WHERE id = %s", (customer_id,))
|
||||||
|
is_fake = cur.fetchone()[0]
|
||||||
|
|
||||||
# Generiere Lizenzschlüssel
|
# Generiere Lizenzschlüssel
|
||||||
license_key = row.get('license_key', generate_license_key())
|
license_key = row.get('license_key', generate_license_key())
|
||||||
|
|
||||||
# Erstelle Lizenz
|
# Erstelle Lizenz - is_fake wird vom Kunden geerbt
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
INSERT INTO licenses (
|
INSERT INTO licenses (
|
||||||
license_key, customer_id,
|
license_key, customer_id,
|
||||||
@@ -340,7 +347,7 @@ def batch_import():
|
|||||||
""", (
|
""", (
|
||||||
license_key, customer_id,
|
license_key, customer_id,
|
||||||
row['license_type'], row['valid_from'], row['valid_until'],
|
row['license_type'], row['valid_from'], row['valid_until'],
|
||||||
int(row['device_limit']), row.get('is_fake', False),
|
int(row['device_limit']), is_fake,
|
||||||
datetime.now()
|
datetime.now()
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
@@ -415,7 +415,8 @@ def api_customer_licenses(customer_id):
|
|||||||
'customer': {
|
'customer': {
|
||||||
'id': customer['id'],
|
'id': customer['id'],
|
||||||
'name': customer['name'],
|
'name': customer['name'],
|
||||||
'email': customer['email']
|
'email': customer['email'],
|
||||||
|
'is_fake': customer.get('is_fake', False) # Include the is_fake field
|
||||||
},
|
},
|
||||||
'licenses': licenses
|
'licenses': licenses
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -117,14 +117,13 @@ def edit_license(license_id):
|
|||||||
'valid_from': request.form['valid_from'],
|
'valid_from': request.form['valid_from'],
|
||||||
'valid_until': request.form['valid_until'],
|
'valid_until': request.form['valid_until'],
|
||||||
'is_active': 'is_active' in request.form,
|
'is_active': 'is_active' in request.form,
|
||||||
'is_fake': 'is_fake' in request.form,
|
|
||||||
'device_limit': int(request.form.get('device_limit', 3))
|
'device_limit': int(request.form.get('device_limit', 3))
|
||||||
}
|
}
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
UPDATE licenses
|
UPDATE licenses
|
||||||
SET license_key = %s, license_type = %s, valid_from = %s,
|
SET license_key = %s, license_type = %s, valid_from = %s,
|
||||||
valid_until = %s, is_active = %s, is_fake = %s, device_limit = %s
|
valid_until = %s, is_active = %s, device_limit = %s
|
||||||
WHERE id = %s
|
WHERE id = %s
|
||||||
""", (
|
""", (
|
||||||
new_values['license_key'],
|
new_values['license_key'],
|
||||||
@@ -132,7 +131,6 @@ def edit_license(license_id):
|
|||||||
new_values['valid_from'],
|
new_values['valid_from'],
|
||||||
new_values['valid_until'],
|
new_values['valid_until'],
|
||||||
new_values['is_active'],
|
new_values['is_active'],
|
||||||
new_values['is_fake'],
|
|
||||||
new_values['device_limit'],
|
new_values['device_limit'],
|
||||||
license_id
|
license_id
|
||||||
))
|
))
|
||||||
@@ -147,7 +145,6 @@ def edit_license(license_id):
|
|||||||
'valid_from': str(current_license.get('valid_from', '')),
|
'valid_from': str(current_license.get('valid_from', '')),
|
||||||
'valid_until': str(current_license.get('valid_until', '')),
|
'valid_until': str(current_license.get('valid_until', '')),
|
||||||
'is_active': current_license.get('is_active'),
|
'is_active': current_license.get('is_active'),
|
||||||
'is_fake': current_license.get('is_fake'),
|
|
||||||
'device_limit': current_license.get('device_limit', 3)
|
'device_limit': current_license.get('device_limit', 3)
|
||||||
},
|
},
|
||||||
new_values=new_values)
|
new_values=new_values)
|
||||||
@@ -286,7 +283,7 @@ def create_license():
|
|||||||
license_key = request.form["license_key"].upper() # Immer Großbuchstaben
|
license_key = request.form["license_key"].upper() # Immer Großbuchstaben
|
||||||
license_type = request.form["license_type"]
|
license_type = request.form["license_type"]
|
||||||
valid_from = request.form["valid_from"]
|
valid_from = request.form["valid_from"]
|
||||||
is_fake = request.form.get("is_fake") == "on" # Checkbox value
|
# is_fake wird später vom Kunden geerbt
|
||||||
|
|
||||||
# Berechne valid_until basierend auf Laufzeit
|
# Berechne valid_until basierend auf Laufzeit
|
||||||
duration = int(request.form.get("duration", 1))
|
duration = int(request.form.get("duration", 1))
|
||||||
@@ -338,7 +335,9 @@ def create_license():
|
|||||||
flash(f'E-Mail bereits vergeben für Kunde: {existing[1]}', 'error')
|
flash(f'E-Mail bereits vergeben für Kunde: {existing[1]}', 'error')
|
||||||
return redirect(url_for('licenses.create_license'))
|
return redirect(url_for('licenses.create_license'))
|
||||||
|
|
||||||
# Kunde einfügen (erbt Test-Status von Lizenz)
|
# Neuer Kunde wird immer als Fake erstellt, da wir in der Testphase sind
|
||||||
|
# TODO: Nach Testphase muss hier die Business-Logik angepasst werden
|
||||||
|
is_fake = True
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
INSERT INTO customers (name, email, is_fake, created_at)
|
INSERT INTO customers (name, email, is_fake, created_at)
|
||||||
VALUES (%s, %s, %s, NOW())
|
VALUES (%s, %s, %s, NOW())
|
||||||
@@ -359,9 +358,8 @@ def create_license():
|
|||||||
return redirect(url_for('licenses.create_license'))
|
return redirect(url_for('licenses.create_license'))
|
||||||
customer_info = {'name': customer_data[0], 'email': customer_data[1]}
|
customer_info = {'name': customer_data[0], 'email': customer_data[1]}
|
||||||
|
|
||||||
# Wenn Kunde Test-Kunde ist, Lizenz auch als Test markieren
|
# Lizenz erbt immer den is_fake Status vom Kunden
|
||||||
if customer_data[2]: # is_fake des Kunden
|
is_fake = customer_data[2]
|
||||||
is_fake = True
|
|
||||||
|
|
||||||
# Lizenz hinzufügen
|
# Lizenz hinzufügen
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
|
|||||||
@@ -191,11 +191,7 @@ def system_status():
|
|||||||
# Check each service
|
# Check each service
|
||||||
service_checks = [
|
service_checks = [
|
||||||
{'name': 'License Server', 'url': 'http://license-server:8443/health', 'port': 8443},
|
{'name': 'License Server', 'url': 'http://license-server:8443/health', 'port': 8443},
|
||||||
{'name': 'Auth Service', 'url': 'http://auth-service:5001/health', 'port': 5001},
|
|
||||||
{'name': 'Analytics Service', 'url': 'http://analytics-service:5003/health', 'port': 5003},
|
|
||||||
{'name': 'Admin API Service', 'url': 'http://admin-api-service:5004/health', 'port': 5004},
|
|
||||||
{'name': 'PostgreSQL', 'check': 'database'},
|
{'name': 'PostgreSQL', 'check': 'database'},
|
||||||
{'name': 'Redis', 'url': 'http://redis:6379', 'check': 'redis'},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for service in service_checks:
|
for service in service_checks:
|
||||||
|
|||||||
@@ -26,6 +26,11 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
|
<!-- Customer Type Indicator -->
|
||||||
|
<div id="customerTypeIndicator" class="alert d-none mb-3" role="alert">
|
||||||
|
<i class="fas fa-info-circle"></i> <span id="customerTypeMessage"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form method="post" action="{{ url_for('batch.batch_create') }}" accept-charset="UTF-8">
|
<form method="post" action="{{ url_for('batch.batch_create') }}" accept-charset="UTF-8">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -173,14 +178,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Test Data Checkbox -->
|
|
||||||
<div class="form-check mt-3">
|
|
||||||
<input class="form-check-input" type="checkbox" id="isFake" name="is_fake">
|
|
||||||
<label class="form-check-label" for="isFake">
|
|
||||||
<i class="fas fa-flask"></i> Als Fake-Daten markieren
|
|
||||||
<small class="text-muted">(wird von der Software ignoriert)</small>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-4 d-flex gap-2">
|
<div class="mt-4 d-flex gap-2">
|
||||||
<button type="submit" class="btn btn-primary btn-lg">
|
<button type="submit" class="btn btn-primary btn-lg">
|
||||||
@@ -316,6 +313,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
emailDiv.style.display = 'block';
|
emailDiv.style.display = 'block';
|
||||||
nameInput.required = true;
|
nameInput.required = true;
|
||||||
emailInput.required = true;
|
emailInput.required = true;
|
||||||
|
|
||||||
|
// Zeige Indikator für neuen Kunden
|
||||||
|
showCustomerTypeIndicator('new');
|
||||||
} else {
|
} else {
|
||||||
// Verstecke Eingabefelder bei bestehendem Kunden
|
// Verstecke Eingabefelder bei bestehendem Kunden
|
||||||
nameDiv.style.display = 'none';
|
nameDiv.style.display = 'none';
|
||||||
@@ -324,6 +324,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
emailInput.required = false;
|
emailInput.required = false;
|
||||||
nameInput.value = '';
|
nameInput.value = '';
|
||||||
emailInput.value = '';
|
emailInput.value = '';
|
||||||
|
|
||||||
|
// Zeige Indikator basierend auf Kundendaten
|
||||||
|
if (e.params.data.is_fake !== undefined) {
|
||||||
|
showCustomerTypeIndicator(e.params.data.is_fake ? 'fake' : 'real');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -333,6 +338,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
document.getElementById('emailDiv').style.display = 'none';
|
document.getElementById('emailDiv').style.display = 'none';
|
||||||
document.getElementById('customerName').required = false;
|
document.getElementById('customerName').required = false;
|
||||||
document.getElementById('email').required = false;
|
document.getElementById('email').required = false;
|
||||||
|
hideCustomerTypeIndicator();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Resource Availability Check
|
// Resource Availability Check
|
||||||
@@ -460,5 +466,28 @@ function updateBatchResourceStatus(data, totalDomains, totalIpv4, totalPhones, q
|
|||||||
submitButton.classList.remove('btn-secondary');
|
submitButton.classList.remove('btn-secondary');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Funktion zur Anzeige des Kundentyp-Indikators
|
||||||
|
function showCustomerTypeIndicator(type) {
|
||||||
|
const indicator = document.getElementById('customerTypeIndicator');
|
||||||
|
const message = document.getElementById('customerTypeMessage');
|
||||||
|
|
||||||
|
indicator.classList.remove('d-none', 'alert-info', 'alert-warning', 'alert-success');
|
||||||
|
|
||||||
|
if (type === 'new') {
|
||||||
|
indicator.classList.add('alert-info');
|
||||||
|
message.textContent = 'Neue Kunden werden in der Testphase als TEST-Kunden erstellt. Alle Batch-Lizenzen werden automatisch als TEST-Lizenzen markiert.';
|
||||||
|
} else if (type === 'fake') {
|
||||||
|
indicator.classList.add('alert-warning');
|
||||||
|
message.textContent = 'Dies ist ein TEST-Kunde. Alle Batch-Lizenzen werden automatisch als TEST-Lizenzen markiert und von der Software ignoriert.';
|
||||||
|
} else if (type === 'real') {
|
||||||
|
indicator.classList.add('alert-success');
|
||||||
|
message.textContent = 'Dies ist ein PRODUKTIV-Kunde. Alle Batch-Lizenzen werden als produktive Lizenzen erstellt.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideCustomerTypeIndicator() {
|
||||||
|
document.getElementById('customerTypeIndicator').classList.add('d-none');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -65,12 +65,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check mt-3">
|
<div class="alert {% if license.is_fake %}alert-warning{% else %}alert-success{% endif %} mt-3" role="alert">
|
||||||
<input class="form-check-input" type="checkbox" id="isTest" name="is_fake" {% if license.is_fake %}checked{% endif %}>
|
<i class="fas fa-info-circle"></i>
|
||||||
<label class="form-check-label" for="isTest">
|
<strong>Status:</strong>
|
||||||
<i class="fas fa-flask"></i> Als Fake-Daten markieren
|
{% if license.is_fake %}
|
||||||
<small class="text-muted">(wird von der Software ignoriert)</small>
|
TEST-Lizenz (wird von der Software ignoriert)
|
||||||
</label>
|
{% else %}
|
||||||
|
PRODUKTIV-Lizenz
|
||||||
|
{% endif %}
|
||||||
|
<br>
|
||||||
|
<small class="text-muted">Der Status wird vom Kunden geerbt und kann nicht direkt geändert werden.</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
|
|||||||
@@ -9,6 +9,11 @@
|
|||||||
<a href="{{ url_for('customers.customers_licenses') }}" class="btn btn-secondary">← Zurück zur Übersicht</a>
|
<a href="{{ url_for('customers.customers_licenses') }}" class="btn btn-secondary">← Zurück zur Übersicht</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Customer Type Indicator -->
|
||||||
|
<div id="customerTypeIndicator" class="alert d-none mb-3" role="alert">
|
||||||
|
<i class="fas fa-info-circle"></i> <span id="customerTypeMessage"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form method="post" action="{{ url_for('licenses.create_license') }}" accept-charset="UTF-8">
|
<form method="post" action="{{ url_for('licenses.create_license') }}" accept-charset="UTF-8">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -152,14 +157,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Test Data Checkbox -->
|
|
||||||
<div class="form-check mt-3">
|
|
||||||
<input class="form-check-input" type="checkbox" id="isTest" name="is_fake">
|
|
||||||
<label class="form-check-label" for="isTest">
|
|
||||||
<i class="fas fa-flask"></i> Als Fake-Daten markieren
|
|
||||||
<small class="text-muted">(wird von der Software ignoriert)</small>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<button type="submit" class="btn btn-primary">➕ Lizenz erstellen</button>
|
<button type="submit" class="btn btn-primary">➕ Lizenz erstellen</button>
|
||||||
@@ -368,6 +365,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
emailDiv.style.display = 'block';
|
emailDiv.style.display = 'block';
|
||||||
nameInput.required = true;
|
nameInput.required = true;
|
||||||
emailInput.required = true;
|
emailInput.required = true;
|
||||||
|
|
||||||
|
// Zeige Indikator für neuen Kunden
|
||||||
|
showCustomerTypeIndicator('new');
|
||||||
} else {
|
} else {
|
||||||
// Verstecke Eingabefelder bei bestehendem Kunden
|
// Verstecke Eingabefelder bei bestehendem Kunden
|
||||||
nameDiv.style.display = 'none';
|
nameDiv.style.display = 'none';
|
||||||
@@ -376,6 +376,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
emailInput.required = false;
|
emailInput.required = false;
|
||||||
nameInput.value = '';
|
nameInput.value = '';
|
||||||
emailInput.value = '';
|
emailInput.value = '';
|
||||||
|
|
||||||
|
// Zeige Indikator basierend auf Kundendaten
|
||||||
|
if (e.params.data.is_fake !== undefined) {
|
||||||
|
showCustomerTypeIndicator(e.params.data.is_fake ? 'fake' : 'real');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -385,6 +390,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
document.getElementById('emailDiv').style.display = 'none';
|
document.getElementById('emailDiv').style.display = 'none';
|
||||||
document.getElementById('customerName').required = false;
|
document.getElementById('customerName').required = false;
|
||||||
document.getElementById('email').required = false;
|
document.getElementById('email').required = false;
|
||||||
|
hideCustomerTypeIndicator();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Resource Availability Check
|
// Resource Availability Check
|
||||||
@@ -529,5 +535,28 @@ function updateResourceStatus(data, domainCount, ipv4Count, phoneCount) {
|
|||||||
statusElement.textContent = message;
|
statusElement.textContent = message;
|
||||||
statusElement.className = hasIssue ? 'text-danger' : 'text-success';
|
statusElement.className = hasIssue ? 'text-danger' : 'text-success';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Funktion zur Anzeige des Kundentyp-Indikators
|
||||||
|
function showCustomerTypeIndicator(type) {
|
||||||
|
const indicator = document.getElementById('customerTypeIndicator');
|
||||||
|
const message = document.getElementById('customerTypeMessage');
|
||||||
|
|
||||||
|
indicator.classList.remove('d-none', 'alert-info', 'alert-warning', 'alert-success');
|
||||||
|
|
||||||
|
if (type === 'new') {
|
||||||
|
indicator.classList.add('alert-info');
|
||||||
|
message.textContent = 'Neue Kunden werden in der Testphase als TEST-Kunden erstellt. Die Lizenz wird automatisch als TEST-Lizenz markiert.';
|
||||||
|
} else if (type === 'fake') {
|
||||||
|
indicator.classList.add('alert-warning');
|
||||||
|
message.textContent = 'Dies ist ein TEST-Kunde. Die Lizenz wird automatisch als TEST-Lizenz markiert und von der Software ignoriert.';
|
||||||
|
} else if (type === 'real') {
|
||||||
|
indicator.classList.add('alert-success');
|
||||||
|
message.textContent = 'Dies ist ein PRODUKTIV-Kunde. Die Lizenz wird als produktive Lizenz erstellt.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideCustomerTypeIndicator() {
|
||||||
|
document.getElementById('customerTypeIndicator').classList.add('d-none');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ class Settings(BaseSettings):
|
|||||||
|
|
||||||
DATABASE_URL: str = "postgresql://license_user:license_password@db:5432/license_db"
|
DATABASE_URL: str = "postgresql://license_user:license_password@db:5432/license_db"
|
||||||
|
|
||||||
REDIS_URL: str = "redis://redis:6379"
|
|
||||||
|
|
||||||
ALLOWED_ORIGINS: List[str] = [
|
ALLOWED_ORIGINS: List[str] = [
|
||||||
"https://api-software-undso.z5m7q9dk3ah2v1plx6ju.com",
|
"https://api-software-undso.z5m7q9dk3ah2v1plx6ju.com",
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren