[split-required] Split remaining Python monoliths (Phase 1 continued)
klausur-service (7 monoliths): - grid_editor_helpers.py (1,737 → 5 files: columns, filters, headers, zones) - cv_cell_grid.py (1,675 → 7 files: build, legacy, streaming, merge, vocab) - worksheet_editor_api.py (1,305 → 4 files: models, AI, reconstruct, routes) - legal_corpus_ingestion.py (1,280 → 3 files: registry, chunking, ingestion) - cv_review.py (1,248 → 4 files: pipeline, spell, LLM, barrel) - cv_preprocessing.py (1,166 → 3 files: deskew, dewarp, barrel) - rbac.py, admin_api.py, routes/eh.py remain (next batch) backend-lehrer (1 monolith): - classroom_engine/repository.py (1,705 → 7 files by domain) All re-export barrels preserve backward compatibility. Zero import errors verified. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
182
backend-lehrer/classroom_engine/repository_feedback.py
Normal file
182
backend-lehrer/classroom_engine/repository_feedback.py
Normal file
@@ -0,0 +1,182 @@
|
||||
"""
|
||||
Teacher Feedback Repository.
|
||||
|
||||
CRUD-Operationen fuer Lehrer-Feedback (Phase 7).
|
||||
Ermoeglicht Lehrern, Bugs, Feature-Requests und Verbesserungen zu melden.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from typing import Optional, List, Dict, Any
|
||||
|
||||
from sqlalchemy.orm import Session as DBSession
|
||||
|
||||
from .db_models import (
|
||||
TeacherFeedbackDB, FeedbackTypeEnum, FeedbackStatusEnum,
|
||||
FeedbackPriorityEnum,
|
||||
)
|
||||
|
||||
|
||||
class TeacherFeedbackRepository:
|
||||
"""
|
||||
Repository fuer Lehrer-Feedback CRUD-Operationen.
|
||||
|
||||
Ermoeglicht Lehrern, Feedback (Bugs, Feature-Requests, Verbesserungen)
|
||||
direkt aus dem Lehrer-Frontend zu senden.
|
||||
"""
|
||||
|
||||
def __init__(self, db: DBSession):
|
||||
self.db = db
|
||||
|
||||
def create(
|
||||
self,
|
||||
teacher_id: str,
|
||||
title: str,
|
||||
description: str,
|
||||
feedback_type: str = "improvement",
|
||||
priority: str = "medium",
|
||||
teacher_name: str = "",
|
||||
teacher_email: str = "",
|
||||
context_url: str = "",
|
||||
context_phase: str = "",
|
||||
context_session_id: str = None,
|
||||
user_agent: str = "",
|
||||
related_feature: str = None,
|
||||
) -> TeacherFeedbackDB:
|
||||
"""Erstellt neues Feedback."""
|
||||
import uuid
|
||||
|
||||
db_feedback = TeacherFeedbackDB(
|
||||
id=str(uuid.uuid4()),
|
||||
teacher_id=teacher_id,
|
||||
teacher_name=teacher_name,
|
||||
teacher_email=teacher_email,
|
||||
title=title,
|
||||
description=description,
|
||||
feedback_type=FeedbackTypeEnum(feedback_type),
|
||||
priority=FeedbackPriorityEnum(priority),
|
||||
status=FeedbackStatusEnum.NEW,
|
||||
related_feature=related_feature,
|
||||
context_url=context_url,
|
||||
context_phase=context_phase,
|
||||
context_session_id=context_session_id,
|
||||
user_agent=user_agent,
|
||||
)
|
||||
|
||||
self.db.add(db_feedback)
|
||||
self.db.commit()
|
||||
self.db.refresh(db_feedback)
|
||||
return db_feedback
|
||||
|
||||
def get_by_id(self, feedback_id: str) -> Optional[TeacherFeedbackDB]:
|
||||
"""Holt Feedback nach ID."""
|
||||
return self.db.query(TeacherFeedbackDB).filter(
|
||||
TeacherFeedbackDB.id == feedback_id
|
||||
).first()
|
||||
|
||||
def get_all(
|
||||
self,
|
||||
status: str = None,
|
||||
feedback_type: str = None,
|
||||
limit: int = 100,
|
||||
offset: int = 0
|
||||
) -> List[TeacherFeedbackDB]:
|
||||
"""Holt alle Feedbacks mit optionalen Filtern."""
|
||||
query = self.db.query(TeacherFeedbackDB)
|
||||
|
||||
if status:
|
||||
query = query.filter(TeacherFeedbackDB.status == FeedbackStatusEnum(status))
|
||||
if feedback_type:
|
||||
query = query.filter(TeacherFeedbackDB.feedback_type == FeedbackTypeEnum(feedback_type))
|
||||
|
||||
return query.order_by(
|
||||
TeacherFeedbackDB.created_at.desc()
|
||||
).offset(offset).limit(limit).all()
|
||||
|
||||
def get_by_teacher(self, teacher_id: str, limit: int = 50) -> List[TeacherFeedbackDB]:
|
||||
"""Holt Feedback eines bestimmten Lehrers."""
|
||||
return self.db.query(TeacherFeedbackDB).filter(
|
||||
TeacherFeedbackDB.teacher_id == teacher_id
|
||||
).order_by(
|
||||
TeacherFeedbackDB.created_at.desc()
|
||||
).limit(limit).all()
|
||||
|
||||
def update_status(
|
||||
self,
|
||||
feedback_id: str,
|
||||
status: str,
|
||||
response: str = None,
|
||||
responded_by: str = None
|
||||
) -> Optional[TeacherFeedbackDB]:
|
||||
"""Aktualisiert den Status eines Feedbacks."""
|
||||
db_feedback = self.get_by_id(feedback_id)
|
||||
if not db_feedback:
|
||||
return None
|
||||
|
||||
db_feedback.status = FeedbackStatusEnum(status)
|
||||
if response:
|
||||
db_feedback.response = response
|
||||
db_feedback.responded_at = datetime.utcnow()
|
||||
db_feedback.responded_by = responded_by
|
||||
|
||||
self.db.commit()
|
||||
self.db.refresh(db_feedback)
|
||||
return db_feedback
|
||||
|
||||
def delete(self, feedback_id: str) -> bool:
|
||||
"""Loescht ein Feedback."""
|
||||
db_feedback = self.get_by_id(feedback_id)
|
||||
if not db_feedback:
|
||||
return False
|
||||
|
||||
self.db.delete(db_feedback)
|
||||
self.db.commit()
|
||||
return True
|
||||
|
||||
def get_stats(self) -> Dict[str, Any]:
|
||||
"""Gibt Statistiken ueber alle Feedbacks zurueck."""
|
||||
all_feedback = self.db.query(TeacherFeedbackDB).all()
|
||||
|
||||
stats = {
|
||||
"total": len(all_feedback),
|
||||
"by_status": {},
|
||||
"by_type": {},
|
||||
"by_priority": {},
|
||||
}
|
||||
|
||||
for fb in all_feedback:
|
||||
# By Status
|
||||
status = fb.status.value
|
||||
stats["by_status"][status] = stats["by_status"].get(status, 0) + 1
|
||||
|
||||
# By Type
|
||||
fb_type = fb.feedback_type.value
|
||||
stats["by_type"][fb_type] = stats["by_type"].get(fb_type, 0) + 1
|
||||
|
||||
# By Priority
|
||||
priority = fb.priority.value
|
||||
stats["by_priority"][priority] = stats["by_priority"].get(priority, 0) + 1
|
||||
|
||||
return stats
|
||||
|
||||
def to_dict(self, db_feedback: TeacherFeedbackDB) -> Dict[str, Any]:
|
||||
"""Konvertiert DB-Model zu Dictionary."""
|
||||
return {
|
||||
"id": db_feedback.id,
|
||||
"teacher_id": db_feedback.teacher_id,
|
||||
"teacher_name": db_feedback.teacher_name,
|
||||
"teacher_email": db_feedback.teacher_email,
|
||||
"title": db_feedback.title,
|
||||
"description": db_feedback.description,
|
||||
"feedback_type": db_feedback.feedback_type.value,
|
||||
"priority": db_feedback.priority.value,
|
||||
"status": db_feedback.status.value,
|
||||
"related_feature": db_feedback.related_feature,
|
||||
"context_url": db_feedback.context_url,
|
||||
"context_phase": db_feedback.context_phase,
|
||||
"context_session_id": db_feedback.context_session_id,
|
||||
"user_agent": db_feedback.user_agent,
|
||||
"response": db_feedback.response,
|
||||
"responded_at": db_feedback.responded_at.isoformat() if db_feedback.responded_at else None,
|
||||
"responded_by": db_feedback.responded_by,
|
||||
"created_at": db_feedback.created_at.isoformat() if db_feedback.created_at else None,
|
||||
"updated_at": db_feedback.updated_at.isoformat() if db_feedback.updated_at else None,
|
||||
}
|
||||
Reference in New Issue
Block a user