class crmHelper(): global dev global TIMEAMOUNT def __init__(self): # link to the crm if not dev: self.crm = Insightly(apikey="1b59c7a6-98cc-4788-b4ae-d063453e04ab") self.taglist={} self.idlist={} self.complist={} self.comptaglist={} self.noteslist={} # maps contact ids to time of contact self.notesbyidlist={} # maps note ids to time of contact self.loadContacts() self.loadNotes() self.loadTasks() self.loadCompanies() self.loadUsers() self.loadOpportunities() def loadContacts(self): # get contacts if dev: # load from file for testing self.contacts=json.load(open("crmdump.txt")) else: self.contacts = self.crm.getContacts() json.dump(self.contacts, open("crmdump.txt", "w")) # map names to ids for x in self.contacts: self.idlist[x["CONTACT_ID"]]="%s %s" % (x["FIRST_NAME"], x["LAST_NAME"]) # map names to tags for x in self.contacts: if x.has_key("TAGS"): tags=x["TAGS"] for t in tags: thistag=t["TAG_NAME"] if self.taglist.has_key(thistag): self.taglist[thistag].append(x["CONTACT_ID"]) else: self.taglist[thistag]=[] self.taglist[thistag].append(x["CONTACT_ID"]) def loadTasks(self): if dev: # load from file for testing self.tasks=json.load(open("crmtaskdump.txt")) else: self.tasks = self.crm.getTasks() json.dump(self.tasks, open("crmtaskdump.txt", "w")) def loadNotes(self): # get all notes if dev: # load from file for testing self.notes=json.load(open("crmnotedump.txt")) else: self.notes = self.crm.getNotes() json.dump(self.notes, open("crmnotedump.txt", "w")) # check we have made notes recently for who in self.idlist.keys(): # go through all contacts and work out last contact time for x in self.notes: for y in x['NOTELINKS']: # go through all of the note links name=y['CONTACT_ID'] # get the associated contact if name==who: time_added=datetime.datetime.strptime(x['DATE_UPDATED_UTC'], "%Y-%m-%d %H:%M:%S") # update time now=datetime.datetime.utcnow() elapsed = now - time_added if self.noteslist.has_key(who): if self.noteslist[who]>elapsed.days: self.noteslist[who]=elapsed.days else: self.noteslist[who]=elapsed.days # get id of recent notes for x in self.notes: time_added=datetime.datetime.strptime(x['DATE_UPDATED_UTC'], "%Y-%m-%d %H:%M:%S") # update time now=datetime.datetime.utcnow() elapsed = now - time_added if (elapsed.days * 60*60*24) + elapsed.seconds < TIMEAMOUNT: self.notesbyidlist[x['NOTE_ID']]=(elapsed.days * 60*60*24) + elapsed.seconds def loadCompanies(self): # get companies if dev: # load from file for testing self.companies=json.load(open("crmcompdump.txt")) else: self.companies = self.crm.getOrganizations() json.dump(self.companies, open("crmcompdump.txt", "w")) # map names to ids for x in self.companies: self.complist[x["ORGANISATION_ID"]]=x["ORGANISATION_NAME"] # map names to tags for x in self.companies: if x.has_key("TAGS"): tags=x["TAGS"] for t in tags: thistag=t["TAG_NAME"] if self.comptaglist.has_key(thistag): self.comptaglist[thistag].append(x["ORGANISATION_ID"]) else: self.comptaglist[thistag]=[] self.comptaglist[thistag].append(x["ORGANISATION_ID"]) def loadUsers(self): # get users if dev: # load from file for testing self.users=json.load(open("crmuserdump.txt")) else: self.users = self.crm.getUsers() json.dump(self.users, open("crmuserdump.txt", "w")) self.username={} for x in self.users: self.username[x['USER_ID']] = x['FIRST_NAME'] def getTag(self, tag): if self.taglist.has_key(tag): return(self.taglist[tag]) else: print "Tag %s not found." % tag return([]) def getEmpbyCompany(self): ret={} for x in self.contacts: comp=x['DEFAULT_LINKED_ORGANISATION'] if comp<>None: if ret.has_key(comp): ret[comp]=ret[comp]+1 else: ret[comp]=1 tabsort=sorted(ret.items(), key=lambda x: x[1]) tabsort.reverse() return(tabsort) def loadOpportunities(self): if dev: # load from file for testing self.opportunities=json.load(open("crmoppsdump.txt")) else: self.opportunities = self.crm.getOpportunities() json.dump(self.opportunities, open("crmoppsdump.txt", "w")) def getOpportunities(self): ret=[] for x in self.opportunities: id=x['OPPORTUNITY_ID'] name=x['OPPORTUNITY_NAME'] amount=x['BID_AMOUNT'] chance=x['PROBABILITY'] owner=x['OWNER_USER_ID'] details=x['OPPORTUNITY_DETAILS'] if amount==None: amount=0 if chance==None: chance=0 if details==None: details="" ret.append({'id': id, 'name' : name, 'details' : details, 'amount' : amount, 'chance' : chance, 'owner' : self.username[owner]}) return(ret) def getTag(self, tag): if self.taglist.has_key(tag): return(self.taglist[tag]) else: print "Tag %s not found." % tag return([]) def getTasks(self): ret=[] for x in self.tasks: id=x['TASK_ID'] title=x['Title'] d=x['DUE_DATE'] if d: t=datetime.datetime.strptime(d, "%Y-%m-%d %H:%M:%S") due=t.strftime('%d %b %Y') else: due="Not Set" # check if overdue now=datetime.datetime.now() if now>t: overdue=True else: overdue=False completed=x['COMPLETED'] details=x['DETAILS'] status=x['STATUS'] who=self.username[x['RESPONSIBLE_USER_ID']] if not completed: ret.append({'id': id, 'overdue': overdue, 'title': title, 'due': due, 'completed': completed, 'details': details, 'status': status, 'who': who}) return(ret) def getCompanyTag(self, tag): if self.comptaglist.has_key(tag): return(self.comptaglist[tag]) else: print "Tag %s not found." % tag return([]) def getAllTags(self): return(self.taglist.keys()) def getAllCompanyTags(self): return(self.comptaglist.keys()) def getNewContacts(self): newc=[] for x in self.contacts: time_added=datetime.datetime.strptime(x['DATE_CREATED_UTC'], "%Y-%m-%d %H:%M:%S") now=datetime.datetime.utcnow() elapsed = now - time_added if (elapsed.days * 60*60*24) + elapsed.seconds < TIMEAMOUNT: newc.append(x['CONTACT_ID']) return(newc) def getCompanieswithTag(self, tag): if self.comptaglist.has_key(tag): return(self.comptaglist[tag]) else: return([]) def getContactswithTag(self, tag): if self.taglist.has_key(tag): return(self.taglist[tag]) else: return([]) def getNewCompanies(self): newc=[] for x in self.companies: time_added=datetime.datetime.strptime(x['DATE_CREATED_UTC'], "%Y-%m-%d %H:%M:%S") now=datetime.datetime.utcnow() elapsed = now - time_added if (elapsed.days * 60*60*24) + elapsed.seconds < TIMEAMOUNT: newc.append(x['ORGANISATION_ID']) return(newc) def checkContact(self,who, days): # check we have made notes recently - return True/False and number of days since contact if self.noteslist.has_key(who): if self.noteslist[who]<=days: return(True, self.noteslist[who]) else: return(False, self.noteslist[who]) else: return(False, None) def getTagwithNoContact(self, tag, days): # return list of contacts with no comms ret=[] for p in self.taglist[tag]: (flag, d) = self.checkContact(p, days) if not flag: ret.append([p, d]) return(ret) def getNote(self, id): for x in self.notes: if x['NOTE_ID']==id: return(x) def getNewNotes(self): data=[] tabsort=sorted(self.notesbyidlist.items(), key=lambda x: x[1]) # tabsort.reverse() for x in tabsort: noteid=x[0] n=self.getNote(noteid) who=self.username[n['OWNER_USER_ID']] con="" for y in n['NOTELINKS']: name=y['CONTACT_ID'] if name<>None: con+=self.idlist[name] title=n['TITLE'] body=n['BODY'] data.append([who, con, title, body]) return(data)
class crm(): ################################ # data and methods for the crm # ################################ def __init__(self, insight_key): print "Connecting to Insightly..." # link to the crm self.crm = Insightly(apikey=insight_key) # load all contacts and orgs from crm self.load_insightly_contacts() self.load_insightly_orgs() def load_insightly_contacts(self): # load contact ids from insightly # self.ins_contacts = {} conns = self.crm.getContacts() for c in conns: self.ins_contacts["%s %s" % (c['FIRST_NAME'], c['LAST_NAME'])] = c['CONTACT_ID'] def addContact(self, dets, who): # add a new contact, also a new org if required c = {} c['CONTACT_ID'] = 0 # id=0 means add a new one c['FIRST_NAME'] = dets["first-name"] c['LAST_NAME'] = dets["last-name"] c['BACKGROUND'] = dets["summary"] # Tags for location and who owns the contact in Linked-In c['TAGS'] = [] if dets["location-country"] <> None: c['TAGS'].append( {"TAG_NAME": "Location-%s" % dets["location-country"].upper()}) c['TAGS'].append({"TAG_NAME": "LIContact-%s" % who}) # linkedIn URL c["CONTACTINFOS"] = [{ "SUBTYPE": "LinkedInPublicProfileUrl", "TYPE": "SOCIAL", "DETAIL": dets['linkedInUrl'], "LABEL": "linkedInPublicProfileUrl" }] # Add email address if we have one if dets['email'] <> None: c["CONTACTINFOS"].append({ "TYPE": "EMAIL", "DETAIL": dets['email'], "LABEL": "Work" }) # See if we can find a matching organisation c['LINKS'] = [] l = {} if self.orgs.has_key(dets['company']): c['DEFAULT_LINKED_ORGANISATION'] = self.orgs[dets['company']] l['ORGANISATION_ID'] = self.orgs[dets['company']] else: # no match, so add one l['ORGANISATION_ID'] = self.addOrg(dets['company']) # add job title l['ROLE'] = dets['title'] c['LINKS'].append(l) # add contact record to crm try: c = self.crm.addContact(c) except urllib2.HTTPError as e: print "Error adding contact." print e print json.dumps(c) sys.exit() # add to in memory list self.ins_contacts["%s %s" % (c['FIRST_NAME'], c['LAST_NAME'])] = c['CONTACT_ID'] # Update image if dets['pictureUrl'] <> None: img = urllib2.urlopen(dets['pictureUrl']).read() self.addPicture(c['CONTACT_ID'], img) def addPicture(self, id, picturestream): callREST("PUT", "/v2.1/Contacts/%s/Image/name.jpg" % str(id), picturestream) def addPicturetoName(self, name, picturestream): # add a picture to a name if self.ins_contacts.has_key(name): id = self.ins_contacts[name] self.addPicture(id, picturestream) else: print "%s - name not found in Insighly" % name def addEmailtoName(self, name, email, label="WORK"): # add an email to a name if self.ins_contacts.has_key(name): id = self.ins_contacts[name] self.addEmail(id, email, label) else: print "%s - name not found in Insighly" % name def addEmail(self, id, email, label="WORK"): # add email to an id # get the record c = self.crm.getContact(id) # add email c["CONTACTINFOS"].append({ "TYPE": "EMAIL", "DETAIL": email, "LABEL": label }) # save self.crm.addContact(c) def addPhonetoName(self, name, phone, label="WORK"): # add a phone number to a name if self.ins_contacts.has_key(name): id = self.ins_contacts[name] self.addPhone(id, phone, label) else: print "%s - name not found in Insighly" % name def addPhone(self, id, phone, label="WORK"): # add phone number to an id # get the record c = self.crm.getContact(id) # add email c["CONTACTINFOS"].append({ "TYPE": "PHONE", "DETAIL": phone, "LABEL": label }) # save self.crm.addContact(c) def addOrg(self, name): # add a new organisation c = {} c['ORGANISATION_NAME'] = name resp = self.crm.addOrganization(c) # add to list of organisations in memory self.orgs[name] = resp['ORGANISATION_ID'] # return id return (resp['ORGANISATION_ID']) def load_insightly_orgs(self): # load org ids from insightly o = self.crm.getOrganizations() self.orgs = {} for x in o: self.orgs[x['ORGANISATION_NAME']] = x['ORGANISATION_ID'] def checkDetails(self, id, name, who): # check for an existing entry if it is in step with linkedIn. # Extend later. For not it just appends a tag if missing # get contact details for supplied id contact = self.crm.getContact(id) # create tag to add for owner tag = {"TAG_NAME": "LIContact-%s" % who} # add tag if needed if contact.has_key("TAGS"): t = contact["TAGS"] if tag not in t: t.append(tag) print "Adding tag %s to %s %s" % (tag, contact['FIRST_NAME'], contact['LAST_NAME']) contact["TAGS"] = t self.crm.addContact(contact) # no Tags so add from scratch else: t = [tag] contacts["TAGS"] = t self.crm.addContact(contact)
class crm(): ################################ # data and methods for the crm # ################################ def __init__(self, insight_key): self.crm = Insightly(apikey=insight_key) self.load_insightly_contacts() self.load_insightly_orgs() def load_insightly_contacts(self): ################################### # load contact ids from insightly # ################################### self.ins_contacts = {} conns = self.crm.getContacts() for c in conns: self.ins_contacts["%s %s" % (c['FIRST_NAME'], c['LAST_NAME'])] = c['CONTACT_ID'] def addContact(self, dets, who): ################################### # add a new contact, also a new # # org if required # ################################### c = {} c['CONTACT_ID'] = 0 # id=0 means add a new one c['FIRST_NAME'] = dets["first-name"] c['LAST_NAME'] = dets["last-name"] c['BACKGROUND'] = dets["summary"] # Tags for location and who owns the contact in Linked-In c['TAGS'] = [] c['TAGS'].append( {"TAG_NAME": "Location-%s" % dets["location-country"].upper()}) c['TAGS'].append({"TAG_NAME": "LIContact-%s" % who}) c['IMAGE_URL'] = dets['pictureUrl'] linkedinurl = "https://www.linkedin.com/profile/view?%s" % dets['id'] c["CONTACTINFOS"] = [{ "SUBTYPE": "LinkedInPublicProfileUrl", "TYPE": "SOCIAL", "DETAIL": linkedinurl, "LABEL": "LinkedInPublicProfileUrl" }] # find org c['LINKS'] = [] l = {} if self.orgs.has_key(dets['company']): c['DEFAULT_LINKED_ORGANISATION'] = self.orgs[dets['company']] l['ORGANISATION_ID'] = self.orgs[dets['company']] else: c['DEFAULT_LINKED_ORGANISATION'] = self.addOrg(dets['company']) l['ORGANISATION_ID'] = self.addOrg(dets['company']) l['ROLE'] = dets['title'] c['LINKS'].append(l) print json.dumps(c, indent=3) self.crm.addContact(c) def addOrg(self, name): ################################### # add a new organisation # ################################### c = {} c['ORGANISATION_NAME'] = name resp = self.crm.addOrganization(c) return (resp['ORGANISATION_ID']) ################################### # load org ids from insightly # ################################### def load_insightly_orgs(self): o = self.crm.getOrganizations() self.orgs = {} for x in o: self.orgs[x['ORGANISATION_NAME']] = x['ORGANISATION_ID']
class crmHelper(): global dev global TIMEAMOUNT def __init__(self): # link to the crm if not dev: self.crm = Insightly(apikey="1b59c7a6-98cc-4788-b4ae-d063453e04ab") self.taglist = {} self.idlist = {} self.complist = {} self.comptaglist = {} self.noteslist = {} # maps contact ids to time of contact self.notesbyidlist = {} # maps note ids to time of contact self.loadContacts() self.loadNotes() self.loadTasks() self.loadCompanies() self.loadUsers() self.loadOpportunities() def loadContacts(self): # get contacts if dev: # load from file for testing self.contacts = json.load(open("crmdump.txt")) else: self.contacts = self.crm.getContacts() json.dump(self.contacts, open("crmdump.txt", "w")) # map names to ids for x in self.contacts: self.idlist[x["CONTACT_ID"]] = "%s %s" % (x["FIRST_NAME"], x["LAST_NAME"]) # map names to tags for x in self.contacts: if x.has_key("TAGS"): tags = x["TAGS"] for t in tags: thistag = t["TAG_NAME"] if self.taglist.has_key(thistag): self.taglist[thistag].append(x["CONTACT_ID"]) else: self.taglist[thistag] = [] self.taglist[thistag].append(x["CONTACT_ID"]) def loadTasks(self): if dev: # load from file for testing self.tasks = json.load(open("crmtaskdump.txt")) else: self.tasks = self.crm.getTasks() json.dump(self.tasks, open("crmtaskdump.txt", "w")) def loadNotes(self): # get all notes if dev: # load from file for testing self.notes = json.load(open("crmnotedump.txt")) else: self.notes = self.crm.getNotes() json.dump(self.notes, open("crmnotedump.txt", "w")) # check we have made notes recently for who in self.idlist.keys( ): # go through all contacts and work out last contact time for x in self.notes: for y in x['NOTELINKS']: # go through all of the note links name = y['CONTACT_ID'] # get the associated contact if name == who: time_added = datetime.datetime.strptime( x['DATE_UPDATED_UTC'], "%Y-%m-%d %H:%M:%S") # update time now = datetime.datetime.utcnow() elapsed = now - time_added if self.noteslist.has_key(who): if self.noteslist[who] > elapsed.days: self.noteslist[who] = elapsed.days else: self.noteslist[who] = elapsed.days # get id of recent notes for x in self.notes: time_added = datetime.datetime.strptime( x['DATE_UPDATED_UTC'], "%Y-%m-%d %H:%M:%S") # update time now = datetime.datetime.utcnow() elapsed = now - time_added if (elapsed.days * 60 * 60 * 24) + elapsed.seconds < TIMEAMOUNT: self.notesbyidlist[x['NOTE_ID']] = (elapsed.days * 60 * 60 * 24) + elapsed.seconds def loadCompanies(self): # get companies if dev: # load from file for testing self.companies = json.load(open("crmcompdump.txt")) else: self.companies = self.crm.getOrganizations() json.dump(self.companies, open("crmcompdump.txt", "w")) # map names to ids for x in self.companies: self.complist[x["ORGANISATION_ID"]] = x["ORGANISATION_NAME"] # map names to tags for x in self.companies: if x.has_key("TAGS"): tags = x["TAGS"] for t in tags: thistag = t["TAG_NAME"] if self.comptaglist.has_key(thistag): self.comptaglist[thistag].append(x["ORGANISATION_ID"]) else: self.comptaglist[thistag] = [] self.comptaglist[thistag].append(x["ORGANISATION_ID"]) def loadUsers(self): # get users if dev: # load from file for testing self.users = json.load(open("crmuserdump.txt")) else: self.users = self.crm.getUsers() json.dump(self.users, open("crmuserdump.txt", "w")) self.username = {} for x in self.users: self.username[x['USER_ID']] = x['FIRST_NAME'] def getTag(self, tag): if self.taglist.has_key(tag): return (self.taglist[tag]) else: print "Tag %s not found." % tag return ([]) def getEmpbyCompany(self): ret = {} for x in self.contacts: comp = x['DEFAULT_LINKED_ORGANISATION'] if comp <> None: if ret.has_key(comp): ret[comp] = ret[comp] + 1 else: ret[comp] = 1 tabsort = sorted(ret.items(), key=lambda x: x[1]) tabsort.reverse() return (tabsort) def loadOpportunities(self): if dev: # load from file for testing self.opportunities = json.load(open("crmoppsdump.txt")) else: self.opportunities = self.crm.getOpportunities() json.dump(self.opportunities, open("crmoppsdump.txt", "w")) def getOpportunities(self): ret = [] for x in self.opportunities: id = x['OPPORTUNITY_ID'] name = x['OPPORTUNITY_NAME'] amount = x['BID_AMOUNT'] chance = x['PROBABILITY'] owner = x['OWNER_USER_ID'] details = x['OPPORTUNITY_DETAILS'] if amount == None: amount = 0 if chance == None: chance = 0 if details == None: details = "" ret.append({ 'id': id, 'name': name, 'details': details, 'amount': amount, 'chance': chance, 'owner': self.username[owner] }) return (ret) def getTag(self, tag): if self.taglist.has_key(tag): return (self.taglist[tag]) else: print "Tag %s not found." % tag return ([]) def getTasks(self): ret = [] for x in self.tasks: id = x['TASK_ID'] title = x['Title'] d = x['DUE_DATE'] t = datetime.datetime.strptime(d, "%Y-%m-%d %H:%M:%S") due = t.strftime('%d %b %Y') # check if overdue now = datetime.datetime.now() if now > t: overdue = True else: overdue = False completed = x['COMPLETED'] details = x['DETAILS'] status = x['STATUS'] who = self.username[x['RESPONSIBLE_USER_ID']] if not completed: ret.append({ 'id': id, 'overdue': overdue, 'title': title, 'due': due, 'completed': completed, 'details': details, 'status': status, 'who': who }) return (ret) def getCompanyTag(self, tag): if self.comptaglist.has_key(tag): return (self.comptaglist[tag]) else: print "Tag %s not found." % tag return ([]) def getAllTags(self): return (self.taglist.keys()) def getAllCompanyTags(self): return (self.comptaglist.keys()) def getNewContacts(self): newc = [] for x in self.contacts: time_added = datetime.datetime.strptime(x['DATE_CREATED_UTC'], "%Y-%m-%d %H:%M:%S") now = datetime.datetime.utcnow() elapsed = now - time_added if (elapsed.days * 60 * 60 * 24) + elapsed.seconds < TIMEAMOUNT: newc.append(x['CONTACT_ID']) return (newc) def getCompanieswithTag(self, tag): if self.comptaglist.has_key(tag): return (self.comptaglist[tag]) else: return ([]) def getContactswithTag(self, tag): if self.taglist.has_key(tag): return (self.taglist[tag]) else: return ([]) def getNewCompanies(self): newc = [] for x in self.companies: time_added = datetime.datetime.strptime(x['DATE_CREATED_UTC'], "%Y-%m-%d %H:%M:%S") now = datetime.datetime.utcnow() elapsed = now - time_added if (elapsed.days * 60 * 60 * 24) + elapsed.seconds < TIMEAMOUNT: newc.append(x['ORGANISATION_ID']) return (newc) def checkContact(self, who, days): # check we have made notes recently - return True/False and number of days since contact if self.noteslist.has_key(who): if self.noteslist[who] <= days: return (True, self.noteslist[who]) else: return (False, self.noteslist[who]) else: return (False, None) def getTagwithNoContact(self, tag, days): # return list of contacts with no comms ret = [] for p in self.taglist[tag]: (flag, d) = self.checkContact(p, days) if not flag: ret.append([p, d]) return (ret) def getNote(self, id): for x in self.notes: if x['NOTE_ID'] == id: return (x) def getNewNotes(self): data = [] tabsort = sorted(self.notesbyidlist.items(), key=lambda x: x[1]) # tabsort.reverse() for x in tabsort: noteid = x[0] n = self.getNote(noteid) who = self.username[n['OWNER_USER_ID']] con = "" for y in n['NOTELINKS']: name = y['CONTACT_ID'] if name <> None: con += self.idlist[name] title = n['TITLE'] body = n['BODY'] data.append([who, con, title, body]) return (data)