diff --git a/README.md b/README.md index 5dde6c464..4d239713b 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ We invite developers to join us in our mission to bring AI and data integration | Name | Type | Status | Release date | Last update | |-------------------------------------------------------------------------------------------------------------------------------------------|----------------------|--------------------|----------------|-----------------| | [**AD-MEN**](./src/hrflow_connectors/v2/connectors/admen/README.md) | CRM | :book: Open source | ** | ** | -| [**Breezy HR**](./src/hrflow_connectors/v1/connectors/breezyhr/README.md) | ATS | :book: Open source | *19/01/2022* | *31/10/2024* | +| [**Breezy HR**](./src/hrflow_connectors/v2/connectors/breezyhr/README.md) | ATS | :book: Open source | *19/01/2022* | *31/10/2024* | | [**Bullhorn**](./src/hrflow_connectors/v2/connectors/bullhorn/README.md) | ATS | :book: Open source | *26/01/2022* | *23/10/2024* | | [**Ceridian**](./src/hrflow_connectors/v1/connectors/ceridian/README.md) | HCM | :book: Open source | *19/01/2022* | *05/09/2024* | | [**Digitalrecruiters**](./src/hrflow_connectors/v1/connectors/digitalrecruiters/README.md) | ATS | :book: Open source | *17/08/2023* | *24/10/2024* | diff --git a/manifest.json b/manifest.json index a368103a9..fa51547c5 100644 --- a/manifest.json +++ b/manifest.json @@ -85030,6 +85030,9485 @@ } } ] + }, + { + "name": "Breezy HR", + "type": "ATS", + "subtype": "breezyhr", + "logo": "https://raw.githubusercontent.com/Riminder/hrflow-connectors/master/src/hrflow_connectors/v2/connectors/breezyhr/logo.jpg", + "actions": [ + { + "name": "create_jobs_in_hrflow", + "data_type": "job", + "direction": "inbound", + "mode": "create", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "email": { + "description": "email", + "type": "string" + }, + "password": { + "description": "password", + "type": "string" + }, + "company_id": { + "description": "ID of company to pull jobs from in Breezy HR database associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company_name": { + "description": "[\u26a0\ufe0f Requiered if company_id is not specified], the company associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "email", + "password" + ], + "$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": "Breezy HR", + "origin_data_schema": { + "title": "BreezyJobModel", + "type": "object", + "properties": { + "_id": { + "description": "position id", + "type": "string" + }, + "type": { + "description": "job type", + "$ref": "#/$defs/Type" + }, + "state": { + "description": "state of the position posting, published or internal and so on", + "type": "string" + }, + "name": { + "description": "job title", + "type": "string" + }, + "friendly_id": { + "description": "another id of the job which combines its title and its id", + "type": "string" + }, + "experience": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Experience" + } + ] + }, + "location": { + "$ref": "#/$defs/Location" + }, + "education": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "description": "Job category", + "type": "string" + }, + "category": { + "$ref": "#/$defs/Category" + }, + "application_form": { + "description": "job Application for", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/ApplicationForm" + } + ] + }, + "creator_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "creation_date": { + "type": "string" + }, + "updated_date": { + "type": "string" + }, + "all_users": { + "type": "array", + "items": { + "type": "string" + } + }, + "all_admins": { + "type": "array", + "items": { + "type": "string" + } + }, + "candidate_type": { + "type": "string" + }, + "tags": { + "type": "array" + }, + "org_type": { + "type": "string" + } + }, + "required": [ + "_id", + "type", + "state", + "name", + "friendly_id", + "experience", + "location", + "education", + "department", + "description", + "category", + "application_form", + "creator_id", + "creation_date", + "updated_date", + "all_users", + "all_admins", + "candidate_type", + "tags", + "org_type" + ], + "$defs": { + "Type": { + "title": "Type", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "country": { + "$ref": "#/$defs/Country" + }, + "city": { + "type": "string" + }, + "is_remote": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + } + }, + "required": [ + "country", + "city", + "is_remote", + "name" + ] + }, + "Country": { + "title": "Country", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "name", + "id" + ] + }, + "Category": { + "title": "Category", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "ApplicationForm": { + "title": "ApplicationForm", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "headline": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "profile_photo": { + "type": "string" + }, + "address": { + "type": "string" + }, + "email_address": { + "type": "string" + }, + "phone_number": { + "type": "string" + }, + "resume": { + "type": "string" + }, + "work_history": { + "type": "string" + }, + "education": { + "type": "string" + }, + "cover_letter": { + "type": "string" + }, + "questionnaire_in_experience": { + "type": "boolean" + } + }, + "required": [ + "name", + "headline", + "summary", + "profile_photo", + "address", + "email_address", + "phone_number", + "resume", + "work_history", + "education", + "cover_letter", + "questionnaire_in_experience" + ] + } + } + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadJobsParameters", + "type": "object", + "properties": { + "state": { + "description": "Specify an optional position state filter. e.g. draft, archived, published, closed, pending\nDefaults to published", + "$ref": "#/$defs/State", + "default": "published" + } + }, + "required": [], + "$defs": { + "State": { + "title": "State", + "enum": [ + "archived", + "closed", + "draft", + "pending", + "published" + ] + } + } + }, + "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": { + "name": "?.name", + "reference": "?._id", + "summary": "?.description | $sub('<[^<]+?>', '') | $sub(' ', ' ')", + "location": { + "text": "?.location?.streetAddress?.custom ?? .location.streetAddress.custom: .location.name", + "geojson": { + "country": "?.location?.country?.name", + "city": "?.location?.city", + "text": "?.location?.streetAddress?.custom ?? .location.streetAddress.custom: .location.name" + }, + "lat": null, + "lng": null + }, + "sections": [ + { + "name": "description", + "title": "description", + "description": "?.description | $sub('<[^<]+?>', '') | $sub(' ', ' ')" + }, + { + "name": "experience", + "title": "Required Experience", + "description": "?.experience?.name" + }, + { + "name": "education", + "title": "Required Education", + "description": "?.education?.name" + }, + { + "name": "category", + "title": "Category", + "description": "?.category?.name" + }, + { + "name": "remote", + "title": "Remote Information", + "description": "?.location?.remote_details" + } + ], + "tags": [ + { + "name": "type", + "value": "?.type?.name" + }, + { + "name": "experience", + "value": "?.experience?.name" + }, + { + "name": "education", + "value": "?.education" + }, + { + "name": "department", + "value": "?.department" + }, + { + "name": "requisition_id", + "value": "?.requisition_id" + }, + { + "name": "category", + "value": "?.category?.name" + }, + { + "name": "candidate_type", + "value": "?.candidate_type" + }, + { + "name": "isremote", + "value": "?.location?.is_remote" + }, + { + "name": "remote_details", + "value": "?.location?.remote_details" + }, + { + "name": "creator_id", + "value": "?.creator_id" + }, + { + "name": "breezy_hr_tags", + "value": "?.tags" + } + ], + "created_at": "?.creation_date", + "updated_at": "?.updated_date" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import BreezyHR\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 BreezyHR.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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('state',):\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 BreezyHR.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 BreezyHR\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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('state',):\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 BreezyHR.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": { + "email": { + "description": "email", + "type": "string" + }, + "password": { + "description": "password", + "type": "string" + }, + "company_id": { + "description": "ID of company to pull jobs from in Breezy HR database associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company_name": { + "description": "[\u26a0\ufe0f Requiered if company_id is not specified], the company associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "email", + "password" + ], + "$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": "Breezy HR", + "origin_data_schema": { + "title": "BreezyJobModel", + "type": "object", + "properties": { + "_id": { + "description": "position id", + "type": "string" + }, + "type": { + "description": "job type", + "$ref": "#/$defs/Type" + }, + "state": { + "description": "state of the position posting, published or internal and so on", + "type": "string" + }, + "name": { + "description": "job title", + "type": "string" + }, + "friendly_id": { + "description": "another id of the job which combines its title and its id", + "type": "string" + }, + "experience": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Experience" + } + ] + }, + "location": { + "$ref": "#/$defs/Location" + }, + "education": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "description": "Job category", + "type": "string" + }, + "category": { + "$ref": "#/$defs/Category" + }, + "application_form": { + "description": "job Application for", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/ApplicationForm" + } + ] + }, + "creator_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "creation_date": { + "type": "string" + }, + "updated_date": { + "type": "string" + }, + "all_users": { + "type": "array", + "items": { + "type": "string" + } + }, + "all_admins": { + "type": "array", + "items": { + "type": "string" + } + }, + "candidate_type": { + "type": "string" + }, + "tags": { + "type": "array" + }, + "org_type": { + "type": "string" + } + }, + "required": [ + "_id", + "type", + "state", + "name", + "friendly_id", + "experience", + "location", + "education", + "department", + "description", + "category", + "application_form", + "creator_id", + "creation_date", + "updated_date", + "all_users", + "all_admins", + "candidate_type", + "tags", + "org_type" + ], + "$defs": { + "Type": { + "title": "Type", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "country": { + "$ref": "#/$defs/Country" + }, + "city": { + "type": "string" + }, + "is_remote": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + } + }, + "required": [ + "country", + "city", + "is_remote", + "name" + ] + }, + "Country": { + "title": "Country", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "name", + "id" + ] + }, + "Category": { + "title": "Category", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "ApplicationForm": { + "title": "ApplicationForm", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "headline": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "profile_photo": { + "type": "string" + }, + "address": { + "type": "string" + }, + "email_address": { + "type": "string" + }, + "phone_number": { + "type": "string" + }, + "resume": { + "type": "string" + }, + "work_history": { + "type": "string" + }, + "education": { + "type": "string" + }, + "cover_letter": { + "type": "string" + }, + "questionnaire_in_experience": { + "type": "boolean" + } + }, + "required": [ + "name", + "headline", + "summary", + "profile_photo", + "address", + "email_address", + "phone_number", + "resume", + "work_history", + "education", + "cover_letter", + "questionnaire_in_experience" + ] + } + } + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadJobsParameters", + "type": "object", + "properties": { + "state": { + "description": "Specify an optional position state filter. e.g. draft, archived, published, closed, pending\nDefaults to published", + "$ref": "#/$defs/State", + "default": "published" + } + }, + "required": [], + "$defs": { + "State": { + "title": "State", + "enum": [ + "archived", + "closed", + "draft", + "pending", + "published" + ] + } + } + }, + "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": "?.name", + "reference": "?._id", + "summary": "?.description | $sub('<[^<]+?>', '') | $sub(' ', ' ')", + "location": { + "text": "?.location?.streetAddress?.custom ?? .location.streetAddress.custom: .location.name", + "geojson": { + "country": "?.location?.country?.name", + "city": "?.location?.city", + "text": "?.location?.streetAddress?.custom ?? .location.streetAddress.custom: .location.name" + }, + "lat": null, + "lng": null + }, + "sections": [ + { + "name": "description", + "title": "description", + "description": "?.description | $sub('<[^<]+?>', '') | $sub(' ', ' ')" + }, + { + "name": "experience", + "title": "Required Experience", + "description": "?.experience?.name" + }, + { + "name": "education", + "title": "Required Education", + "description": "?.education?.name" + }, + { + "name": "category", + "title": "Category", + "description": "?.category?.name" + }, + { + "name": "remote", + "title": "Remote Information", + "description": "?.location?.remote_details" + } + ], + "tags": [ + { + "name": "type", + "value": "?.type?.name" + }, + { + "name": "experience", + "value": "?.experience?.name" + }, + { + "name": "education", + "value": "?.education" + }, + { + "name": "department", + "value": "?.department" + }, + { + "name": "requisition_id", + "value": "?.requisition_id" + }, + { + "name": "category", + "value": "?.category?.name" + }, + { + "name": "candidate_type", + "value": "?.candidate_type" + }, + { + "name": "isremote", + "value": "?.location?.is_remote" + }, + { + "name": "remote_details", + "value": "?.location?.remote_details" + }, + { + "name": "creator_id", + "value": "?.creator_id" + }, + { + "name": "breezy_hr_tags", + "value": "?.tags" + } + ], + "created_at": "?.creation_date", + "updated_at": "?.updated_date" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import BreezyHR\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 BreezyHR.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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('state',):\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 BreezyHR.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 BreezyHR\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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('state',):\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 BreezyHR.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": { + "email": { + "description": "email", + "type": "string" + }, + "password": { + "description": "password", + "type": "string" + }, + "company_id": { + "description": "ID of company to pull jobs from in Breezy HR database associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company_name": { + "description": "[\u26a0\ufe0f Requiered if company_id is not specified], the company associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "email", + "password" + ], + "$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": "Breezy HR", + "origin_data_schema": { + "title": "BreezyJobModel", + "type": "object", + "properties": { + "_id": { + "description": "position id", + "type": "string" + }, + "type": { + "description": "job type", + "$ref": "#/$defs/Type" + }, + "state": { + "description": "state of the position posting, published or internal and so on", + "type": "string" + }, + "name": { + "description": "job title", + "type": "string" + }, + "friendly_id": { + "description": "another id of the job which combines its title and its id", + "type": "string" + }, + "experience": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/Experience" + } + ] + }, + "location": { + "$ref": "#/$defs/Location" + }, + "education": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "description": "Job category", + "type": "string" + }, + "category": { + "$ref": "#/$defs/Category" + }, + "application_form": { + "description": "job Application for", + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/ApplicationForm" + } + ] + }, + "creator_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "creation_date": { + "type": "string" + }, + "updated_date": { + "type": "string" + }, + "all_users": { + "type": "array", + "items": { + "type": "string" + } + }, + "all_admins": { + "type": "array", + "items": { + "type": "string" + } + }, + "candidate_type": { + "type": "string" + }, + "tags": { + "type": "array" + }, + "org_type": { + "type": "string" + } + }, + "required": [ + "_id", + "type", + "state", + "name", + "friendly_id", + "experience", + "location", + "education", + "department", + "description", + "category", + "application_form", + "creator_id", + "creation_date", + "updated_date", + "all_users", + "all_admins", + "candidate_type", + "tags", + "org_type" + ], + "$defs": { + "Type": { + "title": "Type", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "Experience": { + "title": "Experience", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "Location": { + "title": "Location", + "type": "object", + "properties": { + "country": { + "$ref": "#/$defs/Country" + }, + "city": { + "type": "string" + }, + "is_remote": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + } + }, + "required": [ + "country", + "city", + "is_remote", + "name" + ] + }, + "Country": { + "title": "Country", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "name", + "id" + ] + }, + "Category": { + "title": "Category", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "ApplicationForm": { + "title": "ApplicationForm", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "headline": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "profile_photo": { + "type": "string" + }, + "address": { + "type": "string" + }, + "email_address": { + "type": "string" + }, + "phone_number": { + "type": "string" + }, + "resume": { + "type": "string" + }, + "work_history": { + "type": "string" + }, + "education": { + "type": "string" + }, + "cover_letter": { + "type": "string" + }, + "questionnaire_in_experience": { + "type": "boolean" + } + }, + "required": [ + "name", + "headline", + "summary", + "profile_photo", + "address", + "email_address", + "phone_number", + "resume", + "work_history", + "education", + "cover_letter", + "questionnaire_in_experience" + ] + } + } + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadJobsParameters", + "type": "object", + "properties": { + "state": { + "description": "Specify an optional position state filter. e.g. draft, archived, published, closed, pending\nDefaults to published", + "$ref": "#/$defs/State", + "default": "published" + } + }, + "required": [], + "$defs": { + "State": { + "title": "State", + "enum": [ + "archived", + "closed", + "draft", + "pending", + "published" + ] + } + } + }, + "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": "?._id" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import BreezyHR\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 BreezyHR.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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('state',):\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 BreezyHR.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 BreezyHR\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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('state',):\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 BreezyHR.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_hrflow", + "data_type": "profile", + "direction": "inbound", + "mode": "create", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "email": { + "description": "email", + "type": "string" + }, + "password": { + "description": "password", + "type": "string" + }, + "company_id": { + "description": "ID of company to pull jobs from in Breezy HR database associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company_name": { + "description": "[\u26a0\ufe0f Requiered if company_id is not specified], the company associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "email", + "password" + ], + "$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": "Breezy HR", + "origin_data_schema": { + "title": "BreezyProfileModel", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email_address": { + "type": "string" + }, + "phone_number": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "tags": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "origin": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "address": { + "type": "string" + }, + "work_history": { + "type": "array", + "items": { + "$ref": "#/$defs/WorkHistoryItem" + } + }, + "education": { + "type": "array", + "items": { + "$ref": "#/$defs/EducationItem" + } + }, + "social_profiles": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "custom_attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object" + } + }, + { + "type": "null" + } + ] + }, + "cover_letter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "name", + "email_address", + "phone_number", + "summary", + "tags", + "source", + "origin", + "address", + "work_history", + "education", + "social_profiles", + "custom_attributes", + "cover_letter" + ], + "$defs": { + "WorkHistoryItem": { + "title": "WorkHistoryItem", + "type": "object", + "properties": { + "company_name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "start_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "company_name", + "title", + "summary", + "start_month", + "start_year", + "end_month", + "end_year" + ] + }, + "EducationItem": { + "title": "EducationItem", + "type": "object", + "properties": { + "school_name": { + "type": "string" + }, + "field_of_study": { + "type": "string" + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "school_name", + "field_of_study", + "start_year", + "end_year" + ] + } + } + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadProfilesParameters", + "type": "object", + "properties": { + "position_id": { + "description": "Id of the position to create a new candidate for", + "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": "?._id", + "info": { + "full_name": ".name", + "first_name": ".name | $split(' ') | .[0]", + "last_name": ".name | $split(' ') | .[-1]", + "email": ".email_address", + "phone": ".phone_number", + "urls": "?.social_profiles || [] | $map({type: .type, url: .url})", + "summary": ".summary", + "location": { + "text": "?.address", + "lat": null, + "lng": null + } + }, + "created_at": "?.creation_date", + "updated_at": "?.updated_date", + "experiences": "?.work_history || [] | $map({company: ?.company_name, title: ?.title, description: ?.summary, date_start: ?.start_date.year != null and ?.start_date.month != null and ?.start_date.day != null ?? .start_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, date_end: ?.end_date.year != null and ?.end_date.month != null and ?.end_date.day != null ?? .end_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, location: {text: null, lat: null, lng: null}})", + "educations": "?.education || [] | $map({school: ?.school_name, title: $concat(?.degree || '', ' ', ?.field_of_study || '')| $strip, description: $concat(?.degree || '', ' ', ?.field_of_study || '', ' at ', ?.school_name || '')| $strip, date_start: ?.start_date.year != null and ?.start_date.month != null and ?.start_date.day != null ?? .start_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, date_end: ?.end_date.year != null and ?.end_date.month != null and ?.end_date.day != null ?? .end_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, location: {text: null, lat: null, lng: null}})", + "skills": [], + "tags": [ + { + "name": "breezy_hr_tags", + "value": "?.tags" + }, + { + "name": "headline", + "value": "?.headline" + }, + { + "name": "origin", + "value": "?.origin" + }, + { + "name": "source", + "value": "?.source?.name" + }, + { + "name": "sourced_by", + "value": "?.sourced_by" + }, + { + "name": "stage", + "value": "?.stage?.name" + }, + { + "name": "overall_score", + "value": "?.overall_score?.average_score" + } + ], + "resume": "?.resume" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import BreezyHR\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 BreezyHR.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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id',):\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 BreezyHR.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 BreezyHR\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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id',):\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 BreezyHR.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": { + "email": { + "description": "email", + "type": "string" + }, + "password": { + "description": "password", + "type": "string" + }, + "company_id": { + "description": "ID of company to pull jobs from in Breezy HR database associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company_name": { + "description": "[\u26a0\ufe0f Requiered if company_id is not specified], the company associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "email", + "password" + ], + "$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": "Breezy HR", + "origin_data_schema": { + "title": "BreezyProfileModel", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email_address": { + "type": "string" + }, + "phone_number": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "tags": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "origin": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "address": { + "type": "string" + }, + "work_history": { + "type": "array", + "items": { + "$ref": "#/$defs/WorkHistoryItem" + } + }, + "education": { + "type": "array", + "items": { + "$ref": "#/$defs/EducationItem" + } + }, + "social_profiles": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "custom_attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object" + } + }, + { + "type": "null" + } + ] + }, + "cover_letter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "name", + "email_address", + "phone_number", + "summary", + "tags", + "source", + "origin", + "address", + "work_history", + "education", + "social_profiles", + "custom_attributes", + "cover_letter" + ], + "$defs": { + "WorkHistoryItem": { + "title": "WorkHistoryItem", + "type": "object", + "properties": { + "company_name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "start_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "company_name", + "title", + "summary", + "start_month", + "start_year", + "end_month", + "end_year" + ] + }, + "EducationItem": { + "title": "EducationItem", + "type": "object", + "properties": { + "school_name": { + "type": "string" + }, + "field_of_study": { + "type": "string" + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "school_name", + "field_of_study", + "start_year", + "end_year" + ] + } + } + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadProfilesParameters", + "type": "object", + "properties": { + "position_id": { + "description": "Id of the position to create a new candidate for", + "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": "?._id", + "info": { + "full_name": ".name", + "first_name": ".name | $split(' ') | .[0]", + "last_name": ".name | $split(' ') | .[-1]", + "email": ".email_address", + "phone": ".phone_number", + "urls": "?.social_profiles || [] | $map({type: .type, url: .url})", + "summary": ".summary", + "location": { + "text": ".address", + "lat": null, + "lng": null + } + }, + "created_at": "?.creation_date", + "updated_at": "?.updated_date", + "experiences": "?.work_history || [] | $map({company: ?.company_name, title: ?.title, description: ?.summary, date_start: ?.start_date.year != null and ?.start_date.month != null and ?.start_date.day != null ?? .start_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, date_end: ?.end_date.year != null and ?.end_date.month != null and ?.end_date.day != null ?? .end_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, location: {text: null, lat: null, lng: null}})", + "educations": "?.education || [] | $map({school: ?.school_name, title: $concat(?.degree || '', ' ', ?.field_of_study || '')| $strip, description: $concat(?.degree || '', ' ', ?.field_of_study || '', ' at ', ?.school_name || '')| $strip, date_start: ?.start_date.year != null and ?.start_date.month != null and ?.start_date.day != null ?? .start_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, date_end: ?.end_date.year != null and ?.end_date.month != null and ?.end_date.day != null ?? .end_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, location: {text: null, lat: null, lng: null}})", + "skills": [], + "tags": [ + { + "name": "breezy_hr_tags", + "value": "?.tags" + }, + { + "name": "headline", + "value": "?.headline" + }, + { + "name": "origin", + "value": "?.origin" + }, + { + "name": "source", + "value": "?.source?.name" + }, + { + "name": "sourced_by", + "value": "?.sourced_by" + }, + { + "name": "stage", + "value": "?.stage?.name" + }, + { + "name": "overall_score", + "value": "?.overall_score?.average_score" + } + ], + "resume": "?.resume" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import BreezyHR\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 BreezyHR.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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id',):\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 BreezyHR.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 BreezyHR\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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id',):\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 BreezyHR.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": "create_profiles_in_breezyhr", + "data_type": "profile", + "direction": "outbound", + "mode": "create", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "email": { + "description": "email", + "type": "string" + }, + "password": { + "description": "password", + "type": "string" + }, + "company_id": { + "description": "ID of company to pull jobs from in Breezy HR database associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company_name": { + "description": "[\u26a0\ufe0f Requiered if company_id is not specified], the company associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "email", + "password" + ], + "$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": "Breezy HR", + "target_data_schema": { + "title": "BreezyProfileModel", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email_address": { + "type": "string" + }, + "phone_number": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "tags": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "origin": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "address": { + "type": "string" + }, + "work_history": { + "type": "array", + "items": { + "$ref": "#/$defs/WorkHistoryItem" + } + }, + "education": { + "type": "array", + "items": { + "$ref": "#/$defs/EducationItem" + } + }, + "social_profiles": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "custom_attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object" + } + }, + { + "type": "null" + } + ] + }, + "cover_letter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "name", + "email_address", + "phone_number", + "summary", + "tags", + "source", + "origin", + "address", + "work_history", + "education", + "social_profiles", + "custom_attributes", + "cover_letter" + ], + "$defs": { + "WorkHistoryItem": { + "title": "WorkHistoryItem", + "type": "object", + "properties": { + "company_name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "start_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "company_name", + "title", + "summary", + "start_month", + "start_year", + "end_month", + "end_year" + ] + }, + "EducationItem": { + "title": "EducationItem", + "type": "object", + "properties": { + "school_name": { + "type": "string" + }, + "field_of_study": { + "type": "string" + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "school_name", + "field_of_study", + "start_year", + "end_year" + ] + } + } + }, + "push_parameters": { + "title": "WriteProfilesParameters", + "type": "object", + "properties": { + "position_id": { + "description": "Id of the position to create a new candidate for", + "type": "string" + }, + "origin": { + "description": "will indicate in Breezy if the candidate should be marked as sourced or applied", + "$ref": "#/$defs/Origin", + "default": "sourced" + }, + "stage_actions_enabled": { + "description": "When origin is \"sourced\", should stage actions be executed (defaults to false). This is always true when origin is \"applied\"", + "type": "boolean", + "default": false + } + }, + "required": [ + "position_id" + ], + "$defs": { + "Origin": { + "title": "Origin", + "enum": [ + "applied", + "sourced" + ] + } + } + }, + "jsonmap": { + "name": "?.info?.full_name", + "email_address": "?.info?.email", + "phone_number": "?.info?.phone", + "address": "?.info?.location?.text", + "summary": "?.info?.summary", + "work_history": "?.experiences | $map({company_name: ?.company >> 'Undefined', title: ?.title, summary: ?.description, start_year: ?.date_start != null ?? .date_start | $slice(0, 3) | $int, start_month: ?.date_start != null ?? .date_start | $slice(4,7) | $int, end_year: ?.date_end != null ?? .date_end | $slice(0, 3) | $int, end_month: ?.date_end != null ?? .date_end | $slice(4,7) | $int})", + "education": "?.educations | $map({school_name: ?.school >> 'Undefined', field_of_study: ?.title, start_year: ?.date_start != null ?? .date_start | $slice(0, 3) | $int, end_year: ?.date_end != null ?? .date_end | $slice(0, 3) | $int})", + "social_profiles": ".info?.urls >> [] | $map({.type: .url | $sub('(^https?://)(.*)', 'https://$2')})", + "tags": "?.skills >> [] | $map(?.name)" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import BreezyHR\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 BreezyHR.create_profiles_in_breezyhr(\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 BreezyHR.create_profiles_in_breezyhr(\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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id', 'origin', 'stage_actions_enabled'):\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 BreezyHR.create_profiles_in_breezyhr(\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 BreezyHR\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 BreezyHR.create_profiles_in_breezyhr(\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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id', 'origin', 'stage_actions_enabled'):\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 BreezyHR.create_profiles_in_breezyhr(\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_breezyhr", + "data_type": "profile", + "direction": "outbound", + "mode": "update", + "connector_auth_parameters": { + "title": "AuthParameters", + "type": "object", + "properties": { + "email": { + "description": "email", + "type": "string" + }, + "password": { + "description": "password", + "type": "string" + }, + "company_id": { + "description": "ID of company to pull jobs from in Breezy HR database associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company_name": { + "description": "[\u26a0\ufe0f Requiered if company_id is not specified], the company associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "email", + "password" + ], + "$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": "Breezy HR", + "target_data_schema": { + "title": "BreezyProfileModel", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email_address": { + "type": "string" + }, + "phone_number": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "tags": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "origin": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "address": { + "type": "string" + }, + "work_history": { + "type": "array", + "items": { + "$ref": "#/$defs/WorkHistoryItem" + } + }, + "education": { + "type": "array", + "items": { + "$ref": "#/$defs/EducationItem" + } + }, + "social_profiles": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "custom_attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object" + } + }, + { + "type": "null" + } + ] + }, + "cover_letter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "name", + "email_address", + "phone_number", + "summary", + "tags", + "source", + "origin", + "address", + "work_history", + "education", + "social_profiles", + "custom_attributes", + "cover_letter" + ], + "$defs": { + "WorkHistoryItem": { + "title": "WorkHistoryItem", + "type": "object", + "properties": { + "company_name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "start_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "company_name", + "title", + "summary", + "start_month", + "start_year", + "end_month", + "end_year" + ] + }, + "EducationItem": { + "title": "EducationItem", + "type": "object", + "properties": { + "school_name": { + "type": "string" + }, + "field_of_study": { + "type": "string" + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "school_name", + "field_of_study", + "start_year", + "end_year" + ] + } + } + }, + "push_parameters": { + "title": "UpdateProfilesParameters", + "type": "object", + "properties": { + "position_id": { + "description": "Id of the position to create a new candidate for", + "type": "string" + } + }, + "required": [ + "position_id" + ], + "$defs": {} + }, + "jsonmap": { + "id": "?.reference", + "name": "?.info?.full_name", + "email_address": "?.info?.email", + "phone_number": "?.info?.phone", + "address": "?.info?.location?.text", + "summary": "?.info?.summary", + "work_history": "?.experiences | $map({company_name: ?.company >> 'Undefined', title: ?.title, summary: ?.description, start_year: ?.date_start != null ?? .date_start | $slice(0, 3) | $int, start_month: ?.date_start != null ?? .date_start | $slice(4,7) | $int, end_year: ?.date_end != null ?? .date_end | $slice(0, 3) | $int, end_month: ?.date_end != null ?? .date_end | $slice(4,7) | $int})", + "education": "?.educations | $map({school_name: ?.school >> 'Undefined', field_of_study: ?.title, start_year: ?.date_start != null ?? .date_start | $slice(0, 3) | $int, end_year: ?.date_end != null ?? .date_end | $slice(0, 3) | $int})", + "social_profiles": ".info?.urls >> [] | $map({.type: .url | $sub('(^https?://)(.*)', 'https://$2')})", + "tags": "?.skills >> [] | $map(?.name)" + }, + "workflow": { + "catch_template": "import typing as t\n\nfrom hrflow_connectors.v2 import BreezyHR\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 BreezyHR.update_profiles_in_breezyhr(\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 BreezyHR.update_profiles_in_breezyhr(\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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id',):\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 BreezyHR.update_profiles_in_breezyhr(\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 BreezyHR\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 BreezyHR.update_profiles_in_breezyhr(\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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id',):\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 BreezyHR.update_profiles_in_breezyhr(\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": { + "email": { + "description": "email", + "type": "string" + }, + "password": { + "description": "password", + "type": "string" + }, + "company_id": { + "description": "ID of company to pull jobs from in Breezy HR database associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "company_name": { + "description": "[\u26a0\ufe0f Requiered if company_id is not specified], the company associated with the authenticated user", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "email", + "password" + ], + "$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": "Breezy HR", + "origin_data_schema": { + "title": "BreezyProfileModel", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email_address": { + "type": "string" + }, + "phone_number": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "tags": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "origin": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "address": { + "type": "string" + }, + "work_history": { + "type": "array", + "items": { + "$ref": "#/$defs/WorkHistoryItem" + } + }, + "education": { + "type": "array", + "items": { + "$ref": "#/$defs/EducationItem" + } + }, + "social_profiles": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] + }, + "custom_attributes": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object" + } + }, + { + "type": "null" + } + ] + }, + "cover_letter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "name", + "email_address", + "phone_number", + "summary", + "tags", + "source", + "origin", + "address", + "work_history", + "education", + "social_profiles", + "custom_attributes", + "cover_letter" + ], + "$defs": { + "WorkHistoryItem": { + "title": "WorkHistoryItem", + "type": "object", + "properties": { + "company_name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "start_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_month": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "company_name", + "title", + "summary", + "start_month", + "start_year", + "end_month", + "end_year" + ] + }, + "EducationItem": { + "title": "EducationItem", + "type": "object", + "properties": { + "school_name": { + "type": "string" + }, + "field_of_study": { + "type": "string" + }, + "start_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "end_year": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "school_name", + "field_of_study", + "start_year", + "end_year" + ] + } + } + }, + "supports_incremental": false, + "pull_parameters": { + "title": "ReadProfilesParameters", + "type": "object", + "properties": { + "position_id": { + "description": "Id of the position to create a new candidate for", + "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 BreezyHR\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 BreezyHR.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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id',):\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 BreezyHR.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 BreezyHR\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 BreezyHR.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 ('email', 'password', 'company_id', 'company_name'):\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 ('position_id',):\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 BreezyHR.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" + } + } + } + ] } ] } \ No newline at end of file diff --git a/src/hrflow_connectors/v2/__init__.py b/src/hrflow_connectors/v2/__init__.py index 5b02fcd28..d89fa8830 100644 --- a/src/hrflow_connectors/v2/__init__.py +++ b/src/hrflow_connectors/v2/__init__.py @@ -1,5 +1,6 @@ from hrflow_connectors.v2.connectors.admen import Admen from hrflow_connectors.v2.connectors.adzuna import Adzuna +from hrflow_connectors.v2.connectors.breezyhr import BreezyHR from hrflow_connectors.v2.connectors.bullhorn import Bullhorn from hrflow_connectors.v2.connectors.flatchr import Flatchr from hrflow_connectors.v2.connectors.francetravail import FranceTravail @@ -24,4 +25,5 @@ Adzuna, FranceTravail, Flatchr, + BreezyHR, ] diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/README.md b/src/hrflow_connectors/v2/connectors/breezyhr/README.md new file mode 100644 index 000000000..dd1a4c0e4 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/README.md @@ -0,0 +1,92 @@ +# 📖 Summary +- [📖 Summary](#📖-summary) +- [💼 About Breezy hr](#💼-about-breezy-hr) + - [😍 Why is it a big deal for Breezy hr customers & partners?](#😍-why-is-it-a-big-deal-for-breezy-hr-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 Breezy hr + +> Breezyhr is an end-to-end recruiting software to help you attract & hire great employees with less effort + + +

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

+ +

+ +## 🧠 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 Breezy hr**) + + +# 🔌 Connector Actions +

+ +| Action | Description | +| ------- | ----------- | +| [**Create jobs in hrflow**](docs/create_jobs_in_hrflow.md) | Send **created** 'job(s)' _from_ _to_ HrFlow | +| [**Update jobs in hrflow**](docs/update_jobs_in_hrflow.md) | Send **updated** 'job(s)' _from_ _to_ HrFlow | +| [**Archive jobs in hrflow**](docs/archive_jobs_in_hrflow.md) | Send **archived** 'job(s)' _from_ _to_ HrFlow | +| [**Create profiles in hrflow**](docs/create_profiles_in_hrflow.md) | Send **created** 'profile(s)' _from_ _to_ HrFlow | +| [**Update profiles in hrflow**](docs/update_profiles_in_hrflow.md) | Send **updated** 'profile(s)' _from_ _to_ HrFlow | +| [**Create profiles in **](docs/create_profiles_in_.md) | Send **created** 'profile(s)' _from_ HrFlow _to_ | +| [**Update profiles in **](docs/update_profiles_in_.md) | Send **updated** 'profile(s)' _from_ HrFlow _to_ | +| [**Archive profiles in hrflow**](docs/archive_profiles_in_hrflow.md) | Send **archived** 'profile(s)' _from_ _to_ HrFlow | + + +

+ + +# 💍 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 [Breezy HR](https://breezy.hr/) to learn more. +- ⚙️ API documentation : (https://developer.breezy.hr/reference/overview) +- 💻 [Connector code](https://github.com/Riminder/hrflow-connectors/tree/master/src/hrflow_connectors/v2/connectors/breezyhr) on our Github. + + +# 👏 Special Thanks +- 💻 HrFlow.ai : [Limam VADHEL](https://github.com/limamvadhel) - Software Engineer +- 💻 HrFlow.ai : [Leo FERRETTI](https://github.com/Sprenger07) - Software Engineer +- 💻 HrFlow.ai :[Corentin DUCHENE](https://github.com/CorentinDuchene) - Software Engineer +- 💻 HrFlow.ai : [Nedhir Ebnou](https://github.com/nedhirouebnou) - Software Engineer +- 🤝 BreezyHR :[Breezy HR for the partnership and accessible documentation](https://breezy.hr/) + diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/__init__.py b/src/hrflow_connectors/v2/connectors/breezyhr/__init__.py new file mode 100644 index 000000000..1528fac9d --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/__init__.py @@ -0,0 +1 @@ +from hrflow_connectors.v2.connectors.breezyhr.connector import BreezyHR # noqa diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/aisles.py b/src/hrflow_connectors/v2/connectors/breezyhr/aisles.py new file mode 100644 index 000000000..1eb9d6441 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/aisles.py @@ -0,0 +1,644 @@ +import json +import typing as t +from datetime import datetime, timedelta +from enum import Enum +from io import BytesIO +from logging import LoggerAdapter + +import requests +from msgspec import Meta, Struct +from typing_extensions import Annotated + +from hrflow_connectors.v2.connectors.breezyhr.schemas import ( + BreezyJobModel, + BreezyProfileModel, +) +from hrflow_connectors.v2.core.common import Entity, Mode +from hrflow_connectors.v2.core.warehouse import ( + Aisle, + Criterias, + ReadOperation, + WriteOperation, + merge, +) + +BREEZY_BASE_URL = "https://api.breezy.hr/v3" + + +class State(str, Enum): + draft = "draft" + archived = "archived" + published = "published" + closed = "closed" + pending = "pending" + + +class Origin(str, Enum): + sourced = "sourced" + applied = "applied" + + +class AuthParameters(Struct): + email: Annotated[ + str, + Meta( + description="email", + ), + ] + password: Annotated[str, Meta(description="password")] + company_id: Annotated[ + t.Optional[str], + Meta( + description=( + "ID of company to pull jobs from in Breezy HR database associated with" + " the authenticated user" + ), + ), + ] = None + company_name: Annotated[ + t.Optional[str], + Meta( + description=( + "[⚠️ Requiered if company_id is not specified], the company associated" + " with the authenticated user" + ), + ), + ] = None + + +class ReadJobsParameters(Struct): + state: Annotated[ + State, + Meta( + description=( + "Specify an optional position state filter. e.g. draft, archived," + " published, closed, pending\nDefaults to published" + ), + ), + ] = State.published + + +class WriteProfilesParameters(Struct): + position_id: Annotated[ + str, + Meta( + description="Id of the position to create a new candidate for", + ), + ] + origin: Annotated[ + Origin, + Meta( + description=( + "will indicate in Breezy if the candidate should be marked as sourced" + " or applied" + ), + ), + ] = Origin.sourced + stage_actions_enabled: Annotated[ + bool, + Meta( + description=( + 'When origin is "sourced", should stage actions be executed (defaults' + ' to false). This is always true when origin is "applied"' + ), + ), + ] = False + + +class UpdateProfilesParameters(Struct): + position_id: Annotated[ + str, + Meta( + description="Id of the position to create a new candidate for", + ), + ] + + +class ReadProfilesParameters(Struct): + position_id: Annotated[ + t.Optional[str], + Meta( + description="Id of the position to create a new candidate for", + ), + ] = None + + +def get_access_token( + adapter: LoggerAdapter, + auth_parameters: AuthParameters, +): + sign_in_url = f"{BREEZY_BASE_URL}/signin" + + response = requests.post( + sign_in_url, + json={"email": auth_parameters.email, "password": auth_parameters.password}, + ) + + if not response.ok: + adapter.error(f"failed to retrieve access token, reason: {response.text}") + raise Exception("failed to retrieve access token") + + return response.json().get("access_token") + + +def revoke_access_token(access_token): + sign_out_url = f"{BREEZY_BASE_URL}/signout" + + headers = {"Authorization": f"{access_token}"} + + requests.get(sign_out_url, headers=headers) + + +def generic_jobs_read( + mode: Mode, +): + def read_jobs( + adapter: LoggerAdapter, + auth_parameters: AuthParameters, + parameters: ReadJobsParameters, + incremental: bool, + incremental_token: t.Optional[str], + ) -> t.Iterable[t.Dict]: + access_token = get_access_token(adapter, auth_parameters) + headers = {"Authorization": access_token} + + company_id = auth_parameters.company_id + if company_id is None: + companies_url = f"{BREEZY_BASE_URL}/companies" + + companies_response = requests.get(companies_url, headers=headers) + + if not companies_response.ok: + adapter.error( + f"Failed to retrieve company id, reason: {companies_response.text}" + ) + raise Exception("Failed to retrieve company id") + + company_list = companies_response.json() + for company in company_list: + if company["name"] == auth_parameters.company_name: + company_id = company["_id"] + break + if company_id is None: + adapter.error( + "Failed to retrieve company id, reason: company does not match with" + " an id" + ) + raise Exception("Failed to retrieve company id") + + url = f"{BREEZY_BASE_URL}/company/{company_id}/positions" + params = {"state": parameters.state} + + response = requests.get(url, headers=headers, params=params) + if not response.ok: + adapter.error(f"Failed to read jobs, reason: {response.text}") + raise Exception("Failed to read jobs") + + for job in response.json(): + if mode == Mode.create and not is_within_five_minutes( + job["creation_date"], job["updated_date"] + ): + continue + if mode == Mode.update and is_within_five_minutes( + job["creation_date"], job["updated_date"] + ): + continue + yield job + + revoke_access_token(access_token) + + return read_jobs + + +def send_profile( + adapter: LoggerAdapter, + parameters: WriteProfilesParameters, + profiles: t.Iterable[t.Dict], + access_token: str, + company_id: str, + candidate_id: str = "", +): + base_url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/" + f"position/{parameters.position_id}/candidate" + ) + + payload = json.dumps(profiles) + + headers = {"Content-Type": "application/json", "Authorization": f"{access_token}"} + + if candidate_id == "": + url = f"{base_url}s/" + + # If the candidate doesn't already exist we "POST" his profile + response = requests.post(url, headers=headers, data=payload) + + else: + # In case the candidate exists, + # we retrieve his id to update his profile with a "PUT" request + + url = f"{base_url}/{candidate_id}" + + url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/" + f"position/{parameters.position_id}/candidate/{candidate_id}" + ) + + adapter.info(f"Updating id = {candidate_id} profile") + response = requests.put(url, headers=headers, data=payload) + return response + + +def write_profiles( + adapter: LoggerAdapter, + auth_parameters: AuthParameters, + parameters: WriteProfilesParameters, + items: t.Iterable[t.Dict], +) -> t.List[t.Dict]: + failed_profiles = [] + access_token = get_access_token(adapter, auth_parameters) + headers = {"Authorization": access_token} + + company_id = auth_parameters.company_id + + if company_id is None: + companies_url = f"{BREEZY_BASE_URL}/companies" + + companies_response = requests.get(companies_url, headers=headers) + + if not companies_response.ok: + adapter.error( + f"Failed to retrieve company id, reason: {companies_response.text}" + ) + raise Exception("Failed to retrieve company id") + + company_list = companies_response.json() + for company in company_list: + if company["name"] == auth_parameters.company_name: + company_id = company["_id"] + break + if company_id is None: + adapter.error( + "Failed to retrieve company id, reason: company does not match with" + " an id" + ) + raise Exception("Failed to retrieve company id") + + post_candidate_url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/position/" + f"{parameters.position_id}/candidates" + ) + + for profile in items: + resume_url = profile.pop("resume", None) + profile.update({"origin": parameters.origin}) + if parameters.stage_actions_enabled: + params = {"stage_actions_enabled": parameters.stage_actions_enabled} + else: + params = {} + + post_candidate_response = requests.post( + post_candidate_url, headers=headers, json=profile, params=params + ) + if not post_candidate_response.ok: + adapter.error( + f"Couldn't create candidate, reason: {post_candidate_response.text}" + ) + failed_profiles.append(profile) + continue + + if resume_url: + candidate_id = post_candidate_response.json()["_id"] + resume_file_response = requests.get(url=resume_url) + resume_file_obj = BytesIO(resume_file_response.content) + files = { + "file": ( + "resume.pdf", + resume_file_obj, + "application/pdf", + ) + } + post_resume_url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/position/" + f"{parameters.position_id}/candidate/{candidate_id}/resume" + ) + post_resume_response = requests.post( + post_resume_url, headers=headers, files=files + ) + if not post_resume_response.ok: + adapter.error( + "Failed to attach resume to candidate, reason:" + f" {post_resume_response.text}" + ) + + revoke_access_token(access_token) + return failed_profiles + + +def update_profiles( + adapter: LoggerAdapter, + auth_parameters: AuthParameters, + parameters: UpdateProfilesParameters, + items: t.Iterable[t.Dict], +) -> t.List[t.Dict]: + failed_profiles = [] + access_token = get_access_token(adapter, auth_parameters) + headers = {"Authorization": access_token} + + company_id = auth_parameters.company_id + if company_id is None: + companies_url = f"{BREEZY_BASE_URL}/companies" + + companies_response = requests.get(companies_url, headers=headers) + + if not companies_response.ok: + adapter.error( + f"Failed to retrieve company id, reason: {companies_response.text}" + ) + raise Exception("Failed to retrieve company id") + + company_list = companies_response.json() + for company in company_list: + if company["name"] == auth_parameters.company_name: + company_id = company["_id"] + break + if company_id is None: + adapter.error( + "Failed to retrieve company id, reason: company does not match with" + " an id" + ) + raise Exception("Failed to retrieve company id") + + base_url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/position/" + f"{parameters.position_id}/candidate" + ) + + for profile in items: + candidate_id = profile.pop("id") + candidate_work_history = profile.pop("work_history", []) + candidate_education = profile.pop("education", []) + put_candidate_url = f"{base_url}/{candidate_id}" + put_candidate_response = requests.put( + put_candidate_url, headers=headers, json=profile + ) + if not put_candidate_response.ok: + adapter.error( + f"Couldn't create candidate, reason: {put_candidate_response.text}" + ) + failed_profiles.append(profile) + continue + + current_educations = [ + {education["school_name"], education["field_of_study"]} + for education in put_candidate_response.json().get("education", []) + ] + current_work_history = [ + {work_history["company_name"], work_history["title"]} + for work_history in put_candidate_response.json().get("work_history", []) + ] + + for education in candidate_education: + if { + education["school_name"], + education["field_of_study"], + } in current_educations: + continue + education_url = f"{put_candidate_url}/education" + education_response = requests.put( + education_url, headers=headers, json=education + ) + if not education_response.ok: + adapter.error( + f"Couldn't update education, for candidate {candidate_id}, reason:" + f" {education_response.text}" + ) + for work_history in candidate_work_history: + if { + work_history["company_name"], + work_history["title"], + } in current_work_history: + continue + work_history_url = f"{put_candidate_url}/work-history" + work_history_response = requests.put( + work_history_url, headers=headers, json=work_history + ) + if not work_history_response.ok: + adapter.error( + f"Couldn't update experience, for candidate {candidate_id}, reason:" + f" {work_history_response.text}" + ) + + revoke_access_token(access_token) + return failed_profiles + + +def generic_profiles_read( + mode: Mode, +): + def read_profiles( + adapter: LoggerAdapter, + auth_parameters: AuthParameters, + parameters: ReadProfilesParameters, + incremental: bool, + incremental_token: t.Optional[str], + ) -> t.Iterable[t.Dict]: + # TODO: add incremental read_mode using page_size, and page as read_from + access_token = get_access_token(adapter, auth_parameters) + headers = {"Authorization": access_token} + + company_id = auth_parameters.company_id + if company_id is None: + companies_url = f"{BREEZY_BASE_URL}/companies" + + companies_response = requests.get(companies_url, headers=headers) + + if not companies_response.ok: + adapter.error( + f"Failed to retrieve company id, reason: {companies_response.text}" + ) + raise Exception("Failed to retrieve company id") + + company_list = companies_response.json() + for company in company_list: + if company["name"] == auth_parameters.company_name: + company_id = company["_id"] + break + if company_id is None: + adapter.error( + "Failed to retrieve company id, reason: company does not match with" + " an id" + ) + raise Exception("Failed to retrieve company id") + if not parameters.position_id: + # retrieve all postion ids for all published positions + positions_url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/positions?state=published" + ) + + positions_response = requests.get(positions_url, headers=headers) + if len(positions_response.json()) == 0: + adapter.info("No published position found") + for position in positions_response.json(): + position_id = position["_id"] + candidates_url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/position/" + f"{position_id}/candidates?sort=updated" + ) + candidates_response = requests.get(candidates_url, headers=headers) + if not candidates_response.ok: + adapter.error( + "Failed to retrieve candidates, reason:" + f" {candidates_response.text}" + ) + raise Exception("Failed to retrieve candidates") + candidates = candidates_response.json() + for candidate in candidates: + if mode == Mode.create and not is_within_five_minutes( + candidate["creation_date"], candidate["updated_date"] + ): + continue + if mode == Mode.update and is_within_five_minutes( + candidate["creation_date"], candidate["updated_date"] + ): + continue + candidate_id = candidate["_id"] + full_candidate_url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/position/" + f"{position_id}/candidate/{candidate_id}" + ) + full_candidate_response = requests.get( + full_candidate_url, headers=headers + ) + if not full_candidate_response.ok: + adapter.error( + "Failed to retrieve candidate, reason:" + f" {full_candidate_response.text}" + ) + continue + + full_candidate = full_candidate_response.json() + + resume_url = full_candidate.get("resume", {}).get("url") + if not resume_url: + full_candidate["resume"] = None + if resume_url: + resume_response = requests.get(resume_url, headers=headers) + if not resume_response.ok: + adapter.error( + "Failed to retrieve resume, reason:" + f" {resume_response.text}" + ) + full_candidate["resume"] = None + else: + full_candidate["resume"] = dict(raw=resume_response.content) + + yield full_candidate + else: + candidates_url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/position/" + f"{parameters.position_id}/candidates?sort=updated" + ) + + candidates_response = requests.get(candidates_url, headers=headers) + if not candidates_response.ok: + adapter.error( + f"Failed to retrieve candidates, reason: {candidates_response.text}" + ) + raise Exception("Failed to retrieve candidates") + candidates = candidates_response.json() + for candidate in candidates: + if mode == Mode.create and not is_within_five_minutes( + candidate["creation_date"], candidate["updated_date"] + ): + continue + if mode == Mode.update and is_within_five_minutes( + candidate["creation_date"], candidate["updated_date"] + ): + continue + candidate_id = candidate["_id"] + full_candidate_url = ( + f"{BREEZY_BASE_URL}/company/{company_id}/position/" + f"{parameters.position_id}/candidate/{candidate_id}" + ) + full_candidate_response = requests.get( + full_candidate_url, headers=headers + ) + if not full_candidate_response.ok: + adapter.error( + "Failed to retrieve candidate, reason:" + f" {full_candidate_response.text}" + ) + continue + + full_candidate = full_candidate_response.json() + + resume_url = full_candidate.get("resume", {}).get("url") + if not resume_url: + full_candidate["resume"] = None + if resume_url: + resume_response = requests.get(resume_url, headers=headers) + if not resume_response.ok: + adapter.error( + f"Failed to retrieve resume, reason: {resume_response.text}" + ) + full_candidate["resume"] = None + else: + full_candidate["resume"] = dict(raw=resume_response.content) + + yield full_candidate + revoke_access_token(access_token) + + return read_profiles + + +# To account for the time differnece between the start of object creation on the platform +# and its completion +def is_within_five_minutes(date_str1: str, date_str2: str) -> bool: + date1 = datetime.fromisoformat(date_str1.replace("Z", "+00:00")) + date2 = datetime.fromisoformat(date_str2.replace("Z", "+00:00")) + + difference = abs(date1 - date2) + + return difference <= timedelta(minutes=5) + + +JobsAisle = Aisle( + name=Entity.job, + schema=BreezyJobModel, + read=ReadOperation( + criterias=Criterias( + create=ReadJobsParameters, + update=ReadJobsParameters, + archive=ReadJobsParameters, + ), + function=merge( + create=generic_jobs_read(Mode.create), + update=generic_jobs_read(Mode.update), + archive=generic_jobs_read(Mode.archive), + ), + ), +) + +ProfilesAisle = Aisle( + name=Entity.profile, + schema=BreezyProfileModel, + read=ReadOperation( + criterias=Criterias( + create=ReadProfilesParameters, + update=ReadProfilesParameters, + archive=ReadProfilesParameters, + ), + function=merge( + create=generic_profiles_read(Mode.create), + update=generic_profiles_read(Mode.update), + archive=generic_profiles_read(Mode.archive), + ), + ), + write=WriteOperation( + criterias=Criterias( + create=WriteProfilesParameters, update=UpdateProfilesParameters + ), + function=merge(create=write_profiles, update=update_profiles), + ), +) diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/connector.py b/src/hrflow_connectors/v2/connectors/breezyhr/connector.py new file mode 100644 index 000000000..6155281e5 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/connector.py @@ -0,0 +1,327 @@ +import typing as t + +from hrflow_connectors.v2.connectors.breezyhr.utils import ( + is_valid_url, + remove_html_tags, +) +from hrflow_connectors.v2.connectors.breezyhr.warehouse import BreezyHrWarehouse +from hrflow_connectors.v2.core.common import Direction, Entity, Mode +from hrflow_connectors.v2.core.connector import Connector, ConnectorType, Flow + + +def get_location(location: t.Dict) -> t.Dict: + country = location.get("country", {}).get("name") + city = location.get("city") + address = location.get("name") + street_address = location.get("streetAddress", {}).get("custom") + geojson = dict(country=country, city=city, text=street_address or address) + + return dict(text=street_address or address, geojson=geojson, lat=None, lng=None) + + +def format_job(breezy_job: t.Dict) -> t.Dict: + """ + Format a Breezy Hr job object into a hrflow job object + Returns: + HrflowJob: a job object in the hrflow job format + """ + location = get_location(breezy_job.get("location", {})) + is_remote = breezy_job.get("location", {}).get("is_remote") + remote_details = breezy_job.get("location", {}).get("remote_details") + description = remove_html_tags(breezy_job.get("description", "")) + cleaned_description = description.replace(" ", " ") + + sections = [ + dict( + name="description", + title="Description", + description=cleaned_description, + ), + dict( + name="experience", + title="Required Experience", + description=breezy_job.get("experience", {}).get("name"), + ), + dict( + name="education", + title="Required Education", + description=breezy_job.get("education"), + ), + dict( + name="category", + title="Category", + description=breezy_job.get("category", {}).get("name"), + ), + dict( + name="remote", + title="Remote Information", + description=remote_details, + ), + ] + t = lambda name, value: dict(name=name, value=value) + tags = [ + t("type", breezy_job.get("type", {}).get("name")), + t("experience", breezy_job.get("experience", {}).get("name")), + t("education", breezy_job.get("education")), + t("department", breezy_job.get("department")), + t("requisition_id", breezy_job.get("requisition_id")), + t("category", breezy_job.get("category", {}).get("name")), + t("candidate_type", breezy_job.get("candidate_type")), + t("isremote", is_remote), + t("remote_details", remote_details), + t("creator_id", breezy_job.get("creator_id")), + t("breezy_hr_tags", breezy_job.get("tags")), + ] + + hrflow_job = dict( + name=breezy_job.get("name"), + reference=breezy_job.get("_id"), + summary=cleaned_description, + location=location, + sections=sections, + tags=tags, + created_at=breezy_job.get("creation_date"), + updated_at=breezy_job.get("updated_date"), + ) + + return hrflow_job + + +def format_archive_in_hrflow(breezy_element: t.Dict) -> t.Dict: + return dict(reference=breezy_element.get("_id")) + + +def format_profile(hrflow_profile: t.Dict) -> t.Dict: + """ + Format a Hrflow profile object into a breezy hr profile object + Args: + data (HrflowProfile): Hrflow Profile to format + Returns: + BreezyProfileModel: a BreezyHr formatted profile object + """ + + info = hrflow_profile.get("info", {}) + + work_history = [] + for experience in hrflow_profile.get("experiences", []): + formatted_experience = dict() + if experience.get("company") not in ["", None]: + formatted_experience["company_name"] = experience.get("company") + else: + formatted_experience["company_name"] = "Undefined" + formatted_experience["title"] = experience.get("title") + formatted_experience["summary"] = experience.get("description") + if experience.get("date_start") is not None: + date_start = experience["date_start"] + formatted_experience["start_year"] = int(date_start[:4]) + formatted_experience["start_month"] = int(date_start[5:7]) + if experience.get("date_end") is not None: + date_end = experience["date_end"] + formatted_experience["end_year"] = int(date_end[:4]) + formatted_experience["end_month"] = int(date_end[5:7]) + work_history.append(formatted_experience) + + educations = [] + for education in hrflow_profile.get("educations", []): + formatted_education = dict() + if education.get("school") == "": + education["school"] = "Undefined" + formatted_education["school_name"] = education.get("school") + formatted_education["field_of_study"] = education.get("title") + if education.get("date_start") is not None: + date_start = education["date_start"] + formatted_education["start_year"] = int(date_start[:4]) + if education.get("date_end") is not None: + date_end = education["date_end"] + formatted_education["end_year"] = int(date_end[:4]) + educations.append(formatted_education) + + social_profiles = {} + if info.get("urls"): + for url in info.get("urls"): + type = url.get("type") + link = url.get("url") + if type and link: + if type == "from_resume" or not is_valid_url(link): + continue + social_profiles.update({type: link}) + + # add profile skills to tags + tags = [] + skills = hrflow_profile.get("skills") + if skills: + tags = [skill.get("name") for skill in skills] + + # add resume to profile + attachments = hrflow_profile.get("attachments", []) + resume_url = next( + ( + attachment + for attachment in attachments + if attachment.get("type") == "resume" + ), + {}, + ).get("public_url") + breezy_profile = dict( + name=info.get("full_name"), + email_address=info.get("email"), + phone_number=info.get("phone"), + address=info.get("location", {}).get("text"), + summary=info.get("summary"), + work_history=work_history, + education=educations, + social_profiles=social_profiles, + tags=tags, + resume=resume_url, + ) + return breezy_profile + + +def format_profile_for_update(hrflow_profile: t.Dict) -> t.Dict: + breezy_profile = format_profile(hrflow_profile) + breezy_profile["id"] = hrflow_profile.get("reference") + return breezy_profile + + +def format_date_to_iso(date): + year = date.get("year") + month = date.get("month") + day = date.get("day") + # Check if the date is complete, i.e., year, month, and day are all present + if year is not None and month is not None and day is not None: + return f"{year:04d}-{month:02d}-{day:02d}" + elif year is not None and month is not None: + return f"{year:04d}-{month:02d}" + elif year is not None: + return f"{year:04d}" + else: + return None + + +def format_candidate(breezy_profile: t.Dict) -> t.Dict: + """ + Format a Breezy profile object into a Hrflow profile object + Args: + data (BreezyProfileModel): Breezy Profile to format + Returns: + HrFlowProfile: a Hrflow formatted profile object + """ + info = dict( + full_name=breezy_profile["name"], + first_name=breezy_profile["name"].split(" ")[0], + last_name=breezy_profile["name"].split(" ")[-1], + email=breezy_profile["email_address"], + phone=breezy_profile["phone_number"], + urls=[ + dict(type=social_profile["type"], url=social_profile["url"]) + for social_profile in breezy_profile.get("social_profiles", []) + ], + summary=breezy_profile["summary"], + location={"text": breezy_profile.get("address", ""), "lat": None, "lng": None}, + ) + + educations = [] + for education in breezy_profile.get("education", []): + formatted_education = dict() + formatted_education["school"] = education.get("school_name") + degree = education.get("degree") + field_of_study = education.get("field_of_study") + if degree or field_of_study: + formatted_education["title"] = ( + (degree if degree else "") + + " " + + (field_of_study if field_of_study else "") + ).strip() + formatted_education["description"] = ( + formatted_education["title"] + " at " + formatted_education["school"] + ) + formatted_education["date_start"] = None + formatted_education["date_end"] = None + if education.get("start_date") is not None: + formatted_education["date_start"] = format_date_to_iso( + education["start_date"] + ) + if education.get("end_date") is not None: + formatted_education["date_end"] = format_date_to_iso(education["end_date"]) + formatted_education["location"] = {"text": None, "lat": None, "lng": None} + educations.append(formatted_education) + + experiences = [] + for experience in breezy_profile.get("work_history", []): + formatted_experience = dict() + formatted_experience["company"] = experience.get("company_name") + + formatted_experience["title"] = experience.get("title") + formatted_experience["description"] = experience.get("summary") + formatted_experience["date_start"] = None + formatted_experience["date_end"] = None + if experience.get("start_date") is not None: + formatted_experience["date_start"] = format_date_to_iso( + experience["start_date"] + ) + if experience.get("end_date") is not None: + formatted_experience["date_end"] = format_date_to_iso( + experience["end_date"] + ) + formatted_experience["location"] = {"text": None, "lat": None, "lng": None} + experiences.append(formatted_experience) + + tags = [] + t = lambda name, value: dict(name=name, value=value) + tags.append(t("breezy_hr_tags", breezy_profile.get("tags"))) + tags.append(t("headline", breezy_profile.get("headline"))) + tags.append(t("origin", breezy_profile.get("origin"))) + tags.append(t("source", breezy_profile.get("source", {}).get("name"))) + tags.append(t("sourced_by", breezy_profile.get("sourced_by"))) + tags.append(t("stage", breezy_profile.get("stage", {}).get("name"))) + tags.append( + t("overall_score", breezy_profile.get("overall_score", {}).get("average_score")) + ) + hrflow_profile = dict( + reference=breezy_profile.get("_id"), + info=info, + created_at=breezy_profile.get("creation_date"), + updated_at=breezy_profile.get("updated_date"), + experiences=experiences, + educations=educations, + skills=[], + tags=tags, + resume=breezy_profile.get("resume"), + ) + + return hrflow_profile + + +BreezyHR = Connector( + name="Breezy HR", + type=ConnectorType.ATS, + subtype="breezyhr", + description=( + "Breezyhr is an end-to-end recruiting software " + "to help you attract & hire great employees with less effort" + ), + url="https://breezy.hr/", + warehouse=BreezyHrWarehouse, + flows=( + Flow(Mode.create, Entity.job, Direction.inbound, format=format_job), + Flow(Mode.update, Entity.job, Direction.inbound, format=format_job), + Flow( + Mode.archive, Entity.job, Direction.inbound, format=format_archive_in_hrflow + ), + Flow(Mode.create, Entity.profile, Direction.inbound, format=format_candidate), + Flow(Mode.update, Entity.profile, Direction.inbound, format=format_candidate), + Flow(Mode.create, Entity.profile, Direction.outbound, format=format_profile), + Flow( + Mode.update, + Entity.profile, + Direction.outbound, + format=format_profile_for_update, + ), + Flow( + Mode.archive, + Entity.profile, + Direction.inbound, + format=format_archive_in_hrflow, + ), + ), +) diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/connector.pyi b/src/hrflow_connectors/v2/connectors/breezyhr/connector.pyi new file mode 100644 index 000000000..23a8d9e69 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/connector.pyi @@ -0,0 +1,14 @@ +# This file is generated automatically +from hrflow_connectors.v2.core.connector import Connector, PublicActionInterface + +class BreezyHRProto(Connector): + create_jobs_in_hrflow: PublicActionInterface + update_jobs_in_hrflow: PublicActionInterface + archive_jobs_in_hrflow: PublicActionInterface + create_profiles_in_hrflow: PublicActionInterface + update_profiles_in_hrflow: PublicActionInterface + create_profiles_in_breezyhr: PublicActionInterface + update_profiles_in_breezyhr: PublicActionInterface + archive_profiles_in_hrflow: PublicActionInterface + +BreezyHR: BreezyHRProto \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/docs/archive_jobs_in_hrflow.md b/src/hrflow_connectors/v2/connectors/breezyhr/docs/archive_jobs_in_hrflow.md new file mode 100644 index 000000000..77401bdff --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/docs/archive_jobs_in_hrflow.md @@ -0,0 +1,84 @@ +# Archive jobs in hrflow +`Breezy HR` :arrow_right: `HrFlow` + +Send **archived** 'job(s)' _from_ Breezy HR _to_ HrFlow + + + +## Breezy HR Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `email` :red_circle: | `string` | None | email | +| `password` :red_circle: | `string` | None | password | +| `company_id` | `string\|null` | None | ID of company to pull jobs from in Breezy HR database associated with the authenticated user | +| `company_name` | `string\|null` | None | [⚠️ Requiered if company_id is not specified], the company associated with the authenticated user | + +## 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 (Breezy HR) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `state` | `Literal['archived','closed','draft','pending','published']` | published | Specify an optional position state filter. e.g. draft, archived, published, closed, pending +Defaults to published | + +## 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 BreezyHR + + +logging.basicConfig(level=logging.INFO) + + +BreezyHR.archive_jobs_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + email=..., + password=..., + company_id=..., + company_name=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + state=..., + ), + push_parameters=dict( + board_key=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/docs/archive_profiles_in_hrflow.md b/src/hrflow_connectors/v2/connectors/breezyhr/docs/archive_profiles_in_hrflow.md new file mode 100644 index 000000000..d9b30619d --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/docs/archive_profiles_in_hrflow.md @@ -0,0 +1,83 @@ +# Archive profiles in hrflow +`Breezy HR` :arrow_right: `HrFlow` + +Send **archived** 'profile(s)' _from_ Breezy HR _to_ HrFlow + + + +## Breezy HR Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `email` :red_circle: | `string` | None | email | +| `password` :red_circle: | `string` | None | password | +| `company_id` | `string\|null` | None | ID of company to pull jobs from in Breezy HR database associated with the authenticated user | +| `company_name` | `string\|null` | None | [⚠️ Requiered if company_id is not specified], the company associated with the authenticated user | + +## 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 (Breezy HR) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `position_id` | `string\|null` | None | Id of the position to create a new candidate for | + +## 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 BreezyHR + + +logging.basicConfig(level=logging.INFO) + + +BreezyHR.archive_profiles_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + email=..., + password=..., + company_id=..., + company_name=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + position_id=..., + ), + push_parameters=dict( + source_key=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/docs/create_jobs_in_hrflow.md b/src/hrflow_connectors/v2/connectors/breezyhr/docs/create_jobs_in_hrflow.md new file mode 100644 index 000000000..7dfb6884e --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/docs/create_jobs_in_hrflow.md @@ -0,0 +1,86 @@ +# Create jobs in hrflow +`Breezy HR` :arrow_right: `HrFlow` + +Send **created** 'job(s)' _from_ Breezy HR _to_ HrFlow + + + +## Breezy HR Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `email` :red_circle: | `string` | None | email | +| `password` :red_circle: | `string` | None | password | +| `company_id` | `string\|null` | None | ID of company to pull jobs from in Breezy HR database associated with the authenticated user | +| `company_name` | `string\|null` | None | [⚠️ Requiered if company_id is not specified], the company associated with the authenticated user | + +## 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 (Breezy HR) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `state` | `Literal['archived','closed','draft','pending','published']` | published | Specify an optional position state filter. e.g. draft, archived, published, closed, pending +Defaults to published | + +## 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 BreezyHR + + +logging.basicConfig(level=logging.INFO) + + +BreezyHR.create_jobs_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + email=..., + password=..., + company_id=..., + company_name=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + state=..., + ), + 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/breezyhr/docs/create_profiles_in_breezyhr.md b/src/hrflow_connectors/v2/connectors/breezyhr/docs/create_profiles_in_breezyhr.md new file mode 100644 index 000000000..41e53f4f1 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/docs/create_profiles_in_breezyhr.md @@ -0,0 +1,89 @@ +# Create profiles in breezyhr +`HrFlow` :arrow_right: `Breezy HR` + +Send **created** 'profile(s)' _from_ HrFlow _to_ Breezy HR + + + +## Breezy HR Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `email` :red_circle: | `string` | None | email | +| `password` :red_circle: | `string` | None | password | +| `company_id` | `string\|null` | None | ID of company to pull jobs from in Breezy HR database associated with the authenticated user | +| `company_name` | `string\|null` | None | [⚠️ Requiered if company_id is not specified], the company associated with the authenticated user | + +## 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 (Breezy HR) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `position_id` :red_circle: | `string` | None | Id of the position to create a new candidate for | +| `origin` | `Literal['applied','sourced']` | sourced | will indicate in Breezy if the candidate should be marked as sourced or applied | +| `stage_actions_enabled` | `boolean` | False | When origin is "sourced", should stage actions be executed (defaults to false). This is always true when origin is "applied" | + +## 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 BreezyHR + + +logging.basicConfig(level=logging.INFO) + + +BreezyHR.create_profiles_in_breezyhr( + workflow_id=..., + logics=..., + connector_auth=dict( + email=..., + password=..., + company_id=..., + company_name=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + source_key=..., + profile_key=..., + ), + push_parameters=dict( + position_id=..., + origin=..., + stage_actions_enabled=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/docs/create_profiles_in_hrflow.md b/src/hrflow_connectors/v2/connectors/breezyhr/docs/create_profiles_in_hrflow.md new file mode 100644 index 000000000..3d2ffb187 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/docs/create_profiles_in_hrflow.md @@ -0,0 +1,83 @@ +# Create profiles in hrflow +`Breezy HR` :arrow_right: `HrFlow` + +Send **created** 'profile(s)' _from_ Breezy HR _to_ HrFlow + + + +## Breezy HR Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `email` :red_circle: | `string` | None | email | +| `password` :red_circle: | `string` | None | password | +| `company_id` | `string\|null` | None | ID of company to pull jobs from in Breezy HR database associated with the authenticated user | +| `company_name` | `string\|null` | None | [⚠️ Requiered if company_id is not specified], the company associated with the authenticated user | + +## 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 (Breezy HR) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `position_id` | `string\|null` | None | Id of the position to create a new candidate for | + +## 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 BreezyHR + + +logging.basicConfig(level=logging.INFO) + + +BreezyHR.create_profiles_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + email=..., + password=..., + company_id=..., + company_name=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + position_id=..., + ), + push_parameters=dict( + source_key=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/docs/update_jobs_in_hrflow.md b/src/hrflow_connectors/v2/connectors/breezyhr/docs/update_jobs_in_hrflow.md new file mode 100644 index 000000000..8342e47a8 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/docs/update_jobs_in_hrflow.md @@ -0,0 +1,84 @@ +# Update jobs in hrflow +`Breezy HR` :arrow_right: `HrFlow` + +Send **updated** 'job(s)' _from_ Breezy HR _to_ HrFlow + + + +## Breezy HR Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `email` :red_circle: | `string` | None | email | +| `password` :red_circle: | `string` | None | password | +| `company_id` | `string\|null` | None | ID of company to pull jobs from in Breezy HR database associated with the authenticated user | +| `company_name` | `string\|null` | None | [⚠️ Requiered if company_id is not specified], the company associated with the authenticated user | + +## 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 (Breezy HR) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `state` | `Literal['archived','closed','draft','pending','published']` | published | Specify an optional position state filter. e.g. draft, archived, published, closed, pending +Defaults to published | + +## 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 BreezyHR + + +logging.basicConfig(level=logging.INFO) + + +BreezyHR.update_jobs_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + email=..., + password=..., + company_id=..., + company_name=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + state=..., + ), + push_parameters=dict( + board_key=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/docs/update_profiles_in_breezyhr.md b/src/hrflow_connectors/v2/connectors/breezyhr/docs/update_profiles_in_breezyhr.md new file mode 100644 index 000000000..a1562c76d --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/docs/update_profiles_in_breezyhr.md @@ -0,0 +1,85 @@ +# Update profiles in breezyhr +`HrFlow` :arrow_right: `Breezy HR` + +Send **updated** 'profile(s)' _from_ HrFlow _to_ Breezy HR + + + +## Breezy HR Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `email` :red_circle: | `string` | None | email | +| `password` :red_circle: | `string` | None | password | +| `company_id` | `string\|null` | None | ID of company to pull jobs from in Breezy HR database associated with the authenticated user | +| `company_name` | `string\|null` | None | [⚠️ Requiered if company_id is not specified], the company associated with the authenticated user | + +## 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 (Breezy HR) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `position_id` :red_circle: | `string` | None | Id of the position to create a new candidate for | + +## 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 BreezyHR + + +logging.basicConfig(level=logging.INFO) + + +BreezyHR.update_profiles_in_breezyhr( + workflow_id=..., + logics=..., + connector_auth=dict( + email=..., + password=..., + company_id=..., + company_name=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + source_key=..., + profile_key=..., + ), + push_parameters=dict( + position_id=..., + ), + format=..., + callback=..., + persist=..., + incremental=... +) +``` \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/docs/update_profiles_in_hrflow.md b/src/hrflow_connectors/v2/connectors/breezyhr/docs/update_profiles_in_hrflow.md new file mode 100644 index 000000000..09437067e --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/docs/update_profiles_in_hrflow.md @@ -0,0 +1,85 @@ +# Update profiles in hrflow +`Breezy HR` :arrow_right: `HrFlow` + +Send **updated** 'profile(s)' _from_ Breezy HR _to_ HrFlow + + + +## Breezy HR Auth Parameters + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `email` :red_circle: | `string` | None | email | +| `password` :red_circle: | `string` | None | password | +| `company_id` | `string\|null` | None | ID of company to pull jobs from in Breezy HR database associated with the authenticated user | +| `company_name` | `string\|null` | None | [⚠️ Requiered if company_id is not specified], the company associated with the authenticated user | + +## 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 (Breezy HR) + +| Field | Type | Default | Description | +| ----- | ---- | ------- | ----------- | +| `position_id` | `string\|null` | None | Id of the position to create a new candidate for | + +## 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 BreezyHR + + +logging.basicConfig(level=logging.INFO) + + +BreezyHR.update_profiles_in_hrflow( + workflow_id=..., + logics=..., + connector_auth=dict( + email=..., + password=..., + company_id=..., + company_name=..., + ), + hrflow_auth=dict( + api_secret=..., + api_user=..., + ), + pull_parameters=dict( + position_id=..., + ), + 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/breezyhr/logo.jpg b/src/hrflow_connectors/v2/connectors/breezyhr/logo.jpg new file mode 100644 index 000000000..f0eed272e Binary files /dev/null and b/src/hrflow_connectors/v2/connectors/breezyhr/logo.jpg differ diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/archive_jobs_in_hrflow.json b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/archive_jobs_in_hrflow.json new file mode 100644 index 000000000..018c86b68 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/archive_jobs_in_hrflow.json @@ -0,0 +1,3 @@ +{ + "reference": "?._id" +} diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/archive_profiles_in_hrflow.json b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/archive_profiles_in_hrflow.json new file mode 100644 index 000000000..018c86b68 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/archive_profiles_in_hrflow.json @@ -0,0 +1,3 @@ +{ + "reference": "?._id" +} diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/create_jobs_in_hrflow.json b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/create_jobs_in_hrflow.json new file mode 100644 index 000000000..4f08dba1b --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/create_jobs_in_hrflow.json @@ -0,0 +1,90 @@ +{ + "name": "?.name", + "reference": "?._id", + "summary": "?.description | $sub('<[^<]+?>', '') | $sub(' ', ' ')", + "location": { + "text": "?.location?.streetAddress?.custom ?? .location.streetAddress.custom: .location.name", + "geojson": { + "country": "?.location?.country?.name", + "city": "?.location?.city", + "text": "?.location?.streetAddress?.custom ?? .location.streetAddress.custom: .location.name" + }, + "lat": null, + "lng": null + }, + "sections": [ + { + "name": "description", + "title": "description", + "description": "?.description | $sub('<[^<]+?>', '') | $sub(' ', ' ')" + }, + { + "name": "experience", + "title": "Required Experience", + "description": "?.experience?.name" + }, + { + "name": "education", + "title": "Required Education", + "description": "?.education?.name" + }, + { + "name": "category", + "title": "Category", + "description": "?.category?.name" + }, + { + "name": "remote", + "title": "Remote Information", + "description": "?.location?.remote_details" + } + ], + "tags": [ + { + "name": "type", + "value": "?.type?.name" + }, + { + "name": "experience", + "value": "?.experience?.name" + }, + { + "name": "education", + "value": "?.education" + }, + { + "name": "department", + "value": "?.department" + }, + { + "name": "requisition_id", + "value": "?.requisition_id" + }, + { + "name": "category", + "value": "?.category?.name" + }, + { + "name": "candidate_type", + "value": "?.candidate_type" + }, + { + "name": "isremote", + "value": "?.location?.is_remote" + }, + { + "name": "remote_details", + "value": "?.location?.remote_details" + }, + { + "name": "creator_id", + "value": "?.creator_id" + }, + { + "name": "breezy_hr_tags", + "value": "?.tags" + } + ], + "created_at": "?.creation_date", + "updated_at": "?.updated_date" +} diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/create_profiles_in_breezyhr.json b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/create_profiles_in_breezyhr.json new file mode 100644 index 000000000..1296845b1 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/create_profiles_in_breezyhr.json @@ -0,0 +1,11 @@ +{ + "name": "?.info?.full_name", + "email_address": "?.info?.email", + "phone_number": "?.info?.phone", + "address": "?.info?.location?.text", + "summary": "?.info?.summary", + "work_history": "?.experiences | $map({company_name: ?.company >> 'Undefined', title: ?.title, summary: ?.description, start_year: ?.date_start != null ?? .date_start | $slice(0, 3) | $int, start_month: ?.date_start != null ?? .date_start | $slice(4,7) | $int, end_year: ?.date_end != null ?? .date_end | $slice(0, 3) | $int, end_month: ?.date_end != null ?? .date_end | $slice(4,7) | $int})", + "education": "?.educations | $map({school_name: ?.school >> 'Undefined', field_of_study: ?.title, start_year: ?.date_start != null ?? .date_start | $slice(0, 3) | $int, end_year: ?.date_end != null ?? .date_end | $slice(0, 3) | $int})", + "social_profiles": ".info?.urls >> [] | $map({.type: .url | $sub('(^https?://)(.*)', 'https://$2')})", + "tags": "?.skills >> [] | $map(?.name)" +} diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/create_profiles_in_hrflow.json b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/create_profiles_in_hrflow.json new file mode 100644 index 000000000..48f490e80 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/create_profiles_in_hrflow.json @@ -0,0 +1,50 @@ +{ + "reference": "?._id", + "info": { + "full_name": ".name", + "first_name": ".name | $split(' ') | .[0]", + "last_name": ".name | $split(' ') | .[-1]", + "email": ".email_address", + "phone": ".phone_number", + "urls": "?.social_profiles || [] | $map({type: .type, url: .url})", + "summary": ".summary", + "location": { + "text": "?.address", + "lat": null, + "lng": null + } + }, + "created_at": "?.creation_date", + "updated_at": "?.updated_date", + "experiences": "?.work_history || [] | $map({company: ?.company_name, title: ?.title, description: ?.summary, date_start: ?.start_date.year != null and ?.start_date.month != null and ?.start_date.day != null ?? .start_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, date_end: ?.end_date.year != null and ?.end_date.month != null and ?.end_date.day != null ?? .end_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, location: {text: null, lat: null, lng: null}})", + "educations": "?.education || [] | $map({school: ?.school_name, title: $concat(?.degree || '', ' ', ?.field_of_study || '')| $strip, description: $concat(?.degree || '', ' ', ?.field_of_study || '', ' at ', ?.school_name || '')| $strip, date_start: ?.start_date.year != null and ?.start_date.month != null and ?.start_date.day != null ?? .start_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, date_end: ?.end_date.year != null and ?.end_date.month != null and ?.end_date.day != null ?? .end_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, location: {text: null, lat: null, lng: null}})", + "skills": [], + "tags": [ + { + "name": "breezy_hr_tags", + "value": "?.tags" + }, + { + "name": "headline", + "value": "?.headline" + }, + { + "name": "origin", + "value": "?.origin" + }, + { + "name": "source", + "value": "?.source?.name" + }, + { + "name": "sourced_by", + "value": "?.sourced_by" + }, + { "name": "stage", "value": "?.stage?.name" }, + { + "name": "overall_score", + "value": "?.overall_score?.average_score" + } + ], + "resume": "?.resume" +} diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/update_jobs_in_hrflow.json b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/update_jobs_in_hrflow.json new file mode 100644 index 000000000..4f08dba1b --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/update_jobs_in_hrflow.json @@ -0,0 +1,90 @@ +{ + "name": "?.name", + "reference": "?._id", + "summary": "?.description | $sub('<[^<]+?>', '') | $sub(' ', ' ')", + "location": { + "text": "?.location?.streetAddress?.custom ?? .location.streetAddress.custom: .location.name", + "geojson": { + "country": "?.location?.country?.name", + "city": "?.location?.city", + "text": "?.location?.streetAddress?.custom ?? .location.streetAddress.custom: .location.name" + }, + "lat": null, + "lng": null + }, + "sections": [ + { + "name": "description", + "title": "description", + "description": "?.description | $sub('<[^<]+?>', '') | $sub(' ', ' ')" + }, + { + "name": "experience", + "title": "Required Experience", + "description": "?.experience?.name" + }, + { + "name": "education", + "title": "Required Education", + "description": "?.education?.name" + }, + { + "name": "category", + "title": "Category", + "description": "?.category?.name" + }, + { + "name": "remote", + "title": "Remote Information", + "description": "?.location?.remote_details" + } + ], + "tags": [ + { + "name": "type", + "value": "?.type?.name" + }, + { + "name": "experience", + "value": "?.experience?.name" + }, + { + "name": "education", + "value": "?.education" + }, + { + "name": "department", + "value": "?.department" + }, + { + "name": "requisition_id", + "value": "?.requisition_id" + }, + { + "name": "category", + "value": "?.category?.name" + }, + { + "name": "candidate_type", + "value": "?.candidate_type" + }, + { + "name": "isremote", + "value": "?.location?.is_remote" + }, + { + "name": "remote_details", + "value": "?.location?.remote_details" + }, + { + "name": "creator_id", + "value": "?.creator_id" + }, + { + "name": "breezy_hr_tags", + "value": "?.tags" + } + ], + "created_at": "?.creation_date", + "updated_at": "?.updated_date" +} diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/update_profiles_in_breezyhr.json b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/update_profiles_in_breezyhr.json new file mode 100644 index 000000000..69fc2b7b1 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/update_profiles_in_breezyhr.json @@ -0,0 +1,12 @@ +{ + "id": "?.reference", + "name": "?.info?.full_name", + "email_address": "?.info?.email", + "phone_number": "?.info?.phone", + "address": "?.info?.location?.text", + "summary": "?.info?.summary", + "work_history": "?.experiences | $map({company_name: ?.company >> 'Undefined', title: ?.title, summary: ?.description, start_year: ?.date_start != null ?? .date_start | $slice(0, 3) | $int, start_month: ?.date_start != null ?? .date_start | $slice(4,7) | $int, end_year: ?.date_end != null ?? .date_end | $slice(0, 3) | $int, end_month: ?.date_end != null ?? .date_end | $slice(4,7) | $int})", + "education": "?.educations | $map({school_name: ?.school >> 'Undefined', field_of_study: ?.title, start_year: ?.date_start != null ?? .date_start | $slice(0, 3) | $int, end_year: ?.date_end != null ?? .date_end | $slice(0, 3) | $int})", + "social_profiles": ".info?.urls >> [] | $map({.type: .url | $sub('(^https?://)(.*)', 'https://$2')})", + "tags": "?.skills >> [] | $map(?.name)" +} diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/update_profiles_in_hrflow.json b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/update_profiles_in_hrflow.json new file mode 100644 index 000000000..f2f9f56de --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/mappings/format/update_profiles_in_hrflow.json @@ -0,0 +1,50 @@ +{ + "reference": "?._id", + "info": { + "full_name": ".name", + "first_name": ".name | $split(' ') | .[0]", + "last_name": ".name | $split(' ') | .[-1]", + "email": ".email_address", + "phone": ".phone_number", + "urls": "?.social_profiles || [] | $map({type: .type, url: .url})", + "summary": ".summary", + "location": { + "text": ".address", + "lat": null, + "lng": null + } + }, + "created_at": "?.creation_date", + "updated_at": "?.updated_date", + "experiences": "?.work_history || [] | $map({company: ?.company_name, title: ?.title, description: ?.summary, date_start: ?.start_date.year != null and ?.start_date.month != null and ?.start_date.day != null ?? .start_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, date_end: ?.end_date.year != null and ?.end_date.month != null and ?.end_date.day != null ?? .end_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, location: {text: null, lat: null, lng: null}})", + "educations": "?.education || [] | $map({school: ?.school_name, title: $concat(?.degree || '', ' ', ?.field_of_study || '')| $strip, description: $concat(?.degree || '', ' ', ?.field_of_study || '', ' at ', ?.school_name || '')| $strip, date_start: ?.start_date.year != null and ?.start_date.month != null and ?.start_date.day != null ?? .start_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, date_end: ?.end_date.year != null and ?.end_date.month != null and ?.end_date.day != null ?? .end_date | $concat(.year, '-', $concat('0', .month) | $slice(-2), '-', $concat('0', .day) | $slice(-2)) : null, location: {text: null, lat: null, lng: null}})", + "skills": [], + "tags": [ + { + "name": "breezy_hr_tags", + "value": "?.tags" + }, + { + "name": "headline", + "value": "?.headline" + }, + { + "name": "origin", + "value": "?.origin" + }, + { + "name": "source", + "value": "?.source?.name" + }, + { + "name": "sourced_by", + "value": "?.sourced_by" + }, + { "name": "stage", "value": "?.stage?.name" }, + { + "name": "overall_score", + "value": "?.overall_score?.average_score" + } + ], + "resume": "?.resume" +} diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/notebooks/.gitkeep b/src/hrflow_connectors/v2/connectors/breezyhr/notebooks/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/schemas.py b/src/hrflow_connectors/v2/connectors/breezyhr/schemas.py new file mode 100644 index 000000000..f56eea7b1 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/schemas.py @@ -0,0 +1,112 @@ +from typing import Any, Dict, List, Optional + +from msgspec import Meta, Struct +from typing_extensions import Annotated + + +class Type(Struct): + id: str + name: str + + +class Experience(Struct): + id: str + name: str + + +class Country(Struct): + name: str + id: str + + +class Location(Struct): + country: Country + city: str + is_remote: Optional[bool] + name: str + + +class Category(Struct): + id: str + name: str + + +class ApplicationForm(Struct): + name: str + headline: str + summary: str + profile_photo: str + address: str + email_address: str + phone_number: str + resume: str + work_history: str + education: str + cover_letter: str + questionnaire_in_experience: bool + + +class BreezyJobModel(Struct): + _id: Annotated[str, Meta(description="position id")] + type: Annotated[Type, Meta(description="job type")] + state: Annotated[ + str, + Meta( + description="state of the position posting, published or internal and so on" + ), + ] + name: Annotated[str, Meta(description="job title")] + friendly_id: Annotated[ + str, + Meta(description="another id of the job which combines its title and its id"), + ] + experience: Optional[Experience] + location: Location + education: str + department: str + description: Annotated[str, Meta(description="Job category")] + category: Category + application_form: Annotated[ + Optional[ApplicationForm], Meta(description="job Application for") + ] + creator_id: Optional[str] + creation_date: str + updated_date: str + all_users: List[str] + all_admins: List[str] + candidate_type: str + tags: List + org_type: str + + +class WorkHistoryItem(Struct): + company_name: str + title: str + summary: str + start_month: Optional[int] + start_year: Optional[int] + end_month: Optional[int] + end_year: Optional[int] + + +class EducationItem(Struct): + school_name: str + field_of_study: str + start_year: Optional[int] + end_year: Optional[int] + + +class BreezyProfileModel(Struct): + name: str + email_address: str + phone_number: str + summary: str + tags: Optional[List[str]] + source: Optional[str] + origin: Optional[str] + address: str + work_history: List[WorkHistoryItem] + education: List[EducationItem] + social_profiles: Optional[List[str]] + custom_attributes: Optional[List[Dict[str, Any]]] + cover_letter: Optional[str] diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/test-config.yaml b/src/hrflow_connectors/v2/connectors/breezyhr/test-config.yaml new file mode 100644 index 000000000..4fd42883e --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/test-config.yaml @@ -0,0 +1,239 @@ +warehouse: + BreezyHRJobWarehouse: + read: + - parameters: + email: $__EMAIL + password: $__PASSWORD + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + + - parameters: + email: $__EMAIL + password: $__PASSWORD + company_id : $__COMPANY_ID + + - parameters: + email: $__EMAIL + password: $__PASSWORD + company_name : $__COMPANY_NAME + +actions: + pull_jobs: + - id: valid_parameters + origin_parameters: + email: $__EMAIL + password: $__PASSWORD + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: success + + - id: valid_parameters_without_company_name + origin_parameters: + email: $__EMAIL + password: $__PASSWORD + company_id : $__COMPANY_ID + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: success + + - id: valid_parameters_without_company_id + origin_parameters: + email: $__EMAIL + password: $__PASSWORD + company_name : $__COMPANY_NAME + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: success + + - id: invalid_parameters_missing_company_id_or_name + origin_parameters: + email: $__EMAIL + password: $__PASSWORD + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: fatal + + - id: invalid_parameters_email + origin_parameters: + email: invalid + password: $__PASSWORD + company_name : $__COMPANY_NAME + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: fatal + + - id: missing_parameters_email + origin_parameters: + password: $__PASSWORD + company_name : $__COMPANY_NAME + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: fatal + + - id: invalid_parameters_password + origin_parameters: + email: $__EMAIL + password: invalid + company_name : $__COMPANY_NAME + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: fatal + + - id: missing_parameters_password + origin_parameters: + email: $__EMAIL + company_name : $__COMPANY_NAME + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: fatal + + - id: invalid_parameters_company_id + origin_parameters: + email: $__EMAIL + password: $__PASSWORD + company_id: invalid + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: fatal + + - id: invalid_parameters_company_name + origin_parameters: + email: $__EMAIL + password: $__PASSWORD + company_id : invalid + target_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + board_key: $__BOARD_KEY + status: fatal + + push_profiles: + - id: valid_parameters_update_profile + origin_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + source_key: $__SOURCE_KEY + profile_key: $__PROFILE_KEY + target_parameters: + email: $__EMAIL + password: $__PASSWORD + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + position_id : $__POSITION_ID + status: success + + - id: valid_parameters_send_profile + origin_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + source_key: $__SOURCE_KEY + profile_key: $__PROFILE_KEY_WITH_NO_EMAIL + target_parameters: + email: $__EMAIL + password: $__PASSWORD + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + position_id : $__POSITION_ID + status: success + + - id: invalid_parameters_mail + origin_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + source_key: $__SOURCE_KEY + profile_key: $__PROFILE_KEY + target_parameters: + email: invalid + password: $__PASSWORD + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + position_id : $__POSITION_ID + status: fatal + + - id: missing_parameters_mail + origin_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + source_key: $__SOURCE_KEY + profile_key: $__PROFILE_KEY + target_parameters: + password: $__PASSWORD + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + position_id : $__POSITION_ID + status: fatal + + - id: invalid_parameters_password + origin_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + source_key: $__SOURCE_KEY + profile_key: $__PROFILE_KEY + target_parameters: + email: $__EMAIL + password: invalid + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + position_id : $__POSITION_ID + status: fatal + + + - id: missing_parameters_password + origin_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + source_key: $__SOURCE_KEY + profile_key: $__PROFILE_KEY + target_parameters: + email: $__EMAIL + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + position_id : $__POSITION_ID + status: fatal + + - id: invalid_parameters_position_id + origin_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + source_key: $__SOURCE_KEY + profile_key: $__PROFILE_KEY + target_parameters: + email: $__EMAIL + password: $__PASSWORD + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + position_id : invalid + status: fatal + + - id: missing_parameters_position_id + origin_parameters: + api_secret: $__API_SECRET + api_user: $__API_USER + source_key: $__SOURCE_KEY + profile_key: $__PROFILE_KEY + target_parameters: + email: $__EMAIL + password: $__PASSWORD + company_id : $__COMPANY_ID + company_name : $__COMPANY_NAME + status: fatal \ No newline at end of file diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/utils.py b/src/hrflow_connectors/v2/connectors/breezyhr/utils.py new file mode 100644 index 000000000..b5c9b0fb0 --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/utils.py @@ -0,0 +1,17 @@ +import re + + +def remove_html_tags(text: str) -> str: + """ + Remove all HTML tags in a string + Args: + text (str): text to clean + Returns: + str: cleaned text (without HTML tags) + """ + return re.sub("<[^<]+?>", "", text) + + +def is_valid_url(url): + regex = r"^https?:\/\/(www\.)?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\/?[^\s]*$" + return re.match(regex, url) is not None diff --git a/src/hrflow_connectors/v2/connectors/breezyhr/warehouse.py b/src/hrflow_connectors/v2/connectors/breezyhr/warehouse.py new file mode 100644 index 000000000..3c054ed7e --- /dev/null +++ b/src/hrflow_connectors/v2/connectors/breezyhr/warehouse.py @@ -0,0 +1,14 @@ +from hrflow_connectors.v2.connectors.breezyhr.aisles import ( + AuthParameters, + JobsAisle, + ProfilesAisle, +) +from hrflow_connectors.v2.core.warehouse import Warehouse + +BreezyHrWarehouse = Warehouse( + auth=AuthParameters, + aisles=( + JobsAisle, + ProfilesAisle, + ), +)