from fastapi import HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from sqlmodel import select from job.candidate.models import Feedback from job.feedback.models import FeedbackTemplates from job.feedback.serializers import serialize_feedback, serialize_feedback_template class FeedbackView: def __init__(self,session:AsyncSession): self.session=session async def _load(self,record_id): uid=Feedback._as_uuid(record_id) if uid is None: return None result=await self.session.execute( select(Feedback).options(selectinload(Feedback.user)).where(Feedback.id==uid) ) return result.scalars().first() async def get_feedback(self,feedback_id=None,inbox_id=None): if feedback_id: row=await self._load(feedback_id) if not row: raise HTTPException(status_code=404,detail="Feedback not found") return serialize_feedback(row) if inbox_id is None: raise HTTPException(status_code=400,detail="feedback_id or inbox_id is required") result=await self.session.execute( select(Feedback) .options(selectinload(Feedback.user)) .where(Feedback.inbox_id==int(inbox_id)) .order_by(Feedback.created_at.desc()) ) return [serialize_feedback(r) for r in result.scalars().all()] async def create_feedback(self,payload,current_user): fields={ "review":payload.get("review") or "", "financial_status":payload.get("financial_status") or "", "score":payload.get("score") if payload.get("score") is not None else 0.0, "note":payload.get("note"), "inbox_id":payload.get("inbox_id"), "reviewed_by":payload.get("reviewed_by") or ( current_user.get("id") if isinstance(current_user,dict) else None ), } row=await Feedback.insert_feedback(self.session,fields) row=await self._load(row.id) return serialize_feedback(row) async def update_feedback(self,feedback_id,payload): allowed=("review","financial_status","score","note","inbox_id","reviewed_by") fields={k:v for k,v in payload.items() if v is not None and k in allowed} if not fields: raise HTTPException(status_code=400,detail="No fields to update") row=await Feedback.update_feedback(self.session,feedback_id,fields) if not row: raise HTTPException(status_code=404,detail="Feedback not found") row=await self._load(row.id) return serialize_feedback(row) async def get_templates(self): rows,total=await FeedbackTemplates.fetch_templates(self.session) return [serialize_feedback_template(r) for r in rows],total async def create_template(self,payload,current_user): name=(payload.get("name") or "").strip() if not name: raise HTTPException(status_code=422,detail="name is required") criteria=payload.get("criteria") or [] if not isinstance(criteria,list) or not all(isinstance(c,str) for c in criteria): raise HTTPException(status_code=422,detail="criteria must be a list of strings") fields={ "name":name, "department":payload.get("department"), "criteria":[c.strip() for c in criteria if str(c).strip()], "is_active":payload.get("is_active") if payload.get("is_active") is not None else True, "created_by":current_user.get("id") if isinstance(current_user,dict) else None, } row=await FeedbackTemplates.insert_template(self.session,fields) return serialize_feedback_template(row) async def update_template(self,template_id,payload): allowed=("name","department","criteria","is_active") fields={} for key in allowed: if key not in payload: continue value=payload[key] if key=="name": value=(value or "").strip() if not value: raise HTTPException(status_code=422,detail="name cannot be blank") elif key=="criteria": if value is not None and (not isinstance(value,list) or not all(isinstance(c,str) for c in value)): raise HTTPException(status_code=422,detail="criteria must be a list of strings") value=[c.strip() for c in (value or []) if str(c).strip()] fields[key]=value if not fields: raise HTTPException(status_code=400,detail="No fields to update") row=await FeedbackTemplates.update_template(self.session,template_id,fields) if not row: raise HTTPException(status_code=404,detail="Template not found") return serialize_feedback_template(row) async def delete_template(self,template_id): row=await FeedbackTemplates.soft_delete_template(self.session,template_id) if not row: raise HTTPException(status_code=404,detail="Template not found") return {"id":str(row.id),"deleted":True}