netsuite 0.0.49 → 0.0.50
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.
- data/README.md +47 -103
- data/lib/netsuite.rb +16 -6
- data/lib/netsuite/actions/add.rb +3 -0
- data/lib/netsuite/actions/search.rb +126 -0
- data/lib/netsuite/actions/search_more_with_id.rb +106 -0
- data/lib/netsuite/actions/update.rb +1 -0
- data/lib/netsuite/configuration.rb +52 -3
- data/lib/netsuite/namespaces/act_sched.rb +11 -0
- data/lib/netsuite/records/assembly_item.rb +2 -0
- data/lib/netsuite/records/bin_number_list.rb +48 -0
- data/lib/netsuite/records/contact.rb +44 -0
- data/lib/netsuite/records/contact_list.rb +52 -0
- data/lib/netsuite/records/custom_field.rb +4 -0
- data/lib/netsuite/records/custom_field_list.rb +11 -2
- data/lib/netsuite/records/custom_record_ref.rb +2 -0
- data/lib/netsuite/records/customer.rb +1 -1
- data/lib/netsuite/records/inventory_item.rb +3 -1
- data/lib/netsuite/records/invoice.rb +5 -4
- data/lib/netsuite/records/invoice_item.rb +3 -1
- data/lib/netsuite/records/kit_item.rb +7 -0
- data/lib/netsuite/records/non_inventory_sale_item.rb +1 -0
- data/lib/netsuite/records/sales_order.rb +1 -1
- data/lib/netsuite/records/task.rb +29 -0
- data/lib/netsuite/records/transaction.rb +35 -0
- data/lib/netsuite/response.rb +2 -1
- data/lib/netsuite/support/actions.rb +4 -0
- data/lib/netsuite/support/fields.rb +11 -1
- data/lib/netsuite/support/requests.rb +6 -1
- data/lib/netsuite/support/search_result.rb +67 -0
- data/lib/netsuite/version.rb +1 -1
- data/spec/netsuite/configuration_spec.rb +8 -0
- data/spec/netsuite/records/non_inventory_sale_item_spec.rb +2 -1
- data/spec/netsuite/support/record_refs_spec.rb +10 -1
- metadata +12 -2
    
        data/README.md
    CHANGED
    
    | @@ -2,7 +2,8 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            * This gem will act as a wrapper around the NetSuite SuiteTalk WebServices API. Wow, that is a mouthful.
         | 
| 4 4 | 
             
            * The gem does not cover the entire API, only the subset that we have found useful to cover so far.
         | 
| 5 | 
            -
            * Extending the wrapper is pretty simple.  | 
