netsuite 0.8.3 → 0.8.4

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/README.md +3 -2
  4. data/circle.yml +3 -2
  5. data/lib/netsuite.rb +17 -0
  6. data/lib/netsuite/actions/login.rb +11 -0
  7. data/lib/netsuite/actions/update.rb +6 -2
  8. data/lib/netsuite/errors.rb +1 -0
  9. data/lib/netsuite/records/assembly_build.rb +4 -1
  10. data/lib/netsuite/records/assembly_item.rb +1 -0
  11. data/lib/netsuite/records/assembly_unbuild.rb +3 -0
  12. data/lib/netsuite/records/bin_number.rb +18 -0
  13. data/lib/netsuite/records/bin_number_list.rb +1 -20
  14. data/lib/netsuite/records/classification.rb +1 -1
  15. data/lib/netsuite/records/custom_field_list.rb +10 -2
  16. data/lib/netsuite/records/custom_record.rb +2 -2
  17. data/lib/netsuite/records/custom_record_ref.rb +1 -0
  18. data/lib/netsuite/records/customer.rb +3 -3
  19. data/lib/netsuite/records/customer_deposit.rb +5 -2
  20. data/lib/netsuite/records/customer_sales_team.rb +24 -0
  21. data/lib/netsuite/records/customer_sales_team_list.rb +9 -0
  22. data/lib/netsuite/records/customer_status.rb +29 -0
  23. data/lib/netsuite/records/customer_subscription.rb +18 -0
  24. data/lib/netsuite/records/customer_subscriptions_list.rb +10 -0
  25. data/lib/netsuite/records/entity_custom_field.rb +53 -0
  26. data/lib/netsuite/records/non_inventory_resale_item.rb +2 -2
  27. data/lib/netsuite/records/price.rb +17 -0
  28. data/lib/netsuite/records/price_list.rb +9 -0
  29. data/lib/netsuite/records/pricing.rb +20 -0
  30. data/lib/netsuite/records/pricing_matrix.rb +2 -2
  31. data/lib/netsuite/records/promotions.rb +26 -0
  32. data/lib/netsuite/records/promotions_list.rb +9 -0
  33. data/lib/netsuite/records/sales_order.rb +1 -0
  34. data/lib/netsuite/records/sales_role.rb +26 -0
  35. data/lib/netsuite/records/sales_tax_item.rb +3 -1
  36. data/lib/netsuite/records/serialized_assembly_item.rb +239 -0
  37. data/lib/netsuite/records/service_sale_item.rb +1 -1
  38. data/lib/netsuite/records/tax_group.rb +2 -2
  39. data/lib/netsuite/records/transaction_body_custom_field.rb +61 -0
  40. data/lib/netsuite/records/transaction_column_custom_field.rb +59 -0
  41. data/lib/netsuite/records/vendor_credit.rb +2 -0
  42. data/lib/netsuite/records/work_order.rb +8 -0
  43. data/lib/netsuite/support/country.rb +27 -15
  44. data/lib/netsuite/utilities.rb +45 -20
  45. data/lib/netsuite/version.rb +1 -1
  46. data/spec/netsuite/actions/login_spec.rb +23 -0
  47. data/spec/netsuite/actions/update_spec.rb +42 -0
  48. data/spec/netsuite/records/address_spec.rb +10 -0
  49. data/spec/netsuite/records/basic_record_spec.rb +6 -1
  50. data/spec/netsuite/records/bin_number_spec.rb +23 -0
  51. data/spec/netsuite/records/custom_field_list_spec.rb +33 -0
  52. data/spec/netsuite/records/customer_sales_team_list_spec.rb +41 -0
  53. data/spec/netsuite/records/customer_spec.rb +22 -1
  54. data/spec/netsuite/records/customer_subscription_spec.rb +41 -0
  55. data/spec/netsuite/records/customer_subscriptions_list_spec.rb +19 -0
  56. data/spec/netsuite/records/entity_custom_field_spec.rb +34 -0
  57. data/spec/netsuite/records/pricing_matrix_spec.rb +15 -13
  58. data/spec/netsuite/records/transaction_body_custom_field_spec.rb +32 -0
  59. data/spec/netsuite/records/transaction_column_custom_field_spec.rb +32 -0
  60. data/spec/netsuite/records/vendor_credit_spec.rb +29 -0
  61. data/spec/netsuite/utilities_spec.rb +15 -3
  62. data/spec/spec_helper.rb +5 -4
  63. metadata +34 -2
