Signed-off-by: ITQ <itq.dev@ya.ru>
This commit is contained in:
ITQ
2025-11-22 10:58:19 +03:00
parent fc52561154
commit e24a3882a6
5 changed files with 68 additions and 7 deletions
@@ -8,6 +8,7 @@ from template_project.adapters.data_gateways.tables import resume_prediction_tab
from template_project.application.resume.data_gateway import ResumeDataGateway, ResumePredictionDataGateway
from template_project.application.resume.entity import Resume, ResumeEmbeddingId, ResumeId, ResumePrediction
from template_project.application.resume.errors import ResumeNotFoundError
from template_project.application.user.entity import UserId
class DefaultResumeDataGateway(ResumeDataGateway):
@@ -26,6 +27,17 @@ class DefaultResumeDataGateway(ResumeDataGateway):
return resume
@override
async def list_by_user_id(self, user_id: UserId, limit: int, offset: int) -> Sequence[Resume]:
statement = (
select(Resume)
.where(Resume.user_id == user_id)
.limit(limit)
.offset(offset)
)
result = await self._session.execute(statement)
return result.scalars().all()
class DefaultResumePredictionDataGateway(ResumePredictionDataGateway):
def __init__(self, session: AsyncSession) -> None:
@@ -8,6 +8,7 @@ from template_project.application.resume.entity import (
ResumeId,
ResumePrediction,
)
from template_project.application.user.entity import UserId
class ResumeDataGateway(Protocol):
@@ -19,6 +20,10 @@ class ResumeDataGateway(Protocol):
async def load(self, resume_id: ResumeId) -> Resume:
raise NotImplementedError
@abstractmethod
async def list_by_user_id(self, user_id: UserId, limit: int, offset: int) -> Sequence[Resume]:
raise NotImplementedError
class ResumePredictionDataGateway(Protocol):
@abstractmethod
@@ -61,3 +61,32 @@ class GetResumeInteractor:
experience_type=resume.experience_type,
prediction=prediction,
)
@to_data_structure
class ResumeListItemResponse:
position: str
about_me: str
key_skills: list[str]
experience_type: ExperienceType
@to_interactor
class GetResumeListInteractor:
identity_provider: IdentityProvider
resume_data_gateway: ResumeDataGateway
async def execute(self, limit: int, offset: int) -> list[ResumeListItemResponse]:
user = await self.identity_provider.get_current_user()
resumes = await self.resume_data_gateway.list_by_user_id(user.id, limit=limit, offset=offset)
return [
ResumeListItemResponse(
position=r.position,
about_me=r.about_me,
key_skills=r.key_skills,
experience_type=r.experience_type,
)
for r in resumes
]
@@ -31,7 +31,7 @@ def suitable_resumes_key(
return wrapper
class ResumeEmbeddingPipline:
class ResumeEmbeddingPipeline:
def __init__(
self,
unit_of_work: UnitOfWork,
+21 -6
View File
@@ -12,8 +12,11 @@ from template_project.application.common.enums import ExperienceType
from template_project.application.resume.entity import ResumeId
from template_project.application.resume.errors import ResumeDoesBelongUserError, ResumeNotFoundError
from template_project.application.resume.interactors.add import AddResumeInteractor
from template_project.application.resume.interactors.edit import EditResumeInteractor
from template_project.application.resume.interactors.get import GetResumeInteractor
from template_project.application.resume.interactors.get import (
GetResumeInteractor,
GetResumeListInteractor,
ResumeListItemResponse,
)
security = HTTPBearer()
router = APIRouter(route_class=DishkaRoute, tags=["Resume"], dependencies=[Depends(security)])
@@ -192,11 +195,23 @@ async def create_resume(
},
)
async def get_resume_list(
limit: Annotated[int, Query(ge=1, le=100, description="Number of resumes to return", examples=[10])],
offset: Annotated[int, Query(ge=0, description="Number of resumes to skip", examples=[0])],
limit: Annotated[int, Query(ge=1, le=100)],
offset: Annotated[int, Query(ge=0)],
interactor: FromDishka[GetResumeListInteractor],
) -> GetResumeListResponse:
# TODO: Implement resume list retrieval
raise NotImplementedError
interactor_response: list[ResumeListItemResponse] = await interactor.execute(limit=limit, offset=offset)
return GetResumeListResponse(
resumes=[
ResumeListItem(
position=i.position,
about_me=i.about_me,
key_skills=i.key_skills,
experience_type=i.experience_type,
)
for i in interactor_response
]
)
@router.get(