diff --git a/huntflow_api_client/entities/applicant_on_vacancy.py b/huntflow_api_client/entities/applicant_on_vacancy.py index e65e574..75bbf60 100644 --- a/huntflow_api_client/entities/applicant_on_vacancy.py +++ b/huntflow_api_client/entities/applicant_on_vacancy.py @@ -77,6 +77,6 @@ async def move_applicant_to_child_vacancy( response = await self._api.request( "PUT", f"/accounts/{account_id}/applicants/vacancy/{vacancy_id}/split", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return ApplicantVacancySplitResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/applicants.py b/huntflow_api_client/entities/applicants.py index c05e218..d959cf2 100644 --- a/huntflow_api_client/entities/applicants.py +++ b/huntflow_api_client/entities/applicants.py @@ -6,7 +6,7 @@ GetEntityMixin, ListEntityMixin, ) -from huntflow_api_client.models.consts import AgreementState, ApplicantSearchField +from huntflow_api_client.models.consts import AgreementStateRequest, ApplicantSearchField from huntflow_api_client.models.request.applicants import ( ApplicantCreateRequest, ApplicantUpdateRequest, @@ -29,7 +29,7 @@ async def list( page: Optional[int] = 1, status: Optional[int] = None, vacancy_id: Optional[int] = None, - agreement_state: Optional[AgreementState] = None, + agreement_state: Optional[AgreementStateRequest] = None, ) -> ApplicantListResponse: """ API method reference https://api.huntflow.ai/v2/docs#get-/accounts/-account_id-/applicants diff --git a/huntflow_api_client/entities/dictionaries.py b/huntflow_api_client/entities/dictionaries.py index 43e3c32..ce9f0c9 100644 --- a/huntflow_api_client/entities/dictionaries.py +++ b/huntflow_api_client/entities/dictionaries.py @@ -43,7 +43,11 @@ async def create( :return: An object that contains the task ID of the delayed background update task """ path = f"/accounts/{account_id}/dictionaries" - response = await self._api.request("POST", path, json=data.jsonable_dict(exclude_none=True)) + response = await self._api.request( + "POST", + path, + json=data.jsonable_dict(exclude_unset=True), + ) return DictionaryTaskResponse.model_validate(response.json()) async def get(self, account_id: int, dict_code: str) -> DictionaryResponse: @@ -75,5 +79,5 @@ async def update( :return: An object that contains the task ID of the delayed background update task """ path = f"/accounts/{account_id}/dictionaries/{dict_code}" - response = await self._api.request("PUT", path, json=data.jsonable_dict(exclude_none=True)) + response = await self._api.request("PUT", path, json=data.jsonable_dict(exclude_unset=True)) return DictionaryTaskResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/multi_vacancies.py b/huntflow_api_client/entities/multi_vacancies.py index 8f809b5..bc13e6e 100644 --- a/huntflow_api_client/entities/multi_vacancies.py +++ b/huntflow_api_client/entities/multi_vacancies.py @@ -26,7 +26,7 @@ async def create( response = await self._api.request( "POST", f"/accounts/{account_id}/multi-vacancies", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return MultiVacancyResponse.model_validate(response.json()) @@ -52,6 +52,6 @@ async def update( response = await self._api.request( method, f"/accounts/{account_id}/multi-vacancies/{vacancy_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return MultiVacancyResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/production_calendars.py b/huntflow_api_client/entities/production_calendars.py index c27536a..26bdbeb 100644 --- a/huntflow_api_client/entities/production_calendars.py +++ b/huntflow_api_client/entities/production_calendars.py @@ -55,7 +55,7 @@ async def get_non_working_days_in_period( calendar_id: int, deadline: datetime.date, start: Optional[datetime.date] = None, - verbose: Optional[bool] = True, + verbose: Optional[bool] = False, ) -> NonWorkingDaysResponse: """ API method reference diff --git a/huntflow_api_client/entities/resume.py b/huntflow_api_client/entities/resume.py index e664937..899ba52 100644 --- a/huntflow_api_client/entities/resume.py +++ b/huntflow_api_client/entities/resume.py @@ -83,7 +83,7 @@ async def update( response = await self._api.request( "PUT", f"/accounts/{account_id}/applicants/{applicant_id}/externals/{external_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) return ApplicantResumeResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/tags.py b/huntflow_api_client/entities/tags.py index d4cc948..fa86f41 100644 --- a/huntflow_api_client/entities/tags.py +++ b/huntflow_api_client/entities/tags.py @@ -43,7 +43,7 @@ async def create( response = await self._api.request( "POST", f"/accounts/{account_id}/tags", - json=account_tag.jsonable_dict(exclude_none=True), + json=account_tag.jsonable_dict(), ) return AccountTagResponse.model_validate(response.json()) @@ -65,7 +65,7 @@ async def update( response = await self._api.request( "PUT", f"/accounts/{account_id}/tags/{account_tag_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) return AccountTagResponse.model_validate(response.json()) @@ -112,7 +112,7 @@ async def update( response = await self._api.request( "POST", f"/accounts/{account_id}/applicants/{applicant_id}/tags", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) return ApplicantTagsListResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/vacancies.py b/huntflow_api_client/entities/vacancies.py index c0248de..acea6b6 100644 --- a/huntflow_api_client/entities/vacancies.py +++ b/huntflow_api_client/entities/vacancies.py @@ -96,7 +96,7 @@ async def create(self, account_id: int, data: VacancyCreateRequest) -> VacancyCr response = await self._api.request( "POST", f"/accounts/{account_id}/vacancies", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return VacancyCreateResponse.model_validate(response.json()) @@ -118,7 +118,7 @@ async def update( response = await self._api.request( "PUT", f"/accounts/{account_id}/vacancies/{vacancy_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return VacancyResponse.model_validate(response.json()) @@ -150,7 +150,7 @@ async def patch( response = await self._api.request( "PATCH", f"/accounts/{account_id}/vacancies/{vacancy_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return VacancyResponse.model_validate(response.json()) @@ -174,7 +174,7 @@ async def assign_coworker( response = await self._api.request( "PUT", f"/accounts/{account_id}/vacancies/{vacancy_id}/members/{account_member_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) return StatusResponse.model_validate(response.json()) @@ -304,7 +304,7 @@ async def close(self, account_id: int, vacancy_id: int, data: VacancyCloseReques await self._api.request( "POST", f"/accounts/{account_id}/vacancies/{vacancy_id}/state/close", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) async def hold(self, account_id: int, vacancy_id: int, data: VacancyHoldRequest) -> None: @@ -319,7 +319,7 @@ async def hold(self, account_id: int, vacancy_id: int, data: VacancyHoldRequest) await self._api.request( "POST", f"/accounts/{account_id}/vacancies/{vacancy_id}/state/hold", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) async def resume(self, account_id: int, vacancy_id: int) -> None: diff --git a/huntflow_api_client/entities/vacancy_requests.py b/huntflow_api_client/entities/vacancy_requests.py index b89eccb..f818946 100644 --- a/huntflow_api_client/entities/vacancy_requests.py +++ b/huntflow_api_client/entities/vacancy_requests.py @@ -76,6 +76,6 @@ async def create( response = await self._api.request( "POST", path, - json=request_data.jsonable_dict(exclude_none=True), + json=request_data.jsonable_dict(exclude_unset=True), ) return VacancyRequestResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/webhooks.py b/huntflow_api_client/entities/webhooks.py index daa0106..a60d204 100644 --- a/huntflow_api_client/entities/webhooks.py +++ b/huntflow_api_client/entities/webhooks.py @@ -41,7 +41,7 @@ async def create(self, account_id: int, data: WebhookRequest) -> WebhookResponse :return: Information about the webhook """ path = f"/accounts/{account_id}/hooks" - response = await self._api.request("POST", path, json=data.jsonable_dict(exclude_none=True)) + response = await self._api.request("POST", path, json=data.jsonable_dict()) return WebhookResponse.model_validate(response.json()) async def delete(self, account_id: int, webhook_id: int) -> None: diff --git a/huntflow_api_client/models/common.py b/huntflow_api_client/models/common.py index 02bc7da..0a63297 100644 --- a/huntflow_api_client/models/common.py +++ b/huntflow_api_client/models/common.py @@ -170,6 +170,7 @@ class EmailRecipient(BaseModel): name: Optional[str] = Field( None, description="Name of email recipient", + alias="displayName", ) email: str = Field(..., description="Email address") diff --git a/huntflow_api_client/models/consts.py b/huntflow_api_client/models/consts.py index 37bbb36..c6b57c0 100644 --- a/huntflow_api_client/models/consts.py +++ b/huntflow_api_client/models/consts.py @@ -1,5 +1,7 @@ from enum import Enum +from huntflow_api_client.utils import extend_enum + class WebhookEvent(str, Enum): APPLICANT = "APPLICANT" @@ -69,11 +71,15 @@ class FieldType(str, Enum): html = "html" -class AgreementState(str, Enum): +class AgreementStateRequest(str, Enum): not_sent = "not_sent" sent = "sent" accepted = "accepted" declined = "declined" + + +@extend_enum(AgreementStateRequest) +class AgreementStateResponse(str, Enum): send_error = "send_error" diff --git a/huntflow_api_client/models/response/applicant_logs.py b/huntflow_api_client/models/response/applicant_logs.py index 34761eb..24c4896 100644 --- a/huntflow_api_client/models/response/applicant_logs.py +++ b/huntflow_api_client/models/response/applicant_logs.py @@ -6,6 +6,7 @@ from huntflow_api_client.models.common import ( ApplicantOffer, CalendarEventAttendeeResponse, + EmailRecipient, File, PaginatedResponse, VacancyQuotaItem, @@ -15,11 +16,11 @@ CalendarEventReminderMethod, CalendarEventStatus, CalendarEventType, - EmailContactType, SurveyType, Transparency, ) from huntflow_api_client.models.response.applicant_offers import ApplicantVacancyOffer +from huntflow_api_client.models.response.survey import SurveyTypeARespondent class BaseSurveySchemaType(BaseModel): @@ -35,6 +36,10 @@ class SurveySchemaTypeQLogResponse(BaseSurveySchemaType): title: Optional[str] = Field(..., description="Survey title") +class SurveySchemaTypeALogResponse(BaseSurveySchemaType): + pass + + class ApplicantLogSurveyQuestionary(BaseModel): id: int = Field(..., description="Survey questionary ID") survey: SurveySchemaTypeQLogResponse = Field(..., description="Survey schema") @@ -48,13 +53,14 @@ class ApplicantLogSurveyQuestionary(BaseModel): ) -class EmailRecipient(BaseModel): - type: Optional[EmailContactType] = Field(None, description="Type of the email contact") - name: Optional[str] = Field( - None, - description="Name of email recipient", +class ApplicantLogSurveyAnswerTypeA(BaseModel): + id: int = Field(..., description="Survey questionary ID") + created: datetime = Field( + ..., + description="Date and time of creating an survey questionary of type A", ) - email: str = Field(..., description="Email address") + respondent: SurveyTypeARespondent = Field(..., description="Who created the survey answer") + survey: SurveySchemaTypeALogResponse = Field(..., description="Survey schema") class ApplicantLogAccountInfo(BaseModel): @@ -172,6 +178,10 @@ class ApplicantLogItem(BaseModel): None, description="Survey questionary", ) + survey_answer_of_type_a: Optional[ApplicantLogSurveyAnswerTypeA] = Field( + None, + description="Survey answer of type A object", + ) class ApplicantLogResponse(PaginatedResponse): diff --git a/huntflow_api_client/models/response/applicants.py b/huntflow_api_client/models/response/applicants.py index 5f2a8e5..5ae7b5e 100644 --- a/huntflow_api_client/models/response/applicants.py +++ b/huntflow_api_client/models/response/applicants.py @@ -4,7 +4,7 @@ from pydantic import BaseModel, ConfigDict, Field, PositiveInt from huntflow_api_client.models.common import Applicant, PaginatedResponse -from huntflow_api_client.models.consts import AgreementState as AgreementStateEnum +from huntflow_api_client.models.consts import AgreementStateResponse as AgreementStateEnum class ApplicantTag(BaseModel): diff --git a/huntflow_api_client/utils.py b/huntflow_api_client/utils.py new file mode 100644 index 0000000..6cb6c3e --- /dev/null +++ b/huntflow_api_client/utils.py @@ -0,0 +1,16 @@ +from enum import Enum +from typing import Any, Callable, Dict, Type, TypeVar + +T = TypeVar("T", bound=Enum) + + +def extend_enum(inherited_enum: Type[T]) -> Callable: + def wrapper(added_enum: Type[T]) -> Enum: + joined: Dict[str, Any] = {} + for item in inherited_enum: + joined[item.name] = item.value + for item in added_enum: + joined[item.name] = item.value + return Enum(added_enum.__name__, joined) + + return wrapper diff --git a/pyproject.toml b/pyproject.toml index 5d065be..f5c2ff8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "huntflow-api-client" -version = "2.13.2" +version = "2.13.3" description = "Huntflow API Client for Python" authors = [ {name = "Developers huntflow", email = "developer@huntflow.ru"}, diff --git a/tests/test_entities/test_production_calendar.py b/tests/test_entities/test_production_calendar.py index 6c1eb4f..815819e 100644 --- a/tests/test_entities/test_production_calendar.py +++ b/tests/test_entities/test_production_calendar.py @@ -110,7 +110,7 @@ async def test_get_non_working_days_in_period( ) -> None: httpx_mock.add_response( url=f"{VERSIONED_BASE_URL}/production_calendars/{CALENDAR_ID}/days/" - f"{DEADLINE_DATE.strftime('%Y-%m-%d')}?verbose=true", + f"{DEADLINE_DATE.strftime('%Y-%m-%d')}?verbose=false", json=NON_WORKING_DAYS_GET_RESPONSE, ) api_client = HuntflowAPI(BASE_URL, token_proxy=token_proxy)