Skip to content

Commit

Permalink
feat: add more features to Bullhorn and new core action push_application
Browse files Browse the repository at this point in the history
  • Loading branch information
Abdellahitech committed Jul 11, 2024
1 parent 46881e8 commit fecf357
Show file tree
Hide file tree
Showing 12 changed files with 1,350 additions and 121 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ We invite developers to join us in our mission to bring AI and data integration
| **BambooHR** | ATS | 🎯 | | | | | | |
| **BizMerlinHR** | ATS | 🎯 | | | | | | |
| **Beetween** | ATS | 🎯 | | | | | | |
| [**Bullhorn**](./src/hrflow_connectors/connectors/bullhorn/README.md) | ATS | :white_check_mark: | *26/01/2022* | *30/10/2023* | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: |
| [**Bullhorn**](./src/hrflow_connectors/connectors/bullhorn/README.md) | ATS | :white_check_mark: | *26/01/2022* | *11/07/2024* | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: |
| [**Breezy HR**](./src/hrflow_connectors/connectors/breezyhr/README.md) | ATS | :white_check_mark: | *19/01/2022* | *01/07/2024* | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: |
| **CATS** | ATS | 🎯 | | | | | | |
| **Cegid (Meta4)** | ATS | 🎯 | | | | | | |
Expand Down
808 changes: 802 additions & 6 deletions manifest.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/hrflow_connectors/connectors/bullhorn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ This new connector will enable:
| [**Pull job list**](docs/pull_job_list.md) | Retrieves jobs from Bullhorn and writes them to Hrflow.ai Board |
| [**Pull resume attachment list**](docs/pull_resume_attachment_list.md) | retrieves profiles attachments from Bullhorn and Parses them and sends them to Hrflow.ai source |
| [**Pull profile list**](docs/pull_profile_list.md) | Retrieves profiles from Bullhorn and writes them to Hrflow.ai source |
| [**Push application**](docs/push_application.md) | Retrieves profiles from Hrflow.ai and writes their applications to the Bullhorn source |


