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:
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 = {}
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'
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'
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
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
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."
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 = {}