talentro-commons 0.18.12__tar.gz → 0.19.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/PKG-INFO +2 -2
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/pyproject.toml +2 -2
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/acquisition/dataclasses.py +6 -4
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/acquisition/models.py +1 -3
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/billing/models.py +1 -2
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/candidates/dataclasses.py +2 -2
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/general/models.py +2 -3
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/services/caching.py +0 -1
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/services/clients.py +0 -1
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/services/db.py +1 -1
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/services/google_storage.py +12 -19
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/util/attributes.py +4 -1
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/util/files.py +1 -1
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/util/vacancy.py +1 -1
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/vacancies/dataclasses.py +36 -21
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/vacancies/models.py +8 -15
- talentro_commons-0.19.0/src/talentro/vacancies/taxanomy.py +190 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/README.md +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/__init__.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/acquisition/__init__.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/billing/__init__.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/billing/dataclasses.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/candidates/__init__.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/candidates/models.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/constants.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/event.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/exceptions.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/general/__init__.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/general/dataclasses.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/iam/__init__.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/iam/dataclasses.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/iam/models.py +1 -1
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/iam/types.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/integrations/__init__.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/integrations/dataclasses.py +2 -2
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/integrations/models.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/services/__init__.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/services/billing.py +2 -2
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/services/rabbitmq.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/util/__init__.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/util/enum.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/util/singleton.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/util/string.py +0 -0
- {talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/vacancies/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: talentro-commons
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19.0
|
|
4
4
|
Summary: This package contains all globally used code, services, models and data structures for Talentro
|
|
5
5
|
License: Proprietary
|
|
6
6
|
Author: Emiel van Essen
|
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.14
|
|
13
13
|
Requires-Dist: aio-pika (>=9.5.7,<10.0.0)
|
|
14
14
|
Requires-Dist: aiocache[redis] (>=0.12.3,<0.13.0)
|
|
15
|
-
Requires-Dist: fastapi (>=0.
|
|
15
|
+
Requires-Dist: fastapi (>=0.128.0,<0.129.0)
|
|
16
16
|
Requires-Dist: google-cloud-storage (>=3.6.0,<4.0.0)
|
|
17
17
|
Requires-Dist: httpx (>=0.28.1,<0.29.0)
|
|
18
18
|
Requires-Dist: sqlalchemy (>=2.0.38,<3.0.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "talentro-commons"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.19.0"
|
|
4
4
|
description = "This package contains all globally used code, services, models and data structures for Talentro"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Emiel van Essen", email = "emiel@marksmen.nl"}
|
|
@@ -11,7 +11,7 @@ requires-python = ">=3.13,<4.0"
|
|
|
11
11
|
dependencies = [
|
|
12
12
|
"sqlalchemy (>=2.0.38,<3.0.0)",
|
|
13
13
|
"sqlmodel (>=0.0.27,<0.0.28)",
|
|
14
|
-
"fastapi (>=0.
|
|
14
|
+
"fastapi (>=0.128.0,<0.129.0)",
|
|
15
15
|
"aio-pika (>=9.5.7,<10.0.0)",
|
|
16
16
|
"httpx (>=0.28.1,<0.29.0)",
|
|
17
17
|
"google-cloud-storage (>=3.6.0,<4.0.0)",
|
{talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/acquisition/dataclasses.py
RENAMED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
from typing import Optional
|
|
3
3
|
from uuid import UUID
|
|
4
|
+
|
|
4
5
|
from pydantic import BaseModel
|
|
5
6
|
|
|
7
|
+
from .models import CampaignStatus
|
|
6
8
|
from ..acquisition.models import ChannelType, CampaignGoal, Campaign as CampaignModel, Ad as AdModel, AdStatus
|
|
7
9
|
from ..general.dataclasses import ResolvableCompanyModel
|
|
8
10
|
from ..integrations.dataclasses import LinkInfo
|
|
9
|
-
from ..vacancies.dataclasses import FeedInfo
|
|
10
|
-
|
|
11
|
-
from ..services.clients import MSClient
|
|
12
11
|
from ..services.caching import CacheService
|
|
12
|
+
from ..services.clients import MSClient
|
|
13
|
+
from ..util.enum import to_enum
|
|
14
|
+
from ..vacancies.dataclasses import FeedInfo
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
# Campaign object
|
|
@@ -61,7 +63,7 @@ class CampaignInfo(ResolvableCompanyModel):
|
|
|
61
63
|
organization=model.organization,
|
|
62
64
|
name=model.name,
|
|
63
65
|
external_id=model.external_id,
|
|
64
|
-
status=model.status,
|
|
66
|
+
status=to_enum(CampaignStatus, model.status),
|
|
65
67
|
last_sync_date=model.last_sync_date,
|
|
66
68
|
ad_count=model.ad_count,
|
|
67
69
|
auto_sync=model.auto_sync,
|
|
@@ -3,10 +3,10 @@ from typing import Optional
|
|
|
3
3
|
from uuid import UUID
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
|
-
|
|
7
6
|
from talentro.acquisition.dataclasses import CampaignInfo
|
|
7
|
+
from talentro.candidates.models import Application as ApplicationModel, Document as DocumentModel, \
|
|
8
|
+
Candidate as CandidateModel
|
|
8
9
|
from talentro.vacancies.dataclasses import VacancyInfo
|
|
9
|
-
from talentro.candidates.models import Application as ApplicationModel, Document as DocumentModel, Candidate as CandidateModel
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class CandidateInfo(BaseModel):
|
{talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/services/google_storage.py
RENAMED
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
import base64
|
|
2
2
|
import os
|
|
3
|
+
import tempfile
|
|
3
4
|
import traceback
|
|
4
|
-
|
|
5
5
|
from enum import StrEnum
|
|
6
6
|
from http import HTTPStatus
|
|
7
7
|
|
|
8
|
-
import tempfile
|
|
9
|
-
|
|
10
8
|
from fastapi import UploadFile
|
|
11
9
|
from google.api_core.exceptions import NotFound
|
|
12
10
|
from google.cloud import storage
|
|
13
11
|
from google.cloud.storage import Bucket, Blob
|
|
14
|
-
|
|
15
12
|
from talentro.constants import ErrorCode, DisplayMessage
|
|
16
13
|
from talentro.exceptions import APIException
|
|
17
|
-
from ..general.dataclasses import FileData
|
|
18
14
|
|
|
15
|
+
from ..general.dataclasses import FileData
|
|
19
16
|
from ..util.singleton import SingletonMeta
|
|
20
17
|
from ..util.string import render_template_path
|
|
21
18
|
|
|
@@ -45,24 +42,20 @@ class GoogleStorage(metaclass=SingletonMeta):
|
|
|
45
42
|
tmp_fd, tmp_path = tempfile.mkstemp(suffix=ext)
|
|
46
43
|
os.close(tmp_fd)
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
blob = self._get_blob(bucket, destination, path_definitions)
|
|
45
|
+
blob = self._get_blob(bucket, destination, path_definitions)
|
|
50
46
|
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
with open(tmp_path, "wb") as f:
|
|
48
|
+
f.write(file_bytes)
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
blob.upload_from_filename(
|
|
51
|
+
tmp_path,
|
|
52
|
+
content_type=file.content_type # handig voor GCS metadata
|
|
53
|
+
)
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
if os.path.exists(tmp_path):
|
|
56
|
+
os.remove(tmp_path)
|
|
61
57
|
|
|
62
|
-
|
|
63
|
-
except Exception as e:
|
|
64
|
-
print(e)
|
|
65
|
-
traceback.print_exc()
|
|
58
|
+
return blob
|
|
66
59
|
|
|
67
60
|
def _get_bucket(self, bucket: BucketEnum) -> Bucket:
|
|
68
61
|
try:
|
|
@@ -17,7 +17,7 @@ def generate_vacancy_hash(vacancy_data: VacancyModel) -> str:
|
|
|
17
17
|
"location_city", "location_state", "location_country", "salary_min",
|
|
18
18
|
"salary_max", "salary_currency", "salary_frequency", "recruiter_first_name",
|
|
19
19
|
"recruiter_last_name", "recruiter_phone_number", "recruiter_email",
|
|
20
|
-
"recruiter_role"
|
|
20
|
+
"recruiter_role", "contract_type", "industry_category"
|
|
21
21
|
]
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from dataclasses import field
|
|
3
2
|
from datetime import datetime
|
|
4
3
|
from typing import List, Optional, Literal
|
|
5
4
|
from uuid import UUID
|
|
6
|
-
from dataclasses import field
|
|
7
|
-
from pydantic.dataclasses import dataclass
|
|
8
5
|
|
|
6
|
+
from pydantic import BaseModel
|
|
9
7
|
from pydantic import field_validator
|
|
8
|
+
from pydantic.dataclasses import dataclass
|
|
10
9
|
|
|
11
|
-
from
|
|
12
|
-
from pydantic import BaseModel
|
|
10
|
+
from .taxanomy import RemoteType, SalaryFrequency, JobCategory, Education, ExperienceLevel, ContractType, IndustryCategory
|
|
13
11
|
|
|
14
12
|
from ..general.dataclasses import ResolvableCompanyModel
|
|
15
13
|
from ..integrations.dataclasses import LinkInfo
|
|
14
|
+
from ..services.caching import CacheService
|
|
15
|
+
from ..services.clients import MSClient
|
|
16
16
|
from ..util.enum import to_enum
|
|
17
17
|
from ..util.vacancy import generate_vacancy_hash
|
|
18
|
+
from ..vacancies.models import Feed as FeedModel, Vacancy as VacancyModel
|
|
19
|
+
from ..vacancies.models import Question as QuestionModel, ApplicationFlow as ApplicationFlowModel, QuestionCategory, \
|
|
20
|
+
ApplicationFlowType
|
|
18
21
|
|
|
19
|
-
from ..services.clients import MSClient
|
|
20
|
-
from ..services.caching import CacheService
|
|
21
|
-
|
|
22
|
-
from ..vacancies.models import Feed as FeedModel, Vacancy as VacancyModel, SalaryFrequency, RemoteType
|
|
23
|
-
from ..vacancies.models import Question as QuestionModel, ApplicationFlow as ApplicationFlowModel, QuestionCategory, ApplicationFlowType
|
|
24
22
|
|
|
25
23
|
class VacancyLocation(BaseModel):
|
|
26
24
|
zipcode: str | None = None
|
|
@@ -122,8 +120,8 @@ class ApplicationFlowConfig(BaseModel):
|
|
|
122
120
|
updated_at=model.updated_at,
|
|
123
121
|
organization=model.organization,
|
|
124
122
|
name=model.name,
|
|
125
|
-
type=model.type,
|
|
126
|
-
questions=questions,
|
|
123
|
+
type=ApplicationFlowType(model.type),
|
|
124
|
+
questions=[await QuestionConfig.from_model(question) for question in questions],
|
|
127
125
|
)
|
|
128
126
|
|
|
129
127
|
|
|
@@ -162,9 +160,11 @@ class RawVacancy(BaseModel):
|
|
|
162
160
|
job_site_url: str
|
|
163
161
|
company_name: str
|
|
164
162
|
publish_date: datetime | None = None
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
163
|
+
|
|
164
|
+
category: List[JobCategory] = field(default_factory=list)
|
|
165
|
+
experience: List[ExperienceLevel] = field(default_factory=list)
|
|
166
|
+
education: List[Education] = field(default_factory=list)
|
|
167
|
+
industry_category: List[IndustryCategory] = field(default_factory=list)
|
|
168
168
|
|
|
169
169
|
# Connected data
|
|
170
170
|
hours: Hours = field(default_factory=Hours)
|
|
@@ -176,10 +176,14 @@ class RawVacancy(BaseModel):
|
|
|
176
176
|
description: str | None = None
|
|
177
177
|
status: str | None = None
|
|
178
178
|
parent_company_name: str | None = None
|
|
179
|
-
remote_type: RemoteType | None = None
|
|
180
179
|
expiration_date: datetime | None = None
|
|
181
180
|
last_updated_date: datetime | None = None
|
|
182
181
|
|
|
182
|
+
remote_type: RemoteType | None = None
|
|
183
|
+
contract_type: ContractType | None = None
|
|
184
|
+
video_url: str | None = None
|
|
185
|
+
applied_sanitizers: List[str] = []
|
|
186
|
+
|
|
183
187
|
@field_validator("remote_type", mode="before")
|
|
184
188
|
@classmethod
|
|
185
189
|
def cast_remote_type(cls, v):
|
|
@@ -198,10 +202,12 @@ class RawVacancy(BaseModel):
|
|
|
198
202
|
company_name=self.company_name,
|
|
199
203
|
parent_company_name=self.parent_company_name,
|
|
200
204
|
remote_type=self.remote_type.value if self.remote_type else None,
|
|
205
|
+
contract_type=self.contract_type.value if self.contract_type else None,
|
|
201
206
|
publish_date=self.publish_date,
|
|
202
207
|
expiration_date=self.expiration_date,
|
|
203
208
|
last_updated_date=self.last_updated_date,
|
|
204
209
|
category=self.category,
|
|
210
|
+
industry_category=self.industry_category,
|
|
205
211
|
experience=self.experience,
|
|
206
212
|
education=self.education,
|
|
207
213
|
hours_fte=self.hours.fte,
|
|
@@ -223,6 +229,8 @@ class RawVacancy(BaseModel):
|
|
|
223
229
|
recruiter_phone_number=self.recruiter.phone_number,
|
|
224
230
|
recruiter_email=self.recruiter.email,
|
|
225
231
|
recruiter_role=self.recruiter.role,
|
|
232
|
+
video_url=self.video_url,
|
|
233
|
+
applied_sanitizers=getattr(self, "applied_sanitizers", []),
|
|
226
234
|
)
|
|
227
235
|
|
|
228
236
|
checksum = generate_vacancy_hash(model)
|
|
@@ -266,7 +274,7 @@ class VacancyInfo(RawVacancy):
|
|
|
266
274
|
return VacancyInfo(**result.json())
|
|
267
275
|
|
|
268
276
|
@classmethod
|
|
269
|
-
async def from_model(cls: "
|
|
277
|
+
async def from_model(cls: "VacancyInfo", model: VacancyModel) -> "VacancyInfo":
|
|
270
278
|
if model.application_flow_id:
|
|
271
279
|
application_flow = await ApplicationFlowConfig.resolve_object(model.application_flow_id, model.organization)
|
|
272
280
|
else:
|
|
@@ -321,9 +329,13 @@ class VacancyInfo(RawVacancy):
|
|
|
321
329
|
job_site_url=model.job_site_url,
|
|
322
330
|
company_name=model.company_name,
|
|
323
331
|
publish_date=model.publish_date,
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
332
|
+
|
|
333
|
+
contract_type=to_enum(ContractType, getattr(model, "contract_type", ContractType.UNSPECIFIED)),
|
|
334
|
+
|
|
335
|
+
category=[to_enum(JobCategory, category) for category in model.category or []],
|
|
336
|
+
experience=[to_enum(ExperienceLevel, experience) for experience in model.experience or []],
|
|
337
|
+
education=[to_enum(Education, education) for education in model.education or []],
|
|
338
|
+
industry_category=[to_enum(IndustryCategory, industry_category) for industry_category in model.industry_category or []],
|
|
327
339
|
|
|
328
340
|
hours=hours,
|
|
329
341
|
location=location,
|
|
@@ -333,8 +345,11 @@ class VacancyInfo(RawVacancy):
|
|
|
333
345
|
status=model.status,
|
|
334
346
|
parent_company_name=model.parent_company_name,
|
|
335
347
|
remote_type=remote_type,
|
|
348
|
+
video_url=model.video_url,
|
|
336
349
|
expiration_date=model.expiration_date,
|
|
337
350
|
last_updated_date=model.last_updated_date,
|
|
351
|
+
|
|
352
|
+
applied_sanitizers=getattr(model, "applied_sanitizers", []),
|
|
338
353
|
)
|
|
339
354
|
|
|
340
355
|
# Feed object
|
|
@@ -1,30 +1,18 @@
|
|
|
1
|
-
from enum import StrEnum
|
|
2
|
-
from uuid import UUID
|
|
3
|
-
|
|
4
1
|
from datetime import datetime
|
|
2
|
+
from enum import StrEnum
|
|
5
3
|
from typing import Optional, List
|
|
4
|
+
from uuid import UUID
|
|
6
5
|
|
|
7
6
|
from sqlalchemy import Column, JSON, UniqueConstraint, Enum
|
|
8
7
|
from sqlmodel import Field, Relationship
|
|
9
8
|
|
|
10
9
|
from ..general.models import BaseModel
|
|
11
10
|
|
|
11
|
+
|
|
12
12
|
class SourceType(StrEnum):
|
|
13
13
|
ATS = "ATS"
|
|
14
14
|
CUSTOM_FILE = "CUSTOM_FILE"
|
|
15
15
|
|
|
16
|
-
class SalaryFrequency(StrEnum):
|
|
17
|
-
MONTH = "MONTH"
|
|
18
|
-
YEAR = "YEAR"
|
|
19
|
-
WEEK = "WEEK"
|
|
20
|
-
HOUR = "HOUR"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class RemoteType(StrEnum):
|
|
24
|
-
ONSITE = "ONSITE"
|
|
25
|
-
HYBRID = "HYBRID"
|
|
26
|
-
REMOTE = "REMOTE"
|
|
27
|
-
|
|
28
16
|
|
|
29
17
|
class QuestionCategory(StrEnum):
|
|
30
18
|
SCREENING = "SCREENING"
|
|
@@ -59,6 +47,7 @@ class Feed(VacanciesOrganizationModel, table=True):
|
|
|
59
47
|
|
|
60
48
|
vacancies: list["Vacancy"] = Relationship(back_populates="feed")
|
|
61
49
|
|
|
50
|
+
|
|
62
51
|
class Vacancy(VacanciesOrganizationModel, table=True):
|
|
63
52
|
feed_id: UUID = Field(foreign_key="feed.id", ondelete="CASCADE", index=True)
|
|
64
53
|
feed: "Feed" = Relationship(back_populates="vacancies")
|
|
@@ -78,6 +67,8 @@ class Vacancy(VacanciesOrganizationModel, table=True):
|
|
|
78
67
|
category: List[str] = Field(sa_column=Column(JSON))
|
|
79
68
|
experience: List[str] = Field(sa_column=Column(JSON))
|
|
80
69
|
education: List[str] = Field(sa_column=Column(JSON))
|
|
70
|
+
industry_category: List[str] = Field(sa_column=Column(JSON))
|
|
71
|
+
contract_type: Optional[str] = Field()
|
|
81
72
|
hours_fte: Optional[float] = Field()
|
|
82
73
|
hours_min: Optional[int] = Field()
|
|
83
74
|
hours_max: Optional[int] = Field()
|
|
@@ -97,9 +88,11 @@ class Vacancy(VacanciesOrganizationModel, table=True):
|
|
|
97
88
|
recruiter_phone_number: Optional[str] = Field()
|
|
98
89
|
recruiter_email: Optional[str] = Field()
|
|
99
90
|
recruiter_role: Optional[str] = Field()
|
|
91
|
+
video_url: Optional[str] = Field()
|
|
100
92
|
checksum: str = Field(index=True)
|
|
101
93
|
application_flow_id: Optional[UUID] = Field(foreign_key="applicationflow.id", ondelete="SET NULL", index=True, nullable=True)
|
|
102
94
|
application_flow: "ApplicationFlow" = Relationship(back_populates="vacancies")
|
|
95
|
+
applied_sanitizers: List[str] = Field(sa_column=Column(JSON), default_factory=list)
|
|
103
96
|
|
|
104
97
|
__table_args__ = (
|
|
105
98
|
UniqueConstraint("feed_id", "reference_number", name="uq_feed_reference"),
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SalaryFrequency(StrEnum):
|
|
5
|
+
MONTH = "MONTH"
|
|
6
|
+
YEAR = "YEAR"
|
|
7
|
+
WEEK = "WEEK"
|
|
8
|
+
HOUR = "HOUR"
|
|
9
|
+
|
|
10
|
+
class RemoteType(StrEnum):
|
|
11
|
+
ONSITE = "ONSITE"
|
|
12
|
+
HYBRID = "HYBRID"
|
|
13
|
+
REMOTE = "REMOTE"
|
|
14
|
+
|
|
15
|
+
class JobCategory(StrEnum):
|
|
16
|
+
# Customer-facing & commercial
|
|
17
|
+
CUSTOMER_SERVICE = "CUSTOMER_SERVICE"
|
|
18
|
+
SALES = "SALES"
|
|
19
|
+
BUSINESS_DEVELOPMENT = "BUSINESS_DEVELOPMENT"
|
|
20
|
+
ACCOUNT_MANAGEMENT = "ACCOUNT_MANAGEMENT"
|
|
21
|
+
|
|
22
|
+
# Marketing & communication
|
|
23
|
+
MARKETING = "MARKETING"
|
|
24
|
+
COMMUNICATIONS_PR = "COMMUNICATIONS_PR"
|
|
25
|
+
CONTENT_COPY = "CONTENT_COPY"
|
|
26
|
+
BRAND = "BRAND"
|
|
27
|
+
EVENTS = "EVENTS"
|
|
28
|
+
DIGITAL_MARKETING = "DIGITAL_MARKETING"
|
|
29
|
+
|
|
30
|
+
# People & organization
|
|
31
|
+
HR = "HR"
|
|
32
|
+
RECRUITMENT = "RECRUITMENT"
|
|
33
|
+
LEARNING_AND_DEVELOPMENT = "LEARNING_AND_DEVELOPMENT"
|
|
34
|
+
|
|
35
|
+
# Finance & legal
|
|
36
|
+
FINANCE_ACCOUNTING = "FINANCE_ACCOUNTING"
|
|
37
|
+
CONTROLLING = "CONTROLLING"
|
|
38
|
+
LEGAL = "LEGAL"
|
|
39
|
+
COMPLIANCE_RISK = "COMPLIANCE_RISK"
|
|
40
|
+
|
|
41
|
+
# Tech
|
|
42
|
+
IT_SUPPORT = "IT_SUPPORT"
|
|
43
|
+
SOFTWARE_ENGINEERING = "SOFTWARE_ENGINEERING"
|
|
44
|
+
DATA_ANALYTICS = "DATA_ANALYTICS"
|
|
45
|
+
DATA_SCIENCE_ML = "DATA_SCIENCE_ML"
|
|
46
|
+
DEVOPS_SRE = "DEVOPS_SRE"
|
|
47
|
+
SECURITY = "SECURITY"
|
|
48
|
+
QA_TESTING = "QA_TESTING"
|
|
49
|
+
PRODUCT_MANAGEMENT = "PRODUCT_MANAGEMENT"
|
|
50
|
+
PROJECT_MANAGEMENT = "PROJECT_MANAGEMENT"
|
|
51
|
+
UX_UI_DESIGN = "UX_UI_DESIGN"
|
|
52
|
+
|
|
53
|
+
# Operations & supply chain
|
|
54
|
+
OPERATIONS = "OPERATIONS"
|
|
55
|
+
PROCUREMENT = "PROCUREMENT"
|
|
56
|
+
LOGISTICS_SUPPLY_CHAIN = "LOGISTICS_SUPPLY_CHAIN"
|
|
57
|
+
TRANSPORT = "TRANSPORT"
|
|
58
|
+
WAREHOUSE = "WAREHOUSE"
|
|
59
|
+
ADMINISTRATION = "ADMINISTRATION"
|
|
60
|
+
OFFICE_MANAGEMENT = "OFFICE_MANAGEMENT"
|
|
61
|
+
FACILITY_MANAGEMENT = "FACILITY_MANAGEMENT"
|
|
62
|
+
|
|
63
|
+
# Skilled trades & industry
|
|
64
|
+
ENGINEERING_TECHNICAL = "ENGINEERING_TECHNICAL"
|
|
65
|
+
MAINTENANCE = "MAINTENANCE"
|
|
66
|
+
MANUFACTURING_PRODUCTION = "MANUFACTURING_PRODUCTION"
|
|
67
|
+
QUALITY_MANUFACTURING = "QUALITY_MANUFACTURING"
|
|
68
|
+
CONSTRUCTION_INSTALLATION = "CONSTRUCTION_INSTALLATION"
|
|
69
|
+
ENERGY_UTILITIES = "ENERGY_UTILITIES"
|
|
70
|
+
|
|
71
|
+
# Sector-specific
|
|
72
|
+
HEALTHCARE_MEDICAL = "HEALTHCARE_MEDICAL"
|
|
73
|
+
EDUCATION_TRAINING = "EDUCATION_TRAINING"
|
|
74
|
+
RESEARCH_SCIENCE = "RESEARCH_SCIENCE"
|
|
75
|
+
GOVERNMENT_NONPROFIT = "GOVERNMENT_NONPROFIT"
|
|
76
|
+
SECURITY_DEFENSE = "SECURITY_DEFENSE"
|
|
77
|
+
|
|
78
|
+
# Retail & hospitality
|
|
79
|
+
RETAIL = "RETAIL"
|
|
80
|
+
HOSPITALITY = "HOSPITALITY"
|
|
81
|
+
FOOD_SERVICE = "FOOD_SERVICE"
|
|
82
|
+
|
|
83
|
+
# Creative & media
|
|
84
|
+
DESIGN_CREATIVE = "DESIGN_CREATIVE"
|
|
85
|
+
MEDIA_JOURNALISM = "MEDIA_JOURNALISM"
|
|
86
|
+
|
|
87
|
+
# Consulting & advisory
|
|
88
|
+
CONSULTING_ADVISORY = "CONSULTING_ADVISORY"
|
|
89
|
+
|
|
90
|
+
OTHER = "OTHER"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class IndustryCategory(StrEnum):
|
|
94
|
+
UNSPECIFIED = "UNSPECIFIED"
|
|
95
|
+
|
|
96
|
+
ICT = "ICT"
|
|
97
|
+
GOVERNMENT_NONPROFIT = "GOVERNMENT_NONPROFIT"
|
|
98
|
+
FASHION_TEXTILES_COSMETICS = "FASHION_TEXTILES_COSMETICS"
|
|
99
|
+
WHOLESALE_TRADE = "WHOLESALE_TRADE"
|
|
100
|
+
BANKING_FINANCIAL_SERVICES = "BANKING_FINANCIAL_SERVICES"
|
|
101
|
+
AUTOMOTIVE = "AUTOMOTIVE"
|
|
102
|
+
INTERNET_SERVICES = "INTERNET_SERVICES"
|
|
103
|
+
CONSULTING_ADVISORY = "CONSULTING_ADVISORY"
|
|
104
|
+
RETAIL = "RETAIL"
|
|
105
|
+
CONSTRUCTION_INSTALLATION = "CONSTRUCTION_INSTALLATION"
|
|
106
|
+
TELECOMMUNICATIONS = "TELECOMMUNICATIONS"
|
|
107
|
+
HOSPITALITY = "HOSPITALITY"
|
|
108
|
+
CHEMICALS_PETROCHEMICALS = "CHEMICALS_PETROCHEMICALS"
|
|
109
|
+
FACILITY_SERVICES = "FACILITY_SERVICES"
|
|
110
|
+
INSURANCE = "INSURANCE"
|
|
111
|
+
ENGINEERING_TECHNICAL = "ENGINEERING_TECHNICAL"
|
|
112
|
+
EDUCATION_TRAINING = "EDUCATION_TRAINING"
|
|
113
|
+
SPORTS_RECREATION_TOURISM = "SPORTS_RECREATION_TOURISM"
|
|
114
|
+
INDUSTRIAL_MANUFACTURING = "INDUSTRIAL_MANUFACTURING"
|
|
115
|
+
ELECTRONICS = "ELECTRONICS"
|
|
116
|
+
FMCG = "FMCG"
|
|
117
|
+
SECURITY_SERVICES = "SECURITY_SERVICES"
|
|
118
|
+
BUSINESS_SERVICES = "BUSINESS_SERVICES"
|
|
119
|
+
PASSENGER_TRANSPORT = "PASSENGER_TRANSPORT"
|
|
120
|
+
STAFFING_RECRUITMENT = "STAFFING_RECRUITMENT"
|
|
121
|
+
PHARMACEUTICALS = "PHARMACEUTICALS"
|
|
122
|
+
AGRICULTURE_FORESTRY_FISHING = "AGRICULTURE_FORESTRY_FISHING"
|
|
123
|
+
WASTE_ENVIRONMENT = "WASTE_ENVIRONMENT"
|
|
124
|
+
MARITIME = "MARITIME"
|
|
125
|
+
REAL_ESTATE = "REAL_ESTATE"
|
|
126
|
+
LOGISTICS_TRANSPORT_DISTRIBUTION = "LOGISTICS_TRANSPORT_DISTRIBUTION"
|
|
127
|
+
HEALTHCARE_WELLBEING = "HEALTHCARE_WELLBEING"
|
|
128
|
+
LEGAL_SERVICES = "LEGAL_SERVICES"
|
|
129
|
+
ACCOUNTING_AUDIT = "ACCOUNTING_AUDIT"
|
|
130
|
+
ADVERTISING_PR_COMMUNICATIONS = "ADVERTISING_PR_COMMUNICATIONS"
|
|
131
|
+
ARTS_CULTURE_ENTERTAINMENT = "ARTS_CULTURE_ENTERTAINMENT"
|
|
132
|
+
MEDIA_PUBLISHING_BROADCASTING = "MEDIA_PUBLISHING_BROADCASTING"
|
|
133
|
+
ENERGY_UTILITIES = "ENERGY_UTILITIES"
|
|
134
|
+
|
|
135
|
+
OTHER = "OTHER"
|
|
136
|
+
|
|
137
|
+
class ExperienceLevel(StrEnum):
|
|
138
|
+
UNSPECIFIED = "UNSPECIFIED"
|
|
139
|
+
|
|
140
|
+
INTERN = "INTERN"
|
|
141
|
+
ENTRY_LEVEL = "ENTRY_LEVEL"
|
|
142
|
+
JUNIOR = "JUNIOR"
|
|
143
|
+
MID_LEVEL = "MID_LEVEL"
|
|
144
|
+
SENIOR = "SENIOR"
|
|
145
|
+
LEAD = "LEAD"
|
|
146
|
+
MANAGER = "MANAGER"
|
|
147
|
+
SENIOR_MANAGER = "SENIOR_MANAGER"
|
|
148
|
+
DIRECTOR = "DIRECTOR"
|
|
149
|
+
EXECUTIVE = "EXECUTIVE"
|
|
150
|
+
|
|
151
|
+
OTHER = "OTHER"
|
|
152
|
+
|
|
153
|
+
class Education(StrEnum):
|
|
154
|
+
UNSPECIFIED = "UNSPECIFIED"
|
|
155
|
+
|
|
156
|
+
# ISCED 2011 niveaus (UNESCO)
|
|
157
|
+
NO_FORMAL_EDUCATION = "NO_FORMAL_EDUCATION"
|
|
158
|
+
PRIMARY = "PRIMARY"
|
|
159
|
+
LOWER_SECONDARY = "LOWER_SECONDARY"
|
|
160
|
+
UPPER_SECONDARY = "UPPER_SECONDARY"
|
|
161
|
+
POST_SECONDARY_NON_TERTIARY = "POST_SECONDARY_NON_TERTIARY"
|
|
162
|
+
SHORT_CYCLE_TERTIARY = "SHORT_CYCLE_TERTIARY"
|
|
163
|
+
BACHELOR = "BACHELOR"
|
|
164
|
+
MASTER = "MASTER"
|
|
165
|
+
DOCTORATE = "DOCTORATE"
|
|
166
|
+
POSTDOCTORAL = "POSTDOCTORAL"
|
|
167
|
+
|
|
168
|
+
OTHER = "OTHER"
|
|
169
|
+
|
|
170
|
+
class ContractType(StrEnum):
|
|
171
|
+
UNSPECIFIED = "UNSPECIFIED"
|
|
172
|
+
|
|
173
|
+
PERMANENT = "PERMANENT" # indefinite / open-ended
|
|
174
|
+
TEMPORARY = "TEMPORARY" # fixed-term
|
|
175
|
+
CONTRACTOR = "CONTRACTOR" # contractor / 1099 / zelfstandige (zonder payroll)
|
|
176
|
+
FREELANCE = "FREELANCE" # freelancer (overlaps contractor; keep if channels distinguish)
|
|
177
|
+
SELF_EMPLOYED = "SELF_EMPLOYED" # zzp / independent (if you want explicit)
|
|
178
|
+
INTERIM = "INTERIM" # interim assignment
|
|
179
|
+
|
|
180
|
+
INTERN = "INTERN" # internship / stage
|
|
181
|
+
APPRENTICESHIP = "APPRENTICESHIP" # leer-werk / dual / BBL
|
|
182
|
+
TEMP_AGENCY = "TEMP_AGENCY" # via uitzendbureau / staffing
|
|
183
|
+
VOLUNTEER = "VOLUNTEER" # volunteer
|
|
184
|
+
SEASONAL = "SEASONAL" # seasonal work
|
|
185
|
+
STUDENT_JOB = "STUDENT_JOB" # part-time student job / bijbaan
|
|
186
|
+
HOLIDAY_JOB = "HOLIDAY_JOB" # vacation job
|
|
187
|
+
|
|
188
|
+
FRANCHISE = "FRANCHISE" # franchise / zelfstandige formule
|
|
189
|
+
|
|
190
|
+
OTHER = "OTHER"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{talentro_commons-0.18.12 → talentro_commons-0.19.0}/src/talentro/integrations/dataclasses.py
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
from uuid import UUID
|
|
2
1
|
from datetime import datetime
|
|
3
2
|
from typing import Optional
|
|
3
|
+
from uuid import UUID
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
6
|
|
|
7
7
|
from .models import Link as LinkModel, Integration as IntegrationModel, IntegrationType
|
|
8
8
|
from ..general.dataclasses import ResolvableModel, ResolvableCompanyModel, FileData
|
|
9
|
-
from ..services.clients import MSClient
|
|
10
9
|
from ..services.caching import CacheService
|
|
10
|
+
from ..services.clients import MSClient
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
# Integration object
|
|
File without changes
|
|
File without changes
|
|
@@ -2,10 +2,10 @@ from datetime import datetime, UTC
|
|
|
2
2
|
from functools import wraps
|
|
3
3
|
from http import HTTPStatus
|
|
4
4
|
|
|
5
|
-
from ..event import Message, Event, EventMeta
|
|
6
|
-
from ..services.rabbitmq import QueueContext
|
|
7
5
|
from ..constants import ErrorCode, DisplayMessage, SKU
|
|
6
|
+
from ..event import Message, Event, EventMeta
|
|
8
7
|
from ..exceptions import APIException
|
|
8
|
+
from ..services.rabbitmq import QueueContext
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def billable_event(sku: SKU, details=None):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|