netsuite 0.8.2 → 0.8.3

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +69 -20
  3. data/lib/netsuite.rb +11 -0
  4. data/lib/netsuite/actions/search.rb +1 -6
  5. data/lib/netsuite/actions/update_list.rb +109 -0
  6. data/lib/netsuite/records/bin_transfer.rb +38 -0
  7. data/lib/netsuite/records/bin_transfer_inventory.rb +20 -0
  8. data/lib/netsuite/records/bin_transfer_inventory_list.rb +10 -0
  9. data/lib/netsuite/records/cash_refund_item.rb +1 -1
  10. data/lib/netsuite/records/classification.rb +1 -1
  11. data/lib/netsuite/records/inbound_shipment.rb +33 -0
  12. data/lib/netsuite/records/inbound_shipment_item.rb +39 -0
  13. data/lib/netsuite/records/inbound_shipment_item_list.rb +11 -0
  14. data/lib/netsuite/records/inter_company_journal_entry.rb +48 -0
  15. data/lib/netsuite/records/inter_company_journal_entry_line.rb +28 -0
  16. data/lib/netsuite/records/inter_company_journal_entry_line_list.rb +14 -0
  17. data/lib/netsuite/records/inventory_item.rb +1 -1
  18. data/lib/netsuite/records/price_level.rb +26 -0
  19. data/lib/netsuite/records/return_authorization_item.rb +1 -1
  20. data/lib/netsuite/records/sales_order_item.rb +12 -5
  21. data/lib/netsuite/records/support_case.rb +1 -1
  22. data/lib/netsuite/support/actions.rb +2 -0
  23. data/lib/netsuite/support/search_result.rb +7 -3
  24. data/lib/netsuite/utilities.rb +26 -0
  25. data/lib/netsuite/version.rb +1 -1
  26. data/spec/netsuite/actions/update_list_spec.rb +107 -0
  27. data/spec/netsuite/records/basic_record_spec.rb +5 -1
  28. data/spec/netsuite/records/inter_company_journal_entry_line_list_spec.rb +26 -0
  29. data/spec/netsuite/records/inter_company_journal_entry_line_spec.rb +60 -0
  30. data/spec/netsuite/records/inter_company_journal_entry_spec.rb +156 -0
  31. data/spec/netsuite/records/inventory_item_spec.rb +57 -0
  32. data/spec/netsuite/records/price_level_spec.rb +16 -0
  33. data/spec/netsuite/records/return_authorization_item_spec.rb +1 -1
  34. data/spec/netsuite/records/sales_order_item_spec.rb +11 -5
  35. data/spec/netsuite/utilities_spec.rb +21 -0
  36. data/spec/support/fixtures/update_list/update_list_items.xml +22 -0
  37. data/spec/support/fixtures/update_list/update_list_one_item.xml +18 -0
  38. data/spec/support/fixtures/update_list/update_list_with_errors.xml +32 -0
  39. metadata +29 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 797165a82ff004915fd35446c562b168fef1d8a8
4
- data.tar.gz: 361bb3b3119d401e475df8c89e32a4c943b4f3eb
3
+ metadata.gz: cda0456bc8a4964f260bb7e484b64524728ea57a
4
+ data.tar.gz: cbf7749dc5c04d32f6bb2c59f71bb3693a1fdda5
5
5
  SHA512:
