netsuite 0.2.3 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c137a01aff81975a25856d832bc61d90b37468c5
4
- data.tar.gz: afbbaf1726823511a72bef89702f09011c87ceb0
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MTRlZDk0NGYwODZlOTA3OGZmMGQ2MDllMTdmNDNlZDI5YmY4ODNjYw==
5
+ data.tar.gz: !binary |-
6
+ ZTA3YTgyYTE5ZDAxNWUyY2ZiNmViODlmNGE1NTY4MjFlY2U2OGI5Ng==
5
7
  SHA512:
6
- metadata.gz: ec904bf4c128f98da10e50688e3b2ffbfc81fe933c96001fce48f9e9788c1d2df5067206ce19a129296930447b8560de4204776f3c8da4489676c4d57a88be68
7
- data.tar.gz: 8b1d944d17d8af49ce0fee65a965166766e50645ee1c3c759c8178fcfbb094f22e5d83f83cb1e1a8b15a3c614a84630cd5ab15acff64574d77fb5094264ba62f
8
+ metadata.gz: !binary |-
9
+ ZWI1MDEyYWRjNmY3YzNlYWY2ZmUzNDlkNjYzZDgyNGI1YzA5OTg5ZjA0YzQ2
10
+ N2I3YzUzNDU3NGRjYjA2NjQ0MjZmMWY4ZmNjYTc0MzM4N2UxNjVlMWExZWUy
11
+ ODUwYzBjM2QzNTI1NGZkNDZiNWM1ODE5M2FmZGVkNWYwNWU0NmQ=
12
+ data.tar.gz: !binary |-
13
+ OTI5Mzc5MWE1NTg1YjUxZWUzYjhlMWIxYmNiZjZkMmVmODUxNDMzOGFkMTg0
14
+ OGFmZjc5NmMyOGNhZGE0NzJlZTVkYjU2ZWU5YTQwMWYwNmU2NjU2NmExYWNl
15
+ NDAwZWNmMzk2ZTEzOWM3ZWRhOWJjODg4OTljN2ZkMzU4ZmYwM2Y=
data/README.md CHANGED
@@ -265,4 +265,13 @@ NetSuite::Records::BaseRefList.get_select_value(
265
265
  '@xsi:type' => 'customRecord'
266
266
  }
267
267
  )
