<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -5,7 +5,9 @@ require 'activesupport'
 require File.dirname(__FILE__) + '/harvest_entry'
 
 class Harvest
-  VERSION = '0.1.0'
+  VERSION = '0.1.1'
+  @tasks = []
+  @expenses = []
   
   def initialize(domain, email, password)
     @domain = domain
@@ -13,33 +15,64 @@ class Harvest
     @password = password
   end
 
+  # returns all the users created in this Harvest account
+  # see http://www.getharvest.com/api/people for data available
   def users(params={})
     request(&quot;/people&quot;, params).users
   end
 
+  # returns all the projects created in this Harvest account
+  # see http://www.getharvest.com/api/projects for data available
   def projects
     request(&quot;/projects&quot;).projects
   end
 
+  # returns all tasks and expenses for a given project or person
+  # in the given time period. The expenses and entries are
+  # mixed in the same array returned. Use .expense? to determine 
+  # what type it is. Reference http://www.getharvest.com/api/reporting
+  # to get data available for each type
   def report(from, to, project_and_or_person_id)
     entries = []
-    if project_and_or_person_id.has_key?(:project_id)
-      entries += request(&quot;/projects/#{project_and_or_person_id[:project_id]}/entries?from=#{from.strftime(&quot;%Y%m%d&quot;)}&amp;to=#{to.strftime(&quot;%Y%m%d&quot;)}&quot;).day_entries
-    end
     
-    if project_and_or_person_id.has_key?(:person_id)
-      entries += request(&quot;/people/#{project_and_or_person_id[:person_id]}/entries?from=#{from.strftime(&quot;%Y%m%d&quot;)}&amp;to=#{to.strftime(&quot;%Y%m%d&quot;)}&quot;).day_entries
-    end
+    %w(entries expenses).each do |type|
+      if project_and_or_person_id.has_key?(:project_id)
+        t = request(&quot;/projects/#{project_and_or_person_id[:project_id]}/#{type}?from=#{from.strftime(&quot;%Y%m%d&quot;)}&amp;to=#{to.strftime(&quot;%Y%m%d&quot;)}&quot;)
+        temp = (type == &quot;entries&quot; ? t.day_entries : t.expenses)
+        entries += temp.select {|entry| !(entries.any? {|match| match.id == entry.id })}
+      end
     
+      if project_and_or_person_id.has_key?(:person_id)
+        t = request(&quot;/people/#{project_and_or_person_id[:person_id]}/#{type}?from=#{from.strftime(&quot;%Y%m%d&quot;)}&amp;to=#{to.strftime(&quot;%Y%m%d&quot;)}&quot;)
+        temp = (type == &quot;entries&quot; ? t.day_entries : t.expenses)
+        entries += temp.select {|entry| !(entries.any? {|match| match.id == entry.id })}
+      end
+    end
     entries
   end
   
-  def tasks(task_id=nil)
-    if task_id.nil?
-      request(&quot;/tasks&quot;).tasks    
-    else
-      request(&quot;/tasks/#{task_id}&quot;)
-    end
+  # returns all tasks and caches the results
+  # see http://www.getharvest.com/api/tasks
+  def tasks
+    @tasks ||= request(&quot;/tasks&quot;).tasks
+  end
+  
+  # return a specific task
+  # see http://www.getharvest.com/api/tasks
+  def task(id)
+    self.tasks.find {|t| t.id.to_i == id.to_i}
+  end
+
+  # returns all expense categories and caches the results
+  # see http://www.getharvest.com/api/expenses
+  def expense_categories
+    @expense_categories ||= request(&quot;/expense_categories&quot;).expense_categories
+  end
+  
+  # returns a specific expense_category
+  # see http://www.getharvest.com/api/expenses
+  def expense_category(id)
+    self.expense_categories.find {|e| e.id.to_i == id.to_i}
   end
 
 private
@@ -50,6 +83,9 @@ private
     ret = nil
     Net::HTTP.new(@domain).start {|http| 
       response = http.request(request)
+      if response.class == Net::HTTPServiceUnavailable
+        raise ArgumentError, &quot;API Limit exceeded. Retry after #{response[&quot;Retry-After&quot;].to_i/60} minutes.&quot;
+      end
       ret = HarvestEntry.new(XmlSimple.xml_in(response.body))
     }
     ret</diff>
      <filename>lib/harvest.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,6 +15,15 @@ class HarvestEntry
     end
   end
   
+  def expense?
+    begin
+      self.expense_category_id
+      true
+    rescue
+      false
+    end
+  end
+  
   def method_missing(method, *args)
     method = method.to_s.gsub(&quot;_&quot;, &quot;-&quot;).to_sym
     </diff>
      <filename>lib/harvest_entry.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>5a5ef6d1f57704f4dec654dd2555c4e9ddf1cbd9</id>
    </parent>
  </parents>
  <author>
    <name>Brian Cooke</name>
    <email>bcooke@roobasoft.com</email>
  </author>
  <url>http://github.com/bricooke/harvest-ruby/commit/afcce7c82561f7c1d9c385772aa2e11bea720259</url>
  <id>afcce7c82561f7c1d9c385772aa2e11bea720259</id>
  <committed-date>2008-04-14T20:29:57-07:00</committed-date>
  <authored-date>2008-04-14T20:29:57-07:00</authored-date>
  <message>0.1.1. minimal documentation. support for expense_categories. fix duplicates reported in report. support getting the Retry-After</message>
  <tree>cfc0323dd4cc294fbe6dbc89fd1adb463d42306d</tree>
  <committer>
    <name>Brian Cooke</name>
    <email>bcooke@roobasoft.com</email>
  </committer>
</commit>
