app/jobs/competitor_crunchbase_job.rb
class CompetitorCrunchbaseJob < ApplicationJob
include Concerns::Ignorable
FUND_TYPE_KEYWORDS = {
seed: %w(seed),
preseed: %w(pre-seed preseed),
accelerator: %w(accelerator),
angel: %w(angel),
}
queue_as :default
def perform(competitor_id)
competitor = Competitor.find(competitor_id)
competitor.crunchbase_id ||= Http::Crunchbase::Organization.find_investor_id(competitor.name)
begin
competitor.save!
rescue ActiveRecord::RecordInvalid => e
DuplicateCompetitorJob.perform_later competitor.id
return
end
if competitor.angellist_startup.name != competitor.name || competitor.angellist_startup.crunchbase != competitor.crunchbase_id
competitor.al_id = nil
end
competitor.al_id ||= Http::AngelList::Startup.find_id(competitor.name, cb_id: competitor.crunchbase_id)
begin
competitor.save!
rescue ActiveRecord::RecordInvalid => e
Competitor.where(al_id: competitor.al_id).update_all al_id: nil
competitor.save!
end
cb_fund = competitor.crunchbase_fund
al_fund = competitor.angellist_startup
unless competitor.verified?
competitor.description = cb_fund.description || al_fund.description if competitor.description.blank?
competitor.location = (competitor.location || []) + (al_fund.locations || []) + (cb_fund.locations || [])
competitor.hq = cb_fund.hq
competitor.country = cb_fund.country
competitor.photo = al_fund.logo || cb_fund.image
competitor.facebook = al_fund.facebook || cb_fund.facebook
competitor.twitter = al_fund.twitter || cb_fund.twitter
competitor.domain = al_fund.url || cb_fund.url
competitor.al_url = al_fund.angellist_url
competitor.fund_type = (competitor.fund_type || []) + cb_fund.fund_types
competitor.save! if competitor.changed?
end
if competitor.description.present?
FUND_TYPE_KEYWORDS.each do |fund_type, keywords|
if keywords.any? { |w| competitor.description.downcase.include?(w) } && !competitor.fund_type.include?(fund_type.to_s)
competitor.fund_type << fund_type.to_s
end
end
end
if (team = cb_fund.team).present?
team.each do |job|
next if job.title.present? && Competitor::NON_INVESTOR_TITLE.any? { |t| job.title.downcase.include?(t) }
next unless (person = job.person).present?
investor = Investor.from_crunchbase(person.permalink)
if investor.present?
next unless investor.competitor != competitor
begin
investor.update! competitor: competitor, role: job.title, description: person.bio
rescue ActiveRecord::RecordInvalid
other = competitor.investors.where(first_name: investor.first_name, last_name: investor.last_name).first!
investor.reload.update! crunchbase_id: nil
other.update! crunchbase_id: person.permalink
investor.destroy!
InvestorCrunchbaseJob.perform_later(other.id)
else
InvestorCrunchbaseJob.perform_later(investor.id)
end
else
investor = competitor.investors.where(first_name: person.first_name, last_name: person.last_name).first
next unless investor.present?
investor.update! crunchbase_id: person.permalink
InvestorCrunchbaseJob.perform_later(investor.id)
end
end
end
al_fund.roles.each do |person|
Investor.from_angelist(person['id'])
end
if (investments = cb_fund.investments(deep: true)).present?
investments.each do |investment|
partners = (investment.partners || []).map do |partner|
Investor.from_crunchbase(partner.permalink)
end
funding_round = investment.funding_round
company = funding_round&.funded_organization
next unless funding_round.present? && company.present?
retry_record_errors do
c = competitor.companies.where(name: company.name).first
c ||= Company.where(crunchbase_id: company.permalink).first_or_create! do |c|
c.name = company.name
end
cc = c.investments.where(competitor: competitor).first_or_initialize
cc.funded_at = (investment.announced_on || funding_round.announced_on).to_date
cc.funding_type = funding_round.funding_type
cc.series = funding_round.series
cc.round_size = funding_round.money_raised_usd
if partners.present? && (investor = partners.first).present?
cc.investor = investor
cc.featured = true
end
cc.save! if cc.changed?
end
end
end
al_fund.investments.each do |investment|
startup = investment['startup']
next unless startup.present?
c = Company.where(domain: Util.parse_domain(startup['company_url'])).or(Company.where(al_id: startup['id'])).first
c ||= competitor.companies.where(name: startup['name']).first
c ||= retry_record_errors do
Company.where(al_id: startup['id']).first_or_create! do |c|
c.name = startup['name']
c.domain = startup['company_url']
end
end
c.investments.where(competitor: competitor).first_or_create!
end
end
end