diff --git a/README.md b/README.md
index 732448708..6cd1af05b 100644
--- a/README.md
+++ b/README.md
@@ -135,6 +135,7 @@ We invite developers to join us in our mission to bring AI and data integration
| **Indeed** | Job Board | π― | | |
| **Inzojob** | Job Board | π― | | |
| **Jobijoba** | Job Board | π― | | |
+| [**Jobology**](./src/hrflow_connectors/connectors/jobology/README.md) | Job Board | :white_check_mark: | *21/12/2022* | *08/01/2024* | :x: | :x: | :x: | :x: |
| **Jobrapido** | Job Board | π― | | |
| **JobTeaser** | Job Board | π― | | |
| **Jobtransport** | Job Board | π― | | |
diff --git a/manifest.json b/manifest.json
index 7bb5eb904..bad921f3e 100644
--- a/manifest.json
+++ b/manifest.json
@@ -25049,6 +25049,210 @@
],
"type": "ATS",
"logo": "https://raw.githubusercontent.com/Riminder/hrflow-connectors/master/src/hrflow_connectors/connectors/digitalrecruiters/logo.png"
+ },
+ {
+ "name": "Jobology",
+ "actions": [
+ {
+ "name": "catch_profile",
+ "action_type": "inbound",
+ "action_parameters": {
+ "title": "TriggerViewActionParameters",
+ "type": "object",
+ "properties": {
+ "read_mode": {
+ "description": "If 'incremental' then `read_from` of the last run is given to Origin Warehouse during read. **The actual behavior depends on implementation of read**. In 'sync' mode `read_from` is neither fetched nor given to Origin Warehouse during read.",
+ "default": "sync",
+ "allOf": [
+ {
+ "$ref": "#/definitions/ReadMode"
+ }
+ ]
+ },
+ "logics": {
+ "title": "logics",
+ "description": "List of logic functions. Each function should have the following signature typing.Callable[[typing.Dict], typing.Optional[typing.Dict]]. The final list should be exposed in a variable named 'logics'.",
+ "template": "\nimport typing as t\n\ndef logic_1(item: t.Dict) -> t.Union[t.Dict, None]:\n return None\n\ndef logic_2(item: t.Dict) -> t.Uniont[t.Dict, None]:\n return None\n\nlogics = [logic_1, logic_2]\n",
+ "type": "code_editor"
+ },
+ "format": {
+ "title": "format",
+ "description": "Formatting function. You should expose a function named 'format' with following signature typing.Callable[[typing.Dict], typing.Dict]",
+ "template": "\nimport typing as t\n\ndef format(item: t.Dict) -> t.Dict:\n return item\n",
+ "type": "code_editor"
+ },
+ "event_parser": {
+ "title": "event_parser",
+ "description": "Event parsing function for **CATCH** integrations. You should expose a function named 'event_parser' with following signature typing.Callable[[typing.Dict], typing.Dict]",
+ "template": "\nimport typing as t\n\ndef event_parser(event: t.Dict) -> t.Dict:\n parsed = dict()\n parsed[\"user_id\"] = event[\"email\"]\n parsed[\"thread_id\"] = event[\"subscription_id\"]\n return parsed\n",
+ "type": "code_editor"
+ }
+ },
+ "additionalProperties": false,
+ "definitions": {
+ "ReadMode": {
+ "title": "ReadMode",
+ "description": "An enumeration.",
+ "enum": [
+ "sync",
+ "incremental"
+ ]
+ }
+ }
+ },
+ "data_type": "profile",
+ "trigger_type": "hook",
+ "origin": "Jobology Candidate",
+ "origin_parameters": {
+ "title": "ReadProfilesParameters",
+ "type": "object",
+ "properties": {
+ "profile": {
+ "title": "Profile",
+ "description": "Event object recieved from the Webhook",
+ "field_type": "Other",
+ "type": "object"
+ }
+ },
+ "additionalProperties": false
+ },
+ "origin_data_schema": {
+ "title": "BaseModel",
+ "type": "object",
+ "properties": {}
+ },
+ "supports_incremental": false,
+ "target": "HrFlow.ai Profile Parsing",
+ "target_parameters": {
+ "title": "WriteProfileParsingParameters",
+ "type": "object",
+ "properties": {
+ "api_secret": {
+ "title": "Api Secret",
+ "description": "X-API-KEY used to access HrFlow.ai API",
+ "field_type": "Auth",
+ "type": "string"
+ },
+ "api_user": {
+ "title": "Api User",
+ "description": "X-USER-EMAIL used to access HrFlow.ai API",
+ "field_type": "Auth",
+ "type": "string"
+ },
+ "source_key": {
+ "title": "Source Key",
+ "description": "HrFlow.ai source key",
+ "field_type": "Other",
+ "type": "string"
+ },
+ "only_insert": {
+ "title": "Only Insert",
+ "description": "When enabled the profile is written only if it doesn't exist in the source",
+ "default": false,
+ "field_type": "Other",
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "api_secret",
+ "api_user",
+ "source_key"
+ ],
+ "additionalProperties": false
+ },
+ "target_data_schema": {
+ "title": "HrFlowProfileParsing",
+ "type": "object",
+ "properties": {
+ "reference": {
+ "title": "Reference",
+ "description": "Custom identifier of the Profile.",
+ "type": "string"
+ },
+ "created_at": {
+ "title": "Created At",
+ "description": "type: datetime ISO8601, Creation date of the Profile.",
+ "type": "string"
+ },
+ "resume": {
+ "$ref": "#/definitions/ResumeToParse"
+ },
+ "tags": {
+ "title": "Tags",
+ "description": "List of tags of the Profile.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/GeneralEntitySchema"
+ }
+ },
+ "metadatas": {
+ "title": "Metadatas",
+ "description": "List of metadatas of the Profile.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/GeneralEntitySchema"
+ }
+ }
+ },
+ "required": [
+ "reference",
+ "created_at",
+ "resume",
+ "tags",
+ "metadatas"
+ ],
+ "definitions": {
+ "ResumeToParse": {
+ "title": "ResumeToParse",
+ "type": "object",
+ "properties": {
+ "raw": {
+ "title": "Raw",
+ "type": "string",
+ "format": "binary"
+ },
+ "content_type": {
+ "title": "Content Type",
+ "type": "string"
+ }
+ },
+ "required": [
+ "raw",
+ "content_type"
+ ]
+ },
+ "GeneralEntitySchema": {
+ "title": "GeneralEntitySchema",
+ "type": "object",
+ "properties": {
+ "name": {
+ "title": "Name",
+ "description": "Identification name of the Object",
+ "type": "string"
+ },
+ "value": {
+ "title": "Value",
+ "description": "Value associated to the Object's name",
+ "type": "string"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ }
+ },
+ "workflow_code": "import typing as t\n\nfrom hrflow_connectors import Jobology\nfrom hrflow_connectors.core.connector import ActionInitError, Reason\n\nORIGIN_SETTINGS_PREFIX = \"origin_\"\nTARGET_SETTINGS_PREFIX = \"target_\"\n\n# << format_placeholder >>\n\n# << logics_placeholder >>\n\n# << event_parser_placeholder >>\n\n\ndef workflow(\n \n _request: t.Dict,\n \n settings: t.Dict\n ) -> None:\n actions_parameters = dict()\n try:\n format\n except NameError:\n pass\n else:\n actions_parameters[\"format\"] = format\n\n try:\n logics\n except NameError:\n pass\n else:\n actions_parameters[\"logics\"] = logics\n\n if \"__workflow_id\" not in settings:\n return Jobology.catch_profile(\n workflow_id=\"\",\n action_parameters=dict(),\n origin_parameters=dict(),\n target_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 try:\n event_parser\n _event_parser = event_parser\n except NameError as e:\n action = Jobology.model.action_by_name(\"catch_profile\")\n # Without this trick event_parser is always only fetched from the local scope\n # meaning that try block always raises NameError even if the function is\n # defined in the placeholder\n _event_parser = action.parameters.__fields__[\"event_parser\"].default\n\n if _event_parser is not None:\n try:\n _request = _event_parser(_request)\n except Exception as e:\n return Jobology.catch_profile(\n workflow_id=workflow_id,\n action_parameters=dict(),\n origin_parameters=dict(),\n target_parameters=dict(),\n init_error=ActionInitError(\n reason=Reason.event_parsing_failure,\n data=dict(error=e, event=_request),\n )\n )\n \n\n origin_parameters = dict()\n for parameter in ['profile']:\n if \"{}{}\".format(ORIGIN_SETTINGS_PREFIX, parameter) in settings:\n origin_parameters[parameter] = settings[\"{}{}\".format(ORIGIN_SETTINGS_PREFIX, parameter)]\n \n if parameter in _request:\n origin_parameters[parameter] = _request[parameter]\n \n\n target_parameters = dict()\n for parameter in ['api_secret', 'api_user', 'source_key', 'only_insert']:\n if \"{}{}\".format(TARGET_SETTINGS_PREFIX, parameter) in settings:\n target_parameters[parameter] = settings[\"{}{}\".format(TARGET_SETTINGS_PREFIX, parameter)]\n \n if parameter in _request:\n target_parameters[parameter] = _request[parameter]\n \n\n return Jobology.catch_profile(\n workflow_id=workflow_id,\n action_parameters=actions_parameters,\n origin_parameters=origin_parameters,\n target_parameters=target_parameters,\n )",
+ "workflow_code_format_placeholder": "# << format_placeholder >>",
+ "workflow_code_logics_placeholder": "# << logics_placeholder >>",
+ "workflow_code_event_parser_placeholder": "# << event_parser_placeholder >>",
+ "workflow_code_workflow_id_settings_key": "__workflow_id",
+ "workflow_code_origin_settings_prefix": "origin_",
+ "workflow_code_target_settings_prefix": "target_"
+ }
+ ],
+ "type": "Job Board",
+ "logo": "https://raw.githubusercontent.com/Riminder/hrflow-connectors/master/src/hrflow_connectors/connectors/jobology/logo.jpeg"
}
]
}
\ No newline at end of file
diff --git a/src/hrflow_connectors/__init__.py b/src/hrflow_connectors/__init__.py
index 57adaf247..55ad43fc7 100644
--- a/src/hrflow_connectors/__init__.py
+++ b/src/hrflow_connectors/__init__.py
@@ -5,6 +5,7 @@
from hrflow_connectors.connectors.digitalrecruiters import DigitalRecruiters
from hrflow_connectors.connectors.greenhouse.connector import Greenhouse
from hrflow_connectors.connectors.hubspot import Hubspot
+from hrflow_connectors.connectors.jobology import Jobology
from hrflow_connectors.connectors.lever import Lever
from hrflow_connectors.connectors.poleemploi import PoleEmploi
from hrflow_connectors.connectors.recruitee import Recruitee
@@ -40,6 +41,7 @@
Lever,
Salesforce,
DigitalRecruiters,
+ Jobology,
]
# This makes sure that connector are in module namespace
diff --git a/src/hrflow_connectors/connectors/jobology/README.md b/src/hrflow_connectors/connectors/jobology/README.md
new file mode 100644
index 000000000..9aff45bc0
--- /dev/null
+++ b/src/hrflow_connectors/connectors/jobology/README.md
@@ -0,0 +1,72 @@
+# π Summary
+- [π Summary](#-summary)
+- [πΌ About Jobology](#-about-jobology)
+ - [π Why is it a big deal for Jobology customers & partners?](#-why-is-it-a-big-deal-for-jobology-customers--partners)
+- [π§ How does it work?](#-how-does-it-work)
+ - [π Data integration capabilities:](#-data-integration-capabilities)
+- [π Connector Actions](#-connector-actions)
+- [π Quick Start Examples](#-quick-start-examples)
+- [π Useful Links](#-useful-links)
+- [π Special Thanks](#-special-thanks)
+
+
+# πΌ About Jobology
+
+> La mission de jobology est de faciliter le processus de recrutement pour les entreprises
+
+
+## π Why is it a big deal for Jobology customers & partners?
+
+This new connector will enable:
+- β‘ A Fastlane Talent & Workforce data integration for Jobology customers & partners
+- π€ Cutting-edge AI-powered Talent Experiences & Recruiter Experiences for Jobology customers
+
+# π§ How does it work?
+## π Data integration capabilities:
+- β¬
οΈ Send Profiles data from Jobology to a Destination of your choice:
+
+
+
+
+
+# π Connector Actions
+
+
+| Action | Description |
+| ------- | ----------- |
+| [**Catch profile**](docs/catch_profile.md) | Imports candidates, in synchronization with jobology |
+
+
+
+
+
+
+
+
+
+# π 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 [Jobology](https://www.jobology.com/) to learn more.
+- π» [Connector code](https://github.com/Riminder/hrflow-connectors/tree/master/src/hrflow_connectors/connectors/jobology) on our Github.
+
+
+# π Special Thanks
+- π» HrFlow.ai : Abdellahi Mezid - Software Engineer
+- π€ Jobology : Jobology Team
\ No newline at end of file
diff --git a/src/hrflow_connectors/connectors/jobology/__init__.py b/src/hrflow_connectors/connectors/jobology/__init__.py
new file mode 100644
index 000000000..a077e33fd
--- /dev/null
+++ b/src/hrflow_connectors/connectors/jobology/__init__.py
@@ -0,0 +1 @@
+from hrflow_connectors.connectors.jobology.connector import Jobology # noqa
diff --git a/src/hrflow_connectors/connectors/jobology/connector.py b/src/hrflow_connectors/connectors/jobology/connector.py
new file mode 100644
index 000000000..0f20c139a
--- /dev/null
+++ b/src/hrflow_connectors/connectors/jobology/connector.py
@@ -0,0 +1,83 @@
+import typing as t
+
+from hrflow_connectors.connectors.hrflow.warehouse import HrFlowProfileParsingWarehouse
+from hrflow_connectors.connectors.jobology.warehouse import JobologyProfilesWarehouse
+from hrflow_connectors.core import (
+ ActionName,
+ ActionType,
+ BaseActionParameters,
+ Connector,
+ ConnectorAction,
+ ConnectorType,
+ WorkflowType,
+)
+
+
+def rename_profile_fields(jobology_profile: t.Dict) -> t.Dict:
+ return {
+ "job-key": jobology_profile["jobkey"],
+ "first_name": jobology_profile.get("firstName"),
+ "last_name": jobology_profile.get("lastName"),
+ "phone": jobology_profile.get("phone"),
+ "email": jobology_profile.get("email"),
+ "coverText": jobology_profile.get("coverText"),
+ "profile-country": jobology_profile.get("profilecountry"),
+ "profile-regions": jobology_profile.get("profileregions"),
+ "profile-domains": jobology_profile.get("profiledomains"),
+ "job-lien_annonce_site_carriere": jobology_profile.get(
+ "joblien_annonce_site_carriere"
+ ),
+ "statistic-source": jobology_profile.get("statisticsource"),
+ "statistic-jbsource": jobology_profile.get("statisticjbsource"),
+ }
+
+
+def add_tags(profile_tags: t.Dict) -> t.List[t.Dict]:
+ return [dict(name=key, value=value) for key, value in profile_tags.items() if value]
+
+
+def format_jobology_profile(jobology_profile: t.List) -> t.Dict:
+ profile_tags = rename_profile_fields(jobology_profile)
+ tags = add_tags(profile_tags)
+ resume_dict = dict(
+ raw=jobology_profile["cv"],
+ content_type=jobology_profile["content_type"],
+ )
+ return dict(
+ reference=jobology_profile["email"],
+ resume=resume_dict,
+ tags=tags,
+ metadatas=[],
+ created_at=None,
+ )
+
+
+def event_parser(event: t.Dict) -> t.Dict:
+ return dict(profile=event)
+
+
+DESCRIPTION = (
+ "La mission de jobology est de faciliter le processus de recrutement pour les"
+ " entreprises "
+)
+Jobology = Connector(
+ name="Jobology",
+ type=ConnectorType.JobBoard,
+ description=DESCRIPTION,
+ url="https://www.jobology.fr/",
+ actions=[
+ ConnectorAction(
+ name=ActionName.catch_profile,
+ trigger_type=WorkflowType.catch,
+ description="Imports candidates, in synchronization with jobology",
+ parameters=BaseActionParameters.with_defaults(
+ "TriggerViewActionParameters",
+ format=format_jobology_profile,
+ event_parser=event_parser,
+ ),
+ origin=JobologyProfilesWarehouse,
+ target=HrFlowProfileParsingWarehouse,
+ action_type=ActionType.inbound,
+ )
+ ],
+)
diff --git a/src/hrflow_connectors/connectors/jobology/docs/catch_profile.md b/src/hrflow_connectors/connectors/jobology/docs/catch_profile.md
new file mode 100644
index 000000000..86a79e4ce
--- /dev/null
+++ b/src/hrflow_connectors/connectors/jobology/docs/catch_profile.md
@@ -0,0 +1,61 @@
+# Catch profile
+`Jobology Candidate` :arrow_right: `HrFlow.ai Profile Parsing`
+
+Imports candidates, in synchronization with jobology
+
+
+
+## Action Parameters
+
+| Field | Type | Default | Description |
+| ----- | ---- | ------- | ----------- |
+| `logics` | `typing.List[typing.Callable[[typing.Dict], typing.Optional[typing.Dict]]]` | [] | List of logic functions |
+| `format` | `typing.Callable[[typing.Dict], typing.Dict]` | [`format_jobology_profile`](../connector.py#L39) | Formatting function |
+| `read_mode` | `str` | ReadMode.sync | If 'incremental' then `read_from` of the last run is given to Origin Warehouse during read. **The actual behavior depends on implementation of read**. In 'sync' mode `read_from` is neither fetched nor given to Origin Warehouse during read. |
+
+## Source Parameters
+
+| Field | Type | Default | Description |
+| ----- | ---- | ------- | ----------- |
+| `profile` | `typing.Dict` | None | Event object recieved from the Webhook |
+
+## Destination Parameters
+
+| Field | Type | Default | Description |
+| ----- | ---- | ------- | ----------- |
+| `api_secret` :red_circle: | `str` | None | X-API-KEY used to access HrFlow.ai API |
+| `api_user` :red_circle: | `str` | None | X-USER-EMAIL used to access HrFlow.ai API |
+| `source_key` :red_circle: | `str` | None | HrFlow.ai source key |
+| `only_insert` | `bool` | False | When enabled the profile is written only if it doesn't exist in the source |
+
+:red_circle: : *required*
+
+## Example
+
+```python
+import logging
+from hrflow_connectors import Jobology
+from hrflow_connectors.core import ReadMode
+
+
+logging.basicConfig(level=logging.INFO)
+
+
+Jobology.catch_profile(
+ workflow_id="some_string_identifier",
+ action_parameters=dict(
+ logics=[],
+ format=lambda *args, **kwargs: None # Put your code logic here,
+ read_mode=ReadMode.sync,
+ ),
+ origin_parameters=dict(
+ profile=***,
+ ),
+ target_parameters=dict(
+ api_secret="your_api_secret",
+ api_user="your_api_user",
+ source_key="your_source_key",
+ only_insert=False,
+ )
+)
+```
\ No newline at end of file
diff --git a/src/hrflow_connectors/connectors/jobology/logo.jpeg b/src/hrflow_connectors/connectors/jobology/logo.jpeg
new file mode 100644
index 000000000..bdafbe3cf
Binary files /dev/null and b/src/hrflow_connectors/connectors/jobology/logo.jpeg differ
diff --git a/src/hrflow_connectors/connectors/jobology/schemas.py b/src/hrflow_connectors/connectors/jobology/schemas.py
new file mode 100644
index 000000000..e5a0784ea
--- /dev/null
+++ b/src/hrflow_connectors/connectors/jobology/schemas.py
@@ -0,0 +1,20 @@
+import typing as t
+
+from pydantic import BaseModel
+
+
+class jobologyEventObject(BaseModel):
+ type: str
+ jobkey: t.Optional[str]
+ firstName: t.Optional[str]
+ lastName: t.Optional[str]
+ phone: t.Optional[str]
+ email: str
+ cvUrl: str
+ coverText: t.Optional[str]
+ profilecountry: t.Optional[str]
+ profileregions: t.Optional[str]
+ profiledomains: t.Optional[str]
+ joblien_annonce_site_carriere: t.Optional[str]
+ statisticsource: t.Optional[str]
+ statisticjbsource: t.Optional[str]
diff --git a/src/hrflow_connectors/connectors/jobology/test-config.yaml b/src/hrflow_connectors/connectors/jobology/test-config.yaml
new file mode 100644
index 000000000..33eeeed09
--- /dev/null
+++ b/src/hrflow_connectors/connectors/jobology/test-config.yaml
@@ -0,0 +1,96 @@
+warehouse:
+ JobologyProfilesWarehouse:
+ read:
+ - parameters:
+ profile: {
+ "type":"jobology_direct_apply",
+ "jobkey":" JO-0145781_1701343287",
+ "firstName":"Abdellahi",
+ "lastName":"Mezid",
+ "phone":"0611423374",
+ "email":"pierre.dupont@mailprovider.com",
+ "cvUrl":"https://riminder-documents-eu-2019-12.s3-eu-west-1.amazonaws.com/teams/fc9d40fd60e679119130ea74ae1d34a3e22174f2/sources/e6159e65395995ae9f69a90ce916f7b6f90823dd/profiles/ab1c521d49b73d321bd54f6f6d3a4d81a31835eb/parsing/original.pdf",
+ "coverText":"Ceci est le texte de motivation.\nCe champ peut contenir des retours Γ la ligne.",
+ "profilecountry": "France",
+ "profileregions": "Ile-de-france",
+ "profiledomains": "Chauffeur SPL, Chauffeur routier, Chauffeur",
+ "joblien_annonce_site_carriere": "https://www.jobtransport.com/offre-emploi/approvisionneur-h-f-ecquevilly-2476964.aspx",
+ "statisticsource": "Groupe Fed",
+ "statisticjbsource": "jobology",
+ }
+actions:
+ catch_profile:
+ - id: no_hrflow_source_key
+ origin_parameters:
+ profile: {
+ "type":"jobology_direct_apply",
+ "jobkey":" JO-0145781_1701343287",
+ "firstName":"Abdellahi",
+ "lastName":"Mezid",
+ "phone":"0611423374",
+ "email":"pierre.dupont@mailprovider.com",
+ "cvUrl":"https://riminder-documents-eu-2019-12.s3-eu-west-1.amazonaws.com/teams/fc9d40fd60e679119130ea74ae1d34a3e22174f2/sources/e6159e65395995ae9f69a90ce916f7b6f90823dd/profiles/ab1c521d49b73d321bd54f6f6d3a4d81a31835eb/parsing/original.pdf",
+ "coverText":"Ceci est le texte de motivation.\nCe champ peut contenir des retours Γ la ligne.",
+ "profilecountry": "France",
+ "profileregions": "Ile-de-france",
+ "profiledomains": "Chauffeur SPL, Chauffeur routier, Chauffeur",
+ "joblien_annonce_site_carriere": "https://www.jobtransport.com/offre-emploi/approvisionneur-h-f-ecquevilly-2476964.aspx",
+ "statisticsource": "Groupe Fed",
+ "statisticjbsource": "jobology",
+ }
+ target_parameters:
+ api_secret: $__API_SECRET
+ api_user: $__API_USER
+ only_insert: false
+ status: fatal
+ reason: bad_target_parameters
+ - id: invalid_hrflow_api_secret
+ origin_parameters:
+ profile: {
+ "type":"jobology_direct_apply",
+ "jobkey":" JO-0145781_1701343287",
+ "firstName":"Abdellahi",
+ "lastName":"Mezid",
+ "phone":"0611423374",
+ "email":"pierre.dupont@mailprovider.com",
+ "cvUrl":"https://riminder-documents-eu-2019-12.s3-eu-west-1.amazonaws.com/teams/fc9d40fd60e679119130ea74ae1d34a3e22174f2/sources/e6159e65395995ae9f69a90ce916f7b6f90823dd/profiles/ab1c521d49b73d321bd54f6f6d3a4d81a31835eb/parsing/original.pdf",
+ "coverText":"Ceci est le texte de motivation.\nCe champ peut contenir des retours Γ la ligne.",
+ "profilecountry": "France",
+ "profileregions": "Ile-de-france",
+ "profiledomains": "Chauffeur SPL, Chauffeur routier, Chauffeur",
+ "joblien_annonce_site_carriere": "https://www.jobtransport.com/offre-emploi/approvisionneur-h-f-ecquevilly-2476964.aspx",
+ "statisticsource": "Groupe Fed",
+ "statisticjbsource": "jobology",
+ }
+ target_parameters:
+ api_secret: bad_api_secret
+ api_user: $__API_USER
+ source_key: $__SOURCE_KEY
+ only_insert: false
+ status: fatal
+ reason: write_failure
+ - id: write_success
+ origin_parameters:
+ profile: {
+ "type":"jobology_direct_apply",
+ "jobkey":" JO-0145781_1701343287",
+ "firstName":"Abdellahi",
+ "lastName":"Mezid",
+ "phone":"0611423374",
+ "email":"pierre.dupont@mailprovider.com",
+ "cvUrl":"https://riminder-documents-eu-2019-12.s3-eu-west-1.amazonaws.com/teams/fc9d40fd60e679119130ea74ae1d34a3e22174f2/sources/e6159e65395995ae9f69a90ce916f7b6f90823dd/profiles/ab1c521d49b73d321bd54f6f6d3a4d81a31835eb/parsing/original.pdf",
+ "coverText":"Ceci est le texte de motivation.\nCe champ peut contenir des retours Γ la ligne.",
+ "profilecountry": "France",
+ "profileregions": "Ile-de-france",
+ "profiledomains": "Chauffeur SPL, Chauffeur routier, Chauffeur",
+ "joblien_annonce_site_carriere": "https://www.jobtransport.com/offre-emploi/approvisionneur-h-f-ecquevilly-2476964.aspx",
+ "statisticsource": "Groupe Fed",
+ "statisticjbsource": "jobology",
+ }
+ target_parameters:
+ api_secret: $__API_SECRET
+ api_user: $__API_USER
+ source_key: $__SOURCE_KEY
+ only_insert: false
+ status: success
+
\ No newline at end of file
diff --git a/src/hrflow_connectors/connectors/jobology/warehouse.py b/src/hrflow_connectors/connectors/jobology/warehouse.py
new file mode 100644
index 000000000..d90716284
--- /dev/null
+++ b/src/hrflow_connectors/connectors/jobology/warehouse.py
@@ -0,0 +1,55 @@
+import typing as t
+from logging import LoggerAdapter
+
+import requests
+from pydantic import Field
+
+from hrflow_connectors.core import (
+ DataType,
+ FieldType,
+ ParametersModel,
+ ReadMode,
+ Warehouse,
+ WarehouseReadAction,
+)
+
+
+class ReadProfilesParameters(ParametersModel):
+ profile: t.Dict = Field(
+ None,
+ description="Event object recieved from the Webhook",
+ field_type=FieldType.Other,
+ )
+
+
+def read(
+ adapter: LoggerAdapter,
+ parameters: ReadProfilesParameters,
+ read_mode: t.Optional[ReadMode] = None,
+ read_from: t.Optional[str] = None,
+) -> t.Iterable[t.Dict]:
+ result = {**parameters.profile}
+ cv_url = result["cvUrl"]
+ response = requests.get(cv_url)
+ if response.status_code == 200:
+ result["cv"] = response.content
+ result["content_type"] = response.headers["Content-Type"]
+ elif response.status_code == 400:
+ raise Exception(f"Bad Request {response.text}")
+ else:
+ raise Exception(
+ f"request failed with status code {response.status_code} and message"
+ f" {response.text}"
+ )
+
+ return [result]
+
+
+JobologyProfilesWarehouse = Warehouse(
+ name="Jobology Candidate",
+ data_type=DataType.profile,
+ read=WarehouseReadAction(
+ parameters=ReadProfilesParameters,
+ function=read,
+ ),
+)