netsuite 0.8.7 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,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"]