fix(): update schemas

This commit is contained in:
gitgernit
2025-11-23 04:25:59 +03:00
parent d1c7641698
commit f92e3d3372
3 changed files with 258 additions and 33 deletions
@@ -136,35 +136,89 @@ class ResumeListItemResponse:
about_me: str
key_skills: list[str]
experience_type: ExperienceType
experience: list[ExperienceItemResponse]
education: list[EducationItemResponse]
projects: list[ProjectItemResponse]
prediction: ResumePredictionResponse | None
@to_interactor
class GetResumeListInteractor:
identity_provider: IdentityProvider
resume_data_gateway: ResumeDataGateway
resume_prediction_data_gateway: ResumePredictionDataGateway
resume_experience_data_gateway: ResumeExperienceDataGateway
resume_education_data_gateway: ResumeEducationDataGateway
resume_project_data_gateway: ResumeProjectDataGateway
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_latest_by_user_id(user.id, limit=limit, offset=offset)
return [
ResumeListItemResponse(
id=r.id,
position=r.position,
location=r.location,
about_me=r.about_me,
key_skills=r.key_skills,
experience_type=r.experience_type,
result = []
for r in resumes:
resume_prediction = await self.resume_prediction_data_gateway.load_by_resume_id(r.id)
if resume_prediction is not None:
prediction = ResumePredictionResponse(
from_salary=resume_prediction.from_salary,
to_salary=resume_prediction.to_salary,
recommended_skills=resume_prediction.recommended_skills,
)
else:
prediction = None
experiences = await self.resume_experience_data_gateway.load_by_resume_id(r.id)
educations = await self.resume_education_data_gateway.load_by_resume_id(r.id)
projects = await self.resume_project_data_gateway.load_by_resume_id(r.id)
result.append(
ResumeListItemResponse(
id=r.id,
position=r.position,
location=r.location,
about_me=r.about_me,
key_skills=r.key_skills,
experience_type=r.experience_type,
experience=[
ExperienceItemResponse(
place=exp.place,
description=exp.description,
months_duration=exp.months_duration,
)
for exp in experiences
],
education=[
EducationItemResponse(
place=edu.place,
grade=edu.grade,
specialization=edu.specialization,
description=edu.description,
)
for edu in educations
],
projects=[
ProjectItemResponse(
name=proj.name,
description=proj.description,
)
for proj in projects
],
prediction=prediction,
)
)
for r in resumes
]
return result
@to_interactor
class GetResumeHistoryInteractor:
identity_provider: IdentityProvider
resume_data_gateway: ResumeDataGateway
resume_prediction_data_gateway: ResumePredictionDataGateway
resume_experience_data_gateway: ResumeExperienceDataGateway
resume_education_data_gateway: ResumeEducationDataGateway
resume_project_data_gateway: ResumeProjectDataGateway
async def execute(self, resume_id: ResumeId) -> list[ResumeListItemResponse]:
user = await self.identity_provider.get_current_user()
@@ -177,14 +231,56 @@ class GetResumeHistoryInteractor:
history = await self.resume_data_gateway.get_history(resume_id)
return [
ResumeListItemResponse(
id=r.id,
position=r.position,
location=r.location,
about_me=r.about_me,
key_skills=r.key_skills,
experience_type=r.experience_type,
result = []
for r in history:
resume_prediction = await self.resume_prediction_data_gateway.load_by_resume_id(r.id)
if resume_prediction is not None:
prediction = ResumePredictionResponse(
from_salary=resume_prediction.from_salary,
to_salary=resume_prediction.to_salary,
recommended_skills=resume_prediction.recommended_skills,
)
else:
prediction = None
experiences = await self.resume_experience_data_gateway.load_by_resume_id(r.id)
educations = await self.resume_education_data_gateway.load_by_resume_id(r.id)
projects = await self.resume_project_data_gateway.load_by_resume_id(r.id)
result.append(
ResumeListItemResponse(
id=r.id,
position=r.position,
location=r.location,
about_me=r.about_me,
key_skills=r.key_skills,
experience_type=r.experience_type,
experience=[
ExperienceItemResponse(
place=exp.place,
description=exp.description,
months_duration=exp.months_duration,
)
for exp in experiences
],
education=[
EducationItemResponse(
place=edu.place,
grade=edu.grade,
specialization=edu.specialization,
description=edu.description,
)
for edu in educations
],
projects=[
ProjectItemResponse(
name=proj.name,
description=proj.description,
)
for proj in projects
],
prediction=prediction,
)
)
for r in history
]
return result
@@ -41,23 +41,21 @@ def _filter_and_sort_vacancies(
suitable_vacancies: list[SuitableVacancy],
limit: int = 50,
) -> list[SuitableVacancy]:
def is_suitable(vacancy: SuitableVacancy) -> bool:
experience_match = resume.experience_type == vacancy.vacancy.experience_type
skills_matching = _calculate_skills_matching(resume.key_skills, vacancy.vacancy.key_skills)
skills_match = skills_matching >= 0.5
return experience_match and skills_match
def calculate_priority(vacancy: SuitableVacancy) -> float:
priority = vacancy.resume_similarity
filtered = [v for v in suitable_vacancies if is_suitable(v)]
if resume.experience_type == vacancy.vacancy.experience_type:
priority += 0.1
if len(filtered) >= limit:
filtered.sort(key=lambda v: v.resume_similarity, reverse=True)
return filtered[:limit]
if resume.key_skills:
skills_matching = _calculate_skills_matching(resume.key_skills, vacancy.vacancy.key_skills)
priority += skills_matching * 0.2
remaining = [v for v in suitable_vacancies if v not in filtered]
remaining.sort(key=lambda v: v.resume_similarity, reverse=True)
return priority
total_needed = limit - len(filtered)
return filtered + remaining[:total_needed]
sorted_vacancies = sorted(suitable_vacancies, key=calculate_priority, reverse=True)
return sorted_vacancies[:limit]
@to_data_structure
@@ -227,6 +227,10 @@ class ResumeListItem(BaseModel):
about_me: str = Field(description="About me section")
key_skills: list[str] = Field(description="List of key skills")
experience_type: ExperienceType = Field(description="Experience type")
experience: list[ExperienceItem] = Field(description="Work experience list")
education: list[EducationItem] = Field(description="Education list")
projects: list[ProjectItem] = Field(description="Projects list")
prediction: SalaryPrediction | None = Field(None, description="Salary prediction (can be null)")
model_config = {
"json_schema_extra": {
@@ -236,6 +240,27 @@ class ResumeListItem(BaseModel):
"about_me": "Experienced Python developer with 5 years of experience",
"key_skills": ["Python", "FastAPI", "PostgreSQL"],
"experience_type": "between3And6",
"experience": [
{
"place": "T-bank",
"description": "some description lorem ipsum",
"months_duration": 12,
}
],
"education": [
{
"place": "Central university",
"grade": "bachelor",
"specialization": "IT guy",
"description": "optional field, if user want add something",
}
],
"projects": [
{
"name": "Rekomenci fluon",
"description": "fucking shit",
}
],
}
}
}
@@ -255,9 +280,31 @@ class GetResumeListResponse(BaseModel):
"resumes": [
{
"position": "Python Developer",
"location": "Moscow",
"about_me": "Experienced Python developer",
"key_skills": ["Python", "FastAPI"],
"experience_type": "between3And6",
"experience": [
{
"place": "T-bank",
"description": "some description lorem ipsum",
"months_duration": 12,
}
],
"education": [
{
"place": "Central university",
"grade": "bachelor",
"specialization": "IT guy",
"description": "optional field, if user want add something",
}
],
"projects": [
{
"name": "Rekomenci fluon",
"description": "fucking shit",
}
],
}
]
}
@@ -279,9 +326,31 @@ class GetResumeHistoryResponse(BaseModel):
"resumes": [
{
"position": "Python Developer",
"location": "Moscow",
"about_me": "Experienced Python developer",
"key_skills": ["Python", "FastAPI"],
"experience_type": "between3And6",
"experience": [
{
"place": "T-bank",
"description": "some description lorem ipsum",
"months_duration": 12,
}
],
"education": [
{
"place": "Central university",
"grade": "bachelor",
"specialization": "IT guy",
"description": "optional field, if user want add something",
}
],
"projects": [
{
"name": "Rekomenci fluon",
"description": "fucking shit",
}
],
}
]
}
@@ -379,6 +448,37 @@ async def get_resume_list(
about_me=r.about_me,
key_skills=r.key_skills,
experience_type=r.experience_type,
experience=[
ExperienceItem(
place=exp.place,
description=exp.description,
months_duration=exp.months_duration,
)
for exp in r.experience
],
education=[
EducationItem(
place=edu.place,
grade=edu.grade,
specialization=edu.specialization,
description=edu.description,
)
for edu in r.education
],
projects=[
ProjectItem(
name=proj.name,
description=proj.description,
)
for proj in r.projects
],
prediction=SalaryPrediction(
from_salary=r.prediction.from_salary,
to_salary=r.prediction.to_salary,
recommended_skills=r.prediction.recommended_skills,
)
if r.prediction is not None
else None,
)
for r in interactor_response
]
@@ -588,6 +688,37 @@ async def get_resume_history(
about_me=r.about_me,
key_skills=r.key_skills,
experience_type=r.experience_type,
experience=[
ExperienceItem(
place=exp.place,
description=exp.description,
months_duration=exp.months_duration,
)
for exp in r.experience
],
education=[
EducationItem(
place=edu.place,
grade=edu.grade,
specialization=edu.specialization,
description=edu.description,
)
for edu in r.education
],
projects=[
ProjectItem(
name=proj.name,
description=proj.description,
)
for proj in r.projects
],
prediction=SalaryPrediction(
from_salary=r.prediction.from_salary,
to_salary=r.prediction.to_salary,
recommended_skills=r.prediction.recommended_skills,
)
if r.prediction is not None
else None,
)
for r in interactor_response
]