netsuite 0.8.7 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dbeff776d5c83998c7a1f32ede92f9dc5e23dc9779edb7f468c9069f78d45e2c
4
- data.tar.gz: ae0a8d348549c9bfbdd069b2430ceb14d4d9934e5f3af32a2b9cfd4841c7a03b
3
+ metadata.gz: acf21d9a2b7a9ee0eedee971c7ebd1af50c05c28a1a5a03dea740fc1eb22529c
4
+ data.tar.gz: 6b740ed5e9b8d76926d63ca2895d0370b11b0c0656bd2581f15b9133f7d7edec
5
5
  SHA512:
6
- metadata.gz: e832952fe6eba8acb9f2126d6bc378a534a7d081c0f0007c995eebb9d4fe6c11e16a4a5ed8cacfb9135f2e4309d74ffa8535cb6e5825606788f9acff7f980e7b
7
- data.tar.gz: 104588f1bba07662f374d67940ff06fb0cb9b8ffc30cebf402791113d2d8eda023812978025a07dfabd1677108228d6810564c5638fd87cffb1bbc4bb7c04c7b
6
+ metadata.gz: 2a7d9f98b1574b63a6da20d65376e1edb936f8d16d44019871b8d7e2e7f1354956eac101d038f756bc8a2256977c6afbd0742c7f7badbd6ec89a8165fdde77f8
7
+ data.tar.gz: 6a268c38ec15d63e50f5c713363b7cf9f8b5faf67b1a4f40c4cdadc8728a27b1d2928d36debab70db278b26d36661d5e908ba04a3235464f0b23487ac1c6b91c
@@ -0,0 +1,20 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ ruby-version: [2.7, 2.6, 2.5, 2.4, 2.3, 2.2, 2.1]
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ - name: Set up Ruby ${{ matrix.ruby-version }}
14
+ uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: ${{ matrix.ruby-version }}
17
+ - name: Install dependencies
18
+ run: bundle install
19
+ - name: Run tests
20
+ run: bundle exec rake
data/Gemfile CHANGED
@@ -2,7 +2,6 @@ source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
4
  gem 'simplecov', :require => false
5
- gem 'rspec_junit_formatter'
6
5
 
7
6
  gem 'pry-nav'
8
7
  gem 'pry-rescue'
