May 12, 2014

Extracting stats from the Direct Invoice API.

Our friends at Direct Invoice have done a good job with their recent API release. All useful operations on your account can be done through it.

In this article I'll show you how to do a simple task : compute your revenue by customer. It'll be easy. I promise.

Tools

To do so I'll use Ruby and HTTParty. And don't forget that you must party hard when you use the latter.

Listing our invoices

Let's create a small client class. It has only an API key instance variable. The HTTParty module has been included so we have access to all its goodness.

The base_uri is set to DI's endpoint URI :

class DirectInvoice
  include HTTParty

  attr_reader :api_key

  base_uri 'https://direct-invoice.com/api/v1'

  def initialize(api_key)
    @api_key = api_key
  end
end

Now we will create two methods : the first to retrieve all invoices, the second to retieve all companies (customers). We need to be able to get the companies because invoices don't come with their company name (at the moment).

class DirectInvoice
  [...]

  def invoices
    self.class.get('/invoices.json', {
      :query => {
        :api_key  => api_key,
        :per_page => 10_000
      }
    })
  end

  def companies
    self.class.get('/companies.json', {
      :query => {
        :api_key  => api_key,
        :per_page => 10_000
      }
    })
  end
end

Note that I set the per_page to 10000 in order to get all invoices in raw. And we can now use our client to get two arrays with the invoices and the companies :

direct_invoice = DirectInvoice.new(ENV['DI_API_KEY'])

invoices  = direct_invoice.invoices
companies = direct_invoice.companies

You noticed that the secret key is stored in a environment variable.

As we will also need the company names, let's create a Hash in which the key is the company number and where the value is the name :

company_names = {}

companies.each do |company|
  company_names[company['id']] = company['name']
end

Grouping invoices per customer

Ruby has a simple built-in method to group a collection against a block :

invoice_groups = invoices.group_by do |invoice|
  invoice['company_id']
end

Preparing the data

We will need the total invoiced amount :

total = invoices.inject(0.0) { |s, i| s += i['total'] }

After that we keep only the minimum information : the company name, the total invoiced amount for this company and the percentage of the total it represents. An Array of Hashes will be perfect for that :

results = invoice_groups.collect do |company_id, invoices|
  total_amount = invoices.inject(0.0) { |s, i| s += i['total'] }

  {
    :company_name => company_names[company_id],
    :total_amount => total_amount,
    :sharing      => (total_amount / total * 100).round(2)
  }
end.sort_by { |r| r[:total_amount] }.reverse

At the end we sort results by descending order of invoiced amount.

Building a CSV

The standard Ruby CSV library makes that an easy task too :

CSV.open(File.join('data', 'revenue_per_customer.csv'), 'wb') do |csv|
  results.each do |result|
    csv << [
      result[:company_name],
      result[:total_amount],
      result[:sharing]
    ]
  end
end

Done!

If you run the script, you will get a three-column CSV file. You can of course find the code on Github.

I have heard that Direct Invoice will release some tagging features soon : revenue per tag would be great metrics to implement too !

Vous voulez travailler avec moi ?

Je suis développeur et consultant sur des projets informatiques dans ma société, Phonoid. Avec mes amis, nous y développons des solutions sur mesure pour nos clients. Nous travaillons également sur nos futurs produits.