netsuite 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/Gemfile +0 -2
  2. data/README.md +154 -0
  3. data/lib/netsuite.rb +7 -0
  4. data/lib/netsuite/actions/add.rb +6 -21
  5. data/lib/netsuite/actions/delete.rb +7 -10
  6. data/lib/netsuite/actions/get.rb +7 -10
  7. data/lib/netsuite/actions/get_list.rb +77 -0
  8. data/lib/netsuite/actions/get_select_value.rb +71 -0
  9. data/lib/netsuite/actions/search.rb +151 -36
  10. data/lib/netsuite/actions/search_more_with_id.rb +3 -2
  11. data/lib/netsuite/actions/update.rb +16 -16
  12. data/lib/netsuite/configuration.rb +29 -15
  13. data/lib/netsuite/namespaces/list_support.rb +11 -0
  14. data/lib/netsuite/records/account.rb +1 -0
  15. data/lib/netsuite/records/base_ref_list.rb +33 -0
  16. data/lib/netsuite/records/cash_sale.rb +7 -0
  17. data/lib/netsuite/records/custom_field.rb +2 -1
  18. data/lib/netsuite/records/custom_field_list.rb +62 -12
  19. data/lib/netsuite/records/custom_record.rb +1 -7
  20. data/lib/netsuite/records/custom_record_ref.rb +7 -0
  21. data/lib/netsuite/records/customer.rb +4 -3
  22. data/lib/netsuite/records/phone_call.rb +29 -0
  23. data/lib/netsuite/records/record_ref.rb +1 -9
  24. data/lib/netsuite/records/sales_order.rb +2 -1
  25. data/lib/netsuite/records/support_case.rb +32 -0
  26. data/lib/netsuite/records/task.rb +4 -3
  27. data/lib/netsuite/records/transaction.rb +4 -21
  28. data/lib/netsuite/support/actions.rb +4 -0
  29. data/lib/netsuite/support/records.rb +3 -0
  30. data/lib/netsuite/support/search_result.rb +53 -29
  31. data/lib/netsuite/version.rb +1 -1
  32. data/netsuite.gemspec +1 -1
  33. data/spec/netsuite/actions/add_spec.rb +9 -13
  34. data/spec/netsuite/actions/delete_spec.rb +5 -8
  35. data/spec/netsuite/actions/get_spec.rb +39 -24
  36. data/spec/netsuite/actions/search_spec.rb +149 -0
  37. data/spec/netsuite/actions/update_spec.rb +9 -13
  38. data/spec/netsuite/configuration_spec.rb +3 -9
  39. data/spec/netsuite/records/custom_field_list_spec.rb +19 -5
  40. data/spec/netsuite/records/customer_spec.rb +2 -2
  41. data/spec/netsuite/records/phone_call_spec.rb +23 -0
  42. data/spec/netsuite/records/support_case_spec.rb +157 -0
  43. data/spec/support/fixtures/search/saved_search_customer.xml +54 -0
  44. data/spec/support/fixtures/search/saved_search_joined_custom_customer.xml +87 -0
  45. metadata +21 -4
