diff --git a/README.md b/README.md index 2b4ced72d..dc7846b4e 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ We invite developers to join us in our mission to bring AI and data integration | [**SAP SuccessFactors**](./src/hrflow_connectors/v1/connectors/sapsuccessfactors/README.md) | ATS | :book: Open source | *19/01/2022* | *23/10/2024* | | [**SmartRecruiters**](./src/hrflow_connectors/v2/connectors/smartrecruiters/README.md) | ATS | :book: Open source | *21/03/2022* | *05/09/2024* | | [**Taleez**](./src/hrflow_connectors/v2/connectors/taleez/README.md) | ATS | :book: Open source | *19/01/2022* | *23/10/2024* | -| [**TalentSoft**](./src/hrflow_connectors/v1/connectors/talentsoft/README.md) | HCM | :book: Open source | *19/04/2022* | ** | +| [**TalentSoft**](./src/hrflow_connectors/v2/connectors/talentsoft/README.md) | HCM | :book: Open source | *19/04/2022* | ** | | [**Teamtailor**](./src/hrflow_connectors/v2/connectors/teamtailor/README.md) | ATS | :book: Open source | *06/10/2022* | *05/09/2024* | | [**Waalaxy**](./src/hrflow_connectors/v2/connectors/waalaxy/README.md) | Automation | :book: Open source | *18/11/2022* | *05/09/2024* | | [**Workable**](./src/hrflow_connectors/v2/connectors/workable/README.md) | HCM | :book: Open source | *27/09/2022* | *05/09/2024* | diff --git a/manifest.json b/manifest.json index e6a49a222..4923a18a2 100644 --- a/manifest.json +++ b/manifest.json @@ -155461,6 +155461,9836 @@ } } ] + }, + { + "name": "TalentSoft", + "type": "HCM", + "subtype": "talentsoft", + "logo": "https://raw.githubusercontent.com/Riminder/hrflow-connectors/master/src/hrflow_connectors/v2/connectors/talentsoft/logo.png", + "actions": [ + { + "name": "applicant_new", + "data_type": "profile", + "direction": "inbound", + "mode": "create", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "TalentSoft", + "origin_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadProfilesParameters", + "type": "object", + "properties": { + "filter": { + "description": "Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921'", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [], + "$defs": {} + }, + "target": "HrFlow", + "target_data_schema": { + "title": "HrFlowProfile", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "info": { + "description": "Object containing the Profile's info.", + "$ref": "#/$defs/ProfileInfo" + }, + "text_language": { + "description": "Code language of the Profile. type: string code ISO 639-1", + "type": "string" + }, + "text": { + "description": "Full text of the Profile.", + "type": "string" + }, + "archived_at": { + "description": "type: datetime ISO8601, Archive date of the Profile. The value is null for unarchived Profiles.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "experiences_duration": { + "description": "Total number of years of experience.", + "type": "number" + }, + "educations_duration": { + "description": "Total number of years of education.", + "type": "number" + }, + "experiences": { + "description": "List of experiences of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Experience" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "educations": { + "description": "List of educations of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Education" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "attachments": { + "description": "List of documents attached to the Profile.", + "type": "array", + "default": [] + }, + "skills": { + "description": "List of skills of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "List of spoken languages of the profile", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "List of certifications of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "List of courses of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "List of tasks of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "interests": { + "description": "List of interests of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "List of tags of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "List of metadatas of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "labels": { + "description": "List of labels of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "info", + "text_language", + "text", + "experiences_duration", + "educations_duration" + ], + "$defs": { + "ProfileInfo": { + "title": "ProfileInfo", + "type": "object", + "properties": { + "full_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "first_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "date_birth": { + "description": "Profile date of birth", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Profile location object", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "urls": { + "description": "Profile social networks and URLs", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/InfoUrl" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "picture": { + "description": "Profile picture url", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "gender": { + "description": "Profile gender", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Profile summary text", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "full_name", + "first_name", + "last_name", + "email", + "phone" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "InfoUrl": { + "title": "InfoUrl", + "type": "object", + "properties": { + "type": { + "enum": [ + "facebook", + "from_resume", + "github", + "linkedin", + "twitter" + ] + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "type", + "url" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company": { + "description": "Company name of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the Company", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Experience.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Experience.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "Education": { + "title": "Education", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "school": { + "description": "School name of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the School", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Education.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Education.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Label": { + "title": "Label", + "type": "object", + "properties": { + "board_key": { + "description": "Identification key of the Board containing the target Job.", + "type": "string" + }, + "job_key": { + "description": "Identification key of the Job.", + "type": "string" + }, + "job_reference": { + "description": "Custom identifier of the Job.", + "type": "string" + }, + "stage": { + "description": "Stage associated to the Profile following the action of a recruiter (yes, no, later).", + "enum": [ + "later", + "no", + "yes" + ] + }, + "date_stage": { + "description": "Date of the stage edit action. type: ('datetime ISO 8601')", + "type": "string" + }, + "rating": { + "description": "Rating associated to the Profile following the action of a recruiter (from 1 to 5).", + "anyOf": [ + { + "enum": [ + 1, + 2, + 3, + 4, + 5 + ] + }, + { + "type": "null" + } + ] + }, + "date_rating": { + "description": "Date of the rating action. type: ('datetime ISO 8601')", + "type": "string" + } + }, + "required": [ + "board_key", + "job_key", + "job_reference", + "stage", + "date_stage", + "rating", + "date_rating" + ] + } + } + }, + "push_parameters": { + "title": "CreateCriterias", + "type": "object", + "properties": { + "source_key": { + "description": "HrFlow.ai source key", + "type": "string" + } + }, + "required": [ + "source_key" + ], + "$defs": {} + }, + "jsonmap": { + "reference": ".candidateDetail.id", + "created_at": ".candidateDetail.creationDate", + "updated_at": "$now('iso')", + "resume": ".attachments | .isResume ?? {raw: .raw, content_type: .mimeType} : null ", + "tags": "$merge([{ 'name': 'talentsoft-isEmployee', 'value': '.isEmployee'},{ 'name': 'talentsoft-isInProgress', 'value': '.isInProgress'},{ 'name': 'talentsoft-residentCountry-id', 'value': '.candidateDetail.personalInformation.residentCountry?.id'},{ 'name': 'talentsoft-contractType-id', 'value': '.candidateDetail.positionSought.contractType.id'},{ 'name': 'talentsoft-profileStatus-id', 'value': '.candidateDetail.positionSought.jobPreferencesCustomFields.customCodeTable1.id'},{ 'name': 'talentsoft-experienceLevel-id', 'value': '.candidateDetail.globalExperience.globalExperienceLevel.id'},{ 'name': 'talentsoft-profile-id', 'value': '.candidateDetail.positionSought.primaryProfile.id'},{ 'name': 'talentsofteducationLevel-id', 'value': '.candidateDetail.educations.educationLevel.id'}], .candidateDetail.educations | $map(.educationLevel != null ?? {name: 'talentsofteducationLevel-id', value: .educationLevel.id} ), .applications | $map({name: 'talentsoft-application-vacancyReference', value: .vacancyReference}))", + "metadatas": [ + { + "name": "profile_uid", + "value": ".candidateDetail.id" + }, + ".attachments | .isResume ?? {name: 'filename', value: .filename}" + ] + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\ndef default_event_parser(event: t.Dict) -> t.Dict:\n return dict(filter=\"id::{}\".format(event[\"applicantId\"]))\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.applicant_new(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.applicant_new(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.applicant_new(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.applicant_new(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.applicant_new(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + }, + { + "name": "applicant_update", + "data_type": "profile", + "direction": "inbound", + "mode": "update", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "TalentSoft", + "origin_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadProfilesParameters", + "type": "object", + "properties": { + "filter": { + "description": "Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921'", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [], + "$defs": {} + }, + "target": "HrFlow", + "target_data_schema": { + "title": "HrFlowProfile", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "info": { + "description": "Object containing the Profile's info.", + "$ref": "#/$defs/ProfileInfo" + }, + "text_language": { + "description": "Code language of the Profile. type: string code ISO 639-1", + "type": "string" + }, + "text": { + "description": "Full text of the Profile.", + "type": "string" + }, + "archived_at": { + "description": "type: datetime ISO8601, Archive date of the Profile. The value is null for unarchived Profiles.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "experiences_duration": { + "description": "Total number of years of experience.", + "type": "number" + }, + "educations_duration": { + "description": "Total number of years of education.", + "type": "number" + }, + "experiences": { + "description": "List of experiences of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Experience" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "educations": { + "description": "List of educations of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Education" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "attachments": { + "description": "List of documents attached to the Profile.", + "type": "array", + "default": [] + }, + "skills": { + "description": "List of skills of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "List of spoken languages of the profile", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "List of certifications of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "List of courses of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "List of tasks of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "interests": { + "description": "List of interests of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "List of tags of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "List of metadatas of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "labels": { + "description": "List of labels of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "info", + "text_language", + "text", + "experiences_duration", + "educations_duration" + ], + "$defs": { + "ProfileInfo": { + "title": "ProfileInfo", + "type": "object", + "properties": { + "full_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "first_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "date_birth": { + "description": "Profile date of birth", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Profile location object", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "urls": { + "description": "Profile social networks and URLs", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/InfoUrl" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "picture": { + "description": "Profile picture url", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "gender": { + "description": "Profile gender", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Profile summary text", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "full_name", + "first_name", + "last_name", + "email", + "phone" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "InfoUrl": { + "title": "InfoUrl", + "type": "object", + "properties": { + "type": { + "enum": [ + "facebook", + "from_resume", + "github", + "linkedin", + "twitter" + ] + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "type", + "url" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company": { + "description": "Company name of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the Company", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Experience.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Experience.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "Education": { + "title": "Education", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "school": { + "description": "School name of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the School", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Education.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Education.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Label": { + "title": "Label", + "type": "object", + "properties": { + "board_key": { + "description": "Identification key of the Board containing the target Job.", + "type": "string" + }, + "job_key": { + "description": "Identification key of the Job.", + "type": "string" + }, + "job_reference": { + "description": "Custom identifier of the Job.", + "type": "string" + }, + "stage": { + "description": "Stage associated to the Profile following the action of a recruiter (yes, no, later).", + "enum": [ + "later", + "no", + "yes" + ] + }, + "date_stage": { + "description": "Date of the stage edit action. type: ('datetime ISO 8601')", + "type": "string" + }, + "rating": { + "description": "Rating associated to the Profile following the action of a recruiter (from 1 to 5).", + "anyOf": [ + { + "enum": [ + 1, + 2, + 3, + 4, + 5 + ] + }, + { + "type": "null" + } + ] + }, + "date_rating": { + "description": "Date of the rating action. type: ('datetime ISO 8601')", + "type": "string" + } + }, + "required": [ + "board_key", + "job_key", + "job_reference", + "stage", + "date_stage", + "rating", + "date_rating" + ] + } + } + }, + "push_parameters": { + "title": "UpdateCriterias", + "type": "object", + "properties": { + "source_key": { + "description": "HrFlow.ai source key", + "type": "string" + }, + "only_edit_fields": { + "description": "List of attributes to use for the edit operation e.g. ['tags', 'metadatas']", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "source_key" + ], + "$defs": {} + }, + "jsonmap": { + "reference": ".candidateDetail.id", + "created_at": ".candidateDetail.creationDate", + "updated_at": "$now('iso')", + "resume": ".attachments | .isResume ?? {raw: .raw, content_type: .mimeType} : null ", + "tags": "$merge([{ 'name': 'talentsoft-isEmployee', 'value': '.isEmployee'},{ 'name': 'talentsoft-isInProgress', 'value': '.isInProgress'},{ 'name': 'talentsoft-residentCountry-id', 'value': '.candidateDetail.personalInformation.residentCountry?.id'},{ 'name': 'talentsoft-contractType-id', 'value': '.candidateDetail.positionSought.contractType.id'},{ 'name': 'talentsoft-profileStatus-id', 'value': '.candidateDetail.positionSought.jobPreferencesCustomFields.customCodeTable1.id'},{ 'name': 'talentsoft-experienceLevel-id', 'value': '.candidateDetail.globalExperience.globalExperienceLevel.id'},{ 'name': 'talentsoft-profile-id', 'value': '.candidateDetail.positionSought.primaryProfile.id'},{ 'name': 'talentsofteducationLevel-id', 'value': '.candidateDetail.educations.educationLevel.id'}], .candidateDetail.educations | $map(.educationLevel != null ?? {name: 'talentsofteducationLevel-id', value: .educationLevel.id} ), .applications | $map({name: 'talentsoft-application-vacancyReference', value: .vacancyReference}))", + "metadatas": [ + { + "name": "profile_uid", + "value": ".candidateDetail.id" + }, + ".attachments | .isResume ?? {name: 'filename', value: .filename}" + ] + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\ndef default_event_parser(event: t.Dict) -> t.Dict:\n return dict(filter=\"id::{}\".format(event[\"applicantId\"]))\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.applicant_update(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.applicant_update(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key', 'only_edit_fields'):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.applicant_update(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.applicant_update(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key', 'only_edit_fields'):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.applicant_update(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + }, + { + "name": "create_profiles_in_hrflow", + "data_type": "profile", + "direction": "inbound", + "mode": "create", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "TalentSoft", + "origin_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadProfilesParameters", + "type": "object", + "properties": { + "filter": { + "description": "Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921'", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [], + "$defs": {} + }, + "target": "HrFlow", + "target_data_schema": { + "title": "HrFlowProfile", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "info": { + "description": "Object containing the Profile's info.", + "$ref": "#/$defs/ProfileInfo" + }, + "text_language": { + "description": "Code language of the Profile. type: string code ISO 639-1", + "type": "string" + }, + "text": { + "description": "Full text of the Profile.", + "type": "string" + }, + "archived_at": { + "description": "type: datetime ISO8601, Archive date of the Profile. The value is null for unarchived Profiles.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "experiences_duration": { + "description": "Total number of years of experience.", + "type": "number" + }, + "educations_duration": { + "description": "Total number of years of education.", + "type": "number" + }, + "experiences": { + "description": "List of experiences of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Experience" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "educations": { + "description": "List of educations of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Education" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "attachments": { + "description": "List of documents attached to the Profile.", + "type": "array", + "default": [] + }, + "skills": { + "description": "List of skills of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "List of spoken languages of the profile", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "List of certifications of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "List of courses of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "List of tasks of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "interests": { + "description": "List of interests of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "List of tags of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "List of metadatas of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "labels": { + "description": "List of labels of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "info", + "text_language", + "text", + "experiences_duration", + "educations_duration" + ], + "$defs": { + "ProfileInfo": { + "title": "ProfileInfo", + "type": "object", + "properties": { + "full_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "first_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "date_birth": { + "description": "Profile date of birth", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Profile location object", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "urls": { + "description": "Profile social networks and URLs", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/InfoUrl" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "picture": { + "description": "Profile picture url", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "gender": { + "description": "Profile gender", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Profile summary text", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "full_name", + "first_name", + "last_name", + "email", + "phone" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "InfoUrl": { + "title": "InfoUrl", + "type": "object", + "properties": { + "type": { + "enum": [ + "facebook", + "from_resume", + "github", + "linkedin", + "twitter" + ] + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "type", + "url" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company": { + "description": "Company name of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the Company", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Experience.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Experience.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "Education": { + "title": "Education", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "school": { + "description": "School name of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the School", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Education.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Education.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Label": { + "title": "Label", + "type": "object", + "properties": { + "board_key": { + "description": "Identification key of the Board containing the target Job.", + "type": "string" + }, + "job_key": { + "description": "Identification key of the Job.", + "type": "string" + }, + "job_reference": { + "description": "Custom identifier of the Job.", + "type": "string" + }, + "stage": { + "description": "Stage associated to the Profile following the action of a recruiter (yes, no, later).", + "enum": [ + "later", + "no", + "yes" + ] + }, + "date_stage": { + "description": "Date of the stage edit action. type: ('datetime ISO 8601')", + "type": "string" + }, + "rating": { + "description": "Rating associated to the Profile following the action of a recruiter (from 1 to 5).", + "anyOf": [ + { + "enum": [ + 1, + 2, + 3, + 4, + 5 + ] + }, + { + "type": "null" + } + ] + }, + "date_rating": { + "description": "Date of the rating action. type: ('datetime ISO 8601')", + "type": "string" + } + }, + "required": [ + "board_key", + "job_key", + "job_reference", + "stage", + "date_stage", + "rating", + "date_rating" + ] + } + } + }, + "push_parameters": { + "title": "CreateCriterias", + "type": "object", + "properties": { + "source_key": { + "description": "HrFlow.ai source key", + "type": "string" + } + }, + "required": [ + "source_key" + ], + "$defs": {} + }, + "jsonmap": { + "reference": ".candidateDetail.id", + "created_at": ".candidateDetail.creationDate", + "updated_at": "$now('iso')", + "resume": ".attachments | .isResume ?? {raw: .raw, content_type: .mimeType} : null ", + "tags": "$merge([{ 'name': 'talentsoft-isEmployee', 'value': '.isEmployee'},{ 'name': 'talentsoft-isInProgress', 'value': '.isInProgress'},{ 'name': 'talentsoft-residentCountry-id', 'value': '.candidateDetail.personalInformation.residentCountry?.id'},{ 'name': 'talentsoft-contractType-id', 'value': '.candidateDetail.positionSought.contractType.id'},{ 'name': 'talentsoft-profileStatus-id', 'value': '.candidateDetail.positionSought.jobPreferencesCustomFields.customCodeTable1.id'},{ 'name': 'talentsoft-experienceLevel-id', 'value': '.candidateDetail.globalExperience.globalExperienceLevel.id'},{ 'name': 'talentsoft-profile-id', 'value': '.candidateDetail.positionSought.primaryProfile.id'},{ 'name': 'talentsofteducationLevel-id', 'value': '.candidateDetail.educations.educationLevel.id'}], .candidateDetail.educations | $map(.educationLevel != null ?? {name: 'talentsofteducationLevel-id', value: .educationLevel.id} ), .applications | $map({name: 'talentsoft-application-vacancyReference', value: .vacancyReference}))", + "metadatas": [ + { + "name": "profile_uid", + "value": ".candidateDetail.id" + }, + ".attachments | .isResume ?? {name: 'filename', value: .filename}" + ] + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.create_profiles_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.create_profiles_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.create_profiles_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.create_profiles_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.create_profiles_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + }, + { + "name": "update_profiles_in_hrflow", + "data_type": "profile", + "direction": "inbound", + "mode": "update", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "TalentSoft", + "origin_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadProfilesParameters", + "type": "object", + "properties": { + "filter": { + "description": "Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921'", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [], + "$defs": {} + }, + "target": "HrFlow", + "target_data_schema": { + "title": "HrFlowProfile", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "info": { + "description": "Object containing the Profile's info.", + "$ref": "#/$defs/ProfileInfo" + }, + "text_language": { + "description": "Code language of the Profile. type: string code ISO 639-1", + "type": "string" + }, + "text": { + "description": "Full text of the Profile.", + "type": "string" + }, + "archived_at": { + "description": "type: datetime ISO8601, Archive date of the Profile. The value is null for unarchived Profiles.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "experiences_duration": { + "description": "Total number of years of experience.", + "type": "number" + }, + "educations_duration": { + "description": "Total number of years of education.", + "type": "number" + }, + "experiences": { + "description": "List of experiences of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Experience" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "educations": { + "description": "List of educations of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Education" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "attachments": { + "description": "List of documents attached to the Profile.", + "type": "array", + "default": [] + }, + "skills": { + "description": "List of skills of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "List of spoken languages of the profile", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "List of certifications of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "List of courses of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "List of tasks of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "interests": { + "description": "List of interests of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "List of tags of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "List of metadatas of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "labels": { + "description": "List of labels of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "info", + "text_language", + "text", + "experiences_duration", + "educations_duration" + ], + "$defs": { + "ProfileInfo": { + "title": "ProfileInfo", + "type": "object", + "properties": { + "full_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "first_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "date_birth": { + "description": "Profile date of birth", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Profile location object", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "urls": { + "description": "Profile social networks and URLs", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/InfoUrl" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "picture": { + "description": "Profile picture url", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "gender": { + "description": "Profile gender", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Profile summary text", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "full_name", + "first_name", + "last_name", + "email", + "phone" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "InfoUrl": { + "title": "InfoUrl", + "type": "object", + "properties": { + "type": { + "enum": [ + "facebook", + "from_resume", + "github", + "linkedin", + "twitter" + ] + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "type", + "url" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company": { + "description": "Company name of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the Company", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Experience.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Experience.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "Education": { + "title": "Education", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "school": { + "description": "School name of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the School", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Education.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Education.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Label": { + "title": "Label", + "type": "object", + "properties": { + "board_key": { + "description": "Identification key of the Board containing the target Job.", + "type": "string" + }, + "job_key": { + "description": "Identification key of the Job.", + "type": "string" + }, + "job_reference": { + "description": "Custom identifier of the Job.", + "type": "string" + }, + "stage": { + "description": "Stage associated to the Profile following the action of a recruiter (yes, no, later).", + "enum": [ + "later", + "no", + "yes" + ] + }, + "date_stage": { + "description": "Date of the stage edit action. type: ('datetime ISO 8601')", + "type": "string" + }, + "rating": { + "description": "Rating associated to the Profile following the action of a recruiter (from 1 to 5).", + "anyOf": [ + { + "enum": [ + 1, + 2, + 3, + 4, + 5 + ] + }, + { + "type": "null" + } + ] + }, + "date_rating": { + "description": "Date of the rating action. type: ('datetime ISO 8601')", + "type": "string" + } + }, + "required": [ + "board_key", + "job_key", + "job_reference", + "stage", + "date_stage", + "rating", + "date_rating" + ] + } + } + }, + "push_parameters": { + "title": "UpdateCriterias", + "type": "object", + "properties": { + "source_key": { + "description": "HrFlow.ai source key", + "type": "string" + }, + "only_edit_fields": { + "description": "List of attributes to use for the edit operation e.g. ['tags', 'metadatas']", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "source_key" + ], + "$defs": {} + }, + "jsonmap": { + "reference": ".candidateDetail.id", + "created_at": ".candidateDetail.creationDate", + "updated_at": "$now('iso')", + "resume": ".attachments | .isResume ?? {raw: .raw, content_type: .mimeType} : null ", + "tags": "$merge([{ 'name': 'talentsoft-isEmployee', 'value': '.isEmployee'},{ 'name': 'talentsoft-isInProgress', 'value': '.isInProgress'},{ 'name': 'talentsoft-residentCountry-id', 'value': '.candidateDetail.personalInformation.residentCountry?.id'},{ 'name': 'talentsoft-contractType-id', 'value': '.candidateDetail.positionSought.contractType.id'},{ 'name': 'talentsoft-profileStatus-id', 'value': '.candidateDetail.positionSought.jobPreferencesCustomFields.customCodeTable1.id'},{ 'name': 'talentsoft-experienceLevel-id', 'value': '.candidateDetail.globalExperience.globalExperienceLevel.id'},{ 'name': 'talentsoft-profile-id', 'value': '.candidateDetail.positionSought.primaryProfile.id'},{ 'name': 'talentsofteducationLevel-id', 'value': '.candidateDetail.educations.educationLevel.id'}], .candidateDetail.educations | $map(.educationLevel != null ?? {name: 'talentsofteducationLevel-id', value: .educationLevel.id} ), .applications | $map({name: 'talentsoft-application-vacancyReference', value: .vacancyReference}))", + "metadatas": [ + { + "name": "profile_uid", + "value": ".candidateDetail.id" + }, + ".attachments | .isResume ?? {name: 'filename', value: .filename}" + ] + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.update_profiles_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.update_profiles_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key', 'only_edit_fields'):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.update_profiles_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.update_profiles_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key', 'only_edit_fields'):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.update_profiles_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + }, + { + "name": "archive_profiles_in_hrflow", + "data_type": "profile", + "direction": "inbound", + "mode": "archive", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "TalentSoft", + "origin_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadProfilesParameters", + "type": "object", + "properties": { + "filter": { + "description": "Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921'", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [], + "$defs": {} + }, + "target": "HrFlow", + "target_data_schema": { + "title": "HrFlowProfile", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "info": { + "description": "Object containing the Profile's info.", + "$ref": "#/$defs/ProfileInfo" + }, + "text_language": { + "description": "Code language of the Profile. type: string code ISO 639-1", + "type": "string" + }, + "text": { + "description": "Full text of the Profile.", + "type": "string" + }, + "archived_at": { + "description": "type: datetime ISO8601, Archive date of the Profile. The value is null for unarchived Profiles.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "experiences_duration": { + "description": "Total number of years of experience.", + "type": "number" + }, + "educations_duration": { + "description": "Total number of years of education.", + "type": "number" + }, + "experiences": { + "description": "List of experiences of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Experience" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "educations": { + "description": "List of educations of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Education" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "attachments": { + "description": "List of documents attached to the Profile.", + "type": "array", + "default": [] + }, + "skills": { + "description": "List of skills of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "List of spoken languages of the profile", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "List of certifications of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "List of courses of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "List of tasks of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "interests": { + "description": "List of interests of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "List of tags of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "List of metadatas of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "labels": { + "description": "List of labels of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "info", + "text_language", + "text", + "experiences_duration", + "educations_duration" + ], + "$defs": { + "ProfileInfo": { + "title": "ProfileInfo", + "type": "object", + "properties": { + "full_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "first_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "date_birth": { + "description": "Profile date of birth", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Profile location object", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "urls": { + "description": "Profile social networks and URLs", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/InfoUrl" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "picture": { + "description": "Profile picture url", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "gender": { + "description": "Profile gender", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Profile summary text", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "full_name", + "first_name", + "last_name", + "email", + "phone" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "InfoUrl": { + "title": "InfoUrl", + "type": "object", + "properties": { + "type": { + "enum": [ + "facebook", + "from_resume", + "github", + "linkedin", + "twitter" + ] + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "type", + "url" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company": { + "description": "Company name of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the Company", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Experience.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Experience.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "Education": { + "title": "Education", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "school": { + "description": "School name of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the School", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Education.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Education.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Label": { + "title": "Label", + "type": "object", + "properties": { + "board_key": { + "description": "Identification key of the Board containing the target Job.", + "type": "string" + }, + "job_key": { + "description": "Identification key of the Job.", + "type": "string" + }, + "job_reference": { + "description": "Custom identifier of the Job.", + "type": "string" + }, + "stage": { + "description": "Stage associated to the Profile following the action of a recruiter (yes, no, later).", + "enum": [ + "later", + "no", + "yes" + ] + }, + "date_stage": { + "description": "Date of the stage edit action. type: ('datetime ISO 8601')", + "type": "string" + }, + "rating": { + "description": "Rating associated to the Profile following the action of a recruiter (from 1 to 5).", + "anyOf": [ + { + "enum": [ + 1, + 2, + 3, + 4, + 5 + ] + }, + { + "type": "null" + } + ] + }, + "date_rating": { + "description": "Date of the rating action. type: ('datetime ISO 8601')", + "type": "string" + } + }, + "required": [ + "board_key", + "job_key", + "job_reference", + "stage", + "date_stage", + "rating", + "date_rating" + ] + } + } + }, + "push_parameters": { + "title": "ArchiveCriterias", + "type": "object", + "properties": { + "source_key": { + "description": "HrFlow.ai source key", + "type": "string" + } + }, + "required": [ + "source_key" + ], + "$defs": {} + }, + "jsonmap": { + "reference": ".id" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.archive_profiles_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.archive_profiles_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.archive_profiles_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.archive_profiles_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('filter',):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('source_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.archive_profiles_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + }, + { + "name": "create_jobs_in_hrflow", + "data_type": "job", + "direction": "inbound", + "mode": "create", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "TalentSoft", + "origin_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "supports_incremental": true, + "pull_parameters": { + "title": "ReadJobsParameters", + "type": "object", + "properties": { + "q": { + "description": "Query search to get vacancies", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "filter": { + "description": "Filter to apply when reading vacancies. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-vacancies-get . . You can filter by **chronoNumber**, **updateDate**, **reference** **vacancyStatus**, **clientVacancyStatus**, **publicationMedia** **publishedOnTheMedia**. Examples : By reference Single Item 'reference::2019-01'; By reference Multiple Items 'reference::2019-01,2019-02,2019-03'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' . ", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "max_read": { + "description": "The maximum number of jobs to pull during the execution. Proper tuning of this parameter should allow to control the execution time and avoid overtimes", + "type": "integer", + "default": 100 + } + }, + "required": [], + "$defs": {} + }, + "target": "HrFlow", + "target_data_schema": { + "title": "HrFlowJob", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "name": { + "description": "Job title.", + "type": "string" + }, + "location": { + "description": "Job location object.", + "$ref": "#/$defs/Location" + }, + "sections": { + "description": "Job custom sections.", + "type": "array", + "items": { + "$ref": "#/$defs/Section" + } + }, + "url": { + "description": "Job post original URL.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Brief summary of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "archieved_at": { + "description": "type: datetime ISO8601, Archive date of the Job. The value is null for unarchived Jobs.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "list of skills of the Job.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "list of spoken languages of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "list of certifications of the Job.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "list of courses of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "list of tasks of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "list of tags of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "list of metadatas of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "ranges_float": { + "description": "list of ranges of floats", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/RangesFloat" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "ranges_date": { + "description": "list of ranges of dates", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/RangesDate" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "location", + "sections" + ], + "$defs": { + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "Section": { + "title": "Section", + "type": "object", + "properties": { + "name": { + "description": "Identification name of a Section of the Job. Example: culture", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Display Title of a Section. Example: Corporate Culture", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Text description of a Section: Example: Our values areNone", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "RangesFloat": { + "title": "RangesFloat", + "type": "object", + "properties": { + "name": { + "description": "Identification name of a Range of floats attached to the Job. Example: salary", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_min": { + "description": "Min value. Example: 500.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_max": { + "description": "Max value. Example: 100.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "unit": { + "description": "Unit of the value. Example: euros.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "RangesDate": { + "title": "RangesDate", + "type": "object", + "properties": { + "name": { + "description": "Identification name of a Range of dates attached to the Job. Example: availability.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_min": { + "description": "Min value in datetime ISO 8601, Example: 500.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_max": { + "description": "Max value in datetime ISO 8601, Example: 1000", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + } + } + }, + "push_parameters": { + "title": "CreateCriterias", + "type": "object", + "properties": { + "board_key": { + "description": "HrFlow.ai board key", + "type": "string" + }, + "enrich_with_parsing": { + "description": "When enabled jobs are enriched with HrFlow.ai parsing", + "type": "boolean", + "default": false + } + }, + "required": [ + "board_key" + ], + "$defs": {} + }, + "jsonmap": { + "reference": ".reference", + "created_at": ".creationDate", + "location": { + "text": ".location.address", + "lat": ".location.latitude", + "lng": ".location.longitude" + }, + "url": null, + "summary": null, + "sections": [ + { + "name": "description1", + "title": "description1", + "description": ".jobDescription.description1 >> ''" + }, + { + "name": "description2", + "title": "description2", + "description": ".jobDescription.description2 >> ''" + }, + { + "name": "'Compl\u00e9ment du descriptif'", + "title": "'Compl\u00e9ment du descriptif'", + "description": "$concat(.jobDescription.jobDescriptionCustomFields.longText1 >> '', '\n' , .jobDescription.jobDescriptionCustomFields.longText2>> '', '\n' ,.jobDescription.jobDescriptionCustomFields.longText3>> '')" + } + ], + "tags": [ + { + "name": "talentsoft-organisation-id", + "value": "?.organisation?.id" + }, + { + "name": "talentsoft-status-id", + "value": "?.status?.id" + }, + { + "name": "talentsoft-professionalCategory-id", + "value": "?.jobDescription.professionalCategory?.id" + }, + { + "name": "talentsoft-country-id", + "value": "?.jobDescription.country?.id" + }, + { + "name": "talentsoft-primaryProfile-id", + "value": "?.jobDescription.primaryProfile?.id" + }, + { + "name": "talentsoft-contractType-id", + "value": "?.jobDescription.contractType?.id" + }, + { + "name": "talentsoft-publishedOnInternet", + "value": "?.publishedOnInternet" + }, + { + "name": "talentsoft-publishedOnIntranet", + "value": "?.publishedOnIntranet" + }, + { + "name": "talentsoft-experienceLevel", + "value": "?.criteria.experienceLevel?.id" + }, + { + "name": "talentsoft-educationLevel", + "value": "?.criteria.educationLevel?.id" + } + ], + "skills": ".criteria.skills", + "languages": "?.languages >> [] | {name: .language.label, value: null}" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.create_jobs_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.create_jobs_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('q', 'filter', 'max_read'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('board_key', 'enrich_with_parsing'):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.create_jobs_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.create_jobs_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('q', 'filter', 'max_read'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('board_key', 'enrich_with_parsing'):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.create_jobs_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + }, + { + "name": "update_jobs_in_hrflow", + "data_type": "job", + "direction": "inbound", + "mode": "update", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "TalentSoft", + "origin_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadJobsParameters", + "type": "object", + "properties": { + "q": { + "description": "Query search to get vacancies", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "filter": { + "description": "Filter to apply when reading vacancies. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-vacancies-get . . You can filter by **chronoNumber**, **updateDate**, **reference** **vacancyStatus**, **clientVacancyStatus**, **publicationMedia** **publishedOnTheMedia**. Examples : By reference Single Item 'reference::2019-01'; By reference Multiple Items 'reference::2019-01,2019-02,2019-03'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' . ", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "max_read": { + "description": "The maximum number of jobs to pull during the execution. Proper tuning of this parameter should allow to control the execution time and avoid overtimes", + "type": "integer", + "default": 100 + } + }, + "required": [], + "$defs": {} + }, + "target": "HrFlow", + "target_data_schema": { + "title": "HrFlowJob", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "name": { + "description": "Job title.", + "type": "string" + }, + "location": { + "description": "Job location object.", + "$ref": "#/$defs/Location" + }, + "sections": { + "description": "Job custom sections.", + "type": "array", + "items": { + "$ref": "#/$defs/Section" + } + }, + "url": { + "description": "Job post original URL.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Brief summary of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "archieved_at": { + "description": "type: datetime ISO8601, Archive date of the Job. The value is null for unarchived Jobs.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "list of skills of the Job.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "list of spoken languages of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "list of certifications of the Job.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "list of courses of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "list of tasks of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "list of tags of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "list of metadatas of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "ranges_float": { + "description": "list of ranges of floats", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/RangesFloat" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "ranges_date": { + "description": "list of ranges of dates", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/RangesDate" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "location", + "sections" + ], + "$defs": { + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "Section": { + "title": "Section", + "type": "object", + "properties": { + "name": { + "description": "Identification name of a Section of the Job. Example: culture", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Display Title of a Section. Example: Corporate Culture", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Text description of a Section: Example: Our values areNone", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "RangesFloat": { + "title": "RangesFloat", + "type": "object", + "properties": { + "name": { + "description": "Identification name of a Range of floats attached to the Job. Example: salary", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_min": { + "description": "Min value. Example: 500.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_max": { + "description": "Max value. Example: 100.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "unit": { + "description": "Unit of the value. Example: euros.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "RangesDate": { + "title": "RangesDate", + "type": "object", + "properties": { + "name": { + "description": "Identification name of a Range of dates attached to the Job. Example: availability.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_min": { + "description": "Min value in datetime ISO 8601, Example: 500.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_max": { + "description": "Max value in datetime ISO 8601, Example: 1000", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + } + } + }, + "push_parameters": { + "title": "UpdateCriterias", + "type": "object", + "properties": { + "board_key": { + "description": "HrFlow.ai board key", + "type": "string" + } + }, + "required": [ + "board_key" + ], + "$defs": {} + }, + "jsonmap": { + "name": ".jobDescription.title", + "reference": ".reference", + "created_at": ".creationDate", + "location": { + "text": ".location.address", + "lat": ".location.latitude", + "lng": ".location.longitude" + }, + "url": null, + "summary": null, + "sections": [ + { + "name": "description1", + "title": "description1", + "description": ".jobDescription.description1 >> ''" + }, + { + "name": "description2", + "title": "description2", + "description": ".jobDescription.description2 >> ''" + }, + { + "name": "'Compl\u00e9ment du descriptif'", + "title": "'Compl\u00e9ment du descriptif'", + "description": "$concat(.jobDescription.jobDescriptionCustomFields.longText1 >> '', '\n' , .jobDescription.jobDescriptionCustomFields.longText2>> '', '\n' ,.jobDescription.jobDescriptionCustomFields.longText3>> '')" + } + ], + "tags": [ + { + "name": "talentsoft-organisation-id", + "value": "?.organisation?.id" + }, + { + "name": "talentsoft-status-id", + "value": "?.status?.id" + }, + { + "name": "talentsoft-professionalCategory-id", + "value": "?.jobDescription.professionalCategory?.id" + }, + { + "name": "talentsoft-country-id", + "value": "?.jobDescription.country?.id" + }, + { + "name": "talentsoft-primaryProfile-id", + "value": "?.jobDescription.primaryProfile?.id" + }, + { + "name": "talentsoft-contractType-id", + "value": "?.jobDescription.contractType?.id" + }, + { + "name": "talentsoft-publishedOnInternet", + "value": "?.publishedOnInternet" + }, + { + "name": "talentsoft-publishedOnIntranet", + "value": "?.publishedOnIntranet" + }, + { + "name": "talentsoft-experienceLevel", + "value": "?.criteria.experienceLevel?.id" + }, + { + "name": "talentsoft-educationLevel", + "value": "?.criteria.educationLevel?.id" + } + ], + "skills": ".criteria.skills", + "languages": "?.languages >> [] | {name: .language.label, value: null}" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.update_jobs_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.update_jobs_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('q', 'filter', 'max_read'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('board_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.update_jobs_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.update_jobs_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('q', 'filter', 'max_read'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('board_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.update_jobs_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + }, + { + "name": "archive_jobs_in_hrflow", + "data_type": "job", + "direction": "inbound", + "mode": "archive", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "TalentSoft", + "origin_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadJobsParameters", + "type": "object", + "properties": { + "q": { + "description": "Query search to get vacancies", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "filter": { + "description": "Filter to apply when reading vacancies. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-vacancies-get . . You can filter by **chronoNumber**, **updateDate**, **reference** **vacancyStatus**, **clientVacancyStatus**, **publicationMedia** **publishedOnTheMedia**. Examples : By reference Single Item 'reference::2019-01'; By reference Multiple Items 'reference::2019-01,2019-02,2019-03'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' . ", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "max_read": { + "description": "The maximum number of jobs to pull during the execution. Proper tuning of this parameter should allow to control the execution time and avoid overtimes", + "type": "integer", + "default": 100 + } + }, + "required": [], + "$defs": {} + }, + "target": "HrFlow", + "target_data_schema": { + "title": "HrFlowJob", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "name": { + "description": "Job title.", + "type": "string" + }, + "location": { + "description": "Job location object.", + "$ref": "#/$defs/Location" + }, + "sections": { + "description": "Job custom sections.", + "type": "array", + "items": { + "$ref": "#/$defs/Section" + } + }, + "url": { + "description": "Job post original URL.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Brief summary of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "archieved_at": { + "description": "type: datetime ISO8601, Archive date of the Job. The value is null for unarchived Jobs.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Job.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "list of skills of the Job.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "list of spoken languages of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "list of certifications of the Job.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "list of courses of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "list of tasks of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "list of tags of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "list of metadatas of the Job", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "ranges_float": { + "description": "list of ranges of floats", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/RangesFloat" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "ranges_date": { + "description": "list of ranges of dates", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/RangesDate" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "location", + "sections" + ], + "$defs": { + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "Section": { + "title": "Section", + "type": "object", + "properties": { + "name": { + "description": "Identification name of a Section of the Job. Example: culture", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Display Title of a Section. Example: Corporate Culture", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Text description of a Section: Example: Our values areNone", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "RangesFloat": { + "title": "RangesFloat", + "type": "object", + "properties": { + "name": { + "description": "Identification name of a Range of floats attached to the Job. Example: salary", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_min": { + "description": "Min value. Example: 500.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_max": { + "description": "Max value. Example: 100.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "unit": { + "description": "Unit of the value. Example: euros.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "RangesDate": { + "title": "RangesDate", + "type": "object", + "properties": { + "name": { + "description": "Identification name of a Range of dates attached to the Job. Example: availability.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_min": { + "description": "Min value in datetime ISO 8601, Example: 500.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "value_max": { + "description": "Max value in datetime ISO 8601, Example: 1000", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + } + } + }, + "push_parameters": { + "title": "ArchiveCriterias", + "type": "object", + "properties": { + "board_key": { + "description": "HrFlow.ai board key", + "type": "string" + } + }, + "required": [ + "board_key" + ], + "$defs": {} + }, + "jsonmap": { + "reference": ".reference" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.archive_jobs_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.archive_jobs_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('q', 'filter', 'max_read'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('board_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.archive_jobs_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.archive_jobs_in_hrflow(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('q', 'filter', 'max_read'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('board_key',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.archive_jobs_in_hrflow(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + }, + { + "name": "create_profiles_in_talentsoft", + "data_type": "profile", + "direction": "outbound", + "mode": "create", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "HrFlow", + "origin_data_schema": { + "title": "HrFlowProfile", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "info": { + "description": "Object containing the Profile's info.", + "$ref": "#/$defs/ProfileInfo" + }, + "text_language": { + "description": "Code language of the Profile. type: string code ISO 639-1", + "type": "string" + }, + "text": { + "description": "Full text of the Profile.", + "type": "string" + }, + "archived_at": { + "description": "type: datetime ISO8601, Archive date of the Profile. The value is null for unarchived Profiles.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "experiences_duration": { + "description": "Total number of years of experience.", + "type": "number" + }, + "educations_duration": { + "description": "Total number of years of education.", + "type": "number" + }, + "experiences": { + "description": "List of experiences of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Experience" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "educations": { + "description": "List of educations of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Education" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "attachments": { + "description": "List of documents attached to the Profile.", + "type": "array", + "default": [] + }, + "skills": { + "description": "List of skills of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "List of spoken languages of the profile", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "List of certifications of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "List of courses of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "List of tasks of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "interests": { + "description": "List of interests of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "List of tags of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "List of metadatas of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "labels": { + "description": "List of labels of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "info", + "text_language", + "text", + "experiences_duration", + "educations_duration" + ], + "$defs": { + "ProfileInfo": { + "title": "ProfileInfo", + "type": "object", + "properties": { + "full_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "first_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "date_birth": { + "description": "Profile date of birth", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Profile location object", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "urls": { + "description": "Profile social networks and URLs", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/InfoUrl" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "picture": { + "description": "Profile picture url", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "gender": { + "description": "Profile gender", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Profile summary text", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "full_name", + "first_name", + "last_name", + "email", + "phone" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "InfoUrl": { + "title": "InfoUrl", + "type": "object", + "properties": { + "type": { + "enum": [ + "facebook", + "from_resume", + "github", + "linkedin", + "twitter" + ] + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "type", + "url" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company": { + "description": "Company name of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the Company", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Experience.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Experience.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "Education": { + "title": "Education", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "school": { + "description": "School name of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the School", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Education.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Education.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Label": { + "title": "Label", + "type": "object", + "properties": { + "board_key": { + "description": "Identification key of the Board containing the target Job.", + "type": "string" + }, + "job_key": { + "description": "Identification key of the Job.", + "type": "string" + }, + "job_reference": { + "description": "Custom identifier of the Job.", + "type": "string" + }, + "stage": { + "description": "Stage associated to the Profile following the action of a recruiter (yes, no, later).", + "enum": [ + "later", + "no", + "yes" + ] + }, + "date_stage": { + "description": "Date of the stage edit action. type: ('datetime ISO 8601')", + "type": "string" + }, + "rating": { + "description": "Rating associated to the Profile following the action of a recruiter (from 1 to 5).", + "anyOf": [ + { + "enum": [ + 1, + 2, + 3, + 4, + 5 + ] + }, + { + "type": "null" + } + ] + }, + "date_rating": { + "description": "Date of the rating action. type: ('datetime ISO 8601')", + "type": "string" + } + }, + "required": [ + "board_key", + "job_key", + "job_reference", + "stage", + "date_stage", + "rating", + "date_rating" + ] + } + } + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadAllModesCriterias", + "type": "object", + "properties": { + "source_key": { + "description": "HrFlow.ai source key", + "type": "string" + }, + "profile_key": { + "description": "HrFlow.ai profile key", + "type": "string" + } + }, + "required": [ + "source_key", + "profile_key" + ], + "$defs": {} + }, + "target": "TalentSoft", + "target_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "push_parameters": { + "title": "WriteProfileParameters", + "type": "object", + "properties": { + "job_reference": { + "description": "reference of the job offer to which the candidate is applying", + "type": "string" + } + }, + "required": [ + "job_reference" + ], + "$defs": {} + }, + "jsonmap": { + "#CONTRACT_TYPE_REFERENTIAL": { + "Alternance": { + "code": 1047, + "clientCode": "_TS_CO_Contract_Alternance", + "label": "Apprenticeship", + "type": "contractType", + "parentType": "" + }, + "CDD": { + "code": 1045, + "clientCode": "_TS_CO_Contract_CDD", + "label": "Fixed Term contract", + "type": "contractType", + "parentType": "" + }, + "CDI": { + "code": 1044, + "clientCode": "_TS_CO_Contract_CDI", + "label": "Permanent", + "type": "contractType", + "parentType": "" + }, + "CIFRE": { + "code": 1049, + "clientCode": "_TS_CO_Contract_CIFRE", + "label": "CIFRE", + "type": "contractType", + "parentType": "" + }, + "Stage": { + "code": 1046, + "clientCode": "_TS_CO_Contract_Stage", + "label": "Internship / Student", + "type": "contractType", + "parentType": "" + }, + "VIE": { + "code": 1048, + "clientCode": "_TS_CO_Contract_VIE", + "label": "VIE", + "type": "contractType", + "parentType": "" + } + }, + "#EDUCATIONS_REFERENTIEL": { + "Aucun dipl\u00f4me": { + "code": 261, + "clientCode": "_TS_etude_min_Aucun_diplome", + "label": "No Degree", + "type": "educationLevel", + "parentType": "" + }, + "BAC": { + "code": 262, + "clientCode": "_TS_etude_min_BAC", + "label": "Bac", + "type": "educationLevel", + "parentType": "" + }, + "BAC+2": { + "code": 2859, + "clientCode": "_TS_etude_min_BAC2", + "label": "A Levels, Diploma", + "type": "educationLevel", + "parentType": "" + }, + "BAC+3": { + "code": 4028, + "clientCode": "_TS_etude_min_Licence", + "label": "Licence", + "type": "educationLevel", + "parentType": "" + }, + "BAC+4": { + "code": 2860, + "clientCode": "_TS_etude_min_BAC4", + "label": "Bachelor's Degree", + "type": "educationLevel", + "parentType": "" + }, + "BAC+5": { + "code": 266, + "clientCode": "_TS_etude_min_BAC5", + "label": "Master Degree", + "type": "educationLevel", + "parentType": "" + }, + "CAP, BEP": { + "code": 2858, + "clientCode": "_TS_etude_min_CAP_BEP", + "label": "GCSEs", + "type": "educationLevel", + "parentType": "" + }, + "DOCTORAT": { + "code": 2861, + "clientCode": "_TS_etude_min_DOCTORAT", + "label": "PhD, Doctorate", + "type": "educationLevel", + "parentType": "" + }, + "Mast\u00e8re": { + "code": 4030, + "clientCode": "_TS_etude_min_Mastere", + "label": "Mast\u00e8re", + "type": "educationLevel", + "parentType": "" + } + }, + "#EXPERIENCES_REFERENTIEL": { + "Etudiant-e": "", + "D\u00e9butant-e/premi\u00e8re exp\u00e9rience": { + "code": 274, + "clientCode": "_TS_niveau_exp_premiere_exp", + "label": "First experience", + "type": "experienceLevel", + "parentType": "" + }, + "Sup\u00e9rieure \u00e0 3 ans": { + "code": 1785, + "clientCode": "_TS_niveau_exp_superieur_3ans ", + "label": "More than 3 years", + "type": "experienceLevel", + "parentType": "" + }, + "Sup\u00e9rieure \u00e0 5 ans": { + "code": 1783, + "clientCode": "_TS_niveau_exp_superieur_5ans", + "label": "More than 5 years", + "type": "experienceLevel", + "parentType": "" + }, + "Sup\u00e9rieure \u00e0 8 ans": { + "code": 275, + "clientCode": "_TS_niveau_exp_superieur_8ans", + "label": "More than 8 years", + "type": "experienceLevel", + "parentType": "" + } + }, + "applicant": { + "personalInformation": { + "firstName": ".info.first_name", + "lastName": ".info.last_name", + "birthDate": ".info.date_birth", + "phoneNumber": ".info.phone", + "email": ".info.email", + "address": ".info.location.text", + "city": ".info.location.fields?.city >> ''", + "postalCode": ".info.location.fields?.postalCode >> ''", + "civility": ".info?.gender != null ?? .info.gender | {code: . == 'male' ?? 280: 281, clientCode: . == 'male' ?? '_TS_CO_Civility_Mr': '_TS_CO_Civility_Mme' , label: . == 'male' ?? 'Mr.': 'Ms.', type: 'civility', parentType: ''}: null" + }, + "jobPreferences": { + "contractType": ".tags | .name == 'talentsoft_contract_type' ?? #CONTRACT_TYPE_REFERENTIAL.[.value]: null", + "salaryPretensions": ".tags | .name == 'talentsoft_salary' ?? .value: null" + }, + "education": { + "diplomas": "$merge(.tags | .name == 'talentsoft_experience_level' ?? [{educationLevel: #EDUCATIONS_REFERENTIEL.[.value]}]: [], .educations | $map({college: .school, yearObtained: .date_end ?? .date_end | $slice(0, 3): ''}))" + }, + "experiences": { + "experienceLevel": ".tags | .name == 'talentsoft_experience_level' ?? #EXPERIENCES_REFERENTIEL.[.value]: null", + "experienceList": ".experiences | $map({company: .company, function: .title, length: .date_start != null and .date_end != null ?? '<< MISSING ARITHMETICS HERE >>' : null })" + } + }, + "application": { + "type": "offer", + "offerReference": "" + }, + "uploadedFiles": [ + { + "description": ".attachments[0].original_file_name", + "fileTypeId": 36, + "key": "cv_file_id" + } + ], + "attachment": ".attachments[0]" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.create_profiles_in_talentsoft(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.create_profiles_in_talentsoft(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('source_key', 'profile_key'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('job_reference',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.create_profiles_in_talentsoft(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.create_profiles_in_talentsoft(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('source_key', 'profile_key'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ('job_reference',):\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.create_profiles_in_talentsoft(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + }, + { + "name": "update_profiles_in_talentsoft", + "data_type": "profile", + "direction": "outbound", + "mode": "update", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "client_id": { + "description": "client id used to access TalentSoft front office API", + "type": "string" + }, + "client_secret": { + "description": "client secret used to access TalentSoft front office API", + "type": "string" + }, + "client_url": { + "description": "url used to access TalentSoft front office API", + "type": "string" + } + }, + "required": [ + "client_id", + "client_secret", + "client_url" + ], + "$defs": {} + }, + "hrflow_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "api_secret": { + "description": "API Key used to access HrFlow.ai API", + "type": "string" + }, + "api_user": { + "description": "User email used to access HrFlow.ai API", + "type": "string" + } + }, + "required": [ + "api_secret", + "api_user" + ], + "$defs": {} + }, + "origin": "HrFlow", + "origin_data_schema": { + "title": "HrFlowProfile", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "reference": { + "description": "Custom identifier of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "info": { + "description": "Object containing the Profile's info.", + "$ref": "#/$defs/ProfileInfo" + }, + "text_language": { + "description": "Code language of the Profile. type: string code ISO 639-1", + "type": "string" + }, + "text": { + "description": "Full text of the Profile.", + "type": "string" + }, + "archived_at": { + "description": "type: datetime ISO8601, Archive date of the Profile. The value is null for unarchived Profiles.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "updated_at": { + "description": "type: datetime ISO8601, Last update date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "created_at": { + "description": "type: datetime ISO8601, Creation date of the Profile.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "experiences_duration": { + "description": "Total number of years of experience.", + "type": "number" + }, + "educations_duration": { + "description": "Total number of years of education.", + "type": "number" + }, + "experiences": { + "description": "List of experiences of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Experience" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "educations": { + "description": "List of educations of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Education" + } + }, + { + "type": "null" + } + ], + "default": [] + }, + "attachments": { + "description": "List of documents attached to the Profile.", + "type": "array", + "default": [] + }, + "skills": { + "description": "List of skills of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "languages": { + "description": "List of spoken languages of the profile", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "description": "List of certifications of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "courses": { + "description": "List of courses of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tasks": { + "description": "List of tasks of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "interests": { + "description": "List of interests of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "tags": { + "description": "List of tags of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "metadatas": { + "description": "List of metadatas of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "labels": { + "description": "List of labels of the Profile.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + } + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "info", + "text_language", + "text", + "experiences_duration", + "educations_duration" + ], + "$defs": { + "ProfileInfo": { + "title": "ProfileInfo", + "type": "object", + "properties": { + "full_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "first_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "date_birth": { + "description": "Profile date of birth", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Profile location object", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "urls": { + "description": "Profile social networks and URLs", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/InfoUrl" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "picture": { + "description": "Profile picture url", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "gender": { + "description": "Profile gender", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "description": "Profile summary text", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "full_name", + "first_name", + "last_name", + "email", + "phone" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "text": { + "description": "Location text address.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "lat": { + "description": "Geocentric latitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "lng": { + "description": "Geocentric longitude of the Location.", + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null + }, + "fields": { + "description": "other location attributes like country, country_code etc", + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [] + }, + "InfoUrl": { + "title": "InfoUrl", + "type": "object", + "properties": { + "type": { + "enum": [ + "facebook", + "from_resume", + "github", + "linkedin", + "twitter" + ] + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "type", + "url" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company": { + "description": "Company name of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the Company", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Experience.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Experience.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the experience. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Experience.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Skill": { + "title": "Skill", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the skill", + "type": "string" + }, + "type": { + "description": "Type of the skill. hard or soft", + "enum": [ + "hard", + "soft" + ] + }, + "value": { + "description": "Value associated to the skill", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name", + "type" + ] + }, + "GeneralEntitySchema": { + "title": "GeneralEntitySchema", + "type": "object", + "properties": { + "name": { + "description": "Identification name of the Object", + "type": "string" + }, + "value": { + "description": "Value associated to the Object's name", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "name" + ] + }, + "Education": { + "title": "Education", + "type": "object", + "properties": { + "key": { + "description": "Identification key of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "school": { + "description": "School name of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "logo": { + "description": "Logo of the School", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "title": { + "description": "Title of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "description": { + "description": "Description of the Education.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "location": { + "description": "Location object of the Education.", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Location" + } + ], + "default": null + }, + "date_start": { + "description": "Start date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "date_end": { + "description": "End date of the Education. type: ('datetime ISO 8601')", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "skills": { + "description": "List of skills of the Education.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/Skill" + } + }, + { + "type": "null" + } + ], + "default": null + }, + "certifications": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "courses": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + }, + "tasks": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/GeneralEntitySchema" + } + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "certifications", + "courses", + "tasks" + ] + }, + "Label": { + "title": "Label", + "type": "object", + "properties": { + "board_key": { + "description": "Identification key of the Board containing the target Job.", + "type": "string" + }, + "job_key": { + "description": "Identification key of the Job.", + "type": "string" + }, + "job_reference": { + "description": "Custom identifier of the Job.", + "type": "string" + }, + "stage": { + "description": "Stage associated to the Profile following the action of a recruiter (yes, no, later).", + "enum": [ + "later", + "no", + "yes" + ] + }, + "date_stage": { + "description": "Date of the stage edit action. type: ('datetime ISO 8601')", + "type": "string" + }, + "rating": { + "description": "Rating associated to the Profile following the action of a recruiter (from 1 to 5).", + "anyOf": [ + { + "enum": [ + 1, + 2, + 3, + 4, + 5 + ] + }, + { + "type": "null" + } + ] + }, + "date_rating": { + "description": "Date of the rating action. type: ('datetime ISO 8601')", + "type": "string" + } + }, + "required": [ + "board_key", + "job_key", + "job_reference", + "stage", + "date_stage", + "rating", + "date_rating" + ] + } + } + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadAllModesCriterias", + "type": "object", + "properties": { + "source_key": { + "description": "HrFlow.ai source key", + "type": "string" + }, + "profile_key": { + "description": "HrFlow.ai profile key", + "type": "string" + } + }, + "required": [ + "source_key", + "profile_key" + ], + "$defs": {} + }, + "target": "TalentSoft", + "target_data_schema": { + "title": "Struct", + "description": "A base class for defining efficient serializable objects.\n\nFields are defined using type annotations. Fields may optionally have\ndefault values, which result in keyword parameters to the constructor.\n\nStructs automatically define ``__init__``, ``__eq__``, ``__repr__``, and\n``__copy__`` methods. Additional methods can be defined on the class as\nneeded. Note that ``__init__``/``__new__`` cannot be overridden, but other\nmethods can. A tuple of the field names is available on the class via the\n``__struct_fields__`` attribute if needed.\n\nAdditional class options can be enabled by passing keywords to the class\ndefinition (see example below). These configuration options may also be\ninspected at runtime through the ``__struct_config__`` attribute.\n\nConfiguration\n-------------\nfrozen: bool, default False\n Whether instances of this type are pseudo-immutable. If true, attribute\n assignment is disabled and a corresponding ``__hash__`` is defined.\norder: bool, default False\n If True, ``__lt__``, `__le__``, ``__gt__``, and ``__ge__`` methods\n will be generated for this type.\neq: bool, default True\n If True (the default), an ``__eq__`` method will be generated for this\n type. Set to False to compare based on instance identity alone.\nkw_only: bool, default False\n If True, all fields will be treated as keyword-only arguments in the\n generated ``__init__`` method. Default is False.\nomit_defaults: bool, default False\n Whether fields should be omitted from encoding if the corresponding value\n is the default for that field. Enabling this may reduce message size, and\n often also improve encoding & decoding performance.\nforbid_unknown_fields: bool, default False\n If True, an error is raised if an unknown field is encountered while\n decoding structs of this type. If False (the default), no error is raised\n and the unknown field is skipped.\ntag: str, int, bool, callable, or None, default None\n Used along with ``tag_field`` for configuring tagged union support. If\n either are non-None, then the struct is considered \"tagged\". In this case,\n an extra field (the ``tag_field``) and value (the ``tag``) are added to the\n encoded message, which can be used to differentiate message types during\n decoding.\n\n Set ``tag=True`` to enable the default tagged configuration (``tag_field``\n is ``\"type\"``, ``tag`` is the class name). Alternatively, you can provide\n a string (or less commonly int) value directly to be used as the tag\n (e.g. ``tag=\"my-tag-value\"``).``tag`` can also be passed a callable that\n takes the class qualname and returns a valid tag value (e.g.\n ``tag=str.lower``). See the docs for more information.\ntag_field: str or None, default None\n The field name to use for tagged union support. If ``tag`` is non-None,\n then this defaults to ``\"type\"``. See the ``tag`` docs above for more\n information.\nrename: str, mapping, callable, or None, default None\n Controls renaming the field names used when encoding/decoding the struct.\n May be one of ``\"lower\"``, ``\"upper\"``, ``\"camel\"``, ``\"pascal\"``, or\n ``\"kebab\"`` to rename in lowercase, UPPERCASE, camelCase, PascalCase,\n or kebab-case respectively. May also be a mapping from field names to the\n renamed names (missing fields are not renamed). Alternatively, may be a\n callable that takes the field name and returns a new name or ``None`` to\n not rename that field. Default is ``None`` for no field renaming.\nrepr_omit_defaults: bool, default False\n Whether fields should be omitted from the generated repr if the\n corresponding value is the default for that field.\narray_like: bool, default False\n If True, this struct type will be treated as an array-like type during\n encoding/decoding, rather than a dict-like type (the default). This may\n improve performance, at the cost of a more inscrutable message encoding.\ngc: bool, default True\n Whether garbage collection is enabled for this type. Disabling this *may*\n help reduce GC pressure, but will prevent reference cycles composed of only\n ``gc=False`` from being collected. It is the user's responsibility to ensure\n that reference cycles don't occur when setting ``gc=False``.\nweakref: bool, default False\n Whether instances of this type support weak references. Defaults to False.\ndict: bool, default False\n Whether instances of this type will include a ``__dict__``. Setting this to\n True will allow adding additional undeclared attributes to a struct instance,\n which may be useful for holding private runtime state. Defaults to False.\ncache_hash: bool, default False\n If enabled, the hash of a frozen struct instance will be computed at most\n once, and then cached on the instance for further reuse. For expensive\n hash values this can improve performance at the cost of a small amount of\n memory usage.\n\nExamples\n--------\nHere we define a new `Struct` type for describing a dog. It has three fields;\ntwo required and one optional.\n\n>>> class Dog(Struct):\n... name: str\n... breed: str\n... is_good_boy: bool = True\n...\n>>> Dog('snickers', breed='corgi')\nDog(name='snickers', breed='corgi', is_good_boy=True)\n\nAdditional struct options can be set as part of the class definition. Here\nwe define a new `Struct` type for a frozen `Point` object.\n\n>>> class Point(Struct, frozen=True):\n... x: float\n... y: float\n...\n>>> {Point(1.5, 2.0): 1} # frozen structs are hashable\n{Point(x=1.5, y=2.0): 1}", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "push_parameters": { + "title": "UpdateProfileParameters", + "type": "object", + "properties": {}, + "required": [], + "$defs": {} + }, + "jsonmap": { + "#CONTRACT_TYPE_REFERENTIAL": { + "Alternance": { + "code": 1047, + "clientCode": "_TS_CO_Contract_Alternance", + "label": "Apprenticeship", + "type": "contractType", + "parentType": "" + }, + "CDD": { + "code": 1045, + "clientCode": "_TS_CO_Contract_CDD", + "label": "Fixed Term contract", + "type": "contractType", + "parentType": "" + }, + "CDI": { + "code": 1044, + "clientCode": "_TS_CO_Contract_CDI", + "label": "Permanent", + "type": "contractType", + "parentType": "" + }, + "CIFRE": { + "code": 1049, + "clientCode": "_TS_CO_Contract_CIFRE", + "label": "CIFRE", + "type": "contractType", + "parentType": "" + }, + "Stage": { + "code": 1046, + "clientCode": "_TS_CO_Contract_Stage", + "label": "Internship / Student", + "type": "contractType", + "parentType": "" + }, + "VIE": { + "code": 1048, + "clientCode": "_TS_CO_Contract_VIE", + "label": "VIE", + "type": "contractType", + "parentType": "" + } + }, + "#EDUCATIONS_REFERENTIEL": { + "Aucun dipl\u00f4me": { + "code": 261, + "clientCode": "_TS_etude_min_Aucun_diplome", + "label": "No Degree", + "type": "educationLevel", + "parentType": "" + }, + "BAC": { + "code": 262, + "clientCode": "_TS_etude_min_BAC", + "label": "Bac", + "type": "educationLevel", + "parentType": "" + }, + "BAC+2": { + "code": 2859, + "clientCode": "_TS_etude_min_BAC2", + "label": "A Levels, Diploma", + "type": "educationLevel", + "parentType": "" + }, + "BAC+3": { + "code": 4028, + "clientCode": "_TS_etude_min_Licence", + "label": "Licence", + "type": "educationLevel", + "parentType": "" + }, + "BAC+4": { + "code": 2860, + "clientCode": "_TS_etude_min_BAC4", + "label": "Bachelor's Degree", + "type": "educationLevel", + "parentType": "" + }, + "BAC+5": { + "code": 266, + "clientCode": "_TS_etude_min_BAC5", + "label": "Master Degree", + "type": "educationLevel", + "parentType": "" + }, + "CAP, BEP": { + "code": 2858, + "clientCode": "_TS_etude_min_CAP_BEP", + "label": "GCSEs", + "type": "educationLevel", + "parentType": "" + }, + "DOCTORAT": { + "code": 2861, + "clientCode": "_TS_etude_min_DOCTORAT", + "label": "PhD, Doctorate", + "type": "educationLevel", + "parentType": "" + }, + "Mast\u00e8re": { + "code": 4030, + "clientCode": "_TS_etude_min_Mastere", + "label": "Mast\u00e8re", + "type": "educationLevel", + "parentType": "" + } + }, + "#EXPERIENCES_REFERENTIEL": { + "Etudiant-e": "", + "D\u00e9butant-e/premi\u00e8re exp\u00e9rience": { + "code": 274, + "clientCode": "_TS_niveau_exp_premiere_exp", + "label": "First experience", + "type": "experienceLevel", + "parentType": "" + }, + "Sup\u00e9rieure \u00e0 3 ans": { + "code": 1785, + "clientCode": "_TS_niveau_exp_superieur_3ans ", + "label": "More than 3 years", + "type": "experienceLevel", + "parentType": "" + }, + "Sup\u00e9rieure \u00e0 5 ans": { + "code": 1783, + "clientCode": "_TS_niveau_exp_superieur_5ans", + "label": "More than 5 years", + "type": "experienceLevel", + "parentType": "" + }, + "Sup\u00e9rieure \u00e0 8 ans": { + "code": 275, + "clientCode": "_TS_niveau_exp_superieur_8ans", + "label": "More than 8 years", + "type": "experienceLevel", + "parentType": "" + } + }, + "applicant": { + "personalInformation": { + "firstName": ".info.first_name", + "lastName": ".info.last_name", + "birthDate": ".info.date_birth", + "phoneNumber": ".info.phone", + "email": ".info.email", + "address": ".info.location.text", + "city": ".info.location.fields?.city >> ''", + "postalCode": ".info.location.fields?.postalCode >> ''", + "civility": ".info?.gender != null ?? .info.gender | {code: . == 'male' ?? 280: 281, clientCode: . == 'male' ?? '_TS_CO_Civility_Mr': '_TS_CO_Civility_Mme' , label: . == 'male' ?? 'Mr.': 'Ms.', type: 'civility', parentType: ''}: null" + }, + "jobPreferences": { + "contractType": ".tags | .name == 'talentsoft_contract_type' ?? #CONTRACT_TYPE_REFERENTIAL.[.value]: null", + "salaryPretensions": ".tags | .name == 'talentsoft_salary' ?? .value: null" + }, + "education": { + "diplomas": "$merge(.tags | .name == 'talentsoft_experience_level' ?? [{educationLevel: #EDUCATIONS_REFERENTIEL.[.value]}]: [], .educations | $map({college: .school, yearObtained: .date_end ?? .date_end | $slice(0, 3): ''}))" + }, + "experiences": { + "experienceLevel": ".tags | .name == 'talentsoft_experience_level' ?? #EXPERIENCES_REFERENTIEL.[.value]: null", + "experienceList": ".experiences | $map({company: .company, function: .title, length: .date_start != null and .date_end != null ?? '<< MISSING ARITHMETICS HERE >>' : null })" + } + }, + "application": { + "type": "offer", + "offerReference": "" + }, + "uploadedFiles": [ + { + "description": ".attachments[0].original_file_name", + "fileTypeId": 36, + "key": "cv_file_id" + } + ], + "attachment": ".attachments[0]" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\n\n# << event_parser_placeholder >>\n\n\n\ndef workflow(\n \n _request: dict,\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.update_profiles_in_talentsoft(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n event_parser = globals().get(\"event_parser\", globals().get(\"default_event_parser\"))\n\n if event_parser is not None:\n try:\n _request = event_parser(_request)\n except Exception as e:\n return TalentSoft.update_profiles_in_talentsoft(\n workflow_id=workflow_id,\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n connector_auth[parameter] = _request[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n hrflow_auth[parameter] = _request[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('source_key', 'profile_key'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n pull_parameters[parameter] = _request[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ():\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n if parameter_name in _request:\n push_parameters[parameter] = _request[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.update_profiles_in_talentsoft(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "pull_template": "import typing as t\n\nfrom hrflow_connectors.v2 import TalentSoft\nfrom hrflow_connectors.v2.core.run import ActionInitError, Reason\n\nCONNECTOR_AUTH_SETTINGS_PREFIX = \"connector_auth_\"\nHRFLOW_AUTH_SETTINGS_PREFIX = \"hrflow_auth_\"\nPULL_PARAMETERS_SETTINGS_PREFIX = \"pull_parameters_\"\nPUSH_PARAMETERS_SETTINGS_PREFIX = \"push_parameters_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << callback_placeholder >>\n\n\n\ndef workflow(\n \n settings: dict\n ) -> None:\n if \"__workflow_id\" not in settings:\n return TalentSoft.update_profiles_in_talentsoft(\n workflow_id=\"\",\n connector_auth=dict(),\n hrflow_auth=dict(),\n pull_parameters=dict(),\n push_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.workflow_id_not_found,\n data=dict(error=\"__workflow_id not found in settings\", settings_keys=list(settings.keys())),\n )\n )\n workflow_id = settings[\"__workflow_id\"]\n\n \n\n connector_auth = dict()\n for parameter in ('client_id', 'client_secret', 'client_url'):\n parameter_name = \"{}{}\".format(CONNECTOR_AUTH_SETTINGS_PREFIX, parameter) \n if parameter_name in settings:\n connector_auth[parameter] = settings[parameter_name]\n \n\n hrflow_auth = dict()\n for parameter in ('api_secret', 'api_user'):\n parameter_name = \"{}{}\".format(HRFLOW_AUTH_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n hrflow_auth[parameter] = settings[parameter_name]\n \n\n pull_parameters = dict()\n for parameter in ('source_key', 'profile_key'):\n parameter_name = \"{}{}\".format(PULL_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n pull_parameters[parameter] = settings[parameter_name]\n \n\n push_parameters = dict()\n for parameter in ():\n parameter_name = \"{}{}\".format(PUSH_PARAMETERS_SETTINGS_PREFIX, parameter)\n if parameter_name in settings:\n push_parameters[parameter] = settings[parameter_name]\n \n\n incremental = settings.get(\"__incremental\")\n\n return TalentSoft.update_profiles_in_talentsoft(\n workflow_id=workflow_id,\n connector_auth=connector_auth,\n hrflow_auth=hrflow_auth,\n pull_parameters=pull_parameters,\n push_parameters=push_parameters,\n logics=globals().get(\"logics\"),\n format=globals().get(\"format\"),\n callback=globals().get(\"callback\"),\n incremental=incremental == \"enable\",\n )", + "settings_keys": { + "workflow_id": "__workflow_id", + "incremental": "__incremental", + "connector_auth_prefix": "connector_auth_", + "hrflow_auth_prefix": "hrflow_auth_", + "pull_parameters_prefix": "pull_parameters_", + "push_parameters_prefix": "push_parameters_" + }, + "placeholders": { + "logics": "# << logics_placeholder >>", + "format": "# << format_placeholder >>", + "callback": "# << callback_placeholder >>", + "event_parser": "# << event_parser_placeholder >>" + }, + "expected": { + "activate_incremental": "enable", + "logics_functions_name": "logics", + "format_functions_name": "format", + "callback_functions_name": "callback", + "event_parser_function_name": "event_parser" + } + } + } + ] } ] } \ No newline at end of file diff --git a/src/hrflow_connectors/v2/__init__.py b/src/hrflow_connectors/v2/__init__.py index 498a767ba..c9fad1409 100644 --- a/src/hrflow_connectors/v2/__init__.py +++ b/src/hrflow_connectors/v2/__init__.py @@ -11,6 +11,7 @@ from hrflow_connectors.v2.connectors.recruitee import Recruitee from hrflow_connectors.v2.connectors.smartrecruiters import SmartRecruiters from hrflow_connectors.v2.connectors.taleez import Taleez +from hrflow_connectors.v2.connectors.talentsoft import TalentSoft from hrflow_connectors.v2.connectors.teamtailor import Teamtailor from hrflow_connectors.v2.connectors.waalaxy import Waalaxy from hrflow_connectors.v2.connectors.workable import Workable @@ -40,4 +41,5 @@ Greenhouse, JazzHR, Ceipal, + TalentSoft, ] diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/README.md b/src/hrflow_connectors/v2/connectors/talentsoft/README.md new file mode 100644 index 000000000..47288d208 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/README.md @@ -0,0 +1,93 @@ +# 📖 Summary +- [📖 Summary](#📖-summary) +- [💼 About Talentsoft](#💼-about-talentsoft) + - [😍 Why is it a big deal for Talentsoft customers & partners?](#😍-why-is-it-a-big-deal-for-talentsoft-customers--partners) +- [🔧 How does it work?](#🔧-how-does-it-work) + - [📊 Data integration capabilities:](#📊-data-integration-capabilities) + - [🧠 Artificial Intelligence capabilities:](#🧠-artificial-intelligence-capabilities) +- [🔌 Connector Actions](#🔌-connector-actions) +- [💍 Quick Start Examples](#💍-quick-start-examples) +- [🔗 Useful Links](#🔗-useful-links) +- [👏 Special Thanks](#👏-special-thanks) + + +# 💼 About Talentsoft + +> Talentsoft (by Cegid) offers a full-suite HCM solution so you can keep all your HR processes in one platform. Make HR processes easy & simple for your teams. Help HR & IT leaders transform organizations. Accelerate HCM productivity for better performance. + +

+ + +## 😍 Why is it a big deal for Talentsoft customers & partners? + +This new connector will enable: +- ⚡ A Fastlane Talent & Workforce data integration for Talentsoft customers & partners +- 🤖 Cutting-edge AI-powered Talent Experiences & Recruiter Experiences for Talentsoft customers + +# 🔧 How does it work? +## 📊 Data integration capabilities: +- ⬅️ Send Profiles data from Talentsoft to a Destination of your choice. +- ➡️ Send Profiles data from a Source of your choice to Talentsoft. +- ⬅️ Send Jobs data from Talentsoft to a Destination of your choice. +- ➡️ Send Jobs data from a Source of your choice to Talentsoft. + +

+

+ +

+ +## 🧠 Artificial Intelligence capabilities: +- Extract, Structure, and Categorize Talent & Workforce data +- Search, Score, and Match Profiles & Jobs with our APIs and AI Widgets (**Matching Custom Tab in Talentsoft**) + + +# 🔌 Connector Actions +

+ +| Action | Description | +| ------- | ----------- | +| [**Applicant new**](docs/applicant_new.md) | Send **created** 'profile(s)' _from_ Talentsoft _to_ HrFlow | +| [**Applicant update**](docs/applicant_update.md) | Send **updated** 'profile(s)' _from_ Talentsoft _to_ HrFlow | +| [**Create profiles in hrflow**](docs/create_profiles_in_hrflow.md) | Send **created** 'profile(s)' _from_ Talentsoft _to_ HrFlow | +| [**Update profiles in hrflow**](docs/update_profiles_in_hrflow.md) | Send **updated** 'profile(s)' _from_ Talentsoft _to_ HrFlow | +| [**Archive profiles in hrflow**](docs/archive_profiles_in_hrflow.md) | Send **archived** 'profile(s)' _from_ Talentsoft _to_ HrFlow | +| [**Create jobs in hrflow**](docs/create_jobs_in_hrflow.md) | Send **created** 'job(s)' _from_ Talentsoft _to_ HrFlow | +| [**Update jobs in hrflow**](docs/update_jobs_in_hrflow.md) | Send **updated** 'job(s)' _from_ Talentsoft _to_ HrFlow | +| [**Archive jobs in hrflow**](docs/archive_jobs_in_hrflow.md) | Send **archived** 'job(s)' _from_ Talentsoft _to_ HrFlow | +| [**Create profiles in talentsoft**](docs/create_profiles_in_talentsoft.md) | Send **created** 'profile(s)' _from_ HrFlow _to_ Talentsoft | +| [**Update profiles in talentsoft**](docs/update_profiles_in_talentsoft.md) | Send **updated** 'profile(s)' _from_ HrFlow _to_ Talentsoft | + + +

+ + +# 💍 Quick Start Examples + +To make sure you can successfully run the latest versions of the example scripts, you have to **install the package from PyPi**. + + +To browse the examples of actions corresponding to released versions of 🤗 this connector, you just need to import the module like this : + +

+ +

+ + +Once the connector module is imported, you can leverage all the different actions that it offers. + +For more code details checkout connector code. + + +# 🔗 Useful Links + +- 📄 Visit [Talentsoft](https://www.cegid.com/fr/produits/cegid-talentsoft/) to learn more. +- ⚙️ API documentations: + - [Cegid Talentsoft Recruiting MatchingIndexation API](https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation) + - [Cegid Talentsoft Recruiting FrontOffice API](https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-frontoffice) + + +- 💻 [Connector code](https://github.com/Riminder/hrflow-connectors/tree/master/src/hrflow_connectors/v2/connectors/talentsoft) on our Github. + + +## 👏 Special Thanks +- 💻 HrFlow.ai : [the-forest-tree](https://github.com/the-forest-tree) - Software Engineer && [Nedhir Ebnou](https://github.com/itsnedhir) - Software Engineer diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/__init__.py b/src/hrflow_connectors/v2/connectors/talentsoft/__init__.py new file mode 100644 index 000000000..092dc5797 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/__init__.py @@ -0,0 +1 @@ +from hrflow_connectors.v2.connectors.talentsoft.connector import TalentSoft # noqa diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/aisles.py b/src/hrflow_connectors/v2/connectors/talentsoft/aisles.py new file mode 100644 index 000000000..dd3a9c4f2 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/aisles.py @@ -0,0 +1,473 @@ +import json +import mimetypes +import typing as t +from datetime import date +from io import BytesIO +from logging import LoggerAdapter +from zipfile import ZipFile + +import requests +from msgspec import Meta, Struct +from typing_extensions import Annotated, Literal + +from hrflow_connectors.v2.core.common import Entity +from hrflow_connectors.v2.core.warehouse import ( + Aisle, + Criterias, + IncrementalTokenHandler, + ReadOperation, + WriteOperation, + merge, +) + +GRANT_TYPE = "client_credentials" +TOKEN_SCOPE = "MatchingIndexation" +TOKEN_SCOPE_FULL_RIGHT = "Customer" +LIMIT = 100 +TIMEOUT = 10 +JOBS_DEFAULT_MAX_READ = 100 + + +class AuthParameters(Struct): + client_id: Annotated[ + str, + Meta( + description="client id used to access TalentSoft front office API", + ), + ] + client_secret: Annotated[ + str, + Meta( + description="client secret used to access TalentSoft front office API", + ), + ] + client_url: Annotated[ + str, + Meta( + description="url used to access TalentSoft front office API", + ), + ] + + +class ReadProfilesParameters(Struct): + filter: Annotated[ + t.Optional[str], + Meta( + description=( + "Filter to apply when reading profiles. See documentation at" + " https://developers.cegid.com/api-details#api=cegid-talentsoft" + "-recruiting-matchingindexation&operation=api-exports-v1-candidates-get" + " . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items" + " 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp';" + " By updateDate updated before the 10th of June 2019" + " 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 " + " 'chronoNumber:gt:108921'" + ), + ), + ] = None + + +class ReadJobsParameters(Struct): + q: Annotated[ + t.Optional[str], + Meta( + description="Query search to get vacancies", + ), + ] = None + filter: Annotated[ + t.Optional[str], + Meta( + description=( + "Filter to apply when reading vacancies. See documentation at" + " https://developers.cegid.com/api-details#api=cegid-talentsoft" + "-recruiting-matchingindexation&operation=api-exports-v1-vacancies-get" + " . . You can filter by **chronoNumber**, **updateDate**, **reference**" + " **vacancyStatus**, **clientVacancyStatus**, **publicationMedia** " + " **publishedOnTheMedia**. Examples : By reference Single Item" + " 'reference::2019-01'; By reference Multiple Items" + " 'reference::2019-01,2019-02,2019-03'; By updateDate updated before" + " the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber" + " greater than 108921 'chronoNumber:gt:108921' . " + ), + ), + ] = None + max_read: Annotated[ + int, + Meta( + description=( + "The maximum number of jobs to pull during the execution. Proper tuning" + " of this parameter should allow to control the execution time and" + " avoid overtimes" + ), + ), + ] = JOBS_DEFAULT_MAX_READ + + +class WriteProfileParameters(Struct): + job_reference: Annotated[ + str, + Meta( + description="reference of the job offer to which the candidate is applying", + ), + ] + + +class UpdateProfileParameters(Struct): + pass + + +def decode_unicode(input_str: str) -> str: + try: + return bytes(input_str, "utf-8").decode("unicode_escape") + except UnicodeDecodeError: + return input_str + + +def decode_json( + obj: t.Union[str, list, dict, t.Any], +) -> t.Union[str, list, dict, t.Any]: + if isinstance(obj, str): + return decode_unicode(obj) + elif isinstance(obj, list): + return [decode_json(item) for item in obj] + elif isinstance(obj, dict): + return {key: decode_json(value) for key, value in obj.items()} + else: + return obj + + +def get_mime_type(filename: t.Optional[str]) -> str: + if filename is None: + return "application/octet-stream" + mime_type, encoding = mimetypes.guess_type(filename) + return mime_type or "application/octet-stream" + + +def get_cv_content(attachment: dict) -> t.Optional[bytes]: + response = requests.get(attachment["public_url"]) + if response.status_code == 200: + return response.content + raise Exception(response.text) + + +def get_talentsoft_auth_token( + client_url: str, + client_id: str, + client_secret: str, + scope: str = TOKEN_SCOPE, + front_or_back: Literal["back", "front"] = "back", +) -> str: + if front_or_back == "front": + data = dict( + grant_type=GRANT_TYPE, + client_id=client_id, + client_secret=client_secret, + ) + else: + data = dict( + grant_type=GRANT_TYPE, + client_id=client_id, + client_secret=client_secret, + scope=scope, + ) + response = requests.post( + "{}/api/token".format(client_url), + headers={ + "Content-Type": "application/x-www-form-urlencoded", + }, + timeout=TIMEOUT, + data=data, + ) + if not response.ok: + raise Exception( + "Failed to get authentication token with error={}".format(response.text) + ) + try: + return response.json()["access_token"] + except (KeyError, requests.exceptions.JSONDecodeError) as e: + raise Exception( + "Failed to get token from response with error={}".format(repr(e)) + ) + + +def post_applicant_front(client_url, token, applicant, files, job_reference=None): + headers = { + "Authorization": "Bearer " + token, + } + if job_reference: + headers.update( + { + "Accept-Language": "fr-FR", + "jobAdReference": job_reference, + } + ) + response = requests.post( + "{}/api/v2/applicants/applicationswithoutaccount".format(client_url), + headers=headers, + data=applicant, + files=files, + ) + if response.status_code == 201: + return response.json() + raise Exception(response.text) + + +def update_applicant_front(client_url, token, applicant): + headers = { + "Authorization": "Bearer " + token, + } + response = requests.put( + "{}/api/v2/applicants".format(client_url), + headers=headers, + data=applicant, + ) + if response.status_code == 204: + return response.json() + raise Exception(response.text) + + +def read_jobs( + adapter: LoggerAdapter, + auth_parameters: AuthParameters, + parameters: ReadJobsParameters, + incremental: bool, + incremental_token: t.Optional[str], +) -> t.Iterable[t.Dict]: + if parameters.filter and incremental: + raise Exception("filter cannot be set when incremental is enabled") + + adapter.info("Requesting Authentication Token from TS") + token = get_talentsoft_auth_token( + client_url=auth_parameters.client_url, + client_id=auth_parameters.client_id, + client_secret=auth_parameters.client_secret, + ) + adapter.info("Authentication with TS API Endpoint finished") + + limit = min(LIMIT, parameters.max_read) + params: dict[str, t.Union[str, int]] = dict(offset=0, limit=limit) + if incremental: + if incremental_token is None: + incremental_token = date.today().isoformat() + params["filter"] = "updateDate:gt:{}".format(incremental_token) + elif parameters.filter: + params["filter"] = parameters.filter + + if parameters.q: + params["q"] = parameters.q + + item_counter = 0 + while True: + response = requests.get( + "{}/api/exports/v1/vacancies".format(auth_parameters.client_url), + params=params, + timeout=TIMEOUT, + headers={ + "Authorization": "bearer {}".format(token), + }, + ) + if not response.ok: + raise Exception( + "Failed to fetch jobs with params={} from TalentSoft with error={}" + .format(params, response.text) + ) + if response.headers.get("Content-Length") == 0 or not response.content: + if params["offset"] == 0: + adapter.info( + "No jobs found with params={} text={} headers={}".format( + params, response.text, response.headers + ) + ) + return + + data = response.content + while data: + read_up_to = int.from_bytes(data[0:4], byteorder="little") + zip_data = ZipFile(BytesIO(data[4 : 4 + read_up_to])) + job = json.loads(zip_data.read("offerdetail").decode())["offerDetail"] + yield job + item_counter += 1 + if item_counter >= parameters.max_read: + return + data = data[4 + read_up_to :] + params["offset"] = t.cast(int, params["offset"]) + limit + + +def read_profiles( + adapter: LoggerAdapter, + auth_parameters: AuthParameters, + parameters: ReadProfilesParameters, + incremental: bool, + incremental_token: t.Optional[str], +) -> t.Iterable[t.Dict]: + token = get_talentsoft_auth_token( + client_url=auth_parameters.client_url, + client_id=auth_parameters.client_id, + client_secret=auth_parameters.client_secret, + ) + params = dict(offset=0, limit=LIMIT, attachmenttype="resume") + if parameters.filter: + params["filter"] = parameters.filter + + while True: + response = requests.get( + "{}/api/exports/v1/candidates".format(auth_parameters.client_url), + params=params, + timeout=TIMEOUT, + headers={ + "Authorization": "bearer {}".format(token), + }, + ) + if not response.ok: + raise Exception( + "Failed to fetch candidates with params={} from TalentSoft with" + " error={}".format(params, response.text) + ) + if response.headers.get("Content-Length") == 0 or not response.content: + if params["offset"] == 0: + adapter.info( + "No profiles found with params={} text={} headers={}".format( + params, response.text, response.headers + ) + ) + return + + data = response.content + while data: + read_up_to = int.from_bytes(data[0:4], byteorder="little") + zip_data = ZipFile(BytesIO(data[4 : 4 + read_up_to])) + candidate = json.loads(zip_data.read("applicantdetail").decode()) + for attachment in candidate["attachments"]: + attachment["raw"] = zip_data.read(attachment["id"]) + yield candidate + data = data[4 + read_up_to :] + params["offset"] = t.cast(int, params["offset"]) + LIMIT + + +def write_profiles( + adapter: LoggerAdapter, + auth_parameters: AuthParameters, + parameters: WriteProfileParameters, + items: t.Iterable[t.Dict], +) -> t.List[t.Dict]: + failed_profiles = [] + adapter.info("Requesting Authentication Token from TS") + token = get_talentsoft_auth_token( + client_url=auth_parameters.client_url, + client_id=auth_parameters.client_id, + client_secret=auth_parameters.client_secret, + front_or_back="front", + ) + adapter.info("Authentication with TS API Endpoint finished") + for profile in items: + attachment = profile.pop("attachment", None) + if not attachment: + adapter.error("No attachment found for profile={}".format(profile)) + failed_profiles.append(profile) + continue + try: + cv_content = get_cv_content(attachment) + except Exception as e: + adapter.error("Failed to get cv content with response={}".format(e)) + failed_profiles.append(profile) + continue + filename = attachment["original_file_name"] + mime_type = get_mime_type(filename) + files = [ + ( + "cv_file_id", + (filename, cv_content, mime_type), + ) + ] + if parameters.job_reference: + profile["application"]["offerReference"] = parameters.job_reference + profile = decode_json(profile) + profile_ts = dict(applicantApplication=json.dumps(profile)) + try: + post_applicant_front( + auth_parameters.client_url, + token, + profile_ts, + files, + parameters.job_reference, + ) + except Exception as e: + adapter.error("Failed to write profile with response={}".format(e)) + failed_profiles.append(profile) + + return failed_profiles + + +def update_profile( + adapter: LoggerAdapter, + auth_parameters: AuthParameters, + parameters: UpdateProfileParameters, + items: t.Iterable[t.Dict], +) -> t.List[t.Dict]: + failed_profiles = [] + adapter.info("Requesting Authentication Token from TS") + token = get_talentsoft_auth_token( + client_url=auth_parameters.client_url, + client_id=auth_parameters.client_id, + client_secret=auth_parameters.client_secret, + front_or_back="front", + ) + adapter.info("Authentication with TS API Endpoint finished") + for profile in items: + try: + update_applicant_front( + auth_parameters.client_url, + token, + profile, + ) + except Exception as e: + adapter.error("Failed to write profile with response={}".format(e)) + failed_profiles.append(profile) + + return failed_profiles + + +ProfilesAisle = Aisle( + name=Entity.profile, + read=ReadOperation( + criterias=Criterias( + create=ReadProfilesParameters, + update=ReadProfilesParameters, + archive=ReadProfilesParameters, + ), + function=merge( + create=read_profiles, + update=read_profiles, + archive=read_profiles, + ), + ), + write=WriteOperation( + criterias=Criterias( + create=WriteProfileParameters, update=UpdateProfileParameters + ), + function=merge( + create=write_profiles, + update=update_profile, + ), + ), +) + + +JobsAisle = Aisle( + name=Entity.job, + read=ReadOperation( + criterias=Criterias( + create=ReadJobsParameters, + update=ReadJobsParameters, + archive=ReadJobsParameters, + ), + function=merge( + create=read_jobs, + update=read_jobs, + archive=read_jobs, + ), + incremental_token_handler=IncrementalTokenHandler( + create=lambda job: job["modificationDate"], + ), + ), +) diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/connector.py b/src/hrflow_connectors/v2/connectors/talentsoft/connector.py new file mode 100644 index 000000000..53119716f --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/connector.py @@ -0,0 +1,519 @@ +import typing as t +from datetime import datetime + +import requests + +from hrflow_connectors.v2.connectors.talentsoft.aisles import ( + AuthParameters, + get_talentsoft_auth_token, +) +from hrflow_connectors.v2.connectors.talentsoft.utils.const import ( + CIVILITY, + CONTRACT_TYPE_REFERENTIAL, + EDUCATIONS_REFERENTIEL, + EXPERIENCES_REFERENTIEL, +) +from hrflow_connectors.v2.connectors.talentsoft.warehouse import TalentSoftWarehouse +from hrflow_connectors.v2.core.common import Direction, Entity, Mode +from hrflow_connectors.v2.core.connector import Connector, ConnectorType, Flow +from hrflow_connectors.v2.core.run import CallbackT, Event + + +def retrieve_tag_value(tags: t.List[dict], tag_name: str) -> t.Optional[str]: + for tag in tags: + if tag["name"] == tag_name: + return tag["value"] + return None + + +def format_ts_applicant_civility(gender: t.Optional[str]) -> t.Optional[t.Dict]: + civility_ts = {} + if gender is None: + return None + if gender == "male": + return CIVILITY[2] + elif gender == "female": + return CIVILITY[4] + return civility_ts + + +def extract_year(date_str: str) -> t.Optional[int]: + if not date_str: + return None + try: + return datetime.fromisoformat(date_str).year + except ValueError: + return None + + +def calcul_ts_experience_duration(date_start: str, date_end: str) -> t.Optional[float]: + if not date_start or not date_end: + return None + try: + date_start_obj = datetime.fromisoformat(date_start) + date_end_obj = datetime.fromisoformat(date_end) + return (date_end_obj - date_start_obj).days / 365 + except ValueError: + return None + + +def format_contract_type(tags: t.List[dict]) -> t.Optional[t.Dict]: + contract_type = retrieve_tag_value(tags, "talentsoft_contract_type") + if contract_type: + return CONTRACT_TYPE_REFERENTIAL.get(contract_type) + return None + + +def format_ts_educations(educations: t.List[dict], tags: t.List[dict]) -> dict: + education_level = retrieve_tag_value(tags, "talentsoft_education_level") + + diplomas = ( + [{"educationLevel": EDUCATIONS_REFERENTIEL.get(education_level)}] + if education_level + else [] + ) + + diplomas += [ + { + "yearObtained": ( + extract_year(education["date_end"]) if education["date_end"] else "" + ), + "college": education["school"], + } + for education in educations + ] + + return {"diplomas": diplomas} + + +def format_ts_experiences(experiences: t.List[dict], tags: t.List[dict]) -> dict: + experience_level = retrieve_tag_value(tags, "talentsoft_experience_level") + experiences_ts_list = [ + { + "company": experience["company"], + "function": experience["title"], + "length": ( + calcul_ts_experience_duration( + experience["date_start"], experience["date_end"] + ) + if experience["date_start"] and experience["date_end"] + else "" + ), + } + for experience in experiences + ] + if experience_level: + experiences_ts = { + "experienceLevel": EXPERIENCES_REFERENTIEL.get(experience_level), + "experienceList": experiences_ts_list, + } + else: + experiences_ts = {} + return experiences_ts + + +def format_ts_vacancy(ts_vacancy: t.Dict) -> t.Dict: + # FIXME lat and lng makes requests to HERE Maps API in original workflow + ts_location = ts_vacancy["location"] + location = dict( + text=ts_location["address"], + lat=ts_location["latitude"], + lng=ts_location["longitude"], + ) + + job_description = ts_vacancy["jobDescription"] + custom_fields = job_description["jobDescriptionCustomFields"] + sections = [ + dict( + name="description1", + title="description1", + description=job_description["description1"] or "", + ), + dict( + name="description2", + title="description2", + description=job_description["description2"] or "", + ), + dict( + name="Complément du descriptif", + title="Complément du descriptif", + description="\n".join( + [ + custom_fields.get("longText1") or "", + custom_fields.get("longText2") or "", + custom_fields.get("longText3") or "", + ] + ), + ), + ] + + languages = [ + dict(name=language["language"]["label"], value=None) + for language in ts_vacancy.get("languages") or [] + ] + + tags = [ + dict( + name="talentsoft-organisation-id", + value=(ts_vacancy["organisation"] or {}).get("id"), + ), + dict( + name="talentsoft-status-id", + value=(ts_vacancy["status"] or {}).get("id"), + ), + dict( + name="talentsoft-professionalCategory-id", + value=(ts_vacancy["jobDescription"]["professionalCategory"] or {}).get( + "id" + ), + ), + dict( + name="talentsoft-country-id", + value=(ts_vacancy["jobDescription"]["country"] or {}).get("id"), + ), + dict( + name="talentsoft-primaryProfile-id", + value=(ts_vacancy["jobDescription"]["primaryProfile"] or {}).get("id"), + ), + dict( + name="talentsoft-contractType-id", + value=(ts_vacancy["jobDescription"]["contractType"] or {}).get("id"), + ), + dict( + name="talentsoft-publishedOnInternet", + value=ts_vacancy.get("publishedOnInternet"), + ), + dict( + name="talentsoft-publishedOnIntranet", + value=ts_vacancy.get("publishedOnIntranet"), + ), + ] + + if ts_vacancy["criteria"]["experienceLevel"]: + tags.append( + dict( + name="talentsoft-experienceLevel", + value=ts_vacancy["criteria"]["experienceLevel"].get("id"), + ) + ) + + if ts_vacancy["criteria"]["educationLevel"]: + tags.append( + dict( + name="talentsoft-educationLevel", + value=ts_vacancy["criteria"]["educationLevel"].get("id"), + ) + ) + + return dict( + name=ts_vacancy["jobDescription"]["title"], + reference=ts_vacancy["reference"], + created_at=ts_vacancy["creationDate"], + location=location, + url=None, + summary=None, + sections=sections, + tags=tags, + skills=ts_vacancy["criteria"]["skills"], + languages=languages, + ) + + +def format_ts_vacancy_archive(ts_vacancy: t.Dict) -> t.Dict: + return dict( + reference=ts_vacancy["reference"], + ) + + +def format_ts_candidate(ts_candidate: t.Dict) -> t.Dict: + details = ts_candidate["candidateDetail"] + tags = [ + dict(name="talentsoft-isEmployee", value=ts_candidate["isEmployee"]), + dict(name="talentsoft-isInProgress", value=ts_candidate["isInProgress"]), + dict( + name="talentsoft-residentCountry-id", + value=details["personalInformation"]["residentCountry"].get("id"), + ), + ] + + contract_type = details["positionSought"]["contractType"] + if contract_type: + tags.append( + dict( + name="talentsoft-contractType-id", + value=contract_type["id"], + ) + ) + + custom_code_table_1 = details["positionSought"]["jobPreferencesCustomFields"][ + "customCodeTable1" + ] + if custom_code_table_1: + tags.append( + dict( + name="talentsoft-profileStatus-id", + value=custom_code_table_1["id"], + ) + ) + + global_experience_level = details["globalExperience"]["globalExperienceLevel"] + if global_experience_level: + tags.append( + dict( + name="talentsoft-experienceLevel-id", + value=global_experience_level["id"], + ) + ) + + primary_profile = details["positionSought"]["primaryProfile"] + if primary_profile: + tags.append( + dict( + name="talentsoft-profile-id", + value=primary_profile["id"], + ) + ) + + for education in details["educations"]: + if education["educationLevel"]: + tags.append( + { + "name": "talentsofteducationLevel-id", + "value": education["educationLevel"]["id"], + } + ) + for application in ts_candidate["applications"]: + tags.append( + dict( + name="talentsoft-application-vacancyReference", + value=application["vacancyReference"], + ) + ) + + metadatas = [ + dict(name="profile_uid", value=details["id"]), + ] + + resume = None + attachment = next( + ( + attachment + for attachment in ts_candidate["attachments"] + if attachment["isResume"] + ), + None, + ) + if attachment: + resume = dict(raw=attachment["raw"], content_type=attachment["mimeType"]) + metadatas.append(dict(name="filename", value=attachment["filename"])) + return dict( + reference=details["id"], + created_at=details["creationDate"], + updated_at=datetime.utcnow().isoformat(), + resume=resume, + tags=tags, + metadatas=metadatas, + ) + + +def format_ts_candidate_archive(ts_candidate: t.Dict) -> t.Dict: + return dict( + reference=ts_candidate["id"], + ) + + +def ts_callback( + origin_parameters: AuthParameters, + target_parameters: AuthParameters, + events: t.Counter[Event], + items_to_write: t.List[t.Dict], +) -> None: + if len(items_to_write) == 1 and events[Event.write_failure] == 0: + candidate = items_to_write[0] + token = get_talentsoft_auth_token( + client_url=origin_parameters.client_url, + client_id=origin_parameters.client_id, + client_secret=origin_parameters.client_secret, + ) + report = dict( + reportType="Candidates", + items=[ + dict( + id=candidate["reference"], + date=candidate["created_at"], + lastUpdateDate=candidate["updated_at"], + status="success", + ) + ], + ) + response = requests.post( + "{}/api/exports/v1/reports".format(origin_parameters.client_url), + headers={ + "Authorization": "bearer {}".format(token), + }, + json=report, + ) + if not response.ok: + raise Exception( + "Talentsoft callback report failed error={} evens={}".format( + response.text, + events, + ) + ) + + +def applicant_new_parser(event: t.Dict) -> t.Dict: + return dict(filter="id::{}".format(event["applicantId"])) + + +def applicant_update_parser(event: t.Dict) -> t.Dict: + return dict(filter="id::{}".format(event["applicantId"])) + + +def format_info_ts_applicant(profile_hrflow: t.Dict) -> t.Dict: + info_profile_hrflow = profile_hrflow["info"] + attachment = profile_hrflow["attachments"][0] + personal_information = dict( + firstName=info_profile_hrflow["first_name"], + lastName=info_profile_hrflow["last_name"], + birthDate=info_profile_hrflow["date_birth"], + phoneNumber=info_profile_hrflow["phone"], + email=info_profile_hrflow["email"], + address=info_profile_hrflow["location"]["text"], + city=( + info_profile_hrflow["location"].get("fields", {}).get("city", "") + if info_profile_hrflow["location"].get("fields") + else "" + ), + postalCode=( + info_profile_hrflow["location"].get("fields", {}).get("postalCode", "") + if info_profile_hrflow["location"].get("fields") + else "" + ), + civility=format_ts_applicant_civility(info_profile_hrflow["gender"]), + ) + jobPreferences = dict( + contractType=format_contract_type(profile_hrflow["tags"]), + salaryPretensions=retrieve_tag_value( + profile_hrflow["tags"], "talentsoft_salary" + ), + ) + education = format_ts_educations( + profile_hrflow["educations"], profile_hrflow["tags"] + ) + experiences = format_ts_experiences( + profile_hrflow["experiences"], profile_hrflow["tags"] + ) + application = dict( + type="offer", + offerReference="", + ) + uploadedFiles = [ + dict( + description=attachment["original_file_name"], + fileTypeId=36, + key="cv_file_id", + ) + ] + + applicant = dict( + personalInformation=personal_information, + jobPreferences=jobPreferences, + education=education, + experiences=experiences, + ) + + return dict( + applicant=applicant, + application=application, + uploadedFiles=uploadedFiles, + attachment=attachment, + ) + + +DESCRIPTION = ( + "Talentsoft (by Cegid) offers a full-suite HCM solution so you can keep all your HR" + " processes in one platform. Make HR processes easy & simple for your teams. Help" + " HR & IT leaders transform organizations. Accelerate HCM productivity for better" + " performance." +) +TalentSoft = Connector( + name="TalentSoft", + type=ConnectorType.HCM, + subtype="talentsoft", + description=DESCRIPTION, + url="https://www.cegid.com/fr/produits/cegid-talentsoft/", + warehouse=TalentSoftWarehouse, + flows=( + Flow( + Mode.create, + Entity.profile, + Direction.inbound, + override_name="applicant_new", + format=format_ts_candidate, + event_parser=applicant_new_parser, + callback=t.cast( + CallbackT, ts_callback + ), # Explicit CallbackT requires the more general Parameters + ), + Flow( + Mode.update, + Entity.profile, + Direction.inbound, + override_name="applicant_update", + format=format_ts_candidate, + event_parser=applicant_update_parser, + callback=t.cast( + CallbackT, ts_callback + ), # Explicit CallbackT requires the more general Parameters + ), + Flow( + Mode.create, + Entity.profile, + Direction.inbound, + format=format_ts_candidate, + ), + Flow( + Mode.update, + Entity.profile, + Direction.inbound, + format=format_ts_candidate, + ), + Flow( + Mode.archive, + Entity.profile, + Direction.inbound, + format=format_ts_candidate_archive, + ), + Flow( + Mode.create, + Entity.job, + Direction.inbound, + format=format_ts_vacancy, + ), + Flow( + Mode.update, + Entity.job, + Direction.inbound, + format=format_ts_vacancy, + ), + Flow( + Mode.archive, + Entity.job, + Direction.inbound, + format=format_ts_vacancy_archive, + ), + Flow( + Mode.create, + Entity.profile, + Direction.outbound, + format=format_info_ts_applicant, + ), + Flow( + Mode.update, + Entity.profile, + Direction.outbound, + format=format_info_ts_applicant, + ), + ), +) diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/connector.pyi b/src/hrflow_connectors/v2/connectors/talentsoft/connector.pyi new file mode 100644 index 000000000..3391dde67 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/connector.pyi @@ -0,0 +1,16 @@ +# This file is generated automatically +from hrflow_connectors.v2.core.connector import Connector, PublicActionInterface + +class TalentSoftProto(Connector): + applicant_new: PublicActionInterface + applicant_update: PublicActionInterface + create_profiles_in_hrflow: PublicActionInterface + update_profiles_in_hrflow: PublicActionInterface + archive_profiles_in_hrflow: PublicActionInterface + create_jobs_in_hrflow: PublicActionInterface + update_jobs_in_hrflow: PublicActionInterface + archive_jobs_in_hrflow: PublicActionInterface + create_profiles_in_talentsoft: PublicActionInterface + update_profiles_in_talentsoft: PublicActionInterface + +TalentSoft: TalentSoftProto \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/doc.md b/src/hrflow_connectors/v2/connectors/talentsoft/doc.md new file mode 100644 index 000000000..35521ebb8 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/doc.md @@ -0,0 +1,74 @@ +# 📖 Summary +- [📖 Summary](#-summary) +- [📝 About Cegid-Talentsoft](#-about-cegid-talentsoft) +- [🔧 How does it work?](#-how-does-it-work) + - [📊 Data integration capabilities:](#-data-integration-capabilities) + - [🧠 Artificial Intelligence capabilities:](#-artificial-intelligence-capabilities) +- [🔌 Connector Actions](#-connector-actions) +- [🐍 Quick Start Examples](#-quick-start-examples) +- [🔗 Useful Links](#-useful-links) +- [👏 Special Thanks](#-special-thanks) + + +# 📝 About Cegid-Talentsoft +Talentsoft (by Cegid) offers a full-suite HCM solution so you can keep all your HR processes in one platform. Make HR processes easy & simple for your teams. Help HR & IT leaders transform organizations. Accelerate HCM productivity for better performance. + +

+ +

+ +# 🔧 How does it work? +## 📊 Data integration capabilities: +- ⬅️ Send Profiles data from Cegid Talentsoft to a Destination of your choice. +- ⬅️ Send Jobs data from Cegid Talentsoft to a Destination of your choice. + + +## 🧠 Artificial Intelligence capabilities: +- Extract, Structure, and Categorize Talent & Workforce data +- Search, Score, and Match Profiles & Jobs with our APIs and AI Widgets + + +# 🔌 Connector Actions +

+ +| Action | Description | +| ------- | ----------- | +| [**Applicant new**](docs/applicant_new.md) | Handle TalentSoft 'applicant_new' event by fetching profile from TalentSoft and sending it to HrFlow.ai Parsing API. | +| [**Applicant resume update**](docs/applicant_resume_update.md) | Handle TalentSoft 'applicant_resume_update' event by running a new HrFlow.ai Parsing on updated resume. | +| [**Applicant update**](docs/applicant_update.md) | Handle TalentSoft 'applicant_update' event by only updating tags coming from TalentSoft in HrFlow.ai. | +| [**Pull profile list**](docs/pull_profile_list.md) | Retrieves profiles from TalentSoft candidates export API and send them to a ***Hrflow.ai Source***. | +| [**Pull job list**](docs/pull_job_list.md) | Retrieves jobs from TalentSoft vacancies export API and send them to a ***Hrflow.ai Board***. | +| [**Push profile**](docs/push_profile.md) | Pushs specific Profile from HrFlow and writes it to Applicant object in Talentsoft | + + +

+

+ +

+ +# 🐍 Quick Start Examples + +To make sure you can successfully run the latest versions of the example scripts, you have to **install the package from PyPi**. + + +To browse the examples of actions corresponding to released versions of 🤗 this connector, you just need to import the module like this : + +

+ +

+ + +Once the connector module is imported, you can leverage all the different actions that it offers. + +For more code details checkout connector code + + +# 🔗 Useful Links + +- 📄Visit [Cegid Talentsoft](https://www.cegidtalentsoft.com/) to learn more. +- 💻 [Connector code](https://github.com/Riminder/hrflow-connectors/tree/master/src/hrflow_connectors/connectors/talentsoft) on our Github. + + +# 👏 Special Thanks +- 💻 HrFlow.ai : [the-forest-tree](https://github.com/the-forest-tree) - Software Engineer +- 🤝 Cegid Talentsoft :[Cegid Talentsoft for the partnership and accessible documentation](https://www.cegidtalentsoft.com/) \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/applicant_new.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/applicant_new.md new file mode 100644 index 000000000..995204f90 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/applicant_new.md @@ -0,0 +1,81 @@ +# Applicant new +`TalentSoft` :arrow_right: `HrFlow` + +Send **created** 'profile(s)' _from_ TalentSoft _to_ HrFlow + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `filter` | `string\|null` | None | Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' | + +## Push Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `source_key` :red_circle: | `string` | None | HrFlow.ai source key | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.applicant_new( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + filter=..., + ), + push_parameters=dict( + source_key=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/applicant_update.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/applicant_update.md new file mode 100644 index 000000000..3f896be81 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/applicant_update.md @@ -0,0 +1,83 @@ +# Applicant update +`TalentSoft` :arrow_right: `HrFlow` + +Send **updated** 'profile(s)' _from_ TalentSoft _to_ HrFlow + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `filter` | `string\|null` | None | Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' | + +## Push Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `source_key` :red_circle: | `string` | None | HrFlow.ai source key | +| `only_edit_fields` | `array\|null` | None | List of attributes to use for the edit operation e.g. ['tags', 'metadatas'] | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.applicant_update( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + filter=..., + ), + push_parameters=dict( + source_key=..., + only_edit_fields=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/archive_jobs_in_hrflow.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/archive_jobs_in_hrflow.md new file mode 100644 index 000000000..c6656d84f --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/archive_jobs_in_hrflow.md @@ -0,0 +1,85 @@ +# Archive jobs in hrflow +`TalentSoft` :arrow_right: `HrFlow` + +Send **archived** 'job(s)' _from_ TalentSoft _to_ HrFlow + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `q` | `string\|null` | None | Query search to get vacancies | +| `filter` | `string\|null` | None | Filter to apply when reading vacancies. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-vacancies-get . . You can filter by **chronoNumber**, **updateDate**, **reference** **vacancyStatus**, **clientVacancyStatus**, **publicationMedia** **publishedOnTheMedia**. Examples : By reference Single Item 'reference::2019-01'; By reference Multiple Items 'reference::2019-01,2019-02,2019-03'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' . | +| `max_read` | `integer` | 100 | The maximum number of jobs to pull during the execution. Proper tuning of this parameter should allow to control the execution time and avoid overtimes | + +## Push Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `board_key` :red_circle: | `string` | None | HrFlow.ai board key | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.archive_jobs_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + q=..., + filter=..., + max_read=..., + ), + push_parameters=dict( + board_key=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/archive_profiles_in_hrflow.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/archive_profiles_in_hrflow.md new file mode 100644 index 000000000..10319d2a6 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/archive_profiles_in_hrflow.md @@ -0,0 +1,81 @@ +# Archive profiles in hrflow +`TalentSoft` :arrow_right: `HrFlow` + +Send **archived** 'profile(s)' _from_ TalentSoft _to_ HrFlow + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `filter` | `string\|null` | None | Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' | + +## Push Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `source_key` :red_circle: | `string` | None | HrFlow.ai source key | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.archive_profiles_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + filter=..., + ), + push_parameters=dict( + source_key=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/create_jobs_in_hrflow.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/create_jobs_in_hrflow.md new file mode 100644 index 000000000..dd7e602f5 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/create_jobs_in_hrflow.md @@ -0,0 +1,87 @@ +# Create jobs in hrflow +`TalentSoft` :arrow_right: `HrFlow` + +Send **created** 'job(s)' _from_ TalentSoft _to_ HrFlow + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `q` | `string\|null` | None | Query search to get vacancies | +| `filter` | `string\|null` | None | Filter to apply when reading vacancies. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-vacancies-get . . You can filter by **chronoNumber**, **updateDate**, **reference** **vacancyStatus**, **clientVacancyStatus**, **publicationMedia** **publishedOnTheMedia**. Examples : By reference Single Item 'reference::2019-01'; By reference Multiple Items 'reference::2019-01,2019-02,2019-03'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' . | +| `max_read` | `integer` | 100 | The maximum number of jobs to pull during the execution. Proper tuning of this parameter should allow to control the execution time and avoid overtimes | + +## Push Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `board_key` :red_circle: | `string` | None | HrFlow.ai board key | +| `enrich_with_parsing` | `boolean` | False | When enabled jobs are enriched with HrFlow.ai parsing | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.create_jobs_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + q=..., + filter=..., + max_read=..., + ), + push_parameters=dict( + board_key=..., + enrich_with_parsing=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/create_profiles_in_hrflow.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/create_profiles_in_hrflow.md new file mode 100644 index 000000000..aa3895756 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/create_profiles_in_hrflow.md @@ -0,0 +1,81 @@ +# Create profiles in hrflow +`TalentSoft` :arrow_right: `HrFlow` + +Send **created** 'profile(s)' _from_ TalentSoft _to_ HrFlow + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `filter` | `string\|null` | None | Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' | + +## Push Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `source_key` :red_circle: | `string` | None | HrFlow.ai source key | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.create_profiles_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + filter=..., + ), + push_parameters=dict( + source_key=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/create_profiles_in_talentsoft.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/create_profiles_in_talentsoft.md new file mode 100644 index 000000000..0b3cef67f --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/create_profiles_in_talentsoft.md @@ -0,0 +1,83 @@ +# Create profiles in talentsoft +`HrFlow` :arrow_right: `TalentSoft` + +Send **created** 'profile(s)' _from_ HrFlow _to_ TalentSoft + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `source_key` :red_circle: | `string` | None | HrFlow.ai source key | +| `profile_key` :red_circle: | `string` | None | HrFlow.ai profile key | + +## Push Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `job_reference` :red_circle: | `string` | None | reference of the job offer to which the candidate is applying | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.create_profiles_in_talentsoft( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + source_key=..., + profile_key=..., + ), + push_parameters=dict( + job_reference=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/update_jobs_in_hrflow.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/update_jobs_in_hrflow.md new file mode 100644 index 000000000..1e3f10063 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/update_jobs_in_hrflow.md @@ -0,0 +1,85 @@ +# Update jobs in hrflow +`TalentSoft` :arrow_right: `HrFlow` + +Send **updated** 'job(s)' _from_ TalentSoft _to_ HrFlow + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `q` | `string\|null` | None | Query search to get vacancies | +| `filter` | `string\|null` | None | Filter to apply when reading vacancies. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-vacancies-get . . You can filter by **chronoNumber**, **updateDate**, **reference** **vacancyStatus**, **clientVacancyStatus**, **publicationMedia** **publishedOnTheMedia**. Examples : By reference Single Item 'reference::2019-01'; By reference Multiple Items 'reference::2019-01,2019-02,2019-03'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' . | +| `max_read` | `integer` | 100 | The maximum number of jobs to pull during the execution. Proper tuning of this parameter should allow to control the execution time and avoid overtimes | + +## Push Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `board_key` :red_circle: | `string` | None | HrFlow.ai board key | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.update_jobs_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + q=..., + filter=..., + max_read=..., + ), + push_parameters=dict( + board_key=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/update_profiles_in_hrflow.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/update_profiles_in_hrflow.md new file mode 100644 index 000000000..6954eb619 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/update_profiles_in_hrflow.md @@ -0,0 +1,83 @@ +# Update profiles in hrflow +`TalentSoft` :arrow_right: `HrFlow` + +Send **updated** 'profile(s)' _from_ TalentSoft _to_ HrFlow + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `filter` | `string\|null` | None | Filter to apply when reading profiles. See documentation at https://developers.cegid.com/api-details#api=cegid-talentsoft-recruiting-matchingindexation&operation=api-exports-v1-candidates-get . Examples : By id Single Item 'id::_TS-00001'; By id Multiple Items 'id::_TS-00001,_TS-00002'; By email 'email::john.doe@company.corp'; By updateDate updated before the 10th of June 2019 'updateDate:lt:2019-06-10'; By chronoNumber greater than 108921 'chronoNumber:gt:108921' | + +## Push Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `source_key` :red_circle: | `string` | None | HrFlow.ai source key | +| `only_edit_fields` | `array\|null` | None | List of attributes to use for the edit operation e.g. ['tags', 'metadatas'] | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.update_profiles_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + filter=..., + ), + push_parameters=dict( + source_key=..., + only_edit_fields=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/docs/update_profiles_in_talentsoft.md b/src/hrflow_connectors/v2/connectors/talentsoft/docs/update_profiles_in_talentsoft.md new file mode 100644 index 000000000..50218ab69 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/docs/update_profiles_in_talentsoft.md @@ -0,0 +1,81 @@ +# Update profiles in talentsoft +`HrFlow` :arrow_right: `TalentSoft` + +Send **updated** 'profile(s)' _from_ HrFlow _to_ TalentSoft + + + +## TalentSoft Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `client_id` :red_circle: | `string` | None | client id used to access TalentSoft front office API | +| `client_secret` :red_circle: | `string` | None | client secret used to access TalentSoft front office API | +| `client_url` :red_circle: | `string` | None | url used to access TalentSoft front office API | + +## HrFlow.ai Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `api_secret` :red_circle: | `string` | None | API Key used to access HrFlow.ai API | +| `api_user` :red_circle: | `string` | None | User email used to access HrFlow.ai API | + +## Pull Parameters (HrFlow) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `source_key` :red_circle: | `string` | None | HrFlow.ai source key | +| `profile_key` :red_circle: | `string` | None | HrFlow.ai profile key | + +## Push Parameters (TalentSoft) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | + +## Other Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `workflow_id` :red_circle: | `string` | None | A stable identifier used for persisting in incremental mode | +| `logics` :red_circle: | `array\|null` | None | A list of functions called in sequence with each item pulled from the origin. Each function might either return it's argument or None to discard the item. Any item discarded is eventually not pushed to the target | +| `format` | `Callable\|null` | None | A formatting function to apply on items pulled before the push | +| `callback` | `Callable\|null` | None | Registers a callback function to be called at the of a successful execution | +| `persist` | `boolean` | True | When False has the effect of running in dry mode. Items are pulled but not pushed to the target | +| `incremental` | `boolean` | False | Controls the incremental reading execution mode | + +:red_circle: : *required* + +## Example + +```python +import logging +from hrflow_connectors.v2 import TalentSoft + + +logging.basicConfig(level=logging.INFO) + + +TalentSoft.update_profiles_in_talentsoft( + workflow_id=..., + logics=..., + connector_auth=dict( + client_id=..., + client_secret=..., + client_url=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + source_key=..., + profile_key=..., + ), + push_parameters=dict( + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/logo.png b/src/hrflow_connectors/v2/connectors/talentsoft/logo.png new file mode 100644 index 000000000..536f8f71d Binary files /dev/null and b/src/hrflow_connectors/v2/connectors/talentsoft/logo.png differ diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/applicant_new.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/applicant_new.json new file mode 100644 index 000000000..a63516eb0 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/applicant_new.json @@ -0,0 +1,11 @@ +{ + "reference": ".candidateDetail.id", + "created_at": ".candidateDetail.creationDate", + "updated_at": "$now('iso')", + "resume": ".attachments | .isResume ?? {raw: .raw, content_type: .mimeType} : null ", + "tags": "$merge([{ 'name': 'talentsoft-isEmployee', 'value': '.isEmployee'},{ 'name': 'talentsoft-isInProgress', 'value': '.isInProgress'},{ 'name': 'talentsoft-residentCountry-id', 'value': '.candidateDetail.personalInformation.residentCountry?.id'},{ 'name': 'talentsoft-contractType-id', 'value': '.candidateDetail.positionSought.contractType.id'},{ 'name': 'talentsoft-profileStatus-id', 'value': '.candidateDetail.positionSought.jobPreferencesCustomFields.customCodeTable1.id'},{ 'name': 'talentsoft-experienceLevel-id', 'value': '.candidateDetail.globalExperience.globalExperienceLevel.id'},{ 'name': 'talentsoft-profile-id', 'value': '.candidateDetail.positionSought.primaryProfile.id'},{ 'name': 'talentsofteducationLevel-id', 'value': '.candidateDetail.educations.educationLevel.id'}], .candidateDetail.educations | $map(.educationLevel != null ?? {name: 'talentsofteducationLevel-id', value: .educationLevel.id} ), .applications | $map({name: 'talentsoft-application-vacancyReference', value: .vacancyReference}))", + "metadatas": [ + { "name": "profile_uid", "value": ".candidateDetail.id" }, + ".attachments | .isResume ?? {name: 'filename', value: .filename}" + ] +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/applicant_update.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/applicant_update.json new file mode 100644 index 000000000..a63516eb0 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/applicant_update.json @@ -0,0 +1,11 @@ +{ + "reference": ".candidateDetail.id", + "created_at": ".candidateDetail.creationDate", + "updated_at": "$now('iso')", + "resume": ".attachments | .isResume ?? {raw: .raw, content_type: .mimeType} : null ", + "tags": "$merge([{ 'name': 'talentsoft-isEmployee', 'value': '.isEmployee'},{ 'name': 'talentsoft-isInProgress', 'value': '.isInProgress'},{ 'name': 'talentsoft-residentCountry-id', 'value': '.candidateDetail.personalInformation.residentCountry?.id'},{ 'name': 'talentsoft-contractType-id', 'value': '.candidateDetail.positionSought.contractType.id'},{ 'name': 'talentsoft-profileStatus-id', 'value': '.candidateDetail.positionSought.jobPreferencesCustomFields.customCodeTable1.id'},{ 'name': 'talentsoft-experienceLevel-id', 'value': '.candidateDetail.globalExperience.globalExperienceLevel.id'},{ 'name': 'talentsoft-profile-id', 'value': '.candidateDetail.positionSought.primaryProfile.id'},{ 'name': 'talentsofteducationLevel-id', 'value': '.candidateDetail.educations.educationLevel.id'}], .candidateDetail.educations | $map(.educationLevel != null ?? {name: 'talentsofteducationLevel-id', value: .educationLevel.id} ), .applications | $map({name: 'talentsoft-application-vacancyReference', value: .vacancyReference}))", + "metadatas": [ + { "name": "profile_uid", "value": ".candidateDetail.id" }, + ".attachments | .isResume ?? {name: 'filename', value: .filename}" + ] +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/archive_jobs_in_hrflow.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/archive_jobs_in_hrflow.json new file mode 100644 index 000000000..0f08897f0 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/archive_jobs_in_hrflow.json @@ -0,0 +1,3 @@ +{ + "reference": ".reference" +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/archive_profiles_in_hrflow.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/archive_profiles_in_hrflow.json new file mode 100644 index 000000000..cff0fdb0c --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/archive_profiles_in_hrflow.json @@ -0,0 +1,3 @@ +{ + "reference": ".id" +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/create_jobs_in_hrflow.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/create_jobs_in_hrflow.json new file mode 100644 index 000000000..df3113cd2 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/create_jobs_in_hrflow.json @@ -0,0 +1,72 @@ +{ + "reference": ".reference", + "created_at": ".creationDate", + "location": { + "text": ".location.address", + "lat": ".location.latitude", + "lng": ".location.longitude" + }, + "url": null, + "summary": null, + "sections": [ + { + "name": "description1", + "title": "description1", + "description": ".jobDescription.description1 >> ''" + }, + { + "name": "description2", + "title": "description2", + "description": ".jobDescription.description2 >> ''" + }, + { + "name": "'Complément du descriptif'", + "title": "'Complément du descriptif'", + "description": "$concat(.jobDescription.jobDescriptionCustomFields.longText1 >> '', '\n' , .jobDescription.jobDescriptionCustomFields.longText2>> '', '\n' ,.jobDescription.jobDescriptionCustomFields.longText3>> '')" + } + ], + "tags": [ + { + "name": "talentsoft-organisation-id", + "value": "?.organisation?.id" + }, + { + "name": "talentsoft-status-id", + "value": "?.status?.id" + }, + { + "name": "talentsoft-professionalCategory-id", + "value": "?.jobDescription.professionalCategory?.id" + }, + { + "name": "talentsoft-country-id", + "value": "?.jobDescription.country?.id" + }, + { + "name": "talentsoft-primaryProfile-id", + "value": "?.jobDescription.primaryProfile?.id" + }, + { + "name": "talentsoft-contractType-id", + "value": "?.jobDescription.contractType?.id" + }, + { + "name": "talentsoft-publishedOnInternet", + "value": "?.publishedOnInternet" + }, + { + "name": "talentsoft-publishedOnIntranet", + "value": "?.publishedOnIntranet" + }, + { + "name": "talentsoft-experienceLevel", + "value": "?.criteria.experienceLevel?.id" + }, + { + "name": "talentsoft-educationLevel", + "value": "?.criteria.educationLevel?.id" + } + ], + "skills": ".criteria.skills", + "languages": "?.languages >> [] | {name: .language.label, value: null}" +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/create_profiles_in_hrflow.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/create_profiles_in_hrflow.json new file mode 100644 index 000000000..a63516eb0 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/create_profiles_in_hrflow.json @@ -0,0 +1,11 @@ +{ + "reference": ".candidateDetail.id", + "created_at": ".candidateDetail.creationDate", + "updated_at": "$now('iso')", + "resume": ".attachments | .isResume ?? {raw: .raw, content_type: .mimeType} : null ", + "tags": "$merge([{ 'name': 'talentsoft-isEmployee', 'value': '.isEmployee'},{ 'name': 'talentsoft-isInProgress', 'value': '.isInProgress'},{ 'name': 'talentsoft-residentCountry-id', 'value': '.candidateDetail.personalInformation.residentCountry?.id'},{ 'name': 'talentsoft-contractType-id', 'value': '.candidateDetail.positionSought.contractType.id'},{ 'name': 'talentsoft-profileStatus-id', 'value': '.candidateDetail.positionSought.jobPreferencesCustomFields.customCodeTable1.id'},{ 'name': 'talentsoft-experienceLevel-id', 'value': '.candidateDetail.globalExperience.globalExperienceLevel.id'},{ 'name': 'talentsoft-profile-id', 'value': '.candidateDetail.positionSought.primaryProfile.id'},{ 'name': 'talentsofteducationLevel-id', 'value': '.candidateDetail.educations.educationLevel.id'}], .candidateDetail.educations | $map(.educationLevel != null ?? {name: 'talentsofteducationLevel-id', value: .educationLevel.id} ), .applications | $map({name: 'talentsoft-application-vacancyReference', value: .vacancyReference}))", + "metadatas": [ + { "name": "profile_uid", "value": ".candidateDetail.id" }, + ".attachments | .isResume ?? {name: 'filename', value: .filename}" + ] +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/create_profiles_in_talentsoft.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/create_profiles_in_talentsoft.json new file mode 100644 index 000000000..554ec689c --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/create_profiles_in_talentsoft.json @@ -0,0 +1,179 @@ +{ + "#CONTRACT_TYPE_REFERENTIAL": { + "Alternance": { + "code": 1047, + "clientCode": "_TS_CO_Contract_Alternance", + "label": "Apprenticeship", + "type": "contractType", + "parentType": "" + }, + "CDD": { + "code": 1045, + "clientCode": "_TS_CO_Contract_CDD", + "label": "Fixed Term contract", + "type": "contractType", + "parentType": "" + }, + "CDI": { + "code": 1044, + "clientCode": "_TS_CO_Contract_CDI", + "label": "Permanent", + "type": "contractType", + "parentType": "" + }, + "CIFRE": { + "code": 1049, + "clientCode": "_TS_CO_Contract_CIFRE", + "label": "CIFRE", + "type": "contractType", + "parentType": "" + }, + "Stage": { + "code": 1046, + "clientCode": "_TS_CO_Contract_Stage", + "label": "Internship / Student", + "type": "contractType", + "parentType": "" + }, + "VIE": { + "code": 1048, + "clientCode": "_TS_CO_Contract_VIE", + "label": "VIE", + "type": "contractType", + "parentType": "" + } + }, + "#EDUCATIONS_REFERENTIEL": { + "Aucun diplôme": { + "code": 261, + "clientCode": "_TS_etude_min_Aucun_diplome", + "label": "No Degree", + "type": "educationLevel", + "parentType": "" + }, + "BAC": { + "code": 262, + "clientCode": "_TS_etude_min_BAC", + "label": "Bac", + "type": "educationLevel", + "parentType": "" + }, + "BAC+2": { + "code": 2859, + "clientCode": "_TS_etude_min_BAC2", + "label": "A Levels, Diploma", + "type": "educationLevel", + "parentType": "" + }, + "BAC+3": { + "code": 4028, + "clientCode": "_TS_etude_min_Licence", + "label": "Licence", + "type": "educationLevel", + "parentType": "" + }, + "BAC+4": { + "code": 2860, + "clientCode": "_TS_etude_min_BAC4", + "label": "Bachelor's Degree", + "type": "educationLevel", + "parentType": "" + }, + "BAC+5": { + "code": 266, + "clientCode": "_TS_etude_min_BAC5", + "label": "Master Degree", + "type": "educationLevel", + "parentType": "" + }, + "CAP, BEP": { + "code": 2858, + "clientCode": "_TS_etude_min_CAP_BEP", + "label": "GCSEs", + "type": "educationLevel", + "parentType": "" + }, + "DOCTORAT": { + "code": 2861, + "clientCode": "_TS_etude_min_DOCTORAT", + "label": "PhD, Doctorate", + "type": "educationLevel", + "parentType": "" + }, + "Mastère": { + "code": 4030, + "clientCode": "_TS_etude_min_Mastere", + "label": "Mastère", + "type": "educationLevel", + "parentType": "" + } + }, + "#EXPERIENCES_REFERENTIEL": { + "Etudiant-e": "", + "Débutant-e/première expérience": { + "code": 274, + "clientCode": "_TS_niveau_exp_premiere_exp", + "label": "First experience", + "type": "experienceLevel", + "parentType": "" + }, + "Supérieure à 3 ans": { + "code": 1785, + "clientCode": "_TS_niveau_exp_superieur_3ans ", + "label": "More than 3 years", + "type": "experienceLevel", + "parentType": "" + }, + "Supérieure à 5 ans": { + "code": 1783, + "clientCode": "_TS_niveau_exp_superieur_5ans", + "label": "More than 5 years", + "type": "experienceLevel", + "parentType": "" + }, + "Supérieure à 8 ans": { + "code": 275, + "clientCode": "_TS_niveau_exp_superieur_8ans", + "label": "More than 8 years", + "type": "experienceLevel", + "parentType": "" + } + }, + + "applicant": { + "personalInformation": { + "firstName": ".info.first_name", + "lastName": ".info.last_name", + "birthDate": ".info.date_birth", + "phoneNumber": ".info.phone", + "email": ".info.email", + "address": ".info.location.text", + "city": ".info.location.fields?.city >> ''", + "postalCode": ".info.location.fields?.postalCode >> ''", + "civility": ".info?.gender != null ?? .info.gender | {code: . == 'male' ?? 280: 281, clientCode: . == 'male' ?? '_TS_CO_Civility_Mr': '_TS_CO_Civility_Mme' , label: . == 'male' ?? 'Mr.': 'Ms.', type: 'civility', parentType: ''}: null" + }, + "jobPreferences": { + "contractType": ".tags | .name == 'talentsoft_contract_type' ?? #CONTRACT_TYPE_REFERENTIAL.[.value]: null", + "salaryPretensions": ".tags | .name == 'talentsoft_salary' ?? .value: null" + }, + "education": { + "diplomas": "$merge(.tags | .name == 'talentsoft_experience_level' ?? [{educationLevel: #EDUCATIONS_REFERENTIEL.[.value]}]: [], .educations | $map({college: .school, yearObtained: .date_end ?? .date_end | $slice(0, 3): ''}))" + }, + "experiences": { + "experienceLevel": ".tags | .name == 'talentsoft_experience_level' ?? #EXPERIENCES_REFERENTIEL.[.value]: null", + "experienceList": ".experiences | $map({company: .company, function: .title, length: .date_start != null and .date_end != null ?? '<< MISSING ARITHMETICS HERE >>' : null })" + } + }, + "application": { + "type": "offer", + "offerReference": "" + }, + "uploadedFiles": [ + { + "description": ".attachments[0].original_file_name", + "fileTypeId": 36, + "key": "cv_file_id" + } + ], + "attachment": ".attachments[0]" +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/update_jobs_in_hrflow.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/update_jobs_in_hrflow.json new file mode 100644 index 000000000..83690198e --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/update_jobs_in_hrflow.json @@ -0,0 +1,73 @@ +{ + "name": ".jobDescription.title", + "reference": ".reference", + "created_at": ".creationDate", + "location": { + "text": ".location.address", + "lat": ".location.latitude", + "lng": ".location.longitude" + }, + "url": null, + "summary": null, + "sections": [ + { + "name": "description1", + "title": "description1", + "description": ".jobDescription.description1 >> ''" + }, + { + "name": "description2", + "title": "description2", + "description": ".jobDescription.description2 >> ''" + }, + { + "name": "'Complément du descriptif'", + "title": "'Complément du descriptif'", + "description": "$concat(.jobDescription.jobDescriptionCustomFields.longText1 >> '', '\n' , .jobDescription.jobDescriptionCustomFields.longText2>> '', '\n' ,.jobDescription.jobDescriptionCustomFields.longText3>> '')" + } + ], + "tags": [ + { + "name": "talentsoft-organisation-id", + "value": "?.organisation?.id" + }, + { + "name": "talentsoft-status-id", + "value": "?.status?.id" + }, + { + "name": "talentsoft-professionalCategory-id", + "value": "?.jobDescription.professionalCategory?.id" + }, + { + "name": "talentsoft-country-id", + "value": "?.jobDescription.country?.id" + }, + { + "name": "talentsoft-primaryProfile-id", + "value": "?.jobDescription.primaryProfile?.id" + }, + { + "name": "talentsoft-contractType-id", + "value": "?.jobDescription.contractType?.id" + }, + { + "name": "talentsoft-publishedOnInternet", + "value": "?.publishedOnInternet" + }, + { + "name": "talentsoft-publishedOnIntranet", + "value": "?.publishedOnIntranet" + }, + { + "name": "talentsoft-experienceLevel", + "value": "?.criteria.experienceLevel?.id" + }, + { + "name": "talentsoft-educationLevel", + "value": "?.criteria.educationLevel?.id" + } + ], + "skills": ".criteria.skills", + "languages": "?.languages >> [] | {name: .language.label, value: null}" +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/update_profiles_in_hrflow.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/update_profiles_in_hrflow.json new file mode 100644 index 000000000..a63516eb0 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/update_profiles_in_hrflow.json @@ -0,0 +1,11 @@ +{ + "reference": ".candidateDetail.id", + "created_at": ".candidateDetail.creationDate", + "updated_at": "$now('iso')", + "resume": ".attachments | .isResume ?? {raw: .raw, content_type: .mimeType} : null ", + "tags": "$merge([{ 'name': 'talentsoft-isEmployee', 'value': '.isEmployee'},{ 'name': 'talentsoft-isInProgress', 'value': '.isInProgress'},{ 'name': 'talentsoft-residentCountry-id', 'value': '.candidateDetail.personalInformation.residentCountry?.id'},{ 'name': 'talentsoft-contractType-id', 'value': '.candidateDetail.positionSought.contractType.id'},{ 'name': 'talentsoft-profileStatus-id', 'value': '.candidateDetail.positionSought.jobPreferencesCustomFields.customCodeTable1.id'},{ 'name': 'talentsoft-experienceLevel-id', 'value': '.candidateDetail.globalExperience.globalExperienceLevel.id'},{ 'name': 'talentsoft-profile-id', 'value': '.candidateDetail.positionSought.primaryProfile.id'},{ 'name': 'talentsofteducationLevel-id', 'value': '.candidateDetail.educations.educationLevel.id'}], .candidateDetail.educations | $map(.educationLevel != null ?? {name: 'talentsofteducationLevel-id', value: .educationLevel.id} ), .applications | $map({name: 'talentsoft-application-vacancyReference', value: .vacancyReference}))", + "metadatas": [ + { "name": "profile_uid", "value": ".candidateDetail.id" }, + ".attachments | .isResume ?? {name: 'filename', value: .filename}" + ] +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/update_profiles_in_talentsoft.json b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/update_profiles_in_talentsoft.json new file mode 100644 index 000000000..554ec689c --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/mappings/format/update_profiles_in_talentsoft.json @@ -0,0 +1,179 @@ +{ + "#CONTRACT_TYPE_REFERENTIAL": { + "Alternance": { + "code": 1047, + "clientCode": "_TS_CO_Contract_Alternance", + "label": "Apprenticeship", + "type": "contractType", + "parentType": "" + }, + "CDD": { + "code": 1045, + "clientCode": "_TS_CO_Contract_CDD", + "label": "Fixed Term contract", + "type": "contractType", + "parentType": "" + }, + "CDI": { + "code": 1044, + "clientCode": "_TS_CO_Contract_CDI", + "label": "Permanent", + "type": "contractType", + "parentType": "" + }, + "CIFRE": { + "code": 1049, + "clientCode": "_TS_CO_Contract_CIFRE", + "label": "CIFRE", + "type": "contractType", + "parentType": "" + }, + "Stage": { + "code": 1046, + "clientCode": "_TS_CO_Contract_Stage", + "label": "Internship / Student", + "type": "contractType", + "parentType": "" + }, + "VIE": { + "code": 1048, + "clientCode": "_TS_CO_Contract_VIE", + "label": "VIE", + "type": "contractType", + "parentType": "" + } + }, + "#EDUCATIONS_REFERENTIEL": { + "Aucun diplôme": { + "code": 261, + "clientCode": "_TS_etude_min_Aucun_diplome", + "label": "No Degree", + "type": "educationLevel", + "parentType": "" + }, + "BAC": { + "code": 262, + "clientCode": "_TS_etude_min_BAC", + "label": "Bac", + "type": "educationLevel", + "parentType": "" + }, + "BAC+2": { + "code": 2859, + "clientCode": "_TS_etude_min_BAC2", + "label": "A Levels, Diploma", + "type": "educationLevel", + "parentType": "" + }, + "BAC+3": { + "code": 4028, + "clientCode": "_TS_etude_min_Licence", + "label": "Licence", + "type": "educationLevel", + "parentType": "" + }, + "BAC+4": { + "code": 2860, + "clientCode": "_TS_etude_min_BAC4", + "label": "Bachelor's Degree", + "type": "educationLevel", + "parentType": "" + }, + "BAC+5": { + "code": 266, + "clientCode": "_TS_etude_min_BAC5", + "label": "Master Degree", + "type": "educationLevel", + "parentType": "" + }, + "CAP, BEP": { + "code": 2858, + "clientCode": "_TS_etude_min_CAP_BEP", + "label": "GCSEs", + "type": "educationLevel", + "parentType": "" + }, + "DOCTORAT": { + "code": 2861, + "clientCode": "_TS_etude_min_DOCTORAT", + "label": "PhD, Doctorate", + "type": "educationLevel", + "parentType": "" + }, + "Mastère": { + "code": 4030, + "clientCode": "_TS_etude_min_Mastere", + "label": "Mastère", + "type": "educationLevel", + "parentType": "" + } + }, + "#EXPERIENCES_REFERENTIEL": { + "Etudiant-e": "", + "Débutant-e/première expérience": { + "code": 274, + "clientCode": "_TS_niveau_exp_premiere_exp", + "label": "First experience", + "type": "experienceLevel", + "parentType": "" + }, + "Supérieure à 3 ans": { + "code": 1785, + "clientCode": "_TS_niveau_exp_superieur_3ans ", + "label": "More than 3 years", + "type": "experienceLevel", + "parentType": "" + }, + "Supérieure à 5 ans": { + "code": 1783, + "clientCode": "_TS_niveau_exp_superieur_5ans", + "label": "More than 5 years", + "type": "experienceLevel", + "parentType": "" + }, + "Supérieure à 8 ans": { + "code": 275, + "clientCode": "_TS_niveau_exp_superieur_8ans", + "label": "More than 8 years", + "type": "experienceLevel", + "parentType": "" + } + }, + + "applicant": { + "personalInformation": { + "firstName": ".info.first_name", + "lastName": ".info.last_name", + "birthDate": ".info.date_birth", + "phoneNumber": ".info.phone", + "email": ".info.email", + "address": ".info.location.text", + "city": ".info.location.fields?.city >> ''", + "postalCode": ".info.location.fields?.postalCode >> ''", + "civility": ".info?.gender != null ?? .info.gender | {code: . == 'male' ?? 280: 281, clientCode: . == 'male' ?? '_TS_CO_Civility_Mr': '_TS_CO_Civility_Mme' , label: . == 'male' ?? 'Mr.': 'Ms.', type: 'civility', parentType: ''}: null" + }, + "jobPreferences": { + "contractType": ".tags | .name == 'talentsoft_contract_type' ?? #CONTRACT_TYPE_REFERENTIAL.[.value]: null", + "salaryPretensions": ".tags | .name == 'talentsoft_salary' ?? .value: null" + }, + "education": { + "diplomas": "$merge(.tags | .name == 'talentsoft_experience_level' ?? [{educationLevel: #EDUCATIONS_REFERENTIEL.[.value]}]: [], .educations | $map({college: .school, yearObtained: .date_end ?? .date_end | $slice(0, 3): ''}))" + }, + "experiences": { + "experienceLevel": ".tags | .name == 'talentsoft_experience_level' ?? #EXPERIENCES_REFERENTIEL.[.value]: null", + "experienceList": ".experiences | $map({company: .company, function: .title, length: .date_start != null and .date_end != null ?? '<< MISSING ARITHMETICS HERE >>' : null })" + } + }, + "application": { + "type": "offer", + "offerReference": "" + }, + "uploadedFiles": [ + { + "description": ".attachments[0].original_file_name", + "fileTypeId": 36, + "key": "cv_file_id" + } + ], + "attachment": ".attachments[0]" +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/notebooks/.gitkeep b/src/hrflow_connectors/v2/connectors/talentsoft/notebooks/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/schemas.py b/src/hrflow_connectors/v2/connectors/talentsoft/schemas.py new file mode 100644 index 000000000..5cf0e830e --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/schemas.py @@ -0,0 +1,223 @@ +import typing as t + +from pydantic import BaseModel + + +class PersonalInformation(BaseModel): + civility: t.Optional[str] + middleName: t.Optional[str] + title: t.Optional[str] + address: t.Optional[str] + city: t.Optional[str] + postalCode: t.Optional[str] + birthDate: t.Optional[str] + country: t.Optional[str] + skypeAccount: t.Optional[str] + receiveSMS: t.Optional[str] + phoneNumber2: t.Optional[str] + professionalEmail: t.Optional[str] + sex: t.Optional[str] + nationalities: t.List[str] + frenchDisabledWorkerStatus: t.Optional[str] + frenchPriorityNeighbourhood: t.Optional[str] + firstName: str + lastName: str + email: str + phoneNumber: str + + +class Diplomas(BaseModel): + educationLevel: str + diplomaCode: t.Optional[str] + specialisation: t.Optional[str] + yearObtained: str + college: str + collegeCity: t.Optional[str] + + +class Language(BaseModel): + language: str + languageLevel: str + + +class Education(BaseModel): + diplomas: t.List[Diplomas] + studiedLanguages: t.List[Language] + + +class Experience(BaseModel): + experienceLevel: t.Optional[str] + Profile: t.Optional[str] + contract: t.Optional[str] + company: str + function: str + length: t.Optional[str] + + +class Experiences(BaseModel): + experienceLevel: t.Optional[str] + experienceList: t.List[Experience] + + +class Mobility(BaseModel): + geographicalAreas: t.List[str] + countries: t.List[str] + regions: t.List[str] + departments: t.List[str] + + +class Availability(BaseModel): + acceptsExtra: t.Optional[str] + values: t.List[str] + + +class FurtherInformation(BaseModel): + skills: t.List[str] + + +class eEOInformation(BaseModel): + doesNotComplete: bool + sex: t.Optional[str] + race: t.Optional[str] + ethnicity: t.Optional[str] + veteranStatus: t.Optional[str] + incapacityStatus: t.Optional[str] + + +class jobPreferences(BaseModel): + primaryProfile: t.Optional[str] + contract: t.Optional[str] + contractDuration: t.Optional[str] + salaryPretensions: t.Optional[str] + dateOfAvailability: t.Optional[str] + mobility: Mobility + noticeDuration: t.Optional[str] + mobilityDelay: t.Optional[str] + trainingDateStart: t.Optional[str] + trainingDateEnd: t.Optional[str] + jobTime: t.Optional[str] + secondaryProfiles: t.List[str] + availability: Availability + + +class standardItem(BaseModel): + code: int + clientCode: str + label: str + active: bool + parentCode: t.Union[None, int] + type: str + parentType: str + hasChildren: bool + + +class fileItem(BaseModel): + guid: str + name: str + description: str + fileType: standardItem + + +class Application(BaseModel): + id: int + type: str + offerReference: str + offerTitle: str + isOfferPublished: bool + organisation: standardItem + origin: standardItem + motivation: t.Optional[str] + referralCode: t.Optional[str] + files: t.List[fileItem] + applicationAnswers: t.List[dict] + date: str + status: standardItem + personalDataConsentReceived: t.Optional[str] + retentionDelay: t.Optional[str] + frenchDisabledWorkerStatus: t.Optional[str] + + +class UploadedFile(BaseModel): + description: str + fileTypeId: str + key: str + + +class Applicant(BaseModel): + personalInformation: PersonalInformation + jobPreferences: jobPreferences + educations: Education + experiences: Experiences + consents: t.List[dict] + furtherInformation: FurtherInformation + eEOInformation: eEOInformation + customFields: str + + +class TalentsoftApplicantSchema(BaseModel): + applicant: Applicant + application: Application + uploadedFiles: t.List[UploadedFile] + + +class UpdateSpecialEmploymentRegulationsInFrance(BaseModel): + disabledWorkerStatus: bool + priorityNeighbourhood: bool + + +class UpdatePersonalInformation(BaseModel): + birthDate: str + nationalities: t.List[str] + address: str + postalCode: str + city: str + residentCountryId: str + specialEmploymentRegulationsInFrance: t.Optional[ + UpdateSpecialEmploymentRegulationsInFrance + ] + + +class UpdateJobPreferences(BaseModel): + primaryProfileId: str + dateOfAvailability: str + salaryExpectations: str + + +class UpdateLanguage(BaseModel): + languageId: str + languageLevelId: str + + +class UpdateEducation(BaseModel): + diplomaId: str + educationLevelId: str + + +class UpdateExperience(BaseModel): + experienceLevelId: str + profileId: str + company: str + function: str + contractTypeId: str + + +class UpdateAttachment(BaseModel): + description: str + key: str + fileType: str + + +class CandidateUpdated(BaseModel): + employeeNumber: t.Optional[str] + lastName: str + firstName: str + middleName: t.Optional[str] + email: str + phoneNumber: t.Optional[str] + civilityId: t.Optional[str] + personalInformation: t.Optional[UpdatePersonalInformation] + jobPreferences: t.Optional[UpdateJobPreferences] + languages: t.Optional[t.List[UpdateLanguage]] + educations: t.Optional[t.List[UpdateEducation]] + experiences: t.Optional[t.List[UpdateExperience]] + attachments: t.Optional[t.List[UpdateAttachment]] diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/test-config.yaml b/src/hrflow_connectors/v2/connectors/talentsoft/test-config.yaml new file mode 100644 index 000000000..540df0a9b --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/test-config.yaml @@ -0,0 +1 @@ +warehouse: {} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/utils/const.py b/src/hrflow_connectors/v2/connectors/talentsoft/utils/const.py new file mode 100644 index 000000000..9815fdeff --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/utils/const.py @@ -0,0 +1,186 @@ +CIVILITY = [ + { + "code": 3445, + "clientCode": "_TS_CO_Civility_Dr", + "label": "Dr.", + "type": "civility", + "parentType": "", + }, + { + "code": 1790, + "clientCode": "_TS_CO_Civility_Miss", + "label": "Miss", + "type": "civility", + "parentType": "", + }, + { + "code": 280, + "clientCode": "_TS_CO_Civility_Mr", + "label": "Mr.", + "type": "civility", + "parentType": "", + }, + { + "code": 1789, + "clientCode": "_TS_CO_Civility_Mrs ", + "label": "Mrs", + "type": "civility", + "parentType": "", + }, + { + "code": 281, + "clientCode": "_TS_CO_Civility_Mme", + "label": "Ms.", + "type": "civility", + "parentType": "", + }, + { + "code": 3467, + "clientCode": "_TS_CO_Civility_Other", + "label": "Other", + "type": "civility", + "parentType": "", + }, +] + +EDUCATIONS_REFERENTIEL = { + "Aucun diplôme": { + "code": 261, + "clientCode": "_TS_etude_min_Aucun_diplome", + "label": "No Degree", + "type": "educationLevel", + "parentType": "", + }, + "BAC": { + "code": 262, + "clientCode": "_TS_etude_min_BAC", + "label": "Bac", + "type": "educationLevel", + "parentType": "", + }, + "BAC+2": { + "code": 2859, + "clientCode": "_TS_etude_min_BAC2", + "label": "A Levels, Diploma", + "type": "educationLevel", + "parentType": "", + }, + "BAC+3": { + "code": 4028, + "clientCode": "_TS_etude_min_Licence", + "label": "Licence", + "type": "educationLevel", + "parentType": "", + }, + "BAC+4": { + "code": 2860, + "clientCode": "_TS_etude_min_BAC4", + "label": "Bachelor's Degree", + "type": "educationLevel", + "parentType": "", + }, + "BAC+5": { + "code": 266, + "clientCode": "_TS_etude_min_BAC5", + "label": "Master Degree", + "type": "educationLevel", + "parentType": "", + }, + "CAP, BEP": { + "code": 2858, + "clientCode": "_TS_etude_min_CAP_BEP", + "label": "GCSEs", + "type": "educationLevel", + "parentType": "", + }, + "DOCTORAT": { + "code": 2861, + "clientCode": "_TS_etude_min_DOCTORAT", + "label": "PhD, Doctorate", + "type": "educationLevel", + "parentType": "", + }, + "Mastère": { + "code": 4030, + "clientCode": "_TS_etude_min_Mastere", + "label": "Mastère", + "type": "educationLevel", + "parentType": "", + }, +} +EXPERIENCES_REFERENTIEL = { + "Etudiant-e": "", + "Débutant-e/première expérience": { + "code": 274, + "clientCode": "_TS_niveau_exp_premiere_exp", + "label": "First experience", + "type": "experienceLevel", + "parentType": "", + }, + "Supérieure à 3 ans": { + "code": 1785, + "clientCode": "_TS_niveau_exp_superieur_3ans ", + "label": "More than 3 years", + "type": "experienceLevel", + "parentType": "", + }, + "Supérieure à 5 ans": { + "code": 1783, + "clientCode": "_TS_niveau_exp_superieur_5ans", + "label": "More than 5 years", + "type": "experienceLevel", + "parentType": "", + }, + "Supérieure à 8 ans": { + "code": 275, + "clientCode": "_TS_niveau_exp_superieur_8ans", + "label": "More than 8 years", + "type": "experienceLevel", + "parentType": "", + }, +} + +CONTRACT_TYPE_REFERENTIAL = { + "Alternance": { + "code": 1047, + "clientCode": "_TS_CO_Contract_Alternance", + "label": "Apprenticeship", + "type": "contractType", + "parentType": "", + }, + "CDD": { + "code": 1045, + "clientCode": "_TS_CO_Contract_CDD", + "label": "Fixed Term contract", + "type": "contractType", + "parentType": "", + }, + "CDI": { + "code": 1044, + "clientCode": "_TS_CO_Contract_CDI", + "label": "Permanent", + "type": "contractType", + "parentType": "", + }, + "CIFRE": { + "code": 1049, + "clientCode": "_TS_CO_Contract_CIFRE", + "label": "CIFRE", + "type": "contractType", + "parentType": "", + }, + "Stage": { + "code": 1046, + "clientCode": "_TS_CO_Contract_Stage", + "label": "Internship / Student", + "type": "contractType", + "parentType": "", + }, + "VIE": { + "code": 1048, + "clientCode": "_TS_CO_Contract_VIE", + "label": "VIE", + "type": "contractType", + "parentType": "", + }, +} diff --git a/src/hrflow_connectors/v2/connectors/talentsoft/warehouse.py b/src/hrflow_connectors/v2/connectors/talentsoft/warehouse.py new file mode 100644 index 000000000..99e041c2b --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/talentsoft/warehouse.py @@ -0,0 +1,8 @@ +from hrflow_connectors.v2.connectors.talentsoft.aisles import ( + AuthParameters, + JobsAisle, + ProfilesAisle, +) +from hrflow_connectors.v2.core.warehouse import Warehouse + +TalentSoftWarehouse = Warehouse(auth=AuthParameters, aisles=(JobsAisle, ProfilesAisle))