data/HISTORY.md ADDED
@@ -0,0 +1,26 @@
1
+ ## Unreleased
2
+
3
+ ### Added
4
+
5
+ *
6
+ *
7
+
8
+ ### Fixed
9
+
10
+ *
11
+ *
12
+
13
+ ## 0.8.8
14
+
15
+ ### Added
16
+
17
+ * Adding serialized assembly item to get_item
18
+ * Add CostCategory record (#482)
19
+ * Introduce search only fields (#483)
20
+
21
+ ### Fixed
22
+
23
+ * Fix accessing custom field values returned in advanced search results (#480)
24
+ * Fixing bug where single-selection custom multi select fields would incorrectly be parsed 3377c971d0cb727d81f4b4bc6e30edfbdfaccfd1
25
+ * Fixed some field definitions on serialized assembly item
26
+ * Properly extract external_id from advanced search results (#478)
data/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
18
18
 
19
- [![Circle CI](https://circleci.com/gh/NetSweet/netsuite/tree/master.svg?style=svg)](https://circleci.com/gh/NetSweet/netsuite/tree/master)
19
+ [![Ruby](https://github.com/NetSweet/netsuite/actions/workflows/main.yml/badge.svg)](https://github.com/NetSweet/netsuite/actions/workflows/main.yml)
20
20
  [![Slack Status](https://opensuite-slackin.herokuapp.com/badge.svg)](http://opensuite-slackin.herokuapp.com)
21
21
  [![Gem Version](https://badge.fury.io/rb/netsuite.svg)](http://badge.fury.io/rb/netsuite)
22
22
 
@@ -91,7 +91,7 @@ NetSuite.configure do
91
91
  # the endpoint indicated in the > 2018_2 wsdl is invalid
92
92
  # you must set the endpoint directly
93
93
  # https://github.com/NetSweet/netsuite/pull/473
94
- endpoint "#{wsdl_domain}/services/NetSuitePort_#{api_version}"
94
+ endpoint "https://#{wsdl_domain}/services/NetSuitePort_#{api_version}"
95
95
  end
96
96
  ```
97
97
 
@@ -173,7 +173,7 @@ NetSuite.configure do
173
173
  # the endpoint indicated in the > 2018_2 wsdl is invalid
174
174
  # you must set the endpoint directly
175
175
  # https://github.com/NetSweet/netsuite/pull/473
176
- endpoint "#{wsdl_domain}/services/NetSuitePort_#{api_version}"
176
+ endpoint "https://#{wsdl_domain}/services/NetSuitePort_#{api_version}"
177
177
  end
178
178
  ```
179
179
 
@@ -435,7 +435,9 @@ NetSuite::Records::SalesOrder.search({
435
435
  'tranSales:itemJoin' => [
436
436
  'platformCommon:customFieldList' => [
437
437
  'platformCore:customField/' => {
438
- '@internalId' => 'custitem_apcategoryforsales',
438
+ '@scriptId' => 'custitem_apcategoryforsales',
439
+ # Or, for API versions 2013.1 and older:
440
+ # '@internalId' => 'custitem_apcategoryforsales',
439
441
  '@xsi:type' => "platformCore:SearchColumnSelectCustomField"
440
442
  }
441
443
  ]
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ task :default => :spec
7
7
 
8
8
  desc 'Run specs'
9
9
  RSpec::Core::RakeTask.new do |t|
10
- t.pattern = './spec/**/*_spec.rb'
10
+ # t.pattern = './spec/**/*_spec.rb'
11
11
  end
12
12
 
13
13
  desc 'Generate code coverage'
data/lib/netsuite.rb CHANGED
@@ -95,6 +95,7 @@ module NetSuite
95
95
  autoload :CashRefundItemList, 'netsuite/records/cash_refund_item_list'
96
96
  autoload :Campaign, 'netsuite/records/campaign'
97
97
  autoload :Classification, 'netsuite/records/classification'
98
+ autoload :CostCategory, 'netsuite/records/cost_category'
98
99
  autoload :CreditMemo, 'netsuite/records/credit_memo'
99
100
  autoload :CreditMemoApply, 'netsuite/records/credit_memo_apply'
100
101
  autoload :CreditMemoApplyList, 'netsuite/records/credit_memo_apply_list'
@@ -0,0 +1,28 @@
1
+ module NetSuite
2
+ module Records
3
+ class CostCategory
4
+ include Support::Fields
5
+ include Support::RecordRefs
6
+ include Support::Records
7
+ include Support::Actions
8
+ include Namespaces::ListAcct
9
+
10
+ actions :add, :delete, :delete_list, :get, :get_all, :get_list, :get_select_value, :search, :update, :update_list, :upsert, :upsert_list
11
+ # TODO: Add add_list when supported by gem
12
+
13
+ fields :is_inactive, :item_cost_type, :name
14
+
15
+ record_refs :account
16
+
17
+ attr_reader :internal_id
18
+ attr_accessor :external_id
19
+
20
+ def initialize(attributes = {})
21
+ @internal_id = attributes.delete(:internal_id) || attributes.delete(:@internal_id)
22
+ @external_id = attributes.delete(:external_id) || attributes.delete(:@external_id)
23
+ initialize_from_attributes_hash(attributes)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -110,10 +110,16 @@ module NetSuite
110
110
  attrs = custom_field_data.clone
111
111
  type = (custom_field_data[:"@xsi:type"] || custom_field_data[:type])
112
112
 
113
- if type == "platformCore:SelectCustomFieldRef"
113
+ case type
114
+ when "platformCore:SelectCustomFieldRef", "platformCore:SearchColumnSelectCustomField"
114
115
  attrs[:value] = CustomRecordRef.new(custom_field_data[:value])
115
- elsif type == 'platformCore:MultiSelectCustomFieldRef'
116
- attrs[:value] = custom_field_data[:value].map do |entry|
116
+ when 'platformCore:MultiSelectCustomFieldRef', 'platformCore:SearchColumnMultiSelectCustomField'
117
+ # if there is only a single selection, `:value` will be hash not an array
118
+ attrs[:value] = if custom_field_data[:value].is_a?(Array)
119
+ custom_field_data[:value]
120
+ else
121
+ [custom_field_data[:value]]
122
+ end.map do |entry|
117
123
  CustomRecordRef.new(entry)
118
124
  end
119
125
  end
@@ -45,6 +45,66 @@ module NetSuite
45
45
  :total_value, :track_landed_cost, :transfer_price, :upc_code, :url_component, :use_bins, :use_marginal_rates,
46
46
  :vendor_name, :vsoe_deferral, :vsoe_delivered, :vsoe_permit_discount, :vsoe_price, :weight, :weight_unit, :weight_units
47
47
 
48
+ # https://system.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2020_2/schema/search/itemsearchrowbasic.html?mode=package
49
+ search_only_fields :acc_book_rev_rec_forecast_rule, :accounting_book,
50
+ :accounting_book_amortization, :accounting_book_create_plans_on,
51
+ :accounting_book_rev_rec_rule, :accounting_book_rev_rec_schedule,
52
+ :allowed_shipping_method, :atp_lead_time, :atp_method, :base_price,
53
+ :bin_number, :bin_on_hand_avail, :bin_on_hand_count, :bom_quantity,
54
+ :build_entire_assembly, :build_time, :buy_it_now_price, :category,
55
+ :category_preferred, :component_yield, :correlated_item,
56
+ :correlated_item_correlation, :correlated_item_count,
57
+ :correlated_item_lift, :correlated_item_purchase_rate,
58
+ :cost_accounting_status, :created, :create_job,
59
+ :cust_return_variance_account, :date_viewed, :days_before_expiration,
60
+ :default_shipping_method, :deferred_expense_account,
61
+ :departmentnohierarchy, :display_ine_bay_store, :e_bay_item_description,
62
+ :e_bay_item_subtitle, :e_bay_item_title, :ebay_relisting_option,
63
+ :effective_bom_control, :effective_date, :effective_revision,
64
+ :end_auctions_when_out_of_stock, :feed_description, :feed_name,
65
+ :froogle_product_feed, :fx_cost, :generate_accruals,
66
+ :gift_cert_auth_code, :gift_cert_email, :gift_cert_expiration_date,
67
+ :gift_cert_from, :gift_cert_message, :gift_cert_original_amount,
68
+ :gift_cert_recipient, :hierarchy_node, :hierarchy_version, :hits,
69
+ :image_url, :interco_expense_account, :inventory_location,
70
+ :is_available, :is_fulfillable, :is_lot_item, :is_serial_item,
71
+ :is_special_work_order_item, :is_vsoe_bundle, :is_wip, :item_url,
72
+ :last_quantity_available_change, :liability_account, :listing_duration,
73
+ :location_allow_store_pickup, :location_atp_lead_time,
74
+ :location_average_cost, :location_bin_quantity_available,
75
+ :location_build_time, :location_cost, :location_cost_accounting_status,
76
+ :location_default_return_cost, :location_demand_source,
77
+ :location_demand_time_fence, :location_fixed_lot_size,
78
+ :location_inventory_cost_template, :location_invt_classification,
79
+ :location_invt_count_interval, :location_last_invt_count_date,
80
+ :location_lead_time, :location_next_invt_count_date,
81
+ :location_periodic_lot_size_days, :location_periodic_lot_size_type,
82
+ :location_preferred_stock_level, :location_qty_avail_for_store_pickup,
83
+ :location_quantity_available, :location_quantity_back_ordered,
84
+ :location_quantity_committed, :location_quantity_in_transit,
85
+ :location_quantity_on_hand, :location_quantity_on_order,
86
+ :location_re_order_point, :location_reschedule_in_days,
87
+ :location_reschedule_out_days, :location_safety_stock_level,
88
+ :location_store_pickup_buffer_stock, :location_supply_lot_sizing_method,
89
+ :location_supply_time_fence, :location_supply_type,
90
+ :location_total_value, :loc_backward_consumption_days,
91
+ :loc_forward_consumption_days, :manufacturing_charge_item, :member_item,
92
+ :member_quantity, :modified, :moss_applies, :nextag_product_feed,
93
+ :num_active_listings, :number_allowed_downloads, :num_currently_listed,
94
+ :obsolete_date, :obsolete_revision, :online_customer_price,
95
+ :online_price, :other_prices, :other_vendor, :overhead_type,
96
+ :preferred_bin, :primary_category, :prod_price_variance_acct,
97
+ :prod_qty_variance_acct, :purchase_unit, :reserve_price,
98
+ :revenue_recognition_rule, :same_as_primary_book_amortization,
99
+ :same_as_primary_book_rev_rec, :scrap_acct, :sell_on_ebay,
100
+ :serial_number, :serial_number_location, :shipping_carrier,
101
+ :shipping_rate, :shopping_product_feed, :shopzilla_product_feed,
102
+ :soft_descriptor, :starting_price, :subsidiary, :sub_type,
103
+ :thumb_nail_url, :type, :unbuild_variance_account, :use_component_yield,
104
+ :vendor_code, :vendor_cost, :vendor_cost_entered,
105
+ :vendor_price_currency, :vendor_schedule, :vend_return_variance_account,
106
+ :web_site, :wip_acct, :wip_variance_acct, :yahoo_product_feed
107
+
48
108
  record_refs :alternate_demand_source_item, :asset_account, :bill_exch_rate_variance_acct, :bill_price_variance_acct,
49
109
  :bill_qty_variance_acct, :billing_schedule, :cogs_account, :cost_category, :custom_form, :deferred_revenue_account,
50
110
  :demand_source, :department, :expense_account, :gain_loss_account, :income_account, :issue_product, :klass, :location,
@@ -42,6 +42,99 @@ module NetSuite
42
42
  read_only_fields :sub_total, :discount_total, :total, :recognized_revenue, :amount_remaining, :amount_paid, :amount,
43
43
  :alt_shipping_cost, :gift_cert_applied, :handling_cost, :alt_handling_cost
44
44
 
45
+ # https://system.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2020_2/schema/search/transactionsearchrowbasic.html?mode=package
46
+ search_only_fields :abbrev, :account_type, :acct_corp_card_exp,
47
+ :actual_production_end_date, :actual_production_start_date,
48
+ :actual_ship_date, :alt_sales_amount, :alt_sales_net_amount, :amount,
49
+ :amount_unbilled, :applied_to_foreign_amount,
50
+ :applied_to_is_fx_variance, :applied_to_link_amount,
51
+ :applied_to_link_type, :applied_to_transaction,
52
+ :applying_foreign_amount, :applying_is_fx_variance,
53
+ :applying_link_amount, :applying_link_type, :applying_transaction,
54
+ :auth_code, :auto_calculate_lag, :avs_street_match, :avs_zip_match,
55
+ :billable, :bill_address, :bill_address1, :bill_address2,
56
+ :bill_address3, :bill_addressee, :bill_attention, :bill_city,
57
+ :bill_country, :bill_country_code, :billed_date, :billing_amount,
58
+ :billing_transaction, :bill_phone, :bill_state, :bill_variance_status,
59
+ :bill_zip, :bin_number, :bin_number_quantity, :bom_quantity,
60
+ :build_entire_assembly, :build_variance, :built,
61
+ :can_have_stackable_promotions, :catch_up_period, :cc_customer_code,
62
+ :cc_exp_date, :cc_holder_name, :cc_number, :cc_street, :cc_zip_code,
63
+ :cleared, :closed, :close_date, :cogs_amount,
64
+ :commission_effective_date, :commit, :component_yield,
65
+ :confirmation_number, :contribution, :contribution_primary,
66
+ :cost_component_amount, :cost_component_category, :cost_component_item,
67
+ :cost_component_quantity, :cost_component_standard_cost, :cost_estimate,
68
+ :cost_estimate_rate, :cost_estimate_type, :created_by, :credit_amount,
69
+ :csc_match, :custom_gl, :cust_type, :date_created, :days_open,
70
+ :days_overdue, :debit_amount, :defer_rev_rec, :deposit_date,
71
+ :deposit_transaction, :doc_unit, :dr_account, :effective_rate,
72
+ :entity_status, :est_gross_profit_pct, :exclude_from_rate_request,
73
+ :expected_close_date, :expected_receipt_date, :expense_category,
74
+ :expense_date, :firmed, :forecast_type, :fulfilling_transaction,
75
+ :fx_account, :fx_amount, :fx_cost_estimate, :fx_cost_estimate_rate,
76
+ :fx_est_gross_profit, :fx_tran_cost_estimate, :fx_vsoe_allocation,
77
+ :fx_vsoe_amount, :fx_vsoe_price, :gco_availabel_to_charge,
78
+ :gco_available_to_refund, :gco_avs_street_match, :gco_avs_zip_match,
79
+ :gco_buyer_account_age, :gco_buyer_ip, :gco_charge_amount,
80
+ :gco_chargeback_amount, :gco_confirmed_charged_total,
81
+ :gco_confirmed_refunded_total, :gco_creditcard_number, :gco_csc_match,
82
+ :gco_financial_state, :gco_fulfillment_state, :gco_order_id,
83
+ :gco_order_total, :gco_promotion_amount, :gco_promotion_name,
84
+ :gco_refund_amount, :gco_shipping_total, :gco_state_changed_detail,
85
+ :gift_cert, :gross_amount, :include_in_forecast, :incoterm,
86
+ :interco_status, :interco_transaction, :inventory_location,
87
+ :inventory_subsidiary, :in_vsoe_bundle, :is_allocation, :is_backflush,
88
+ :is_gco_chargeback, :is_gco_charge_confirmed,
89
+ :is_gco_payment_guaranteed, :is_gco_refund_confirmed,
90
+ :is_inside_delivery, :is_inside_pickup, :is_intercompany_adjustment,
91
+ :is_in_transit_payment, :is_multi_ship_to, :is_reversal,
92
+ :is_rev_rec_transaction, :is_scrap, :is_ship_address,
93
+ :is_transfer_price_costing, :is_wip, :item, :item_fulfillment_choice,
94
+ :item_revision, :landed_cost_per_line, :line, :line_sequence_number,
95
+ :line_unique_key, :location_auto_assigned, :main_line, :main_name,
96
+ :manufacturing_routing, :match_bill_to_receipt, :memo_main, :memorized,
97
+ :merchant_account, :multi_subsidiary, :net_amount, :net_amount_no_tax,
98
+ :next_bill_date, :no_auto_assign_location, :non_reimbursable,
99
+ :one_time_total, :options, :order_allocation_strategy, :order_priority,
100
+ :originator, :other_ref_num, :overhead_parent_item,
101
+ :override_installments, :package_count, :paid_amount, :paid_transaction,
102
+ :partner_contribution, :partner_role, :partner_team_member,
103
+ :paying_amount, :paying_transaction, :payment_approved,
104
+ :payment_event_date, :payment_event_hold_reason,
105
+ :payment_event_purchase_card_used, :payment_event_purchase_data_sent,
106
+ :payment_event_result, :payment_event_type, :payment_hold,
107
+ :payment_method, :payment_option, :pay_pal_pending, :pay_pal_status,
108
+ :pay_pal_tran_id, :payroll_batch, :pn_ref_num, :po_rate, :posting,
109
+ :price_level, :print, :probability, :projected_amount, :project_task,
110
+ :purchase_order, :quantity, :quantity_billed, :quantity_committed,
111
+ :quantity_packed, :quantity_picked, :quantity_rev_committed,
112
+ :quantity_ship_recv, :quantity_uom, :rate,
113
+ :realized_gain_posting_transaction, :recur_annually_total,
114
+ :recur_monthly_total, :recur_quarterly_total, :recur_weekly_total,
115
+ :ref_number, :requested_date, :rev_commit_status,
116
+ :rev_committing_transaction, :reversal_date, :reversal_number,
117
+ :rg_account, :rg_amount, :sales_order, :sales_team_member,
118
+ :sales_team_role, :scheduling_method, :serial_number,
119
+ :serial_number_cost, :serial_number_cost_adjustment,
120
+ :serial_number_quantity, :serial_numbers, :ship_address, :ship_address1,
121
+ :ship_address2, :ship_address3, :ship_addressee, :ship_attention,
122
+ :ship_carrier, :ship_city, :ship_complete, :ship_country,
123
+ :ship_country_code, :ship_group, :ship_phone, :shipping_amount,
124
+ :ship_recv_status_line, :ship_state, :ship_to, :ship_zip,
125
+ :signed_amount, :subscription, :subscription_line, :tax_amount,
126
+ :tax_code, :tax_line, :tax_period, :term_in_months, :terms_of_sale,
127
+ :title, :to_subsidiary, :tran_est_gross_profit,
128
+ :tran_fx_est_gross_profit, :transaction_discount,
129
+ :transaction_line_type, :transaction_number, :transfer_location,
130
+ :transfer_order_item_line, :transfer_order_quantity_committed,
131
+ :transfer_order_quantity_packed, :transfer_order_quantity_picked,
132
+ :transfer_order_quantity_received, :transfer_order_quantity_shipped,
133
+ :type, :unit, :unit_cost_override, :vend_type, :visible_to_customer,
134
+ :vsoe_allocation, :vsoe_amount, :vsoe_deferral, :vsoe_delivered,
135
+ :vsoe_permit_discount, :vsoe_price, :web_site
136
+ # TODO: Add record_type, conflicts with Support::Records#record_type, returns "invoice" versus "tranSales:Invoice"
137
+
45
138
  record_refs :account, :bill_address_list, :custom_form, :department, :entity, :klass, :partner,
46
139
  :posting_period, :ship_address_list, :terms, :location, :sales_rep, :tax_item, :created_from,
47
140
  :ship_method, :lead_source, :promo_code, :subsidiary, :currency, :approval_status, :job, :discount_item
@@ -61,7 +61,6 @@ module NetSuite
61
61
  :hazmat_packing_group,
62
62
  :hazmat_shipping_name,
63
63
  :include_children,
64
- :income_account,
65
64
  :interco_cogs_account,
66
65
  :interco_income_account,
67
66
  :invt_classification,
@@ -209,6 +208,8 @@ module NetSuite
209
208
  :wip_acct,
210
209
  :wip_variance_acct
211
210
 
211
+ record_refs :income_account
212
+
212
213
  # accountingBookDetailList ItemAccountingBookDetailList
213
214
  # binNumberList InventoryItemBinNumberList
214
215
  # itemOptionsList ItemOptionsList
@@ -220,6 +221,7 @@ module NetSuite
220
221
  # siteCategoryList SiteCategoryList
221
222
  # translationsList TranslationList
222
223
 
224
+ field :subsidiary_list, RecordRefList
223
225
  field :custom_field_list, CustomFieldList
224
226
 
225
227
  attr_reader :internal_id
@@ -60,6 +60,22 @@ module NetSuite
60
60
  read_only_fields << name_sym
61
61
  field name
62
62
  end
63
+
64
+ def search_only_fields(*args)
65
+ if args.empty?
66
+ @search_only_fields ||= Set.new
67
+ else
68
+ args.each do |arg|
69
+ search_only_field arg
70
+ end
71
+ end
72
+ end
73
+
74
+ def search_only_field(name)
75
+ name_sym = name.to_sym
76
+ search_only_fields << name_sym
77
+ field name
78
+ end
63
79
  end
64
80
 
65
81
  end
@@ -5,7 +5,7 @@ module NetSuite
5
5
  include Namespaces::PlatformCore
6
6
 
7
7
  def to_record
8
- attributes.reject { |k,v| self.class.read_only_fields.include?(k) }.inject({}) do |hash, (k,v)|
8
+ attributes.reject { |k,v| self.class.read_only_fields.include?(k) || self.class.search_only_fields.include?(k) }.inject({}) do |hash, (k,v)|
9
9
  kname = "#{record_namespace}:"
10
10
  kname += k == :klass ? 'class' : k.to_s.lower_camelcase
11
11
 
@@ -52,9 +52,6 @@ module NetSuite
52
52
  record_list = [record_list] unless record_list.is_a?(Array)
53
53
 
54
54
  record_list.each do |record|
55
- # TODO because of customFieldList we need to either make this recursive
56
- # or handle the customFieldList as a special case
57
-
58
55
  record.each_pair do |search_group, search_data|
59
56
  # skip all attributes: look for :basic and all :xxx_join
60
57
  next if search_group.to_s.start_with?('@')
@@ -63,7 +60,25 @@ module NetSuite
63
60
  # all return values are wrapped in a <SearchValue/>
64
61
  # extract the value from <SearchValue/> to make results easier to work with
65
62
 
66
- if v.is_a?(Hash) && v.has_key?(:search_value)
63
+ if k == :custom_field_list
64
+ # Here's an example of a response
65
+
66
+ # <platformCommon:customFieldList>
67
+ # <platformCore:customField internalId="1756" scriptId="custitem_stringfield" xsi:type="platformCore:SearchColumnStringCustomField">
68
+ # <platformCore:searchValue>sample string value</platformCore:searchValue>
69
+ # </platformCore:customField>
70
+ # <platformCore:customField internalId="1713" scriptId="custitem_apcategoryforsales" xsi:type="platformCore:SearchColumnSelectCustomField">
71
+ # <platformCore:searchValue internalId="4" typeId="464"/>
72
+ # </platformCore:customField>
73
+ # </platformCommon:customFieldList>
74
+
75
+ custom_field_list = v.fetch(:custom_field)
76
+ custom_field_list = [custom_field_list] unless custom_field_list.is_a?(Array)
77
+ record[search_group][k][:custom_field] = custom_field_list.map do |custom_field|
78
+ custom_field[:value] = custom_field.fetch(:search_value)
79
+ custom_field
80
+ end
81
+ elsif v.is_a?(Hash) && v.has_key?(:search_value)
67
82
  # Here's an example of a record ref and string response
68
83
 
69
84
  # <platformCommon:entity>
@@ -89,6 +104,10 @@ module NetSuite
89
104
  record[:basic][:internal_id] = record[:basic][:internal_id][:@internal_id]
90
105
  end
91
106
 
107
+ if record[:basic][:external_id]
108
+ record[:basic][:external_id] = record[:basic][:external_id][:@external_id]
109
+ end
110
+
92
111
  result_wrapper = result_class.new(record.delete(:basic))
93
112
  result_wrapper.search_joins = record
94
113
  results << result_wrapper
@@ -173,6 +173,7 @@ module NetSuite
173
173
  ns_item ||= NetSuite::Utilities.get_record(NetSuite::Records::GiftCertificateItem, ns_item_internal_id, opts)
174
174
  ns_item ||= NetSuite::Utilities.get_record(NetSuite::Records::KitItem, ns_item_internal_id, opts)
175
175
  ns_item ||= NetSuite::Utilities.get_record(NetSuite::Records::SerializedInventoryItem, ns_item_internal_id, opts)
176
+ ns_item ||= NetSuite::Utilities.get_record(NetSuite::Records::SerializedAssemblyItem, ns_item_internal_id, opts)
176
177
  ns_item ||= NetSuite::Utilities.get_record(NetSuite::Records::LotNumberedAssemblyItem, ns_item_internal_id, opts)
177
178
  ns_item ||= NetSuite::Utilities.get_record(NetSuite::Records::LotNumberedInventoryItem, ns_item_internal_id, opts)
178
179
 
@@ -1,3 +1,3 @@
1
1
  module NetSuite
2
- VERSION = '0.8.7'
2
+ VERSION = '0.8.8'
3
3
  end
data/netsuite.gemspec CHANGED
@@ -18,5 +18,6 @@ Gem::Specification.new do |gem|
18
18
 
19
19
  gem.add_dependency 'savon', '>= 2.3.0', '<= 2.11.1'
20
20
 
21
- gem.add_development_dependency 'rspec', '~> 3.8.0'
21
+ gem.add_development_dependency 'rspec', '~> 3.10.0'
22
+ gem.add_development_dependency 'rake'
22
23
  end
@@ -168,9 +168,31 @@ describe NetSuite::Actions::Search do
168
168
 
169
169
  expect(search.results.size).to eq(2)
170
170
  expect(search.current_page).to eq(1)
171
+ expect(search.results.first.internal_id).to eq('123')
172
+ expect(search.results.first.external_id).to eq('456')
171
173
  expect(search.results.first.alt_name).to eq('A Awesome Name')
174
+ expect(search.results.first.custom_field_list.custitem_stringfield.value).to eq('sample string value')
175
+ expect(search.results.first.custom_field_list.custitem_apcategoryforsales.value.internal_id).to eq('4')
172
176
  expect(search.results.last.email).to eq('alessawesome@gmail.com')
173
177
  end
178
+
179
+ it "should handle an ID search with basic search only field result columns" do
180
+ response = File.read('spec/support/fixtures/search/saved_search_item.xml')
181
+ savon.expects(:search)
182
+ .with(message: {
183
+ "searchRecord"=>{
184
+ "@xsi:type" =>"listAcct:ItemSearchAdvanced",
185
+ "@savedSearchId" =>42,
186
+ :content! =>{"listAcct:criteria"=>{}},
187
+ }
188
+ }).returns(response)
189
+
190
+ search = NetSuite::Records::InventoryItem.search(saved: 42)
191
+
192
+ expect(search.results.first.location_quantity_available).to eq('3307.0')
193
+ expect(search.results.first.location_re_order_point).to eq('2565.0')
194
+ expect(search.results.first.location_quantity_on_order).to eq('40000.0')
195
+ end
174
196
  end
175
197
 
176
198
  context "advanced search" do
@@ -401,7 +401,7 @@ describe NetSuite::Configuration do
401
401
 
402
402
  describe "#log" do
403
403
  it 'allows a file path to be set as the log destination' do
404
- file_path = Tempfile.new.path
404
+ file_path = Tempfile.new('tmplog').path
405
405
  config.log = file_path
406
406
  config.logger.info "foo"
407
407
 
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::CostCategory do
4
+ let(:cost_category) { described_class.new }
5
+
6
+ it 'has all the right fields' do
7
+ [
8
+ :is_inactive,
9
+ :item_cost_type,
10
+ :name,
11
+ ].each do |field|
12
+ expect(cost_category).to have_field(field)
13
+ end
14
+ end
15
+
16
+ it 'has all the right record refs' do
17
+ [
18
+ :account,
19
+ ].each do |record_ref|
20
+ expect(cost_category).to have_record_ref(record_ref)
21
+ end
22
+ end
23
+
24
+ describe '.get' do
25
+ context 'when the response is successful' do
26
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :name => 'CostCategory 1' }) }
27
+
28
+ it 'returns a CostCategory instance populated with the data from the response object' do
29
+ expect(NetSuite::Actions::Get).to receive(:call).with([described_class, {:external_id => 1}], {}).and_return(response)
30
+ cost_category = described_class.get(:external_id => 1)
31
+ expect(cost_category).to be_kind_of(described_class)
32
+ expect(cost_category.name).to eql('CostCategory 1')
33
+ end
34
+ end
35
+
36
+ context 'when the response is unsuccessful' do
37
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
38
+
39
+ it 'raises a RecordNotFound exception' do
40
+ expect(NetSuite::Actions::Get).to receive(:call).with([described_class, {:external_id => 1}], {}).and_return(response)
41
+ expect {
42
+ described_class.get(:external_id => 1)
43
+ }.to raise_error(NetSuite::RecordNotFound,
44
+ /NetSuite::Records::CostCategory with OPTIONS=(.*) could not be found/)
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#add' do
50
+ let(:test_data) { { :name => 'Test CostCategory' } }
51
+
52
+ context 'when the response is successful' do
53
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
54
+
55
+ it 'returns true' do
56
+ cost_category = described_class.new(test_data)
57
+ expect(NetSuite::Actions::Add).to receive(:call).
58
+ with([cost_category], {}).
59
+ and_return(response)
60
+ expect(cost_category.add).to be_truthy
61
+ end
62
+ end
63
+
64
+ context 'when the response is unsuccessful' do
65
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
66
+
67
+ it 'returns false' do
68
+ cost_category = described_class.new(test_data)
69
+ expect(NetSuite::Actions::Add).to receive(:call).
70
+ with([cost_category], {}).
71
+ and_return(response)
72
+ expect(cost_category.add).to be_falsey
73
+ end
74
+ end
75
+ end
76
+
77
+ describe '#delete' do
78
+ let(:test_data) { { :internal_id => '1' } }
79
+
80
+ context 'when the response is successful' do
81
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
82
+
83
+ it 'returns true' do
84
+ cost_category = described_class.new(test_data)
85
+ expect(NetSuite::Actions::Delete).to receive(:call).
86
+ with([cost_category], {}).
87
+ and_return(response)
88
+ expect(cost_category.delete).to be_truthy
89
+ end
90
+ end
91
+
92
+ context 'when the response is unsuccessful' do
93
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
94
+
95
+ it 'returns false' do
96
+ cost_category = described_class.new(test_data)
97
+ expect(NetSuite::Actions::Delete).to receive(:call).
98
+ with([cost_category], {}).
99
+ and_return(response)
100
+ expect(cost_category.delete).to be_falsey
101
+ end
102
+ end
103
+ end
104
+
105
+ end
@@ -3,17 +3,53 @@ require 'spec_helper'
3
3
  describe NetSuite::Records::CustomFieldList do
4
4
  let(:list) { NetSuite::Records::CustomFieldList.new }
5
5
 
6
+ before(:all) { savon.mock! }
7
+ after(:all) { savon.unmock! }
8
+
6
9
  it 'has a custom_fields attribute' do
7
10
  expect(list.custom_fields).to be_kind_of(Array)
8
11
  end
9
12
 
10
13
  it 'accepts a collection of CustomField records' do
11
- field = NetSuite::Records::CustomField.new({:value=>{:internal_id=>"5", :type_id=>"103"},
12
- :script_id=>"custitem_item_category", :"@xsi:type"=>"platformCore:SelectCustomFieldRef"})
14
+ field = NetSuite::Records::CustomField.new({
15
+ :value=>{:internal_id=>"5", :type_id=>"103"},
16
+ :script_id=>"custitem_item_category",
17
+ :"@xsi:type"=>"platformCore:SelectCustomFieldRef"
18
+ })
19
+
13
20
  list = described_class.new(custom_field: [field])
21
+
14
22
  expect(list.custom_fields).to eq([field])
15
23
  end
16
24
 
25
+ it 'properly decodes various custom field types' do
26
+ savon.
27
+ expects(:get).
28
+ with(message: {"platformMsgs:baseRef"=>{"@xsi:type"=>"platformCore:RecordRef", "@internalId"=>123, "@type"=>"creditMemo"}}).
29
+ returns(File.read('spec/support/fixtures/custom_fields/multi_select.xml'))
30
+
31
+ credit_memo_with_custom_fields = NetSuite::Records::CreditMemo.get(123)
32
+
33
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_standard_select.value.internal_id).to eq("2")
34
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_standard_select.value.attributes[:name]).to eq("Manual")
35
+
36
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_date_field.value).to be_a(DateTime)
37
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_date_field.value.to_s).to eq("2021-07-13T22:00:00-07:00")
38
+
39
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_string_field.value).to eq("a very nice string")
40
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_boolean_field.value).to eq(false)
41
+
42
+ # even if there's a single value, it should return an array
43
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_field.value).to be_a(Array)
44
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_field.value.size).to eq(1)
45
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_field.value.first.attributes[:name]).to eq("selection value")
46
+
47
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_with_multiple.value).to be_a(Array)
48
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_with_multiple.value.size).to eq(2)
49
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_with_multiple.value.first.attributes[:name]).to eq("selection value 1")
50
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_with_multiple.value.last.attributes[:name]).to eq("selection value 2")
51
+ end
52
+
17
53
  context 'initializing with custom field attributes without a type' do
