netsuite 0.1.0 → 0.2.0

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.
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