insightly 0.1.1
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/LICENSE +24 -0
- data/README.rdoc +53 -0
- data/insightly.gemspec +20 -0
- data/lib/insightly.rb +14 -0
- data/lib/insightly/base.rb +123 -0
- data/lib/insightly/comment.rb +56 -0
- data/lib/insightly/configuration.rb +81 -0
- data/lib/insightly/opportunity.rb +115 -0
- data/lib/insightly/opportunity_state_reason.rb +46 -0
- data/lib/insightly/read_only.rb +52 -0
- data/lib/insightly/read_write.rb +44 -0
- data/lib/insightly/task.rb +72 -0
- data/lib/insightly/task_link.rb +22 -0
- data/lib/insightly/version.rb +10 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/unit/base_spec.rb +6 -0
- data/spec/unit/comment_spec.rb +92 -0
- data/spec/unit/configuration_spec.rb +50 -0
- data/spec/unit/opportunity_spec.rb +180 -0
- data/spec/unit/opportunity_state_reason_spec.rb +77 -0
- data/spec/unit/task_link_spec.rb +47 -0
- data/spec/unit/task_spec.rb +135 -0
- metadata +182 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
module Insightly
|
2
|
+
class OpportunityStateReason < ReadOnly
|
3
|
+
self.url_base = "OpportunityStateReasons"
|
4
|
+
STATES = ["Abandoned", "Lost", "Open", "Suspended", "Won"]
|
5
|
+
api_field "STATE_REASON_ID",
|
6
|
+
"FOR_OPPORTUNITY_STATE",
|
7
|
+
"STATE_REASON"
|
8
|
+
|
9
|
+
|
10
|
+
def self.find_by_state(state)
|
11
|
+
list = []
|
12
|
+
OpportunityStateReason.all.each.each do |x|
|
13
|
+
if x.for_opportunity_state && x.for_opportunity_state.match(state)
|
14
|
+
list << x
|
15
|
+
end
|
16
|
+
end
|
17
|
+
list
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find_by_state_reason(state,reason)
|
21
|
+
OpportunityStateReason.all.each.each do |x|
|
22
|
+
return x if x.for_opportunity_state && x.for_opportunity_state.match(state) && x.state_reason == reason
|
23
|
+
end
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
STATES.each do |state|
|
27
|
+
|
28
|
+
(
|
29
|
+
class << self;
|
30
|
+
self;
|
31
|
+
end).instance_eval do
|
32
|
+
define_method state.downcase.to_sym do |*args|
|
33
|
+
reason = args.first
|
34
|
+
if reason
|
35
|
+
OpportunityStateReason.find_by_state_reason(state,reason)
|
36
|
+
else
|
37
|
+
OpportunityStateReason.find_by_state(state)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Insightly
|
2
|
+
class ReadOnly < Base
|
3
|
+
def initialize
|
4
|
+
@data = {}
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
def url_base
|
9
|
+
self.class.const_get(:URL_BASE)
|
10
|
+
end
|
11
|
+
|
12
|
+
def build(data)
|
13
|
+
@data = data
|
14
|
+
self
|
15
|
+
end
|
16
|
+
def self.build(data)
|
17
|
+
self.new.build(data)
|
18
|
+
end
|
19
|
+
def ==(other)
|
20
|
+
self.remote_data == other.remote_data
|
21
|
+
end
|
22
|
+
def remote_data
|
23
|
+
@data
|
24
|
+
end
|
25
|
+
def process(result, content_type)
|
26
|
+
puts result
|
27
|
+
if content_type == :json
|
28
|
+
JSON.parse(result.to_str)
|
29
|
+
elsif content_type == :xml
|
30
|
+
Hash.from_xml(result.to_str)
|
31
|
+
else
|
32
|
+
result.to_str
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def config
|
37
|
+
Insightly::Configuration.instantiate
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_collection(path, content_type = :json)
|
41
|
+
response = RestClient::Request.new(:method => :get,
|
42
|
+
:url => "#{config.endpoint}/#{path.to_s}",
|
43
|
+
:user => config.api_key,
|
44
|
+
:password => "",
|
45
|
+
:headers => {:accept => content_type, :content_type => content_type}).execute
|
46
|
+
process(response, content_type)
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Insightly
|
2
|
+
class ReadWrite < Base
|
3
|
+
def save
|
4
|
+
if !remote_id
|
5
|
+
@data = post_collection("#{url_base}", @data.to_json)
|
6
|
+
else
|
7
|
+
|
8
|
+
@data = put_collection("#{url_base}/#{remote_id}", @data.to_json)
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def post_collection(path, params, content_selector = :json)
|
15
|
+
if content_selector == :xml_raw
|
16
|
+
content_type = :xml
|
17
|
+
else
|
18
|
+
content_type = content_selector
|
19
|
+
end
|
20
|
+
response = RestClient::Request.new(:method => :post,
|
21
|
+
:url => "#{config.endpoint}/#{path.to_s}",
|
22
|
+
:user => config.api_key,
|
23
|
+
:password => "",
|
24
|
+
:payload => params,
|
25
|
+
:headers => {:accept => content_type, :content_type => content_type}).execute
|
26
|
+
process(response, content_selector)
|
27
|
+
end
|
28
|
+
|
29
|
+
def put_collection(path, params, content_selector = :json)
|
30
|
+
if content_selector == :xml_raw
|
31
|
+
content_type = :xml
|
32
|
+
else
|
33
|
+
content_type = content_selector
|
34
|
+
end
|
35
|
+
response = RestClient::Request.new(:method => :put,
|
36
|
+
:url => "#{config.endpoint}/#{path.to_s}",
|
37
|
+
:user => config.api_key,
|
38
|
+
:password => "",
|
39
|
+
:payload => params,
|
40
|
+
:headers => {:accept => content_type, :content_type => content_type}).execute
|
41
|
+
process(response, content_selector)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#METODO Find a way to link a task to an opportunity
|
2
|
+
|
3
|
+
module Insightly
|
4
|
+
class Task < ReadWrite
|
5
|
+
self.url_base = "Tasks"
|
6
|
+
|
7
|
+
def comments
|
8
|
+
list = []
|
9
|
+
get_collection("#{url_base}/#{task_id}/comments").each do |d|
|
10
|
+
list << Insightly::Comment.build(d)
|
11
|
+
end
|
12
|
+
list
|
13
|
+
end
|
14
|
+
def comment_on(body)
|
15
|
+
comment = Insightly::Comment.new.build({ "BODY" => body})
|
16
|
+
result = post_collection("#{url_base}/#{task_id}/comments", comment.remote_data.to_json)
|
17
|
+
comment.build(result)
|
18
|
+
end
|
19
|
+
#def comment_on(body)
|
20
|
+
# user_id = 226277
|
21
|
+
# xml_data = '<?xml version="1.0" encoding="utf-8"?><Comment xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><BODY><p>&nbsp;Hello Nurse</p></BODY><OWNER_USER_ID>226277</OWNER_USER_ID><FILE_ATTACHMENTS/></Comment>'
|
22
|
+
#
|
23
|
+
#
|
24
|
+
# post_collection("#{url_base}/#{task_id}/comments", xml_data, :xml)
|
25
|
+
#end
|
26
|
+
#
|
27
|
+
#def comments
|
28
|
+
# data = get_collection("#{url_base}/#{task_id}/Comments")
|
29
|
+
# list = []
|
30
|
+
# data.each do |x|
|
31
|
+
# end
|
32
|
+
# list
|
33
|
+
#end
|
34
|
+
|
35
|
+
def status
|
36
|
+
@data["STATUS"]
|
37
|
+
end
|
38
|
+
def status=(new_status)
|
39
|
+
@data["STATUS"] = new_status
|
40
|
+
end
|
41
|
+
def not_started?
|
42
|
+
status == "NOT STARTED"
|
43
|
+
end
|
44
|
+
|
45
|
+
def in_progress?
|
46
|
+
status == "IN PROGRESS"
|
47
|
+
end
|
48
|
+
|
49
|
+
def waiting?
|
50
|
+
status == "WAITING"
|
51
|
+
end
|
52
|
+
|
53
|
+
def completed?
|
54
|
+
status == "COMPLETED"
|
55
|
+
end
|
56
|
+
|
57
|
+
def deferred?
|
58
|
+
status == "DEFERRED"
|
59
|
+
end
|
60
|
+
|
61
|
+
def task_id
|
62
|
+
@data["TASK_ID"]
|
63
|
+
end
|
64
|
+
|
65
|
+
def remote_id
|
66
|
+
task_id
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Insightly
|
2
|
+
class TaskLink < ReadOnly
|
3
|
+
self.url_base ="TaskLinks"
|
4
|
+
|
5
|
+
def opportunity_id
|
6
|
+
@data["OPPORTUNITY_ID"]
|
7
|
+
end
|
8
|
+
def task_id
|
9
|
+
@data["TASK_ID"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.search_by_opportunity_id(opportunity_id)
|
13
|
+
list = []
|
14
|
+
TaskLink.all.each do |x|
|
15
|
+
if !x.task_id.nil? && x.opportunity_id == opportunity_id
|
16
|
+
list << x
|
17
|
+
end
|
18
|
+
end
|
19
|
+
list
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
require "rubygems"
|
8
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
|
9
|
+
|
10
|
+
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
11
|
+
Bundler.require(:default, :testing) if defined?(Bundler)
|
12
|
+
|
13
|
+
require "insightly"
|
14
|
+
require File.expand_path(File.dirname(__FILE__) + "/../api_key")
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
17
|
+
config.run_all_when_everything_filtered = true
|
18
|
+
config.filter_run :focus
|
19
|
+
|
20
|
+
# Run specs in random order to surface order dependencies. If you find an
|
21
|
+
# order dependency and want to debug it, you can fix the order by providing
|
22
|
+
# the seed, which is printed after each run.
|
23
|
+
# --seed 1234
|
24
|
+
config.order = 'random'
|
25
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe Insightly::Comment do
|
4
|
+
before(:each) do
|
5
|
+
Insightly::Configuration.api_key = INSIGHTLY_API_KEY
|
6
|
+
Insightly::Configuration.logger = Insightly::Configuration._debug_logger
|
7
|
+
@comment = Insightly::Comment.new.build({
|
8
|
+
"COMMENT_ID" => 132456,
|
9
|
+
"BODY" => "test comment",
|
10
|
+
"OWNER_USER_ID" => 12345,
|
11
|
+
"DATE_CREATED_UTC" => "2012-03-09 11:59:19",
|
12
|
+
"DATE_UPDATED_UTC" => "2012-03-09 11:59:19",
|
13
|
+
"FILE_ATTACHMENTS" =>
|
14
|
+
{
|
15
|
+
"FILE_ID" => 4567899,
|
16
|
+
"FILE_NAME" => "test.docx",
|
17
|
+
"CONTENT_TYPE" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
18
|
+
"FILE_SIZE" => 2489,
|
19
|
+
"FILE_CATEGORY_ID" => nil,
|
20
|
+
"OWNER_USER_ID" => 12345,
|
21
|
+
"DATE_CREATED_UTC" => "2012-03-09 11:59:20",
|
22
|
+
"DATE_UPDATED_UTC" => "2012-03-09 11:59:20",
|
23
|
+
"URL" => "/api/fileattachments/4567899"
|
24
|
+
}
|
25
|
+
}
|
26
|
+
)
|
27
|
+
|
28
|
+
# @comment = Insightly::Comment.new(3216775)
|
29
|
+
end
|
30
|
+
it "should be able to create a comment" do
|
31
|
+
end
|
32
|
+
it "should have a url base" do
|
33
|
+
@comment.url_base.should == "Comments"
|
34
|
+
end
|
35
|
+
it "should know the comment id" do
|
36
|
+
@comment.comment_id.should == 132456
|
37
|
+
end
|
38
|
+
it "should know that the remote id and the comment id are the same" do
|
39
|
+
@comment.remote_id.should == @comment.comment_id
|
40
|
+
end
|
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
|
45
|
+
end
|
46
|
+
it "should allow you to build an object from a hash" do
|
47
|
+
comment = Insightly::Comment.new.build({"BODY" => "Other"})
|
48
|
+
comment.remote_data.should == {"BODY" => "Other"}
|
49
|
+
end
|
50
|
+
context "xml" do
|
51
|
+
before(:each) do
|
52
|
+
@raw_xml = <<-END_XML
|
53
|
+
<?xml version="1.0" encoding="utf-8"?>
|
54
|
+
<Comment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
55
|
+
<COMMENT_ID>132456</COMMENT_ID>
|
56
|
+
<BODY>test comment</BODY>
|
57
|
+
<OWNER_USER_ID>12345</OWNER_USER_ID>
|
58
|
+
<DATE_CREATED_UTC>2012-03-09T23:59:19.503</DATE_CREATED_UTC>
|
59
|
+
<DATE_UPDATED_UTC>2012-03-09T23:59:19.503</DATE_UPDATED_UTC>
|
60
|
+
<FILE_ATTACHMENTS></FILE_ATTACHMENTS>
|
61
|
+
</Comment>
|
62
|
+
END_XML
|
63
|
+
end
|
64
|
+
it "should be able to parse the xml into a valid comment" do
|
65
|
+
@comment = Insightly::Comment.new.load_from_xml(@raw_xml)
|
66
|
+
@comment.comment_id.should == 132456
|
67
|
+
@comment.body.should == "test comment"
|
68
|
+
@comment.date_created_utc.should == "2012-03-09T23:59:19.503"
|
69
|
+
@comment.date_updated_utc.should == "2012-03-09T23:59:19.503"
|
70
|
+
@comment.owner_user_id.should == 12345
|
71
|
+
|
72
|
+
end
|
73
|
+
it "should be able to generate xml from the commment" do
|
74
|
+
@comment = Insightly::Comment.new.load_from_xml(@raw_xml)
|
75
|
+
@comment.to_xml.should == @raw_xml
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
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
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe Insightly::Configuration do
|
4
|
+
#customer_user_agent
|
5
|
+
#endpoint
|
6
|
+
#logger
|
7
|
+
#api_key
|
8
|
+
before(:each) do
|
9
|
+
Insightly::Configuration.custom_user_agent = nil
|
10
|
+
Insightly::Configuration.api_key = "123"
|
11
|
+
Insightly::Configuration.endpoint = nil
|
12
|
+
end
|
13
|
+
it "should provide a default user agent" do
|
14
|
+
|
15
|
+
Insightly::Configuration.instantiate.custom_user_agent.should be_nil
|
16
|
+
Insightly::Configuration.instantiate.user_agent.should == "Insightly Ruby Gem 0.1.0"
|
17
|
+
end
|
18
|
+
it "should allow you to override the user agent" do
|
19
|
+
|
20
|
+
Insightly::Configuration.custom_user_agent = "Bob"
|
21
|
+
Insightly::Configuration.instantiate.user_agent.should == "Insightly Ruby Gem 0.1.0 (Bob)"
|
22
|
+
end
|
23
|
+
it "should provide a default endpoint" do
|
24
|
+
Insightly::Configuration.instantiate.endpoint.should == "https://api.insight.ly/v1"
|
25
|
+
end
|
26
|
+
it "should allow you to override the endpoint" do
|
27
|
+
Insightly::Configuration.endpoint = "Bob"
|
28
|
+
Insightly::Configuration.instantiate.endpoint.should == "Bob"
|
29
|
+
end
|
30
|
+
it "should raise an error if you do not set an api key" do
|
31
|
+
Insightly::Configuration.instance_variable_set(:@api_key, nil)
|
32
|
+
expect do
|
33
|
+
Insightly::Configuration.api_key
|
34
|
+
end.to raise_error(Insightly::ConfigurationError, "Insightly::Configuration.api_key needs to be set")
|
35
|
+
expect do
|
36
|
+
Insightly::Configuration.instantiate.api_key
|
37
|
+
end.to raise_error(Insightly::ConfigurationError, "Insightly::Configuration.api_key needs to be set")
|
38
|
+
end
|
39
|
+
it "should allow you to set the api_key" do
|
40
|
+
Insightly::Configuration.api_key = "Bob"
|
41
|
+
Insightly::Configuration.api_key.should == "Bob"
|
42
|
+
Insightly::Configuration.instantiate.api_key.should == "Bob"
|
43
|
+
end
|
44
|
+
it "should be able to set custom fields for opportunities" do
|
45
|
+
Insightly::Opportunity.should_receive(:custom_fields).with(:rank, :branch_of_service)
|
46
|
+
|
47
|
+
Insightly::Configuration.custom_fields_for_opportunities(:rank, :branch_of_service)
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe Insightly::Opportunity do
|
4
|
+
before(:each) do
|
5
|
+
Insightly::Configuration.api_key = INSIGHTLY_API_KEY
|
6
|
+
Insightly::Configuration.logger = Insightly::Configuration._debug_logger
|
7
|
+
@opportunity = Insightly::Opportunity.build({
|
8
|
+
"OPPORTUNITY_FIELD_10" => nil,
|
9
|
+
"OPPORTUNITY_FIELD_9" => nil,
|
10
|
+
"OPPORTUNITY_FIELD_8" => "Bob Roberts",
|
11
|
+
"OPPORTUNITY_FIELD_7" => "r26D Trucking",
|
12
|
+
"OPPORTUNITY_FIELD_6" => "TruckingOffice",
|
13
|
+
"OPPORTUNITY_FIELD_5" => "Owner/Operator",
|
14
|
+
"OPPORTUNITY_FIELD_4" => "Central",
|
15
|
+
"OPPORTUNITY_FIELD_3" => "210-555-1212",
|
16
|
+
"OPPORTUNITY_FIELD_2" => "http://www.truckingoffice.com/522",
|
17
|
+
"OPPORTUNITY_FIELD_1" => nil,
|
18
|
+
"VISIBLE_TO" => "EVERYONE",
|
19
|
+
"BID_TYPE" => "Fixed Bid",
|
20
|
+
"ACTUAL_CLOSE_DATE" => nil,
|
21
|
+
"DATE_UPDATED_UTC" => "2012-06-06 02:05:34",
|
22
|
+
"OWNER_USER_ID" => 226277,
|
23
|
+
"BID_DURATION" => nil,
|
24
|
+
"BID_CURRENTY" => "USD",
|
25
|
+
"PIPELINE_ID" => 24377,
|
26
|
+
"CATEGORY_ID" => 628187,
|
27
|
+
"PROBABILITY" => nil,
|
28
|
+
"TAGS" => [],
|
29
|
+
"IMAGE_URL" => "http://s3.amazonaws.com/insightly.userfiles/20562/",
|
30
|
+
"BID_AMOUNT" => 20,
|
31
|
+
"VISIBLE_TEAM_ID" => nil,
|
32
|
+
"STAGE_ID" => 71162,
|
33
|
+
"DATE_CREATED_UTC" => "2012-09-06 02:04:47",
|
34
|
+
"OPPORTUNITY_STATE" => "OPEN",
|
35
|
+
"FORECAST_CLOSE_DATE" => "2012-10-05 00:00:00",
|
36
|
+
"OPPORTUNITY_NAME" => "Sample Opportunity",
|
37
|
+
"OPPORTUNITY_ID" => 957168,
|
38
|
+
"VISIBLE_USER_IDS" => nil,
|
39
|
+
"LINKS" => [],
|
40
|
+
"RESPONSIBLE_USER_ID" => 226277,
|
41
|
+
"OPPORTUNITY_DETAILS" => "This is a description."
|
42
|
+
|
43
|
+
})
|
44
|
+
end
|
45
|
+
it "should be able to create a opportunity" do
|
46
|
+
end
|
47
|
+
it "should have a url base" do
|
48
|
+
@opportunity.url_base.should == "Opportunities"
|
49
|
+
end
|
50
|
+
it "should know the opportunity id" do
|
51
|
+
@opportunity.opportunity_id.should == 957168
|
52
|
+
end
|
53
|
+
it "should know that the remote id and the opportunity id are the same" do
|
54
|
+
@opportunity.remote_id.should == @opportunity.opportunity_id
|
55
|
+
end
|
56
|
+
it "should allow you to load based on an id"
|
57
|
+
it "should allow you to build an object from a hash" do
|
58
|
+
opportunity = Insightly::Opportunity.new.build({"TITLE" => "Other"})
|
59
|
+
opportunity.remote_data.should == {"TITLE" => "Other"}
|
60
|
+
end
|
61
|
+
it "should have allow you to read and write all fields" do
|
62
|
+
fields = Insightly::Opportunity.api_fields
|
63
|
+
|
64
|
+
Insightly::Opportunity.api_fields.each do |f|
|
65
|
+
@opportunity.send(f.downcase.to_sym).should == @opportunity.remote_data[f]
|
66
|
+
@opportunity.send("#{f.downcase}=".to_sym, "Bob")
|
67
|
+
@opportunity.send(f.downcase.to_sym).should == "Bob"
|
68
|
+
@opportunity.remote_data[f].should == "Bob"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
it "should allow you to define custom field labels" do
|
72
|
+
Insightly::Opportunity.custom_fields(:dummy1, :dummy2, :dummy3)
|
73
|
+
@opportunity.dummy1.should == @opportunity.remote_data["OPPORTUNITY_FIELD_1"]
|
74
|
+
@opportunity.dummy2.should == "http://www.truckingoffice.com/522"
|
75
|
+
@opportunity.dummy3.should == @opportunity.remote_data["OPPORTUNITY_FIELD_3"]
|
76
|
+
|
77
|
+
@opportunity.dummy1 = "Bob1"
|
78
|
+
@opportunity.dummy2 = "Bob2"
|
79
|
+
@opportunity.dummy3 = "Bob3"
|
80
|
+
|
81
|
+
@opportunity.dummy1.should == "Bob1"
|
82
|
+
@opportunity.dummy2.should == "Bob2"
|
83
|
+
@opportunity.dummy3.should == "Bob3"
|
84
|
+
@opportunity.remote_data["OPPORTUNITY_FIELD_1"].should == "Bob1"
|
85
|
+
@opportunity.remote_data["OPPORTUNITY_FIELD_2"].should == "Bob2"
|
86
|
+
@opportunity.remote_data["OPPORTUNITY_FIELD_3"].should == "Bob3"
|
87
|
+
end
|
88
|
+
it "should handle special fields" do
|
89
|
+
Insightly::Opportunity.custom_fields(:dummy1, :admin_url, :phone_number, :timezone, :plan, :organization, :company_name, :contact_name)
|
90
|
+
@opportunity.admin_url.should == "http://www.truckingoffice.com/522"
|
91
|
+
@opportunity.phone_number.should == "210-555-1212"
|
92
|
+
@opportunity.timezone.should == "Central"
|
93
|
+
@opportunity.plan.should == "Owner/Operator"
|
94
|
+
@opportunity.organization.should == "TruckingOffice"
|
95
|
+
@opportunity.company_name.should == "r26D Trucking"
|
96
|
+
@opportunity.contact_name.should == "Bob Roberts"
|
97
|
+
end
|
98
|
+
context "search/find" do
|
99
|
+
before(:each) do
|
100
|
+
@opp1 = Insightly::Opportunity.build(@opportunity.remote_data.clone)
|
101
|
+
@opp1.opportunity_name = "Apple Sale"
|
102
|
+
@opp2 = Insightly::Opportunity.build(@opportunity.remote_data.clone)
|
103
|
+
@opp2.opportunity_name = "Apple Sale 2"
|
104
|
+
@opp3 = Insightly::Opportunity.build(@opportunity.remote_data.clone)
|
105
|
+
@opp3.opportunity_name = "Box Sale"
|
106
|
+
@opp4 = Insightly::Opportunity.build(@opportunity.remote_data.clone)
|
107
|
+
@opp4.opportunity_name = nil
|
108
|
+
|
109
|
+
Insightly::Opportunity.should_receive(:all).and_return([@opp1, @opp2, @opp3, @opp4])
|
110
|
+
|
111
|
+
end
|
112
|
+
it "should find all the names that match" do
|
113
|
+
Insightly::Opportunity.search_by_name("Apple").should == [@opp1, @opp2]
|
114
|
+
end
|
115
|
+
it "should return an empty array if there are not matches" do
|
116
|
+
Insightly::Opportunity.search_by_name("Cobra").should == []
|
117
|
+
end
|
118
|
+
it "should find the first one that is exactly the right" do
|
119
|
+
Insightly::Opportunity.find_by_name("Apple Sale 2").should == @opp2
|
120
|
+
end
|
121
|
+
it "should return nil if no opportunity name is found" do
|
122
|
+
Insightly::Opportunity.find_by_name("Cobra").should == nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "State" do
|
127
|
+
it "should have state booleans" do
|
128
|
+
|
129
|
+
states = Insightly::OpportunityStateReason::STATES
|
130
|
+
states.each do |state|
|
131
|
+
opportunity = Insightly::Opportunity.build({"OPPORTUNITY_STATE" => state})
|
132
|
+
|
133
|
+
states.each do |current_state|
|
134
|
+
if state == current_state
|
135
|
+
opportunity.send("#{current_state.downcase}?".to_sym).should be_true
|
136
|
+
|
137
|
+
else
|
138
|
+
opportunity.send("#{current_state.downcase}?".to_sym).should be_false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
it "should be able to search by state" do
|
145
|
+
|
146
|
+
end
|
147
|
+
it "should allow you to change the state without a reason" do
|
148
|
+
@opportunity = Insightly::Opportunity.new(957168)
|
149
|
+
|
150
|
+
@opportunity.open!
|
151
|
+
@opportunity.lost!
|
152
|
+
@opportunity.should be_lost
|
153
|
+
@opportunity.reload
|
154
|
+
@opportunity.should be_lost
|
155
|
+
end
|
156
|
+
it "should allow you to provide a reason - and the state should change if the reason isn't valid" do
|
157
|
+
@opportunity = Insightly::Opportunity.new(957168)
|
158
|
+
|
159
|
+
@opportunity.open!
|
160
|
+
@opportunity.won!("Bobobob")
|
161
|
+
@opportunity.reload
|
162
|
+
@opportunity.should be_won
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should allow you to change the state and set the reason" do
|
166
|
+
@opportunity = Insightly::Opportunity.new(957168)
|
167
|
+
Insightly::OpportunityStateReason.find_by_state_reason("Won", "They converted").should_not be_nil
|
168
|
+
|
169
|
+
@opportunity.open!
|
170
|
+
@opportunity.won!("They converted")
|
171
|
+
@opportunity.reload
|
172
|
+
@opportunity.should be_won
|
173
|
+
# Currently there is no way to test the reason is set
|
174
|
+
|
175
|
+
end
|
176
|
+
it "should set the reason to Created by API if you create an opportunity"
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|