Commit dc8aa5b675b8f9d5a3aa9f60101185bf0ad9f9fc

Authored by Joe Weakley
1 parent bbf1c61a

Rubocop corrections

.rubocop.yml 0 → 100644
  1 +AllCops:
  2 + Exclude:
  3 + - Gemfile*
  4 + - syspro-ruby.gemspec
1 #!/usr/bin/env ruby 1 #!/usr/bin/env ruby
  2 +# frozen_string_literal: true
2 3
3 -require "bundler/setup"  
4 -require "syspro"  
5 -require "pry" 4 +require 'bundler/setup'
  5 +require 'syspro'
  6 +require 'pry'
6 7
7 Pry.start 8 Pry.start
1 -require "cgi"  
2 -require "faraday"  
3 -require "json"  
4 -require "logger"  
5 -require "openssl"  
6 -  
7 -require "syspro/api_resource"  
8 -require "syspro/errors"  
9 -require "syspro/get_logon_profile"  
10 -require "syspro/get_version"  
11 -require "syspro/logoff"  
12 -require "syspro/logon"  
13 -require "syspro/syspro_client"  
14 -require "syspro/singleton_api_resource"  
15 -require "syspro/syspro_object"  
16 -require "syspro/syspro_response"  
17 -require "syspro/util"  
18 -require "syspro/version"  
19 -  
20 -require "syspro/api_operations/request"  
21 -require "syspro/api_operations/query"  
22 -  
23 -require "syspro/business_objects/combrw"  
24 -require "syspro/business_objects/comfch"  
25 -require "syspro/business_objects/comfnd"  
26 -  
27 -require "syspro/business_objects/parsers/combrw_parser"  
28 -require "syspro/business_objects/parsers/comfch_parser"  
29 -require "syspro/business_objects/parsers/comfnd_parser"  
30 - 1 +# frozen_string_literal: true
  2 +
  3 +require 'cgi'
  4 +require 'faraday'
  5 +require 'json'
  6 +require 'logger'
  7 +require 'openssl'
  8 +
  9 +require 'syspro/api_resource'
  10 +require 'syspro/errors'
  11 +require 'syspro/get_logon_profile'
  12 +require 'syspro/get_version'
  13 +require 'syspro/logoff'
  14 +require 'syspro/logon'
  15 +require 'syspro/syspro_client'
  16 +require 'syspro/singleton_api_resource'
  17 +require 'syspro/syspro_object'
  18 +require 'syspro/syspro_response'
  19 +require 'syspro/util'
  20 +require 'syspro/version'
  21 +
  22 +require 'syspro/api_operations/request'
  23 +require 'syspro/api_operations/query'
  24 +
  25 +require 'syspro/business_objects/combrw'
  26 +require 'syspro/business_objects/comfch'
  27 +require 'syspro/business_objects/comfnd'
  28 +
  29 +require 'syspro/business_objects/parsers/combrw_parser'
  30 +require 'syspro/business_objects/parsers/comfch_parser'
  31 +require 'syspro/business_objects/parsers/comfnd_parser'
  32 +
  33 +# Main Module
31 module Syspro 34 module Syspro
32 - @api_base = "http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest" 35 + @api_base = 'http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest'
33 36
34 @open_timeout = 30 37 @open_timeout = 30
35 @read_timeout = 80 38 @read_timeout = 80
@@ -69,14 +72,13 @@ module Syspro @@ -69,14 +72,13 @@ module Syspro
69 72
70 def self.log_level=(val) 73 def self.log_level=(val)
71 # Backwards compatibility for values that we briefly allowed 74 # Backwards compatibility for values that we briefly allowed
72 - if val == "debug"  
73 - val = LEVEL_DEBUG  
74 - elsif val == "info"  
75 - val = LEVEL_INFO  
76 - end  
77 - 75 + val = LEVEL_DEBUG if val == 'debug'
  76 + val = LEVEL_INFO if val == 'info'
78 if !val.nil? && ![LEVEL_DEBUG, LEVEL_ERROR, LEVEL_INFO].include?(val) 77 if !val.nil? && ![LEVEL_DEBUG, LEVEL_ERROR, LEVEL_INFO].include?(val)
79 - raise ArgumentError, "log_level should only be set to `nil`, `debug` or `info`" 78 + raise(
  79 + ArgumentError,
  80 + 'log_level should only be set to `nil`, `debug` or `info`'
  81 + )
80 end 82 end
81 @log_level = val 83 @log_level = val
82 end 84 end
@@ -104,5 +106,5 @@ module Syspro @@ -104,5 +106,5 @@ module Syspro
104 @max_network_retries = val.to_i 106 @max_network_retries = val.to_i
105 end 107 end
106 108
107 - Syspro.log_level = ENV["SYSPRO_LOG"] unless ENV["SYSPRO_LOG"].nil? 109 + Syspro.log_level = ENV['SYSPRO_LOG'] unless ENV['SYSPRO_LOG'].nil?
108 end 110 end
lib/syspro/api_operations/query.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 module ApiOperations 4 module ApiOperations
3 module Query 5 module Query
@@ -5,26 +7,25 @@ module Syspro @@ -5,26 +7,25 @@ module Syspro
5 include Request 7 include Request
6 8
7 def browse(params) 9 def browse(params)
8 - request(:get, "/Query/Browse", params) 10 + request(:get, '/Query/Browse', params)
9 end 11 end
10 12
11 def fetch(params) 13 def fetch(params)
12 - request(:get, "/Query/Fetch", params) 14 + request(:get, '/Query/Fetch', params)
13 end 15 end
14 16
15 def query(params) 17 def query(params)
16 - request(:get, "/Query/Query", params) 18 + request(:get, '/Query/Query', params)
17 end 19 end
18 20
19 - def find  
20 - end 21 + def find; end
21 22
22 private 23 private
23 24
24 def warn_on_opts_in_params(params) 25 def warn_on_opts_in_params(params)
25 Util::OPTS_USER_SPECIFIED.each do |opt| 26 Util::OPTS_USER_SPECIFIED.each do |opt|
26 if params.key?(opt) 27 if params.key?(opt)
27 - $stderr.puts("WARNING: #{opt} should be in opts instead of params.") 28 + warn("WARNING: #{opt} should be in opts instead of params.")
28 end 29 end
29 end 30 end
30 end 31 end
@@ -43,4 +44,3 @@ module Syspro @@ -43,4 +44,3 @@ module Syspro
43 end 44 end
44 end 45 end
45 end 46 end
46 -  
lib/syspro/api_operations/request.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 module ApiOperations 4 module ApiOperations
3 module Request 5 module Request
@@ -28,7 +30,7 @@ module Syspro @@ -28,7 +30,7 @@ module Syspro
28 def warn_on_opts_in_params(params) 30 def warn_on_opts_in_params(params)
29 Util::OPTS_USER_SPECIFIED.each do |opt| 31 Util::OPTS_USER_SPECIFIED.each do |opt|
30 if params.key?(opt) 32 if params.key?(opt)
31 - $stderr.puts("WARNING: #{opt} should be in opts instead of params.") 33 + warn("WARNING: #{opt} should be in opts instead of params.")
32 end 34 end
33 end 35 end
34 end 36 end
@@ -40,4 +42,3 @@ module Syspro @@ -40,4 +42,3 @@ module Syspro
40 end 42 end
41 end 43 end
42 end 44 end
43 -  
lib/syspro/api_resource.rb
1 -require "syspro/syspro_object"  
2 -require "syspro/api_operations/request" 1 +# frozen_string_literal: true
  2 +
  3 +require 'syspro/syspro_object'
  4 +require 'syspro/api_operations/request'
3 5
4 module Syspro 6 module Syspro
5 class ApiResource < SysproObject 7 class ApiResource < SysproObject
6 include Syspro::ApiOperations::Request 8 include Syspro::ApiOperations::Request
7 9
8 def self.class_name 10 def self.class_name
9 - name.split("::")[-1] 11 + name.split('::')[-1]
10 end 12 end
11 13
12 def self.resource_url 14 def self.resource_url
13 if self == ApiResource 15 if self == ApiResource
14 - raise NotImplementedError, "APIResource is an abstract class. You should perform actions on its subclasses (Charge, Customer, etc.)" 16 + raise NotImplementedError, 'APIResource is an abstract class. You should perform actions on its subclasses (Charge, Customer, etc.)'
15 end 17 end
16 "/#{CGI.escape(class_name.downcase)}" 18 "/#{CGI.escape(class_name.downcase)}"
17 end 19 end
lib/syspro/business_objects/combrw.rb
1 -require "syspro/business_objects/parsers/combrw_parser"  
2 -require "erb" 1 +# frozen_string_literal: true
  2 +
  3 +require 'syspro/business_objects/parsers/combrw_parser'
  4 +require 'erb'