18
54
  it 'does not mutate the attributes' do
19
55
  field = {:value=>{:internal_id=>"5", :type_id=>"103"},
@@ -28,7 +64,9 @@ describe NetSuite::Records::CustomFieldList do
28
64
  it 'does not mutate the attributes' do
29
65
  field = {:value=>{:internal_id=>"5", :type_id=>"103"},
30
66
  :script_id=>"custitem_item_category", :"@xsi:type"=>"platformCore:SelectCustomFieldRef"}
67
+
31
68
  described_class.new(custom_field: [field])
69
+
32
70
  expect(field).to eq({:value=>{:internal_id=>"5", :type_id=>"103"},
33
71
  :script_id=>"custitem_item_category", :"@xsi:type"=>"platformCore:SelectCustomFieldRef"})
34
72
  end
@@ -31,6 +31,70 @@ describe NetSuite::Records::InventoryItem do
31
31
  end
32
32
  end
33
33
 
34
+ it 'has all the right search_only_fields' do
35
+ [
36
+ :acc_book_rev_rec_forecast_rule, :accounting_book,
37
+ :accounting_book_amortization, :accounting_book_create_plans_on,
38
+ :accounting_book_rev_rec_rule, :accounting_book_rev_rec_schedule,
39
+ :allowed_shipping_method, :atp_lead_time, :atp_method, :base_price,
40
+ :bin_number, :bin_on_hand_avail, :bin_on_hand_count, :bom_quantity,
41
+ :build_entire_assembly, :build_time, :buy_it_now_price, :category,
42
+ :category_preferred, :component_yield, :correlated_item,
43
+ :correlated_item_correlation, :correlated_item_count,
44
+ :correlated_item_lift, :correlated_item_purchase_rate,
45
+ :cost_accounting_status, :created, :create_job,
46
+ :cust_return_variance_account, :date_viewed, :days_before_expiration,
47
+ :default_shipping_method, :deferred_expense_account,
48
+ :departmentnohierarchy, :display_ine_bay_store, :e_bay_item_description,
49
+ :e_bay_item_subtitle, :e_bay_item_title, :ebay_relisting_option,
50
+ :effective_bom_control, :effective_date, :effective_revision,
51
+ :end_auctions_when_out_of_stock, :feed_description, :feed_name,
52
+ :froogle_product_feed, :fx_cost, :generate_accruals, :gift_cert_auth_code,
53
+ :gift_cert_email, :gift_cert_expiration_date, :gift_cert_from,
54
+ :gift_cert_message, :gift_cert_original_amount, :gift_cert_recipient,
55
+ :hierarchy_node, :hierarchy_version, :hits, :image_url,
56
+ :interco_expense_account, :inventory_location, :is_available,
57
+ :is_fulfillable, :is_lot_item, :is_serial_item,
58
+ :is_special_work_order_item, :is_vsoe_bundle, :is_wip, :item_url,
59
+ :last_quantity_available_change, :liability_account, :listing_duration,
60
+ :location_allow_store_pickup, :location_atp_lead_time,
61
+ :location_average_cost, :location_bin_quantity_available,
62
+ :location_build_time, :location_cost, :location_cost_accounting_status,
63
+ :location_default_return_cost, :location_demand_source,
64
+ :location_demand_time_fence, :location_fixed_lot_size,
65
+ :location_inventory_cost_template, :location_invt_classification,
66
+ :location_invt_count_interval, :location_last_invt_count_date,
67
+ :location_lead_time, :location_next_invt_count_date,
68
+ :location_periodic_lot_size_days, :location_periodic_lot_size_type,
69
+ :location_preferred_stock_level, :location_qty_avail_for_store_pickup,
70
+ :location_quantity_available, :location_quantity_back_ordered,
71
+ :location_quantity_committed, :location_quantity_in_transit,
72
+ :location_quantity_on_hand, :location_quantity_on_order,
73
+ :location_re_order_point, :location_reschedule_in_days,
74
+ :location_reschedule_out_days, :location_safety_stock_level,
75
+ :location_store_pickup_buffer_stock, :location_supply_lot_sizing_method,
76
+ :location_supply_time_fence, :location_supply_type, :location_total_value,
77
+ :loc_backward_consumption_days, :loc_forward_consumption_days,
78
+ :manufacturing_charge_item, :member_item, :member_quantity, :modified,
79
+ :moss_applies, :nextag_product_feed, :num_active_listings,
80
+ :number_allowed_downloads, :num_currently_listed, :obsolete_date,
81
+ :obsolete_revision, :online_customer_price, :online_price, :other_prices,
82
+ :other_vendor, :overhead_type, :preferred_bin, :primary_category,
83
+ :prod_price_variance_acct, :prod_qty_variance_acct, :purchase_unit,
84
+ :reserve_price, :revenue_recognition_rule,
85
+ :same_as_primary_book_amortization, :same_as_primary_book_rev_rec,
86
+ :scrap_acct, :sell_on_ebay, :serial_number, :serial_number_location,
87
+ :shipping_carrier, :shipping_rate, :shopping_product_feed,
88
+ :shopzilla_product_feed, :soft_descriptor, :starting_price, :subsidiary,
89
+ :sub_type, :thumb_nail_url, :type, :unbuild_variance_account,
90
+ :use_component_yield, :vendor_code, :vendor_cost, :vendor_cost_entered,
91
+ :vendor_price_currency, :vendor_schedule, :vend_return_variance_account,
92
+ :web_site, :wip_acct, :wip_variance_acct, :yahoo_product_feed,
93
+ ].each do |field|
94
+ expect(NetSuite::Records::InventoryItem).to have_search_only_field(field)
95
+ end
96
+ end
97
+
34
98
  it 'has all the right record refs' do
35
99
  [
36
100
  :alternate_demand_source_item, :asset_account, :bill_exch_rate_variance_acct, :bill_price_variance_acct, :bill_qty_variance_acct, :billing_schedule, :cogs_account, :cost_category, :custom_form, :deferred_revenue_account, :demand_source, :department, :expense_account, :gain_loss_account, :income_account, :issue_product, :klass, :location, :parent, :preferred_location, :pricing_group, :purchase_price_variance_acct, :purchase_tax_code, :purchase_unit, :quantity_pricing_schedule, :rev_rec_schedule, :sale_unit, :sales_tax_code, :ship_package, :soft_descriptor, :stock_unit, :store_display_image, :store_display_thumbnail, :store_item_template, :supply_lot_sizing_method, :supply_replenishment_method, :supply_type, :tax_schedule, :units_type, :vendor
@@ -215,6 +279,7 @@ describe NetSuite::Records::InventoryItem do
215
279
  before do
216
280
  item.cost = 100
217
281
  item.is_inactive = false
282
+ item.location_quantity_available = '1.0' # Search only, excluded
218
283
  end
219
284
  it 'can represent itself as a SOAP record' do
220
285
  record = {
@@ -41,6 +41,99 @@ describe NetSuite::Records::Invoice do
41
41
  end
42
42
  end
43
43
 
44
+ it 'has all the right search_only_fields' do
45
+ [
46
+ :abbrev, :account_type, :acct_corp_card_exp, :actual_production_end_date,
47
+ :actual_production_start_date, :actual_ship_date, :alt_sales_amount,
48
+ :alt_sales_net_amount, :amount, :amount_unbilled,
49
+ :applied_to_foreign_amount, :applied_to_is_fx_variance,
50
+ :applied_to_link_amount, :applied_to_link_type, :applied_to_transaction,
51
+ :applying_foreign_amount, :applying_is_fx_variance, :applying_link_amount,
52
+ :applying_link_type, :applying_transaction, :auth_code,
53
+ :auto_calculate_lag, :avs_street_match, :avs_zip_match, :billable,
54
+ :bill_address, :bill_address1, :bill_address2, :bill_address3,
55
+ :bill_addressee, :bill_attention, :bill_city, :bill_country,
56
+ :bill_country_code, :billed_date, :billing_amount, :billing_transaction,
57
+ :bill_phone, :bill_state, :bill_variance_status, :bill_zip, :bin_number,
58
+ :bin_number_quantity, :bom_quantity, :build_entire_assembly,
59
+ :build_variance, :built, :can_have_stackable_promotions, :catch_up_period,
60
+ :cc_customer_code, :cc_exp_date, :cc_holder_name, :cc_number, :cc_street,
61
+ :cc_zip_code, :cleared, :closed, :close_date, :cogs_amount,
62
+ :commission_effective_date, :commit, :component_yield,
63
+ :confirmation_number, :contribution, :contribution_primary,
64
+ :cost_component_amount, :cost_component_category, :cost_component_item,
65
+ :cost_component_quantity, :cost_component_standard_cost, :cost_estimate,
66
+ :cost_estimate_rate, :cost_estimate_type, :created_by, :credit_amount,
67
+ :csc_match, :custom_gl, :cust_type, :date_created, :days_open,
68
+ :days_overdue, :debit_amount, :defer_rev_rec, :deposit_date,
69
+ :deposit_transaction, :doc_unit, :dr_account, :effective_rate,
70
+ :entity_status, :est_gross_profit_pct, :exclude_from_rate_request,
71
+ :expected_close_date, :expected_receipt_date, :expense_category,
72
+ :expense_date, :firmed, :forecast_type, :fulfilling_transaction,
73
+ :fx_account, :fx_amount, :fx_cost_estimate, :fx_cost_estimate_rate,
74
+ :fx_est_gross_profit, :fx_tran_cost_estimate, :fx_vsoe_allocation,
75
+ :fx_vsoe_amount, :fx_vsoe_price, :gco_availabel_to_charge,
76
+ :gco_available_to_refund, :gco_avs_street_match, :gco_avs_zip_match,
77
+ :gco_buyer_account_age, :gco_buyer_ip, :gco_charge_amount,
78
+ :gco_chargeback_amount, :gco_confirmed_charged_total,
79
+ :gco_confirmed_refunded_total, :gco_creditcard_number, :gco_csc_match,
80
+ :gco_financial_state, :gco_fulfillment_state, :gco_order_id,
81
+ :gco_order_total, :gco_promotion_amount, :gco_promotion_name,
82
+ :gco_refund_amount, :gco_shipping_total, :gco_state_changed_detail,
83
+ :gift_cert, :gross_amount, :include_in_forecast, :incoterm,
84
+ :interco_status, :interco_transaction, :inventory_location,
85
+ :inventory_subsidiary, :in_vsoe_bundle, :is_allocation, :is_backflush,
86
+ :is_gco_chargeback, :is_gco_charge_confirmed, :is_gco_payment_guaranteed,
87
+ :is_gco_refund_confirmed, :is_inside_delivery, :is_inside_pickup,
88
+ :is_intercompany_adjustment, :is_in_transit_payment, :is_multi_ship_to,
89
+ :is_reversal, :is_rev_rec_transaction, :is_scrap, :is_ship_address,
90
+ :is_transfer_price_costing, :is_wip, :item, :item_fulfillment_choice,
91
+ :item_revision, :landed_cost_per_line, :line, :line_sequence_number,
92
+ :line_unique_key, :location_auto_assigned, :main_line, :main_name,
93
+ :manufacturing_routing, :match_bill_to_receipt, :memo_main, :memorized,
94
+ :merchant_account, :multi_subsidiary, :net_amount, :net_amount_no_tax,
95
+ :next_bill_date, :no_auto_assign_location, :non_reimbursable,
96
+ :one_time_total, :options, :order_allocation_strategy, :order_priority,
97
+ :originator, :other_ref_num, :overhead_parent_item,
98
+ :override_installments, :package_count, :paid_amount, :paid_transaction,
99
+ :partner_contribution, :partner_role, :partner_team_member,
100
+ :paying_amount, :paying_transaction, :payment_approved,
101
+ :payment_event_date, :payment_event_hold_reason,
102
+ :payment_event_purchase_card_used, :payment_event_purchase_data_sent,
103
+ :payment_event_result, :payment_event_type, :payment_hold,
104
+ :payment_method, :payment_option, :pay_pal_pending, :pay_pal_status,
105
+ :pay_pal_tran_id, :payroll_batch, :pn_ref_num, :po_rate, :posting,
106
+ :price_level, :print, :probability, :projected_amount, :project_task,
107
+ :purchase_order, :quantity, :quantity_billed, :quantity_committed,
108
+ :quantity_packed, :quantity_picked, :quantity_rev_committed,
109
+ :quantity_ship_recv, :quantity_uom, :rate,
110
+ :realized_gain_posting_transaction, :recur_annually_total,
111
+ :recur_monthly_total, :recur_quarterly_total, :recur_weekly_total,
112
+ :ref_number, :requested_date, :rev_commit_status,
113
+ :rev_committing_transaction, :reversal_date, :reversal_number,
114
+ :rg_account, :rg_amount, :sales_order, :sales_team_member,
115
+ :sales_team_role, :scheduling_method, :serial_number, :serial_number_cost,
116
+ :serial_number_cost_adjustment, :serial_number_quantity, :serial_numbers,
117
+ :ship_address, :ship_address1, :ship_address2, :ship_address3,
118
+ :ship_addressee, :ship_attention, :ship_carrier, :ship_city,
119
+ :ship_complete, :ship_country, :ship_country_code, :ship_group,
120
+ :ship_phone, :shipping_amount, :ship_recv_status_line, :ship_state,
121
+ :ship_to, :ship_zip, :signed_amount, :subscription, :subscription_line,
122
+ :tax_amount, :tax_code, :tax_line, :tax_period, :term_in_months,
123
+ :terms_of_sale, :title, :to_subsidiary, :tran_est_gross_profit,
124
+ :tran_fx_est_gross_profit, :transaction_discount, :transaction_line_type,
125
+ :transaction_number, :transfer_location, :transfer_order_item_line,
126
+ :transfer_order_quantity_committed, :transfer_order_quantity_packed,
127
+ :transfer_order_quantity_picked, :transfer_order_quantity_received,
128
+ :transfer_order_quantity_shipped, :type, :unit, :unit_cost_override,
129
+ :vend_type, :visible_to_customer, :vsoe_allocation, :vsoe_amount,
130
+ :vsoe_deferral, :vsoe_delivered, :vsoe_permit_discount, :vsoe_price,
131
+ :web_site,
132
+ ].each do |field|
133
+ expect(NetSuite::Records::Invoice).to have_search_only_field(field)
134
+ end
135
+ end
136
+
44
137
  it 'has the right record_refs' do
45
138
  [
46
139
  :account, :bill_address_list, :job, :custom_form, :department, :entity, :klass, :posting_period, :ship_address_list, :terms,
@@ -329,6 +422,7 @@ describe NetSuite::Records::Invoice do
329
422
  before do
330
423
  invoice.email = 'something@example.com'
331
424
  invoice.tran_id = '4'
425
+ invoice.close_date = '2021-08-04' # Search only, excluded
332
426
  end
333
427
  it 'can represent itself as a SOAP record' do
334
428
  record = {
@@ -0,0 +1,47 @@
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_2017_2.platform.webservices.netsuite.com">
4
+ <platformMsgs:nsId>WEBSERVICES_4384362_0714202114843454571284681300_c8529d78de5</platformMsgs:nsId>
5
+ </platformMsgs:documentInfo>
6
+ </soapenv:Header>
7
+ <soapenv:Body>
8
+ <getResponse xmlns="urn:messages_2017_2.platform.webservices.netsuite.com">
9
+ <readResponse>
10
+ <platformCore:status xmlns:platformCore="urn:core_2017_2.platform.webservices.netsuite.com" isSuccess="true"/>
11
+ <record xmlns:tranCust="urn:customers_2017_2.transactions.webservices.netsuite.com" internalId="9948394" xsi:type="tranCust:CreditMemo">
12
+ <tranCust:createdDate>2021-07-14T12:45:42.000-07:00</tranCust:createdDate>
13
+ <tranCust:lastModifiedDate>2021-07-14T14:56:35.000-07:00</tranCust:lastModifiedDate>
14
+ <tranCust:customFieldList xmlns:platformCore="urn:core_2017_2.platform.webservices.netsuite.com">
15
+ <platformCore:customField internalId="520" scriptId="custbody_standard_select" xsi:type="platformCore:SelectCustomFieldRef">
16
+ <platformCore:value internalId="2" typeId="142">
17
+ <platformCore:name>Manual</platformCore:name>
18
+ </platformCore:value>
19
+ </platformCore:customField>
20
+ <platformCore:customField internalId="26" scriptId="custbody_date_field" xsi:type="platformCore:DateCustomFieldRef">
21
+ <platformCore:value>2021-07-13T22:00:00.000-07:00</platformCore:value>
22
+ </platformCore:customField>
23
+ <platformCore:customField internalId="1371" scriptId="custbody_string_field" xsi:type="platformCore:StringCustomFieldRef">
24
+ <platformCore:value>a very nice string</platformCore:value>
25
+ </platformCore:customField>
26
+ <platformCore:customField internalId="1593" scriptId="custbody_boolean_field" xsi:type="platformCore:BooleanCustomFieldRef">
27
+ <platformCore:value>false</platformCore:value>
28
+ </platformCore:customField>
29
+ <platformCore:customField internalId="1552" scriptId="custbody_multi_select_field" xsi:type="platformCore:MultiSelectCustomFieldRef">
30
+ <platformCore:value internalId="7623" typeId="164">
31
+ <platformCore:name>selection value</platformCore:name>
32
+ </platformCore:value>
33
+ </platformCore:customField>
34
+ <platformCore:customField internalId="1553" scriptId="custbody_multi_select_with_multiple" xsi:type="platformCore:MultiSelectCustomFieldRef">
35
+ <platformCore:value internalId="7613" typeId="164">
36
+ <platformCore:name>selection value 1</platformCore:name>
37
+ </platformCore:value>
38
+ <platformCore:value internalId="7614" typeId="165">
39
+ <platformCore:name>selection value 2</platformCore:name>
40
+ </platformCore:value>
41
+ </platformCore:customField>
42
+ </tranCust:customFieldList>
43
+ </record>
44
+ </readResponse>
45
+ </getResponse>
46
+ </soapenv:Body>
47
+ </soapenv:Envelope>
@@ -0,0 +1,55 @@
1
+ <soapenv:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <soapenv:Header>
3
+ <platformMsgs:documentInfo xmlns:platformMsgs="urn:messages_2012_1.platform.webservices.netsuite.com">
4
+ <platformMsgs:nsId>WEBSERVICES_3603333_SB1_0320201916835580962038419462_2ce0aa2</platformMsgs:nsId>
5
+ </platformMsgs:documentInfo>
6
+ </soapenv:Header>
7
+ <soapenv:Body>
8
+ <searchResponse xmlns="urn:messages_2012_1.platform.webservices.netsuite.com">
9
+ <platformCore:searchResult xmlns:platformCore="urn:core_2012_1.platform.webservices.netsuite.com">
10
+ <platformCore:status isSuccess="true"/>
11
+ <platformCore:totalRecords>49</platformCore:totalRecords>
12
+ <platformCore:pageSize>1000</platformCore:pageSize>
13
+ <platformCore:totalPages>1</platformCore:totalPages>
14
+ <platformCore:pageIndex>1</platformCore:pageIndex>
15
+ <platformCore:searchId>WEBSERVICES_3603333_SB1_0320201916835580962038419462_2ce0aa2</platformCore:searchId>
16
+ <platformCore:searchRowList>
17
+ <platformCore:searchRow xsi:type="listAcct:ItemSearchRow" xmlns:listAcct="urn:accounting_2012_1.lists.webservices.netsuite.com">
18
+ <listAcct:basic xmlns:platformCommon="urn:common_2012_1.platform.webservices.netsuite.com">
19
+ <platformCommon:department>
20
+ <platformCore:searchValue internalId="113"/>
21
+ <platformCore:customLabel>Business Unit</platformCore:customLabel>
22
+ </platformCommon:department>
23
+ <platformCommon:itemId>
24
+ <platformCore:searchValue>9781945179747</platformCore:searchValue>
25
+ <platformCore:customLabel>SKU</platformCore:customLabel>
26
+ </platformCommon:itemId>
27
+ <platformCommon:locationQuantityAvailable>
28
+ <platformCore:searchValue>3307.0</platformCore:searchValue>
29
+ <platformCore:customLabel>Qty - Available</platformCore:customLabel>
30
+ </platformCommon:locationQuantityAvailable>
31
+ <platformCommon:locationQuantityOnOrder>
32
+ <platformCore:searchValue>40000.0</platformCore:searchValue>
33
+ <platformCore:customLabel>Qty - On Order</platformCore:customLabel>
34
+ </platformCommon:locationQuantityOnOrder>
35
+ <platformCommon:locationReOrderPoint>
36
+ <platformCore:searchValue>2565.0</platformCore:searchValue>
37
+ <platformCore:customLabel>Qty - Reorder Point</platformCore:customLabel>
38
+ </platformCommon:locationReOrderPoint>
39
+ <platformCommon:customFieldList>
40
+ <platformCore:customField xsi:type="platformCore:SearchColumnSelectCustomField" internalId="custitem_productline">
41
+ <platformCore:searchValue typeId="37" internalId="123"/>
42
+ <platformCore:customLabel>Product Line</platformCore:customLabel>
43
+ </platformCore:customField>
44
+ <platformCore:customField xsi:type="platformCore:SearchColumnSelectCustomField" internalId="custitem_inv_reorder_status">
45
+ <platformCore:searchValue typeId="211" internalId="8"/>
46
+ <platformCore:customLabel>Reorder Status</platformCore:customLabel>
47
+ </platformCore:customField>
48
+ </platformCommon:customFieldList>
49
+ </listAcct:basic>
50
+ </platformCore:searchRow>
51
+ </platformCore:searchRowList>
52
+ </platformCore:searchResult>
53
+ </searchResponse>
54
+ </soapenv:Body>
55
+ </soapenv:Envelope>
@@ -16,6 +16,12 @@
16
16
  <platformCore:searchRowList>
17
17
  <platformCore:searchRow xmlns:listRel="urn:relationships_2012_1.lists.webservices.netsuite.com" xsi:type="listRel:CustomerSearchRow">
18
18
  <listRel:basic xmlns:platformCommon="urn:common_2012_1.platform.webservices.netsuite.com">
19
+ <platformCommon:internalId>
20
+ <platformCore:searchValue internalId="123"/>
21
+ </platformCommon:internalId>
22
+ <platformCommon:externalId>
23
+ <platformCore:searchValue externalId="456"/>
24
+ </platformCommon:externalId>
19
25
  <platformCommon:altName>
20
26
  <platformCore:searchValue>A Awesome Name</platformCore:searchValue>
21
27
  </platformCommon:altName>
@@ -37,6 +43,14 @@
37
43
  <platformCommon:phone>
38
44
  <platformCore:searchValue>444-444-4444</platformCore:searchValue>
39
45
  </platformCommon:phone>
46
+ <platformCommon:customFieldList>
47
+ <platformCore:customField internalId="1756" scriptId="custitem_stringfield" xsi:type="platformCore:SearchColumnStringCustomField">
48
+ <platformCore:searchValue>sample string value</platformCore:searchValue>
49
+ </platformCore:customField>
50
+ <platformCore:customField internalId="1713" scriptId="custitem_apcategoryforsales" xsi:type="platformCore:SearchColumnSelectCustomField">
51
+ <platformCore:searchValue internalId="4" typeId="464"/>
52
+ </platformCore:customField>
53
+ </platformCommon:customFieldList>
40
54
  </listRel:basic>
41
55
  <listRel:contactJoin xmlns:platformCommon="urn:common_2012_1.platform.webservices.netsuite.com">
42
56
  <platformCommon:email>
@@ -84,4 +98,4 @@
84
98
  </platformCore:searchResult>
85
99
  </searchResponse>
86
100
  </soapenv:Body>
87
- </soapenv:Envelope>
101
+ </soapenv:Envelope>
@@ -0,0 +1,7 @@
1
+ RSpec::Matchers.define :have_search_only_field do |attribute|
2
+
3
+ match do |model|
4
+ expect(model.search_only_fields.include?(attribute)).to be_truthy
5
+ end
6
+
7
+ end
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.8.7
4
+ version: 0.8.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Moran
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-05-12 00:00:00.000000000 Z
12
+ date: 2021-08-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: savon
@@ -37,14 +37,28 @@ dependencies:
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 3.8.0
40
+ version: 3.10.0
41
41
  type: :development
42
42
  prerelease: false
43
43
  version_requirements: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 3.8.0
47
+ version: 3.10.0
48
+ - !ruby/object:Gem::Dependency
49
+ name: rake
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
48
62
  description: NetSuite SuiteTalk API Wrapper
49
63
  email:
50
64
  - ryan.moran@gmail.com
@@ -53,15 +67,16 @@ executables: []
53
67
  extensions: []
54
68
  extra_rdoc_files: []
55
69
  files:
70
+ - ".github/workflows/main.yml"
56
71
  - ".gitignore"
57
72
  - ".rspec"
58
73
  - ".ruby-version"
59
74
  - ".tool-versions"
60
75
  - Gemfile
76
+ - HISTORY.md
61
77
  - LICENSE
62
78
  - README.md
63
79
  - Rakefile
64
- - circle.yml
65
80
  - lib/netsuite.rb
66
81
  - lib/netsuite/actions/add.rb
67
82
  - lib/netsuite/actions/delete.rb
@@ -138,6 +153,7 @@ files:
138
153
  - lib/netsuite/records/contact_addressbook_list.rb
139
154
  - lib/netsuite/records/contact_list.rb
140
155
  - lib/netsuite/records/contact_role.rb
156
+ - lib/netsuite/records/cost_category.rb
141
157
  - lib/netsuite/records/credit_memo.rb
142
158
  - lib/netsuite/records/credit_memo_apply.rb
143
159
  - lib/netsuite/records/credit_memo_apply_list.rb
@@ -396,6 +412,7 @@ files:
396
412
  - spec/netsuite/records/cash_sale_item_spec.rb
397
413
  - spec/netsuite/records/cash_sale_spec.rb
398
414
  - spec/netsuite/records/classification_spec.rb
415
+ - spec/netsuite/records/cost_category_spec.rb
399
416
  - spec/netsuite/records/credit_memo_apply_list_spec.rb
400
417
  - spec/netsuite/records/credit_memo_apply_spec.rb
401
418
  - spec/netsuite/records/credit_memo_item_list_spec.rb
@@ -529,6 +546,7 @@ files:
529
546
  - spec/support/fixtures/add/add_invoice.xml
530
547
  - spec/support/fixtures/add/add_invoice_error.xml
531
548
  - spec/support/fixtures/add/add_invoice_multiple_errors.xml
549
+ - spec/support/fixtures/custom_fields/multi_select.xml
532
550
  - spec/support/fixtures/delete/delete_customer.xml
533
551
  - spec/support/fixtures/delete_list/delete_list_customers.xml
534
552
  - spec/support/fixtures/delete_list/delete_list_customers_with_errors.xml
@@ -540,6 +558,7 @@ files:
540
558
  - spec/support/fixtures/login/failure_invalid_credentials.xml
541
559
  - spec/support/fixtures/login/success.xml
542
560
  - spec/support/fixtures/search/saved_search_customer.xml
561
+ - spec/support/fixtures/search/saved_search_item.xml
543
562
  - spec/support/fixtures/search/saved_search_joined_custom_customer.xml
544
563
  - spec/support/fixtures/update/update_customer.xml
545
564
  - spec/support/fixtures/update/update_customer_error.xml
@@ -558,6 +577,7 @@ files:
558
577
  - spec/support/read_only_field_matcher.rb
559
578
  - spec/support/record_ref_matcher.rb
560
579
  - spec/support/savon.rb
580
+ - spec/support/search_only_field_matcher.rb
561
581
  homepage: https://github.com/NetSweet/netsuite
562
582
  licenses:
563
583
  - MIT
@@ -617,6 +637,7 @@ test_files:
617
637
  - spec/netsuite/records/cash_sale_item_spec.rb
618
638
  - spec/netsuite/records/cash_sale_spec.rb
619
639
  - spec/netsuite/records/classification_spec.rb
640
+ - spec/netsuite/records/cost_category_spec.rb
620
641
  - spec/netsuite/records/credit_memo_apply_list_spec.rb
621
642
  - spec/netsuite/records/credit_memo_apply_spec.rb
622
643
  - spec/netsuite/records/credit_memo_item_list_spec.rb
@@ -750,6 +771,7 @@ test_files:
750
771
  - spec/support/fixtures/add/add_invoice.xml
751
772
  - spec/support/fixtures/add/add_invoice_error.xml
752
773
  - spec/support/fixtures/add/add_invoice_multiple_errors.xml
774
+ - spec/support/fixtures/custom_fields/multi_select.xml
753
775
  - spec/support/fixtures/delete/delete_customer.xml
754
776
  - spec/support/fixtures/delete_list/delete_list_customers.xml
755
777
  - spec/support/fixtures/delete_list/delete_list_customers_with_errors.xml
@@ -761,6 +783,7 @@ test_files:
761
783
  - spec/support/fixtures/login/failure_invalid_credentials.xml
762
784
  - spec/support/fixtures/login/success.xml
763
785
  - spec/support/fixtures/search/saved_search_customer.xml
786
+ - spec/support/fixtures/search/saved_search_item.xml
764
787
  - spec/support/fixtures/search/saved_search_joined_custom_customer.xml
765
788
  - spec/support/fixtures/update/update_customer.xml
766
789
  - spec/support/fixtures/update/update_customer_error.xml
@@ -779,3 +802,4 @@ test_files:
779
802
  - spec/support/read_only_field_matcher.rb
780
803
  - spec/support/record_ref_matcher.rb
781
804
  - spec/support/savon.rb
805
+ - spec/support/search_only_field_matcher.rb
data/circle.yml DELETED
@@ -1,39 +0,0 @@
1
- version: 2.1
2
-
3
- orbs:
4
- # orbs are basically bundles of pre-written build scripts that work for common cases
5
- # https://github.com/CircleCI-Public/ruby-orb
6
- ruby: circleci/ruby@1.1.2
7
-
8
- jobs:
9
- # skipping build step because Gemfile.lock is not included in the source
10
- # this makes the bundler caching step a noop
11
- test:
12
- parameters:
13
- ruby-version:
14
- type: string
15
- docker:
16
- - image: cimg/ruby:<< parameters.ruby-version >>
17
- steps:
18
- - checkout
19
- - ruby/install-deps:
20
- bundler-version: '2.1.4'
21
- with-cache: false
22
- # without specifying a non-standard path `--deployment` will be used when running bundler
23
- # which causes the bundler to fail
24
- path: './vendor/custom_bundle'
25
- - ruby/rspec-test
26
-
27
- # strangely, there seems to be very little documentation about exactly how martix builds work.
28
- # By defining a param inside your job definition, Circle CI will automatically spawn a job for
29
- # unique param value passed via `matrix`. Neat!
30
- # https://circleci.com/blog/circleci-matrix-jobs/
31
- workflows:
32
- build_and_test:
33
- jobs:
34
- - test:
35
- matrix:
36
- parameters:
37
- # https://github.com/CircleCI-Public/cimg-ruby
38
- # only supports the last three ruby versions
39
- ruby-version: ["2.5", "2.6", "2.7"]