| 5 | 
            +
            * Extending the wrapper is pretty simple. Check out the [contribution help doc](https://github.com/RevolutionPrep/netsuite/wiki/Contributing-to-the-Supported-NetSuite-API)
         | 
| 6 | 
            +
            * NetSuite development is overall a pretty poor experience. We have a list of [NetSuite Development Resources](https://github.com/RevolutionPrep/netsuite/wiki/NetSuite-Development-Resources) that might make things a bit less painful.
         | 
| 6 7 |  | 
| 7 8 | 
             
            ## Installation
         | 
| 8 9 |  | 
| @@ -24,7 +25,7 @@ This gem is built for ruby 1.9.x, checkout the [1-8-stable](https://github.com/R | |
| 24 25 | 
             
            Before contributing a patch make sure all existing tests pass.
         | 
| 25 26 |  | 
| 26 27 | 
             
            ```
         | 
| 27 | 
            -
            git clone git://github.com/ | 
| 28 | 
            +
            git clone git://github.com/RevolutionPrep/netsuite.git
         | 
| 28 29 | 
             
            cd netsuite
         | 
| 29 30 | 
             
            bundle
         | 
| 30 31 | 
             
            bundle exec rspec
         | 
| @@ -36,114 +37,57 @@ bundle exec rspec | |
| 36 37 | 
             
            NetSuite.configure do
         | 
| 37 38 | 
             
              reset!
         | 
| 38 39 |  | 
| 40 | 
            +
              # optional, defaults to 2011_2
         | 
| 39 41 | 
             
              api_version	'2012_1'
         | 
| 40 42 |  | 
| 41 | 
            -
              # specify full wsdl URL  | 
| 43 | 
            +
              # optionally specify full wsdl URL (to switch to sandbox, for example)
         | 
| 42 44 | 
             
              wsdl          "https://webservices.sandbox.netsuite.com/wsdl/v#{api_version}_0/netsuite.wsdl"
         | 
| 43 45 |  | 
| 46 | 
            +
              # or specify the sandbox flag if you don't want to deal with specifying a full URL
         | 
| 47 | 
            +
              sandbox	true
         | 
| 48 | 
            +
              
         | 
| 49 | 
            +
              # often the netsuite servers will hang which would cause a timeout exception to be raised
         | 
| 50 | 
            +
              # if you don't mind waiting (e.g. processing NS via DJ), increasing the timeout should fix the issue
         | 
| 51 | 
            +
              read_timeout  100000
         | 
| 52 | 
            +
              
         | 
| 53 | 
            +
              # you can specify a file or file descriptor to send the log output to (defaults to STDOUT)
         | 
| 54 | 
            +
              log           File.join(Rails.root, 'log/netsuite.log')
         | 
| 55 | 
            +
              
         | 
| 44 56 | 
             
              # login information
         | 
| 45 | 
            -
              email | 
| 46 | 
            -
              password | 
| 57 | 
            +
              email    	'email@domain.com'
         | 
| 58 | 
            +
              password 	'password'
         | 
| 47 59 | 
             
              account   	'12345'
         | 
| 48 60 | 
             
              role      	1111
         | 
| 49 61 | 
             
            end
         | 
| 50 62 | 
             
            ```
         | 
| 51 63 |  | 
| 52 | 
            -
            ###  | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
                    module Customer
         | 
| 83 | 
            -
                      class Add
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                        def initialize(attributes = {})
         | 
| 86 | 
            -
                          @attributes = attributes
         | 
| 87 | 
            -
                        end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                        def self.call(attributes)
         | 
| 90 | 
            -
                          new(attributes).call
         | 
| 91 | 
            -
                        end
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                        def call
         | 
| 94 | 
            -
                          response = NetSuite::Configuration.connection.request :add do
         | 
| 95 | 
            -
                            soap.header =  NetSuite::Configuration.auth_header
         | 
| 96 | 
            -
                            soap.body = {
         | 
| 97 | 
            -
                              :entityId    => @attributes[:entity_id],
         | 
| 98 | 
            -
                              :companyName => @attributes[:company_name],
         | 
| 99 | 
            -
                              :unsubscribe => @attributes[:unsubscribe]
         | 
| 100 | 
            -
                            }
         | 
| 101 | 
            -
                          end
         | 
| 102 | 
            -
                          success = response.to_hash[:add_response][:write_response][:status][:@is_success] == 'true'
         | 
| 103 | 
            -
                          body    = response.to_hash[:add_response][:write_response][:base_ref]
         | 
| 104 | 
            -
                          NetSuite::Response.new(:success => success, :body => body)
         | 
| 105 | 
            -
                        end
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                      end
         | 
| 108 | 
            -
                    end
         | 
| 109 | 
            -
                  end
         | 
| 110 | 
            -
                end
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                response = NetSuite::Actions::Customer::Add.call(
         | 
| 113 | 
            -
                  :entity_id    => 'Shutter Fly',
         | 
| 114 | 
            -
                  :company_name => 'Shutter Fly, Inc.',
         | 
| 115 | 
            -
                  :unsubscribe  => false
         | 
| 116 | 
            -
                )                 # => #<NetSuite::Response:0x1041f64b5>
         | 
| 117 | 
            -
                response.success? # => true
         | 
| 118 | 
            -
                response.body     # => { :internal_id => '979', :type => 'customer' }
         | 
| 119 | 
            -
                ```
         | 
| 120 | 
            -
             | 
| 121 | 
            -
            ## Gotchas
         | 
| 122 | 
            -
             | 
| 123 | 
            -
              * The Initialize Action duck-punches the .initialize method on any class that includes it.
         | 
| 124 | 
            -
                This has not proven to be a issue yet, but should be taken into account when analyzing any
         | 
| 125 | 
            -
                strange issues with the gem.
         | 
| 126 | 
            -
              * Some records define a 'class' field. Defining a 'class' field on a record overrides the
         | 
| 127 | 
            -
                #class and #class= methods for this class. This is very obviously a problem.  You can,
         | 
| 128 | 
            -
                instead, define a 'klass' field that will be turned into 'class' before being submitted
         | 
| 129 | 
            -
                to the API. The Invoice record has an example of this.
         | 
| 130 | 
            -
             | 
| 131 | 
            -
            ## Contributing
         | 
| 132 | 
            -
             | 
| 133 | 
            -
            1. Fork it
         | 
| 134 | 
            -
            2. Create your feature branch (`git checkout -b my-new-feature`)
         | 
| 135 | 
            -
            3. Write new test and ensure that `bundle exec rspec` doesn't fail
         | 
| 136 | 
            -
            4. Commit your changes (`git commit -am 'Added some feature'`)
         | 
| 137 | 
            -
            5. Push to the branch (`git push origin my-new-feature`)
         | 
| 138 | 
            -
            6. Create new Pull Request
         | 
| 139 | 
            -
             | 
| 140 | 
            -
            ## Fields and RecordRefs
         | 
| 141 | 
            -
             | 
| 142 | 
            -
            Note that some record attributes are specified as Fields while others are specified as RecordRefs. In some cases
         | 
| 143 | 
            -
            attributes are actually RecordRefs in the schema, but we indicate them as Fields. Our experience has shown
         | 
| 144 | 
            -
            this works as long as the attribute is only read from and is not written to. Writing a value for an attribute
         | 
| 145 | 
            -
            that has been wrongly specified will result in an error. Be careful when initializing objects from other objects --
         | 
| 146 | 
            -
            they may carry attributes that write to the new object.
         | 
| 147 | 
            -
             | 
| 148 | 
            -
            As we build up this gem we will replace these inconsistent Fields with RecordRefs. Feel free to contribute new Record 
         | 
| 149 | 
            -
            definitions to help us along.
         | 
| 64 | 
            +
            ### Examples
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            ```ruby
         | 
| 67 | 
            +
            # retrieve a customer
         | 
| 68 | 
            +
            customer = NetSuite::Records::Customer.get(:internal_id => 4)
         | 
| 69 | 
            +
            customer.is_person
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            # or
         | 
| 72 | 
            +
            NetSuite::Records::Customer.get(4).is_person
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            # randomly assign a task
         | 
| 75 | 
            +
            customer_support_reps = [12345, 12346]
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            task = NetSuite::Records::Task.new(
         | 
| 78 | 
            +
            	:title => 'Take Care of a Customer',
         | 
| 79 | 
            +
            	:assigned => NetSuite::Records::RecordRef.new(customer_support_reps.sample),
         | 
| 80 | 
            +
            	:due_date => DateTime.now + 1,
         | 
| 81 | 
            +
            	:message => "Take care of this"
         | 
| 82 | 
            +
            )
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            task.add
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            # this will only work on OS X, open a browser to the record that was just created
         | 
| 87 | 
            +
            `open https://system.sandbox.netsuite.com/app/crm/calendar/task.nl?id=#{invoice.internal_id}`
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            task.update :message => 'New Message'
         | 
| 90 | 
            +
            ```
         | 
| 91 | 
            +
             | 
| 92 | 
            +
             | 
| 93 | 
            +
             | 
    
        data/lib/netsuite.rb
    CHANGED
    
    | @@ -11,6 +11,7 @@ module NetSuite | |
| 11 11 | 
             
              autoload :Response,      'netsuite/response'
         | 
| 12 12 |  | 
| 13 13 | 
             
              module Namespaces
         | 
| 14 | 
            +
                autoload :ActSched,       'netsuite/namespaces/act_sched'
         | 
| 14 15 | 
             
                autoload :ListAcct,       'netsuite/namespaces/list_acct'
         | 
| 15 16 | 
             
                autoload :ListRel,        'netsuite/namespaces/list_rel'
         | 
| 16 17 | 
             
                autoload :PlatformCommon, 'netsuite/namespaces/platform_common'
         | 
| @@ -28,14 +29,17 @@ module NetSuite | |
| 28 29 | 
             
                autoload :RecordRefs, 'netsuite/support/record_refs'
         | 
| 29 30 | 
             
                autoload :Records,    'netsuite/support/records'
         | 
| 30 31 | 
             
                autoload :Requests,   'netsuite/support/requests'
         | 
| 32 | 
            +
                autoload :SearchResult, 'netsuite/support/search_result'
         | 
| 31 33 | 
             
              end
         | 
| 32 34 |  | 
| 33 35 | 
             
              module Actions
         | 
| 34 | 
            -
                autoload :Add, | 
| 35 | 
            -
                autoload :Delete, | 
| 36 | 
            -
                autoload :Get, | 
| 37 | 
            -
                autoload :Initialize, | 
| 38 | 
            -
                autoload :Update, | 
| 36 | 
            +
                autoload :Add,              'netsuite/actions/add'
         | 
| 37 | 
            +
                autoload :Delete,           'netsuite/actions/delete'
         | 
| 38 | 
            +
                autoload :Get,              'netsuite/actions/get'
         | 
| 39 | 
            +
                autoload :Initialize,       'netsuite/actions/initialize'
         | 
| 40 | 
            +
                autoload :Update,           'netsuite/actions/update'
         | 
| 41 | 
            +
                autoload :Search,           'netsuite/actions/search'
         | 
| 42 | 
            +
                autoload :SearchMoreWithId, 'netsuite/actions/search_more_with_id'
         | 
| 39 43 | 
             
              end
         | 
| 40 44 |  | 
| 41 45 | 
             
              module Records
         | 
| @@ -43,6 +47,7 @@ module NetSuite | |
| 43 47 | 
             
                autoload :Account,                    'netsuite/records/account'
         | 
| 44 48 | 
             
                autoload :AccountingPeriod,           'netsuite/records/accounting_period'
         | 
| 45 49 | 
             
                autoload :BillAddress,                'netsuite/records/bill_address'
         | 
| 50 | 
            +
                autoload :BinNumberList,              'netsuite/records/bin_number_list'
         | 
| 46 51 | 
             
                autoload :Classification,             'netsuite/records/classification'
         | 
| 47 52 | 
             
                autoload :CreditMemo,                 'netsuite/records/credit_memo'
         | 
| 48 53 | 
             
                autoload :CreditMemoApply,            'netsuite/records/credit_memo_apply'
         | 
| @@ -63,6 +68,8 @@ module NetSuite | |
| 63 68 | 
             
                autoload :CustomerRefundApplyList,    'netsuite/records/customer_refund_apply_list'
         | 
| 64 69 | 
             
                autoload :CustomerRefundDeposit,      'netsuite/records/customer_refund_deposit'
         | 
| 65 70 | 
             
                autoload :CustomerRefundDepositList,  'netsuite/records/customer_refund_deposit_list'
         | 
| 71 | 
            +
                autoload :ContactList,                'netsuite/records/contact_list'
         | 
| 72 | 
            +
                autoload :Contact,                    'netsuite/records/contact'
         | 
| 66 73 | 
             
                autoload :Department,                 'netsuite/records/department'
         | 
| 67 74 | 
             
                autoload :Duration,                   'netsuite/records/duration'
         | 
| 68 75 | 
             
                autoload :InventoryItem,              'netsuite/records/inventory_item'
         | 
| @@ -73,6 +80,7 @@ module NetSuite | |
| 73 80 | 
             
                autoload :JournalEntry,               'netsuite/records/journal_entry'
         | 
| 74 81 | 
             
                autoload :JournalEntryLine,           'netsuite/records/journal_entry_line'
         | 
| 75 82 | 
             
                autoload :JournalEntryLineList,       'netsuite/records/journal_entry_line_list'
         | 
| 83 | 
            +
                autoload :KitItem,                    'netsuite/records/kit_item'
         | 
| 76 84 | 
             
                autoload :Location,                   'netsuite/records/location'
         | 
| 77 85 | 
             
                autoload :NonInventorySaleItem,       'netsuite/records/non_inventory_sale_item'
         | 
| 78 86 | 
             
                autoload :PaymentMethod,              'netsuite/records/payment_method'
         | 
| @@ -83,13 +91,15 @@ module NetSuite | |
| 83 91 | 
             
                autoload :SalesOrderItem,             'netsuite/records/sales_order_item'
         | 
| 84 92 | 
             
                autoload :SalesOrderItemList,         'netsuite/records/sales_order_item_list'
         | 
| 85 93 | 
             
                autoload :ShipAddress,                'netsuite/records/ship_address'
         | 
| 94 | 
            +
                autoload :Task,                       'netsuite/records/task'
         | 
| 86 95 | 
             
                autoload :Term,                       'netsuite/records/term'
         | 
| 96 | 
            +
                autoload :Transaction,                'netsuite/records/transaction'
         | 
| 87 97 | 
             
              end
         | 
| 88 98 |  | 
| 89 99 | 
             
              def self.configure(&block)
         | 
| 90 100 | 
             
                NetSuite::Configuration.instance_eval(&block)
         | 
| 91 101 | 
             
                Savon.configure do |config|
         | 
| 92 | 
            -
                  config.logger = NetSuite:: | 
| 102 | 
            +
                  config.logger = NetSuite::Configuration.logger
         | 
| 93 103 | 
             
                end
         | 
| 94 104 | 
             
              end
         | 
| 95 105 |  | 
    
        data/lib/netsuite/actions/add.rb
    CHANGED
    
    | @@ -17,6 +17,7 @@ module NetSuite | |
| 17 17 | 
             
                      soap.namespaces['xmlns:tranSales']      = "urn:sales_#{NetSuite::Configuration.api_version}.transactions.webservices.netsuite.com"
         | 
| 18 18 | 
             
                      soap.namespaces['xmlns:platformCommon'] = "urn:common_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
         | 
| 19 19 | 
             
                      soap.namespaces['xmlns:listAcct']       = "urn:accounting_#{NetSuite::Configuration.api_version}.lists.webservices.netsuite.com"
         | 
| 20 | 
            +
                      soap.namespaces['xmlns:actSched']       = "urn:scheduling_#{NetSuite::Configuration.api_version}.activities.webservices.netsuite.com"
         | 
| 20 21 | 
             
                      soap.namespaces['xmlns:tranCust']       = "urn:customers_#{NetSuite::Configuration.api_version}.transactions.webservices.netsuite.com"
         | 
| 21 22 | 
             
                      soap.namespaces['xmlns:setupCustom']    = "urn:customization_#{NetSuite::Configuration.api_version}.setup.webservices.netsuite.com"
         | 
| 22 23 | 
             
                      soap.namespaces['xmlns:tranGeneral']    = "urn:general_#{NetSuite::Configuration.api_version}.transactions.webservices.netsuite.com"
         | 
| @@ -69,6 +70,8 @@ module NetSuite | |
| 69 70 | 
             
                      if response.success?
         | 
| 70 71 | 
             
                        @internal_id = response.body[:@internal_id]
         | 
| 71 72 | 
             
                        true
         | 
| 73 | 
            +
                      else
         | 
| 74 | 
            +
                        false
         | 
| 72 75 | 
             
                      end
         | 
| 73 76 | 
             
                    end
         | 
| 74 77 | 
             
                  end
         | 
| @@ -0,0 +1,126 @@ | |
| 1 | 
            +
            # TODO: Tests
         | 
| 2 | 
            +
            module NetSuite
         | 
| 3 | 
            +
              module Actions
         | 
| 4 | 
            +
                class Search
         | 
| 5 | 
            +
                  include Support::Requests
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize(klass, options = { })
         | 
| 8 | 
            +
                    @klass = klass
         | 
| 9 | 
            +
                    @options = options
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  private
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def request
         | 
| 15 | 
            +
                    # need to do this outside the block below because of variable scoping
         | 
| 16 | 
            +
                    preferences = (@options[:preferences] || {}).inject({}) do |h, (k, v)|
         | 
| 17 | 
            +
                      h[k.to_s.lower_camelcase] = v
         | 
| 18 | 
            +
                      h
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    connection.request(:search) do
         | 
| 22 | 
            +
                      soap.namespaces['xmlns:platformMsgs'] = "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
         | 
| 23 | 
            +
                      soap.namespaces['xmlns:platformCore'] = "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
         | 
| 24 | 
            +
                      soap.namespaces['xmlns:platformCommon'] = "urn:common_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
         | 
| 25 | 
            +
                      soap.namespaces['xmlns:listRel'] = "urn:relationships_#{NetSuite::Configuration.api_version}.lists.webservices.netsuite.com"
         | 
| 26 | 
            +
                      soap.namespaces['xmlns:tranSales'] = "urn:sales_#{NetSuite::Configuration.api_version}.transactions.webservices.netsuite.com"
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                      # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteFlex/WebServices/STP_SettingSearchPreferences.html#N2028598271-3
         | 
| 29 | 
            +
                      soap.header = auth_header.merge(preferences.empty? ? {} : { 'platformMsgs:searchPreferences' => preferences })
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                      soap.body = request_body
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  # basic search XML
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  # <soap:Body>
         | 
| 38 | 
            +
                  # <platformMsgs:search>
         | 
| 39 | 
            +
                  # <searchRecord xsi:type="ContactSearch">
         | 
| 40 | 
            +
                  #   <customerJoin xsi:type="CustomerSearchBasic">
         | 
| 41 | 
            +
                  #     <email operator="contains" xsi:type="platformCore:SearchStringField">
         | 
| 42 | 
            +
                  #     <platformCore:searchValue>shutterfly.com</platformCore:searchValue>
         | 
| 43 | 
            +
                  #     <email>
         | 
| 44 | 
            +
                  #   <customerJoin>
         | 
| 45 | 
            +
                  # </searchRecord>
         | 
| 46 | 
            +
                  # </search>
         | 
| 47 | 
            +
                  # </soap:Body>
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def request_body
         | 
| 50 | 
            +
                    criteria = @options[:criteria] || @options
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    # TODO wish there was a cleaner way to do this: we need the namespace of the record
         | 
| 53 | 
            +
                    example_instance = @klass.new
         | 
| 54 | 
            +
                    namespace = example_instance.record_namespace
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    # extract the class name without the module
         | 
| 57 | 
            +
                    class_name = @klass.to_s.split("::").last
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    search_record = {}
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    criteria.each_pair do |condition_category, conditions|
         | 
| 62 | 
            +
                      search_record["#{namespace}:#{condition_category}"] = conditions.inject({}) do |h, condition|
         | 
| 63 | 
            +
                        h["platformCommon:#{condition[:field]}"] = {
         | 
| 64 | 
            +
                          "platformCore:searchValue" => condition[:value]
         | 
| 65 | 
            +
                        }
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                        (h[:attributes!] ||= {}).merge!({
         | 
| 68 | 
            +
                          "platformCommon:#{condition[:field]}" => {
         | 
| 69 | 
            +
                            'operator' => condition[:operator]
         | 
| 70 | 
            +
                          }
         | 
| 71 | 
            +
                        })
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                        h
         | 
| 74 | 
            +
                      end
         | 
| 75 | 
            +
                    end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    {
         | 
| 78 | 
            +
                      'searchRecord' => search_record,
         | 
| 79 | 
            +
                      :attributes! => {
         | 
| 80 | 
            +
                        'searchRecord' => {
         | 
| 81 | 
            +
                          'xsi:type' => "#{namespace}:#{class_name}Search"
         | 
| 82 | 
            +
                        },
         | 
| 83 | 
            +
                      }
         | 
| 84 | 
            +
                    }
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  def response_header
         | 
| 88 | 
            +
                    @response_header ||= response_header_hash
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  def response_header_hash
         | 
| 92 | 
            +
                    @response_header_hash = @response.header[:document_info]
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  def response_body
         | 
| 96 | 
            +
                    @response_body ||= search_result
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  def search_result
         | 
| 100 | 
            +
                    @search_result = @response[:search_response][:search_result]
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  def success?
         | 
| 104 | 
            +
                    @success ||= search_result[:status][:@is_success] == 'true'
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  module Support
         | 
| 108 | 
            +
                    def self.included(base)
         | 
| 109 | 
            +
                      base.extend(ClassMethods)
         | 
| 110 | 
            +
                    end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                    module ClassMethods
         | 
| 113 | 
            +
                      def search(options = { })
         | 
| 114 | 
            +
                        response = NetSuite::Actions::Search.call(self, options)
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                        if response.success?
         | 
| 117 | 
            +
                          NetSuite::Support::SearchResult.new(response, self)
         | 
| 118 | 
            +
                        else
         | 
| 119 | 
            +
                          false
         | 
| 120 | 
            +
                        end
         | 
| 121 | 
            +
                      end
         | 
| 122 | 
            +
                    end
         | 
| 123 | 
            +
                  end
         | 
| 124 | 
            +
                end
         | 
| 125 | 
            +
              end
         | 
| 126 | 
            +
            end
         | 
| @@ -0,0 +1,106 @@ | |
| 1 | 
            +
            # TODO: Tests
         | 
| 2 | 
            +
            # TODO: DBC
         | 
| 3 | 
            +
            module NetSuite
         | 
| 4 | 
            +
              module Actions
         | 
| 5 | 
            +
                class SearchMoreWithId
         | 
| 6 | 
            +
                  include Support::Requests
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def initialize(klass, options = { })
         | 
| 9 | 
            +
                    @klass = klass
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    @options = options
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  private
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def request
         | 
| 17 | 
            +
                    connection.request(:search_more_with_id) do
         | 
| 18 | 
            +
                      soap.namespaces['xmlns:platformMsgs'] = "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
         | 
| 19 | 
            +
                      soap.namespaces['xmlns:platformCore'] = "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
         | 
| 20 | 
            +
                      soap.namespaces['xmlns:platformCommon'] = "urn:common_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
         | 
| 21 | 
            +
                      soap.namespaces['xmlns:listRel'] = "urn:relationships_#{NetSuite::Configuration.api_version}.lists.webservices.netsuite.com"
         | 
| 22 | 
            +
                      soap.namespaces['xmlns:tranSales'] = "urn:sales_#{NetSuite::Configuration.api_version}.transactions.webservices.netsuite.com"
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      soap.header = auth_header
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      soap.body = request_body
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  # TODO: Consistent use of namespace qualifying
         | 
| 31 | 
            +
                  def request_body
         | 
| 32 | 
            +
                    buffer = ''
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    xml = Builder::XmlMarkup.new(target: buffer)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    xml.platformMsgs(:searchId, @options[:search_id])
         | 
| 37 | 
            +
                    xml.platformMsgs(:pageIndex, @options[:page].present? ? @options[:page] : 2)
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    buffer
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def response_body
         | 
| 43 | 
            +
                    @response_body ||= response_body_hash
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  def response_body_hash
         | 
| 47 | 
            +
                    @response_body_hash = @response[:search_more_with_id_response][:search_result]
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  def success?
         | 
| 51 | 
            +
                    @success ||= response_body_hash[:status][:@is_success] == 'true'
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  # TODO: Refactor
         | 
| 55 | 
            +
                  def more?
         | 
| 56 | 
            +
                    @more ||= response_body_hash[:page_index] < response_body_hash[:total_pages]
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  module Support
         | 
| 60 | 
            +
                    def self.included(base)
         | 
| 61 | 
            +
                      base.extend(ClassMethods)
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    # TODO: Rename page_index to page
         | 
| 65 | 
            +
                    module ClassMethods
         | 
| 66 | 
            +
                      # Preconditions
         | 
| 67 | 
            +
                      # => options[:search_id] is a string
         | 
| 68 | 
            +
                      # => options[:page], optional, is an integer
         | 
| 69 | 
            +
                      # Postconditions
         | 
| 70 | 
            +
                      # => Hash with the following keys:
         | 
| 71 | 
            +
                      #      * page_index which is an integer
         | 
| 72 | 
            +
                      #      * total_pages which is an integer
         | 
| 73 | 
            +
                      #      * search_results containing array of SearchResult's
         | 
| 74 | 
            +
                      def search_more_with_id(options = { })
         | 
| 75 | 
            +
                        response = NetSuite::Actions::SearchMoreWithId.call(self, options)
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                        response_hash = { }
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                        if response.success?
         | 
| 80 | 
            +
                          search_results = []
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                          if response.body[:search_row_list].present?
         | 
| 83 | 
            +
                            response.body[:search_row_list][:search_row].each do |record|
         | 
| 84 | 
            +
                              search_result = NetSuite::Support::SearchResult.new(record)
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                              search_results << search_result
         | 
| 87 | 
            +
                            end
         | 
| 88 | 
            +
                          end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                          page_index = response.body[:page_index]
         | 
| 91 | 
            +
                          total_pages = response.body[:total_pages]
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                          response_hash[:page_index] = page_index
         | 
| 94 | 
            +
                          response_hash[:total_pages] = total_pages
         | 
| 95 | 
            +
                          response_hash[:search_results] = search_results
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                          response_hash
         | 
| 98 | 
            +
                        else
         | 
| 99 | 
            +
                          raise ArgumentError
         | 
| 100 | 
            +
                        end
         | 
| 101 | 
            +
                      end
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
            end
         | 
| @@ -16,6 +16,7 @@ module NetSuite | |
| 16 16 | 
             
                      soap.namespaces['xmlns:tranSales']      = "urn:sales_#{NetSuite::Configuration.api_version}.transactions.webservices.netsuite.com"
         | 
| 17 17 | 
             
                      soap.namespaces['xmlns:platformCommon'] = "urn:common_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
         | 
| 18 18 | 
             
                      soap.namespaces['xmlns:listAcct']       = "urn:accounting_#{NetSuite::Configuration.api_version}.lists.webservices.netsuite.com"
         | 
| 19 | 
            +
                      soap.namespaces['xmlns:actSched']       = "urn:scheduling_#{NetSuite::Configuration.api_version}.activities.webservices.netsuite.com"
         | 
| 19 20 | 
             
                      soap.namespaces['xmlns:tranCust']       = "urn:customers_#{NetSuite::Configuration.api_version}.transactions.webservices.netsuite.com"
         | 
| 20 21 | 
             
                      soap.namespaces['xmlns:setupCustom']    = "urn:customization_#{NetSuite::Configuration.api_version}.setup.webservices.netsuite.com"
         | 
| 21 22 | 
             
                      soap.header = auth_header
         | 
| @@ -11,9 +11,14 @@ module NetSuite | |
| 11 11 | 
             
                end
         | 
| 12 12 |  | 
| 13 13 | 
             
                def connection
         | 
| 14 | 
            -
                  attributes[:connection] | 
| 14 | 
            +
                  unless attributes[:connection]
         | 
| 15 | 
            +
                    attributes[:connection] = Savon::Client.new(self.wsdl)
         | 
| 16 | 
            +
                    attributes[:connection].http.read_timeout = read_timeout
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  attributes[:connection]
         | 
| 15 20 | 
             
                end
         | 
| 16 | 
            -
             | 
| 21 | 
            +
             | 
| 17 22 | 
             
                def api_version(version = nil)
         | 
| 18 23 | 
             
                  if version
         | 
| 19 24 | 
             
                    self.api_version = version
         | 
| @@ -26,6 +31,18 @@ module NetSuite | |
| 26 31 | 
             
                  attributes[:api_version] = version
         | 
| 27 32 | 
             
                end
         | 
| 28 33 |  | 
| 34 | 
            +
                def sandbox=(flag)
         | 
| 35 | 
            +
                  attributes[:flag] = flag
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def sandbox(flag = nil)
         | 
| 39 | 
            +
                  if flag.nil?
         | 
| 40 | 
            +
                    attributes[:flag] ||= false
         | 
| 41 | 
            +
                  else
         | 
| 42 | 
            +
                    self.sandbox = flag
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 29 46 | 
             
                def wsdl=(wsdl)
         | 
| 30 47 | 
             
                  attributes[:wsdl] = wsdl
         | 
| 31 48 | 
             
                end
         | 
| @@ -34,7 +51,14 @@ module NetSuite | |
| 34 51 | 
             
                  if wsdl
         | 
| 35 52 | 
             
                    self.wsdl = wsdl
         | 
| 36 53 | 
             
                  else
         | 
| 37 | 
            -
                     | 
| 54 | 
            +
                    if sandbox
         | 
| 55 | 
            +
                      wsdl_path = "https://webservices.sandbox.netsuite.com/wsdl/v#{api_version}_0/netsuite.wsdl"
         | 
| 56 | 
            +
                    else
         | 
| 57 | 
            +
                      wsdl_path = File.expand_path("../../../wsdl/#{api_version}.wsdl", __FILE__)
         | 
| 58 | 
            +
                      wsdl_path = "https://webservices.netsuite.com/wsdl/v#{api_version}_0/netsuite.wsdl" unless File.exists? wsdl_path
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    attributes[:wsdl] ||= wsdl_path
         | 
| 38 62 | 
             
                  end
         | 
| 39 63 | 
             
                end
         | 
| 40 64 |  | 
| @@ -106,5 +130,30 @@ module NetSuite | |
| 106 130 | 
             
                  end
         | 
| 107 131 | 
             
                end
         | 
| 108 132 |  | 
| 133 | 
            +
                def read_timeout=(timeout)
         | 
| 134 | 
            +
                  attributes[:read_timeout] = timeout
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                def read_timeout(timeout = nil)
         | 
| 138 | 
            +
                  if timeout
         | 
| 139 | 
            +
                    self.read_timeout = timeout
         | 
| 140 | 
            +
                  else
         | 
| 141 | 
            +
                    attributes[:read_timeout] ||= 60
         | 
| 142 | 
            +
                  end
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                def log=(path)
         | 
| 146 | 
            +
                  attributes[:log] = path
         | 
| 147 | 
            +
                end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                def log(path = nil)
         | 
| 150 | 
            +
                  self.log = path if path
         | 
| 151 | 
            +
                  attributes[:log]
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                def logger
         | 
| 155 | 
            +
                  attributes[:logger] ||= NetSuite::XmlLogger.new (log && !log.empty?) ? log : STDOUT
         | 
| 156 | 
            +
                end
         | 
| 157 | 
            +
             | 
| 109 158 | 
             
              end
         | 
| 110 159 | 
             
            end
         | 
| @@ -41,6 +41,8 @@ module NetSuite | |
| 41 41 | 
             
                    :supply_replenishment_method, :supply_type, :tax_schedule, :units_type, :vendor
         | 
| 42 42 |  | 
| 43 43 | 
             
                  field :custom_field_list, CustomFieldList
         | 
| 44 | 
            +
                  field :bin_number_list, BinNumberList
         | 
| 45 | 
            +
                  field :pricing_matrix, PricingMatrix
         | 
| 44 46 |  | 
| 45 47 | 
             
                  attr_reader :internal_id
         | 
| 46 48 | 
             
                  attr_accessor :external_id
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            module NetSuite
         | 
| 2 | 
            +
              module Records
         | 
| 3 | 
            +
                # TODO this is fairly messy: shouldn't mix multiple classes in one file
         | 
| 4 | 
            +
                # might be possible to trash the GenericField as well
         | 
| 5 | 
            +
                
         | 
| 6 | 
            +
                class GenericField
         | 
| 7 | 
            +
                  include Support::Attributes
         | 
| 8 | 
            +
                  include Support::Fields
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def initialize(attributes = {})
         | 
| 11 | 
            +
                    self.attributes = attributes
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                class BinNumber < GenericField
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                class BinNumberList
         | 
| 20 | 
            +
                  include Support::Fields
         | 
| 21 | 
            +
                  include Namespaces::PlatformCore
         | 
| 22 | 
            +
                  # include Namespaces::ListAcct
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  fields :bin_number
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def initialize(attributes = {})
         | 
| 27 | 
            +
                    initialize_from_attributes_hash(attributes)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def bin_number=(items)
         | 
| 31 | 
            +
                    case items
         | 
| 32 | 
            +
                    when Hash
         | 
| 33 | 
            +
                      self.bin_numbers << BinNumber.new(items)
         | 
| 34 | 
            +
                    when Array
         | 
| 35 | 
            +
                      items.each { |item| self.bin_numbers << BinNumber.new(item) }
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def bin_numbers
         | 
| 40 | 
            +
                    @bin_numbers ||= []
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def to_record
         | 
| 44 | 
            +
                    { "#{record_namespace}:item" => bin_numbers.map(&:to_record) }
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            module NetSuite
         | 
| 2 | 
            +
              module Records
         | 
| 3 | 
            +
                class Contact
         | 
| 4 | 
            +
                  include Support::Fields
         | 
| 5 | 
            +
                  include Support::RecordRefs
         | 
| 6 | 
            +
                  include Support::Records
         | 
| 7 | 
            +
                  include Support::Actions
         | 
| 8 | 
            +
                  include Namespaces::ListRel
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  actions :get, :add, :delete, :search
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  fields :salutation, :first_name, :middle_name, :last_name, :title, :phone, :fax, :email, :default_address,
         | 
| 13 | 
            +
                         :entity_id, :phonetic_name, :alt_email, :office_phone, :home_phone, :mobile_phone, :supervisor_phone,
         | 
| 14 | 
            +
                         :assistant_phone, :comments, :bill_pay, :is_private, :is_inactive
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  field :addressbook_list,  CustomerAddressbookList
         | 
| 17 | 
            +
                  field :custom_field_list, CustomFieldList
         | 
| 18 | 
            +
                  # field :subscriptions_list, SubscriptionsList
         | 
| 19 | 
            +
                  # field :category_list, CategoryList
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  read_only_fields :last_modified_date, :date_created
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  record_refs :custom_form, :company, :subsidiary, :supervisor, :assistant, :image, :global_subscription_status
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  attr_reader   :internal_id
         | 
| 26 | 
            +
                  attr_accessor :external_id
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def initialize(attributes = {})
         | 
| 29 | 
            +
                    @internal_id = attributes.delete(:internal_id) || attributes.delete(:@internal_id)
         | 
| 30 | 
            +
                    @external_id = attributes.delete(:external_id) || attributes.delete(:@external_id)
         | 
| 31 | 
            +
                    initialize_from_attributes_hash(attributes)
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def to_record
         | 
| 35 | 
            +
                    rec = super
         | 
| 36 | 
            +
                    if rec["#{record_namespace}:customFieldList"]
         | 
| 37 | 
            +
                      rec["#{record_namespace}:customFieldList!"] = rec.delete("#{record_namespace}:customFieldList")
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                    rec
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
            end
         | 
| @@ -0,0 +1,52 @@ | |
| 1 | 
            +
            module NetSuite
         | 
| 2 | 
            +
              module Records
         | 
| 3 | 
            +
                class ContactList
         | 
| 4 | 
            +
                  include Namespaces::ActSched
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  def initialize(attributes = {})
         | 
| 7 | 
            +
                    # - the contact list on the NS GUI doesn't show the assigned contact which shows up in the XML
         | 
| 8 | 
            +
                    # - you can't add an arbitary number of contacts through the NS GUI
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    # TODO the contact list doesn't really work because of the strange XML below (2 assigned companies, one contact)
         | 
| 11 | 
            +
                    
         | 
| 12 | 
            +
                    # <actSched:contactList>
         | 
| 13 | 
            +
                    #   <actSched:contact>
         | 
| 14 | 
            +
                    #     <actSched:company xmlns:platformCore="urn:core_2012_1.platform.webservices.netsuite.com" internalId="12345">
         | 
| 15 | 
            +
                    #       <platformCore:name>10001 Another Customer</platformCore:name>
         | 
| 16 | 
            +
                    #     </actSched:company>
         | 
| 17 | 
            +
                    #   </actSched:contact>
         | 
| 18 | 
            +
                    #   <actSched:contact>
         | 
| 19 | 
            +
                    #     <actSched:company xmlns:platformCore="urn:core_2012_1.platform.webservices.netsuite.com" internalId="12346">
         | 
| 20 | 
            +
                    #       <platformCore:name>31500 A Customer</platformCore:name>
         | 
| 21 | 
            +
                    #     </actSched:company>
         | 
| 22 | 
            +
                    #     <actSched:contact xmlns:platformCore="urn:core_2012_1.platform.webservices.netsuite.com" internalId="12347">
         | 
| 23 | 
            +
                    #       <platformCore:name>A Person</platformCore:name>
         | 
| 24 | 
            +
                    #     </actSched:contact>
         | 
| 25 | 
            +
                    #   </actSched:contact>
         | 
| 26 | 
            +
                    # </actSched:contactList>
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    case attributes[:contact]
         | 
| 29 | 
            +
                    when Hash
         | 
| 30 | 
            +
                      contacts << Contact.new(attributes[:contact])
         | 
| 31 | 
            +
                    when Array
         | 
| 32 | 
            +
                      attributes[:contact].each { |contact| contacts << Contact.new(contact) }
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def <<(contact)
         | 
| 37 | 
            +
                    @contacts << contact
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def contacts
         | 
| 41 | 
            +
                    @contacts ||= []
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def to_record
         | 
| 45 | 
            +
                    contacts.map do |contact|
         | 
| 46 | 
            +
                      { "#{record_namespace}:contact" => contact.to_record }
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
            end
         | 
| @@ -6,9 +6,9 @@ module NetSuite | |
| 6 6 | 
             
                  def initialize(attributes = {})
         | 
| 7 7 | 
             
                    case attributes[:custom_field]
         | 
| 8 8 | 
             
                    when Hash
         | 
| 9 | 
            -
                       | 
| 9 | 
            +
                      extract_custom_field(attributes[:custom_field])
         | 
| 10 10 | 
             
                    when Array
         | 
| 11 | 
            -
                      attributes[:custom_field].each { |custom_field|  | 
| 11 | 
            +
                      attributes[:custom_field].each { |custom_field| extract_custom_field(custom_field) }
         | 
| 12 12 | 
             
                    end
         | 
| 13 13 |  | 
| 14 14 | 
             
                    @custom_fields_assoc = Hash.new
         | 
| @@ -40,6 +40,15 @@ module NetSuite | |
| 40 40 | 
             
                    }.join
         | 
| 41 41 | 
             
                  end
         | 
| 42 42 |  | 
| 43 | 
            +
                  private
         | 
| 44 | 
            +
                    def extract_custom_field(custom_field_data)
         | 
| 45 | 
            +
                      # TODO this needs to be cleaned up & tested; very messy
         | 
| 46 | 
            +
                      if custom_field_data[:"@xsi:type"] == "platformCore:SelectCustomFieldRef"
         | 
| 47 | 
            +
                        custom_field_data[:value] = CustomRecordRef.new(custom_field_data.delete(:value))
         | 
| 48 | 
            +
                      end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                      custom_fields << CustomField.new(custom_field_data)
         | 
| 51 | 
            +
                    end
         | 
| 43 52 | 
             
                end
         | 
| 44 53 | 
             
              end
         | 
| 45 54 | 
             
            end
         | 
| @@ -7,7 +7,7 @@ module NetSuite | |
| 7 7 | 
             
                  include Support::Actions
         | 
| 8 8 | 
             
                  include Namespaces::ListRel
         | 
| 9 9 |  | 
| 10 | 
            -
                  actions :get, :add, :delete
         | 
| 10 | 
            +
                  actions :get, :add, :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,
         | 
| @@ -9,13 +9,13 @@ module NetSuite | |
| 9 9 |  | 
| 10 10 | 
             
                  actions :get, :initialize, :add, :delete
         | 
| 11 11 |  | 
| 12 | 
            -
                  fields :alt_handling_cost, : | 
| 12 | 
            +
                  fields :alt_handling_cost, :balance, :bill_address,
         | 
| 13 13 | 
             
                    :billing_schedule, :contrib_pct, :created_date, :currency_name, :custom_field_list,
         | 
| 14 14 | 
             
                    :deferred_revenue, :discount_amount, :discount_date, :discount_item, :discount_rate,
         | 
| 15 15 | 
             
                    :due_date, :email, :end_date, :est_gross_profit, :est_gross_profit_percent, :exchange_rate,
         | 
| 16 16 | 
             
                    :exclude_commission, :exp_cost_disc_amount, :exp_cost_disc_print, :exp_cost_disc_rate, :exp_cost_disc_tax_1_amt,
         | 
| 17 17 | 
             
                    :exp_cost_disc_taxable, :exp_cost_discount, :exp_cost_list, :exp_cost_tax_code, :exp_cost_tax_rate_1,
         | 
| 18 | 
            -
                    :exp_cost_tax_rate_2, :fax, :fob, : | 
| 18 | 
            +
                    :exp_cost_tax_rate_2, :fax, :fob, :gift_cert_redemption_list, :handling_tax_1_rate,
         | 
| 19 19 | 
             
                    :handling_tax_2_rate, :handling_tax_code, :is_taxable, :item_cost_disc_amount, :item_cost_disc_print,
         | 
| 20 20 | 
             
                    :item_cost_disc_rate, :item_cost_disc_tax_1_amt, :item_cost_disc_taxable, :item_cost_discount, :item_cost_list,
         | 
| 21 21 | 
             
                    :item_cost_tax_code, :item_cost_tax_rate_1, :item_cost_tax_rate_2, :item_list, :job, :last_modified_date,
         | 
| @@ -24,7 +24,7 @@ module NetSuite | |
| 24 24 | 
             
                    :rev_rec_on_rev_commitment, :rev_rec_schedule, :rev_rec_start_date, :revenue_status, :sales_effective_date,
         | 
| 25 25 | 
             
                    :sales_group, :sales_team_list, :ship_address, :ship_date, :ship_group_list,
         | 
| 26 26 | 
             
                    :shipping_cost, :shipping_tax_1_rate, :shipping_tax_2_rate, :shipping_tax_code, :source, :start_date,
         | 
| 27 | 
            -
                    :status, :subsidiary, :sync_partner_teams, :sync_sales_teams, :tax_2_total, | 
| 27 | 
            +
                    :status, :subsidiary, :sync_partner_teams, :sync_sales_teams, :tax_2_total,
         | 
| 28 28 | 
             
                    :tax_total, :time_disc_amount, :time_disc_print, :time_disc_rate, :time_disc_tax_1_amt, :time_disc_taxable,
         | 
| 29 29 | 
             
                    :time_discount, :time_list, :time_tax_code, :time_tax_rate_1, :time_tax_rate_2, :to_be_emailed, :to_be_faxed,
         | 
| 30 30 | 
             
                    :to_be_printed, :total_cost_estimate, :tracking_numbers, :tran_date, :tran_id, :tran_is_vsoe_bundle,
         | 
| @@ -35,7 +35,8 @@ module NetSuite | |
| 35 35 | 
             
                  field :item_list,                InvoiceItemList
         | 
| 36 36 | 
             
                  field :custom_field_list,        CustomFieldList
         | 
| 37 37 |  | 
| 38 | 
            -
                  read_only_fields :sub_total, :discount_total, :total, :recognized_revenue, :amount_remaining, :amount_paid
         | 
| 38 | 
            +
                  read_only_fields :sub_total, :discount_total, :total, :recognized_revenue, :amount_remaining, :amount_paid,
         | 
| 39 | 
            +
                                   :alt_shipping_cost, :gift_cert_applied, :tax_rate, :handling_cost
         | 
| 39 40 |  | 
| 40 41 | 
             
                  record_refs :account, :bill_address_list, :custom_form, :department, :entity, :klass,
         | 
| 41 42 | 
             
                              :posting_period, :ship_address_list, :terms, :location, :sales_rep, :tax_item, :created_from,
         | 
| @@ -10,12 +10,14 @@ module NetSuite | |
| 10 10 | 
             
                    :defer_rev_rec, :description, :gift_cert_from, :gift_cert_message, :gift_cert_number, :gift_cert_recipient_email,
         | 
| 11 11 | 
             
                    :gift_cert_recipient_name, :gross_amt, :inventory_detail, :is_taxable, :item_is_fulfilled, :license_code, :line,
         | 
| 12 12 | 
             
                    :klass, :options, :order_line, :percent_complete, :quantity, :quantity_available, :quantity_fulfilled,
         | 
| 13 | 
            -
                    :quantity_on_hand, :quantity_ordered, : | 
| 13 | 
            +
                    :quantity_on_hand, :quantity_ordered, :rate, :rev_rec_end_date, :rev_rec_start_date,
         | 
| 14 14 | 
             
                    :serial_numbers, :ship_group, :tax1_amt, :tax_rate1, :tax_rate2, :vsoe_allocation, :vsoe_amount, :vsoe_deferral,
         | 
| 15 15 | 
             
                    :vsoe_delivered, :vsoe_permit_discount, :vsoe_price
         | 
| 16 16 |  | 
| 17 17 | 
             
                  field :custom_field_list, CustomFieldList
         | 
| 18 18 |  | 
| 19 | 
            +
                  read_only_fields :quantity_remaining
         | 
| 20 | 
            +
             | 
| 19 21 | 
             
                  record_refs :department, :item, :job, :location, :price, :rev_rec_schedule, :ship_address, :ship_method, :tax_code, :units, :klass
         | 
| 20 22 |  | 
| 21 23 | 
             
                  def initialize(attributes_or_record = {})
         | 
| @@ -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
         | 
| 10 | 
            +
                  actions :get, :add, :initialize, :delete, :update, :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,
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            module NetSuite
         | 
| 2 | 
            +
              module Records
         | 
| 3 | 
            +
                class Task
         | 
| 4 | 
            +
                  include Support::Fields
         | 
| 5 | 
            +
                  include Support::RecordRefs
         | 
| 6 | 
            +
                  include Support::Records
         | 
| 7 | 
            +
                  include Support::Actions
         | 
| 8 | 
            +
                  include Namespaces::ActSched
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  actions :get, :add, :delete, :update
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  fields :title, :send_email, :message, :status, :access_level, :reminder_type,
         | 
| 13 | 
            +
                         :reminder_minutes, :start_date, :end_date, :due_date, :timed_event
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  field :contact_list, ContactList
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  record_refs :assigned, :owner, :company, :contact
         | 
| 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 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            module NetSuite
         | 
| 2 | 
            +
              module Records
         | 
| 3 | 
            +
                class Transaction
         | 
| 4 | 
            +
                  include Support::Fields
         | 
| 5 | 
            +
                  include Support::RecordRefs
         | 
| 6 | 
            +
                  include Support::Records
         | 
| 7 | 
            +
                  include Support::Actions
         | 
| 8 | 
            +
                  include Namespaces::TranSales
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  actions :get, :search, :search_more_with_id, :initialize, :add, :delete
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  attr_reader   :internal_id
         | 
| 13 | 
            +
                  attr_accessor :external_id
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def initialize(attributes = {})
         | 
| 16 | 
            +
                    @internal_id = attributes.delete(:internal_id) || attributes.delete(:@internal_id)
         | 
| 17 | 
            +
                    @external_id = attributes.delete(:external_id) || attributes.delete(:@external_id)
         | 
| 18 | 
            +
                    initialize_from_attributes_hash(attributes)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def self.custom_soap_advanced_search_record_type
         | 
| 22 | 
            +
                    'tranSales:TransactionSearchAdvanced'
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def to_record
         | 
| 26 | 
            +
                    rec = super
         | 
| 27 | 
            +
                    if rec["#{record_namespace}:customFieldList"]
         | 
| 28 | 
            +
                      rec["#{record_namespace}:customFieldList!"] = rec.delete("#{record_namespace}:customFieldList")
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                    rec
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
    
        data/lib/netsuite/response.rb
    CHANGED
    
    
| @@ -18,6 +18,10 @@ module NetSuite | |
| 18 18 | 
             
                      case name
         | 
| 19 19 | 
             
                      when :get
         | 
| 20 20 | 
             
                        self.send(:include, NetSuite::Actions::Get::Support)
         | 
| 21 | 
            +
                      when :search
         | 
| 22 | 
            +
                        self.send(:include, NetSuite::Actions::Search::Support)
         | 
| 23 | 
            +
                      when :search_more_with_id
         | 
| 24 | 
            +
                        self.send(:include, NetSuite::Actions::SearchMoreWithId::Support)
         | 
| 21 25 | 
             
                      when :add
         | 
| 22 26 | 
             
                        self.send(:include, NetSuite::Actions::Add::Support)
         | 
| 23 27 | 
             
                      when :delete
         | 
| @@ -28,7 +28,11 @@ module NetSuite | |
| 28 28 | 
             
                        end
         | 
| 29 29 |  | 
| 30 30 | 
             
                        define_method("#{name_sym}=") do |value|
         | 
| 31 | 
            -
                           | 
| 31 | 
            +
                          if value.nil?
         | 
| 32 | 
            +
                            attributes.delete(name_sym)
         | 
| 33 | 
            +
                          else
         | 
| 34 | 
            +
                            attributes[name_sym] = value.kind_of?(klass) ? value : klass.new(value)
         | 
| 35 | 
            +
                          end
         | 
| 32 36 | 
             
                        end
         | 
| 33 37 | 
             
                      else
         | 
| 34 38 | 
             
                        define_method(name_sym) do
         | 
| @@ -57,6 +61,12 @@ module NetSuite | |
| 57 61 | 
             
                      field name
         | 
| 58 62 | 
             
                    end
         | 
| 59 63 |  | 
| 64 | 
            +
                    # a bit of trickery: this is for classes which inherit from other classes
         | 
| 65 | 
            +
                    # i.e. the AssemblyItem, KitItem, etc; this copies the superclass's fields over
         | 
| 66 | 
            +
                    def inherited(klass)
         | 
| 67 | 
            +
                      klass.instance_variable_set("@fields", self.fields)
         | 
| 68 | 
            +
                      klass.instance_variable_set("@read_only_fields", self.read_only_fields)
         | 
| 69 | 
            +
                    end
         | 
| 60 70 | 
             
                  end
         | 
| 61 71 |  | 
| 62 72 | 
             
                end
         | 
| @@ -34,13 +34,18 @@ module NetSuite | |
| 34 34 | 
             
                  end
         | 
| 35 35 |  | 
| 36 36 | 
             
                  def build_response
         | 
| 37 | 
            -
                    Response.new(:success => success?, :body => response_body)
         | 
| 37 | 
            +
                    Response.new(:success => success?, header: response_header, :body => response_body)
         | 
| 38 38 | 
             
                  end
         | 
| 39 39 |  | 
| 40 40 | 
             
                  def success?
         | 
| 41 41 | 
             
                    raise NotImplementedError, 'Please implement a #success? method'
         | 
| 42 42 | 
             
                  end
         | 
| 43 43 |  | 
| 44 | 
            +
                  # Only care about headers in Search class for now
         | 
| 45 | 
            +
                  def response_header
         | 
| 46 | 
            +
                    nil
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 44 49 | 
             
                  def response_body
         | 
| 45 50 | 
             
                    raise NotImplementedError, 'Please implement a #response_body method'
         | 
| 46 51 | 
             
                  end
         | 
| @@ -0,0 +1,67 @@ | |
| 1 | 
            +
            module NetSuite
         | 
| 2 | 
            +
              module Support
         | 
| 3 | 
            +
                class SearchResult
         | 
| 4 | 
            +
                  attr_accessor :response
         | 
| 5 | 
            +
                  attr_reader :total_records
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  # header from a basic customer search:
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  # <platformCore:searchResult xmlns:platformCore="urn:core_2012_1.platform.webservices.netsuite.com">
         | 
| 10 | 
            +
                  #   <platformCore:status isSuccess="true"/>
         | 
| 11 | 
            +
                  #   <platformCore:totalRecords>2770</platformCore:totalRecords>
         | 
| 12 | 
            +
                  #   <platformCore:pageSize>5</platformCore:pageSize>
         | 
| 13 | 
            +
                  #   <platformCore:totalPages>554</platformCore:totalPages>
         | 
| 14 | 
            +
                  #   <platformCore:pageIndex>1</platformCore:pageIndex>
         | 
| 15 | 
            +
                  #   <platformCore:searchId>WEBSERVICES_738944_SB2_03012013650784545962753432_28d96bd280</platformCore:searchId>
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def initialize(response, result_class)
         | 
| 18 | 
            +
                    @response = response
         | 
| 19 | 
            +
                    @total_records = response.body[:total_records].to_i
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    if @total_records > 0
         | 
| 22 | 
            +
                      if @total_records == 1
         | 
| 23 | 
            +
                        [response.body[:record_list][:record]]
         | 
| 24 | 
            +
                      else
         | 
| 25 | 
            +
                        response.body[:record_list][:record]
         | 
| 26 | 
            +
                      end.each do |record|
         | 
| 27 | 
            +
                        results << result_class.new(record)
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    # search_results = []
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    # if !!response.body[:search_row_list] && !response.body[:search_row_list].empty?
         | 
| 34 | 
            +
                    #   response.body[:search_row_list][:search_row].each do |record|
         | 
| 35 | 
            +
                    #     search_result = NetSuite::Support::SearchResult.new(record)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    #     search_results << search_result
         | 
| 38 | 
            +
                    #   end
         | 
| 39 | 
            +
                    # end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    # search_id = response.header[:ns_id]
         | 
| 42 | 
            +
                    # page_index = response.body[:page_index]
         | 
| 43 | 
            +
                    # total_pages = response.body[:total_pages]
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    # response_hash[:search_id] = search_id
         | 
| 46 | 
            +
                    # response_hash[:page_index] = page_index
         | 
| 47 | 
            +
                    # response_hash[:total_pages] = total_pages
         | 
| 48 | 
            +
                    # response_hash[:search_results] = search_results
         | 
| 49 | 
            +
                    # puts response.body
         | 
| 50 | 
            +
                    # response_hash
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  def results
         | 
| 54 | 
            +
                    @results ||= []
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  def next_page
         | 
| 58 | 
            +
                    
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  def all_pages
         | 
| 62 | 
            +
                    
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
            end
         | 
    
        data/lib/netsuite/version.rb
    CHANGED
    
    
| @@ -38,6 +38,14 @@ describe NetSuite::Configuration do | |
| 38 38 | 
             
                    config.wsdl.should match(/.*\/netsuite\/wsdl\/2011_2\.wsdl/)
         | 
| 39 39 | 
             
                  end
         | 
| 40 40 | 
             
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                context 'when the wsdl has not been set, but the API has been set' do
         | 
| 43 | 
            +
                  it 'should correctly return the full HTTP sandbox URL' do
         | 
| 44 | 
            +
                    config.api_version '2013_1'
         | 
| 45 | 
            +
                    config.sandbox false
         | 
| 46 | 
            +
                    config.wsdl.should eql('https://webservices.netsuite.com/wsdl/v2013_1_0/netsuite.wsdl')
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                end
         | 
| 41 49 | 
             
              end
         | 
| 42 50 |  | 
| 43 51 | 
             
              describe '#auth_header' do
         | 
| @@ -23,8 +23,9 @@ describe NetSuite::Records::NonInventorySaleItem do | |
| 23 23 | 
             
                  item.should have_field(field)
         | 
| 24 24 | 
             
                end
         | 
| 25 25 |  | 
| 26 | 
            -
                 | 
| 26 | 
            +
                # TODO there is a probably a more robust way to test this
         | 
| 27 27 | 
             
                item.custom_field_list.class.should == NetSuite::Records::CustomFieldList
         | 
| 28 | 
            +
                item.pricing_matrix.class.should == NetSuite::Records::PricingMatrix
         | 
| 28 29 | 
             
              end
         | 
| 29 30 |  | 
| 30 31 | 
             
              it 'has the right record_refs' do
         | 
| @@ -1,5 +1,14 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe NetSuite::Support::RecordRefs do
         | 
| 4 | 
            -
               | 
| 4 | 
            +
              let(:klass) { Class.new.send(:include, NetSuite::Support::Fields) }
         | 
| 5 | 
            +
              let(:instance) { klass.new }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              context "assigning record reference" do
         | 
| 8 | 
            +
                it 'assigns a nil value for a field with a specified class' do
         | 
| 9 | 
            +
                  klass.field(:record_test, NetSuite::Records::RecordRef)
         | 
| 10 | 
            +
                  instance.record_test = nil
         | 
| 11 | 
            +
                  instance.attributes.has_key?(:record_test).should be_false
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 5 14 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            name: netsuite
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 4 | 
             
              prerelease: 
         | 
| 5 | 
            -
              version: 0.0. | 
| 5 | 
            +
              version: 0.0.50
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| 8 8 | 
             
            - Ryan Moran
         | 
| @@ -10,7 +10,7 @@ authors: | |
| 10 10 | 
             
            autorequire: 
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date: 2013- | 
| 13 | 
            +
            date: 2013-04-04 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| @@ -112,10 +112,13 @@ files: | |
| 112 112 | 
             
            - lib/netsuite/actions/delete.rb
         | 
| 113 113 | 
             
            - lib/netsuite/actions/get.rb
         | 
| 114 114 | 
             
            - lib/netsuite/actions/initialize.rb
         | 
| 115 | 
            +
            - lib/netsuite/actions/search.rb
         | 
| 116 | 
            +
            - lib/netsuite/actions/search_more_with_id.rb
         | 
| 115 117 | 
             
            - lib/netsuite/actions/update.rb
         | 
| 116 118 | 
             
            - lib/netsuite/configuration.rb
         | 
| 117 119 | 
             
            - lib/netsuite/core_ext/string/lower_camelcase.rb
         | 
| 118 120 | 
             
            - lib/netsuite/errors.rb
         | 
| 121 | 
            +
            - lib/netsuite/namespaces/act_sched.rb
         | 
| 119 122 | 
             
            - lib/netsuite/namespaces/list_acct.rb
         | 
| 120 123 | 
             
            - lib/netsuite/namespaces/list_rel.rb
         | 
| 121 124 | 
             
            - lib/netsuite/namespaces/platform_common.rb
         | 
| @@ -128,7 +131,10 @@ files: | |
| 128 131 | 
             
            - lib/netsuite/records/accounting_period.rb
         | 
| 129 132 | 
             
            - lib/netsuite/records/assembly_item.rb
         | 
| 130 133 | 
             
            - lib/netsuite/records/bill_address.rb
         | 
| 134 | 
            +
            - lib/netsuite/records/bin_number_list.rb
         | 
| 131 135 | 
             
            - lib/netsuite/records/classification.rb
         | 
| 136 | 
            +
            - lib/netsuite/records/contact.rb
         | 
| 137 | 
            +
            - lib/netsuite/records/contact_list.rb
         | 
| 132 138 | 
             
            - lib/netsuite/records/credit_memo.rb
         | 
| 133 139 | 
             
            - lib/netsuite/records/credit_memo_apply.rb
         | 
| 134 140 | 
             
            - lib/netsuite/records/credit_memo_apply_list.rb
         | 
| @@ -158,6 +164,7 @@ files: | |
| 158 164 | 
             
            - lib/netsuite/records/journal_entry.rb
         | 
| 159 165 | 
             
            - lib/netsuite/records/journal_entry_line.rb
         | 
| 160 166 | 
             
            - lib/netsuite/records/journal_entry_line_list.rb
         | 
| 167 | 
            +
            - lib/netsuite/records/kit_item.rb
         | 
| 161 168 | 
             
            - lib/netsuite/records/location.rb
         | 
| 162 169 | 
             
            - lib/netsuite/records/non_inventory_sale_item.rb
         | 
| 163 170 | 
             
            - lib/netsuite/records/payment_method.rb
         | 
| @@ -168,7 +175,9 @@ files: | |
| 168 175 | 
             
            - lib/netsuite/records/sales_order_item.rb
         | 
| 169 176 | 
             
            - lib/netsuite/records/sales_order_item_list.rb
         | 
| 170 177 | 
             
            - lib/netsuite/records/ship_address.rb
         | 
| 178 | 
            +
            - lib/netsuite/records/task.rb
         | 
| 171 179 | 
             
            - lib/netsuite/records/term.rb
         | 
| 180 | 
            +
            - lib/netsuite/records/transaction.rb
         | 
| 172 181 | 
             
            - lib/netsuite/response.rb
         | 
| 173 182 | 
             
            - lib/netsuite/support/actions.rb
         | 
| 174 183 | 
             
            - lib/netsuite/support/attributes.rb
         | 
| @@ -176,6 +185,7 @@ files: | |
| 176 185 | 
             
            - lib/netsuite/support/record_refs.rb
         | 
| 177 186 | 
             
            - lib/netsuite/support/records.rb
         | 
| 178 187 | 
             
            - lib/netsuite/support/requests.rb
         | 
| 188 | 
            +
            - lib/netsuite/support/search_result.rb
         | 
| 179 189 | 
             
            - lib/netsuite/version.rb
         | 
| 180 190 | 
             
            - lib/netsuite/xml_logger.rb
         | 
| 181 191 | 
             
            - netsuite.gemspec
         |