@@ -1,3 +1,3 @@
1
1
  module NetSuite
2
- VERSION = '0.8.3'
2
+ VERSION = '0.8.4'
3
3
  end
@@ -41,4 +41,27 @@ describe NetSuite::Actions::Login do
41
41
  role: 234
42
42
  }) }.to raise_error(Savon::SOAPFault)
43
43
  end
44
+
45
+ it 'handles a login call when token based auth is in place' do
46
+ NetSuite.configure do
47
+ consumer_key '123'
48
+ consumer_secret '123'
49
+ token_id '123'
50
+ token_secret '123'
51
+
52
+ api_version '2017_2'
53
+ end
54
+
55
+ message = {"platformMsgs:passport"=>{"platformCore:email"=>"email", "platformCore:password"=>"password", "platformCore:account"=>"1234", "platformCore:role"=>234}}
56
+ savon.expects(:login).with(:message => message).returns(File.read('spec/support/fixtures/login/success.xml'))
57
+
58
+ result = NetSuite::Actions::Login.call({
59
+ email: 'email',
60
+ password: 'password',
61
+ role: 234
62
+ })
63
+
64
+ expect(result.success?).to eq(true)
65
+ expect(result.body[:user_id]).to_not be_nil
66
+ end
44
67
  end
@@ -19,6 +19,48 @@ describe NetSuite::Actions::Update do
19
19
  }
20
20
  end
21
21
 
22
+ describe 'updating the external ID' do
23
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
24
+
25
+ # https://github.com/NetSweet/netsuite/pull/416
26
+ # if the external ID is set, and the external ID field is ommitted on an update, the external ID field does not change
27
+ # if the external_id field is set to nil, it should not be passed to netsuite
28
+ # passing an empty string to the external ID field does not remove it
29
+
30
+ it 'does not pass the external ID to an update call if not modified or included in update options' do
31
+ expect(NetSuite::Actions::Update).to receive(:call).
32
+ with([customer.class, {}], {}).
33
+ and_return(response)
34
+
35
+ expect(customer.update).to be_truthy
36
+ end
37
+
38
+ it 'should update the external ID when the attribute on the record is set' do
39
+ expect(NetSuite::Actions::Update).to receive(:call).
40
+ with([customer.class, {external_id: 'foo'}], {}).
41
+ and_return(response)
42
+
43
+ customer.external_id = 'foo'
44
+ expect(customer.update).to be_truthy
45
+ end
46
+
47
+ it 'should update the external ID to nil when the attribute on the record is set' do
48
+ expect(NetSuite::Actions::Update).to receive(:call).
49
+ with([customer.class, {external_id: nil}], {}).
50
+ and_return(response)
51
+
52
+ expect(customer.update(external_id: nil)).to be_truthy
53
+ end
54
+
55
+ it 'should update the external ID to the options value not the attribute value' do
56
+ expect(NetSuite::Actions::Update).to receive(:call).
57
+ with([customer.class, {external_id: 'bar'}], {}).
58
+ and_return(response)
59
+
60
+ customer.external_id = 'foo'
61
+ expect(customer.update(external_id: 'bar')).to be_truthy
62
+ end
63
+ end
22
64
 
23
65
  context 'when successful' do
24
66
 
@@ -134,6 +134,16 @@ describe NetSuite::Records::Address do
134
134
  expect(addressbook.country.to_record).to eql ""
135
135
  expect(addressbook.to_record["platformCommon:country"]).to eql ""
136
136
  end
137
+
138
+ it 'changes the netsuite identifier based on the current API version' do
139
+ NetSuite::Configuration.api_version = '2015_1'
140
+ addressbook = NetSuite::Records::Address.new country: "GB"
141
+ expect(addressbook.to_record["platformCommon:country"]).to eql "_unitedKingdomGB"
142
+ NetSuite::Configuration.api_version = '2018_1'
143
+
144
+ addressbook = NetSuite::Records::Address.new country: "GB"
145
+ expect(addressbook.to_record["platformCommon:country"]).to eql "_unitedKingdom"
146
+ end
137
147
  end
138
148
 
139
149
  end
