netsuite 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +0 -2
- data/README.md +154 -0
- data/lib/netsuite.rb +7 -0
- data/lib/netsuite/actions/add.rb +6 -21
- data/lib/netsuite/actions/delete.rb +7 -10
- data/lib/netsuite/actions/get.rb +7 -10
- data/lib/netsuite/actions/get_list.rb +77 -0
- data/lib/netsuite/actions/get_select_value.rb +71 -0
- data/lib/netsuite/actions/search.rb +151 -36
- data/lib/netsuite/actions/search_more_with_id.rb +3 -2
- data/lib/netsuite/actions/update.rb +16 -16
- data/lib/netsuite/configuration.rb +29 -15
- data/lib/netsuite/namespaces/list_support.rb +11 -0
- data/lib/netsuite/records/account.rb +1 -0
- data/lib/netsuite/records/base_ref_list.rb +33 -0
- data/lib/netsuite/records/cash_sale.rb +7 -0
- data/lib/netsuite/records/custom_field.rb +2 -1
- data/lib/netsuite/records/custom_field_list.rb +62 -12
- data/lib/netsuite/records/custom_record.rb +1 -7
- data/lib/netsuite/records/custom_record_ref.rb +7 -0
- data/lib/netsuite/records/customer.rb +4 -3
- data/lib/netsuite/records/phone_call.rb +29 -0
- data/lib/netsuite/records/record_ref.rb +1 -9
- data/lib/netsuite/records/sales_order.rb +2 -1
- data/lib/netsuite/records/support_case.rb +32 -0
- data/lib/netsuite/records/task.rb +4 -3
- data/lib/netsuite/records/transaction.rb +4 -21
- data/lib/netsuite/support/actions.rb +4 -0
- data/lib/netsuite/support/records.rb +3 -0
- data/lib/netsuite/support/search_result.rb +53 -29
- data/lib/netsuite/version.rb +1 -1
- data/netsuite.gemspec +1 -1
- data/spec/netsuite/actions/add_spec.rb +9 -13
- data/spec/netsuite/actions/delete_spec.rb +5 -8
- data/spec/netsuite/actions/get_spec.rb +39 -24
- data/spec/netsuite/actions/search_spec.rb +149 -0
- data/spec/netsuite/actions/update_spec.rb +9 -13
- data/spec/netsuite/configuration_spec.rb +3 -9
- data/spec/netsuite/records/custom_field_list_spec.rb +19 -5
- data/spec/netsuite/records/customer_spec.rb +2 -2
- data/spec/netsuite/records/phone_call_spec.rb +23 -0
- data/spec/netsuite/records/support_case_spec.rb +157 -0
- data/spec/support/fixtures/search/saved_search_customer.xml +54 -0
- data/spec/support/fixtures/search/saved_search_joined_custom_customer.xml +87 -0
- 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
|
-
|
15
|
-
|
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
|
-
|
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.
|
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.
|
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 => '
|
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" => {
|
23
|
-
|
24
|
-
"
|
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, :
|
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, :
|
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
|