from fastapi import HTTPException from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.asyncio import AsyncSession from department.models import Department from department.plugins import as_uuid,department_job_metrics,location_options from department.serializers import serialize_department,serialize_head_option from job.job_post.models import JobPosts from users.models import Users def serialize_department_name(row): return {"id":str(row.id),"name":row.name} class DepartmentService: def __init__(self,session:AsyncSession): self.session=session async def get_department_names(self,search): rows=await Department.get_department_names(self.session,search) return [serialize_department_name(row) for row in rows] async def _serialize_many(self,departments): head_names=await Users.names_by_ids(self.session,[d.department_head_id for d in departments]) parent_names=await Department.names_by_ids(self.session,[d.parent_department_id for d in departments]) job_rows=await Department.job_posts_for(self.session,[d.id for d in departments]) job_ids=list({str(r[1]) for r in job_rows}) applicants={} if job_ids: stats,_=await JobPosts.fetch_job_stats(self.session,ids=job_ids) applicants={str(row["job_post_id"]):row["total_applicants"] for row in stats} metrics=department_job_metrics(job_rows,applicants) return [ serialize_department( d, head_name=head_names.get(str(d.department_head_id)), parent_name=parent_names.get(d.parent_department_id), metrics=metrics.get(d.id), ) for d in departments ] async def get_department(self,record_id): department=await Department.get_by_id(self.session,record_id) if not department: raise HTTPException(status_code=404,detail="Department not found") return (await self._serialize_many([department]))[0] async def get_departments(self,top,skip,search,is_active): departments=await Department.get_departments(self.session,top,skip,search,is_active) total=await Department.count_departments(self.session,search,is_active) return await self._serialize_many(departments),total async def create_department(self,payload,user_id): actor=as_uuid(user_id) fields={**payload,"created_by":actor,"updated_by":actor} try: department=await Department.insert_department(self.session,fields) except IntegrityError as e: raise HTTPException(status_code=409,detail=str(e.orig)) from e return (await self._serialize_many([department]))[0] async def update_department(self,record_id,payload,user_id): fields={**payload,"updated_by":as_uuid(user_id)} try: department=await Department.update_department(self.session,record_id,fields) except IntegrityError as e: raise HTTPException(status_code=409,detail=str(e.orig)) from e if not department: raise HTTPException(status_code=404,detail="Department not found") return (await self._serialize_many([department]))[0] async def get_head_options(self,role_id,top,skip,search): rows=await Users.get_users(self.session,top,skip,search,role_id) return [serialize_head_option(row) for row in rows] async def get_location_options(self,search): return location_options(search)