refactor: AIDA -> modulare Zeiterfassung
- Alle AIDA-Referenzen durch generische Begriffe ersetzt
(aida -> attendance im Code, "Zeiterfassung" im UI)
- DB-Spalten: last_aida_status -> last_attendance_status
- Settings: aida_csv_path -> attendance_csv_path
- REST API fuer Zeiterfassung auf Port 8081:
POST /api/attendance/{personal_nr} mit {"status": "anwesend"}
GET /api/attendance - alle Status abfragen
- Automatische DB-Migration fuer bestehende Installationen
- CSV bleibt als Option, API als Echtzeit-Alternative
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -192,14 +192,14 @@ async def dashboard(request: Request):
|
||||
for seg_idx in range(dev["segment_count"]):
|
||||
row = conn.execute("""
|
||||
SELECT u.display_name, u.azure_id,
|
||||
s.last_aida_status, s.last_teams_status,
|
||||
s.last_attendance_status, s.last_teams_status,
|
||||
COALESCE(s.phone_active, 0) as phone_active,
|
||||
cr_aida.r as ar, cr_aida.g as ag, cr_aida.b as ab,
|
||||
cr_att.r as ar, cr_att.g as ag, cr_att.b as ab,
|
||||
cr_teams.r as tr, cr_teams.g as tg, cr_teams.b as tb
|
||||
FROM assignments a
|
||||
JOIN users u ON u.azure_id = a.user_azure_id
|
||||
LEFT JOIN state s ON s.user_azure_id = u.azure_id
|
||||
LEFT JOIN color_rules cr_aida ON cr_aida.status = s.last_aida_status
|
||||
LEFT JOIN color_rules cr_att ON cr_att.status = s.last_attendance_status
|
||||
LEFT JOIN color_rules cr_teams ON cr_teams.status = s.last_teams_status
|
||||
WHERE a.wled_device_id = ? AND a.segment = ?
|
||||
""", (dev["id"], seg_idx)).fetchone()
|
||||
@@ -207,10 +207,9 @@ async def dashboard(request: Request):
|
||||
if row:
|
||||
phone = row["phone_active"]
|
||||
if phone:
|
||||
# Phone active: show phone color
|
||||
pc = conn.execute("SELECT r,g,b FROM color_rules WHERE status='phone_active'").fetchone()
|
||||
r, g, b = (pc["r"], pc["g"], pc["b"]) if pc else (255, 0, 0)
|
||||
elif row["last_aida_status"] == "anwesend" and row["tr"] is not None:
|
||||
elif row["last_attendance_status"] == "anwesend" and row["tr"] is not None:
|
||||
r, g, b = row["tr"], row["tg"], row["tb"]
|
||||
elif row["ar"] is not None:
|
||||
r, g, b = row["ar"], row["ag"], row["ab"]
|
||||
@@ -219,7 +218,7 @@ async def dashboard(request: Request):
|
||||
segments.append({
|
||||
"index": seg_idx,
|
||||
"user": row["display_name"],
|
||||
"aida": row["last_aida_status"] or "-",
|
||||
"attendance": row["last_attendance_status"] or "-",
|
||||
"teams": row["last_teams_status"] or "-",
|
||||
"phone": phone,
|
||||
"r": r, "g": g, "b": b,
|
||||
@@ -227,7 +226,7 @@ async def dashboard(request: Request):
|
||||
else:
|
||||
segments.append({
|
||||
"index": seg_idx, "user": None,
|
||||
"aida": "-", "teams": "-",
|
||||
"attendance": "-", "teams": "-",
|
||||
"r": 128, "g": 128, "b": 128,
|
||||
})
|
||||
|
||||
@@ -558,8 +557,8 @@ async def update_settings(request: Request):
|
||||
keys = [
|
||||
"azure_client_id", "azure_client_secret", "azure_tenant_id",
|
||||
"azure_auth_tenant", "azure_scopes", "poll_interval",
|
||||
"aida_csv_path", "aida_status_anwesend", "aida_status_abwesend",
|
||||
"aida_status_homeoffice",
|
||||
"attendance_csv_path", "attendance_status_anwesend", "attendance_status_abwesend",
|
||||
"attendance_status_homeoffice",
|
||||
]
|
||||
for key in keys:
|
||||
value = form.get(key, "")
|
||||
@@ -607,7 +606,7 @@ async def log_page(request: Request):
|
||||
async def api_status():
|
||||
conn = database.get_db()
|
||||
states = conn.execute("""
|
||||
SELECT u.display_name, u.azure_id, s.last_aida_status, s.last_teams_status,
|
||||
SELECT u.display_name, u.azure_id, s.last_attendance_status, s.last_teams_status,
|
||||
s.updated_at, d.hostname, a.segment
|
||||
FROM state s
|
||||
JOIN users u ON u.azure_id = s.user_azure_id
|
||||
|
||||
Reference in New Issue
Block a user