[split-required] Split 500-1000 LOC files across all services
backend-lehrer (5 files): - alerts_agent/db/repository.py (992 → 5), abitur_docs_api.py (956 → 3) - teacher_dashboard_api.py (951 → 3), services/pdf_service.py (916 → 3) - mail/mail_db.py (987 → 6) klausur-service (5 files): - legal_templates_ingestion.py (942 → 3), ocr_pipeline_postprocess.py (929 → 4) - ocr_pipeline_words.py (876 → 3), ocr_pipeline_ocr_merge.py (616 → 2) - KorrekturPage.tsx (956 → 6) website (5 pages): - mail (985 → 9), edu-search (958 → 8), mac-mini (950 → 7) - ocr-labeling (946 → 7), audit-workspace (871 → 4) studio-v2 (5 files + 1 deleted): - page.tsx (946 → 5), MessagesContext.tsx (925 → 4) - korrektur (914 → 6), worksheet-cleanup (899 → 6) - useVocabWorksheet.ts (888 → 3) - Deleted dead page-original.tsx (934 LOC) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
247
klausur-service/backend/mail/mail_db_tasks.py
Normal file
247
klausur-service/backend/mail/mail_db_tasks.py
Normal file
@@ -0,0 +1,247 @@
|
||||
"""
|
||||
Mail Database - Inbox Task Operations.
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from typing import Optional, List, Dict
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from .mail_db_pool import get_pool
|
||||
|
||||
|
||||
async def create_task(
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
title: str,
|
||||
description: Optional[str] = None,
|
||||
priority: str = "medium",
|
||||
deadline: Optional[datetime] = None,
|
||||
email_id: Optional[str] = None,
|
||||
account_id: Optional[str] = None,
|
||||
source_email_subject: Optional[str] = None,
|
||||
source_sender: Optional[str] = None,
|
||||
source_sender_type: Optional[str] = None,
|
||||
ai_extracted: bool = False,
|
||||
confidence_score: Optional[float] = None,
|
||||
) -> Optional[str]:
|
||||
"""Create a new inbox task."""
|
||||
pool = await get_pool()
|
||||
if pool is None:
|
||||
return None
|
||||
|
||||
task_id = str(uuid.uuid4())
|
||||
try:
|
||||
async with pool.acquire() as conn:
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO inbox_tasks
|
||||
(id, user_id, tenant_id, title, description, priority, deadline,
|
||||
email_id, account_id, source_email_subject, source_sender,
|
||||
source_sender_type, ai_extracted, confidence_score)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
|
||||
""",
|
||||
task_id, user_id, tenant_id, title, description, priority, deadline,
|
||||
email_id, account_id, source_email_subject, source_sender,
|
||||
source_sender_type, ai_extracted, confidence_score
|
||||
)
|
||||
return task_id
|
||||
except Exception as e:
|
||||
print(f"Failed to create task: {e}")
|
||||
return None
|
||||
|
||||
|
||||
async def get_tasks(
|
||||
user_id: str,
|
||||
status: Optional[str] = None,
|
||||
priority: Optional[str] = None,
|
||||
include_completed: bool = False,
|
||||
limit: int = 50,
|
||||
offset: int = 0,
|
||||
) -> List[Dict]:
|
||||
"""Get tasks for a user."""
|
||||
pool = await get_pool()
|
||||
if pool is None:
|
||||
return []
|
||||
|
||||
try:
|
||||
async with pool.acquire() as conn:
|
||||
conditions = ["user_id = $1"]
|
||||
params = [user_id]
|
||||
param_idx = 2
|
||||
|
||||
if not include_completed:
|
||||
conditions.append("status != 'completed'")
|
||||
|
||||
if status:
|
||||
conditions.append(f"status = ${param_idx}")
|
||||
params.append(status)
|
||||
param_idx += 1
|
||||
|
||||
if priority:
|
||||
conditions.append(f"priority = ${param_idx}")
|
||||
params.append(priority)
|
||||
param_idx += 1
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
params.extend([limit, offset])
|
||||
|
||||
query = f"""
|
||||
SELECT * FROM inbox_tasks
|
||||
WHERE {where_clause}
|
||||
ORDER BY
|
||||
CASE priority
|
||||
WHEN 'urgent' THEN 1
|
||||
WHEN 'high' THEN 2
|
||||
WHEN 'medium' THEN 3
|
||||
WHEN 'low' THEN 4
|
||||
END,
|
||||
deadline ASC NULLS LAST,
|
||||
created_at DESC
|
||||
LIMIT ${param_idx} OFFSET ${param_idx + 1}
|
||||
"""
|
||||
|
||||
rows = await conn.fetch(query, *params)
|
||||
return [dict(r) for r in rows]
|
||||
except Exception as e:
|
||||
print(f"Failed to get tasks: {e}")
|
||||
return []
|
||||
|
||||
|
||||
async def get_task(task_id: str, user_id: str) -> Optional[Dict]:
|
||||
"""Get a single task."""
|
||||
pool = await get_pool()
|
||||
if pool is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
async with pool.acquire() as conn:
|
||||
row = await conn.fetchrow(
|
||||
"SELECT * FROM inbox_tasks WHERE id = $1 AND user_id = $2",
|
||||
task_id, user_id
|
||||
)
|
||||
return dict(row) if row else None
|
||||
except Exception as e:
|
||||
print(f"Failed to get task: {e}")
|
||||
return None
|
||||
|
||||
|
||||
async def update_task(
|
||||
task_id: str,
|
||||
user_id: str,
|
||||
title: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
priority: Optional[str] = None,
|
||||
status: Optional[str] = None,
|
||||
deadline: Optional[datetime] = None,
|
||||
) -> bool:
|
||||
"""Update a task."""
|
||||
pool = await get_pool()
|
||||
if pool is None:
|
||||
return False
|
||||
|
||||
try:
|
||||
async with pool.acquire() as conn:
|
||||
updates = ["updated_at = NOW()"]
|
||||
params = [task_id, user_id]
|
||||
param_idx = 3
|
||||
|
||||
if title is not None:
|
||||
updates.append(f"title = ${param_idx}")
|
||||
params.append(title)
|
||||
param_idx += 1
|
||||
|
||||
if description is not None:
|
||||
updates.append(f"description = ${param_idx}")
|
||||
params.append(description)
|
||||
param_idx += 1
|
||||
|
||||
if priority is not None:
|
||||
updates.append(f"priority = ${param_idx}")
|
||||
params.append(priority)
|
||||
param_idx += 1
|
||||
|
||||
if status is not None:
|
||||
updates.append(f"status = ${param_idx}")
|
||||
params.append(status)
|
||||
param_idx += 1
|
||||
if status == "completed":
|
||||
updates.append("completed_at = NOW()")
|
||||
|
||||
if deadline is not None:
|
||||
updates.append(f"deadline = ${param_idx}")
|
||||
params.append(deadline)
|
||||
param_idx += 1
|
||||
|
||||
set_clause = ", ".join(updates)
|
||||
await conn.execute(
|
||||
f"UPDATE inbox_tasks SET {set_clause} WHERE id = $1 AND user_id = $2",
|
||||
*params
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Failed to update task: {e}")
|
||||
return False
|
||||
|
||||
|
||||
async def get_task_dashboard_stats(user_id: str) -> Dict:
|
||||
"""Get dashboard statistics for tasks."""
|
||||
pool = await get_pool()
|
||||
if pool is None:
|
||||
return {}
|
||||
|
||||
try:
|
||||
async with pool.acquire() as conn:
|
||||
now = datetime.now()
|
||||
today_end = now.replace(hour=23, minute=59, second=59)
|
||||
week_end = now + timedelta(days=7)
|
||||
|
||||
stats = await conn.fetchrow(
|
||||
"""
|
||||
SELECT
|
||||
COUNT(*) as total_tasks,
|
||||
COUNT(*) FILTER (WHERE status = 'pending') as pending_tasks,
|
||||
COUNT(*) FILTER (WHERE status = 'in_progress') as in_progress_tasks,
|
||||
COUNT(*) FILTER (WHERE status = 'completed') as completed_tasks,
|
||||
COUNT(*) FILTER (WHERE status != 'completed' AND deadline < $2) as overdue_tasks,
|
||||
COUNT(*) FILTER (WHERE status != 'completed' AND deadline <= $3) as due_today,
|
||||
COUNT(*) FILTER (WHERE status != 'completed' AND deadline <= $4) as due_this_week
|
||||
FROM inbox_tasks
|
||||
WHERE user_id = $1
|
||||
""",
|
||||
user_id, now, today_end, week_end
|
||||
)
|
||||
|
||||
by_priority = await conn.fetch(
|
||||
"""
|
||||
SELECT priority, COUNT(*) as count
|
||||
FROM inbox_tasks
|
||||
WHERE user_id = $1 AND status != 'completed'
|
||||
GROUP BY priority
|
||||
""",
|
||||
user_id
|
||||
)
|
||||
|
||||
by_sender = await conn.fetch(
|
||||
"""
|
||||
SELECT source_sender_type, COUNT(*) as count
|
||||
FROM inbox_tasks
|
||||
WHERE user_id = $1 AND status != 'completed' AND source_sender_type IS NOT NULL
|
||||
GROUP BY source_sender_type
|
||||
""",
|
||||
user_id
|
||||
)
|
||||
|
||||
return {
|
||||
"total_tasks": stats['total_tasks'] or 0,
|
||||
"pending_tasks": stats['pending_tasks'] or 0,
|
||||
"in_progress_tasks": stats['in_progress_tasks'] or 0,
|
||||
"completed_tasks": stats['completed_tasks'] or 0,
|
||||
"overdue_tasks": stats['overdue_tasks'] or 0,
|
||||
"due_today": stats['due_today'] or 0,
|
||||
"due_this_week": stats['due_this_week'] or 0,
|
||||
"by_priority": {r['priority']: r['count'] for r in by_priority},
|
||||
"by_sender_type": {r['source_sender_type']: r['count'] for r in by_sender},
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Failed to get task stats: {e}")
|
||||
return {}
|
||||
Reference in New Issue
Block a user