@@ -57,7 +57,12 @@ describe 'basic records' do
57
57
  NetSuite::Records::LotNumberedAssemblyItem,
58
58
  NetSuite::Records::InboundShipment,
59
59
  NetSuite::Records::InterCompanyJournalEntry,
60
- NetSuite::Records::BinTransfer
60
+ NetSuite::Records::BinTransfer,
61
+ NetSuite::Records::SerializedAssemblyItem,
62
+ NetSuite::Records::CustomerStatus,
63
+ NetSuite::Records::TransactionBodyCustomField,
64
+ NetSuite::Records::TransactionColumnCustomField,
65
+ NetSuite::Records::EntityCustomField
61
66
  ]
62
67
  }
63
68
 
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::BinNumber do
4
+ it "has all the right fields" do
5
+ bin_number = described_class.new
6
+
7
+ [:preferred_bin, :location].each do |field|
8
+ expect(bin_number).to have_field(field)
9
+ end
10
+ end
11
+
12
+ it "has all the right record refs" do
13
+ bin_number = described_class.new
14
+
15
+ expect(bin_number).to have_record_ref(:bin_number)
16
+ end
17
+
18
+ it "has the right namespace" do
19
+ bin_number = described_class.new
20
+
21
+ expect(bin_number.record_namespace).to eq('listAcct')
22
+ end
23
+ end
@@ -180,6 +180,20 @@ describe NetSuite::Records::CustomFieldList do
180
180
  script_id: "custbody_salesclassification",
181
181
  type: "platformCore:StringCustomFieldRef",
182
182
  value: "foobar"
183
+ },
184
+ {
185
+ script_id: 'custbody_multipleselectfield',
186
+ type: "platformCore:MultiSelectCustomFieldRef",
187
+ value: [
188
+ {
189
+ internal_id: 405,
190
+ type_id: 157
191
+ },
192
+ {
193
+ internal_id: 419,
194
+ type_id: 157
195
+ }
196
+ ]
183
197
  }
184
198
  ]
185
199
  }
@@ -200,9 +214,28 @@ describe NetSuite::Records::CustomFieldList do
200
214
  "@xsi:type" => "platformCore:StringCustomFieldRef",
201
215
  "platformCore:value" => "foobar",
202
216
  },
217
+ {
218
+ '@scriptId' => 'custbody_multipleselectfield',
219
+ '@xsi:type' => 'platformCore:MultiSelectCustomFieldRef',
220
+ 'platformCore:value' => [
221
+ {
222
+ :@internalId => 405,
223
+ :@typeId => "157"
224
+ },
225
+ {
226
+ :@internalId => 419,
227
+ :@typeId => "157"
228
+ }
229
+ ]
230
+ }
203
231
  ]
204
232
  }
205
233
 
234
+ # field accessors are tested elsewhere, but let's run tests here to check various field types
235
+ expect(list).to respond_to(:custbody_multipleselectfield)
236
+ expect(list).to respond_to(:custbody_salesclassification)
237
+ expect(list).to respond_to(:custentity_registeredonline)
238
+
206
239
  expect(list.to_record).to eql(record)
207
240
  expect(list.to_record.length).to eq(1)
208
241
  end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::CustomerSalesTeamList do
4
+ let(:list) { NetSuite::Records::CustomerSalesTeamList.new }
5
+
6
+ it 'has an customer_sales_team attribute' do
7
+ expect(list.sales_team).to be_kind_of(Array)
8
+ end
9
+
10
+ describe '#to_record' do
11
+ it 'can represent itself as a SOAP record' do
12
+ list.replace_all = true
13
+
14
+ record = {
15
+ 'listRel:salesTeam' => [],
16
+ 'listRel:replaceAll' => true
17
+ }
18
+ expect(list.to_record).to eql(record)
19
+ end
20
+ end
21
+
22
+ describe "#replace_all" do
23
+ it "can be changed via accessor" do
24
+ list.replace_all = false
25
+
26
+ expect(list.replace_all).to eql(false)
27
+ end
28
+
29
+ it "coerces to a boolean" do
30
+ list.replace_all = "goober"
31
+
32
+ record = {
33
+ 'listRel:salesTeam' => [],
34
+ 'listRel:replaceAll' => true
35
+ }
36
+
37
+ expect(list.to_record).to eql(record)
38
+ end
39
+ end
40
+
41
+ end
@@ -17,7 +17,7 @@ describe NetSuite::Records::Customer do
17
17
  :opening_balance, :opening_balance_account, :opening_balance_date, :overdue_balance,