268
+
269
+ # updating a custom field list
270
+ # you need to push ALL the values of ALL of the custom fields that you want set on the record
271
+ # you can't just push the values of the fields that you want to update: all of the values of
272
+ # other fields will then fall back to their default values
273
+ contact = NetSuite::Records::Contact.get(12345)
274
+ contact.custom_field_list.custentity_alistfield = { internal_id: 1 }
275
+ contact.custom_field_list.custentity_abooleanfield = true
276
+ contact.update(custom_field_list: contact.custom_field_list)
268
277
  ```
@@ -3,6 +3,7 @@ require 'set'
3
3
  require 'savon'
4
4
  require 'netsuite/version'
5
5
  require 'netsuite/errors'
6
+ require 'netsuite/utilities'
6
7
  require 'netsuite/core_ext/string/lower_camelcase'
7
8
 
8
9
  module NetSuite
@@ -16,6 +17,7 @@ module NetSuite
16
17
  autoload :ListSupport, 'netsuite/namespaces/list_support'
17
18
  autoload :PlatformCommon, 'netsuite/namespaces/platform_common'
18
19
  autoload :PlatformCore, 'netsuite/namespaces/platform_core'
20
+ autoload :TranBank, 'netsuite/namespaces/tran_bank'
19
21
  autoload :TranCust, 'netsuite/namespaces/tran_cust'
20
22
  autoload :TranGeneral, 'netsuite/namespaces/tran_general'
21
23
  autoload :TranSales, 'netsuite/namespaces/tran_sales'
@@ -40,6 +42,7 @@ module NetSuite
40
42
  autoload :GetSelectValue, 'netsuite/actions/get_select_value'
41
43
  autoload :Initialize, 'netsuite/actions/initialize'
42
44
  autoload :Update, 'netsuite/actions/update'
45
+ autoload :Upsert, 'netsuite/actions/upsert'
43
46
  autoload :Search, 'netsuite/actions/search'
44
47
  autoload :SearchMoreWithId, 'netsuite/actions/search_more_with_id'
45
48
  end
@@ -78,6 +81,9 @@ module NetSuite
78
81
  autoload :ContactList, 'netsuite/records/contact_list'
79
82
  autoload :Contact, 'netsuite/records/contact'
80
83
  autoload :Department, 'netsuite/records/department'
84
+ autoload :Deposit, 'netsuite/records/deposit'
85
+ autoload :DepositPayment, 'netsuite/records/deposit_payment'
86
+ autoload :DepositPaymentList, 'netsuite/records/deposit_payment_list'
81
87
  autoload :Duration, 'netsuite/records/duration'
82
88
  autoload :InventoryItem, 'netsuite/records/inventory_item'
83
89
  autoload :Invoice, 'netsuite/records/invoice'
@@ -0,0 +1,89 @@
1
+ module NetSuite
2
+ module Actions
3
+ class Upsert
4
+ include Support::Requests
5
+
6
+ attr_reader :response_hash
7
+
8
+ def initialize(object = nil)
9
+ @object = object
10
+ end
11
+
12
+ private
13
+
14
+ def request
15
+ NetSuite::Configuration.connection.call :upsert, :message => request_body
16
+ end
17
+
18
+ # <soap:Body>
19
+ # <platformMsgs:upsert>
20
+ # <platformMsgs:record xsi:type="listRel:Customer">
21
+ # <listRel:entityId>Shutter Fly</listRel:entityId>
22
+ # <listRel:companyName>Shutter Fly, Inc</listRel:companyName>
23
+ # </platformMsgs:record>
24
+ # </platformMsgs:upsert>
25
+ # </soap:Body>
26
+
27
+ def request_body
28
+ hash = {
29
+ 'platformMsgs:record' => {
30
+ :content! => @object.to_record,
31
+ '@xsi:type' => @object.record_type
32
+ }
33
+ }
34
+
35
+ if @object.respond_to?(:internal_id) && @object.internal_id
36
+ hash['platformMsgs:record']['@platformMsgs:internalId'] = @object.internal_id
37
+ end
38
+
39
+ if @object.respond_to?(:external_id) && @object.external_id
40
+ hash['platformMsgs:record']['@platformMsgs:externalId'] = @object.external_id
41
+ end
42
+
43
+ hash
44
+ end
45
+
46
+ def success?
47
+ @success ||= response_hash[:status][:@is_success] == 'true'
48
+ end
49
+
50
+ def response_body
51
+ @response_body ||= response_hash[:base_ref]
52
+ end
53
+
54
+ def response_errors
55
+ if response_hash[:status] && response_hash[:status][:status_detail]
56
+ @response_errors ||= errors
57
+ end
58
+ end
59
+
60
+ def response_hash
61
+ @response_hash ||= @response.to_hash[:upsert_response][:write_response]
62
+ end
63
+
64
+ def errors
65
+ error_obj = response_hash[:status][:status_detail]
66
+ error_obj = [error_obj] if error_obj.class == Hash
67
+ error_obj.map do |error|
68
+ NetSuite::Error.new(error)
69
+ end
70
+ end
71
+
72
+ module Support
73
+ def upsert
74
+ response = NetSuite::Actions::Upsert.call(self)
75
+
76
+ @errors = response.errors
77
+
78
+ if response.success?
79
+ @internal_id = response.body[:@internal_id]
80
+ true
81
+ else
82
+ false
83
+ end
84
+ end
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -86,6 +86,7 @@ module NetSuite
86
86
  'xmlns:actSched' => "urn:scheduling_#{api_version}.activities.webservices.netsuite.com",
87
87
  'xmlns:setupCustom' => "urn:customization_#{api_version}.setup.webservices.netsuite.com",
88
88
  'xmlns:listAcct' => "urn:accounting_#{api_version}.lists.webservices.netsuite.com",
89
+ 'xmlns:tranBank' => "urn:bank_#{api_version}.transactions.webservices.netsuite.com",
89
90
  'xmlns:tranCust' => "urn:customers_#{api_version}.transactions.webservices.netsuite.com",
90
91
  'xmlns:listSupport' => "urn:support_#{api_version}.lists.webservices.netsuite.com",
91
92
  'xmlns:tranGeneral' => "urn:general_#{api_version}.transactions.webservices.netsuite.com",
@@ -0,0 +1,11 @@
1
+ module NetSuite
2
+ module Namespaces
3
+ module TranBank
4
+
5
+ def record_namespace
6
+ 'tranBank'
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -7,7 +7,7 @@ module NetSuite
7
7
  include Support::Actions
8
8
  include Namespaces::TranCust
9
9
 
10
- actions :get, :add, :initialize, :delete, :update
10
+ actions :get, :add, :initialize, :delete, :update, :upsert
11
11
 
12
12
  fields :alt_handling_cost, :alt_shipping_cost, :amount_paid, :amount_remaining, :auto_apply, :balance,
13
13
  :bill_address, :contrib_pct, :created_date, :currency_name, :deferred_revenue, :discount_rate, :email,
@@ -7,7 +7,7 @@ module NetSuite
7
7
  include Support::Actions
8
8
  include Namespaces::ListRel
9
9
 
10
- actions :get, :get_list, :add, :update, :delete, :search
10
+ actions :get, :get_list, :add, :update, :upsert, :delete, :search
11
11
 
12
12
  fields :access_role, :account_number, :aging, :alt_email, :alt_name, :alt_phone, :bill_pay,
13
13
  :buying_reason, :buying_time_frame, :campaign_category, :category, :click_stream, :comments, :company_name,
@@ -0,0 +1,32 @@
1
+ module NetSuite
2
+ module Records
3
+ class Deposit
4
+ include Support::Fields
5
+ include Support::RecordRefs
6
+ include Support::Records
7
+ include Support::Actions
8
+ include Namespaces::TranBank
9
+
10
+ actions :get, :add, :delete
11
+
12
+ fields :created_date, :last_modified_date, :currency_name, :tran_id, :total, :tran_date, :memo, :to_be_printed
13
+
14
+ record_refs :custom_form, :account, :posting_period, :subsidiary, :department, :klass, :location
15
+
16
+ field :payment_list, DepositPaymentList
17
+ # field :other_list, DepositOtherList
18
+ # field :cash_back_list, DepositCashBackList
19
+ field :custom_field_list, CustomFieldList
20
+
21
+ attr_reader :internal_id
22
+ attr_accessor :external_id
23
+
24
+ def initialize(attributes = {})
25
+ @internal_id = attributes.delete(:internal_id) || attributes.delete(:@internal_id)
26
+ @external_id = attributes.delete(:external_id) || attributes.delete(:@external_id)
27
+ initialize_from_attributes_hash(attributes)
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,48 @@
1
+ module NetSuite
2
+ module Records
3
+ class DepositPayment
4
+ include Support::Fields
5
+ include Support::RecordRefs
6
+ include Support::Records
7
+ include Namespaces::TranBank
8
+
9
+ # <element name="deposit" type="xsd:boolean" minOccurs="0"/>
10
+ # <element name="id" type="xsd:long" minOccurs="0"/>
11
+ # <element name="docDate" type="xsd:dateTime" minOccurs="0"/>
12
+ # <element name="type" type="xsd:string" minOccurs="0"/>
13
+ # <element name="docNumber" type="xsd:string" minOccurs="0"/>
14
+ # <element name="memo" type="xsd:string" minOccurs="0"/>
15
+ # <element name="paymentMethod" type="platformCore:RecordRef" minOccurs="0"/>
16
+ # <element name="refNum" type="xsd:string" minOccurs="0"/>
17
+ # <element name="entity" type="platformCore:RecordRef" minOccurs="0"/>
18
+ # <element name="currency" type="platformCore:RecordRef" minOccurs="0"/>
19
+ # <element name="transactionAmount" type="xsd:double" minOccurs="0"/>
20
+ # <element name="paymentAmount" type="xsd:double" minOccurs="0"/>
21
+
22
+ fields :deposit, :id, :doc_date, :type, :doc_number, :memo, :ref_num, :transaction_amount, :payment_amount
23
+
24
+ record_refs :entity, :currency, :payment_method
25
+
26
+ def initialize(attributes_or_record = {})
27
+ case attributes_or_record
28
+ when Hash
29
+ initialize_from_attributes_hash(attributes_or_record)
30
+ when self.class
31
+ initialize_from_record(attributes_or_record)
32
+ end
33
+ end
34
+
35
+ def initialize_from_record(record)
36
+ self.attributes = record.send(:attributes)
37
+ end
38
+
39
+ def to_record
40
+ rec = super
41
+ if rec["#{record_namespace}:customFieldList"]
42
+ rec["#{record_namespace}:customFieldList!"] = rec.delete("#{record_namespace}:customFieldList")
43
+ end
44
+ rec
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,32 @@
1
+ module NetSuite
2
+ module Records
3
+ class DepositPaymentList
4
+ include Support::Fields
5
+ include Namespaces::TranBank
6
+
7
+ fields :deposit_payment
8
+
9
+ def initialize(attributes = {})
10
+ initialize_from_attributes_hash(attributes)
11
+ end
12
+
13
+ def payment=(payments)
14
+ case payments
15
+ when Hash
16
+ self.payments << DepositPayment.new(payments)
17
+ when Array
18
+ payments.each { |p| self.payments << DepositPayment.new(p) }
19
+ end
20
+ end
21
+
22
+ def payments
23
+ @payments ||= []
24
+ end
25
+
26
+ def to_record
27
+ { "#{record_namespace}:depositPayment" => payments.map(&:to_record) }
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -20,7 +20,7 @@ module NetSuite
20
20
  # }
21
21
  # ]
22
22
  #
23
- actions :get, :add, :delete, :search, :update
23
+ actions :get, :add, :delete, :search, :update, :upsert
24
24
 
25
25
  fields :auto_lead_time, :auto_preferred_stock_level, :auto_reorder_point, :available_to_partners, :average_cost,
26
26
  :copy_description, :cost, :cost_estimate, :cost_estimate_type, :cost_estimate_units, :cost_units, :costing_method,
@@ -7,7 +7,7 @@ module NetSuite
7
7
  include Support::Actions
8
8
  include Namespaces::TranSales
9
9
 
10
- actions :get, :initialize, :add, :delete
10
+ actions :get, :initialize, :add, :delete, :upsert
11
11
 
12
12
  fields :balance, :bill_address,
13
13
  :billing_schedule, :contrib_pct, :created_date, :currency_name, :custom_field_list,
@@ -1,16 +1,17 @@
1
1
  module NetSuite
2
2
  module Records
3
- class ItemFulfillment
4
- include Support::Fields
5
- include Support::RecordRefs
6
- include Support::Records
7
- include Support::Actions
8
- include Namespaces::TranSales
3
+ class ItemFulfillment
4
+ include Support::Fields
5
+ include Support::RecordRefs
6
+ include Support::Records
7
+ include Support::Actions
8
+ include Namespaces::TranSales
9
9
 
10
- actions :get, :add, :initialize, :delete
10
+ actions :get, :add, :initialize, :delete, :search
11
11
 
12
12
  fields :tran_date, :tran_id, :shipping_cost, :memo, :ship_company, :ship_attention, :ship_addr1,
13
- :ship_addr2, :ship_city, :ship_state, :ship_zip, :ship_phone, :ship_is_residential
13
+ :ship_addr2, :ship_city, :ship_state, :ship_zip, :ship_phone, :ship_is_residential,
14
+ :ship_status
14
15
 
15
16
  read_only_fields :handling_cost
16
17
 
@@ -39,6 +40,9 @@ module NetSuite
39
40
  rec
40
41
  end
41
42
 
42
- end
43
+ def self.search_class_name
44
+ "Transaction"
45
+ end
46
+ end
43
47
  end
44
- end
48
+ end
@@ -5,23 +5,23 @@ module NetSuite
5
5
  include Support::Records
6
6
  include Namespaces::TranSales
7
7
 
8
- fields :item
8
+ fields :package
9
9
 
10
10
  def initialize(attributes = {})
11
11
  initialize_from_attributes_hash(attributes)
12
12
  end
13
13
 
14
- def item=(items)
15
- case items
14
+ def package=(packages)
15
+ case packages
16
16
  when Hash
17
- self.items << ItemFulfillmentPackage.new(items)
17
+ self.packages << ItemFulfillmentPackage.new(packages)
18
18
  when Array
19
- items.each { |item| self.items << ItemFulfillmentPackage.new(item) }
19
+ packages.each { |package| self.packages << ItemFulfillmentPackage.new(package) }
20
20
  end
21
21
  end
22
22
 
23
- def items
24
- @items ||= []
23
+ def packages
24
+ @packages ||= []
25
25
  end
26
26
 
27
27
  def to_record
@@ -7,7 +7,7 @@ module NetSuite
7
7
  include Support::Actions
8
8
  include Namespaces::ListRel
9
9
 
10
- actions :get, :add, :delete, :update
10
+ actions :get, :add, :delete, :update, :upsert
11
11
 
12
12
  fields :account_number, :allocate_payroll_expenses, :allow_all_resources_for_tasks, :allow_expenses, :allow_time,
13
13
  :alt_name, :alt_phone, :bill_pay, :calculated_end_date, :calculated_end_date_baseline, :comments, :company_name,
@@ -7,7 +7,7 @@ module NetSuite
7
7
  include Support::Actions
8
8
  include Namespaces::ActSched
9
9
 
10
- actions :get, :add, :delete, :update
10
+ actions :get, :add, :delete, :update, :upsert
11
11
 
12
12
  fields :title, :message, :phone, :status, :priority, :start_date, :end_date,
13
13
  :start_time, :end_time, :completed_date, :timed_event, :access_level, :timed_event
@@ -7,7 +7,7 @@ module NetSuite
7
7
  include Support::Actions
8
8
  include Namespaces::TranSales
9
9
 
10
- actions :get, :add, :initialize, :delete, :update, :search
10
+ actions :get, :add, :initialize, :delete, :update, :upsert, :search
11
11
 
12
12
  fields :alt_handling_cost, :alt_shipping_cost, :amount_paid, :amount_remaining, :auto_apply, :balance,
13
13
  :bill_address, :contrib_pct, :created_date, :currency_name, :deferred_revenue, :discount_rate, :email, :end_date,
@@ -7,7 +7,7 @@ module NetSuite
7
7
  include Support::Actions
8
8
  include Namespaces::ListSupport
9
9
 
10
- actions :get, :add, :delete, :update
10
+ actions :get, :add, :delete, :update, :upsert
11
11
 
12
12
  fields :end_date, :incoming_message, :outgoing_message, :search_solution, :email_form,
13
13
  :internal_only, :title, :case_number, :start_date, :email, :phone, :inbound_email,
@@ -7,7 +7,7 @@ module NetSuite
7
7
  include Support::Actions
8
8
  include Namespaces::ActSched
9
9
 
10
- actions :get, :add, :search, :delete, :update
10
+ actions :get, :add, :search, :delete, :update, :upsert
11
11
 
12
12
  fields :title, :send_email, :message, :status, :access_level, :reminder_type,
13
13
  :reminder_minutes, :start_date, :end_date, :due_date, :timed_event,
@@ -6,7 +6,7 @@ module NetSuite
6
6
  @success = attributes[:success]
7
7
  @header = attributes[:header]
8
8
  @body = attributes[:body]
9
- @errors = attributes[:errors]
9
+ @errors = attributes[:errors] || []
10
10
  end
11
11
 
12
12
  def success!
@@ -16,6 +16,5 @@ module NetSuite
16
16
  def success?
17
17
  @success
18
18
  end
19
-
20
19
  end
21
20
  end
@@ -30,6 +30,8 @@ module NetSuite
30
30
  self.send(:include, NetSuite::Actions::SearchMoreWithId::Support)
31
31
  when :add
32
32
  self.send(:include, NetSuite::Actions::Add::Support)
33
+ when :upsert
34
+ self.send(:include, NetSuite::Actions::Upsert::Support)
33
35
  when :delete
34
36
  self.send(:include, NetSuite::Actions::Delete::Support)
35
37
  when :update
@@ -0,0 +1,34 @@
1
+ module NetSuite
2
+ module Utilities
3
+
4
+ # Warning this was developed with a Web Services user whose time zone was set to CST
5
+ # the time zone setting of the user seems to effect how times work in NS
6
+
7
+ # modifying time without rails:
8
+ # http://stackoverflow.com/questions/238684/subtract-n-hours-from-a-datetime-in-ruby
9
+
10
+ # converting between time and datetime:
11
+ # http://stackoverflow.com/questions/279769/convert-to-from-datetime-and-time-in-ruby
12
+
13
+ # use when sending times to NS
14
+ def self.normalize_datetime_to_netsuite(datetime)
15
+ # normalize the time to UCT0
16
+ # add 6 hours (21600 seconds) of padding (CST offset)
17
+ # to force the same time to be displayed in the NS UI
18
+
19
+ is_dst = Time.parse(datetime.to_s).dst?
20
+
21
+ datetime.new_offset(0) + datetime.offset + Rational(is_dst ? 5 : 6, 24)
22
+ end
23
+
24
+ # use when displaying times from a NS record
25
+ def self.normalize_datetime_from_netsuite(datetime)
26
+ # the code below eliminates the TimeZone offset then shifts the date forward 2 hours (7200 seconds)
27
+ # this ensures that ActiveRecord is given a UTC0 DateTime with the exact hour that
28
+ # was displayed in the NS UI (CST time zone), which will result in the correct display on the web side
29
+
30
+ datetime.new_offset(0) + datetime.offset + Rational(2, 24)
31
+ end
32
+
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module Netsuite
2
- VERSION = '0.2.3'
2
+ VERSION = '0.2.4'
3
3
  end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Actions::Upsert do
4
+ before(:all) { savon.mock! }
5
+ after(:all) { savon.unmock! }
6
+
7
+ context 'Customer' do
8
+ let(:customer) do
9
+ NetSuite::Records::Customer.new(:entity_id => 'Shutter Fly', :company_name => 'Shutter Fly, Inc.')
10
+ end
11
+
12
+ before do
13
+ savon.expects(:upsert).with(:message => {
14
+ 'platformMsgs:record' => {
15
+ :content! => {
16
+ 'listRel:entityId' => 'Shutter Fly',
17
+ 'listRel:companyName' => 'Shutter Fly, Inc.'
18
+ },
19
+ '@xsi:type' => 'listRel:Customer'
20
+ },
21
+ }).returns(File.read('spec/support/fixtures/upsert/upsert_customer.xml'))
22
+ end
23
+
24
+ it 'makes a valid request to the NetSuite API' do
25
+ NetSuite::Actions::Upsert.call(customer)
26
+ end
27
+
28
+ it 'returns a valid Response object' do
29
+ response = NetSuite::Actions::Upsert.call(customer)
30
+ response.should be_kind_of(NetSuite::Response)
31
+ response.should be_success
32
+ end
33
+ end
34
+
35
+ context 'Invoice' do
36
+ let(:invoice) do
37
+ NetSuite::Records::Invoice.new(:source => 'Google', :total => 100.0)
38
+ end
39
+
40
+ context 'when successful' do
41
+ before do
42
+ savon.expects(:upsert).with(:message => {
43
+ 'platformMsgs:record' => {
44
+ :content! => {
45
+ 'tranSales:source' => 'Google'
46
+ },
47
+ '@xsi:type' => 'tranSales:Invoice'
48
+ },
49
+ }).returns(File.read('spec/support/fixtures/upsert/upsert_invoice.xml'))
50
+ end
51
+
52
+ it 'makes a valid request to the NetSuite API' do
53
+ NetSuite::Actions::Upsert.call(invoice)
54
+ end
55
+
56
+ it 'returns a valid Response object' do
57
+ response = NetSuite::Actions::Upsert.call(invoice)
58
+ response.should be_kind_of(NetSuite::Response)
59
+ response.should be_success
60
+ end
61
+ end
62
+
63
+ context 'when not successful' do
64
+ before do
65
+ savon.expects(:upsert).with(:message => {
66
+ 'platformMsgs:record' => {
67
+ :content! => {
68
+ 'tranSales:source' => 'Google'
69
+ },
70
+ '@xsi:type' => 'tranSales:Invoice'
71
+ },
72
+ }).returns(File.read('spec/support/fixtures/upsert/upsert_invoice_error.xml'))
73
+ end
74
+
75
+ it 'provides an error method on the object with details about the error' do
76
+ invoice.upsert
77
+ error = invoice.errors.first
78
+
79
+ error.should be_kind_of(NetSuite::Error)
80
+ error.type.should eq('ERROR')
81
+ error.code.should eq('INVALID_KEY_OR_REF')
82
+ error.message.should eq('The specified key is invalid.')
83
+ end
84
+
85
+ it 'provides an error method on the response' do
86
+ response = NetSuite::Actions::Upsert.call(invoice)
87
+ response.errors.first.should be_kind_of(NetSuite::Error)
88
+ end
89
+ end
90
+
91
+ context 'when not successful with multiple errors' do
92
+ before do
93
+ savon.expects(:upsert).with(:message => {
94
+ 'platformMsgs:record' => {
95
+ :content! => {
96
+ 'tranSales:source' => 'Google'
97
+ },
98
+ '@xsi:type' => 'tranSales:Invoice'
99
+ },
100
+ }).returns(File.read('spec/support/fixtures/upsert/upsert_invoice_multiple_errors.xml'))
101
+ end
102
+
103
+ it 'provides an error method on the object with details about the error' do
104
+ invoice.upsert
105
+ invoice.errors.length.should eq(2)
106
+
107
+ error = invoice.errors.first
108
+
109
+ error.should be_kind_of(NetSuite::Error)
110
+ error.type.should eq('ERROR')
111
+ error.code.should eq('ERROR')
112
+ error.message.should eq('Some message')
113
+ end
114
+ end
115
+ end
116
+
117
+ end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::Deposit do
4
+ let(:deposit) { NetSuite::Records::Deposit.new }
5
+ let(:customer) { NetSuite::Records::Customer.new }
6
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
7
+
8
+ it 'has all the right fields' do
9
+ [
10
+ :created_date, :last_modified_date, :currency_name, :tran_id, :total, :tran_date, :memo, :to_be_printed
11
+ ].each do |field|
12
+ deposit.should have_field(field)
13
+ end
14
+ end
15
+
16
+ it 'has all the right record refs' do
17
+ [
18
+ :custom_form, :account, :posting_period, :subsidiary, :department, :klass, :location
19
+ ].each do |record_ref|
20
+ deposit.should have_record_ref(record_ref)
21
+ end
22
+ end
23
+
24
+ describe '#item_list' do
25
+ it 'can be set from attributes' do
26
+ attributes = {
27
+ payment: {
28
+ deposit: true,
29
+ id: '941',
30
+ type: 'CashSale'
31
+ }
32
+ }
33
+ deposit.payment_list.payment = attributes
34
+ deposit.payment_list.should be_kind_of(NetSuite::Records::DepositPaymentList)
35
+ deposit.payment_list.payments.length.should eql(1)
36
+ end
37
+
38
+ it 'can be set from a DepositItemList object' do
39
+ item_list = NetSuite::Records::DepositPaymentList.new
40
+ deposit.payment_list = item_list
41
+ deposit.payment_list.should eql(item_list)
42
+ end
43
+ end
44
+
45
+ describe '.get' do
46
+ context 'when the response is successful' do
47
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :alt_shipping_cost => 100 }) }
48
+
49
+ it 'returns a Deposit instance populated with the data from the response object' do
50
+ NetSuite::Actions::Get.should_receive(:call).with(NetSuite::Records::Deposit, :external_id => 1).and_return(response)
51
+ deposit = NetSuite::Records::Deposit.get(:external_id => 1)
52
+ deposit.should be_kind_of(NetSuite::Records::Deposit)
53
+ deposit.alt_shipping_cost.should eql(100)
54
+ end
55
+ end
56
+
57
+ context 'when the response is unsuccessful' do
58
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
59
+
60
+ it 'raises a RecordNotFound exception' do
61
+ NetSuite::Actions::Get.should_receive(:call).with(NetSuite::Records::Deposit, :external_id => 1).and_return(response)
62
+ lambda {
63
+ NetSuite::Records::Deposit.get(:external_id => 1)
64
+ }.should raise_error(NetSuite::RecordNotFound,
65
+ /NetSuite::Records::Deposit with OPTIONS=(.*) could not be found/)
66
+ end
67
+ end
68
+ end
69
+
70
+ describe '#add' do
71
+ let(:test_data) { { :email => 'test@example.com', :fax => '1234567890' } }
72
+
73
+ context 'when the response is successful' do
74
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
75
+
76
+ it 'returns true' do
77
+ deposit = NetSuite::Records::Deposit.new(test_data)
78
+ NetSuite::Actions::Add.should_receive(:call).
79
+ with(deposit).
80
+ and_return(response)
81
+ deposit.add.should be_true
82
+ end
83
+ end
84
+
85
+ context 'when the response is unsuccessful' do
86
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
87
+
88
+ it 'returns false' do
89
+ deposit = NetSuite::Records::Deposit.new(test_data)
90
+ NetSuite::Actions::Add.should_receive(:call).
91
+ with(deposit).
92
+ and_return(response)
93
+ deposit.add.should be_false
94
+ end
95
+ end
96
+ end
97
+
98
+ describe '#delete' do
99
+ let(:test_data) { { :internal_id => '1' } }
100
+
101
+ context 'when the response is successful' do
102
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
103
+
104
+ it 'returns true' do
105
+ deposit = NetSuite::Records::Deposit.new(test_data)
106
+ NetSuite::Actions::Delete.should_receive(:call).
107
+ with(deposit).
108
+ and_return(response)
109
+ deposit.delete.should be_true
110
+ end
111
+ end
112
+
113
+ context 'when the response is unsuccessful' do
114
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
115
+
116
+ it 'returns false' do
117
+ deposit = NetSuite::Records::Deposit.new(test_data)
118
+ NetSuite::Actions::Delete.should_receive(:call).
119
+ with(deposit).
120
+ and_return(response)
121
+ deposit.delete.should be_false
122
+ end
123
+ end
124
+ end
125
+
126
+ describe '#to_record' do
127
+ before do
128
+ deposit.email = 'something@example.com'
129
+ deposit.tran_id = '4'
130
+ end
131
+ it 'can represent itself as a SOAP record' do
132
+ record = {
133
+ 'tranBank:email' => 'something@example.com',
134
+ 'tranBank:tranId' => '4'
135
+ }
136
+ deposit.to_record.should eql(record)
137
+ end
138
+ end
139
+
140
+ describe '#record_type' do
141
+ it 'returns a string representation of the SOAP type' do
142
+ deposit.record_type.should eql('tranBank:Deposit')
143
+ end
144
+ end
145
+
146
+ end
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3
+ <soapenv:Header>
4
+ <platformMsgs:documentInfo xmlns:platformMsgs="urn:messages_2014_1.platform.webservices.netsuite.com">
5
+ <platformMsgs:nsId>WEBSERVICES_3392464_1220201115821392011296470399_67055c545d0</platformMsgs:nsId>
6
+ </platformMsgs:documentInfo>
7
+ </soapenv:Header>
8
+ <soapenv:Body>
9
+ <upsertResponse xmlns="urn:messages_2014_1.platform.webservices.netsuite.com">
10
+ <writeResponse xmlns="urn:messages_2014_1.platform.webservices.netsuite.com">
11
+ <platformCore:status xmlns:platformCore="urn:core_2014_1.platform.webservices.netsuite.com" isSuccess="true"/>
12
+ <baseRef xmlns:platformCore="urn:core_2014_1.platform.webservices.netsuite.com" internalId="979" externalId="cu241" type="customer" xsi:type="platformCore:RecordRef"/>
13
+ </writeResponse>
14
+ </upsertResponse>
15
+ </soapenv:Body>
16
+ </soapenv:Envelope>
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3
+ <soapenv:Header>
4
+ <platformMsgs:documentInfo xmlns:platformMsgs="urn:messages_2014_1.platform.webservices.netsuite.com">
5
+ <platformMsgs:nsId>WEBSERVICES_3392464_1220201115821392011296470399_67055c545d0</platformMsgs:nsId>
6
+ </platformMsgs:documentInfo>
7
+ </soapenv:Header>
8
+ <soapenv:Body>
9
+ <upsertResponse xmlns="urn:messages_2014_1.platform.webservices.netsuite.com">
10
+ <writeResponse xmlns="urn:messages_2014_1.platform.webservices.netsuite.com">
11
+ <platformCore:status xmlns:platformCore="urn:core_2014_1.platform.webservices.netsuite.com" isSuccess="true"/>
12
+ <baseRef xmlns:platformCore="urn:core_2014_1.platform.webservices.netsuite.com" internalId="979" externalId="in241" type="invoice" xsi:type="platformCore:RecordRef"/>
13
+ </writeResponse>
14
+ </upsertResponse>
15
+ </soapenv:Body>
16
+ </soapenv:Envelope>
@@ -0,0 +1,20 @@
1
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <soapenv:Header>
3
+ <platformMsgs:documentInfo xmlns:platformMsgs="urn:messages_2014_1.platform.webservices.netsuite.com">
4
+ <platformMsgs:nsId>WEBSERVICES_TSTDRV1141558_0120201413459254121612426069_c2488</platformMsgs:nsId>
5
+ </platformMsgs:documentInfo>
6
+ </soapenv:Header>
7
+ <soapenv:Body>
8
+ <upsertResponse xmlns="urn:messages_2014_1.platform.webservices.netsuite.com">
9
+ <writeResponse>
10
+ <platformCore:status xmlns:platformCore="urn:core_2014_1.platform.webservices.netsuite.com" isSuccess="false">
11
+ <platformCore:statusDetail type="ERROR">
12
+ <platformCore:code>INVALID_KEY_OR_REF</platformCore:code>
13
+ <platformCore:message>The specified key is invalid.</platformCore:message>
14
+ </platformCore:statusDetail>
15
+ </platformCore:status>
16
+ <baseRef xmlns:platformCore="urn:core_2014_1.platform.webservices.netsuite.com" externalId="in_334" type="invoice" xsi:type="platformCore:RecordRef"/>
17
+ </writeResponse>
18
+ </upsertResponse>
19
+ </soapenv:Body>
20
+ </soapenv:Envelope>
@@ -0,0 +1,24 @@
1
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <soapenv:Header>
3
+ <platformMsgs:documentInfo xmlns:platformMsgs="urn:messages_2014_1.platform.webservices.netsuite.com">
4
+ <platformMsgs:nsId>WEBSERVICES_TSTDRV1141558_0120201413459254121612426069_c2488</platformMsgs:nsId>
5
+ </platformMsgs:documentInfo>
6
+ </soapenv:Header>
7
+ <soapenv:Body>
8
+ <upsertResponse xmlns="urn:messages_2014_1.platform.webservices.netsuite.com">
9
+ <writeResponse>
10
+ <platformCore:status xmlns:platformCore="urn:core_2014_1.platform.webservices.netsuite.com" isSuccess="false">
11
+ <platformCore:statusDetail type="ERROR">
12
+ <platformCore:code>ERROR</platformCore:code>
13
+ <platformCore:message>Some message</platformCore:message>
14
+ </platformCore:statusDetail>
15
+ <platformCore:statusDetail type="ERROR">
16
+ <platformCore:code>ERROR</platformCore:code>
17
+ <platformCore:message>Some message 2</platformCore:message>
18
+ </platformCore:statusDetail>
19
+ </platformCore:status>
20
+ <baseRef internalId="999" type="invoice" xsi:type="ns2:RecordRef" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="urn:core_2_5.platform.webservices.netsuite.com"/>
21
+ </writeResponse>
22
+ </upsertResponse>
23
+ </soapenv:Body>
24
+ </soapenv:Envelope>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: netsuite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Moran
@@ -9,36 +9,36 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-14 00:00:00.000000000 Z
12
+ date: 2014-04-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: savon
16
15
  requirement: !ruby/object:Gem::Requirement
17
16
  requirements:
18
- - - "~>"
17
+ - - ~>
19
18
  - !ruby/object:Gem::Version
20
19
  version: 2.3.0
21
- type: :runtime
22
20
  prerelease: false
23
21
  version_requirements: !ruby/object:Gem::Requirement
24
22
  requirements:
25
- - - "~>"
23
+ - - ~>
26
24
  - !ruby/object:Gem::Version
27
25
  version: 2.3.0
26
+ name: savon
27
+ type: :runtime
28
28
  - !ruby/object:Gem::Dependency
29
- name: rspec
30
29
  requirement: !ruby/object:Gem::Requirement
31
30
  requirements:
32
- - - "~>"
31
+ - - ~>
33
32
  - !ruby/object:Gem::Version
34
33
  version: '2.10'
35
- type: :development
36
34
  prerelease: false
37
35
  version_requirements: !ruby/object:Gem::Requirement
38
36
  requirements:
39
- - - "~>"
37
+ - - ~>
40
38
  - !ruby/object:Gem::Version
41
39
  version: '2.10'
40
+ name: rspec
41
+ type: :development
42
42
  description: NetSuite SuiteTalk API Wrapper
43
43
  email:
44
44
  - ryan.moran@gmail.com
@@ -47,8 +47,8 @@ executables: []
47
47
  extensions: []
48
48
  extra_rdoc_files: []
49
49
  files:
50
- - ".gitignore"
51
- - ".rspec"
50
+ - .gitignore
51
+ - .rspec
52
52
  - Gemfile
53
53
  - LICENSE
54
54
  - README.md
@@ -63,6 +63,7 @@ files:
63
63
  - lib/netsuite/actions/search.rb
64
64
  - lib/netsuite/actions/search_more_with_id.rb
65
65
  - lib/netsuite/actions/update.rb
66
+ - lib/netsuite/actions/upsert.rb
66
67
  - lib/netsuite/configuration.rb
67
68
  - lib/netsuite/core_ext/string/lower_camelcase.rb
68
69
  - lib/netsuite/errors.rb
@@ -73,6 +74,7 @@ files:
73
74
  - lib/netsuite/namespaces/platform_common.rb
74
75
  - lib/netsuite/namespaces/platform_core.rb
75
76
  - lib/netsuite/namespaces/setup_custom.rb
77
+ - lib/netsuite/namespaces/tran_bank.rb
76
78
  - lib/netsuite/namespaces/tran_cust.rb
77
79
  - lib/netsuite/namespaces/tran_general.rb
78
80
  - lib/netsuite/namespaces/tran_sales.rb
@@ -109,6 +111,9 @@ files:
109
111
  - lib/netsuite/records/customer_refund_deposit.rb
110
112
  - lib/netsuite/records/customer_refund_deposit_list.rb
111
113
  - lib/netsuite/records/department.rb
114
+ - lib/netsuite/records/deposit.rb
115
+ - lib/netsuite/records/deposit_payment.rb
116
+ - lib/netsuite/records/deposit_payment_list.rb
112
117
  - lib/netsuite/records/duration.rb
113
118
  - lib/netsuite/records/inventory_item.rb
114
119
  - lib/netsuite/records/invoice.rb
@@ -150,6 +155,7 @@ files:
150
155
  - lib/netsuite/support/records.rb
151
156
  - lib/netsuite/support/requests.rb
152
157
  - lib/netsuite/support/search_result.rb
158
+ - lib/netsuite/utilities.rb
153
159
  - lib/netsuite/version.rb
154
160
  - netsuite.gemspec
155
161
  - spec/netsuite/actions/add_spec.rb
@@ -158,6 +164,7 @@ files:
158
164
  - spec/netsuite/actions/initialize_spec.rb
159
165
  - spec/netsuite/actions/search_spec.rb
160
166
  - spec/netsuite/actions/update_spec.rb
167
+ - spec/netsuite/actions/upsert_spec.rb
161
168
  - spec/netsuite/configuration_spec.rb
162
169
  - spec/netsuite/records/account_spec.rb
163
170
  - spec/netsuite/records/accounting_period_spec.rb
@@ -183,6 +190,7 @@ files:
183
190
  - spec/netsuite/records/customer_refund_spec.rb
184
191
  - spec/netsuite/records/customer_spec.rb
185
192
  - spec/netsuite/records/department_spec.rb
193
+ - spec/netsuite/records/deposit_spec.rb
186
194
  - spec/netsuite/records/duration_spec.rb
187
195
  - spec/netsuite/records/inventory_item_spec.rb
188
196
  - spec/netsuite/records/invoice_item_list_spec.rb
@@ -229,6 +237,10 @@ files:
229
237
  - spec/support/fixtures/search/saved_search_joined_custom_customer.xml
230
238
  - spec/support/fixtures/update/update_customer.xml
231
239
  - spec/support/fixtures/update/update_invoice.xml
240
+ - spec/support/fixtures/upsert/upsert_customer.xml
241
+ - spec/support/fixtures/upsert/upsert_invoice.xml
242
+ - spec/support/fixtures/upsert/upsert_invoice_error.xml
243
+ - spec/support/fixtures/upsert/upsert_invoice_multiple_errors.xml
232
244
  - spec/support/read_only_field_matcher.rb
233
245
  - spec/support/record_ref_matcher.rb
234
246
  - spec/support/savon.rb
@@ -243,17 +255,17 @@ require_paths:
243
255
  - lib
244
256
  required_ruby_version: !ruby/object:Gem::Requirement
245
257
  requirements:
246
- - - ">="
258
+ - - ! '>='
247
259
  - !ruby/object:Gem::Version
248
260
  version: '0'
249
261
  required_rubygems_version: !ruby/object:Gem::Requirement
250
262
  requirements:
251
- - - ">="
263
+ - - ! '>='
252
264
  - !ruby/object:Gem::Version
253
265
  version: '0'
254
266
  requirements: []
255
267
  rubyforge_project:
256
- rubygems_version: 2.2.0
268
+ rubygems_version: 2.1.11
257
269
  signing_key:
258
270
  specification_version: 4
259
271
  summary: NetSuite SuiteTalk API (SOAP) Wrapper
@@ -264,6 +276,7 @@ test_files:
264
276
  - spec/netsuite/actions/initialize_spec.rb
265
277
  - spec/netsuite/actions/search_spec.rb
266
278
  - spec/netsuite/actions/update_spec.rb
279
+ - spec/netsuite/actions/upsert_spec.rb
267
280
  - spec/netsuite/configuration_spec.rb
268
281
  - spec/netsuite/records/account_spec.rb
269
282
  - spec/netsuite/records/accounting_period_spec.rb
@@ -289,6 +302,7 @@ test_files:
289
302
  - spec/netsuite/records/customer_refund_spec.rb
290
303
  - spec/netsuite/records/customer_spec.rb
291
304
  - spec/netsuite/records/department_spec.rb
305
+ - spec/netsuite/records/deposit_spec.rb
292
306
  - spec/netsuite/records/duration_spec.rb
293
307
  - spec/netsuite/records/inventory_item_spec.rb
294
308
  - spec/netsuite/records/invoice_item_list_spec.rb
@@ -335,6 +349,10 @@ test_files:
335
349
  - spec/support/fixtures/search/saved_search_joined_custom_customer.xml
336
350
  - spec/support/fixtures/update/update_customer.xml
337
351
  - spec/support/fixtures/update/update_invoice.xml
352
+ - spec/support/fixtures/upsert/upsert_customer.xml
353
+ - spec/support/fixtures/upsert/upsert_invoice.xml
354
+ - spec/support/fixtures/upsert/upsert_invoice_error.xml
355
+ - spec/support/fixtures/upsert/upsert_invoice_multiple_errors.xml
338
356
  - spec/support/read_only_field_matcher.rb
339
357
  - spec/support/record_ref_matcher.rb
340
358
  - spec/support/savon.rb