resp = api.get('custom_fields/lead')
available_custom_fieldnames = [x['name'] for x in resp['data']]
new_custom_fieldnames = [
    x for x in
    [y.split('.', 1)[1] for y in c.fieldnames if y.startswith('custom.')]
    if x not in available_custom_fieldnames
]

if new_custom_fieldnames:
    if args.create_custom_fields:
        for field in new_custom_fieldnames:
            if args.confirmed:
                api.post('custom_fields/lead',
                         data={
                             'name': field,
                             'type': 'text'
                         })
            available_custom_fieldnames.append(field)
            logging.info('added new custom field "%s"' % field)
    else:
        logging.error('unknown custom fieldnames: %s' % new_custom_fieldnames)
        sys.exit(1)

logging.debug('avaliable custom fields: %s' % available_custom_fieldnames)

updated_leads = 0
new_leads = 0
skipped_leads = 0

for r in c:
Example #2
0
                destination_lead = last_lead
                source_lead = lead
            else:
                destination_lead = lead
                source_lead = last_lead

            print 'Duplicate (preferring 1st one: %s)' % prefer_last_lead
            print last_lead
            print lead
            print ''

            if args.confirmed:

                # Merge the leads using the 'Merge Leads' API endpoint
                api.post('lead/merge', data={
                    'source': source_lead['id'],
                    'destination': destination_lead['id'],
                })
                leads_merged_this_page += 1
                total_merged += 1

                last_lead = destination_lead
                continue

        last_lead = lead

    # In order to make sure we don't skip any possible duplicates at the per-page boundry, we subtract offset
    # by one each time so there's an overlap. We also subtract the number of leads merged since those no longer exist.
    offset += max(0, len(leads) - 1 - leads_merged_this_page)
    has_more = resp['has_more']

print 'Done; %d merges made' % total_merged
assert any(x in ('company', 'lead_id') for x in c.fieldnames), \
    'ERROR: column "company" or "lead_id" is not found'


api = CloseIO_API(args.api_key, development=args.development)

resp = api.get('custom_fields/lead')
available_custom_fieldnames = [x['name'] for x in resp['data']]
new_custom_fieldnames = [x for x in [y.split('.', 1)[1] for y in c.fieldnames if y.startswith('custom.')]
                         if x not in available_custom_fieldnames]

if new_custom_fieldnames:
    if args.create_custom_fields:
        for field in new_custom_fieldnames:
            if args.confirmed:
                api.post('custom_fields/lead', data={'name': field, 'type': 'text'})
            available_custom_fieldnames.append(field)
            logging.info('added new custom field "%s"' % field)
    else:
        logging.error('unknown custom fieldnames: %s' % new_custom_fieldnames)
        sys.exit(1)

logging.debug('avaliable custom fields: %s' % available_custom_fieldnames)

updated_leads = 0
new_leads = 0
skipped_leads = 0

for r in c:
    payload = {}
Example #4
0
            skip += len(results)

        for result in search_results:
            if result["display_name"] == val["name"]:
                dupe = True
                break

    while retries > 0:
        if dupe:
            dupes_cnt += 1
            warning("Duplicate - not importing: %s" % val["name"])
            break

        try:
            retries -= 1
            api.post("lead", val)
            retries = 0
            success_cnt += 1
        except closeio_api.APIError, err:
            warning('An error occurred while saving "%s"' % key)
            warning(err)
            retries = 0
        except ConnectionError, e:
            warning("Connection error occurred, retrying... (%d/5)" % retries)
            if retries == 0:
                raise
            time.sleep(2)

    cnt += 1
    if cnt > import_count:
        warning("Warning: count overflow")
