2 Commits

Author SHA1 Message Date
e4b37d9261 Fehler in der API behoben 2025-08-02 18:37:17 +02:00
45cc02b4b0 Fehler in API behoben 2025-08-02 18:30:16 +02:00
4 changed files with 19 additions and 24 deletions

View File

@@ -334,6 +334,7 @@ curl -X POST http://localhost:5000/api/plusminus \
``` ```
**Hinweis:** **Hinweis:**
- `"einheit"`: `"tage"`, `"wochen"` oder `"monate"` - `"einheit"`: `"tage"`, `"wochen"` oder `"monate"`
- `"richtung"`: `"add"` (plus) oder `"sub"` (minus) - `"richtung"`: `"add"` (plus) oder `"sub"` (minus)
- `"werktage"`: `true` für Werktage, sonst `false` (nur bei `"tage"` unterstützt) - `"werktage"`: `true` für Werktage, sonst `false` (nur bei `"tage"` unterstützt)

29
app.py
View File

@@ -415,34 +415,22 @@ def api_plusminus():
if is_werktage: if is_werktage:
result = np.busday_offset(d.date(), anzahl_int, roll='forward') result = np.busday_offset(d.date(), anzahl_int, roll='forward')
result_dt = datetime.strptime(str(result), '%Y-%m-%d') result_dt = datetime.strptime(str(result), '%Y-%m-%d')
if locale == 'en': return jsonify({'result': result_dt.strftime('%Y-%m-%d')})
plusminus_result = f"Date {d.strftime('%m/%d/%Y')} {'plus' if anzahl_int>=0 else 'minus'} {abs(anzahl_int)} workdays: {result_dt.strftime('%m/%d/%Y')}"
else:
plusminus_result = f"Datum {d.strftime('%d.%m.%Y')} {'plus' if anzahl_int>=0 else 'minus'} {abs(anzahl_int)} Werktage: {result_dt.strftime('%d.%m.%Y')}"
else: else:
result = d + timedelta(days=anzahl_int) result = d + timedelta(days=anzahl_int)
if locale == 'en': return jsonify({'result': result.strftime('%Y-%m-%d')})
plusminus_result = f"Date {d.strftime('%m/%d/%Y')} {'plus' if anzahl_int>=0 else 'minus'} {abs(anzahl_int)} days: {result.strftime('%m/%d/%Y')}"
else:
plusminus_result = f"Datum {d.strftime('%d.%m.%Y')} {'plus' if anzahl_int>=0 else 'minus'} {abs(anzahl_int)} Tage: {result.strftime('%d.%m.%Y')}"
elif einheit == 'wochen': elif einheit == 'wochen':
if is_werktage: if is_werktage:
return jsonify({'error': 'Nicht unterstützt: Werktage + Wochen.'}), 400 return jsonify({'error': 'Nicht unterstützt: Werktage + Wochen.'}), 400
else: else:
result = d + timedelta(weeks=anzahl_int) result = d + timedelta(weeks=anzahl_int)
if locale == 'en': return jsonify({'result': result.strftime('%Y-%m-%d')})
plusminus_result = f"Date {d.strftime('%m/%d/%Y')} {'plus' if anzahl_int>=0 else 'minus'} {abs(anzahl_int)} weeks: {result.strftime('%m/%d/%Y')}"
else:
plusminus_result = f"Datum {d.strftime('%d.%m.%Y')} {'plus' if anzahl_int>=0 else 'minus'} {abs(anzahl_int)} Wochen: {result.strftime('%d.%m.%Y')}"
elif einheit == 'monate': elif einheit == 'monate':
if is_werktage: if is_werktage:
return jsonify({'error': 'Nicht unterstützt: Werktage + Monate.'}), 400 return jsonify({'error': 'Nicht unterstützt: Werktage + Monate.'}), 400
else: else:
result = d + relativedelta(months=anzahl_int) result = d + relativedelta(months=anzahl_int)
if locale == 'en': return jsonify({'result': result.strftime('%Y-%m-%d')})
plusminus_result = f"Date {d.strftime('%m/%d/%Y')} {'plus' if anzahl_int>=0 else 'minus'} {abs(anzahl_int)} months: {result.strftime('%m/%d/%Y')}"
else:
plusminus_result = f"Datum {d.strftime('%d.%m.%Y')} {'plus' if anzahl_int>=0 else 'minus'} {abs(anzahl_int)} Monate: {result.strftime('%d.%m.%Y')}"
else: else:
return jsonify({'error': 'Ungültige Einheit'}), 400 return jsonify({'error': 'Ungültige Einheit'}), 400
except Exception as e: except Exception as e:
@@ -451,8 +439,13 @@ def api_plusminus():
@app.route('/api/stats', methods=['GET']) @app.route('/api/stats', methods=['GET'])
def api_stats(): def api_stats():
log_path = os.path.join('log', 'pageviews.log') log_path = os.path.join('log', 'pageviews.log')
pageviews, func_counts, impressions_per_day, api_counts = parse_log_stats(log_path) pageviews, func_counts, func_counts_hourly, impressions_per_day, impressions_per_hour, api_counts, api_counts_hourly = parse_log_stats(log_path)
return render_template('stats_dashboard.html', pageviews=pageviews, func_counts=func_counts, impressions_per_day=impressions_per_day, api_counts=api_counts) return jsonify({
"pageviews": pageviews,
"func_counts": func_counts,
"impressions_per_day": impressions_per_day,
"api_counts": api_counts
})
@app.route('/api/monitor', methods=['GET']) @app.route('/api/monitor', methods=['GET'])
def api_monitor(): def api_monitor():

