netsuite 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
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