insightly 0.2.8 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -6,6 +6,11 @@ This is a rest client library to handle talking to http://Insight.ly
6
6
  The official API for Insigh.ly was released on August 12, 2012. This library is in the very early stages of implementing access to everything expose in
7
7
  that API. The focus is primarily on opportunities and tasks.
8
8
 
9
+ Freedom isn't Free - Neither is the API
10
+ ===========
11
+
12
+ You have to be a paying customer of Insight.ly to use the API. If you are on a free plan, then it will give you 401 errors when you try to do anything with the API
13
+
9
14
  Getting Started
10
15
  =========
11
16
 
@@ -1,17 +1,20 @@
1
+ #METODO need to be able to delete records
2
+ #METODO create a script that can talk to the remote insightly install and confirm that everything still workd
3
+ #METODO re-write all the tests so that they store local data to work against
1
4
  #METODO contacts allow you to set special dates to remember - can we access that via api?
2
- #METODO It should have a method for converting date/time to the Insightly format
3
5
  #METODO custom fields expect text,drop down, or date - add better handling (text should cast to_s)
4
6
  #METODO contact infos should auto filter out duplicate entries
5
7
  #METODO all the helpers should auto filter out duplicates (links,contact info,address etc)
6
8
  #METODO only allow build to set fields that are part of the API fields
7
9
  #METODO Fix all tests so they don't require the existence of certain object ids
8
-
10
+ #METODO add support for $top $skip and Brief=true for the things that suppor them
9
11
  #METODO make a distinction between fields that you can set and save and ones you can only read - like DATE_UPDATED_UTC
12
+
10
13
  module Insightly
11
14
  class Base
12
15
 
13
16
  class << self
14
- attr_accessor :api_fields,:url_base
17
+ attr_accessor :api_fields, :url_base, :remote_id_field
15
18
  end
16
19
  self.api_fields = []
17
20
 
@@ -46,6 +49,9 @@ module Insightly
46
49
  end
47
50
  end
48
51
 
52
+ def self.date_to_insightly(date = Date.today)
53
+ date.strftime("%Y-%m-%d %H:%M:%S")
54
+ end
49
55
  def initialize(id = nil)
50
56
  @data = {}
51
57
  load(id) if id
@@ -55,8 +61,22 @@ module Insightly
55
61
  def url_base
56
62
  self.class.url_base
57
63
  end
64
+
65
+ def remote_id_field
66
+ return self.class.remote_id_field if self.class.remote_id_field
67
+ self.class.to_s.downcase.gsub("insightly::", "") + "_id"
68
+ end
69
+
58
70
  def remote_id
59
- raise ScriptError, "This should be overridden in the subclass"
71
+ self.send(remote_id_field.to_sym)
72
+ end
73
+
74
+ def remote_id=(value)
75
+ self.send("#{remote_id_field}=", value)
76
+ end
77
+
78
+ def remote_id?
79
+ self.remote_id.nil? || self.remote_id.to_s.empty? ? false : true
60
80
  end
61
81
 
62
82
  def load(id)
@@ -67,9 +87,11 @@ module Insightly
67
87
  def reload
68
88
  load(remote_id)
69
89
  end
90
+
70
91
  def to_json
71
- @data.to_json
72
- end
92
+ @data.to_json
93
+ end
94
+
73
95
  def build(data)
74
96
  @data = data
75
97
  self
@@ -123,7 +145,9 @@ module Insightly
123
145
  end
124
146
  list
125
147
  end
126
-
148
+ #def self.to_insightly_date(date)
149
+ # date.strftime("%Y-%m-%d 00:00:00")
150
+ #end
127
151
 
128
152
  end
129
153
  end
@@ -1,7 +1,8 @@
1
1
  #METODO Add support for FileAttachment xml
2
+ #METODO the load via xml and load via json do not return the same format data
2
3
  module Insightly
3
4
  class Comment < ReadWrite
4
- URL_BASE = "Comments"
5
+ self.url_base = "Comments"
5
6
 
6
7
  api_field "COMMENT_ID",
7
8
  "BODY",
@@ -41,7 +42,6 @@ module Insightly
41
42
 
42
43
  def load(id)
43
44
  load_from_xml(get_collection("#{url_base}/#{id}", :xml_raw))