3 5
4 module Syspro 6 module Syspro
5 module BusinessObjects 7 module BusinessObjects
@@ -12,13 +14,19 @@ module Syspro @@ -12,13 +14,19 @@ module Syspro
12 14
13 def call(user_id) 15 def call(user_id)
14 xml_in = template.result(binding) 16 xml_in = template.result(binding)
15 - params = { "UserId" => user_id, "XmlIn" => xml_in } 17 + params = { 'UserId' => user_id, 'XmlIn' => xml_in }
16 resp = ComBrw.browse(params) 18 resp = ComBrw.browse(params)
17 parse_response(resp) 19 parse_response(resp)
18 end 20 end
19 21
20 def template 22 def template
21 - ERB.new File.read(File.expand_path("schemas/combrw.xml.erb", File.dirname(__FILE__))), nil, "%" 23 + ERB.new(
  24 + File.read(
  25 + File.expand_path('schemas/combrw.xml.erb', File.dirname(__FILE__))
  26 + ),
  27 + nil,
  28 + '%'
  29 + )
22 end 30 end
23 31
24 def parse_response(resp) 32 def parse_response(resp)
@@ -29,11 +37,8 @@ module Syspro @@ -29,11 +37,8 @@ module Syspro
29 37
30 def handle_errors(resp) 38 def handle_errors(resp)
31 body = resp[0].http_body 39 body = resp[0].http_body
32 - if body.match(/^(ERROR)/)  
33 - raise SysproError, body  
34 - end 40 + raise SysproError, body if body =~ /^(ERROR)/
35 end 41 end
36 end 42 end
37 end 43 end
38 end 44 end
39 -  
lib/syspro/business_objects/comfch.rb
1 -require "syspro/business_objects/parsers/comfch_parser"  
2 -require "erb" 1 +# frozen_string_literal: true
  2 +
  3 +require 'syspro/business_objects/parsers/comfch_parser'
  4 +require 'erb'
3 5
4 module Syspro 6 module Syspro
5 module BusinessObjects 7 module BusinessObjects
@@ -12,13 +14,19 @@ module Syspro @@ -12,13 +14,19 @@ module Syspro
12 14
13 def call(user_id) 15 def call(user_id)
14 xml_in = template.result(binding) 16 xml_in = template.result(binding)
15 - params = { "UserId" => user_id, "XmlIn" => xml_in } 17 + params = { 'UserId' => user_id, 'XmlIn' => xml_in }
16 resp = ComFch.fetch(params) 18 resp = ComFch.fetch(params)
17 parse_response(resp) 19 parse_response(resp)
18 end 20 end
19 21
20 def template 22 def template
21 - ERB.new File.read(File.expand_path("schemas/comfch.xml.erb", File.dirname(__FILE__))), nil, "%" 23 + ERB.new(
  24 + File.read(
  25 + File.expand_path('schemas/comfch.xml.erb', File.dirname(__FILE__))
  26 + ),
  27 + nil,
  28 + '%'
  29 + )
22 end 30 end
23 31
24 def parse_response(resp) 32 def parse_response(resp)
@@ -29,11 +37,8 @@ module Syspro @@ -29,11 +37,8 @@ module Syspro
29 37
30 def handle_errors(resp) 38 def handle_errors(resp)
31 body = resp[0].http_body 39 body = resp[0].http_body
32 - if body.match(/^(ERROR)/)  
33 - raise SysproError, body  
34 - end 40 + raise SysproError, body if body =~ /^(ERROR)/
35 end 41 end
36 end 42 end
37 end 43 end
38 end 44 end
39 -  
lib/syspro/business_objects/comfnd.rb
1 -require "syspro/business_objects/parsers/comfnd_parser"  
2 -require "erb" 1 +# frozen_string_literal: true
  2 +
  3 +require 'syspro/business_objects/parsers/comfnd_parser'
  4 +require 'erb'
3 5
4 module Syspro 6 module Syspro
5 module BusinessObjects 7 module BusinessObjects
@@ -12,14 +14,14 @@ module Syspro @@ -12,14 +14,14 @@ module Syspro
12 14
13 def call(user_id) 15 def call(user_id)
14 xml_in = template.result(binding) 16 xml_in = template.result(binding)
15 - business_object = "COMFND"  
16 - params = { "UserId" => user_id, "BusinessObject" => business_object, "XmlIn" => xml_in } 17 + business_object = 'COMFND'
  18 + params = { 'UserId' => user_id, 'BusinessObject' => business_object, 'XmlIn' => xml_in }
17 resp = ComFnd.query(params) 19 resp = ComFnd.query(params)
18 parse_response(resp) 20 parse_response(resp)
19 end 21 end
20 22
21 def template 23 def template
22 - ERB.new File.read(File.expand_path("schemas/comfnd.xml.erb", File.dirname(__FILE__))), nil, "%" 24 + ERB.new File.read(File.expand_path('schemas/comfnd.xml.erb', File.dirname(__FILE__))), nil, '%'
23 end 25 end
24 26
25 def parse_response(resp) 27 def parse_response(resp)
@@ -30,11 +32,8 @@ module Syspro @@ -30,11 +32,8 @@ module Syspro
30 32
31 def handle_errors(resp) 33 def handle_errors(resp)
32 body = resp[0].http_body 34 body = resp[0].http_body
33 - if body.match(/^(ERROR)/)  
34 - raise SysproError, body  
35 - end 35 + raise SysproError, body if body =~ /^(ERROR)/
36 end 36 end
37 end 37 end
38 end 38 end
39 end 39 end
40 -  
lib/syspro/business_objects/parsers/combrw_parser.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 module BusinessObjects 4 module BusinessObjects
3 module Parsers 5 module Parsers
@@ -9,41 +11,37 @@ module Syspro @@ -9,41 +11,37 @@ module Syspro
9 end 11 end
10 12
11 def parse 13 def parse
12 - next_prev_key = doc.first_element_child.xpath("NextPrevKey")  
13 - next_prev_key_obj = next_prev_key.children.map { |el|  
14 - if el.name == "text"  
15 - next  
16 - end 14 + next_prev_key = doc.first_element_child.xpath('NextPrevKey')
  15 + next_prev_key_obj = next_prev_key.children.map do |el|
  16 + next if el.name == 'text'
17 { 17 {
18 name: el.name, 18 name: el.name,
19 text: el.text 19 text: el.text
20 } 20 }
21 - }.compact 21 + end.compact
22 22
23 - header_details = doc.first_element_child.xpath("HeaderDetails")  
24 - header_details_obj = header_details.children.map { |el|  
25 - if el.name == "text"  
26 - next  
27 - end 23 + header_details = doc.first_element_child.xpath('HeaderDetails')
  24 + header_details_obj = header_details.children.map do |el|
  25 + next if el.name == 'text'
28 { 26 {
29 name: el.name, 27 name: el.name,
30 text: el.text 28 text: el.text
31 } 29 }
32 - }.compact 30 + end.compact
33 31
34 rows = doc.first_element_child.xpath('Row') 32 rows = doc.first_element_child.xpath('Row')
35 - rows_obj = rows.map { |el|  
36 - el.elements.map { |inner| 33 + rows_obj = rows.flat_map do |el|
  34 + el.elements.map do |inner|
37 { 35 {
38 name: inner.name, 36 name: inner.name,
39 value: inner.xpath('Value').text, 37 value: inner.xpath('Value').text,
40 data_type: inner.xpath('DataType').text 38 data_type: inner.xpath('DataType').text
41 } 39 }
42 - }  
43 - }.flatten(1).compact 40 + end
  41 + end.compact
