Commit 0c0af54a8bd446733ec29ed87509d6c12b68d578
1 parent
eef01045
error handling; cleanup; rename to `syspro-ruby`
Showing
13 changed files
with
131 additions
and
54 deletions
Show diff stats
Gemfile
README.md
1 | -# Syspro | |
1 | +# syspro-ruby | |
2 | 2 | |
3 | -Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/syspro`. To experiment with that code, run `bin/console` for an interactive prompt. | |
4 | - | |
5 | -TODO: Delete this and the text above, and describe your gem | |
3 | +syspro-ruby is an adapter gem to connect to SYSPRO 7 ERP installations. You can use this gem to connect to the SYSPRO 7 WCF Service and build Ruby applications on top of your SYSPRO data. | |
6 | 4 | |
7 | 5 | ## Installation |
8 | 6 | |
... | ... | @@ -22,7 +20,57 @@ Or install it yourself as: |
22 | 20 | |
23 | 21 | ## Usage |
24 | 22 | |
25 | -TODO: Write usage instructions here | |
23 | +### Utilities | |
24 | + | |
25 | +#### Logon | |
26 | + | |
27 | +```rb | |
28 | +user_id = Syspro::Logon.logon(username, password, company_id, company_password) | |
29 | +``` | |
30 | +`user_id` will be a `UserId` object that contains the `guid` supplied by SYSPRO. You will use this guid to make further requests to SYSPRO. | |
31 | + | |
32 | +#### GetUserProfile | |
33 | + | |
34 | +```rb | |
35 | +user_profile = Syspro::GetUserProfile.get_user_profile(guid) | |
36 | +``` | |
37 | +`user_profile` will be a `UserProfile` object that contains the following: | |
38 | + - `company_name` | |
39 | + - `operator_code` | |
40 | + - `operator_group` | |
41 | + - `operator_email_address` | |
42 | + - `operator_location` | |
43 | + - `operator_language_code` | |
44 | + - `system_language` | |
45 | + - `accounting_date` | |
46 | + - `company_date` | |
47 | + - `default_ar_branch` | |
48 | + - `default_ap_branch` | |
49 | + - `default_bank` | |
50 | + - `default_warehouse` | |
51 | + - `default_customer` | |
52 | + - `system_site_id` | |
53 | + - `system_nationality_code` | |
54 | + - `local_currency_code` | |
55 | + - `currency_description` | |
56 | + - `default_requisition_user` | |
57 | + - `xml_to_html_transform` | |
58 | + - `css_style` | |
59 | + - `css_suffix` | |
60 | + - `decimal_format` | |
61 | + - `date_format` | |
62 | + - `functional_role` | |
63 | + - `database_type` | |
64 | + - `syspro_version` | |
65 | + - `enet_version` | |
66 | + - `syspro_server_bit_width` | |
67 | + | |
68 | +#### Logoff | |
69 | + | |
70 | +```rb | |
71 | +logged_off = Syspro::Logoff.logoff(guid) | |
72 | +``` | |
73 | +`logged_off` will be `true` if the user has been successfully logged off, and will contain an error string if an error has occured. | |
26 | 74 | |
27 | 75 | ## Development |
28 | 76 | |
... | ... | @@ -32,7 +80,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To |
32 | 80 | |
33 | 81 | ## Contributing |
34 | 82 | |
35 | -Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/syspro. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. | |
83 | +Bug reports and pull requests are welcome on GitHub at https://github.com/ike/syspro-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. | |
36 | 84 | |
37 | 85 | ## License |
38 | 86 | |
... | ... | @@ -40,4 +88,4 @@ The gem is available as open source under the terms of the [MIT License](https:/ |
40 | 88 | |
41 | 89 | ## Code of Conduct |
42 | 90 | |
43 | -Everyone interacting in the Syspro project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/syspro/blob/master/CODE_OF_CONDUCT.md). | |
91 | +Everyone interacting in the Syspro project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ike/syspro-ruby/blob/master/CODE_OF_CONDUCT.md). | ... | ... |
bin/console
... | ... | @@ -2,13 +2,6 @@ |
2 | 2 | |
3 | 3 | require "bundler/setup" |
4 | 4 | require "syspro" |
5 | +require "pry" | |
5 | 6 | |
6 | -# You can add fixtures and/or initialization code here to make experimenting | |
7 | -# with your gem easier. You can also use a different console, if you like. | |
8 | - | |
9 | -# (If you use this, don't forget to add pry to your Gemfile!) | |
10 | -# require "pry" | |
11 | -# Pry.start | |
12 | - | |
13 | -require "irb" | |
14 | -IRB.start(__FILE__) | |
7 | +Pry.start | ... | ... |
bin/setup
lib/syspro.rb
lib/syspro/api_resource.rb
... | ... | @@ -16,13 +16,6 @@ module Syspro |
16 | 16 | "/#{CGI.escape(class_name.downcase)}" |
17 | 17 | end |
18 | 18 | |
19 | - def resource_url | |
20 | - #unless (id = self["id"]) | |
21 | - #raise InvalidRequestError.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}", "id") | |
22 | - #end | |
23 | - #"#{self.class.resource_url}/#{CGI.escape(id)}" | |
24 | - end | |
25 | - | |
26 | 19 | def refresh |
27 | 20 | resp, opts = request(:get, resource_url, @retrieve_params) |
28 | 21 | initialize_from(resp.data, opts) | ... | ... |
1 | +module Syspro | |
2 | + class SysproError < StandardError | |
3 | + attr_reader :message, :response, :code, :http_body, :http_headers, | |
4 | + :http_status, :data, :request_id | |
5 | + | |
6 | + # Initializes a SysproError. | |
7 | + def initialize(message = nil, http_status: nil, http_body: nil, data: nil, | |
8 | + http_headers: nil, code: nil) | |
9 | + @message = message | |
10 | + @http_status = http_status | |
11 | + @http_body = http_body | |
12 | + @http_headers = http_headers || {} | |
13 | + @data = data | |
14 | + @code = code | |
15 | + @request_id = @http_headers[:request_id] | |
16 | + end | |
17 | + | |
18 | + def to_s | |
19 | + status_string = @http_status.nil? ? "" : "(Status #{@http_status}) " | |
20 | + id_string = @request_id.nil? ? "" : "(Request #{@request_id}) " | |
21 | + "#{status_string}#{id_string}#{@message}" | |
22 | + end | |
23 | + end | |
24 | + | |
25 | + class AuthenticationError < SysproError | |
26 | + end | |
27 | + | |
28 | + class ApiConnectionError < SysproError | |
29 | + end | |
30 | + | |
31 | + class ApiError < SysproError | |
32 | + end | |
33 | + | |
34 | +end | ... | ... |
lib/syspro/syspro_client.rb
... | ... | @@ -40,6 +40,7 @@ module Syspro |
40 | 40 | c.adapter Faraday.default_adapter |
41 | 41 | end |
42 | 42 | |
43 | + # For now, we're not verifying SSL certificates. The warning will appear. | |
43 | 44 | #if Syspro.verify_ssl_certs |
44 | 45 | #conn.ssl.verify = true |
45 | 46 | #conn.ssl.cert_store = Syspro.ca_store |
... | ... | @@ -129,7 +130,7 @@ module Syspro |
129 | 130 | end |
130 | 131 | |
131 | 132 | def general_api_error(status, body) |
132 | - APIError.new("Invalid response object from API: #{body.inspect} " \ | |
133 | + ApiError.new("Invalid response object from API: #{body.inspect} " \ | |
133 | 134 | "(HTTP response code was #{status})", |
134 | 135 | http_status: status, http_body: body) |
135 | 136 | end | ... | ... |
lib/syspro/syspro_object.rb
... | ... | @@ -4,6 +4,14 @@ module Syspro |
4 | 4 | |
5 | 5 | def initialize(id = nil, opts = {}) |
6 | 6 | @opts = Util.normalize_opts(opts) |
7 | + @original_values = {} | |
8 | + @values = {} | |
9 | + | |
10 | + # This really belongs in APIResource, but not putting it there allows us | |
11 | + # to have a unified inspect method | |
12 | + @unsaved_values = Set.new | |
13 | + @transient_values = Set.new | |
14 | + @values[:id] = id if id | |
7 | 15 | end |
8 | 16 | |
9 | 17 | # Determines the equality of two Syspro objects. Syspro objects are |
... | ... | @@ -52,7 +60,7 @@ module Syspro |
52 | 60 | private |
53 | 61 | |
54 | 62 | # Produces a deep copy of the given object including support for arrays, |
55 | - # hashes, and SysproObject. | |
63 | + # hashes, and SysproObjects. | |
56 | 64 | def self.deep_copy(obj) |
57 | 65 | case obj |
58 | 66 | when Array | ... | ... |
lib/syspro/syspro_response.rb
1 | 1 | require "nokogiri" |
2 | 2 | |
3 | 3 | module Syspro |
4 | - # SysproResponse encapsulates some vitals of a response that came back from | |
5 | - # the Syspro API. | |
6 | 4 | class SysproResponse |
7 | - # The data contained by the HTTP body of the response deserialized from | |
8 | - # JSON. | |
9 | - attr_accessor :data | |
10 | - | |
11 | - # The raw HTTP body of the response. | |
12 | - attr_accessor :http_body | |
13 | - | |
14 | - # A Hash of the HTTP headers of the response. | |
15 | - attr_accessor :http_headers | |
16 | - | |
17 | - # The integer HTTP status code of the response. | |
18 | - attr_accessor :http_status | |
19 | - | |
20 | - # The Syspro request ID of the response. | |
21 | - attr_accessor :request_id | |
5 | + attr_accessor :data, :http_body, :http_headers, :http_status, :request_id | |
22 | 6 | |
23 | 7 | # Initializes a SysproResponse object from a Hash like the kind returned as |
24 | 8 | # part of a Faraday exception. |
25 | - # | |
26 | - # This may throw JSON::ParserError if the response body is not valid JSON. | |
27 | 9 | def self.from_faraday_hash(http_resp) |
28 | 10 | resp = SysproResponse.new |
29 | 11 | resp.http_body = http_resp[:body] |
... | ... | @@ -35,8 +17,6 @@ module Syspro |
35 | 17 | end |
36 | 18 | |
37 | 19 | # Initializes a SysproResponse object from a Faraday HTTP response object. |
38 | - # | |
39 | - # This may throw JSON::ParserError if the response body is not valid JSON. | |
40 | 20 | def self.from_faraday_response(http_resp) |
41 | 21 | resp = SysproResponse.new |
42 | 22 | resp.http_body = http_resp.body | ... | ... |
lib/syspro/util.rb
... | ... | @@ -2,9 +2,21 @@ module Syspro |
2 | 2 | class Util |
3 | 3 | # Options that a user is allowed to specify. |
4 | 4 | OPTS_USER_SPECIFIED = Set[ |
5 | - # :syspro_version | |
5 | + :user_id | |
6 | 6 | ].freeze |
7 | 7 | |
8 | + # Options that should be copyable from one StripeObject to another | |
9 | + # including options that may be internal. | |
10 | + OPTS_COPYABLE = ( | |
11 | + OPTS_USER_SPECIFIED + Set[:api_base] | |
12 | + ).freeze | |
13 | + | |
14 | + # Options that should be persisted between API requests. This includes | |
15 | + # client, which is an object containing an HTTP client to reuse. | |
16 | + OPTS_PERSISTABLE = ( | |
17 | + OPTS_USER_SPECIFIED + Set[:client] | |
18 | + ).freeze | |
19 | + | |
8 | 20 | |
9 | 21 | def self.objects_to_ids(h) |
10 | 22 | case h |
... | ... | @@ -45,8 +57,7 @@ module Syspro |
45 | 57 | end |
46 | 58 | end |
47 | 59 | |
48 | - | |
49 | - # The secondary opts argument can either be a string or hash | |
60 | + # The secondary opts argument can either be a string or hash | |
50 | 61 | # Turn this value into an api_key and a set of headers |
51 | 62 | def self.normalize_opts(opts) |
52 | 63 | case opts | ... | ... |
syspro.gemspec renamed to syspro-ruby.gemspec
... | ... | @@ -3,10 +3,10 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) |
3 | 3 | require "syspro/version" |
4 | 4 | |
5 | 5 | Gem::Specification.new do |spec| |
6 | - spec.name = "syspro" | |
6 | + spec.name = "syspro-ruby" | |
7 | 7 | spec.version = Syspro::VERSION |
8 | 8 | spec.authors = ["Isaac Lewis"] |
9 | - spec.email = ["ike@wild.land"] | |
9 | + spec.email = ["isaac@ike.io"] | |
10 | 10 | |
11 | 11 | spec.summary = %q{SYSPRO 7 Api Ruby adapter} |
12 | 12 | spec.license = "MIT" | ... | ... |
test/client_test.rb
... | ... | @@ -5,4 +5,15 @@ class SysproClientTest < Minitest::Test |
5 | 5 | client = ::Syspro::SysproClient.new |
6 | 6 | assert_match (/(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/), client.get_syspro_version.version |
7 | 7 | end |
8 | + | |
9 | + def test_client_block_execution | |
10 | + client = ::Syspro::SysproClient.new | |
11 | + | |
12 | + version, resp = client.request { | |
13 | + Syspro::GetVersion.get_version | |
14 | + } | |
15 | + | |
16 | + assert_match version.version, resp.http_body | |
17 | + assert_match (/(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/), version.version | |
18 | + end | |
8 | 19 | end | ... | ... |