44
-
45
45
  end
46
46
 
47
47
  def save
@@ -29,4 +29,4 @@ module Insightly
29
29
  item
30
30
  end
31
31
  end
32
- end
32
+ end
@@ -1,16 +1,43 @@
1
+ #METODO be able to ask the object for a list of project_ids and projects
1
2
  module Insightly
2
3
  module LinkHelper
3
4
  def links
4
5
  @data["LINKS"] ||= []
5
- @data["LINKS"].collect {|a| Insightly::Link.build(a)}
6
- end
7
- def links=(list)
8
- @data["LINKS"] = list ? list.collect {|a| fix_for_link(a).remote_data} : []
9
- end
10
- def add_link(link)
11
- @data["LINKS"] ||= []
12
- @data["LINKS"] << fix_for_link(link).remote_data
13
- true
14
- end
6
+ @data["LINKS"].collect { |a| Insightly::Link.build(a) }
7
+ end
8
+
9
+ def links=(list)
10
+ @data["LINKS"] = list ? list.collect { |a| fix_for_link(a).remote_data } : []
11
+ end
12
+
13
+ def add_link(link)
14
+ @data["LINKS"] ||= []
15
+ @data["LINKS"] << fix_for_link(link).remote_data
16
+ true
17
+ end
18
+ def contact_ids
19
+ self.links.collect { |link| link.contact_id}.compact
20
+ end
21
+ def opportunity_ids
22
+ self.links.collect { |link| link.opportunity_id}.compact
23
+ end
24
+ def organisation_ids
25
+ self.links.collect { |link| link.organisation_id}.compact
26
+ end
27
+ def contacts
28
+ self.contact_ids.collect { |id| Insightly::Contact.new(id)}
29
+ end
30
+ def opportunities
31
+ self.opportunity_ids.collect { |id| Insightly::Opportunity.new(id)}
32
+ end
33
+ def organisations
34
+ self.organisation_ids.collect { |id| Insightly::Organisation.new(id)}
35
+ end
36
+ #def project_ids
37
+ # self.links.collect { |link| link.project_id}.compact
38
+ #end
39
+ #def projects
40
+ # self.project_ids.collect { |id| Insightly::Project.new(id)}
41
+ #end
15
42
  end
16
- end
43
+ end
@@ -37,11 +37,6 @@ module Insightly
37
37
  "RESPONSIBLE_USER_ID",
38
38
  "OPPORTUNITY_DETAILS"
39
39
 
40
-
41
- def remote_id
42
- opportunity_id
43
- end
44
-
45
40
  def tasks
46
41
  list = []
47
42
  Insightly::TaskLink.search_by_opportunity_id(opportunity_id).each do |x|
@@ -44,4 +44,4 @@ module Insightly
44
44
 
45
45
  end
46
46
 
47
- end
47
+ end
@@ -1,5 +1,3 @@
1
- #METODO make it so you can just say task.add_contact(contact/contact_id) (for opportunity and organisation as well)
2
- #METODO warn them about how you have to save a task before you can link it up
3
1
  module Insightly
4
2
  class Task < ReadWrite
5
3
  include Insightly::TaskLinkHelper
@@ -61,12 +59,7 @@ module Insightly
61
59
  end
62
60
 
63
61
 
64
- def remote_id
65
- task_id
66
- end
67
-
68
62
  def fix_for_link(link)
69
- #This needs to auto set the org id on the item
70
63
  link.task_id = self.remote_id
71
64
  link
72
65
  end
@@ -1,3 +1,5 @@
1
+ #METODO add support for project
2
+
1
3
  module Insightly
2
4
  class TaskLink < ReadOnly
3
5
  self.url_base ="TaskLinks"
@@ -1,16 +1,89 @@
1
+ #METODO add support for project
1
2
  module Insightly
2
3
  module TaskLinkHelper
3
4
  def task_links
4
5
  @data["TASKLINKS"] ||= []