18
18
  :password, :password2, :phone, :phonetic_name, :pref_cc_processor,:print_on_check_as,
19
19
  :print_transactions, :referrer, :reminder_days, :representing_subsidiary, :require_pwd_change, :resale_number,
20
- :sales_group, :sales_readiness, :sales_team_list, :salutation, :send_email, :ship_complete,
20
+ :sales_group, :sales_readiness, :salutation, :send_email, :ship_complete,
21
21
  :stage, :start_date, :sync_partner_teams, :tax_exempt, :taxable,
22
22
  :third_party_acct, :third_party_country, :third_party_zipcode, :title, :unbilled_orders, :url,
23
23
  :vat_reg_number, :visits, :web_lead
@@ -85,6 +85,27 @@ describe NetSuite::Records::Customer do
85
85
  end
86
86
  end
87
87
 
88
+ describe '#subscriptions_list' do
89
+ it 'can be set from attributes' do
90
+ customer.subscriptions_list = {
91
+ subscriptions: [
92
+ {
93
+ :subscribed => true
94
+ }
95
+ ]
96
+ }
97
+ expect(customer.subscriptions_list).to be_kind_of(NetSuite::Records::CustomerSubscriptionsList)
98
+ expect(customer.subscriptions_list.subscriptions.length).to eql(1)
99
+ end
100
+
101
+ it 'can be set from a CustomerSubscriptionsList object' do
102
+ customer_subscriptions_list = NetSuite::Records::CustomerSubscriptionsList.new
103
+ customer.subscriptions_list = customer_subscriptions_list
104
+ expect(customer.subscriptions_list).to eql(customer_subscriptions_list)
105
+ end
106
+ end
107
+
108
+
88
109
  describe '.get' do
89
110
  context 'when the response is successful' do
90
111
  let(:response) { NetSuite::Response.new(:success => true, :body => { :is_person => true }) }
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::CustomerSubscription do
4
+
5
+ before do
6
+ NetSuite::Configuration.api_version = '2014_2'
7
+ end
8
+
9
+ let(:attributes) do
10
+ {
11
+ :subscription => {
12
+ :subscribed => true,
13
+ :subscription => NetSuite::Records::RecordRef.new(internal_id: '123123', name: 'My Sub'),
14
+ :last_modified_date => DateTime.new(2018, 1, 1, 0, 0, 0)
15
+ }
16
+ }
17
+ end
18
+
19
+ let(:list) { NetSuite::Records::CustomerSubscription.new(attributes) }
20
+
21
+ it 'has all the right fields' do
22
+ [
23
+ :subscribed, :last_modified_date
24
+ ].each do |field|
25
+ expect(list).to have_field(field)
26
+ end
27
+
28
+ expect(list.subscription).to_not be_nil
29
+ end
30
+
31
+ describe '#initialize' do
32
+ context 'when taking in a hash of attributes' do
33
+ it 'sets the attributes for the object given the attributes hash' do
34
+ expect(list.subscription.subscribed).to eql(true)
35
+ expect(list.subscription.subscription.internal_id).to eql('123123')
36
+ expect(list.subscription.subscription.name).to eql('My Sub')
37
+ expect(list.subscription.last_modified_date).to_not be_nil
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::CustomerSubscriptionsList do
4
+ let(:list) { NetSuite::Records::CustomerSubscriptionsList.new }
5
+
6
+ it 'has a subscriptions attribute' do
7
+ expect(list.subscriptions).to be_kind_of(Array)
8
+ end
9
+
10
+ describe '#to_record' do
11
+ it 'can represent itself as a SOAP record' do
12
+
13
+ record = {
14
+ 'listRel:subscriptions' => []
15
+ }
16
+ expect(list.to_record).to eql(record)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ describe NetSuite::Records::EntityCustomField do
4
+ describe ".get" do
5
+ context "success" do
6
+ let(:internal_id) { 1 }
7
+ let(:response) do
8
+ NetSuite::Response.new(
9
+ success: true,
10
+ body: {
11
+ access_level: "_edit",
12
+ field_type: "_integerNumber",
13
+ label: "Salesforce Customer ID",
14
+ show_in_list: true,
15
+ }
16
+ )
17
+ end
18
+
19
+ it "returns a EntityCustomField instance with populated fields" do
20
+ expect(NetSuite::Actions::Get)
21
+ .to receive(:call)
22
+ .with([NetSuite::Records::EntityCustomField, internal_id: internal_id], {})
23
+ .and_return(response)
24
+
25
+ record = NetSuite::Records::EntityCustomField.get(internal_id: internal_id)
26
+
27
+ expect(record.access_level).to eql("_edit")
28
+ expect(record.field_type).to eql("_integerNumber")
29
+ expect(record.label).to eql("Salesforce Customer ID")
30
+ expect(record.show_in_list).to eq(true)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -5,21 +5,23 @@ describe NetSuite::Records::PricingMatrix do
5
5
  it "behaves appropriately if it gets a hash as attributes[:pricing]" do
