def find_organization_in_pipedrive(company): # Search for the organization in Pipedrive # Try by id app.logger.debug('Trying to fetch organization data from Pipedrive with marketo_id=%s', company.id) organization = pipedrive.Organization(get_pipedrive_client(), company.id, 'marketoid') if organization.id is None: # Then name app.logger.debug('Trying to fetch organization data from Pipedrive with name=%s', company.company) organization = pipedrive.Organization(get_pipedrive_client(), company.company, 'name') if organization.id is None: # Finally Email domain app.logger.debug('Trying to fetch organization data from Pipedrive with email_domain=%s', company.website) organization = pipedrive.Organization(get_pipedrive_client(), company.website, 'email_domain') return organization
def compute_organization_in_pipedrive(organization_id): app.logger.info('Fetching organization data from Pipedrive with id=%s', str(organization_id)) organization = pipedrive.Organization(get_pipedrive_client(), organization_id) if organization.id is not None: status = 'skipped' # Use keys to avoid conflicts in field names and keys if organization.b97ac2f12d2071c4c5efbf3a89c812c970f04af1\ and organization.b97ac2f12d2071c4c5efbf3a89c812c970f04af1 in mappings.COUNTRY_TO_REGION: old_region = organization.e1cfd37b3fa5a3847f662fb7a3728c181b6dac15 new_region = mappings.COUNTRY_TO_REGION[ organization.b97ac2f12d2071c4c5efbf3a89c812c970f04af1] if new_region and new_region != old_region: organization.e1cfd37b3fa5a3847f662fb7a3728c181b6dac15 = new_region organization.save() status = 'updated' response = {'status': status} else: message = 'No organization found with id %s' % str(organization_id) app.logger.error(message) response = {'error': message} return response
def create_activity_in_pipedrive(lead_id): """ Create an activity in Pipedrive. Data to set is defined in mappings. :param lead_id: The lead id to synchronize data from :return: A custom response object containing the synchronized entity status and id """ app.logger.info('Fetching lead data from Marketo with id=%s', str(lead_id)) lead = marketo.Lead(get_marketo_client(), lead_id) if lead.id is not None: activity = pipedrive.Activity(get_pipedrive_client()) app.logger.info('New activity created') status = 'created' for pd_field in mappings.ACTIVITY_TO_LEAD: update_field(lead, activity, pd_field, mappings.ACTIVITY_TO_LEAD[pd_field]) app.logger.info('Sending lead data with id=%s to Pipedrive activity', str(lead_id)) activity.save() response = {'status': status, 'id': activity.id} else: message = 'No lead found in Marketo with id=%s' % str(lead_id) app.logger.error(message) response = {'error': message} return response
def user_name_to_user_id_or_big_bot(user_name): user_id = BIG_BOT_ID if user_name and user_name.strip(): user = pipedrive.User(sync.get_pipedrive_client(), user_name, 'name') # TODO use existing value if not found? user_id = user.id or user_id return user_id
def create_or_update_lead_in_marketo(person_id): """ Create or update a lead in Marketo. Update can be performed if the person is already associated to a lead (field marketoid is populated). If the lead is already up-to-date with the associated person, does nothing. Data to set is defined in mappings. :param person_id: The person id to synchronize data from :return: A custom response object containing the synchronized entity status and id """ app.logger.info('Fetching person data from Pipedrive with id=%s', str(person_id)) person = pipedrive.Person(get_pipedrive_client(), person_id) if person.id is not None: lead = marketo.Lead(get_marketo_client(), person.marketoid) if lead.id is None: app.logger.info('New lead created') status = 'created' else: app.logger.info('Lead data fetched from Marketo with id=%s', str(lead.id)) status = 'updated' data_changed = False for mkto_field in mappings.LEAD_TO_PERSON: data_changed = update_field( person, lead, mkto_field, mappings.LEAD_TO_PERSON[mkto_field]) or data_changed if data_changed: # Perform the update only if data has actually changed app.logger.info( 'Sending person data with id=%s to Marketo%s', str(person_id), ' with id=%s' % str(person.id) if person.id is not None else '') lead.save() if not person.marketoid or len( person.marketoid.split(',')) > 1 or int( person.marketoid) != lead.id: app.logger.info( 'Updating marketo_id=%s in Pipedrive%s', lead.id, ' (old=%s)' % person.marketoid if person.marketoid else '') person.marketoid = lead.id person.save() else: app.logger.info('Nothing to do in Marketo for lead with id=%s', lead.id) status = 'skipped' response = {'status': status, 'id': lead.id} else: message = 'No person found with id %s' % str(person_id) app.logger.error(message) response = {'error': message} return response
def create_or_update_person_in_pipedrive(lead_id): """ Create or update a person in Pipedrive. Update can be performed if the lead is already associated to a person (field pipedriveId is populated). If the person is already up-to-date with the associated lead, does nothing. Data to set is defined in mappings. :param lead_id: The lead id to synchronize data from :return: A custom response object containing the synchronized entity status and id """ app.logger.info('Fetching lead data from Marketo with id=%s', str(lead_id)) lead = marketo.Lead(get_marketo_client(), lead_id) if lead.id is not None: person = pipedrive.Person(get_pipedrive_client(), lead.pipedriveId) if person.id is None: app.logger.info('New person created') status = 'created' else: app.logger.info('Person data fetched from Pipedrive with id=%s', str(person.id)) status = 'updated' data_changed = False for pd_field in mappings.PERSON_TO_LEAD: data_changed = update_field( lead, person, pd_field, mappings.PERSON_TO_LEAD[pd_field]) or data_changed if data_changed: # Perform the update only if data has actually changed app.logger.info( 'Sending lead data with id=%s to Pipedrive%s', str(lead_id), ' for person with id=%s' % str(person.id) if person.id is not None else '') person.save() if not lead.pipedriveId or lead.pipedriveId != person.id: app.logger.info( 'Updating pipedrive_id=%s in Marketo%s', person.id, ' (old=%s)' % lead.pipedriveId if lead.pipedriveId else '') lead.pipedriveId = person.id lead.save() else: app.logger.info('Nothing to do in Pipedrive for person with id=%s', person.id) status = 'skipped' response = {'status': status, 'id': person.id} else: message = 'No lead found in Marketo with id=%s' % str(lead_id) app.logger.error(message) response = {'error': message} return response
def notify_deal_in_slack_for_note(deal_id): app.logger.info('Fetching deal data from Pipedrive with id=%s', str(deal_id)) deal = pipedrive.Deal(get_pipedrive_client(), deal_id) if deal.id is not None: encoded_deal_title = deal.title.encode('utf-8') encoded_organization_name = deal.organization.name.encode('utf-8') status_comment = pipedrive.Note(get_pipedrive_client(), deal.id, 'deal_id') payload = { 'attachments': [{ 'fallback': 'New Note Added: <{}/deal/{}|{} for {}>'.format( app.config['PD_APP_URL'], deal.id, encoded_deal_title, encoded_organization_name), 'pretext': 'New Note Added: <{}/deal/{}|{} for {}>'.format( app.config['PD_APP_URL'], deal.id, encoded_deal_title, encoded_organization_name), 'fields': [{ 'value': html2text.html2text(status_comment.content) if status_comment and status_comment.content else '', 'short': False }], 'mrkdwn_in': ['fields'] }] } content = post_message_on_slack(payload) response = {'content': content} else: message = 'No deal found with id %s' % str(deal_id) app.logger.error(message) response = {'error': message} return response
def create_activity_in_pipedrive_for_email_sent(lead_id): """ Create one or several activities for one or several Email sent in Pipedrive. Data to set is defined in mappings. :param lead_id: The lead id to synchronize data from :return: A custom response object containing the synchronized entity statuses and ids """ app.logger.info('Fetching lead data from Marketo with id=%s', str(lead_id)) lead = marketo.Lead(get_marketo_client(), lead_id) if lead.id is not None: mkto_activities = lead.get_activities(['Send Email']) statuses = [] ids = [] for mkto_activity in mkto_activities: activity = pipedrive.Activity(get_pipedrive_client()) app.logger.info('New activity created') statuses.append('created') for pd_field in mappings.ACTIVITY_TO_EMAIL_SENT: update_field(lead, activity, pd_field, mappings.ACTIVITY_TO_EMAIL_SENT[pd_field]) activity.subject = mkto_activity['primaryAttributeValue'] email_content = get_marketo_client().get_asset( 'email', mkto_activity['primaryAttributeValueId'], 'content') if email_content and 'value' in email_content: content_text = [ value['value'] for value in email_content['value'] if value['type'] == 'Text' ] if content_text: activity.note = content_text[0] app.logger.info( 'Sending lead activities with id=%s to Pipedrive activities', str(lead_id)) activity.save() ids.append(activity.id) response = {'status': statuses, 'id': ids} else: message = 'No lead found in Marketo with id=%s' % str(lead_id) app.logger.error(message) response = {'error': message} return response
def delete_person_in_pipedrive(lead_pipedrive_id): """ Delete a person in Pipedrive. :param lead_pipedrive_id: The lead related person id to delete :return: A custom response object containing the synchronized entity status and id """ app.logger.info('Deleting person in Pipedrive with id=%s', str(lead_pipedrive_id)) person = pipedrive.Person(get_pipedrive_client(), lead_pipedrive_id, 'id', False) person_id = person.delete() if person_id: response = {'status': 'deleted', 'id': person_id} else: message = 'Could not delete person in Pipedrive with id=%s' % str( lead_pipedrive_id) app.logger.error(message) response = {'error': message} return response
def notify_deal_in_slack_for_status(deal_id): app.logger.info('Fetching deal data from Pipedrive with id=%s', str(deal_id)) deal = pipedrive.Deal(get_pipedrive_client(), deal_id) if deal.id is not None: encoded_deal_title = deal.title.encode('utf-8') encoded_organization_name = deal.organization.name.encode('utf-8') status_comment = pipedrive.Note(get_pipedrive_client(), deal.id, 'deal_id') payload = { 'attachments': [{ 'fallback': 'New Deal {}: <{}/deal/{}|{} for {}>'.format( deal.status, app.config['PD_APP_URL'], deal.id, encoded_deal_title, encoded_organization_name), 'pretext': 'New Deal {}: <{}/deal/{}|{} for {}>'.format( deal.status, app.config['PD_APP_URL'], deal.id, encoded_deal_title, encoded_organization_name), 'text': '{} has {} the deal {}'.format(deal.owner.name.encode('utf-8'), deal.status, encoded_deal_title), 'color': 'good' if deal.status == 'won' else 'danger', 'fields': [{ 'title': '', 'value': ('*Company*: {}\n' '*Value*: {} {}\n' '*Pipeline*: {}').format( encoded_organization_name, deal.currency, deal.value, pipedrive.Pipeline(get_pipedrive_client(), deal.pipeline_id).name), 'short': True }, { 'title': '', 'value': ('*Start Date*: {}\n' '*Duration (month)*: {}\n' '*Won Time*: {}').format(deal.contract_start_date, deal.duration, deal.won_time), 'short': True }, { 'title': 'Comments', 'value': html2text.html2text(status_comment.content) if status_comment and status_comment.content else '', 'short': False }], 'mrkdwn_in': ['fields'] }] } content = post_message_on_slack(payload) if deal.status == 'won' and deal.value >= 100000: payload['channel'] = '#general' content = post_message_on_slack(payload) response = {'content': content} else: message = 'No deal found with id %s' % str(deal_id) app.logger.error(message) response = {'error': message} return response
def create_or_update_opportunity_in_marketo(deal_id): """ Create or update an opportunity in Marketo. Update can be performed if the opportunity external id comes from the deal id. If the opportunity is already up-to-date with the associated deal, does nothing. Role cannot be updated (the only updateable field would be isPrimary). Data to set is defined in mappings. :param deal_id: The deal id to synchronize data from :return: A custom response object containing the synchronized entity status and id """ app.logger.info('Fetching deal data from Pipedrive with id=%s', str(deal_id)) deal = pipedrive.Deal(get_pipedrive_client(), deal_id) if deal.id is not None: # Filter deals pipeline = pipedrive.Pipeline(get_pipedrive_client(), deal.pipeline_id) if pipeline.name in mappings.PIPELINE_FILTER_NAMES: # Opportunity opportunity_external_id = marketo.compute_external_id( 'deal', deal.id) opportunity = marketo.Opportunity(get_marketo_client(), opportunity_external_id, 'externalOpportunityId') data_changed = False if opportunity.id is None: app.logger.info('New opportunity created') opportunity_status = 'created' opportunity.externalOpportunityId = opportunity_external_id data_changed = True else: app.logger.info( 'Opportunity data fetched from Marketo with id=%s/external_id=%s', str(opportunity.id), opportunity_external_id) opportunity_status = 'updated' for mkto_field in mappings.OPPORTUNITY_TO_DEAL: data_changed = update_field(deal, opportunity, mkto_field, mappings.OPPORTUNITY_TO_DEAL[mkto_field]) \ or data_changed if data_changed: # Perform the update only if data has actually changed app.logger.info( 'Sending deal data with id=%s to Marketo%s', str(deal_id), ' for opportunity with id=%s/external_id=%s' % (str(opportunity.id), opportunity_external_id) if opportunity.id is not None else '') opportunity.save() else: app.logger.info( 'Nothing to do in Marketo for opportunity with id=%s/external_id=%s', opportunity.id, opportunity_external_id) opportunity_status = 'skipped' response = { 'opportunity': { 'status': opportunity_status, 'id': opportunity.id } } # Role if deal.contact_person and deal.contact_person.marketoid: # Ensure person has been synced # TODO create if not? # Role will automatically be created or updated using these 3 fields ("dedupeFields") role = marketo.Role(get_marketo_client()) role.externalOpportunityId = opportunity.externalOpportunityId role.leadId = deal.contact_person.marketoid role.role = deal.champion.title if deal.champion and deal.champion.title else 'Default Role' role.isPrimary = deal.champion and deal.champion.marketoid == role.leadId app.logger.info( 'Sending deal data with id=%s to Marketo for role with (externalOpportunityId=%s, leadId=%s, role=%s)', str(deal_id), role.externalOpportunityId, role.leadId, role.role) role.save() response['role'] = {'id': role.id} else: message = 'Deal synchronization with id=%s not enabled for pipeline=%s' % ( deal_id, pipeline.name) app.logger.info(message) response = {'status': 'skipped', 'message': message} else: message = 'No deal found in Pipedrive with id=%s' % str(deal_id) app.logger.error(message) response = {'error': message} return response
def create_or_update_company_in_marketo(organization_id): """ Create or update a company in Marketo. Update can be performed if the company is already associated to an organization (organization field marketoid is populated) or if the external id comes from the organization id or if they share the same name. If the company is already up-to-date with the associated organization, does nothing. Data to set is defined in mappings. :param organization_id: The organization id to synchronize data from :return: A custom response object containing the synchronized entity status and id """ app.logger.info('Fetching organization data from Pipedrive with id=%s', str(organization_id)) organization = pipedrive.Organization(get_pipedrive_client(), organization_id) if organization.id is not None: company = find_company_in_marketo(organization) data_changed = False if company.id is None: app.logger.info('New company created') status = 'created' external_id = marketo.compute_external_id('organization', organization.id) company.externalCompanyId = external_id data_changed = True else: app.logger.info( 'Company data fetched from Marketo with id=%s/external_id=%s', str(company.id), company.externalCompanyId) status = 'updated' for mkto_field in mappings.COMPANY_TO_ORGANIZATION: data_changed = update_field(organization, company, mkto_field, mappings.COMPANY_TO_ORGANIZATION[mkto_field]) \ or data_changed if data_changed: # Perform the update only if data has actually changed app.logger.info( 'Sending organization data with id=%s to Marketo%s', str(organization_id), ' with id=%s/external_id=%s' % (str(company.id), company.externalCompanyId) if company.id is not None else '') company.save() if not organization.marketoid \ or len(organization.marketoid.split(',')) > 1 or int(organization.marketoid) != company.id: app.logger.info( 'Updating marketo_id=%s in Pipedrive%s', organization.id, ' (old=%s)' % organization.marketoid if organization.marketoid else '') organization.marketoid = company.id organization.save() else: app.logger.info( 'Nothing to do in Marketo for company with id=%s/external_id=%s', company.id, company.externalCompanyId) status = 'skipped' response = { 'status': status, 'id': company.id, 'externalId': company.externalCompanyId } else: message = 'No organization found with id %s' % str(organization_id) app.logger.error(message) response = {'error': message} return response
def user_name_to_user_id(user_name): user_id = None if user_name and user_name.strip(): user = pipedrive.User(sync.get_pipedrive_client(), user_name, 'name') user_id = user.id return user_id