5
- @data["TASKLINKS"].collect {|a| Insightly::TaskLink.build(a)}
6
- end
7
- def task_links=(list)
8
- @data["TASKLINKS"] = list ? list.collect {|a| fix_for_link(a).remote_data} : []
9
- end
10
- def add_task_link(link)
11
- @data["TASKLINKS"] ||= []
12
- @data["TASKLINKS"] << fix_for_link(link).remote_data
13
- true
14
- end
6
+ @data["TASKLINKS"].collect { |a| Insightly::TaskLink.build(a) }
7
+ end
8
+
9
+ def task_links=(list)
10
+ @data["TASKLINKS"] = list ? list.collect { |a| fix_for_link(a).remote_data } : []
11
+ end
12
+
13
+ def add_task_link(link)
14
+ raise(ScriptError, "You must save the #{self.class} before adding a link.") if !remote_id
15
+ @data["TASKLINKS"] ||= []
16
+ @data["TASKLINKS"] << fix_for_link(link).remote_data
17
+ true
18
+ end
19
+ def contact_ids
20
+ list_ids_by_type("contact")
21
+ end
22
+
23
+ def contacts
24
+ list_objs_by_type("contact", Insightly::Contact)
25
+ end
26
+
27
+ def add_contact_id(contact_id)
28
+ add_by_id("contact", contact_id)
29
+ end
30
+
31
+ def add_contact(contact)
32
+ add_by_obj("contact", contact)
33
+ end
34
+
35
+
36
+
37
+ def opportunity_ids
38
+ list_ids_by_type("opportunity")
39
+ end
40
+
41
+ def opportunities
42
+ list_objs_by_type("opportunity", Insightly::Opportunity)
43
+ end
44
+
45
+ def add_opportunity_id(opportunity_id)
46
+ add_by_id("opportunity", opportunity_id)
47
+ end
48
+
49
+ def add_opportunity(opportunity)
50
+ add_by_obj("opportunity", opportunity)
51
+ end
52
+ def organisation_ids
53
+ list_ids_by_type("organisation")
54
+ end
55
+
56
+ def organisations
57
+ list_objs_by_type("organisation", Insightly::Organisation)
58
+ end
59
+
60
+ def add_organisation_id(organisation_id)
61
+ add_by_id("organisation", organisation_id)
62
+ end
63
+
64
+ def add_organisation(organisation)
65
+ add_by_obj("organisation", organisation)
66
+ end
67
+
68
+ def list_ids_by_type(type)
69
+ self.task_links.collect { |task_link| task_link.send("#{type}_id".to_sym) }.compact
70
+ end
71
+
72
+ def list_objs_by_type(type,klass)
73
+ self.send("#{type}_ids".to_sym).collect { |id| klass.new(id) }
74
+ end
75
+
76
+ def add_by_id(type, id)
77
+ return false if !id
78
+ self.save if !remote_id?
79
+ add_task_link(Insightly::TaskLink.send("add_#{type}".to_sym,id))
80
+ self.save
81
+ end
82
+
83
+ def add_by_obj(type, obj)
84
+ obj.save if !obj.remote_id?
85
+ self.send("add_#{type}_id".to_sym, obj.remote_id)
86
+ end
87
+ protected :list_ids_by_type, :list_objs_by_type, :add_by_id, :add_by_obj
15
88
  end
16
89
  end
@@ -4,7 +4,7 @@ module Insightly
4
4
  module Version
5
5
  Major = 0
6
6
  Minor = 2
7
- Tiny = 8
7
+ Tiny = 9
8
8
  String = "#{Major}.#{Minor}.#{Tiny}"
9
9
  end
10
10
  end
@@ -7,12 +7,30 @@
7
7
  require "rubygems"
8
8
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
9
9
 
10
+
11
+
10
12
  require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
11
13
  Bundler.require(:default, :testing) if defined?(Bundler)
12
14
 
15
+
16
+ require 'vcr'
17
+
18
+ VCR.configure do |c|
19
+ c.cassette_library_dir = 'cassettes'
20
+ c.hook_into :webmock
21
+ c.default_cassette_options = {:record => :new_episodes} # :new_episodes, :none, :all
22
+ c.ignore_localhost = true
23
+ # c.allow_http_connections_when_no_cassette = true
24
+ c.filter_sensitive_data('<API_KEY>') { INSIGHTLY_API_KEY }
25
+ end
26
+
27
+
28
+
13
29
  require "insightly"
14
30
  require File.expand_path(File.dirname(__FILE__) + "/../api_key")
15
31
  RSpec.configure do |config|
32
+ config.extend VCR::RSpec::Macros
33
+
16
34
  config.treat_symbols_as_metadata_keys_with_true_values = true