</p>|
Expand Down
55 changes: 51 additions & 4 deletions src/hrflow_connectors/connectors/bullhorn/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from hrflow_connectors.connectors.bullhorn.schemas import BullhornProfile
from hrflow_connectors.connectors.bullhorn.utils import date_format
from hrflow_connectors.connectors.bullhorn.warehouse import (
BullhornApplicationWarehouse,
BullhornJobWarehouse,
BullhornProfileParsingWarehouse,
BullhornProfileWarehouse,
Expand Down Expand Up @@ -43,6 +44,7 @@ def get_location(info: t.Dict) -> t.Dict:
fields = {}
location_dict = {
"address1": location.get("text"),
"address2": None,
"city": fields.get("city"),
"state": fields.get("country"),
"zip": fields.get("postcode"),
Expand Down Expand Up @@ -126,7 +128,13 @@ def get_experience(experience_list: t.List[t.Dict]) -> t.List[t.Dict]:
return experience_json


def get_attachments(attachment_list: t.List[t.Dict]) -> t.List[t.Dict]:
def get_attachments(
attachment_list: t.List[t.Dict],
file_type: str = "SAMPLE",
content_type: str = "text/plain",
type: str = "cover",
format: bool = False,
) -> t.List[t.Dict]:
attachments_json = []
for hrflow_attachment in attachment_list:
url = hrflow_attachment["public_url"]
Expand All @@ -136,12 +144,15 @@ def get_attachments(attachment_list: t.List[t.Dict]) -> t.List[t.Dict]:
attachment = {
"externalID": "portfolio",
"fileContent": b64.decode(),
"fileType": "SAMPLE",
"fileType": file_type,
"name": hrflow_attachment["file_name"],
"contentType": "text/plain",
"description": "Resume file for candidate.",
"type": "cover",
"type": type,
}
if format:
attachment["format"] = "PDF"
else:
attachment["content_type"] = content_type
attachments_json.append(attachment)
return attachments_json

Expand Down Expand Up @@ -371,6 +382,28 @@ def profile_format(data: BullhornProfile) -> t.Dict:
return profile


def format_application(data: HrFlowProfile) -> t.Dict:
info = data.get("info") or {}
attachments = (
[data["attachments"][0]] if data.get("attachments") is not None else []
)
profile = {
"firstName": info.get("first_name"),
"lastName": info.get("last_name"),
"name": info.get("full_name"),
"address": get_location(info),
"email": info.get("email"),
"mobile": info.get("phone"),
}

attachment_list = get_attachments(
attachments, file_type="RESUME", type="RESUME", format=True
)

profile["attachment"] = attachment_list[0] if len(attachment_list) > 0 else {}
return profile


DESCRIPTION = "Transform Your Business with Bullhorn Staffing and Recruitment Software"

Bullhorn = Connector(
Expand Down Expand Up @@ -432,5 +465,19 @@ def profile_format(data: BullhornProfile) -> t.Dict:
target=HrFlowProfileWarehouse,
action_type=ActionType.inbound,
),
ConnectorAction(
name=ActionName.push_application,
trigger_type=WorkflowType.catch,
description=(
"Retrieves profiles from Hrflow.ai and writes their applications to the"
" Bullhorn source"
),
parameters=BaseActionParameters.with_defaults(
"WriteProfileActionParameters", format=format_application
),
origin=HrFlowProfileWarehouse,
target=BullhornApplicationWarehouse,
action_type=ActionType.outbound,
),
],
)
10 changes: 8 additions & 2 deletions src/hrflow_connectors/connectors/bullhorn/docs/pull_job_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Retrieves jobs from Bullhorn and writes them to Hrflow.ai Board
| 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_job`](../connector.py#L188) | Formatting function |
| `format` | `typing.Callable[[typing.Dict], typing.Dict]` | [`format_job`](../connector.py#L199) | 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
Expand All @@ -19,8 +19,11 @@ Retrieves jobs from Bullhorn and writes them to Hrflow.ai Board
| ----- | ---- | ------- | ----------- |
| `client_id` :red_circle: | `str` | None | Client identifier for Bullhorn |
| `client_secret` :red_circle: | `str` | None | Client secret identifier for Bullhorn |
| `password` :red_circle: | `str` | None | Passoword for Bullhorn login |
| `password` :red_circle: | `str` | None | Password for Bullhorn login |
| `username` :red_circle: | `str` | None | Username for Bullhorn login |
| `last_modified_date` :red_circle: | `str` | None | Last Modified Date in timestamp |
| `fields` :red_circle: | `str` | None | Fields to be retrieved from Bullhorn |
| `query` :red_circle: | `str` | None | the query parameters |

## Destination Parameters

Expand Down Expand Up @@ -58,6 +61,9 @@ Bullhorn.pull_job_list(
client_secret="your_client_secret",
password="your_password",
username="your_username",
last_modified_date="your_last_modified_date",
fields="your_fields",
query="your_query",
),
target_parameters=dict(
api_secret="your_api_secret",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Retrieves profiles from Bullhorn and writes them to Hrflow.ai source
| 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]` | [`profile_format`](../connector.py#L276) | Formatting function |
| `format` | `typing.Callable[[typing.Dict], typing.Dict]` | [`profile_format`](../connector.py#L287) | 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
Expand All @@ -19,7 +19,7 @@ Retrieves profiles from Bullhorn and writes them to Hrflow.ai source
| ----- | ---- | ------- | ----------- |
| `client_id` :red_circle: | `str` | None | Client identifier for Bullhorn |
| `client_secret` :red_circle: | `str` | None | Client secret identifier for Bullhorn |
| `password` :red_circle: | `str` | None | Passoword for Bullhorn login |
| `password` :red_circle: | `str` | None | Password for Bullhorn login |
| `username` :red_circle: | `str` | None | Username for Bullhorn login |

## Destination Parameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ retrieves profiles attachments from Bullhorn and Parses them and sends them to H
| 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]` | [`profile_format_parsing`](../connector.py#L254) | Formatting function |
| `format` | `typing.Callable[[typing.Dict], typing.Dict]` | [`profile_format_parsing`](../connector.py#L265) | 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
Expand All @@ -19,7 +19,7 @@ retrieves profiles attachments from Bullhorn and Parses them and sends them to H
| ----- | ---- | ------- | ----------- |
| `client_id` :red_circle: | `str` | None | Client identifier for Bullhorn |
| `client_secret` :red_circle: | `str` | None | Client secret identifier for Bullhorn |
| `password` :red_circle: | `str` | None | Passoword for Bullhorn login |
| `password` :red_circle: | `str` | None | Password for Bullhorn login |
| `username` :red_circle: | `str` | None | Username for Bullhorn login |

## Destination Parameters
Expand Down
73 changes: 73 additions & 0 deletions src/hrflow_connectors/connectors/bullhorn/docs/push_application.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Push application
`HrFlow.ai Profiles` :arrow_right: `Bullhorn Applications`

Retrieves profiles from Hrflow.ai and writes their applications to the Bullhorn source



## 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_application`](../connector.py#L385) | 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 |
| ----- | ---- | ------- | ----------- |
| `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 |
| `profile_key` :red_circle: | `str` | None | HrFlow.ai profile key |

## Destination Parameters

| Field | Type | Default | Description |
| ----- | ---- | ------- | ----------- |
| `client_id` :red_circle: | `str` | None | Client identifier for Bullhorn |
| `client_secret` :red_circle: | `str` | None | Client secret identifier for Bullhorn |
| `password` :red_circle: | `str` | None | Password for Bullhorn login |
| `username` :red_circle: | `str` | None | Username for Bullhorn login |
| `job_id` :red_circle: | `str` | None | id for the job in Bullhorn |
| `status_when_created` :red_circle: | `str` | None | The status of the application when created in Bullhorn |
| `source` | `str` | None | The source of the application to be created in Bullhorn |

:red_circle: : *required*

## Example

```python
import logging
from hrflow_connectors import Bullhorn
from hrflow_connectors.core import ReadMode


logging.basicConfig(level=logging.INFO)


Bullhorn.push_application(
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(
api_secret="your_api_secret",
api_user="your_api_user",
source_key="your_source_key",
profile_key="your_profile_key",
),
target_parameters=dict(
client_id="your_client_id",
client_secret="your_client_secret",
password="your_password",
username="your_username",
job_id="your_job_id",
status_when_created="your_status_when_created",
source="your_source",
)
)
```
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Writes a profile from Hrflow.ai Source to Bullhorn via the API
| 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_profile`](../connector.py#L149) | Formatting function |
| `format` | `typing.Callable[[typing.Dict], typing.Dict]` | [`format_profile`](../connector.py#L160) | 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
Expand All @@ -28,7 +28,7 @@ Writes a profile from Hrflow.ai Source to Bullhorn via the API
| ----- | ---- | ------- | ----------- |
| `client_id` :red_circle: | `str` | None | Client identifier for Bullhorn |
| `client_secret` :red_circle: | `str` | None | Client secret identifier for Bullhorn |
| `password` :red_circle: | `str` | None | Passoword for Bullhorn login |
| `password` :red_circle: | `str` | None | Password for Bullhorn login |
| `username` :red_circle: | `str` | None | Username for Bullhorn login |

:red_circle: : *required*
Expand Down
Loading

0 comments on commit fecf357

Please sign in to comment.