netsuite 0.8.10 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/dependabot.yml +14 -0
- data/.github/workflows/codeql-analysis.yml +70 -0
- data/.github/workflows/main.yml +7 -4
- data/Gemfile +5 -3
- data/HISTORY.md +56 -2
- data/README.md +94 -38
- data/lib/netsuite/actions/add.rb +7 -2
- data/lib/netsuite/actions/attach_file.rb +87 -0
- data/lib/netsuite/actions/delete.rb +18 -1
- data/lib/netsuite/actions/delete_list.rb +1 -1
- data/lib/netsuite/actions/get.rb +1 -1
- data/lib/netsuite/actions/get_deleted.rb +1 -1
- data/lib/netsuite/actions/get_list.rb +1 -1
- data/lib/netsuite/actions/initialize.rb +2 -2
- data/lib/netsuite/actions/search.rb +20 -7
- data/lib/netsuite/configuration.rb +16 -3
- data/lib/netsuite/records/account.rb +0 -1
- data/lib/netsuite/records/accounting_period.rb +1 -1
- data/lib/netsuite/records/assembly_component.rb +0 -2
- data/lib/netsuite/records/assembly_item.rb +2 -2
- data/lib/netsuite/records/assembly_unbuild.rb +0 -1
- data/lib/netsuite/records/cash_refund.rb +0 -1
- data/lib/netsuite/records/cash_refund_item.rb +1 -1
- data/lib/netsuite/records/cash_sale.rb +1 -2
- data/lib/netsuite/records/contact.rb +0 -1
- data/lib/netsuite/records/credit_memo.rb +1 -1
- data/lib/netsuite/records/currency_rate.rb +0 -1
- data/lib/netsuite/records/custom_record.rb +1 -1
- data/lib/netsuite/records/customer.rb +224 -23
- data/lib/netsuite/records/customer_deposit.rb +0 -1
- data/lib/netsuite/records/customer_payment.rb +0 -1
- data/lib/netsuite/records/customer_refund.rb +1 -2
- data/lib/netsuite/records/deposit.rb +0 -1
- data/lib/netsuite/records/deposit_application.rb +0 -1
- data/lib/netsuite/records/description_item.rb +3 -3
- data/lib/netsuite/records/discount_item.rb +1 -1
- data/lib/netsuite/records/employee.rb +1 -1
- data/lib/netsuite/records/estimate.rb +0 -1
- data/lib/netsuite/records/file.rb +1 -1
- data/lib/netsuite/records/gift_certificate_item.rb +1 -1
- data/lib/netsuite/records/inbound_shipment.rb +0 -1
- data/lib/netsuite/records/inventory_item.rb +237 -38
- data/lib/netsuite/records/inventory_number.rb +0 -1
- data/lib/netsuite/records/invoice.rb +2 -2
- data/lib/netsuite/records/item_availability.rb +46 -0
- data/lib/netsuite/records/item_fulfillment.rb +4 -2
- data/lib/netsuite/records/item_fulfillment_package_fed_ex.rb +28 -0
- data/lib/netsuite/records/item_fulfillment_package_fed_ex_list.rb +32 -0
- data/lib/netsuite/records/item_fulfillment_package_ups.rb +27 -0
- data/lib/netsuite/records/item_fulfillment_package_ups_list.rb +32 -0
- data/lib/netsuite/records/item_fulfillment_package_usps.rb +26 -0
- data/lib/netsuite/records/item_fulfillment_package_usps_list.rb +32 -0
- data/lib/netsuite/records/item_group.rb +3 -3
- data/lib/netsuite/records/item_option_custom_field.rb +52 -0
- data/lib/netsuite/records/item_receipt.rb +0 -1
- data/lib/netsuite/records/item_vendor.rb +10 -1
- data/lib/netsuite/records/job.rb +0 -1
- data/lib/netsuite/records/kit_item.rb +2 -2
- data/lib/netsuite/records/location.rb +0 -1
- data/lib/netsuite/records/lot_numbered_assembly_item.rb +1 -1
- data/lib/netsuite/records/lot_numbered_inventory_item.rb +226 -82
- data/lib/netsuite/records/matrix_option_list.rb +16 -0
- data/lib/netsuite/records/non_inventory_purchase_item.rb +1 -1
- data/lib/netsuite/records/non_inventory_resale_item.rb +157 -21
- data/lib/netsuite/records/non_inventory_sale_item.rb +134 -22
- data/lib/netsuite/records/null_field_list.rb +15 -0
- data/lib/netsuite/records/opportunity.rb +0 -1
- data/lib/netsuite/records/other_charge_sale_item.rb +2 -2
- data/lib/netsuite/records/payment_item.rb +3 -3
- data/lib/netsuite/records/payroll_item.rb +0 -1
- data/lib/netsuite/records/purchase_order.rb +0 -1
- data/lib/netsuite/records/record_ref.rb +1 -1
- data/lib/netsuite/records/return_authorization.rb +1 -0
- data/lib/netsuite/records/sales_order.rb +2 -2
- data/lib/netsuite/records/sales_order_item.rb +2 -1
- data/lib/netsuite/records/serialized_assembly_item.rb +1 -1
- data/lib/netsuite/records/serialized_inventory_item.rb +2 -2
- data/lib/netsuite/records/serialized_inventory_item_location.rb +0 -1
- data/lib/netsuite/records/service_resale_item.rb +125 -21
- data/lib/netsuite/records/service_sale_item.rb +1 -2
- data/lib/netsuite/records/{customer_subscription.rb → subscription.rb} +1 -1
- data/lib/netsuite/records/subscriptions_list.rb +10 -0
- data/lib/netsuite/records/subsidiary.rb +0 -1
- data/lib/netsuite/records/subtotal_item.rb +3 -4
- data/lib/netsuite/records/transfer_order.rb +0 -1
- data/lib/netsuite/records/translation.rb +17 -0
- data/lib/netsuite/records/translation_list.rb +11 -0
- data/lib/netsuite/records/vendor.rb +0 -1
- data/lib/netsuite/records/vendor_bill.rb +0 -1
- data/lib/netsuite/records/work_order.rb +0 -1
- data/lib/netsuite/records/work_order_item.rb +0 -1
- data/lib/netsuite/support/actions.rb +2 -0
- data/lib/netsuite/support/fields.rb +2 -0
- data/lib/netsuite/support/records.rb +22 -5
- data/lib/netsuite/support/sublist.rb +2 -2
- data/lib/netsuite/utilities/strings.rb +15 -0
- data/lib/netsuite/utilities.rb +25 -13
- data/lib/netsuite/version.rb +1 -1
- data/lib/netsuite.rb +15 -3
- data/netsuite.gemspec +5 -2
- data/spec/netsuite/actions/add_spec.rb +39 -1
- data/spec/netsuite/actions/attach_file_spec.rb +59 -0
- data/spec/netsuite/actions/delete_spec.rb +74 -14
- data/spec/netsuite/actions/get_select_value_spec.rb +43 -0
- data/spec/netsuite/actions/search_spec.rb +205 -0
- data/spec/netsuite/configuration_spec.rb +35 -0
- data/spec/netsuite/records/cash_refund_item_spec.rb +1 -1
- data/spec/netsuite/records/credit_memo_spec.rb +14 -0
- data/spec/netsuite/records/customer_spec.rb +287 -20
- data/spec/netsuite/records/inventory_item_spec.rb +239 -22
- data/spec/netsuite/records/invoice_spec.rb +43 -0
- data/spec/netsuite/records/item_availability_spec.rb +59 -0
- data/spec/netsuite/records/item_fulfillment_package_fed_ex_list_spec.rb +27 -0
- data/spec/netsuite/records/item_fulfillment_package_ups_list_spec.rb +27 -0
- data/spec/netsuite/records/item_fulfillment_package_usps_list_spec.rb +27 -0
- data/spec/netsuite/records/item_option_custom_field_spec.rb +27 -0
- data/spec/netsuite/records/item_vendor_list_spec.rb +2 -5
- data/spec/netsuite/records/item_vendor_spec.rb +14 -2
- data/spec/netsuite/records/lot_numbered_inventory_item_spec.rb +247 -0
- data/spec/netsuite/records/matrix_option_list_spec.rb +26 -0
- data/spec/netsuite/records/non_inventory_resale_item_spec.rb +159 -24
- data/spec/netsuite/records/non_inventory_sale_item_spec.rb +135 -22
- data/spec/netsuite/records/null_field_list_spec.rb +30 -0
- data/spec/netsuite/records/return_authorization_spec.rb +62 -0
- data/spec/netsuite/records/sales_order_item_spec.rb +4 -3
- data/spec/netsuite/records/sales_order_spec.rb +46 -0
- data/spec/netsuite/records/service_resale_item_spec.rb +122 -17
- data/spec/netsuite/records/{customer_subscription_spec.rb → subscription_spec.rb} +2 -2
- data/spec/netsuite/records/{customer_subscriptions_list_spec.rb → subscriptions_list_spec.rb} +2 -2
- data/spec/netsuite/records/translation_list_spec.rb +34 -0
- data/spec/netsuite/records/translation_spec.rb +28 -0
- data/spec/netsuite/support/fields_spec.rb +16 -4
- data/spec/netsuite/support/records_spec.rb +33 -7
- data/spec/netsuite/support/search_result_spec.rb +12 -0
- data/spec/netsuite/utilities_spec.rb +10 -2
- data/spec/support/fixtures/add/add_file.xml +20 -0
- data/spec/support/fixtures/add/add_invoice.xml +9 -5
- data/spec/support/fixtures/attach/attach_file_to_sales_order.xml +16 -0
- data/spec/support/fixtures/attach/attach_file_to_sales_order_error.xml +20 -0
- data/spec/support/fixtures/delete/delete_customer_error.xml +21 -0
- data/spec/support/fixtures/delete/delete_customer_multiple_errors.xml +25 -0
- data/spec/support/fixtures/get_item_availability/get_item_availability.xml +46 -0
- data/spec/support/fixtures/get_select_value/empty_result.xml +22 -0
- data/spec/support/fixtures/get_select_value/item_fulfillment_ship_method.xml +43 -0
- data/spec/support/fixtures/search/basic_search_contact.xml +39 -0
- data/spec/support/fixtures/search/single_search_result.xml +46 -0
- metadata +78 -17
- data/lib/netsuite/core_ext/string/lower_camelcase.rb +0 -9
- data/lib/netsuite/records/customer_subscriptions_list.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53e37d7468526bab26109064a50e3d393735e7fbb0758b56867de985e3230170
|
4
|
+
data.tar.gz: 318ed153297d54f2d19c821677e5d8bfffe89d7f688ea31aa324f93e1293f411
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0df38ba22afe3361daace766b033e947f20962ab0ac6d0f336e706b2bbd06bfae091478c856ce9b33ff18f28f07a3e796a774d1a78a1fc6766348538b89afb0a
|
7
|
+
data.tar.gz: c3021d78e3718dd30332accc69de70e3f88df394e33648a49eb995d4d9a5177ad669c5fdb269485a75cd29c13a186c5b863e84a83dfee8eb88ea7c7ba4c9765e
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
github: [NetSweet]
|
@@ -0,0 +1,14 @@
|
|
1
|
+
version: 2
|
2
|
+
updates:
|
3
|
+
|
4
|
+
# Maintain dependencies for GitHub Actions
|
5
|
+
- package-ecosystem: "github-actions"
|
6
|
+
directory: "/"
|
7
|
+
schedule:
|
8
|
+
interval: "daily"
|
9
|
+
|
10
|
+
# Maintain dependencies for rubygems
|
11
|
+
- package-ecosystem: "bundler"
|
12
|
+
directory: "/"
|
13
|
+
schedule:
|
14
|
+
interval: "daily"
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
2
|
+
# to commit it to your repository.
|
3
|
+
#
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
5
|
+
# or to provide custom queries or build logic.
|
6
|
+
#
|
7
|
+
# ******** NOTE ********
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
10
|
+
# supported CodeQL languages.
|
11
|
+
#
|
12
|
+
name: "CodeQL"
|
13
|
+
|
14
|
+
on:
|
15
|
+
push:
|
16
|
+
branches: [ master ]
|
17
|
+
pull_request:
|
18
|
+
# The branches below must be a subset of the branches above
|
19
|
+
branches: [ master ]
|
20
|
+
schedule:
|
21
|
+
- cron: '32 15 * * 6'
|
22
|
+
|
23
|
+
jobs:
|
24
|
+
analyze:
|
25
|
+
name: Analyze
|
26
|
+
runs-on: ubuntu-latest
|
27
|
+
permissions:
|
28
|
+
actions: read
|
29
|
+
contents: read
|
30
|
+
security-events: write
|
31
|
+
|
32
|
+
strategy:
|
33
|
+
fail-fast: false
|
34
|
+
matrix:
|
35
|
+
language: [ 'ruby' ]
|
36
|
+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
37
|
+
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
38
|
+
|
39
|
+
steps:
|
40
|
+
- name: Checkout repository
|
41
|
+
uses: actions/checkout@v3
|
42
|
+
|
43
|
+
# Initializes the CodeQL tools for scanning.
|
44
|
+
- name: Initialize CodeQL
|
45
|
+
uses: github/codeql-action/init@v2
|
46
|
+
with:
|
47
|
+
languages: ${{ matrix.language }}
|
48
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
49
|
+
# By default, queries listed here will override any specified in a config file.
|
50
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
51
|
+
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
52
|
+
|
53
|
+
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
54
|
+
# If this step fails, then you should remove it and run the build manually (see below)
|
55
|
+
- name: Autobuild
|
56
|
+
uses: github/codeql-action/autobuild@v2
|
57
|
+
|
58
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
59
|
+
# 📚 https://git.io/JvXDl
|
60
|
+
|
61
|
+
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
62
|
+
# and modify them (or add more) to build your code if your project
|
63
|
+
# uses a compiled language
|
64
|
+
|
65
|
+
#- run: |
|
66
|
+
# make bootstrap
|
67
|
+
# make release
|
68
|
+
|
69
|
+
- name: Perform CodeQL Analysis
|
70
|
+
uses: github/codeql-action/analyze@v2
|
data/.github/workflows/main.yml
CHANGED
@@ -1,15 +1,18 @@
|
|
1
1
|
name: Ruby
|
2
2
|
|
3
|
-
on: [push,pull_request]
|
3
|
+
on: [push, pull_request]
|
4
4
|
|
5
5
|
jobs:
|
6
6
|
build:
|
7
7
|
runs-on: ubuntu-latest
|
8
8
|
strategy:
|
9
9
|
matrix:
|
10
|
-
ruby-version: [2.7, 2.6, 2.5, 2.4, 2.3, 2.2, 2.1]
|
10
|
+
ruby-version: [3.1, 3.0, 2.7, 2.6, 2.5, 2.4, 2.3, 2.2, 2.1]
|
11
|
+
bundle-tzinfo: [true, false]
|
12
|
+
env:
|
13
|
+
BUNDLE_TZINFO: "${{ matrix.bundle-tzinfo }}"
|
11
14
|
steps:
|
12
|
-
- uses: actions/checkout@
|
15
|
+
- uses: actions/checkout@v3
|
13
16
|
- name: Set up Ruby ${{ matrix.ruby-version }}
|
14
17
|
uses: ruby/setup-ruby@v1
|
15
18
|
with:
|
@@ -17,4 +20,4 @@ jobs:
|
|
17
20
|
- name: Install dependencies
|
18
21
|
run: bundle install
|
19
22
|
- name: Run tests
|
20
|
-
run: bundle exec rake
|
23
|
+
run: bundle exec rake
|
data/Gemfile
CHANGED
@@ -6,6 +6,8 @@ gem 'simplecov', :require => false
|
|
6
6
|
gem 'pry-nav'
|
7
7
|
gem 'pry-rescue'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
#
|
9
|
+
|
10
|
+
if ENV.fetch('BUNDLE_TZINFO', 'false') == 'true'
|
11
|
+
# optional dependency for more accurate timezone conversion
|
12
|
+
gem 'tzinfo', '>= 1.2.5'
|
13
|
+
end
|
data/HISTORY.md
CHANGED
@@ -1,10 +1,64 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
+
|
4
|
+
### Added
|
5
|
+
### Fixed
|
6
|
+
### Breaking Changes
|
7
|
+
|
8
|
+
## 0.9.0
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
* Update `Customer` record fields/record refs for 2021.2. (#535)
|
13
|
+
The following were moved from `fields` to `record_refs`: `buying_reason`, `buying_time_frame`, `campaign_category`, `image`, `opening_balance_account`, `pref_cc_processor`, `representing_subsidiary`, `sales_group`, `sales_readiness`
|
14
|
+
The following were removed as `fields` since their sublist class is not yet implemented: `download_list`, `group_pricing_list`, `item_pricing_list`
|
15
|
+
* Add search-only fields to `Customer` (#535)
|
16
|
+
* Add `attach_file` action to `Customer` records (#544)
|
17
|
+
* Add `update` action to `File` records (#544)
|
18
|
+
* Expose `errors` after calls to `delete` action (#545)
|
19
|
+
* Add `update_list` action where missing on supported item records (#546)
|
20
|
+
* Ignore `after_submit_failed` status details (>= 2018.2) when collating errors in add action (#550)
|
21
|
+
* Add `NullFieldList` to `SalesOrder` (#552)
|
22
|
+
* Add thread safety to NetSuite configuration and utilities (#549)
|
23
|
+
|
24
|
+
### Breaking Changes
|
25
|
+
* Rename `CustomerSubscriptionsList` to `SubscriptionsList` and `CustomerSubscription` to `Subscription` to match NetSuite naming (#535)
|
26
|
+
|
27
|
+
## 0.8.12
|
28
|
+
|
29
|
+
### Added
|
30
|
+
|
31
|
+
* Add NullFieldList record (to credit memos and invoices) (#529)
|
32
|
+
* Add `get_deleted` action to item records (#530)
|
33
|
+
* Add `get_deleted` action to Employee records (#531)
|
34
|
+
* Remove monkey patched `lower_camelcase` method on String (#533)
|
35
|
+
|
36
|
+
## 0.8.11
|
37
|
+
|
3
38
|
### Added
|
4
|
-
|
39
|
+
|
40
|
+
* Update ServiceResaleItem record fields/record refs for 2021.2. `item_options_list`, `presentation_item_list`, `site_category_list`, `translations_list` were all removed as fields as the are not simple fields, they require special classes. (#500)
|
41
|
+
* Dependabot to CI
|
42
|
+
* CI run for Ruby 3.0 & 3.1
|
43
|
+
* Add CI run for an environment with and without `tzinfo` installed
|
44
|
+
* Update NonInventorySaleItem record fields/record refs for 2021.2. `item_options_list`, `presentation_item_list`, `product_feed_list`, `site_category_list`, `translations_list` were all removed as fields as the are not simple fields, they require special classes. (#503)
|
45
|
+
* Implement MatrixOptionList#to_record (#504)
|
46
|
+
* Update ItemVendor record fields/record refs for 2021.1. `vendor` is now a record_ref instead of a field. (#505)
|
47
|
+
* Update InventoryItem record fields/record refs for 2021.2. `member_list` was removed as a field as it doesn't belong to InventoryItem. (#506)
|
48
|
+
* Update LotNumberedInventoryItem record fields/record refs for 2021.2. (#507)
|
49
|
+
* Update NonInventoryResaleItem record fields/record refs for 2021.2. `item_options_list`, `presentation_item_list`, `product_feed_list`, `site_category_list`, `translations_list` were all removed as fields as the are not simple fields, they require special classes. (#508)
|
50
|
+
* Add `attach_file` action for Invoice and SalesOrder. (#509)
|
51
|
+
* Add ItemOptionCustomField recrd (#512)
|
52
|
+
* Add Ship Address to Return Authorization (#525)
|
53
|
+
* Support translations records (#516)
|
5
54
|
|
6
55
|
### Fixed
|
7
|
-
|
56
|
+
|
57
|
+
* Fix "undefined method `[]` for #<Nori::StringIOFile>" when adding File (#495)
|
58
|
+
* Moved definition of `search_joins` attribute from records to search action. The attribute was removed for AssemblyComponent, SerializedInventoryItemLocation, and WorkOrderItem as they don't offer the search action. (#511)
|
59
|
+
* Consider externalId in search criteria when using RecordRef as value (#517)
|
60
|
+
* Retry http client error subclasses
|
61
|
+
* Add upsert list action for cash sales (#523)
|
8
62
|
|
9
63
|
## 0.8.10
|
10
64
|
|
data/README.md
CHANGED
@@ -1,34 +1,16 @@
|
|
1
|
-
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
2
|
-
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
3
|
-
**Table of Contents**
|
4
|
-
|
5
|
-
- [NetSuite SuiteTalk API Ruby Gem](#netsuite-suitetalk-api-ruby-gem)
|
6
|
-
- [Help & Support](#help--support)
|
7
|
-
- [Testing](#testing)
|
8
|
-
- [Installation](#installation)
|
9
|
-
- [Configuration](#configuration)
|
10
|
-
- [Token based Authentication](#token-based-authentication)
|
11
|
-
- [Usage](#usage)
|
12
|
-
- [CRUD Operations](#crud-operations)
|
13
|
-
- [Custom Records & Fields](#custom-records--fields)
|
14
|
-
- [Searching](#searching)
|
15
|
-
- [Non-standard Operations](#non-standard-operations)
|
16
|
-
|
17
|
-
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
18
|
-
|
19
1
|
[![Ruby](https://github.com/NetSweet/netsuite/actions/workflows/main.yml/badge.svg)](https://github.com/NetSweet/netsuite/actions/workflows/main.yml)
|
20
2
|
[![Slack Status](https://opensuite-slackin.herokuapp.com/badge.svg)](http://opensuite-slackin.herokuapp.com)
|
21
3
|
[![Gem Version](https://badge.fury.io/rb/netsuite.svg)](http://badge.fury.io/rb/netsuite)
|
22
4
|
|
23
5
|
# NetSuite SuiteTalk API Ruby Gem
|
24
6
|
|
25
|
-
* This gem will act as a wrapper around the NetSuite SuiteTalk
|
7
|
+
* This gem will act as a wrapper around the NetSuite SuiteTalk Web Services API.
|
26
8
|
* The gem does not cover the entire API, only the subset contributors have used so far. Please submit a PR for any functionality that's missing!
|
27
9
|
* NetSuite is a complex system. There's a lot to learn and sparse resources available to learn from. Here's a list of [NetSuite Development Resources](https://github.com/NetSweet/netsuite/wiki/NetSuite-Development-Resources).
|
28
10
|
|
29
11
|
# Help & Support
|
30
12
|
|
31
|
-
Join the [
|
13
|
+
Join the [Slack channel](http://opensuite-slackin.herokuapp.com) for help with any NetSuite issues. Please do not post usage questions as issues in GitHub.
|
32
14
|
|
33
15
|
There is some additional helpful resources for NetSuite development [listed here](https://dashboard.suitesync.io/docs/resources#netsuite).
|
34
16
|
|
@@ -54,20 +36,20 @@ gem 'netsuite'
|
|
54
36
|
|
55
37
|
If you'd like more accurate time conversion support, include the `tzinfo` gem.
|
56
38
|
|
57
|
-
This gem is built for
|
39
|
+
This gem is built for Ruby 2.6.x+, but should work on older versions down to 1.9. There's a [1-8-stable](https://github.com/NetSweet/netsuite/tree/1-8-stable) branch for Ruby 1.8.x support.
|
58
40
|
|
59
41
|
## Configuration
|
60
42
|
|
61
|
-
The most important thing you'll need is your NetSuite account ID. Not sure how to find your account
|
43
|
+
The most important thing you'll need is your NetSuite account ID. Not sure how to find your account ID? [Here's a guide.](http://mikebian.co/find-netsuite-web-services-account-number/)
|
62
44
|
|
63
45
|
How you connect to NetSuite has changed a lot over the years and differs between API versions. For instance:
|
64
46
|
|
65
47
|
* Older API versions (~2015) allowed authentication via username and password
|
66
|
-
*
|
48
|
+
* Newer API versions (> 2016) still allowed for username and password authentication, but required an application ID
|
67
49
|
* "OAuth", which requires four separate keys to be manually generated, was supported sometime after 2015
|
68
50
|
* API versions greater than 2018_2 require `endpoint` to be set directly ([more info](https://github.com/NetSweet/netsuite/pull/473))
|
69
51
|
|
70
|
-
Here's an example connection configuration. You don't want to actually use username + password config;
|
52
|
+
Here's an example connection configuration. You don't want to actually use username + password config; Token Based Authentication is detailed [in a separate section](#token-based-authentication):
|
71
53
|
|
72
54
|
```ruby
|
73
55
|
NetSuite.configure do
|
@@ -78,13 +60,13 @@ NetSuite.configure do
|
|
78
60
|
api_version '2018_2'
|
79
61
|
|
80
62
|
# password-based login information
|
81
|
-
# in most cases you should use
|
63
|
+
# in most cases you should use Token Based Authentication instead
|
82
64
|
email 'email@example.com'
|
83
65
|
password 'password'
|
84
66
|
role 10
|
85
67
|
|
86
|
-
# recent API versions require
|
87
|
-
# use `NetSuite::Utilities.data_center_url('TSTDRV1576318')` to retrieve
|
68
|
+
# recent API versions require an account-specific endpoint to be set
|
69
|
+
# use `NetSuite::Utilities.data_center_url('TSTDRV1576318')` to retrieve WSDL URL
|
88
70
|
# you'll want to do this in a background process and strip the protocol out of the return string
|
89
71
|
wsdl_domain 'tstdrv1576318.suitetalk.api.netsuite.com'
|
90
72
|
|
@@ -105,17 +87,17 @@ NetSuite.configure do
|
|
105
87
|
|
106
88
|
api_version '2018_2'
|
107
89
|
|
108
|
-
# optionally specify full
|
90
|
+
# optionally specify full WSDL URL (to switch to sandbox, for example)
|
109
91
|
wsdl "https://webservices.sandbox.netsuite.com/wsdl/v#{api_version}_0/netsuite.wsdl"
|
110
92
|
|
111
|
-
# if your datacenter is being switched, you'll have to manually set your
|
93
|
+
# if your datacenter is being switched, you'll have to manually set your WSDL location
|
112
94
|
wsdl "https://webservices.na2.netsuite.com/wsdl/v#{api_version}_0/netsuite.wsdl"
|
113
95
|
|
114
96
|
# or specify the wsdl_domain if you want to specify the datacenter and let the configuration
|
115
97
|
# construct the full wsdl location - e.g. "https://#{wsdl_domain}/wsdl/v#{api_version}_0/netsuite.wsdl"
|
116
98
|
wsdl_domain "webservices.na2.netsuite.com"
|
117
99
|
|
118
|
-
# often the
|
100
|
+
# often the NetSuite servers will hang which would cause a timeout exception to be raised
|
119
101
|
# if you don't mind waiting (e.g. processing NS via a background worker), increasing the timeout should fix the issue
|
120
102
|
read_timeout 100_000
|
121
103
|
|
@@ -129,7 +111,7 @@ NetSuite.configure do
|
|
129
111
|
# log_level :debug
|
130
112
|
|
131
113
|
# password-based login information
|
132
|
-
# in most cases you should use
|
114
|
+
# in most cases you should use Token Based Authentication instead
|
133
115
|
email 'email@domain.com'
|
134
116
|
password 'password'
|
135
117
|
account '12345'
|
@@ -142,7 +124,7 @@ NetSuite.configure do
|
|
142
124
|
end
|
143
125
|
```
|
144
126
|
|
145
|
-
If are using username + password authentication (which you shouldn't be!) *and* you'd like to use
|
127
|
+
If you are using username + password authentication (which you shouldn't be!) *and* you'd like to use an API endpoint greater than 2015_1, you'll need to specify an application ID:
|
146
128
|
|
147
129
|
```ruby
|
148
130
|
NetSuite::Configuration.soap_header = {
|
@@ -152,9 +134,9 @@ NetSuite::Configuration.soap_header = {
|
|
152
134
|
}
|
153
135
|
```
|
154
136
|
|
155
|
-
### Token
|
137
|
+
### Token Based Authentication
|
156
138
|
|
157
|
-
OAuth credentials are supported and the recommended authentication approach. [Learn more about how to set up
|
139
|
+
OAuth credentials are supported and the recommended authentication approach. [Learn more about how to set up Token Based Authentication here](http://mikebian.co/using-netsuites-token-based-authentication-with-suitetalk/).
|
158
140
|
|
159
141
|
```ruby
|
160
142
|
NetSuite.configure do
|
@@ -170,7 +152,7 @@ NetSuite.configure do
|
|
170
152
|
# oauth does not work with API versions less than 2015_2
|
171
153
|
api_version '2016_2'
|
172
154
|
|
173
|
-
# the endpoint indicated in the > 2018_2
|
155
|
+
# the endpoint indicated in the > 2018_2 WSDL is invalid
|
174
156
|
# you must set the endpoint directly
|
175
157
|
# https://github.com/NetSweet/netsuite/pull/473
|
176
158
|
endpoint "https://#{wsdl_domain}/services/NetSuitePort_#{api_version}"
|
@@ -238,6 +220,19 @@ options = NetSuite::Records::BaseRefList.get_select_value(
|
|
238
220
|
options.base_refs.map(&:name)
|
239
221
|
```
|
240
222
|
|
223
|
+
## Uploading/Attaching Files
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
file = NetSuite::Records::File.new(
|
227
|
+
content: Base64.encode64(File.read('/path/to/file')),
|
228
|
+
name: 'Invoice.pdf',
|
229
|
+
)
|
230
|
+
file.add
|
231
|
+
|
232
|
+
invoice = NetSuite::Records::Invoice.get(internal_id: 1)
|
233
|
+
invoice.attach_file(NetSuite::Records::RecordRef.new(internal_id: file.internal_id))
|
234
|
+
```
|
235
|
+
|
241
236
|
## Custom Records & Fields
|
242
237
|
|
243
238
|
```ruby
|
@@ -289,6 +284,20 @@ NetSuite::Records::BaseRefList.get_select_value(
|
|
289
284
|
)
|
290
285
|
```
|
291
286
|
|
287
|
+
## Null Fields
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
# updating a field on a record to be null
|
291
|
+
invoice = NetSuite::Records::Invoice.get(12345)
|
292
|
+
invoice.update(null_field_list: 'shipMethod')
|
293
|
+
|
294
|
+
# updating multiple fields on a record to be null
|
295
|
+
invoice.update(null_field_list: ['shipAddressList', 'shipMethod'])
|
296
|
+
|
297
|
+
# updating a custom fields on a record to be null, using custom field ID
|
298
|
+
invoice.update(null_field_list: 'custBody9')
|
299
|
+
```
|
300
|
+
|
292
301
|
## Searching
|
293
302
|
|
294
303
|
```ruby
|
@@ -305,7 +314,7 @@ search = NetSuite::Records::Customer.search({
|
|
305
314
|
|
306
315
|
`open https://system.netsuite.com/app/common/entity/custjob.nl?id=#{search.results.first.internal_id}`
|
307
316
|
|
308
|
-
# find the
|
317
|
+
# find the Avalara tax item. Some records don't support search.
|
309
318
|
all_sales_taxes = NetSuite::Utilities.backoff { NetSuite::Records::SalesTaxItem.get_all }
|
310
319
|
ns_tax_code = all_sales_taxes.detect { |st| st.item_id == 'AVATAX' }
|
311
320
|
|
@@ -416,13 +425,13 @@ NetSuite::Records::SalesOrder.search({
|
|
416
425
|
]
|
417
426
|
},
|
418
427
|
|
419
|
-
# the column syntax is a WIP. This will change in the future
|
428
|
+
# the column syntax is a WIP. This will change in the future.
|
420
429
|
columns: {
|
421
430
|
'tranSales:basic' => [
|
422
431
|
'platformCommon:internalId/' => {},
|
423
432
|
'platformCommon:email/' => {},
|
424
433
|
'platformCommon:tranDate/' => {},
|
425
|
-
# If you include columns that are only part of the *SearchRowBasic (ie. TransactionSearchRowBasic),
|
434
|
+
# If you include columns that are only part of the *SearchRowBasic (ie. TransactionSearchRowBasic),
|
426
435
|
# they'll be readable on the resulting record just like regular fields (my_record.close_date).
|
427
436
|
'platformCommon:closeDate/' => {}
|
428
437
|
],
|
@@ -598,6 +607,53 @@ deposit.payment = 20
|
|
598
607
|
deposit.add
|
599
608
|
```
|
600
609
|
|
610
|
+
## Getting Deleted Records
|
611
|
+
|
612
|
+
```ruby
|
613
|
+
response = NetSuite::Records::LotNumberedInventoryItem.get_deleted({
|
614
|
+
criteria: [
|
615
|
+
{
|
616
|
+
# If you don't specify a type criteria, you'll get all deleted records,
|
617
|
+
# regardless of the type of record you called this on.
|
618
|
+
field: 'type',
|
619
|
+
operator: 'anyOf',
|
620
|
+
value: 'lotNumberedInventoryItem',
|
621
|
+
}
|
622
|
+
],
|
623
|
+
})
|
624
|
+
|
625
|
+
Array(response.body.fetch(:deleted_record_list)).first
|
626
|
+
# => {
|
627
|
+
# :deleted_date => Wed, 16 Feb 2022 17:43:45 -0800,
|
628
|
+
# :record => {
|
629
|
+
# :name => "My Item",
|
630
|
+
# :@internal_id => "12485",
|
631
|
+
# :@type => "lotNumberedInventoryItem",
|
632
|
+
# :"@xsi:type" => "platformCore:RecordRef"
|
633
|
+
# }
|
634
|
+
# }
|
635
|
+
|
636
|
+
# deleted_record_list could be:
|
637
|
+
# nil - No records matching criteria were deleted
|
638
|
+
# Hash - A single record matching criteria was deleted
|
639
|
+
# Array - Multiple records matching criteria were deleted
|
640
|
+
|
641
|
+
# Simple pagination
|
642
|
+
page = 1
|
643
|
+
begin
|
644
|
+
response = NetSuite::Records::LotNumberedInventoryItem.get_deleted({
|
645
|
+
criteria: [
|
646
|
+
# your criteria
|
647
|
+
],
|
648
|
+
page: page,
|
649
|
+
})
|
650
|
+
|
651
|
+
# Do your thing with response.body.fetch(:deleted_record_list)
|
652
|
+
|
653
|
+
page += 1
|
654
|
+
end until page > Integer(response.fetch(:total_pages))
|
655
|
+
```
|
656
|
+
|
601
657
|
## Non-standard Operations
|
602
658
|
|
603
659
|
```ruby
|
data/lib/netsuite/actions/add.rb
CHANGED
@@ -49,7 +49,11 @@ module NetSuite
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def response_body
|
52
|
-
@response_body ||= response_hash[:base_ref]
|
52
|
+
@response_body ||= if response_hash[:base_ref].is_a?(Nori::StringIOFile)
|
53
|
+
{ :@internal_id => Nokogiri::XML(@response.to_s).remove_namespaces!.at_xpath('//baseRef')[:internalId] }
|
54
|
+
else
|
55
|
+
response_hash[:base_ref]
|
56
|
+
end
|
53
57
|
end
|
54
58
|
|
55
59
|
def response_errors
|
@@ -66,8 +70,9 @@ module NetSuite
|
|
66
70
|
error_obj = response_hash[:status][:status_detail]
|
67
71
|
error_obj = [error_obj] if error_obj.class == Hash
|
68
72
|
error_obj.map do |error|
|
73
|
+
next if error.keys == [:after_submit_failed]
|
69
74
|
NetSuite::Error.new(error)
|
70
|
-
end
|
75
|
+
end.compact
|
71
76
|
end
|
72
77
|
|
73
78
|
module Support
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module NetSuite
|
2
|
+
module Actions
|
3
|
+
class AttachFile
|
4
|
+
include Support::Requests
|
5
|
+
|
6
|
+
def initialize(object, file)
|
7
|
+
@object = object
|
8
|
+
@file = file
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def request(credentials = {})
|
14
|
+
NetSuite::Configuration.connection({}, credentials).call(:attach, :message => request_body)
|
15
|
+
end
|
16
|
+
|
17
|
+
# <soap:Body>
|
18
|
+
# <platformMsgs:attach>
|
19
|
+
# <platformCore:attachReference xsi:type="platformCore:AttachContactReference">
|
20
|
+
# <platformCore::attachTo internalId="176" type="customer" xsi:type="platformCore::RecordRef">
|
21
|
+
# </platformCore:attachTo>
|
22
|
+
# <platformCore:attachRecord internalId="1467" type="file" xsi:type="platformCore:RecordRef"/>
|
23
|
+
# </platformCore:attachReference>
|
24
|
+
# </platformMsgs:attach>
|
25
|
+
# </soap:Body>
|
26
|
+
|
27
|
+
def request_body
|
28
|
+
{
|
29
|
+
'platformCore:attachReference' => {
|
30
|
+
'@xsi:type' => 'platformCore:AttachBasicReference',
|
31
|
+
'platformCore:attachTo' => {
|
32
|
+
'@internalId' => @object.internal_id,
|
33
|
+
'@type' => @object.netsuite_type,
|
34
|
+
'@xsi:type' => 'platformCore:RecordRef'
|
35
|
+
},
|
36
|
+
'platformCore:attachedRecord' => {
|
37
|
+
'@internalId' => @file.internal_id,
|
38
|
+
'@type' => 'file',
|
39
|
+
'@xsi:type' => 'platformCore:RecordRef'
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def success?
|
46
|
+
@success ||= response_hash[:status][:@is_success] == 'true'
|
47
|
+
end
|
48
|
+
|
49
|
+
def response_body
|
50
|
+
@response_body ||= response_hash[:base_ref]
|
51
|
+
end
|
52
|
+
|
53
|
+
def response_errors
|
54
|
+
if response_hash[:status] && response_hash[:status][:status_detail]
|
55
|
+
@response_errors ||= errors
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def response_hash
|
60
|
+
@response_hash ||= @response.to_hash[:attach_response][:write_response]
|
61
|
+
end
|
62
|
+
|
63
|
+
def errors
|
64
|
+
error_obj = response_hash[:status][:status_detail]
|
65
|
+
error_obj = [error_obj] if error_obj.class == Hash
|
66
|
+
error_obj.map do |error|
|
67
|
+
NetSuite::Error.new(error)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
module Support
|
72
|
+
def attach_file(file, credentials = {})
|
73
|
+
response = NetSuite::Actions::AttachFile.call([self, file], credentials)
|
74
|
+
|
75
|
+
@errors = response.errors
|
76
|
+
|
77
|
+
if response.success?
|
78
|
+
@internal_id = response.body[:@internal_id]
|
79
|
+
true
|
80
|
+
else
|
81
|
+
false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -21,7 +21,7 @@ module NetSuite
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def soap_type
|
24
|
-
@object
|
24
|
+
NetSuite::Support::Records.netsuite_type(@object)
|
25
25
|
end
|
26
26
|
|
27
27
|
# <soap:Body>
|
@@ -65,6 +65,20 @@ module NetSuite
|
|
65
65
|
@response_body ||= response_hash[:base_ref]
|
66
66
|
end
|
67
67
|
|
68
|
+
def response_errors
|
69
|
+
if response_hash[:status] && response_hash[:status][:status_detail]
|
70
|
+
@response_errors ||= errors
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def errors
|
75
|
+
error_obj = response_hash[:status][:status_detail]
|
76
|
+
error_obj = [error_obj] if error_obj.class == Hash
|
77
|
+
error_obj.map do |error|
|
78
|
+
NetSuite::Error.new(error)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
68
82
|
module Support
|
69
83
|
def delete(options = {}, credentials={})
|
70
84
|
response = if options.empty?
|
@@ -72,6 +86,9 @@ module NetSuite
|
|
72
86
|
else
|
73
87
|
NetSuite::Actions::Delete.call([self, options], credentials)
|
74
88
|
end
|
89
|
+
|
90
|
+
@errors = response.errors
|
91
|
+
|
75
92
|
response.success?
|
76
93
|
end
|
77
94
|
end
|
data/lib/netsuite/actions/get.rb
CHANGED
@@ -28,12 +28,12 @@ module NetSuite
|
|
28
28
|
def request_body
|
29
29
|
{
|
30
30
|
'platformMsgs:initializeRecord' => {
|
31
|
-
'platformCore:type' => @klass
|
31
|
+
'platformCore:type' => NetSuite::Support::Records.netsuite_type(@klass),
|
32
32
|
'platformCore:reference' => {},
|
33
33
|
:attributes! => {
|
34
34
|
'platformCore:reference' => {
|
35
35
|
'internalId' => @object.internal_id,
|
36
|
-
:type => @object
|
36
|
+
:type => NetSuite::Support::Records.netsuite_type(@object)
|
37
37
|
}
|
38
38
|
}
|
39
39
|
}
|