44 42
45 BrowseObject.new( 43 BrowseObject.new(
46 - doc.first_element_child.xpath("Title").text, 44 + doc.first_element_child.xpath('Title').text,
47 rows_obj, 45 rows_obj,
48 next_prev_key_obj, 46 next_prev_key_obj,
49 header_details_obj 47 header_details_obj
@@ -55,4 +53,3 @@ module Syspro @@ -55,4 +53,3 @@ module Syspro
55 end 53 end
56 end 54 end
57 end 55 end
58 -  
lib/syspro/business_objects/parsers/comfch_parser.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 module BusinessObjects 4 module BusinessObjects
3 module Parsers 5 module Parsers
@@ -11,9 +13,9 @@ module Syspro @@ -11,9 +13,9 @@ module Syspro
11 def parse 13 def parse
12 table_name = doc.first_element_child.name 14 table_name = doc.first_element_child.name
13 columns = doc.first_element_child.elements 15 columns = doc.first_element_child.elements
14 - columns_obj = columns.map { |el| 16 + columns_obj = columns.map do |el|
15 { name: el.name, value: el.children.text } 17 { name: el.name, value: el.children.text }
16 - }.compact 18 + end.compact
17 19
18 FetchObject.new( 20 FetchObject.new(
19 table_name, 21 table_name,
@@ -26,4 +28,3 @@ module Syspro @@ -26,4 +28,3 @@ module Syspro
26 end 28 end
27 end 29 end
28 end 30 end
29 -  
lib/syspro/business_objects/parsers/comfnd_parser.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 module BusinessObjects 4 module BusinessObjects
3 module Parsers 5 module Parsers
@@ -9,26 +11,24 @@ module Syspro @@ -9,26 +11,24 @@ module Syspro
9 end 11 end
10 12
11 def parse 13 def parse
12 - header_details = doc.first_element_child.xpath("HeaderDetails")  
13 - header_details_obj = header_details.children.map { |el|  
14 - if el.name == "text"  
15 - next  
16 - end 14 + header_details = doc.first_element_child.xpath('HeaderDetails')
  15 + header_details_obj = header_details.children.map do |el|
  16 + next if el.name == 'text'
17 { 17 {
18 name: el.name, 18 name: el.name,
19 text: el.text 19 text: el.text
20 } 20 }
21 - }.compact 21 + end.compact
22 22
23 rows = doc.first_element_child.xpath('Row') 23 rows = doc.first_element_child.xpath('Row')
24 - rows_obj = rows.map { |el|  
25 - el.elements.map { |inner| 24 + rows_obj = rows.flat_map do |el|
  25 + el.elements.map do |inner|
26 { 26 {
27 name: inner.name, 27 name: inner.name,
28 value: inner.children.text 28 value: inner.children.text
29 } 29 }
30 - }  
31 - }.flatten(1).compact 30 + end
  31 + end.compact
32 32
33 QueryObject.new( 33 QueryObject.new(
34 header_details_obj, 34 header_details_obj,
@@ -42,4 +42,3 @@ module Syspro @@ -42,4 +42,3 @@ module Syspro
42 end 42 end
43 end 43 end
44 end 44 end
45 -  
lib/syspro/errors.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 class SysproError < StandardError 4 class SysproError < StandardError
3 attr_reader :message, :response, :code, :http_body, :http_headers, 5 attr_reader :message, :response, :code, :http_body, :http_headers,
@@ -16,8 +18,8 @@ module Syspro @@ -16,8 +18,8 @@ module Syspro
16 end 18 end
17 19
18 def to_s 20 def to_s
19 - status_string = @http_status.nil? ? "" : "(Status #{@http_status}) "  
20 - id_string = @request_id.nil? ? "" : "(Request #{@request_id}) " 21 + status_string = @http_status.nil? ? '' : "(Status #{@http_status}) "
  22 + id_string = @request_id.nil? ? '' : "(Request #{@request_id}) "
21 "#{status_string}#{id_string}#{@message}" 23 "#{status_string}#{id_string}#{@message}"
22 end 24 end
23 end 25 end
@@ -30,5 +32,4 @@ module Syspro @@ -30,5 +32,4 @@ module Syspro
30 32
31 class ApiError < SysproError 33 class ApiError < SysproError
32 end 34 end
33 -  
34 end 35 end
lib/syspro/get_logon_profile.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 class GetLogonProfile < ApiResource 4 class GetLogonProfile < ApiResource
3 def self.get_logon_profile(user_id) 5 def self.get_logon_profile(user_id)
4 - params = { "UserId" => user_id }  
5 - resp = self.request(:get, resource_url, params) 6 + params = { 'UserId' => user_id }
  7 + resp = request(:get, resource_url, params)
6 parse_response(resp[0]) 8 parse_response(resp[0])
7 end 9 end
8 10
9 def resource_url 11 def resource_url
10 - "/GetLogonProfile" 12 + '/GetLogonProfile'
11 end 13 end
12 14
13 - def self.parse_response(resp) 15 + def self.parse_response(resp) # rubocop:disable Metrics/MethodLength
14 doc = resp.data 16 doc = resp.data
15 17
16 UserProfile.new( 18 UserProfile.new(
17 - doc.xpath("//CompanyName").text,  
18 - doc.xpath("//OperatorCode").text,  
19 - doc.xpath("//OperatorGroup").text,  
20 - doc.xpath("//OperatorEmailAddress").text,  
21 - doc.xpath("//OperatorLocation").text,  
22 - doc.xpath("//OperatorLanguageCode").text,  
23 - doc.xpath("//SystemLanguage").text,  
24 - doc.xpath("//AccountingDate").text,  
25 - doc.xpath("//CompanyDate").text,  
26 - doc.xpath("//DefaultArBranch").text,  
27 - doc.xpath("//DefaultApBranch").text,  
28 - doc.xpath("//DefaultBank").text,  
29 - doc.xpath("//DefaultWarehouse").text,  
30 - doc.xpath("//DefaultCustomer").text,  
31 - doc.xpath("//SystemSiteId").text,  
32 - doc.xpath("//SystemNationalityCode").text,  
33 - doc.xpath("//LocalCurrencyCode").text,  
34 - doc.xpath("//CurrencyDescription").text,  
35 - doc.xpath("//DefaultRequisitionUser").text,  
36 - doc.xpath("//XMLToHTMLTransform").text,  
37 - doc.xpath("//CssStyle").text,  
38 - doc.xpath("//CssSuffix").text,  
39 - doc.xpath("//DecimalFormat").text,  
40 - doc.xpath("//DateFormat").text,  
41 - doc.xpath("//FunctionalRole").text,  
42 - doc.xpath("//DatabaseType").text,  
43 - doc.xpath("//SysproVersion").text,  
44 - doc.xpath("//EnetVersion").text,  
45 - doc.xpath("//SysproServerBitWidth").text, 19 + doc.xpath('//CompanyName').text,
  20 + doc.xpath('//OperatorCode').text,
  21 + doc.xpath('//OperatorGroup').text,
  22 + doc.xpath('//OperatorEmailAddress').text,
  23 + doc.xpath('//OperatorLocation').text,
  24 + doc.xpath('//OperatorLanguageCode').text,
  25 + doc.xpath('//SystemLanguage').text,
  26 + doc.xpath('//AccountingDate').text,
  27 + doc.xpath('//CompanyDate').text,
  28 + doc.xpath('//DefaultArBranch').text,
  29 + doc.xpath('//DefaultApBranch').text,
  30 + doc.xpath('//DefaultBank').text,
  31 + doc.xpath('//DefaultWarehouse').text,
  32 + doc.xpath('//DefaultCustomer').text,
  33 + doc.xpath('//SystemSiteId').text,
  34 + doc.xpath('//SystemNationalityCode').text,
  35 + doc.xpath('//LocalCurrencyCode').text,
  36 + doc.xpath('//CurrencyDescription').text,
  37 + doc.xpath('//DefaultRequisitionUser').text,
  38 + doc.xpath('//XMLToHTMLTransform').text,
  39 + doc.xpath('//CssStyle').text,
  40 + doc.xpath('//CssSuffix').text,
  41 + doc.xpath('//DecimalFormat').text,
  42 + doc.xpath('//DateFormat').text,
  43 + doc.xpath('//FunctionalRole').text,
  44 + doc.xpath('//DatabaseType').text,
  45 + doc.xpath('//SysproVersion').text,
  46 + doc.xpath('//EnetVersion').text,
  47 + doc.xpath('//SysproServerBitWidth').text
46 ) 48 )
47 end 49 end
48 private_class_method :parse_response 50 private_class_method :parse_response
49 51
50 - UserProfile = Struct.new(:company_name, :operator_code, :operator_group, :operator_email_address,  
51 - :operator_location, :operator_language_code, :system_language, :accounting_date,  
52 - :company_date, :default_ar_branch, :default_ap_branch, :default_bank, :default_warehouse,  
53 - :default_customer, :system_site_id, :system_nationality_code, :local_currency_code,  
54 - :currency_description, :default_requisition_user, :xml_to_html_transform, :css_style,  
55 - :css_suffix, :decimal_format, :date_format, :functional_role, :database_type, :syspro_version,  
56 - :enet_version, :syspro_server_bit_width) 52 + UserProfile = Struct.new(
  53 + :company_name,
  54 + :operator_code,
  55 + :operator_group,
  56 + :operator_email_address,
  57 + :operator_location,
  58 + :operator_language_code,
  59 + :system_language,
  60 + :accounting_date,
  61 + :company_date,
  62 + :default_ar_branch,
  63 + :default_ap_branch,
  64 + :default_bank,
  65 + :default_warehouse,
  66 + :default_customer,
  67 + :system_site_id,
  68 + :system_nationality_code,
  69 + :local_currency_code,
  70 + :currency_description,
  71 + :default_requisition_user,
  72 + :xml_to_html_transform,
  73 + :css_style,
  74 + :css_suffix,
  75 + :decimal_format,
  76 + :date_format,
  77 + :functional_role,
  78 + :database_type,
  79 + :syspro_version,
  80 + :enet_version,
  81 + :syspro_server_bit_width
  82 + )
57 end 83 end
58 end 84 end
59 -  
lib/syspro/get_version.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 class GetVersion < ApiResource 4 class GetVersion < ApiResource
3 def self.get_version 5 def self.get_version
4 - resp = self.request(:get, resource_url) 6 + resp = request(:get, resource_url)
5 VersionObject.new(resp[0].http_body) 7 VersionObject.new(resp[0].http_body)
6 end 8 end
7 9
8 def resource_url 10 def resource_url
9 - "/GetVersion" 11 + '/GetVersion'
10 end 12 end
11 13
12 VersionObject = Struct.new(:version) 14 VersionObject = Struct.new(:version)
13 end 15 end
14 end 16 end
15 -  
lib/syspro/logoff.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 class Logoff < ApiResource 4 class Logoff < ApiResource
3 def self.logoff(user_id) 5 def self.logoff(user_id)
4 - params = { "UserId" => user_id }  
5 - resp = self.request(:get, resource_url, params) 6 + params = { 'UserId' => user_id }
  7 + resp = request(:get, resource_url, params)
6 8
7 - if resp[0].http_body == "0" 9 + if resp[0].http_body == '0'
8 true 10 true
9 else 11 else
10 resp[0].http_body 12 resp[0].http_body
@@ -12,7 +14,7 @@ module Syspro @@ -12,7 +14,7 @@ module Syspro
12 end 14 end
13 15
14 def resource_url 16 def resource_url
15 - "/Logoff" 17 + '/Logoff'
16 end 18 end
17 end 19 end
18 end 20 end
lib/syspro/logon.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 class Logon < ApiResource 4 class Logon < ApiResource
3 def self.logon(username, password, company_id, company_password = nil) 5 def self.logon(username, password, company_id, company_password = nil)
4 params = { 6 params = {
5 - "Operator" => username,  
6 - "OperatorPassword" => password,  
7 - "CompanyId" => company_id,  
8 - "CompanyPassword" => company_password 7 + 'Operator' => username,
  8 + 'OperatorPassword' => password,
  9 + 'CompanyId' => company_id,
  10 + 'CompanyPassword' => company_password
9 } 11 }
10 - resp = self.request(:get, resource_url, params) 12 + resp = request(:get, resource_url, params)
11 UserIdObject.new(resp[0].http_body) 13 UserIdObject.new(resp[0].http_body)
12 end 14 end
13 15
14 def resource_url 16 def resource_url
15 - "/Logon" 17 + '/Logon'
16 end 18 end
17 19
18 UserIdObject = Struct.new(:guid) 20 UserIdObject = Struct.new(:guid)
19 end 21 end
20 end 22 end
21 -  
lib/syspro/singleton_api_resource.rb
1 -require_relative "api_resource" 1 +# frozen_string_literal: true
  2 +
  3 +require_relative 'api_resource'
2 4
3 module Syspro 5 module Syspro
4 class SingletonAPIResource < ApiResource 6 class SingletonAPIResource < ApiResource
5 def self.resource_url 7 def self.resource_url
6 if self == SingletonAPIResource 8 if self == SingletonAPIResource
7 - raise NotImplementedError, "SingletonAPIResource is an abstract class. You should perform actions on its subclasses (Customer, etc.)" 9 + raise(
  10 + NotImplementedError,
  11 + 'SingletonAPIResource is an abstract class. You should perform actions on its subclasses (Customer, etc.)' # rubocop:disable Metrics/LineLength
  12 + )
8 end 13 end
9 "/#{CGI.escape(class_name.downcase)}" 14 "/#{CGI.escape(class_name.downcase)}"
10 end 15 end
lib/syspro/syspro_client.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 - class SysproClient 4 + # This class is the main syspro client
  5 + class SysproClient # rubocop:disable Metrics/ClassLength
3 attr_accessor :conn, :api_base 6 attr_accessor :conn, :api_base
4 7
5 @verify_ssl_warned = false 8 @verify_ssl_warned = false
@@ -13,7 +16,7 @@ module Syspro @@ -13,7 +16,7 @@ module Syspro
13 Syspro::Logon.logon(username, password, company_id, company_password) 16 Syspro::Logon.logon(username, password, company_id, company_password)
14 end 17 end
15 18
16 - def get_syspro_version 19 + def get_syspro_version # rubocop:disable Naming/AccessorMethodName
17 Syspro::GetVersion.get_version 20 Syspro::GetVersion.get_version
18 end 21 end
19 22
@@ -22,13 +25,13 @@ module Syspro @@ -22,13 +25,13 @@ module Syspro
22 end 25 end
23 26
24 def self.default_client 27 def self.default_client
25 - Thread.current[:syspro_client_default_client] ||= SysproClient.new(default_conn) 28 + Thread.current[:syspro_client_default_client] ||= SysproClient.new(default_conn) # rubocop:disable Metrics/LineLength
26 end 29 end
27 30
28 # A default Faraday connection to be used when one isn't configured. This 31 # A default Faraday connection to be used when one isn't configured. This
29 # object should never be mutated, and instead instantiating your own 32 # object should never be mutated, and instead instantiating your own
30 # connection and wrapping it in a SysproClient object should be preferred. 33 # connection and wrapping it in a SysproClient object should be preferred.
31 - def self.default_conn 34 + def self.default_conn # rubocop:disable Metrics/MethodLength
32 # We're going to keep connections around so that we can take advantage 35 # We're going to keep connections around so that we can take advantage
33 # of connection re-use, so make sure that we have a separate connection 36 # of connection re-use, so make sure that we have a separate connection
34 # object per thread. 37 # object per thread.
@@ -40,20 +43,21 @@ module Syspro @@ -40,20 +43,21 @@ module Syspro
40 c.adapter Faraday.default_adapter 43 c.adapter Faraday.default_adapter
41 end 44 end
42 45
43 - # For now, we're not verifying SSL certificates. The warning will appear.  
44 - #if Syspro.verify_ssl_certs  
45 - #conn.ssl.verify = true  
46 - #conn.ssl.cert_store = Syspro.ca_store  
47 - #else 46 + # For now, we're not verifying SSL certificates.
  47 + # The warning will appear.
  48 + # if Syspro.verify_ssl_certs
  49 + # conn.ssl.verify = true
  50 + # conn.ssl.cert_store = Syspro.ca_store
  51 + # else
48 conn.ssl.verify = false 52 conn.ssl.verify = false
49 53
50 unless @verify_ssl_warned 54 unless @verify_ssl_warned
51 @verify_ssl_warned = true 55 @verify_ssl_warned = true
52 - $stderr.puts("WARNING: Running without SSL cert verification. " \  
53 - "You should never do this in production. " \ 56 + warn('WARNING: Running without SSL cert verification. ' \
  57 + 'You should never do this in production. ' \
54 "Execute 'Syspro.verify_ssl_certs = true' to enable verification.") 58 "Execute 'Syspro.verify_ssl_certs = true' to enable verification.")
55 end 59 end
56 - #end 60 + # end
57 61
58 conn 62 conn
59 end 63 end
@@ -77,9 +81,9 @@ module Syspro @@ -77,9 +81,9 @@ module Syspro
77 end 81 end
78 end 82 end
79 83
80 - def execute_request(method, path, user_id: nil, api_base: nil, headers: {}, params: {}) 84 + def execute_request(method, path, user_id: nil, api_base: nil, headers: {}, params: {}) # rubocop:disable Metrics/LineLength, Metrics/MethodLength
81 api_base ||= Syspro.api_base 85 api_base ||= Syspro.api_base
82 - user_id ||= "" 86 + user_id ||= ''
83 87
84 params = Util.objects_to_ids(params) 88 params = Util.objects_to_ids(params)
85 url = api_url(path, api_base) 89 url = api_url(path, api_base)
@@ -91,7 +95,7 @@ module Syspro @@ -91,7 +95,7 @@ module Syspro
91 when :get, :head, :delete 95 when :get, :head, :delete
92 query_params = params 96 query_params = params
93 else 97 else
94 - body = if headers[:content_type] && headers[:content_type] == "multipart/form-data" 98 + body = if headers[:content_type] && headers[:content_type] == 'multipart/form-data' # rubocop:disable Metrics/LineLength
95 params 99 params
96 else 100 else
97 Util.encode_parameters(params) 101 Util.encode_parameters(params)
@@ -108,7 +112,7 @@ module Syspro @@ -108,7 +112,7 @@ module Syspro
108 context.method = method 112 context.method = method
109 context.path = path 113 context.path = path
110 context.user_id = user_id 114 context.user_id = user_id
111 - context.query_params = query_params ? Util.encode_parameters(query_params) : nil 115 + context.query_params = query_params ? Util.encode_parameters(query_params) : nil # rubocop:disable Metrics/LineLength
112 116
113 http_resp = execute_request_with_rescues(api_base, context) do 117 http_resp = execute_request_with_rescues(api_base, context) do
114 conn.run_request(method, url, body, headers) do |req| 118 conn.run_request(method, url, body, headers) do |req|
@@ -135,22 +139,22 @@ module Syspro @@ -135,22 +139,22 @@ module Syspro
135 http_status: status, http_body: body) 139 http_status: status, http_body: body)
136 end 140 end
137 141
138 - def api_url(url = "", api_base = nil) 142 + def api_url(url = '', api_base = nil)
139 (api_base || Syspro.api_base) + url 143 (api_base || Syspro.api_base) + url
140 end 144 end
141 145
142 - def request_headers(method) 146 + def request_headers(_method)
143 user_agent = "Syspro/7 RubyBindings/#{Syspro::VERSION}" 147 user_agent = "Syspro/7 RubyBindings/#{Syspro::VERSION}"
144 148
145 headers = { 149 headers = {
146 - "User-Agent" => user_agent,  
147 - "Content-Type" => "application/x-www-form-urlencoded", 150 + 'User-Agent' => user_agent,
  151 + 'Content-Type' => 'application/x-www-form-urlencoded'
148 } 152 }
149 153
150 headers 154 headers
151 end 155 end
152 156
153 - def execute_request_with_rescues(api_base, context) 157 + def execute_request_with_rescues(api_base, context) # rubocop:disable Metrics/LineLength, Metrics/MethodLength
154 num_retries = 0 158 num_retries = 0
155 begin 159 begin
156 request_start = Time.now 160 request_start = Time.now
@@ -159,8 +163,8 @@ module Syspro @@ -159,8 +163,8 @@ module Syspro
159 log_response(context, request_start, resp.status, resp.body) 163 log_response(context, request_start, resp.status, resp.body)
160 164
161 # We rescue all exceptions from a request so that we have an easy spot to 165 # We rescue all exceptions from a request so that we have an easy spot to
162 - # implement our retry logic across the board. We'll re-raise if it's a type  
163 - # of exception that we didn't expect to handle. 166 + # implement our retry logic across the board. We'll re-raise if it's a
  167 + # type of exception that we didn't expect to handle.
164 rescue StandardError => e 168 rescue StandardError => e
165 if e.respond_to?(:response) && e.response 169 if e.respond_to?(:response) && e.response
166 log_response(context, request_start, 170 log_response(context, request_start,
@@ -193,36 +197,36 @@ module Syspro @@ -193,36 +197,36 @@ module Syspro
193 resp 197 resp
194 end 198 end
195 199
196 - def handle_network_error(e, context, num_retries, api_base = nil)  
197 - Util.log_error("Syspro network error", 200 + def handle_network_error(e, context, num_retries, api_base = nil) # rubocop:disable Metrics/LineLength, Metrics/MethodLength, Naming/UncommunicativeMethodParamName
  201 + Util.log_error('Syspro network error',
198 error_message: e.message, 202 error_message: e.message,
199 request_id: context.request_id) 203 request_id: context.request_id)
200 204
201 case e 205 case e
202 when Faraday::ConnectionFailed 206 when Faraday::ConnectionFailed
203 - message = "Unexpected error communicating when trying to connect to Syspro." 207 + message = 'Unexpected error communicating when trying to connect to Syspro.' # rubocop:disable Metrics/LineLength
204 208
205 when Faraday::SSLError 209 when Faraday::SSLError
206 - message = "Could not establish a secure connection to Syspro." 210 + message = 'Could not establish a secure connection to Syspro.'
207 211
208 when Faraday::TimeoutError 212 when Faraday::TimeoutError
209 api_base ||= Syspro.api_base 213 api_base ||= Syspro.api_base
210 message = "Could not connect to Syspro (#{api_base}). " \ 214 message = "Could not connect to Syspro (#{api_base}). " \
211 - "Please check your internet connection and try again. " \  
212 - "If this problem persists, you should check your Syspro service status." 215 + 'Please check your internet connection and try again. ' \
  216 + 'If this problem persists, you should check your Syspro service status.' # rubocop:disable Metrics/LineLength
213 217
214 else 218 else
215 - message = "Unexpected error communicating with Syspro. " \  
216 - "If this problem persists, talk to your Syspro implementation team." 219 + message = 'Unexpected error communicating with Syspro. ' \
  220 + 'If this problem persists, talk to your Syspro implementation team.'
217 221
218 end 222 end
219 223
220 - message += " Request was retried #{num_retries} times." if num_retries > 0 224 + message += " Request was retried #{num_retries} times." if num_retries.positive? # rubocop:disable Metrics/LineLength
221 225
222 raise ApiConnectionError, message + "\n\n(Network error: #{e.message})" 226 raise ApiConnectionError, message + "\n\n(Network error: #{e.message})"
223 end 227 end
224 228
225 - def self.should_retry?(e, num_retries) 229 + def self.should_retry?(e, num_retries) # rubocop:disable Metrics/LineLength, Naming/UncommunicativeMethodParamName
226 return false if num_retries >= Syspro.max_network_retries 230 return false if num_retries >= Syspro.max_network_retries
227 231
228 # Retry on timeout-related problems (either on open or read). 232 # Retry on timeout-related problems (either on open or read).
@@ -242,20 +246,20 @@ module Syspro @@ -242,20 +246,20 @@ module Syspro
242 end 246 end
243 247
244 def log_request(context, num_retries) 248 def log_request(context, num_retries)
245 - Util.log_info("Request to Syspro API", 249 + Util.log_info('Request to Syspro API',
246 account: context.account, 250 account: context.account,
247 api_version: context.api_version, 251 api_version: context.api_version,
248 method: context.method, 252 method: context.method,
249 num_retries: num_retries, 253 num_retries: num_retries,
250 path: context.path) 254 path: context.path)
251 - Util.log_debug("Request details", 255 + Util.log_debug('Request details',
252 body: context.body, 256 body: context.body,
253 query_params: context.query_params) 257 query_params: context.query_params)
254 end 258 end
255 private :log_request 259 private :log_request
256 260
257 - def log_response(context, request_start, status, body)  
258 - Util.log_info("Response from Syspro API", 261 + def log_response(context, request_start, status, body) # rubocop:disable Metrics/LineLength, Metrics/MethodLength
  262 + Util.log_info('Response from Syspro API',
259 account: context.account, 263 account: context.account,
260 api_version: context.api_version, 264 api_version: context.api_version,
261 elapsed: Time.now - request_start, 265 elapsed: Time.now - request_start,
@@ -263,14 +267,14 @@ module Syspro @@ -263,14 +267,14 @@ module Syspro
263 path: context.path, 267 path: context.path,
264 request_id: context.request_id, 268 request_id: context.request_id,
265 status: status) 269 status: status)
266 - Util.log_debug("Response details", 270 + Util.log_debug('Response details',
267 body: body, 271 body: body,
268 request_id: context.request_id) 272 request_id: context.request_id)
269 end 273 end
270 private :log_response 274 private :log_response
271 275
272 - def log_response_error(context, request_start, e)  
273 - Util.log_error("Request error", 276 + def log_response_error(context, request_start, e) # rubocop:disable Metrics/LineLength, Naming/UncommunicativeMethodParamName
  277 + Util.log_error('Request error',
274 elapsed: Time.now - request_start, 278 elapsed: Time.now - request_start,
275 error_message: e.message, 279 error_message: e.message,
276 method: context.method, 280 method: context.method,
@@ -278,12 +282,12 @@ module Syspro @@ -278,12 +282,12 @@ module Syspro
278 end 282 end
279 private :log_response_error 283 private :log_response_error
280 284
281 - def handle_error_response(http_resp, context) 285 + def handle_error_response(http_resp, context) # rubocop:disable Metrics/LineLength, Metrics/MethodLength
282 begin 286 begin
283 resp = SysproResponse.from_faraday_hash(http_resp) 287 resp = SysproResponse.from_faraday_hash(http_resp)
284 error_data = resp.data[:error] 288 error_data = resp.data[:error]
285 289
286 - raise SysproError, "Indeterminate error" unless error_data 290 + raise SysproError, 'Indeterminate error' unless error_data
287 rescue Nokogiri::XML::SyntaxError, SysproError 291 rescue Nokogiri::XML::SyntaxError, SysproError
288 raise general_api_error(http_resp[:status], http_resp[:body]) 292 raise general_api_error(http_resp[:status], http_resp[:body])
289 end 293 end
@@ -316,56 +320,55 @@ module Syspro @@ -316,56 +320,55 @@ module Syspro
316 # in so that we can generate a rich user agent header to help debug 320 # in so that we can generate a rich user agent header to help debug
317 # integrations. 321 # integrations.
318 class SystemProfiler 322 class SystemProfiler
319 - def self.uname  
320 - if File.exist?("/proc/version")  
321 - File.read("/proc/version").strip 323 + def self.uname # rubocop:disable Metrics/MethodLength
  324 + if File.exist?('/proc/version')
  325 + File.read('/proc/version').strip
322 else 326 else
323 - case RbConfig::CONFIG["host_os"] 327 + case RbConfig::CONFIG['host_os']
324 when /linux|darwin|bsd|sunos|solaris|cygwin/i 328 when /linux|darwin|bsd|sunos|solaris|cygwin/i
325 uname_from_system 329 uname_from_system
326 when /mswin|mingw/i 330 when /mswin|mingw/i
327 uname_from_system_ver 331 uname_from_system_ver
328 else 332 else
329 - "unknown platform" 333 + 'unknown platform'
330 end 334 end
331 end 335 end
332 end 336 end
333 337
334 def self.uname_from_system 338 def self.uname_from_system
335 - (`uname -a 2>/dev/null` || "").strip 339 + (`uname -a 2>/dev/null` || '').strip
336 rescue Errno::ENOENT 340 rescue Errno::ENOENT
337 - "uname executable not found" 341 + 'uname executable not found'
338 rescue Errno::ENOMEM # couldn't create subprocess 342 rescue Errno::ENOMEM # couldn't create subprocess
339 - "uname lookup failed" 343 + 'uname lookup failed'
340 end 344 end
341 345
342 def self.uname_from_system_ver 346 def self.uname_from_system_ver
343 - (`ver` || "").strip 347 + (`ver` || '').strip
344 rescue Errno::ENOENT 348 rescue Errno::ENOENT
345 - "ver executable not found" 349 + 'ver executable not found'
346 rescue Errno::ENOMEM # couldn't create subprocess 350 rescue Errno::ENOMEM # couldn't create subprocess
347 - "uname lookup failed" 351 + 'uname lookup failed'
348 end 352 end
349 353
350 def initialize 354 def initialize
351 @uname = self.class.uname 355 @uname = self.class.uname
352 end 356 end
353 357
354 - def user_agent  
355 - lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})" 358 + def user_agent # rubocop:disable Metrics/MethodLength
  359 + lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})" # rubocop:disable Metrics/LineLength
356 360
357 { 361 {
358 application: Syspro.app_info, 362 application: Syspro.app_info,
359 bindings_version: Syspro::VERSION, 363 bindings_version: Syspro::VERSION,
360 - lang: "ruby", 364 + lang: 'ruby',
361 lang_version: lang_version, 365 lang_version: lang_version,
362 platform: RUBY_PLATFORM, 366 platform: RUBY_PLATFORM,
363 - engine: defined?(RUBY_ENGINE) ? RUBY_ENGINE : "", 367 + engine: defined?(RUBY_ENGINE) ? RUBY_ENGINE : '',
364 uname: @uname, 368 uname: @uname,
365 - hostname: Socket.gethostname, 369 + hostname: Socket.gethostname
366 }.delete_if { |_k, v| v.nil? } 370 }.delete_if { |_k, v| v.nil? }
367 end 371 end
368 end 372 end
369 end 373 end
370 end 374 end
371 -  
lib/syspro/syspro_object.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
  4 + # This class represents a syspro response
2 class SysproObject 5 class SysproObject
3 include Enumerable 6 include Enumerable
4 7
@@ -18,7 +21,8 @@ module Syspro @@ -18,7 +21,8 @@ module Syspro
18 # considered to be equal if they have the same set of values and each one 21 # considered to be equal if they have the same set of values and each one
19 # of those values is the same. 22 # of those values is the same.
20 def ==(other) 23 def ==(other)
21 - other.is_a?(SysproObject) && @values == other.instance_variable_get(:@values) 24 + other.is_a?(SysproObject) &&
  25 + @values == other.instance_variable_get(:@values)
22 end 26 end
23 27
24 def to_s(*_args) 28 def to_s(*_args)
@@ -26,8 +30,8 @@ module Syspro @@ -26,8 +30,8 @@ module Syspro
26 end 30 end
27 31
28 def inspect 32 def inspect
29 - id_string = respond_to?(:id) && !id.nil? ? " id=#{id}" : ""  
30 - "#<#{self.class}:0x#{object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values) 33 + id_string = respond_to?(:id) && !id.nil? ? " id=#{id}" : ''
  34 + "#<#{self.class}:0x#{object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values) # rubocop:disable Metrics/LineLength
31 end 35 end
32 36
33 def keys 37 def keys
@@ -38,9 +42,9 @@ module Syspro @@ -38,9 +42,9 @@ module Syspro
38 @values.values 42 @values.values
39 end 43 end
40 44
41 - def to_hash 45 + def to_hash # rubocop:disable Metrics/MethodLength
42 maybe_to_hash = lambda do |value| 46 maybe_to_hash = lambda do |value|
43 - value && value.respond_to?(:to_hash) ? value.to_hash : value 47 + value&.respond_to?(:to_hash) ? value.to_hash : value
44 end 48 end
45 49
46 @values.each_with_object({}) do |(key, value), acc| 50 @values.each_with_object({}) do |(key, value), acc|
@@ -57,11 +61,9 @@ module Syspro @@ -57,11 +61,9 @@ module Syspro
57 @values.each(&blk) 61 @values.each(&blk)
58 end 62 end
59 63
60 - private  
61 -  
62 # Produces a deep copy of the given object including support for arrays, 64 # Produces a deep copy of the given object including support for arrays,
63 # hashes, and SysproObjects. 65 # hashes, and SysproObjects.
64 - def self.deep_copy(obj) 66 + def self.deep_copy(obj) # rubocop:disable Metrics/MethodLength
65 case obj 67 case obj
66 when Array 68 when Array
67 obj.map { |e| deep_copy(e) } 69 obj.map { |e| deep_copy(e) }
@@ -82,6 +84,5 @@ module Syspro @@ -82,6 +84,5 @@ module Syspro
82 end 84 end
83 end 85 end
84 private_class_method :deep_copy 86 private_class_method :deep_copy
85 -  
86 end 87 end
87 end 88 end
lib/syspro/syspro_response.rb
1 -require "nokogiri" 1 +# frozen_string_literal: true
  2 +
  3 +require 'nokogiri'
2 4
3 module Syspro 5 module Syspro
  6 + # This class represents a syspro response
4 class SysproResponse 7 class SysproResponse
5 attr_accessor :data, :http_body, :http_headers, :http_status, :request_id 8 attr_accessor :data, :http_body, :http_headers, :http_status, :request_id
6 9
@@ -12,7 +15,7 @@ module Syspro @@ -12,7 +15,7 @@ module Syspro
12 resp.data = Nokogiri::XML(resp.http_body) 15 resp.data = Nokogiri::XML(resp.http_body)
13 resp.http_headers = http_resp[:headers] 16 resp.http_headers = http_resp[:headers]
14 resp.http_status = http_resp[:status] 17 resp.http_status = http_resp[:status]
15 - resp.request_id = http_resp[:headers]["Request-Id"] 18 + resp.request_id = http_resp[:headers]['Request-Id']
16 resp 19 resp
17 end 20 end
18 21
@@ -23,7 +26,7 @@ module Syspro @@ -23,7 +26,7 @@ module Syspro
23 resp.data = Nokogiri::XML(resp.http_body) 26 resp.data = Nokogiri::XML(resp.http_body)
24 resp.http_headers = http_resp.headers 27 resp.http_headers = http_resp.headers
25 resp.http_status = http_resp.status 28 resp.http_status = http_resp.status
26 - resp.request_id = http_resp.headers["Request-Id"] 29 + resp.request_id = http_resp.headers['Request-Id']
27 resp 30 resp
28 end 31 end
29 end 32 end
lib/syspro/util.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 - class Util 4 + # Utillity class
  5 + class Util # rubocop:disable Metrics/ClassLength
3 # Options that a user is allowed to specify. 6 # Options that a user is allowed to specify.
4 OPTS_USER_SPECIFIED = Set[ 7 OPTS_USER_SPECIFIED = Set[
5 :user_id 8 :user_id
@@ -17,8 +20,7 @@ module Syspro @@ -17,8 +20,7 @@ module Syspro
17 OPTS_USER_SPECIFIED + Set[:client] 20 OPTS_USER_SPECIFIED + Set[:client]
18 ).freeze 21 ).freeze
19 22
20 -  
21 - def self.objects_to_ids(h) 23 + def self.objects_to_ids(h) # rubocop:disable Metrics/MethodLength, Metrics/LineLength, Naming/UncommunicativeMethodParamName
22 case h 24 case h
23 when ApiResource 25 when ApiResource
24 h.id 26 h.id
@@ -45,13 +47,17 @@ module Syspro @@ -45,13 +47,17 @@ module Syspro
45 # * +data+ - Hash of fields and values to be converted into a SysproObject. 47 # * +data+ - Hash of fields and values to be converted into a SysproObject.
46 # * +opts+ - Options for +SysproObject+ like an API key that will be reused 48 # * +opts+ - Options for +SysproObject+ like an API key that will be reused
47 # on subsequent API calls. 49 # on subsequent API calls.
48 - def self.convert_to_syspro_object(data, opts = {}) 50 + def self.convert_to_syspro_object(data, opts = {}) # rubocop:disable Metrics/LineLength, Metrics/MethodLength
49 case data 51 case data
50 when Array 52 when Array
51 data.map { |i| convert_to_syspro_object(i, opts) } 53 data.map { |i| convert_to_syspro_object(i, opts) }
52 when Hash 54 when Hash
53 - # Try converting to a known object class. If none available, fall back to generic SysproObject  
54 - object_classes.fetch(data[:object], SysproObject).construct_from(data, opts) 55 + # Try converting to a known object class.
  56 + # If none available, fall back to generic SysproObject
  57 + object_classes.fetch(
  58 + data[:object],
  59 + SysproObject
  60 + ).construct_from(data, opts)
55 else 61 else
56 data 62 data
57 end 63 end
@@ -66,7 +72,7 @@ module Syspro @@ -66,7 +72,7 @@ module Syspro
66 when Hash 72 when Hash
67 opts.clone 73 opts.clone
68 else 74 else
69 - raise TypeError, "normalize_opts expects a string or a hash" 75 + raise TypeError, 'normalize_opts expects a string or a hash'
70 end 76 end
71 end 77 end
72 78
@@ -78,7 +84,7 @@ module Syspro @@ -78,7 +84,7 @@ module Syspro
78 def self.normalize_headers(headers) 84 def self.normalize_headers(headers)
79 headers.each_with_object({}) do |(k, v), new_headers| 85 headers.each_with_object({}) do |(k, v), new_headers|
80 if k.is_a?(Symbol) 86 if k.is_a?(Symbol)
81 - k = titlecase_parts(k.to_s.tr("_", "-")) 87 + k = titlecase_parts(k.to_s.tr('_', '-'))
82 elsif k.is_a?(String) 88 elsif k.is_a?(String)
83 k = titlecase_parts(k) 89 k = titlecase_parts(k)
84 end 90 end
@@ -89,10 +95,10 @@ module Syspro @@ -89,10 +95,10 @@ module Syspro
89 95
90 def self.encode_parameters(params) 96 def self.encode_parameters(params)
91 Util.flatten_params(params) 97 Util.flatten_params(params)
92 - .map { |k, v| "#{url_encode(k)}=#{url_encode(v)}" }.join("&") 98 + .map { |k, v| "#{url_encode(k)}=#{url_encode(v)}" }.join('&')
93 end 99 end
94 100
95 - def self.flatten_params(params, parent_key = nil) 101 + def self.flatten_params(params, parent_key = nil) # rubocop:disable Metrics/LineLength, Metrics/MethodLength
96 result = [] 102 result = []
97 103
98 # do not sort the final output because arrays (and arrays of hashes 104 # do not sort the final output because arrays (and arrays of hashes
@@ -113,26 +119,41 @@ module Syspro @@ -113,26 +119,41 @@ module Syspro
113 end 119 end
114 120
115 def self.log_error(message, data = {}) 121 def self.log_error(message, data = {})
116 - if !Syspro.logger.nil? ||  
117 - !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_ERROR  
118 - log_internal(message, data, color: :cyan,  
119 - level: Syspro::LEVEL_ERROR, logger: Syspro.logger, out: $stderr) 122 + if !Syspro.logger.nil? || !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_ERROR # rubocop:disable Style/GuardClause, Metrics/LineLength
  123 + log_internal(
  124 + message,
  125 + data,
  126 + color: :cyan,
  127 + level: Syspro::LEVEL_ERROR,
  128 + logger: Syspro.logger,
  129 + out: $stderr
  130 + )
120 end 131 end
121 end 132 end
122 133
123 def self.log_info(message, data = {}) 134 def self.log_info(message, data = {})
124 - if !Syspro.logger.nil? ||  
125 - !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_INFO  
126 - log_internal(message, data, color: :cyan,  
127 - level: Syspro::LEVEL_INFO, logger: Syspro.logger, out: $stdout) 135 + if !Syspro.logger.nil? || !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_INFO # rubocop:disable Style/GuardClause, Metrics/LineLength
  136 + log_internal(
  137 + message,
  138 + data,
  139 + color: :cyan,
  140 + level: Syspro::LEVEL_INFO,
  141 + logger: Syspro.logger,
  142 + out: $stdout
  143 + )
128 end 144 end
129 end 145 end
130 146
131 def self.log_debug(message, data = {}) 147 def self.log_debug(message, data = {})
132 - if !Syspro.logger.nil? ||  
133 - !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_DEBUG  
134 - log_internal(message, data, color: :blue,  
135 - level: Syspro::LEVEL_DEBUG, logger: Syspro.logger, out: $stdout) 148 + if !Syspro.logger.nil? || !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_DEBUG # rubocop:disable Style/GuardClause, Metrics/LineLength
  149 + log_internal(
  150 + message,
  151 + data,
  152 + color: :blue,
  153 + level: Syspro::LEVEL_DEBUG,
  154 + logger: Syspro.logger,
  155 + out: $stdout
  156 + )
136 end 157 end
137 end 158 end
138 159
@@ -141,8 +162,47 @@ module Syspro @@ -141,8 +162,47 @@ module Syspro
141 # Don't use strict form encoding by changing the square bracket control 162 # Don't use strict form encoding by changing the square bracket control
142 # characters back to their literals. This is fine by the server, and 163 # characters back to their literals. This is fine by the server, and
143 # makes these parameter strings easier to read. 164 # makes these parameter strings easier to read.
144 - gsub("%5B", "[").gsub("%5D", "]") 165 + gsub('%5B', '[').gsub('%5D', ']')
145 end 166 end
  167 +
  168 + # TODO: Make these named required arguments when we drop support for Ruby
  169 + # 2.0.
  170 + def self.log_internal(message, data = {}, color: nil, level: nil, logger: nil, out: nil) # rubocop:disable Metrics/LineLength, Metrics/AbcSize, Metrics/MethodLength, Metrics/ParameterLists
  171 + data_str = data.reject { |_k, v| v.nil? }.map do |(k, v)|
  172 + format(
  173 + '%s=%s', # rubocop:disable Style/FormatStringToken
  174 + colorize(k, color, !out.nil? && out.isatty),
  175 + wrap_logfmt_value(v)
  176 + )
  177 + end.join(' ')
  178 +
  179 + if !logger.nil?
  180 + # the library's log levels are mapped to the same values as the
  181 + # standard library's logger
  182 + logger.log(
  183 + level,
  184 + format(
  185 + 'message=%s %s', # rubocop:disable Style/FormatStringToken
  186 + wrap_logfmt_value(message),
  187 + data_str
  188 + )
  189 + )
  190 + elsif out.isatty
  191 + out.puts format(
  192 + '%s %s %s', # rubocop:disable Style/FormatStringToken
  193 + colorize(level_name(level)[0, 4].upcase, color, out.isatty),
  194 + message,
  195 + data_str
  196 + )
  197 + else
  198 + out.puts format(
  199 + 'message=%s level=%s %s', # rubocop:disable Style/FormatStringToken
  200 + wrap_logfmt_value(message),
  201 + level_name(level),
  202 + data_str
  203 + )
  204 + end
  205 + end
  206 + private_class_method :log_internal
146 end 207 end
147 end 208 end
148 -  
lib/syspro/version.rb
  1 +# frozen_string_literal: true
  2 +
1 module Syspro 3 module Syspro
2 - VERSION = "0.1.0" 4 + VERSION = '0.1.0'
3 end 5 end
test/client_test.rb
1 -require "test_helper" 1 +# frozen_string_literal: true
  2 +
  3 +require 'test_helper'
2 4
3 class SysproClientTest < Minitest::Test 5 class SysproClientTest < Minitest::Test
  6 + extend Minitest::Spec::DSL
  7 +
  8 + let(:client) { ::Syspro::SysproClient.new }
  9 +
4 def test_get_syspro_version 10 def test_get_syspro_version
5 - client = ::Syspro::SysproClient.new  
6 - assert_match (/(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/), client.get_syspro_version.version 11 + assert_match(
  12 + /(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/,
  13 + client.get_syspro_version.version
  14 + )
7 end 15 end
8 16
9 def test_client_block_execution 17 def test_client_block_execution
10 - client = ::Syspro::SysproClient.new  
11 -  
12 - version, resp = client.request { 18 + version, resp = client.request do
13 Syspro::GetVersion.get_version 19 Syspro::GetVersion.get_version
14 - } 20 + end
15 21
16 - assert_match version.version, resp.http_body  
17 - assert_match (/(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/), version.version 22 + assert_match(version.version, resp.http_body)
  23 + assert_match(/(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/, version.version)
18 end 24 end
19 end 25 end
test/logoff_test.rb
1 -require "test_helper" 1 +# frozen_string_literal: true
  2 +
  3 +require 'test_helper'
2 4
3 class LogoffTest < Minitest::Test 5 class LogoffTest < Minitest::Test
4 - def test_successful_logoff  
5 - username = "wland"  
6 - password = "piperita2016"  
7 - company = "L"  
8 - company_password = "" 6 + extend Minitest::Spec::DSL
  7 +
  8 + let(:username) { 'wland' }
  9 + let(:password) { 'piperita2016' }
  10 + let(:company) { 'L' }
  11 + let(:company_password) { '' }
9 12
  13 + def test_successful_logoff
10 uid = Syspro::Logon.logon(username, password, company, company_password) 14 uid = Syspro::Logon.logon(username, password, company, company_password)
11 assert_equal true, Syspro::Logoff.logoff(uid.guid) 15 assert_equal true, Syspro::Logoff.logoff(uid.guid)
12 end 16 end
13 17
14 def test_logoff_error 18 def test_logoff_error
15 - assert_kind_of String, Syspro::Logoff.logoff('1BB5B3050954BB459A5D034DB5CC386980') 19 + assert_kind_of(
  20 + String,
  21 + Syspro::Logoff.logoff('1BB5B3050954BB459A5D034DB5CC386980')
  22 + )
16 end 23 end
17 end 24 end
18 -  
test/logon_test.rb
1 -require "test_helper" 1 +# frozen_string_literal: true
  2 +
  3 +require 'test_helper'
2 4
3 class LogonTest < Minitest::Test 5 class LogonTest < Minitest::Test
4 - def test_logon  
5 - username = "wland"  
6 - password = "piperita2016"  
7 - company = "L"  
8 - company_password = ""  
9 - client = ::Syspro::SysproClient.new 6 + extend Minitest::Spec::DSL
  7 +
  8 + let(:username) { 'wland' }
  9 + let(:password) { 'piperita2016' }
  10 + let(:company) { 'L' }
  11 + let(:company_password) { '' }
10 12
11 - assert_match (/([A-Z0-9]{33})\w/), client.logon(username, password, company, company_password).guid 13 + def test_logon
  14 + assert_match(
  15 + /([A-Z0-9]{33})\w/,
  16 + ::Syspro::SysproClient.new.logon(
  17 + username,
  18 + password,
  19 + company,
  20 + company_password
  21 + ).guid
  22 + )
12 end 23 end
13 end 24 end
14 -  
test/query_test.rb
1 -require "test_helper" 1 +# frozen_string_literal: true
  2 +
  3 +require 'test_helper'
2 4
3 class QueryTest < Minitest::Test 5 class QueryTest < Minitest::Test
4 - def test_query_browse  
5 - user_id = Syspro::Logon.logon("wland", "piperita2016", "L", "") 6 + def test_query_browse # rubocop:disable Metrics/MethodLength
  7 + user_id = Syspro::Logon.logon('wland', 'piperita2016', 'L', '')
6 8
7 combrw = Syspro::BusinessObjects::ComBrw.new 9 combrw = Syspro::BusinessObjects::ComBrw.new
8 - combrw.browse_name = "InvMaster"  
9 - combrw.start_condition = "" 10 + combrw.browse_name = 'InvMaster'
  11 + combrw.start_condition = ''
10 combrw.return_rows = 5 12 combrw.return_rows = 5
11 combrw.filters = [] 13 combrw.filters = []
12 - combrw.table_name = "InvMaster"  
13 - combrw.title = "StockCodes" 14 + combrw.table_name = 'InvMaster'
  15 + combrw.title = 'StockCodes'
14 combrw.columns = [ 16 combrw.columns = [
15 - {name: "StockCode"} 17 + { name: 'StockCode' }
16 ] 18 ]
17 19
18 browse_result = combrw.call(user_id.guid) 20 browse_result = combrw.call(user_id.guid)
@@ -20,26 +22,26 @@ class QueryTest &lt; Minitest::Test @@ -20,26 +22,26 @@ class QueryTest &lt; Minitest::Test
20 refute_nil browse_result 22 refute_nil browse_result
21 end 23 end
22 24
23 - def test_query_query  
24 - user_id = Syspro::Logon.logon("wland", "piperita2016", "L", "") 25 + def test_query_query # rubocop:disable Metrics/MethodLength
  26 + user_id = Syspro::Logon.logon('wland', 'piperita2016', 'L', '')
25 27
26 comfnd = Syspro::BusinessObjects::ComFnd.new 28 comfnd = Syspro::BusinessObjects::ComFnd.new
27 - comfnd.table_name = "InvMaster" 29 + comfnd.table_name = 'InvMaster'
28 comfnd.return_rows = 5 30 comfnd.return_rows = 5
29 comfnd.columns = [ 31 comfnd.columns = [
30 { 32 {
31 - name: "StockCode" 33 + name: 'StockCode'
32 } 34 }
33 ] 35 ]
34 comfnd.expressions = [ 36 comfnd.expressions = [
35 { 37 {
36 - andor: "And",  
37 - column: "StockCode",  
38 - condition: "EQ",  
39 - value: "02" 38 + andor: 'And',
  39 + column: 'StockCode',
  40 + condition: 'EQ',
  41 + value: '02'
40 } 42 }
41 ] 43 ]
42 - comfnd.order_by = "StockCode" 44 + comfnd.order_by = 'StockCode'
43 45
44 query_result = comfnd.call(user_id.guid) 46 query_result = comfnd.call(user_id.guid)
45 47
@@ -47,14 +49,14 @@ class QueryTest &lt; Minitest::Test @@ -47,14 +49,14 @@ class QueryTest &lt; Minitest::Test
47 end 49 end
48 50
49 def test_query_fetch 51 def test_query_fetch
50 - user_id = Syspro::Logon.logon("wland", "piperita2016", "L", "") 52 + user_id = Syspro::Logon.logon('wland', 'piperita2016', 'L', '')
51 53
52 comfch = Syspro::BusinessObjects::ComFch.new 54 comfch = Syspro::BusinessObjects::ComFch.new
53 - comfch.table_name = "InvMaster"  
54 - comfch.key = "02" 55 + comfch.table_name = 'InvMaster'
  56 + comfch.key = '02'
55 comfch.optional_keys = [] 57 comfch.optional_keys = []
56 comfch.full_key_provided = false 58 comfch.full_key_provided = false
57 - comfch.default_type = "" 59 + comfch.default_type = ''
58 comfch.espresso_fetch = true 60 comfch.espresso_fetch = true
59 61
60 fetch_result = comfch.call(user_id.guid) 62 fetch_result = comfch.call(user_id.guid)
test/syspro_test.rb
1 -require "test_helper" 1 +# frozen_string_literal: true
  2 +
  3 +require 'test_helper'
2 4
3 class SysproTest < Minitest::Test 5 class SysproTest < Minitest::Test
4 def test_that_it_has_a_version_number 6 def test_that_it_has_a_version_number
test/test_helper.rb
1 -$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)  
2 -require "syspro" 1 +# frozen_string_literal: true
3 2
4 -require "pry"  
5 -require "minitest/autorun" 3 +$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
  4 +require 'syspro'
  5 +
  6 +require 'pry'
  7 +require 'minitest/autorun'