17
35
  config.run_all_when_everything_filtered = true
18
36
  config.filter_run :focus
@@ -23,3 +41,39 @@ RSpec.configure do |config|
23
41
  # --seed 1234
24
42
  config.order = 'random'
25
43
  end
44
+
45
+ def simple_insightly_user
46
+
47
+ VCR.use_cassette('all insightly users', :allow_playback_repeats => true) do
48
+ return Insightly::User.all.first
49
+ end
50
+
51
+ end
52
+
53
+ def simple_insightly_task(title = nil)
54
+ VCR.use_cassette('simple task', :allow_playback_repeats => true) do
55
+ task = Insightly::Task.new.build({"STATUS" => "Completed",
56
+ "RESPONSIBLE_USER_ID" => simple_insightly_user.user_id,
57
+ "OWNER_USER_ID" => simple_insightly_user.user_id,
58
+ "TITLE" => title ? title : "000 Test Task #{Date.today}"
59
+ })
60
+ task.save
61
+ return task
62
+ end
63
+
64
+ end
65
+ def simple_insightly_organisation(title = nil)
66
+ VCR.use_cassette('simple contact') do
67
+
68
+ end
69
+ end
70
+ def simple_insightly_opportunity(title = nil)
71
+ VCR.use_cassette('simple contact') do
72
+
73
+ end
74
+ end
75
+ def simple_insightly_contact(first_name = nil, last_name = nil)
76
+ VCR.use_cassette('simple contact') do
77
+
78
+ end
79
+ end
@@ -39,9 +39,25 @@ describe Insightly::Comment do
39
39
  @comment.remote_id.should == @comment.comment_id
40
40
  end
41
41
  it "should allow you to load based on an id" do
42
- #METODO This should create the comment so we can make sure it exists - once that feature is available
43
- @comment = Insightly::Comment.new(768880)
44
- @comment.comment_id.should == 768880
42
+ VCR.use_cassette('create and load comment') do
43
+ @user = Insightly::User.all.first
44
+
45
+ @task = Insightly::Task.new
46
+ @task.title = "000 Test Task"
47
+ @task.status = "Completed"
48
+ @task.owner_user_id = @user.user_id
49
+ @task.responsible_user_id = @user.user_id
50
+ @task.save
51
+ @task.comment_on("Sample Comment")
52
+ @saved_comment = @task.comments.first
53
+
54
+
55
+ @comment = Insightly::Comment.new(@saved_comment.comment_id)
56
+ @comment.comment_id.should == @saved_comment.comment_id
57
+ @comment.body.should == @saved_comment.body
58
+
59
+
60
+ end
45
61
  end
46
62
  it "should allow you to build an object from a hash" do
47
63
  comment = Insightly::Comment.new.build({"BODY" => "Other"})
@@ -77,15 +93,34 @@ describe Insightly::Comment do
77
93
  end
78
94
 
79
95
  it "should allow you to modify a comment" do
80
- @comment = Insightly::Comment.new(769043)
81
- before_body = @comment.body
82
- value = "Test Comment Edit #{Time.now}"
83
- @comment.body = value
84
- @comment.save
85
- @comment.body.should == value
86
-
87
- @comment.reload
88
- @comment.body.should == value
96
+ VCR.use_cassette('first insightly user') do
97
+ @user = Insightly::User.all.first
98
+ end
99
+ VCR.use_cassette('create and modify comment') do
100
+
101
+
102
+ @task = Insightly::Task.new
103
+ @task.title = "000 Test Task"
104
+ @task.status = "Completed"
105
+ @task.owner_user_id = @user.user_id
106
+ @task.responsible_user_id = @user.user_id
107
+ @task.save
108
+ @task.comment_on("Sample Comment")
109
+ @saved_comment = @task.comments.first
110
+
111
+ @comment = Insightly::Comment.new(@saved_comment.comment_id)
112
+ @comment.body.should == "Sample Comment"
113
+
114
+ value = "Test Comment Edit Now"
115
+ @comment.body = value
116
+ @comment.save
117
+ @comment.body.should == value
118
+ @comment.reload
119
+ @comment.body.should == value
120
+
121
+ end
122
+
123
+
89
124
  end
90
125
 
91
126