insightly 0.2.8 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
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