@@ -0,0 +1,149 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Actions::Search do
4
+ before(:all) { savon.mock! }
5
+ after(:all) { savon.unmock! }
6
+
7
+ context "saved search" do
8
+ it "should handle a ID only search" do
9
+ savon.expects(:search).with(:message => {
10
+ 'searchRecord' => {
11
+ '@xsi:type' => 'listRel:CustomerSearchAdvanced',
12
+ '@savedSearchId' => 500,
13
+ :content! => { "listRel:criteria" => {} }
14
+ },
15
+ }).returns(File.read('spec/support/fixtures/search/saved_search_customer.xml'))
16
+
17
+ result = NetSuite::Records::Customer.search(saved: 500)
18
+ result.results.size.should == 1
19
+ result.results.first.email.should == 'aemail@gmail.com'
20
+ end
21
+
22
+ it "should handle a ID search with basic params" do
23
+
24
+ end
25
+
26
+ it "should handle a search with joined params" do
27
+
28
+ end
29
+
30
+ it "should handle a search with joined params containing custom field search" do
31
+ savon.expects(:search).with(:message => {
32
+ 'searchRecord' => {
33
+ '@xsi:type' => 'listRel:CustomerSearchAdvanced',
34
+ '@savedSearchId' => 500,
35
+ :content! => {
36
+ "listRel:criteria" => {
37
+ "listRel:basic" => {
38
+ "platformCommon:entityId" => {
39
+ "platformCore:searchValue" => "New Keywords"
40
+ },
41
+
42
+ :attributes! => {
43
+ "platformCommon:entityId" => { "operator" => "hasKeywords" },
44
+ "platformCommon:stage" => { "operator" => "anyOf" }
45
+ },
46
+
47
+ "platformCommon:stage" => { "platformCore:searchValue" => ["_lead", "_customer"] },
48
+ "platformCommon:customFieldList" => {
49
+ "platformCore:customField" => [
50
+ {
51
+ "platformCore:searchValue" => [{}, {}],
52
+ :attributes! => {
53
+ "platformCore:searchValue" => {
54
+ "internalId" => [4, 11]
55
+ }
56
+ }
57
+ },
58
+ {
59
+ "platformCore:searchValue" => [{}],
60
+ :attributes! => {
61
+ "platformCore:searchValue" => { "internalId" => [88825] }
62
+ }
63
+ }
64
+ ],
65
+
66
+ :attributes! => {
67
+ "platformCore:customField" => {
68
+ "internalId" => ["custentity_customerandcontacttypelist", "custentity_relatedthing"],
69
+ "operator" => ["anyOf", "anyOf"],
70
+ "xsi:type" => ["platformCore:SearchMultiSelectCustomField", "platformCore:SearchMultiSelectCustomField"]
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ },
78
+ }).returns(File.read('spec/support/fixtures/search/saved_search_joined_custom_customer.xml'))
79
+
80
+ search = NetSuite::Records::Customer.search({
81
+ saved: 500,
82
+ basic: [
83
+ {
84
+ field: 'entityId',
85
+ value: 'New Keywords',
86
+ operator: 'hasKeywords'
87
+ },
88
+ {
89
+ field: 'stage',
90
+ operator: 'anyOf',
91
+ type: 'SearchMultiSelectCustomField',
92
+ value: [
93
+ '_lead',
94
+ '_customer'
95
+ ]
96
+ },
97
+ {
98
+ field: 'customFieldList',
99
+ value: [
100
+ {
101
+ field: 'custentity_customerandcontacttypelist',
102
+ operator: 'anyOf',
103
+ # type is needed for multiselect fields
104
+ type: 'SearchMultiSelectCustomField',
105
+ value: [
106
+ NetSuite::Records::CustomRecordRef.new(:internal_id => 4),
107
+ NetSuite::Records::CustomRecordRef.new(:internal_id => 11),
108
+ ]
109
+ },
110
+ {
111
+ field: 'custentity_relatedthing',
112
+ # is in the GUI is the equivilent of anyOf with a single element array
113
+ operator: 'anyOf',
114
+ type: 'SearchMultiSelectCustomField',
115
+ value: [
116
+ NetSuite::Records::Customer.new(:internal_id => 88825)
117
+ ]
118
+ }
119
+ ]
120
+ }
121
+ ]
122
+ })
123
+
124
+ search.results.size.should == 2
125
+ search.results.first.alt_name.should == 'A Awesome Name'
126
+ search.results.last.email.should == 'alessawesome@gmail.com'
127
+ end
128
+ end
129
+
130
+ context "advanced search" do
131
+ it "should handle search column definitions" do
132
+
133
+ end
134
+
135
+ it "should handle joined search results" do
136
+
137
+ end
138
+ end
139
+
140
+ context "basic search" do
141
+ it "should handle searching basic fields" do
142
+
143
+ end
144
+
145
+ it "should handle searching with joined fields" do
146
+
147
+ end
148
+ end
149
+ end
@@ -11,14 +11,12 @@ describe NetSuite::Actions::Update do
11
11
  before do
12
12
  savon.expects(:update).with(:message => {
13
13
  'platformMsgs:record' => {
14
- 'listRel:entityId' => 'Shutter Fly',
15
- 'listRel:companyName' => 'Shutter Fly, Inc.'
14
+ :content! => {
15
+ 'listRel:entityId' => 'Shutter Fly',
16
+ 'listRel:companyName' => 'Shutter Fly, Inc.',
17
+ },
18
+ '@xsi:type' => 'listRel:Customer'
16
19
  },
17
- :attributes! => {
18
- 'platformMsgs:record' => {
19
- 'xsi:type' => 'listRel:Customer'
20
- }
21
- }
22
20
  }).returns(File.read('spec/support/fixtures/update/update_customer.xml'))
23
21
  end
24
22
 
@@ -40,13 +38,11 @@ describe NetSuite::Actions::Update do
40
38
  before do
41
39
  savon.expects(:update).with(:message => {
42
40
  'platformMsgs:record' => {
43
- 'tranSales:source' => 'Google',
41
+ :content! => {
42
+ 'tranSales:source' => 'Google',
43
+ },
44
+ '@xsi:type' => 'tranSales:Invoice'
44
45
  },
45
- :attributes! => {
46
- 'platformMsgs:record' => {
47
- 'xsi:type' => 'tranSales:Invoice'
48
- }
49
- }
50
46
  }).returns(File.read('spec/support/fixtures/update/update_invoice.xml'))
51
47
  end
52
48
 
@@ -66,13 +66,7 @@ describe NetSuite::Configuration do
66
66
  'platformCore:email' => 'user@example.com',
67
67
  'platformCore:password' => 'myPassword',
68
68
  'platformCore:account' => '1234',
69
- 'platformCore:role' => {},
70
- :attributes! => {
71
- 'platformCore:role' => {
72
- :internalId => '3',
73
- :type => 'role'
74
- }
75
- }
69
+ 'platformCore:role' => { :@type => 'role', :@internalId => '3' },
76
70
  }
77
71
  })
78
72
  end
@@ -145,7 +139,7 @@ describe NetSuite::Configuration do
145
139
  describe '#role' do
146
140
  context 'when no role is defined' do
147
141
  it 'defaults to "3"' do
148
- config.role.internal_id.should == "3"
142
+ config.role.should == "3"
149
143
  end
150
144
  end
151
145
  end
@@ -153,7 +147,7 @@ describe NetSuite::Configuration do
153
147
  describe '#role=' do
154
148
  it 'sets the role according to the input value' do
155
149
  config.role = "6"
156
- config.role.internal_id.should == "6"
150
+ config.role.should == "6"
157
151
  end
158
152
  end
159
153
 
@@ -10,23 +10,37 @@ describe NetSuite::Records::CustomFieldList do
10
10
  describe '#to_record' do
11
11
  before do
12
12
  list.custom_fields << NetSuite::Records::CustomField.new(
13
- :internal_id => '3',
13
+ :internal_id => 'custentity_registeredonline',
14
14
  :type => 'BooleanCustomFieldRef',
15
15
  :value => false
16
16
  )
17
+ list.custom_fields << NetSuite::Records::CustomField.new(
18
+ :internal_id => 'custbody_salesclassification',
19
+ :type => 'SelectCustomFieldRef',
20
+ :value => NetSuite::Records::CustomRecordRef.new(:internal_id => 13, :name => "The Name")
21
+ )
17
22
  end
18
23
 
19
24
  it 'can represent itself as a SOAP record' do
20
25
  record = [
21
26
  {
22
- "platformCore:customField" => {"platformCore:value"=>false},
23
- :attributes! => {
24
- "platformCore:customField" => {"internalId"=>"3", "xsi:type"=>"BooleanCustomFieldRef"}
27
+ "platformCore:customField" => {
28
+ "@internalId" => "custentity_registeredonline",
29
+ "@xsi:type" => "BooleanCustomFieldRef",
30
+ :content! => { "platformCore:value" => false }
31
+ }
32
+ },
33
+ {
34
+ "platformCore:customField" => {
35
+ '@internalId' => 'custbody_salesclassification',
36
+ '@xsi:type' => 'BooleanCustomFieldRef',
37
+ :content! => { "platformCore:value" => true }
25
38
  }
26
39
  }
27
40
  ]
28
-
41
+
29
42
  list.to_record.should eql(record)
43
+ list.to_record.length.should == 2
30
44
  end
31
45
  end
32
46
 
@@ -13,9 +13,9 @@ describe NetSuite::Records::Customer do
13
13
  :deposit_balance, :download_list, :email, :email_preference, :email_transactions, :end_date, :entity_id,
14
14
  :estimated_budget, :fax, :fax_transactions, :first_name, :first_visit, :give_access, :global_subscription_status,
15
15
  :group_pricing_list, :home_phone, :image, :is_budget_approved, :is_inactive, :is_person, :item_pricing_list, :keywords,
16
- :language, :last_modified, :last_name, :last_page_visited, :last_visit, :lead_source, :middle_name, :mobile_phone,
16
+ :language, :last_modified_date, :last_name, :last_page_visited, :last_visit, :lead_source, :middle_name, :mobile_phone,
17
17
  :opening_balance, :opening_balance_account, :opening_balance_date, :overdue_balance, :parent, :partners_list,
18
- :password, :password_2, :phone, :phonetic_name, :pref_cc_processor, :price_level, :print_on_check_as,
18
+ :password, :password2, :phone, :phonetic_name, :pref_cc_processor, :price_level, :print_on_check_as,
19
19
  :print_transactions, :referrer, :reminder_days, :representing_subsidiary, :require_pwd_change, :resale_number,
20
20
  :sales_group, :sales_readiness, :sales_rep, :sales_team_list, :salutation, :send_email, :ship_complete, :shipping_item,
21
21
  :stage, :start_date, :subscriptions_list, :subsidiary, :sync_partner_teams, :tax_exempt, :tax_item, :taxable, :terms,
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::PhoneCall do
4
+ let(:phone_call) { NetSuite::Records::PhoneCall.new }
5
+
6
+ it "has the right fields" do
7
+ [:title, :message, :phone, :status, :priority, :start_date, :end_date, :completed_date, :timed_event, :access_level].each do |f|
8
+ phone_call.should have_field(f)
9
+ end
10
+ end
11
+
12
+ it 'has the right record refs' do
13
+ [:assigned, :owner, :company, :contact].each do |rr|
14
+ phone_call.should have_record_ref(rr)
15
+ end
16
+ end
17
+
18
+ describe 'to_record' do
19
+ it 'should be verified with our params' do
20
+ fail 'Not Verified.'
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::SupportCase do
4
+ let(:support_case) { NetSuite::Records::SupportCase.new }
5
+
6
+ it 'has all the right fields' do
7
+ [
8
+ :end_date, :incoming_message, :outgoing_message, :search_solution, :email_form,
9
+ :internal_only, :title, :case_number, :start_date, :email, :phone, :inbound_email,
10
+ :is_inactive, :help_desk
11
+ ].each do |field|
12
+ support_case.should have_field(field)
13
+ end
14
+ end
15
+
16
+ it 'has the right record_refs' do
17
+ [
18
+ :custom_form, :company, :contact, :issue, :status, :priority, :origin, :category, :assigned
19
+ ].each do |record_ref|
20
+ support_case.should have_record_ref(record_ref)
21
+ end
22
+ end
23
+
24
+ describe '#custom_field_list' do
25
+ it 'can be set from attributes' do
26
+ attributes = {
27
+ :custom_field => {
28
+ :value => 10,
29
+ :internal_id => 'custfield_something'
30
+ }
31
+ }
32
+ support_case.custom_field_list = attributes
33
+ support_case.custom_field_list.should be_kind_of(NetSuite::Records::CustomFieldList)
34
+ support_case.custom_field_list.custom_fields.length.should eql(1)
35
+ end
36
+
37
+ it 'can be set from a CustomFieldList object' do
38
+ custom_field_list = NetSuite::Records::CustomFieldList.new
39
+ support_case.custom_field_list = custom_field_list
40
+ support_case.custom_field_list.should eql(custom_field_list)
41
+ end
42
+ end
43
+
44
+ describe '.get' do
45
+ context 'when the response is successful' do
46
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :title => 'Case title' }) }
47
+
48
+ it 'returns a SupportCase instance populated with the data from the response object' do
49
+ NetSuite::Actions::Get.should_receive(:call).with(NetSuite::Records::SupportCase, :external_id => 1).and_return(response)
50
+ support_case = NetSuite::Records::SupportCase.get(:external_id => 1)
51
+ support_case.should be_kind_of(NetSuite::Records::SupportCase)
52
+ support_case.title.should == 'Case title'
53
+ end
54
+ end
55
+
56
+ context 'when the response is unsuccessful' do
57
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
58
+
59
+ it 'raises a RecordNotFound exception' do
60
+ NetSuite::Actions::Get.should_receive(:call).with(NetSuite::Records::SupportCase, :external_id => 1).and_return(response)
61
+ lambda {
62
+ NetSuite::Records::SupportCase.get(:external_id => 1)
63
+ }.should raise_error(NetSuite::RecordNotFound,
64
+ /NetSuite::Records::SupportCase with OPTIONS=(.*) could not be found/)
65
+ end
66
+ end
67
+ end
68
+
69
+ describe '#add' do
70
+ let(:support_case) { NetSuite::Records::SupportCase.new(:title => 'Case title') }
71
+
72
+ context 'when the response is successful' do
73
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
74
+
75
+ it 'returns true' do
76
+ NetSuite::Actions::Add.should_receive(:call).
77
+ with(support_case).
78
+ and_return(response)
79
+ support_case.add.should be_true
80
+ end
81
+ end
82
+
83
+ context 'when the response is unsuccessful' do
84
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
85
+
86
+ it 'returns false' do
87
+ NetSuite::Actions::Add.should_receive(:call).
88
+ with(support_case).
89
+ and_return(response)
90
+ support_case.add.should be_false
91
+ end
92
+ end
93
+ end
94
+
95
+ describe '#delete' do
96
+ context 'when the response is successful' do
97
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
98
+
99
+ it 'returns true' do
100
+ NetSuite::Actions::Delete.should_receive(:call).
101
+ with(support_case).
102
+ and_return(response)
103
+ support_case.delete.should be_true
104
+ end
105
+ end
106
+
107
+ context 'when the response is unsuccessful' do
108
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
109
+
110
+ it 'returns false' do
111
+ NetSuite::Actions::Delete.should_receive(:call).
112
+ with(support_case).
113
+ and_return(response)
114
+ support_case.delete.should be_false
115
+ end
116
+ end
117
+ end
118
+
119
+ describe '.update' do
120
+ context 'when the response is successful' do
121
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :title => 'Case title' }) }
122
+
123
+ it 'returns true' do
124
+ NetSuite::Actions::Update.should_receive(:call).with(NetSuite::Records::SupportCase, :external_id => 1, :title => 'Case title').and_return(response)
125
+ support_case = NetSuite::Records::SupportCase.new(:external_id => 1)
126
+ support_case.update(:title => 'Case title').should be_true
127
+ end
128
+ end
129
+
130
+ context 'when the response is unsuccessful' do
131
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
132
+
133
+ it 'raises a RecordNotFound exception' do
134
+ NetSuite::Actions::Update.should_receive(:call).with(NetSuite::Records::SupportCase, :internal_id => 1, :title => 'Case title').and_return(response)
135
+ support_case = NetSuite::Records::SupportCase.new(:internal_id => 1)
136
+ support_case.update(:title => 'Case title').should be_false
137
+ end
138
+ end
139
+ end
140
+
141
+ describe '#to_record' do
142
+ let(:support_case) { NetSuite::Records::SupportCase.new(:title => 'Case title') }
143
+
144
+ it 'returns a hash of attributes that can be used in a SOAP request' do
145
+ support_case.to_record.should eql({
146
+ 'listSupport:title' => 'Case title'
147
+ })
148
+ end
149
+ end
150
+
151
+ describe '#record_type' do
152
+ it 'returns a string type for the record to be used in a SOAP request' do
153
+ support_case.record_type.should eql('listSupport:SupportCase')
154
+ end
155
+ end
156
+
157
+ end