feat(): openapi docs for resume

This commit is contained in:
gitgernit
2025-11-21 22:25:36 +03:00
parent 44b10a1a03
commit 8fb00d5293
3 changed files with 83 additions and 19 deletions
+79 -11
View File
@@ -11,10 +11,10 @@ router = APIRouter(route_class=DishkaRoute, tags=["Resume"], dependencies=[Depen
class ExperienceTypeEnum(StrEnum): class ExperienceTypeEnum(StrEnum):
NO_EXPERIENCE = "no_experience" NO_EXPERIENCE = "noExperience"
BETWEEN_1_AND_3 = "between_1_and_3" BETWEEN_1_AND_3 = "between1And3"
BETWEEN_3_AND_6 = "between_3_and_6" BETWEEN_3_AND_6 = "between3And6"
MORE_THAN_6 = "more_than_6" MORE_THAN_6 = "moreThan6"
class CreateResumeRequest(BaseModel): class CreateResumeRequest(BaseModel):
@@ -28,6 +28,11 @@ class CreateResumeRequest(BaseModel):
experience_type: ExperienceTypeEnum = Field( experience_type: ExperienceTypeEnum = Field(
..., description="Experience type", examples=[ExperienceTypeEnum.BETWEEN_3_AND_6] ..., description="Experience type", examples=[ExperienceTypeEnum.BETWEEN_3_AND_6]
) )
parent_resume_id: str | None = Field(
None,
description="ID of parent resume (for creating resume from existing one)",
examples=["01234567-89ab-cdef-0123-456789abcdef"],
)
model_config = { model_config = {
"json_schema_extra": { "json_schema_extra": {
@@ -35,7 +40,8 @@ class CreateResumeRequest(BaseModel):
"position": "Python Developer", "position": "Python Developer",
"about_me": "Experienced Python developer with 5 years of experience", "about_me": "Experienced Python developer with 5 years of experience",
"key_skills": ["Python", "FastAPI", "PostgreSQL", "Docker"], "key_skills": ["Python", "FastAPI", "PostgreSQL", "Docker"],
"experience_type": "between_3_and_6", "experience_type": "between3And6",
"parent_resume_id": None,
} }
} }
} }
@@ -78,7 +84,7 @@ class ResumeResponse(BaseModel):
"position": "Python Developer", "position": "Python Developer",
"about_me": "Experienced Python developer with 5 years of experience", "about_me": "Experienced Python developer with 5 years of experience",
"key_skills": ["Python", "FastAPI", "PostgreSQL", "Docker"], "key_skills": ["Python", "FastAPI", "PostgreSQL", "Docker"],
"experience_type": "between_3_and_6", "experience_type": "between3And6",
"prediction": { "prediction": {
"from_salary": "100000", "from_salary": "100000",
"to_salary": "150000", "to_salary": "150000",
@@ -101,7 +107,7 @@ class ResumeListItem(BaseModel):
"position": "Python Developer", "position": "Python Developer",
"about_me": "Experienced Python developer with 5 years of experience", "about_me": "Experienced Python developer with 5 years of experience",
"key_skills": ["Python", "FastAPI", "PostgreSQL"], "key_skills": ["Python", "FastAPI", "PostgreSQL"],
"experience_type": "between_3_and_6", "experience_type": "between3And6",
} }
} }
} }
@@ -123,7 +129,7 @@ class GetResumeListResponse(BaseModel):
"position": "Python Developer", "position": "Python Developer",
"about_me": "Experienced Python developer", "about_me": "Experienced Python developer",
"key_skills": ["Python", "FastAPI"], "key_skills": ["Python", "FastAPI"],
"experience_type": "between_3_and_6", "experience_type": "between3And6",
} }
] ]
} }
@@ -147,7 +153,7 @@ class GetResumeHistoryResponse(BaseModel):
"position": "Python Developer", "position": "Python Developer",
"about_me": "Experienced Python developer", "about_me": "Experienced Python developer",
"key_skills": ["Python", "FastAPI"], "key_skills": ["Python", "FastAPI"],
"experience_type": "between_3_and_6", "experience_type": "between3And6",
} }
] ]
} }
@@ -182,7 +188,7 @@ async def create_resume(
}, },
) )
async def get_resume( async def get_resume(
resume_id: str = Field(..., description="Resume ID"), resume_id: str,
) -> ResumeResponse: ) -> ResumeResponse:
# TODO: Implement resume retrieval # TODO: Implement resume retrieval
raise NotImplementedError raise NotImplementedError
@@ -205,6 +211,50 @@ async def get_resume_list(
raise NotImplementedError raise NotImplementedError
class PatchResumeRequest(BaseModel):
position: str | None = Field(
None, min_length=1, max_length=200, description="Job position", examples=["Python Developer"]
)
about_me: str | None = Field(
None, min_length=1, max_length=2000, description="About me section", examples=["Experienced Python developer"]
)
key_skills: list[str] | None = Field(
None, min_length=1, description="List of key skills", examples=[["Python", "FastAPI", "PostgreSQL"]]
)
experience_type: ExperienceTypeEnum | None = Field(
None, description="Experience type", examples=[ExperienceTypeEnum.BETWEEN_3_AND_6]
)
model_config = {
"json_schema_extra": {
"example": {
"position": "Python Developer",
"about_me": "Experienced Python developer with 5 years of experience",
"key_skills": ["Python", "FastAPI", "PostgreSQL", "Docker"],
"experience_type": "between3And6",
}
}
}
class PatchResumeResponse(BaseModel):
position: str = Field(..., description="Job position")
about_me: str = Field(..., description="About me section")
key_skills: list[str] = Field(..., description="List of key skills")
experience_type: ExperienceTypeEnum = Field(..., description="Experience type")
model_config = {
"json_schema_extra": {
"example": {
"position": "Python Developer",
"about_me": "Experienced Python developer with 5 years of experience",
"key_skills": ["Python", "FastAPI", "PostgreSQL", "Docker"],
"experience_type": "between3And6",
}
}
}
@router.get( @router.get(
"/resume/{resume_id}/history", "/resume/{resume_id}/history",
summary="Get resume history", summary="Get resume history",
@@ -216,9 +266,27 @@ async def get_resume_list(
}, },
) )
async def get_resume_history( async def get_resume_history(
resume_id: str = Field(..., description="Resume ID"), resume_id: str,
limit: int = Query(..., ge=1, le=100, description="Number of history items to return", examples=[10]), limit: int = Query(..., ge=1, le=100, description="Number of history items to return", examples=[10]),
offset: int = Query(..., ge=0, description="Number of history items to skip", examples=[0]), offset: int = Query(..., ge=0, description="Number of history items to skip", examples=[0]),
) -> GetResumeHistoryResponse: ) -> GetResumeHistoryResponse:
# TODO: Implement resume history retrieval # TODO: Implement resume history retrieval
raise NotImplementedError raise NotImplementedError
@router.patch(
"/resume/{resume_id}",
summary="Update resume",
description="Update resume fields. All fields are optional.",
responses={
200: {"description": "Resume updated successfully", "model": PatchResumeResponse},
401: {"description": "Unauthorized - invalid or missing token"},
404: {"description": "Resume not found"},
},
)
async def patch_resume(
resume_id: str,
request: PatchResumeRequest,
) -> PatchResumeResponse:
# TODO: Implement resume update
raise NotImplementedError
+1 -3
View File
@@ -28,9 +28,7 @@ async def test_email_sign_up_creates_user(
password=DEFAULT_PASSWORD, password=DEFAULT_PASSWORD,
) )
assert is_success_response(response) assert is_success_response(response)
assert response.json() == IsPartialDict( assert response.json() == IsPartialDict(access_token=IsStr())
access_token=IsStr()
)
@inject @inject
+3 -5
View File
@@ -12,8 +12,6 @@ async def test_healthcheck(
) -> None: ) -> None:
response = await http_client.get("/healthcheck") response = await http_client.get("/healthcheck")
assert is_success_response(response) assert is_success_response(response)
assert response.json() == IsDict( assert response.json() == IsDict({
{ "ok": True,
"ok": True, })
}
)