6
- metadata.gz: c91ea28fb5fe26b22bfb01fa5db2006cc18cfe7c2a6957cfe87d3b08b2a734ea091bbfccd2f430eb1ceb7cc8f95c809f67feb451c4ae7681c4f4de236e752fec
7
- data.tar.gz: 5d70ad8c9b507230a4f2a7db2a114eb15ea92d46801d84d89de7b002adf1f65f75e4698f869ddb6a59b570a994896b15b42ce90088e78548850581a46e0670ec
6
+ metadata.gz: f7e304a05344e3611a0f84741d9acf258bd10b4a6599735778514408dbd3dd1b02d5e697f07a798ab613af3ba3e77238ae394f661c66324ec2eaa38cdbf0d107
7
+ data.tar.gz: f083d2d5c1b982a378a151b47a8e423524727dc9fc346e25093f9f53bbc4e8e3a0cd0b49b16196643ea5cc8e1918af363e04a0ecb742ed09ed169de9f0d9ae3c
data/README.md CHANGED
@@ -1,21 +1,42 @@
1
- [![Circle CI](https://circleci.com/gh/NetSweet/netsuite/tree/master.svg?style=svg)](https://circleci.com/gh/NetSweet/netsuite/tree/master)
2
- [![Slack Status](https://opensuite-slackin.herokuapp.com/badge.svg)](http://opensuite-slackin.herokuapp.com)
3
- [![Gem Version](https://badge.fury.io/rb/netsuite.svg)](http://badge.fury.io/rb/netsuite)
1
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
2
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
3
+ **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
4
+
5
+ - [NetSuite SuiteTalk API Ruby Gem](#netsuite-suitetalk-api-ruby-gem)
6
+ - [Help & Support](#help--support)
7
+ - [Testing](#testing)
8
+ - [Installation](#installation)
9
+ - [Configuration](#configuration)
10
+ - [Token based Authentication](#token-based-authentication)
11
+ - [Usage](#usage)
12
+ - [CRUD Operations](#crud-operations)
13
+ - [Custom Records & Fields](#custom-records--fields)
14
+ - [Searching](#searching)
15
+ - [Non-standard Operations](#non-standard-operations)
16
+ - [About SuiteSync](#about-suitesync)
17
+
18
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
19
+
20
+ [![Circle CI](https://circleci.com/gh/NetSweet/netsuite/tree/master.svg?style=svg)](https://circleci.com/gh/NetSweet/netsuite/tree/master)
21
+ [![Slack Status](https://opensuite-slackin.herokuapp.com/badge.svg)](http://opensuite-slackin.herokuapp.com)
22
+ [![Gem Version](https://badge.fury.io/rb/netsuite.svg)](http://badge.fury.io/rb/netsuite)
4
23
  [![Dependency Status](https://gemnasium.com/roidrage/lograge.svg)](https://gemnasium.com/netsweet/netsuite)
5
24
 
6
- # NetSuite Ruby SuiteTalk API Gem
25
+ # NetSuite SuiteTalk API Ruby Gem
7
26
 
8
27
  * This gem will act as a wrapper around the NetSuite SuiteTalk WebServices API.
9
28
  * The gem does not cover the entire API, only the subset contributors have used so far.
10
- * NetSuite is a huge complex system. There's a lot to learn and sparse resources available to learn from. Here's a list of [NetSuite Development Resources](https://github.com/NetSweet/netsuite/wiki/NetSuite-Development-Resources) that might make things a bit less painful.
29
+ * NetSuite is a complex system. There's a lot to learn and sparse resources available to learn from. Here's a list of [NetSuite Development Resources](https://github.com/NetSweet/netsuite/wiki/NetSuite-Development-Resources) that might make things a bit less painful.
11
30
 
12
31
  # Help & Support
13
32
 
14
- Join the [slack channel](http://opensuite-slackin.herokuapp.com) for help with any NetSuite issues.
33
+ Join the [slack channel](http://opensuite-slackin.herokuapp.com) for help with any NetSuite issues. Please do not post usage questions as issues in GitHub.
15
34
 
16
- Please do not post usage questions as issues in GitHub.
35
+ Messages in the Slack ground are [archived here](https://suitechat.slackarchive.io). Search the archives to see if your question has been answered before.
17
36
 
18
- ## Testing
37
+ There is some additional helpful resources for NetSuite development [listed here](https://dashboard.suitesync.io/docs/resources#netsuite).
38
+
39
+ # Testing
19
40
 
20
41
  Before contributing a patch make sure all existing tests pass.
21
42
 
@@ -26,9 +47,7 @@ bundle
26
47
  bundle exec rspec
27
48
  ```
28
49
 
29
- ## Usage
30
-
31
- ### Installation
50
+ # Installation
32
51
 
33
52
  Add this line to your application's Gemfile:
34
53
 
@@ -38,7 +57,7 @@ gem 'netsuite'
38
57
 
39
58
  This gem is built for ruby 1.9.x+, checkout the [1-8-stable](https://github.com/NetSweet/netsuite/tree/1-8-stable) branch for ruby 1.8.x support.
40
59
 
41
- ### Configuration
60
+ ## Configuration
42
61
 
43
62
  Not sure how to find your account id? Search for "web service preferences" in the NetSuite global search.
44
63
 
@@ -53,10 +72,14 @@ NetSuite.configure do
53
72
  wsdl "https://webservices.sandbox.netsuite.com/wsdl/v#{api_version}_0/netsuite.wsdl"
54
73
 
55
74
  # if your datacenter is being switched, you'll have to manually set your wsdl location
56
- wsdl "https://webservices.na2.netsuite.com/wsdl/v#{api_version}_0/netsuite.wsdl"
75
+ wsdl "https://webservices.na2.netsuite.com/wsdl/v#{api_version}_0/netsuite.wsdl"
76
+
77
+ # or specify the wsdl_domain if you want to specify the datacenter and let the configuration
78
+ # construct the full wsdl location - e.g. "https://#{wsdl_domain}/wsdl/v#{api_version}_0/netsuite.wsdl"
79
+ wsdl_domain "webservices.na2.netsuite.com"
57
80
 
58
81
  # or specify the sandbox flag if you don't want to deal with specifying a full URL
59
- sandbox true
82
+ sandbox true
60
83
 
61
84
  # often the netsuite servers will hang which would cause a timeout exception to be raised
62
85
  # if you don't mind waiting (e.g. processing NS via DJ), increasing the timeout should fix the issue
@@ -70,7 +93,7 @@ NetSuite.configure do
70
93
  password 'password'
71
94
  account '12345'
72
95
  role 1111
73
-
96
+
74
97
  # optional, ensures that read-only fields don't cause API errors
75
98
  soap_header 'platformMsgs:preferences' => {
76
99
  'platformMsgs:ignoreReadOnlyFields' => true,
@@ -88,6 +111,8 @@ NetSuite::Configuration.soap_header = {
88
111
  }
89
112
  ```
90
113
 
114
+ ### Token based Authentication
115
+
91
116
  OAuth credentials are also supported. [Learn more about how to set up token based authentication here](http://mikebian.co/using-netsuites-token-based-authentication-with-suitetalk/).
92
117
 
93
118
  ```ruby
@@ -106,9 +131,9 @@ NetSuite.configure do
106
131
  end
107
132
  ```
108
133
 
109
- ### Examples
134
+ # Usage
110
135
 
111
- #### CRUD Operations
136
+ ## CRUD Operations
112
137
 
113
138
  ```ruby
114
139
  # get a customer
@@ -167,7 +192,7 @@ options = NetSuite::Records::BaseRefList.get_select_value(
167
192
  options.base_refs.map(&:name)
168
193
  ```
169
194
 
170
- #### Custom Records & Fields
195
+ ## Custom Records & Fields
171
196
 
172
197
  ```ruby
173
198
  # updating a custom field list on a record
@@ -218,7 +243,7 @@ NetSuite::Records::BaseRefList.get_select_value(
218
243
  )
219
244
  ```
220
245
 
221
- #### Searching
246
+ ## Searching
222
247
 
223
248
  ```ruby
224
249
  # basic search
@@ -379,6 +404,26 @@ NetSuite::Records::SalesOrder.search({
379
404
  }
380
405
  }).results
381
406
 
407
+ # Search for SalesOrder records with a "Pending Approval" status using the TransactionStatus enum value.
408
+ # https://system.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2016_2/schema/enum/transactionstatus.html
409
+
410
+ NetSuite::Records::SalesOrder.search(
411
+ criteria: {
412
+ basic: [
413
+ {
414
+ field: 'type',
415
+ operator: 'anyOf',
416
+ value: ['_salesOrder'],
417
+ },
418
+ {
419
+ field: 'status',
420
+ operator: 'anyOf',
421
+ value: ['_salesOrderPendingApproval'],
422
+ },
423
+ ],
424
+ },
425
+ )
426
+
382
427
  NetSuite::Records::ItemFulfillment.search({
383
428
  criteria: {
384
429
  basic: [
@@ -502,7 +547,7 @@ deposit.payment = 20
502
547
  deposit.add
503
548
  ```
504
549
 
505
- #### Non-standard Operations
550
+ ## Non-standard Operations
506
551
 
507
552
  ```ruby
508
553
  # making a call that hasn't been implemented yet
@@ -522,3 +567,7 @@ states = NetSuite::Configuration.connection.call(:get_all, message: {
522
567
  })
523
568
  states.to_array.first[:get_all_response][:get_all_result][:record_list][:record].map { |r| { country: r[:country], abbr: r[:shortname], name: r[:full_name] } }
524
569
  ```
570
+
571
+ # About SuiteSync
572
+
573
+ [SuiteSync, the Stripe-NetSuite integration](http://suitesync.io) uses this gem and funds the majority of it's development and maintenance.
@@ -58,6 +58,7 @@ module NetSuite
58
58
  autoload :GetSelectValue, 'netsuite/actions/get_select_value'
59
59
  autoload :Initialize, 'netsuite/actions/initialize'
60
60
  autoload :Update, 'netsuite/actions/update'
61
+ autoload :UpdateList, 'netsuite/actions/update_list'
61
62
  autoload :Upsert, 'netsuite/actions/upsert'
62
63
  autoload :UpsertList, 'netsuite/actions/upsert_list'
63
64
  autoload :Search, 'netsuite/actions/search'
@@ -82,6 +83,9 @@ module NetSuite
82
83
  autoload :BillingScheduleRecurrenceList, 'netsuite/records/billing_schedule_recurrence_list'
83
84
  autoload :Bin, 'netsuite/records/bin'
84
85
  autoload :BinNumberList, 'netsuite/records/bin_number_list'
86
+ autoload :BinTransfer, 'netsuite/records/bin_transfer'
87
+ autoload :BinTransferInventory, 'netsuite/records/bin_transfer_inventory'
88
+ autoload :BinTransferInventoryList, 'netsuite/records/bin_transfer_inventory_list'
85
89
  autoload :CashSale, 'netsuite/records/cash_sale'
86
90
  autoload :CashSaleItem, 'netsuite/records/cash_sale_item'
87
91
  autoload :CashSaleItemList, 'netsuite/records/cash_sale_item_list'
@@ -150,6 +154,12 @@ module NetSuite
150
154
  autoload :GiftCertRedemption, 'netsuite/records/gift_cert_redemption'
151
155
  autoload :GiftCertRedemptionList, 'netsuite/records/gift_cert_redemption_list'
152
156
  autoload :Folder, 'netsuite/records/folder'
157
+ autoload :InboundShipment, 'netsuite/records/inbound_shipment'
158
+ autoload :InboundShipmentItem, 'netsuite/records/inbound_shipment_item'
159
+ autoload :InboundShipmentItemList, 'netsuite/records/inbound_shipment_item_list'
160
+ autoload :InterCompanyJournalEntry, 'netsuite/records/inter_company_journal_entry'
161
+ autoload :InterCompanyJournalEntryLine, 'netsuite/records/inter_company_journal_entry_line'
162
+ autoload :InterCompanyJournalEntryLineList, 'netsuite/records/inter_company_journal_entry_line_list'
153
163
  autoload :InventoryAdjustment, 'netsuite/records/inventory_adjustment'
154
164
  autoload :InventoryAdjustmentInventory, 'netsuite/records/inventory_adjustment_inventory'
155
165
  autoload :InventoryAdjustmentInventoryList, 'netsuite/records/inventory_adjustment_inventory_list'
@@ -204,6 +214,7 @@ module NetSuite
204
214
  autoload :PaymentMethod, 'netsuite/records/payment_method'
205
215
  autoload :PayrollItem, 'netsuite/records/payroll_item'
206
216
  autoload :PhoneCall, 'netsuite/records/phone_call'
217
+ autoload :PriceLevel, 'netsuite/records/price_level'
207
218
  autoload :PricingMatrix, 'netsuite/records/pricing_matrix'
208
219
  autoload :PromotionCode, 'netsuite/records/promotion_code'
209
220
  autoload :PurchaseOrder, 'netsuite/records/purchase_order'
@@ -232,11 +232,6 @@ module NetSuite
232
232
  @success ||= search_result[:status][:@is_success] == 'true'
233
233
  end
234
234
 
235
- protected
236
- def method_name
237
-
238
- end
239
-
240
235
  module Support
241
236
  def self.included(base)
242
237
  base.extend(ClassMethods)
@@ -247,7 +242,7 @@ module NetSuite
247
242
  response = NetSuite::Actions::Search.call([self, options], credentials)
248
243
 
249
244
  if response.success?
250
- NetSuite::Support::SearchResult.new(response, self)
245
+ NetSuite::Support::SearchResult.new(response, self, credentials)
251
246
  else
252
247
  false
253
248
  end
@@ -0,0 +1,109 @@
1
+ # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/updateList.html
2
+ module NetSuite
3
+ module Actions
4
+ class UpdateList
5
+ include Support::Requests
6
+
7
+ def initialize(*objects)
8
+ @objects = objects
9
+ end
10
+
11
+ private
12
+
13
+ def request(credentials={})
14
+ NetSuite::Configuration.connection(
15
+ { element_form_default: :unqualified }, credentials
16
+ ).call(:update_list, message: request_body)
17
+ end
18
+
19
+ # <soap:Body>
20
+ # <updateList>
21
+ # <record xsi:type="listRel:Customer" externalId="ext1">
22
+ # <listRel:entityId>Shutter Fly</listRel:entityId>
23
+ # <listRel:companyName>Shutter Fly, Inc</listRel:companyName>
24
+ # </record>
25
+ # <record xsi:type="listRel:Customer" externalId="ext2">
26
+ # <listRel:entityId>Target</listRel:entityId>
27
+ # <listRel:companyName>Target</listRel:companyName>
28
+ # </record>
29
+ # </updateList>
30
+ # </soap:Body>
31
+ def request_body
32
+ attrs = @objects.map do |o|
33
+ hash = o.to_record.merge({
34
+ '@xsi:type' => o.record_type
35
+ })
36
+
37
+ if o.respond_to?(:internal_id) && o.internal_id
38
+ hash['@internalId'] = o.internal_id
39
+ end
40
+
41
+ if o.respond_to?(:external_id) && o.external_id
42
+ hash['@externalId'] = o.external_id
43
+ end
44
+
45
+ hash
46
+ end
47
+
48
+ { 'record' => attrs }
49
+ end
50
+
51
+ def response_hash
52
+ @response_hash ||= Array[@response.body[:update_list_response][:write_response_list][:write_response]].flatten
53
+ end
54
+
55
+ def response_body
56
+ @response_body ||= response_hash.map { |h| h[:base_ref] }
57
+ end
58
+
59
+ def response_errors
60
+ if response_hash.any? { |h| h[:status] && h[:status][:status_detail] }
61
+ @response_errors ||= errors
62
+ end
63
+ end
64
+
65
+ def errors
66
+ errors = response_hash.select { |h| h[:status] && h[:status][:status_detail] }.map do |obj|
67
+ error_obj = obj[:status][:status_detail]
68
+ error_obj = [error_obj] if error_obj.class == Hash
69
+ errors = error_obj.map do |error|
70
+ NetSuite::Error.new(error)
71
+ end
72
+
73
+ [obj[:base_ref][:@internal_id], errors]
74
+ end
75
+ Hash[errors]
76
+ end
77
+
78
+ def success?
79
+ @success ||= response_hash.all? { |h| h[:status][:@is_success] == 'true' }
80
+ end
81
+
82
+ module Support
83
+
84
+ def self.included(base)
85
+ base.extend(ClassMethods)
86
+ end
87
+
88
+ module ClassMethods
89
+ def update_list(records, credentials = {})
90
+ netsuite_records = records.map do |r|
91
+ if r.kind_of?(self)
92
+ r
93
+ else
94
+ self.new(r)
95
+ end
96
+ end
97
+ response = NetSuite::Actions::UpdateList.call(netsuite_records, credentials)
98
+
99
+ if response.success?
100
+ netsuite_records
101
+ else
102
+ false
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,38 @@
1
+ module NetSuite
2
+ module Records
3
+ class BinTransfer
4
+ include Support::Fields
5
+ include Support::RecordRefs
6
+ include Support::Records
7
+ include Support::Actions
8
+ include Namespaces::TranInvt
9
+
10
+ actions :get, :get_list, :add, :initialize, :delete, :update, :upsert, :search
11
+
12
+ fields :created_date, :last_modified_date, :memo, :subsidiary, :tran_date, :tran_id
13
+
14
+ record_refs :location
15
+
16
+ field :custom_field_list, CustomFieldList
17
+ field :inventory_list, BinTransferInventoryList
18
+
19
+ attr_reader :internal_id
20
+ attr_accessor :external_id
21
+
22
+ def initialize(attributes = {})
23
+ @internal_id = attributes.delete(:internal_id) || attributes.delete(:@internal_id)
24
+ @external_id = attributes.delete(:external_id) || attributes.delete(:@external_id)
25
+ initialize_from_attributes_hash(attributes)
26
+ end
27
+
28
+ def self.search_class_name
29
+ "Transaction"
30
+ end
31
+
32
+ def self.search_class_namespace
33
+ 'tranSales'
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ module NetSuite
2
+ module Records
3
+ class BinTransferInventory
4
+ include Support::Records
5
+ include Support::Fields
6
+ include Support::RecordRefs
7
+ include Namespaces::TranInvt
8
+
9
+ fields :description, :from_bins, :item_units_label, :line, :preferred_bin, :quantity, :to_bins
10
+
11
+ field :inventory_detail, InventoryDetail
12
+
13
+ record_refs :item
14
+
15
+ def initialize(attributes = {})
16
+ initialize_from_attributes_hash(attributes)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ module NetSuite
2
+ module Records
3
+ class BinTransferInventoryList < Support::Sublist
4
+ include Namespaces::TranInvt
5
+
6
+ sublist :inventory, BinTransferInventory
7
+
8
+ end
9
+ end
10
+ end
@@ -6,7 +6,7 @@ module NetSuite
6
6
  include Support::Records
7
7
  include Namespaces::TranCust
8
8
 
9
- fields :amount, :rate, :quantity
9
+ fields :amount, :rate, :quantity, :is_taxable, :order_line, :line, :description
10
10
  field :custom_field_list, CustomFieldList
11
11
 
12
12
  record_refs :item, :klass, :price
@@ -9,7 +9,7 @@ module NetSuite
9
9
 
10
10
  actions :get, :get_list, :delete, :upsert, :search
11
11
 
12
- fields :name, :include_children, :is_inactive, :class_translation_list, :custom_field_list
12
+ fields :name, :include_children, :is_inactive, :class_translation_list, :custom_field_list, :parent
13
13
 
14
14
  field :subsidiary_list, RecordRefList
15
15