Source code for parsons.bloomerang.bloomerang

import json
import requests
import logging

from parsons.utilities import check_env
from parsons.utilities.api_connector import APIConnector
from parsons.etl import Table

logger = logging.getLogger(__name__)

URI = "https://api.bloomerang.co/v2/"
URI_AUTH = "https://crm.bloomerang.co/authorize/"


[docs]class Bloomerang(object): """ Instantiate Bloomerang class `Args:` api_key: str The Bloomerang API key. Not required if the ``BLOOMERANG_API_KEY`` environmental variable is set or if the OAuth2 authentication parameters ``client_id`` and ``client_secret`` are set. client_id: str The Bloomerang client ID for OAuth2 authentication. Not required if the ``BLOOMERANG_CLIENT_ID`` env variable is set or if the ``api_key`` parameter is set. Note that the ``client_secret`` parameter must also be set in order to use OAuth2 authentication. client_secret: str The Bloomerang client secret for OAuth2 authetication. Not required if the ``BLOOMERANG_CLIENT_SECRET`` env variable is set or if the ``api_key`` parameter is set. Note that the ``client_id`` parameter must also be set in order to use OAuth2 authentication. """ def __init__(self, api_key=None, client_id=None, client_secret=None): self.api_key = check_env.check("BLOOMERANG_API_KEY", api_key, optional=True) self.client_id = check_env.check("BLOOMERANG_CLIENT_ID", client_id, optional=True) self.client_secret = check_env.check( "BLOOMERANG_CLIENT_SECRET", client_secret, optional=True ) self.uri = URI self.uri_auth = URI_AUTH self.conn = self._conn() def _conn(self): # Instantiate APIConnector with authentication credentials headers = {"accept": "application/json", "Content-Type": "application/json"} if self.api_key is not None: logger.info("Using API key authentication.") headers["X-API-KEY"] = f"{self.api_key}" elif (self.client_id is not None) & (self.client_secret is not None): logger.info("Using OAuth2 authentication.") self._generate_authorization_code() self._generate_access_token() headers["Authorization"] = f"Bearer {self.access_token}" else: raise Exception("Missing authorization credentials.") return APIConnector(uri=self.uri, headers=headers) def _generate_authorization_code(self): data = {"client_id": self.client_id, "response_type": "code"} r = requests.post(url=self.uri_auth, json=data) self.authorization_code = r.json().get("code", None) def _generate_access_token(self): data = { "client_id": self.client_id, "client_secret": self.client_secret, "grant_type": "authorization_code", "code": self.authorization_code, } r = requests.post(url=self.uri + "oauth/token", json=data) self.access_token = r.json().get("access_token", None) def _base_endpoint(self, endpoint, entity_id=None): url = f"{self.uri}{endpoint}/" if entity_id: url = url + f"{entity_id}/" return url @staticmethod def _base_pagination_params(page_number=1, page_size=50): return {"skip": page_size * (page_number - 1), "take": min(page_size, 50)} @staticmethod def _base_ordering_params(order_by=None, order_direction=None): params = {} if order_by: params["orderBy"] = order_by if order_direction: params["orderDirection"] = order_direction return params def _base_create(self, endpoint, entity_id=None, **kwargs): return self.conn.post_request( url=self._base_endpoint(endpoint, entity_id), json=json.dumps({**kwargs}) ) def _base_update(self, endpoint, entity_id=None, **kwargs): return self.conn.put_request( url=self._base_endpoint(endpoint, entity_id), json=json.dumps({**kwargs}) ) def _base_get(self, endpoint, entity_id=None, params=None): return self.conn.get_request(url=self._base_endpoint(endpoint, entity_id), params=params) def _base_delete(self, endpoint, entity_id=None): return self.conn.delete_request(url=self._base_endpoint(endpoint, entity_id))
[docs] def create_constituent(self, **kwargs): """ `Args:` **kwargs:` Fields to include, e.g., FirstName = 'Rachel'. See the Bloomerang API docs for a full list of `fields <https://bloomerang.co/features/integrations/api/rest-api#/Constituents/post_constituent>`_. # noqa """ return self._base_create("constituent", **kwargs)
[docs] def update_constituent(self, constituent_id, **kwargs): """ `Args:` constituent_id: str or int Constituent ID to update **kwargs:` Fields to update, e.g., FirstName = 'RJ'. See the Bloomerang API docs for a full list of `fields <https://bloomerang.co/features/integrations/api/rest-api#/Constituents/put_constituent__id_>`_. # noqa """ return self._base_update("constituent", entity_id=constituent_id, **kwargs)
[docs] def get_constituent(self, constituent_id): """ `Args:` constituent_id: str or int Constituent ID to get fields for `Returns:` A JSON of the entry or an error. """ return self._base_get("constituent", entity_id=constituent_id)
[docs] def delete_constituent(self, constituent_id): """ `Args:` constituent_id: str or int Constituent ID to delete """ return self._base_delete("constituent", entity_id=constituent_id)
[docs] def get_constituents( self, page_number=1, page_size=50, order_by=None, order_direction=None, last_modified=None, ): """ `Args:` page_number: int Number of the page to fetch page_size: int Number of records per page (maximum allowed is 50) order_by: str Sorts by ``Id``, ``CreatedDate``, or ``LastModifiedDate`` (default ``Id``). order_direction: str Sorts the order_by in ``Asc`` or ``Desc`` order. last_modified: str Filters to constituents last modified after the specified date (ISO-8601 format). `Returns:` A Table of the entries. """ params = self._base_pagination_params(page_number, page_size) params.update(self._base_ordering_params(order_by, order_direction)) if last_modified: params["lastModified"] = last_modified response = self._base_get("constituents", params=params) return Table(response["Results"])
[docs] def create_transaction(self, **kwargs): """ `Args:` **kwargs:` Fields to include, e.g., CreditCardType = 'Visa'. See the Bloomerang API docs for a full list of `fields <https://bloomerang.co/features/integrations/api/rest-api#/Transactions/post_transaction>`_. # noqa """ return self._base_create("transaction", **kwargs)
[docs] def update_transaction(self, transaction_id, **kwargs): """ `Args:` transaction_id: str or int Transaction ID to update **kwargs:` Fields to update, e.g., CreditCardType = 'Visa'. See the Bloomerang API docs for a full list of `fields <https://bloomerang.co/features/integrations/api/rest-api#/Transactions/put_transaction__id_>`_. # noqa """ return self._base_update("transaction", entity_id=transaction_id, **kwargs)
[docs] def get_transaction(self, transaction_id): """ `Args:` transaction_id: str or int Transaction ID to get fields for `Returns:` A JSON of the entry or an error. """ return self._base_get("transaction", entity_id=transaction_id)
[docs] def delete_transaction(self, transaction_id): """ `Args:` transaction_id: str or int Transaction ID to delete """ return self._base_delete("transaction", entity_id=transaction_id)
[docs] def get_transactions(self, page_number=1, page_size=50, order_by=None, order_direction=None): """ `Args:` page_number: int Number of the page to fetch page_size: int Number of records per page (maximum allowed is 50) order_by: str Sorts by ``Date``, ``CreatedDate``, or ``LastModifiedDate`` (default ``Date``). order_direction: str Sorts the order_by in ``Asc`` or ``Desc`` order (default ``Desc``). `Returns:` A JSON of the entry or an error. """ params = self._base_pagination_params(page_number, page_size) params.update(self._base_ordering_params(order_by, order_direction)) response = self._base_get("transactions", params=params) return Table(response["Results"])
[docs] def get_transaction_designation(self, designation_id): """ `Args:` designation_id: str or int Transaction Designation ID to get fields for `Returns:` A JSON of the entry or an error. """ return self._base_get("transaction/designation", entity_id=designation_id)
[docs] def get_transaction_designations( self, page_number=1, page_size=50, order_by=None, order_direction=None ): """ `Args:` page_number: int Number of the page to fetch page_size: int Number of records per page (maximum allowed is 50) order_by: str Sorts by ``Date``, ``CreatedDate``, or ``LastModifiedDate`` (default ``Date``). order_direction: str Sorts the order_by in ``Asc`` or ``Desc`` order (default ``Desc``). `Returns:` A JSON of the entry or an error. """ params = self._base_pagination_params(page_number, page_size) params.update(self._base_ordering_params(order_by, order_direction)) response = self._base_get("transactions/designations", params=params) return Table(response["Results"])
[docs] def create_interaction(self, **kwargs): """ `Args:` **kwargs:` Fields to include, e.g., Channel = "Email". See the Bloomerang API docs for a full list of `fields <https://bloomerang.co/features/integrations/api/rest-api#/Interactions/post_interaction>`_. # noqa """ return self._base_create("interaction", **kwargs)
[docs] def update_interaction(self, interaction_id, **kwargs): """ `Args:` interaction_id: str or int Interaction ID to update **kwargs:` Fields to update, e.g., EmailAddress = "user@example.com". See the Bloomerang API docs for a full list of `fields <https://bloomerang.co/features/integrations/api/rest-api#/Interactions/put_interaction__id_>`_. # noqa """ return self._base_update("interaction", entity_id=interaction_id, **kwargs)
[docs] def get_interaction(self, interaction_id): """ `Args:` interaction_id: str or int Interaction ID to get fields for `Returns:` A JSON of the entry or an error. """ return self._base_get("interaction", entity_id=interaction_id)
[docs] def delete_interaction(self, interaction_id): """ `Args:` interaction_id: str or int Interaction ID to delete """ return self._base_delete("interaction", entity_id=interaction_id)
[docs] def get_interactions(self, page_number=1, page_size=50): """ `Args:` page_number: int Number of the page to fetch page_size: int Number of records per page (maximum allowed is 50) `Returns:` A JSON of the entry or an error. """ params = self._base_pagination_params(page_number, page_size) response = self._base_get("interactions", params=params) return Table(response["Results"])