-
-
Notifications
You must be signed in to change notification settings - Fork 270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cld 1835 netsuite null fields #481
Changes from all commits
cf1338c
55bea99
2b61c83
633895a
f4e02c9
247a8db
022a6e6
e4dcb31
3d77d54
656ca69
439e871
3ef6d6c
fe66da5
fe96eff
330ffa6
f9b05f7
7fbe5b2
bc79ecf
0423790
99b040d
3a3c747
811e421
3d0f984
1a2045e
e188a5d
28125a4
e20132a
16371f7
c36ebba
7db5d5d
ce4b0fb
8db4b19
b3f65d1
f61fd97
e27f858
3b941d2
c3145a6
805c7cd
a89db03
ccc3e31
4251842
f73435d
d410bee
489aa8b
cdc3e50
d74d3be
67a0215
a4460fe
4f0cc2c
1776652
1ac62f8
f7fd347
6227de5
d8ff880
bb7f976
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -591,3 +591,23 @@ states.to_array.first[:get_all_response][:get_all_result][:record_list][:record] | |
# About SuiteSync | ||
|
||
[SuiteSync, the Stripe-NetSuite integration](http://suitesync.io) uses this gem and funds the majority of it's development and maintenance. | ||
|
||
|
||
|
||
|
||
# Cloudsnap Additions | ||
|
||
I generally refer to the Netsuite Schema Browser as a source of truth over the actions, records, and fields that you see in this gem. That documentation can be found here: https://www.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2018_1/schema/record/account.html?mode=package | ||
|
||
**One note is to be mindful of the version that you are looking at in the schema browser and the version that you are using when you configure the netsuite credentials. | ||
|
||
### Actions | ||
attach.rb--> lib/netsuite/actions/attach.rb | ||
Based on the Netsuite Schema documentation, we added in the attach action functionality. This is primarily used to attach records considered File Cabinate | ||
|
||
|
||
### Records | ||
If you see the record in the netsuite schema browser, you can easily add it to the records in this gem. Use the fields and sub lists mentioned in the Netsuite schema browser to build out the record file following the same format as the other record files. | ||
|
||
### Other Cloudsnap Changes | ||
We made a few changes to the configuration.rb file. The check credentials method and set attributes methods were added to support the updated way of passing credentials. In the connection method, we also added the ability to set the wsdl and the endpoint level for the Savon client that is configured. This was required to connect to Netsuite api versions 2020+ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After this is merged, I'll go ahead and edit these readme changes a bit to fit within the existing readme structure. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,11 +73,10 @@ def errors | |
module Support | ||
def add(credentials={}) | ||
response = NetSuite::Actions::Add.call([self], credentials) | ||
|
||
@errors = response.errors | ||
|
||
if response.success? | ||
@internal_id = response.body[:@internal_id] | ||
@internal_id = response.body.dig(:@internal_id) unless response.body.class == Nori::StringIOFile | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #495 likely adds some more context around where |
||
true | ||
else | ||
false | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
module NetSuite | ||
module Actions | ||
class Attach | ||
include Support::Requests | ||
|
||
attr_reader :response_hash | ||
|
||
def initialize(object=nil) | ||
@object = object | ||
end | ||
|
||
private | ||
|
||
def request(credentials={}) | ||
NetSuite::Configuration.connection({}, credentials).call(:attach, :message => request_body) | ||
end | ||
|
||
#please note, reference is spelled referece and is documented that way in NetSuite's documentation | ||
# <soap:Body> | ||
# <platformMsgs:attach> | ||
# <platformMsgs:attachReferece xsi:type="platformCore:AttachBasicReference"> | ||
# <platformCore:attachTo internalId="443" type="vendorBill" xsi:type="platformCore:RecordRef"/> | ||
# <platformCore:attachedRecord type="file" internalId="353" xsi:type="platformCore:RecordRef"/> | ||
# </platformMsgs:attachReferece> | ||
# </platformMsgs:attach> | ||
# </soap:Body> | ||
|
||
def request_body | ||
hash = { | ||
'platformMsgs:attachReferece' => { | ||
:content! => @object.to_record, | ||
'@xsi:type' => @object.record_type | ||
} | ||
} | ||
#not crazy about this solution but not sure how else to get the 'xsi:type' var in the hash | ||
hash["platformMsgs:attachReferece"][:content!][:attributes!]["platformCore:attachTo"]["xsi:type"] = "platformCore:RecordRef" | ||
hash["platformMsgs:attachReferece"][:content!][:attributes!]["platformCore:attachedRecord"]["xsi:type"] = "platformCore:RecordRef" | ||
|
||
hash | ||
end | ||
|
||
def success? | ||
@success ||= response_hash[:status][:@is_success] == 'true' | ||
end | ||
|
||
def response_body | ||
@response_body ||= response_hash[:base_ref] | ||
end | ||
|
||
def response_errors | ||
if response_hash[:status] && response_hash[:status][:status_detail] | ||
@response_errors ||= errors | ||
end | ||
end | ||
|
||
def response_hash | ||
@response_hash ||= @response.to_hash[:attach_response][:write_response] | ||
end | ||
|
||
def errors | ||
error_obj = response_hash[:status][:status_detail] | ||
error_obj = [error_obj] if error_obj.class == Hash | ||
error_obj.map do |error| | ||
NetSuite::Error.new(error) | ||
end | ||
end | ||
|
||
|
||
module Support | ||
def attach(credentials={}) | ||
response = NetSuite::Actions::Attach.call([self], credentials) | ||
|
||
@errors = response.errors | ||
|
||
if response.success? | ||
@internal_id = response.body[:@internal_id] | ||
true | ||
else | ||
false | ||
end | ||
end | ||
end | ||
|
||
|
||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,17 @@ def response_hash | |
@response_hash = @response.body[:get_response][:read_response] | ||
end | ||
|
||
def response_errors | ||
if response_hash[:status] && response_hash[:status][:status_detail] | ||
@response_errors ||= errors | ||
end | ||
end | ||
|
||
def errors | ||
error_obj = response_hash.dig(:status,:status_detail) | ||
OpenStruct.new(status: 404, status_detail: error_obj) | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we pull this logic into a separate PR? |
||
|
||
module Support | ||
|
||
def self.included(base) | ||
|
@@ -71,7 +82,7 @@ def get(options = {}, credentials = {}) | |
if response.success? | ||
new(response.body) | ||
else | ||
raise RecordNotFound, "#{self} with OPTIONS=#{options.inspect} could not be found" | ||
raise RecordNotFound, "#{self} with OPTIONS=#{options.inspect} could not be found, NetSuite message: #{response.errors.status_detail[:message]}" | ||
end | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,12 @@ def request_body | |
hash['platformMsgs:record']['@platformMsgs:externalId'] = updated_record.external_id | ||
end | ||
|
||
inner = hash.dig("platformMsgs:record", :content!) | ||
if inner.keys.grep(/(.*):nullFieldList?/).any? | ||
null_field_key = inner.keys.grep(/(.*):nullFieldList?/) | ||
hash["platformMsgs:record"][:content!]["platformCore:nullFieldList"] = hash["platformMsgs:record"][:content!].delete null_field_key[0] | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you explain what's going on here? Could you pull this into a separate PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I needed to extract the |
||
|
||
hash | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,8 @@ def attributes | |
end | ||
|
||
def connection(params={}, credentials={}) | ||
check_credentials(credentials) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why were these changes required in your case? This smells like something specific to your application and not something we'd want to include in the netsuite gem. |
||
|
||
client = Savon.client({ | ||
wsdl: cached_wsdl || wsdl, | ||
read_timeout: read_timeout, | ||
|
@@ -27,10 +29,28 @@ def connection(params={}, credentials={}) | |
log_level: log_level, | ||
log: !silent, # turn off logging entirely if configured | ||
}.update(params)) | ||
client.wsdl.endpoint = client.wsdl.endpoint.to_s.sub('//webservices.netsuite.com/', "//#{wsdl_domain}/") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be fixed by this PR #473 |
||
cache_wsdl(client) | ||
return client | ||
end | ||
|
||
def check_credentials(creds) | ||
if !creds.blank? | ||
set_attributes(creds) | ||
end | ||
end | ||
|
||
def set_attributes(credentials) | ||
account(credentials[:account]) | ||
consumer_key(credentials[:consumer_key]) | ||
consumer_secret(credentials[:consumer_secret]) | ||
token_id(credentials[:token_id]) | ||
token_secret(credentials[:token_secret]) | ||
api_version(credentials[:api_version]) | ||
wsdl_domain(credentials[:wsdl_domain]) | ||
soap_header(credentials[:soap_header]) | ||
end | ||
|
||
def filters(list = nil) | ||
if list | ||
self.filters = list | ||
|
@@ -323,7 +343,7 @@ def read_timeout(timeout = nil) | |
if timeout | ||
self.read_timeout = timeout | ||
else | ||
attributes[:read_timeout] ||= 60 | ||
attributes[:read_timeout] ||= 120 | ||
end | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module NetSuite | ||
module Records | ||
class AttachBasicReference | ||
include Support::Fields | ||
include Support::RecordRefs | ||
include Support::Records | ||
include Support::Actions | ||
include Namespaces::PlatformCore | ||
|
||
actions :attach | ||
|
||
record_refs :attach_to, :attached_record | ||
|
||
def initialize(attributes = {}) | ||
initialize_from_attributes_hash(attributes) | ||
end | ||
|
||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,12 +113,15 @@ def extract_custom_field(custom_field_data) | |
if type == "platformCore:SelectCustomFieldRef" | ||
attrs[:value] = CustomRecordRef.new(custom_field_data[:value]) | ||
elsif type == 'platformCore:MultiSelectCustomFieldRef' | ||
attrs[:value] = custom_field_data[:value].map do |entry| | ||
CustomRecordRef.new(entry) | ||
# if only one value of multiselect is selected it will be a hash, not an array | ||
if attrs[:value].is_a?(Array) | ||
attrs[:value] = custom_field_data[:value].map { |entry| CustomRecordRef.new(entry) } | ||
else | ||
attrs[:value] = CustomRecordRef.new(custom_field_data[:value]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was recently fixed: 3377c97 Can you remove this change from your PR? |
||
end | ||
end | ||
|
||
custom_fields << CustomField.new(attrs) | ||
|
||
end | ||
end | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you need to include this directly?