def run(api_key, confirmed, development=False, use_existing_contact=False, new_contact_name='', phones_custom_field='all phones', emails_custom_field='all emails'):
    """
    After an import from a different CRM, for all leads, move emails and phones that were put in
    in a lead custom field to the lead's first contact (if--use_existing_contact flag was used)
    or create a new contact.
    """

    print 'confirmed:', `confirmed`
    print 'phones_custom_field:', `phones_custom_field`
    print 'emails_custom_field:', `emails_custom_field`
    print 'use_existing_contact:', `use_existing_contact`

    api = CloseIO_API(api_key, development=development)
    has_more = True
    offset = 0

    while has_more:

        # Get a page of leads
        resp = api.get('lead', data={
            'query': '"custom.Source CRM":* not "custom.Migration completed":* sort:created',
            '_skip': offset,
            '_fields': 'id,display_name,name,contacts,custom',
        })
        leads = resp['data']

        for lead in leads:
            contacts = lead['contacts']
            custom = lead['custom']

            company_emails = custom.get(emails_custom_field, '')
            company_phones = custom.get(phones_custom_field, '')

            if not company_phones and not company_emails:
                continue

            if company_emails :
                if company_emails.startswith('["'):
                    company_emails = company_emails[2:-2].split('", "')
                else:
                    company_emails = [company_emails]

            if company_phones:
                if company_phones.startswith('["'):
                    company_phones = company_phones[2:-2].split('", "')
                else:
                    company_phones = [company_phones]

            if contacts and use_existing_contact:
                contact = contacts[0]
            else:
                contact = {
                    'lead_id': lead['id'],
                    'phones': [],
                    'emails': []
                }
                if new_contact_name:
                    contact['name'] = new_contact_name


            for pn in company_phones:
                contact['phones'].append({ 'type': 'office', 'phone': pn })
            for e in company_emails:
                contact['emails'].append({ 'type': 'office', 'email': e })

            print 'Lead:', lead['id'], lead['name'].encode('utf8')
            print 'Emails:', `custom.get(emails_custom_field)`, ' => ', `company_emails`
            print 'Phones:', `custom.get(phones_custom_field)`, ' => ', `company_phones`

            try:
                if contact.get('id'):
                    print 'Updating an existing contact', contact['id']
                    if confirmed:
                        api.put('contact/%s' % contact['id'], data={
                            'phones': contact['phones'],
                            'emails': contact['emails'],
                        })
                else:
                    print 'Creating a new contact'
                    if confirmed:
                        api.post('contact', data=contact)
                print 'Payload:', contact
                if confirmed:
                    api.put('lead/%s' % lead['id'], data={
                        'custom.Migration completed': 'Yes'
                    })
            except APIError as e:
                print e
                print 'Payload:', contact
                if confirmed:
                    api.put('lead/%s' % lead['id'], data={
                        'custom.Migration completed': 'skipped'
                    })

            print ''

        if not confirmed:
            # If we don't actually update the "Migration completed" custom field,
            # we need to paginate
            offset += len(leads)

        has_more = resp['has_more']

    print 'Done'
Example #6
0
                break
            skip += limit
        for result in search_results:
            if result['display_name'] == val['name']:
                dupe = True
                break

    while retries > 0:
        if dupe:
            dupes_cnt += 1
            print 'Duplicate - not importing: %s' % val['name']
            break

        try:
            retries -= 1
            api.post('lead', val)
            retries = 0
            success_cnt += 1
        except APIError, err:
            print 'An error occurred while saving "%s"' % key
            print err
            retries = 0
        except ConnectionError, e:
            print 'Connection error occurred, retrying... (%d/5)' % retries
            if retries == 0:
                raise
            time.sleep(2)

    cnt += 1
    if cnt > import_count:
        print 'Warning: count overflow'
Example #7
0
                    if statusLabelOrder[lead["status_label"]]>statusLabelOrder[combinedLeads[highestRankingLeadId]["status_label"]]:
                        highestRankingLeadId = leadId
    if stopMatch:
        continue
    idlist.remove(highestRankingLeadId)
    for sourceId in idlist:
        if sourceId not in alreadyMergedIds:
            printLeadRelevantMatchingData(sourceId,match["Type"])
            print "======>>"
            printLeadRelevantMatchingData(highestRankingLeadId,match["Type"])
            choice = raw_input("Please type y for merging > ")
            if choice == 'y' :
                print "merged"
                # Merge the leads using the 'Merge Leads' API endpoint
                api.post('lead/merge', data={
                    'source': sourceId,
                    'destination': highestRankingLeadId,
                })
            alreadyMergedIds.append(sourceId)
            print ""
            print ""
            print ""
            print ""
            print ""
            print ""
            print ""
            print ""
            print ""

for index in missingStatusLabels:
    print "please remove/replace the following status labels"
    print "leadId: "+index
