diff --git a/src/template_project/web_api/routes/resume.py b/src/template_project/web_api/routes/resume.py index 093b081..c0ae4c4 100644 --- a/src/template_project/web_api/routes/resume.py +++ b/src/template_project/web_api/routes/resume.py @@ -11,10 +11,10 @@ router = APIRouter(route_class=DishkaRoute, tags=["Resume"], dependencies=[Depen class ExperienceTypeEnum(StrEnum): - NO_EXPERIENCE = "no_experience" - BETWEEN_1_AND_3 = "between_1_and_3" - BETWEEN_3_AND_6 = "between_3_and_6" - MORE_THAN_6 = "more_than_6" + NO_EXPERIENCE = "noExperience" + BETWEEN_1_AND_3 = "between1And3" + BETWEEN_3_AND_6 = "between3And6" + MORE_THAN_6 = "moreThan6" class CreateResumeRequest(BaseModel): @@ -28,6 +28,11 @@ class CreateResumeRequest(BaseModel): experience_type: ExperienceTypeEnum = Field( ..., 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 = { "json_schema_extra": { @@ -35,7 +40,8 @@ class CreateResumeRequest(BaseModel): "position": "Python Developer", "about_me": "Experienced Python developer with 5 years of experience", "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", "about_me": "Experienced Python developer with 5 years of experience", "key_skills": ["Python", "FastAPI", "PostgreSQL", "Docker"], - "experience_type": "between_3_and_6", + "experience_type": "between3And6", "prediction": { "from_salary": "100000", "to_salary": "150000", @@ -101,7 +107,7 @@ class ResumeListItem(BaseModel): "position": "Python Developer", "about_me": "Experienced Python developer with 5 years of experience", "key_skills": ["Python", "FastAPI", "PostgreSQL"], - "experience_type": "between_3_and_6", + "experience_type": "between3And6", } } } @@ -123,7 +129,7 @@ class GetResumeListResponse(BaseModel): "position": "Python Developer", "about_me": "Experienced Python developer", "key_skills": ["Python", "FastAPI"], - "experience_type": "between_3_and_6", + "experience_type": "between3And6", } ] } @@ -147,7 +153,7 @@ class GetResumeHistoryResponse(BaseModel): "position": "Python Developer", "about_me": "Experienced Python developer", "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( - resume_id: str = Field(..., description="Resume ID"), + resume_id: str, ) -> ResumeResponse: # TODO: Implement resume retrieval raise NotImplementedError @@ -205,6 +211,50 @@ async def get_resume_list( 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( "/resume/{resume_id}/history", summary="Get resume history", @@ -216,9 +266,27 @@ async def get_resume_list( }, ) 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]), offset: int = Query(..., ge=0, description="Number of history items to skip", examples=[0]), ) -> GetResumeHistoryResponse: # TODO: Implement resume history retrieval 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 diff --git a/tests/web_api/e2e/test_auth.py b/tests/web_api/e2e/test_auth.py index a14fd4e..5a9d48a 100644 --- a/tests/web_api/e2e/test_auth.py +++ b/tests/web_api/e2e/test_auth.py @@ -28,9 +28,7 @@ async def test_email_sign_up_creates_user( password=DEFAULT_PASSWORD, ) assert is_success_response(response) - assert response.json() == IsPartialDict( - access_token=IsStr() - ) + assert response.json() == IsPartialDict(access_token=IsStr()) @inject diff --git a/tests/web_api/e2e/test_healthcheck.py b/tests/web_api/e2e/test_healthcheck.py index 03b60e7..fb9035d 100644 --- a/tests/web_api/e2e/test_healthcheck.py +++ b/tests/web_api/e2e/test_healthcheck.py @@ -12,8 +12,6 @@ async def test_healthcheck( ) -> None: response = await http_client.get("/healthcheck") assert is_success_response(response) - assert response.json() == IsDict( - { - "ok": True, - } - ) + assert response.json() == IsDict({ + "ok": True, + })