View File

@@ -1081,9 +1081,9 @@ footer br + a {
</div> </div>
<footer style="text-align:center; margin-top:2em; color:#475569; font-size:0.98em; padding-bottom:1.5em;"> <footer style="text-align:center; margin-top:2em; color:#475569; font-size:0.98em; padding-bottom:1.5em;">
Dies ist ein werbe- und trackingfreier <a href="https://codeberg.org/elpatron/datecalc/src/branch/main/README.md" target="_blank" style="color:#1e40af; text-decoration:underline;">Open Source Datumsrechner</a><br> Dies ist ein werbe- und trackingfreier <a href="https://codeberg.org/elpatron/datecalc/src/branch/main/README.md" target="_blank" style="color:#1e40af; text-decoration:underline;">Open Source</a> Datumsrechner<br>
<a href="/api-docs" target="_blank" style="color:#1e40af; text-decoration:underline;">REST API Dokumentation (Swagger)</a><br> <a href="/api-docs" target="_blank" style="color:#1e40af; text-decoration:underline;">REST API Dokumentation (Swagger)</a><br>
© 2025 <a href="mailto:elpatron@mailbox.org?subject=Datumsrechner" style="color:#1e40af; text-decoration:underline;">M. Busche</a> © 2025 <a href="mailto:elpatron@mailbox.org?subject=Datumsrechner" style="color:#1e40af; text-decoration:underline;">Markus Busche</a>
<div style="margin-top:0.5em; font-size:0.85em; color:#64748b;">v{{ app_version }}</div> <div style="margin-top:0.5em; font-size:0.85em; color:#64748b;">v{{ app_version }}</div>
</footer> </footer>
<script> <script>

View File

@@ -221,10 +221,11 @@ def test_api_plusminus(client):
def test_api_stats(client): def test_api_stats(client):
resp = client.get('/api/stats') resp = client.get('/api/stats')
assert resp.status_code == 200 assert resp.status_code == 200
# Die Route gibt HTML zurück, nicht JSON data = resp.get_json()
html = resp.data.decode('utf-8') assert "pageviews" in data
# Prüfe auf typische HTML-Elemente des Dashboards assert "func_counts" in data
assert 'Statistik-Dashboard' in html or 'Dashboard' in html assert "impressions_per_day" in data
assert "api_counts" in data
def test_api_monitor(client): def test_api_monitor(client):
resp = client.get('/api/monitor') resp = client.get('/api/monitor')