6
6
  # this is what savon returns if there is only one pricing strategy matrix
7
7
  # for the item:
8
- matrix = {
9
- :pricing=> {
10
- :currency=>"US Dollar",
11
- :priceLevel=>"Base Price",
12
- :priceList=>[
13
- {:price=>{:value=>12.0, :quantity=>0.0}},
14
- {:price=>{:value=>10.0, :quantity=>10.0}},
15
- {:price=>{:value=>9.0, :quantity=>100.0}},
16
- {:price=>{:value=>7.0, :quantity=>5000.0}}
17
- ]
8
+ matrix = [
9
+ {
10
+ currency: { internal_id: 1 },
11
+ price_level: { internal_id: 1 },
12
+ price_list: {
13
+ price: [
14
+ {
15
+ value: 25.0,
16
+ quantity: 0
17
+ }
18
+ ]
19
+ }
18
20
  }
19
- }
21
+ ]
20
22
 
21
- subject = NetSuite::Records::PricingMatrix.new({pricing: matrix})
22
- expect(subject.prices[0].pricing).to eq(matrix[:pricing])
23
+ subject = described_class.new({pricing: matrix})
24
+ expect(subject.pricing[0]).to be_kind_of(NetSuite::Records::Pricing)
23
25
  end
24
26
  end
25
27
  end
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+
3
+ describe NetSuite::Records::TransactionBodyCustomField do
4
+ describe ".get" do
5
+ context "success" do
6
+ let(:internal_id) { 1 }
7
+ let(:response) do
8
+ NetSuite::Response.new(
9
+ success: true,
10
+ body: {
11
+ access_level: "_edit",
12
+ field_type: "_freeFormText",
13
+ label: "Billing System Subdomain",
14
+ }
15
+ )
16
+ end
17
+
18
+ it "returns a TransactionColumnCustomField instance with populated fields" do
19
+ expect(NetSuite::Actions::Get)
20
+ .to receive(:call)
21
+ .with([NetSuite::Records::TransactionBodyCustomField, internal_id: internal_id], {})
22
+ .and_return(response)
23
+
24
+ record = NetSuite::Records::TransactionBodyCustomField.get(internal_id: internal_id)
25
+
26
+ expect(record.access_level).to eql("_edit")
27
+ expect(record.field_type).to eql("_freeFormText")
28
+ expect(record.label).to eql("Billing System Subdomain")
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+
3
+ describe NetSuite::Records::TransactionColumnCustomField do
4
+ describe ".get" do
5
+ context "success" do
6
+ let(:internal_id) { 1 }
7
+ let(:response) do
8
+ NetSuite::Response.new(
9
+ success: true,
10
+ body: {
11
+ access_level: "_none",
12
+ field_type: "_decimalNumber",
13
+ label: "Billing System Tax",
14
+ }
15
+ )
16
+ end
17
+
18
+ it "returns a TransactionColumnCustomField instance with populated fields" do
19
+ expect(NetSuite::Actions::Get)
20
+ .to receive(:call)
21
+ .with([NetSuite::Records::TransactionColumnCustomField, internal_id: internal_id], {})
22
+ .and_return(response)
23
+
24
+ record = NetSuite::Records::TransactionColumnCustomField.get(internal_id: internal_id)
25
+
26
+ expect(record.access_level).to eql("_none")
27
+ expect(record.field_type).to eql("_decimalNumber")
28
+ expect(record.label).to eql("Billing System Tax")
29
+ end
30
+ end
31
+ end
32
+ end