Example #8
0
def run_import(api_key, list_type):

	import_status = ''
	api = CloseIO_API(api_key)

	# Try API Key
	try:
		test_api_key = api.get('me')
	except:
		import_status = 'bad_api_key'
		return import_status

	### Get Close.io Custom Fields
	print "...Getting Current Custom Fields"
	current_custom_fields = {}
	has_more = True
	offset = 0

	while has_more:
		resp = api.get('custom_fields/lead', params={ '_skip': offset, '_fields': 'id,name' })
		for field in resp['data']:
			current_custom_fields[field['name']] = field['id']
		offset += len(resp['data'])
		has_more = resp['has_more']

	### Create Custom Fields
	print "...Creating Any Missing Custom Fields"

	new_custom_fields = [
		{
    		"name": "Lead Source (Sample)",
    		"type": "text"
		},
		{
    		"name": "Industry (Sample)",
    		"type": "text"
		},
		{
			"name": "List Type (Sample)",
			"type": "text"
		}
	]

	custom_field_ids = []

	for custom_field in new_custom_fields:
		if custom_field['name'] in current_custom_fields:
			custom_field_ids.append("custom.{}".format(current_custom_fields[custom_field['name']]))
		else:
			try:
				create_custom_field = api.post('custom_fields/lead', data=custom_field)
				custom_field_ids.append("custom.{}".format(create_custom_field['id']))
				print "... {} Custom Field added".format(custom_field['name'])
			except:
				import_status = 'custom_field_error'
				return import_status
				break

	### Import Sample Leads
	print "... Creating Sample Leads"
	sample_lead_data = generate_lead_data(custom_field_ids=custom_field_ids, list_type=list_type)

	for lead in sample_lead_data:
		try:
			lead = api.post('lead', data=lead)
			print "... Importing {}".format(lead['name'])
		except:
			continue

	### Get Current Close.io Smart views
	print "...Getting Current Smart Views"
	current_smart_views = {}
	has_more = True
	offset = 0

	while has_more:
		resp = api.get('saved_search', params={ '_skip': offset, '_fields': 'id,name' })
		for query in resp['data']:
			current_smart_views[query['name']] = query['id']
		offset += len(resp['data'])
		has_more = resp['has_more']
		
	### Create Smart Views
	print "...Creating Any Missing Smart Views"
	smart_view_queries = [
		{
			'name': '[SAMPLE] {} Leads w/ Phone and Email'.format(list_type),
			'query': '"custom.Lead Source (Sample)":"Sample Lead Importer" "custom.List Type (Sample)":"{}" has:phone_numbers has:email_addresses sort:display_name'.format(list_type)
		},
		{
			'name': '[SAMPLE] {} Sample Leads'.format(list_type),
			'query': '"custom.Lead Source (Sample)":"Sample Lead Importer" "custom.List Type (Sample)":"{}" sort:display_name'.format(list_type)
		}
	]

	for query in smart_view_queries:
		if query['name'] not in current_smart_views:
			try:
				create_smart_view = api.post('saved_search', data=query)
				print "... {} Smart View added".format(query['name'])
			except:
				import_status = 'smartview_create_error'
				return import_status
				break

	import_status = 'https://app.close.io/search/%22custom.Lead%20Source%20(Sample)%22%3A%22Sample%20Lead%20Importer%22%20has%3Aphone_numbers%20has%3Aemail_addresses/'

	return import_status
Example #9
0
statuses_ids = set([x['status_id'] for x in leads_to_transfer])
for status_id in statuses_ids:
    status = api.get('status/lead/' + status_id)
    status_map[status['id']] = status['label']

# custom fields
resp = api.get('custom_fields/lead')
source_custom_fieldnames = [x['name'] for x in resp['data']]
resp = target_api.get('custom_fields/lead')
target_custom_fieldnames = [x['name'] for x in resp['data']]

new_custom_fieldnames = [
    x for x in source_custom_fieldnames if x not in target_custom_fieldnames
]
for field in new_custom_fieldnames:
    target_api.post('custom_fields/lead', data={'name': field, 'type': 'text'})
    logging.info('added new custom field "%s"' % field)

#target user ids
has_more = True
offset = 0
target_user_ids = []
while has_more:
    users = resp['data']
    for user in users:
        target_user_ids.append(user['id'])
    offset += max(0, len(users) - 1)
    has_more = resp['has_more']

for lead in leads_to_transfer:
    payload = {
                choices_data[field_name].extend(field["choices"])

            if action == "create":
                print "Error: " + field_name + " already exists.  Choose another name or use update or replace."
                sys.exit(1)
            elif field["type"] != "choices":
                print "Error: " + field_name + " does not have a choices field type."
                sys.exit(1)

    if not field_id and action in ("update", "replace"):
        print "Error: " + field_name + " not found.  Remove --update if you wish to create a new field with this name."
        sys.exit(1)

        # Only runs against the org if --confirmed is used.
        # Uses post for creating and put for update/replace
    if args.confirmed:
        if action == "create":
            api.post(
                "custom_fields/lead", data={"name": field_name, "type": "choices", "choices": choices_data[field_name]}
            )
            print "Successfully created " + field_name + "!"
        else:
            api.put("custom_fields/lead/" + field_id, data={"choices": choices_data[field_name]})
            if action == "update":
                print "Successfully updated existing values for " + field_name + "!"
            else:
                print "Successfully replaced existing values for " + field_name + "!"
    else:
        print "No problems detected with " + field_name + "!"
        print "Use --confirmed if you wish to run these changes against your Close.io org."
Example #11
0
api = CloseIO_API(args.api_key, development=args.development)

resp = api.get("custom_fields/lead")
available_custom_fieldnames = [x["name"] for x in resp["data"]]
new_custom_fieldnames = [
    x
    for x in [y.split(".", 1)[1] for y in c.fieldnames if y.startswith("custom.")]
    if x not in available_custom_fieldnames
]

if new_custom_fieldnames:
    if args.create_custom_fields:
        for field in new_custom_fieldnames:
            if args.confirmed:
                api.post("custom_fields/lead", data={"name": field, "type": "text"})
            available_custom_fieldnames.append(field)
            logging.info('added new custom field "%s"' % field)
    else:
        logging.error("unknown custom fieldnames: %s" % new_custom_fieldnames)
        sys.exit(1)

logging.debug("avaliable custom fields: %s" % available_custom_fieldnames)

updated_leads = 0
new_leads = 0
skipped_leads = 0

for r in c:
    payload = {}