fishbowl 0.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +9 -4
  4. data/Gemfile +9 -2
  5. data/Guardfile +13 -0
  6. data/README.md +25 -5
  7. data/fishbowl.gemspec +5 -5
  8. data/lib/fishbowl/configuration.rb +9 -0
  9. data/lib/fishbowl/connection.rb +100 -0
  10. data/lib/fishbowl/errors.rb +18 -8
  11. data/lib/fishbowl/ext.rb +15 -0
  12. data/lib/fishbowl/objects/account.rb +8 -12
  13. data/lib/fishbowl/objects/address.rb +86 -0
  14. data/lib/fishbowl/objects/base_object.rb +42 -9
  15. data/lib/fishbowl/objects/carrier.rb +15 -0
  16. data/lib/fishbowl/objects/carton.rb +54 -0
  17. data/lib/fishbowl/objects/uom.rb +47 -0
  18. data/lib/fishbowl/objects/user.rb +15 -0
  19. data/lib/fishbowl/objects.rb +5 -0
  20. data/lib/fishbowl/requests/add_inventory.rb +34 -0
  21. data/lib/fishbowl/requests/add_sales_order_item.rb +42 -0
  22. data/lib/fishbowl/requests/adjust_inventory.rb +28 -0
  23. data/lib/fishbowl/requests/get_account_balance.rb +15 -0
  24. data/lib/fishbowl/requests/get_account_list.rb +13 -0
  25. data/lib/fishbowl/requests/get_carrier_list.rb +14 -0
  26. data/lib/fishbowl/requests/get_customer_list.rb +12 -0
  27. data/lib/fishbowl/requests/get_customer_name_list.rb +12 -0
  28. data/lib/fishbowl/requests/get_export_list.rb +12 -0
  29. data/lib/fishbowl/requests/get_import_list.rb +12 -0
  30. data/lib/fishbowl/requests/get_location_group_list.rb +12 -0
  31. data/lib/fishbowl/requests/get_location_list.rb +12 -0
  32. data/lib/fishbowl/requests/get_product.rb +18 -0
  33. data/lib/fishbowl/requests/get_product_price.rb +21 -0
  34. data/lib/fishbowl/requests/get_uom_list.rb +12 -0
  35. data/lib/fishbowl/requests/get_vendor_list.rb +12 -0
  36. data/lib/fishbowl/requests/get_vendor_name_list.rb +12 -0
  37. data/lib/fishbowl/requests/get_work_order_list.rb +12 -0
  38. data/lib/fishbowl/requests/inventory_quantity.rb +17 -0
  39. data/lib/fishbowl/requests/load_sales_order.rb +21 -0
  40. data/lib/fishbowl/requests/make_payment.rb +32 -0
  41. data/lib/fishbowl/requests/save_sales_order.rb +86 -0
  42. data/lib/fishbowl/requests/total_inventory.rb +18 -0
  43. data/lib/fishbowl/requests/void_sales_order.rb +18 -0
  44. data/lib/fishbowl/requests.rb +5 -0
  45. data/lib/fishbowl/version.rb +1 -1
  46. data/lib/fishbowl.rb +12 -95
  47. data/lib/status_codes.yml +183 -0
  48. data/spec/connection_spec.rb +99 -99
  49. data/spec/errors_spec.rb +11 -9
  50. data/spec/examples/account.xml +6 -0
  51. data/spec/examples/address.xml +30 -0
  52. data/spec/examples/carrier.xml +3 -0
  53. data/spec/examples/carton.xml +93 -0
  54. data/spec/examples/contact_information.xml +5 -0
  55. data/spec/examples/contacts.xml +7 -0
  56. data/spec/examples/credit_card.xml +10 -0
  57. data/spec/examples/customer.xml +54 -0
  58. data/spec/examples/location.xml +14 -0
  59. data/spec/examples/location_group.xml +5 -0
  60. data/spec/examples/location_group_string.xml +1 -0
  61. data/spec/examples/order_history.xml +8 -0
  62. data/spec/examples/part.xml +105 -0
  63. data/spec/examples/payment.xml +6 -0
  64. data/spec/examples/pick.xml +265 -0
  65. data/spec/examples/pick_item.xml +236 -0
  66. data/spec/examples/product.xml +159 -0
  67. data/spec/examples/purchase_order.xml +53 -0
  68. data/spec/examples/receipt.xml +146 -0
  69. data/spec/examples/report.xml +10 -0
  70. data/spec/examples/report_tree.xml +7 -0
  71. data/spec/examples/sales_order.xml +47 -0
  72. data/spec/examples/sales_order_item.xml +32 -0
  73. data/spec/examples/shipping.xml +127 -0
  74. data/spec/examples/tag.xml +28 -0
  75. data/spec/examples/tax_rate.xml +10 -0
  76. data/spec/examples/tracking.xml +14 -0
  77. data/spec/examples/tracking_item.xml +12 -0
  78. data/spec/examples/transfer_order.xml +257 -0
  79. data/spec/examples/transfer_order_item.xml +147 -0
  80. data/spec/examples/uom.xml +26 -0
  81. data/spec/examples/uom_conversion.xml +8 -0
  82. data/spec/examples/user.xml +8 -0
  83. data/spec/examples/vendor.xml +19 -0
  84. data/spec/examples/vendor_part_number.xml +3 -0
  85. data/spec/examples/work_order.xml +228 -0
  86. data/spec/examples/work_order_item.xml +172 -0
  87. data/spec/objects/account_spec.rb +33 -27
  88. data/spec/objects/address_information_spec.rb +18 -0
  89. data/spec/objects/address_spec.rb +36 -0
  90. data/spec/objects/base_object_spec.rb +67 -23
  91. data/spec/objects/carrier_spec.rb +15 -0
  92. data/spec/objects/carton_spec.rb +23 -0
  93. data/spec/objects/country_spec.rb +16 -0
  94. data/spec/objects/shipping_item_spec.rb +21 -0
  95. data/spec/objects/state_spec.rb +17 -0
  96. data/spec/objects/uom_conversion_spec.rb +20 -0
  97. data/spec/objects/uom_spec.rb +20 -0
  98. data/spec/objects/user_spec.rb +20 -0
  99. data/spec/requests/add_inventory_spec.rb +79 -0
  100. data/spec/requests/add_sales_order_item_spec.rb +85 -0
  101. data/spec/requests/adjust_inventory_spec.rb +62 -0
  102. data/spec/requests/calculate_sales_order_spec.rb +48 -0
  103. data/spec/requests/close_short_sales_order_spec.rb +45 -0
  104. data/spec/requests/cycle_count_spec.rb +49 -0
  105. data/spec/requests/delete_sales_order_spec.rb +45 -0
  106. data/spec/requests/export_spec.rb +45 -0
  107. data/spec/requests/get_account_balance_spec.rb +52 -0
  108. data/spec/requests/get_account_list_spec.rb +51 -0
  109. data/spec/requests/get_carrier_list_spec.rb +54 -0
  110. data/spec/requests/get_customer_list_spec.rb +51 -0
  111. data/spec/requests/get_customer_name_list_spec.rb +45 -0
  112. data/spec/requests/get_customer_spec.rb +45 -0
  113. data/spec/requests/get_export_list_spec.rb +45 -0
  114. data/spec/requests/get_import_list_spec.rb +45 -0
  115. data/spec/requests/get_inventory_quantity_spec.rb +65 -0
  116. data/spec/requests/get_light_part_list_spec.rb +51 -0
  117. data/spec/requests/get_location_group_list_spec.rb +45 -0
  118. data/spec/requests/get_location_list_spec.rb +45 -0
  119. data/spec/requests/get_next_number_spec.rb +45 -0
  120. data/spec/requests/get_part_cost_spec.rb +45 -0
  121. data/spec/requests/get_part_information_spec.rb +45 -0
  122. data/spec/requests/get_part_list_spec.rb +65 -0
  123. data/spec/requests/get_pick_spec.rb +45 -0
  124. data/spec/requests/get_product_information_spec.rb +46 -0
  125. data/spec/requests/get_purchase_order_list_spec.rb +45 -0
  126. data/spec/requests/get_receipt_spec.rb +49 -0
  127. data/spec/requests/get_receiving_list_spec.rb +49 -0
  128. data/spec/requests/get_sales_order_list_spec.rb +49 -0
  129. data/spec/requests/get_ship_list_spec.rb +49 -0
  130. data/spec/requests/get_ship_now_list_spec.rb +48 -0
  131. data/spec/requests/get_shipment_spec.rb +45 -0
  132. data/spec/requests/get_system_property_spec.rb +45 -0
  133. data/spec/requests/get_total_inventory_spec.rb +46 -0
  134. data/spec/requests/get_transfer_order_list_spec.rb +45 -0
  135. data/spec/requests/get_uom_list_spec.rb +45 -0
  136. data/spec/requests/get_user_property_spec.rb +45 -0
  137. data/spec/requests/get_vendor_list_spec.rb +45 -0
  138. data/spec/requests/get_vendor_name_list_spec.rb +45 -0
  139. data/spec/requests/get_vendor_spec.rb +48 -0
  140. data/spec/requests/get_work_order_list_spec.rb +45 -0
  141. data/spec/requests/get_work_order_spec.rb +45 -0
  142. data/spec/requests/import_spec.rb +49 -0
  143. data/spec/requests/issues_sales_order_spec.rb +45 -0
  144. data/spec/requests/load_sales_order_spec.rb +45 -0
  145. data/spec/requests/load_transfer_order_spec.rb +45 -0
  146. data/spec/requests/location_query_spec.rb +49 -0
  147. data/spec/requests/make_payment_spec.rb +50 -0
  148. data/spec/requests/move_spec.rb +49 -0
  149. data/spec/requests/part_query_spec.rb +46 -0
  150. data/spec/requests/pick_query_spec.rb +49 -0
  151. data/spec/requests/print_report_spec.rb +48 -0
  152. data/spec/requests/product_query_spec.rb +46 -0
  153. data/spec/requests/quick_ship_spec.rb +45 -0
  154. data/spec/requests/quickbooks_export_spec.rb +43 -0
  155. data/spec/requests/save_customer_spec.rb +48 -0
  156. data/spec/requests/save_discount_spec.rb +48 -0
  157. data/spec/requests/save_pick_spec.rb +48 -0
  158. data/spec/requests/save_purchase_order_spec.rb +48 -0
  159. data/spec/requests/save_receipt_spec.rb +48 -0
  160. data/spec/requests/save_report_spec.rb +49 -0
  161. data/spec/requests/save_sales_order_spec.rb +48 -0
  162. data/spec/requests/save_shipment_spec.rb +48 -0
  163. data/spec/requests/save_tax_rate_spec.rb +48 -0
  164. data/spec/requests/save_transfer_order_spec.rb +48 -0
  165. data/spec/requests/save_upc_spec.rb +48 -0
  166. data/spec/requests/save_vendor_spec.rb +48 -0
  167. data/spec/requests/save_work_order_spec.rb +48 -0
  168. data/spec/requests/set_default_part_location_spec.rb +48 -0
  169. data/spec/requests/set_system_property_spec.rb +48 -0
  170. data/spec/requests/set_user_property_spec.rb +48 -0
  171. data/spec/requests/ship_spec.rb +48 -0
  172. data/spec/requests/void_sales_order_spec.rb +43 -0
  173. data/spec/spec_helper.rb +48 -16
  174. data/spec/support/examples_loader.rb +5 -0
  175. data/spec/support/response_mocks.rb +27 -0
  176. metadata +304 -35
  177. data/spec/support/fake_login.rb +0 -15
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2d19ab01cc4985f080ac26eda680a01a02c15b278172ffc4f18d2b6c6090c3de
4
+ data.tar.gz: a24fcb59434941c7af2a4747b91eb09d0e4e7293cd11a50d8885080dc62e94af
5
+ SHA512:
6
+ metadata.gz: dd3cc10062e90203f9a688548b344221684e84f02fe90561435913d825b0fe27fdd8026935636b7b424693783ee3accda60fef44a61e8cdedf2125ad18cada71
7
+ data.tar.gz: 29e6eaa2e0be585ce71138b2e62748721a58bc43f2e8fc267c5d750559ce376d3ba538479d1a3be757c07b66528460139be249c9a4d6217f03ef3567de33653b
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .idea/
data/.travis.yml CHANGED
@@ -1,19 +1,24 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - jruby-19mode # JRuby in 1.9 mode
3
+ - "1.9.3"
4
+ - jruby-19mode
5
+ - jruby-head
5
6
  - rbx-19mode
6
7
  jdk:
7
8
  - openjdk7
8
9
  - oraclejdk7
9
10
  - openjdk6
11
+ bundler_args: --without=localtest
10
12
  matrix:
11
13
  exclude:
12
- - rvm: 1.9.3
14
+ - rvm: "1.9.3"
13
15
  jdk: oraclejdk7
14
- - rvm: 1.9.3
16
+ - rvm: "1.9.3"
15
17
  jdk: openjdk6
16
18
  - rvm: rbx-19mode
17
19
  jdk: oraclejdk7
18
20
  - rvm: rbx-19mode
19
21
  jdk: openjdk6
22
+ allow_failures:
23
+ - rvm: jruby-head
24
+ - rvm: rbx-19mode
data/Gemfile CHANGED
@@ -4,6 +4,13 @@ gemspec
4
4
 
5
5
  gem 'rake'
6
6
  gem 'rspec'
7
- gem 'simplecov'
8
-
9
7
  gem 'equivalent-xml'
8
+ gem 'nokogiri', '>= 1.8.5'
9
+
10
+ group :localtest do
11
+ gem 'pry'
12
+ end
13
+
14
+ group :test do
15
+ gem 'spork'
16
+ end
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ guard 'spork' do
2
+ watch('Gemfile')
3
+ watch('Gemfile.lock')
4
+ watch('spec/spec_helper.rb') { :rspec }
5
+ end
6
+
7
+ guard 'rspec' do
8
+ watch(%r{^spec/.+_spec\.rb$})
9
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
10
+ watch('spec/spec_helper.rb') { "spec" }
11
+
12
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
13
+ end
data/README.md CHANGED
@@ -2,10 +2,6 @@
2
2
 
3
3
  Provides an interface to the Fishbowl Inventory API.
4
4
 
5
- [![Build Status](https://travis-ci.org/readyproject/fishbowl.png)](https://travis-ci.org/readyproject/fishbowl)
6
- [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/readyproject/fishbowl)
7
- [![Dependency Status](https://gemnasium.com/readyproject/fishbowl.png)](https://gemnasium.com/readyproject/fishbowl)
8
-
9
5
  ## Requirements
10
6
 
11
7
  A Ruby 1.9 compatible interpreter
@@ -26,7 +22,31 @@ Or install it yourself as:
26
22
 
27
23
  ## Usage
28
24
 
29
- TODO: Write usage instructions here
25
+ Add this to your env.rb file or as an initializer
26
+
27
+ ```ruby
28
+ Fishbowl.configure do |config|
29
+ config.username = "joe"
30
+ config.password = "joes_password"
31
+ config.host = "999.888.77.666"
32
+ config.app_id = "1234"
33
+ config.app_name = "Fishbowl Ruby Gem"
34
+ config.app_description = "Fishbowl Ruby Gem"
35
+ config.debug = true
36
+ end
37
+ ```
38
+
39
+ Now you are setup to make API calls in your application code
40
+
41
+ ```ruby
42
+ Fishbowl::Connection.connect
43
+ Fishbowl::Connection.login
44
+ carriers = Fishbowl::Requests.get_carrier_list
45
+ ```
46
+
47
+ The 'connect' method establishes the connection socket to the server, the 'login' method authenticates the connection to the server using a username and password.
48
+
49
+ Once the login method is successful (The Fishbowl API responds with statusCode=1000 for successful requests, see a [complete list](../master/lib/status_codes.yml) of status codes)
30
50
 
31
51
  ## Contributing
32
52
 
data/fishbowl.gemspec CHANGED
@@ -6,16 +6,16 @@ require 'fishbowl/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "fishbowl"
8
8
  gem.version = Fishbowl::VERSION
9
- gem.authors = ["James Thompson"]
10
- gem.email = ["james@plainprograms.com"]
11
- gem.description = %q{Provides an interface to the Fishbowl Inventory API.}
9
+ gem.authors = ["James Thompson, Simeon Berns"]
10
+ gem.email = ["james@plainprograms.com, simeonberns@gmail.com"]
11
+ gem.description = %q{Provides an interface to the Fishbowl Inventory API}
12
12
  gem.summary = %q{Fishbowl Inventory API}
13
- gem.homepage = "https://github.com/readyproject/fishbowl"
13
+ gem.homepage = "https://github.com/zion/fishbowl"
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
16
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
19
 
20
- gem.add_dependency 'nokogiri', '~> 1.5.5'
20
+ gem.add_dependency 'nokogiri', '>= 1.8.5'
21
21
  end
@@ -0,0 +1,9 @@
1
+ module Fishbowl
2
+ class Configuration
3
+ attr_accessor :username, :password, :host, :port, :app_id, :app_name, :app_description, :debug
4
+
5
+ def initialize
6
+ @debug = false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,100 @@
1
+ require 'nokogiri'
2
+
3
+ module Fishbowl
4
+ class Connection
5
+ include Singleton
6
+
7
+ def self.connect()
8
+ raise Fishbowl::Errors::MissingHost if Fishbowl.configuration.host.nil?
9
+
10
+ @host = Fishbowl.configuration.host
11
+ @port = Fishbowl.configuration.port.nil? ? 28192 : Fishbowl.configuration.port
12
+
13
+ @connection = TCPSocket.new @host, @port
14
+
15
+ self.instance
16
+ end
17
+
18
+ def self.login()
19
+ raise Fishbowl::Errors::ConnectionNotEstablished if @connection.nil?
20
+ raise Fishbowl::Errors::MissingUsername if Fishbowl.configuration.host.nil?
21
+ raise Fishbowl::Errors::MissingPassword if Fishbowl.configuration.host.nil?
22
+
23
+ @username = Fishbowl.configuration.username
24
+ @password = Fishbowl.configuration.password
25
+
26
+ code, _ = Fishbowl::Objects::BaseObject.new.send_request(login_request)
27
+ Fishbowl::Errors.confirm_success_or_raise(code)
28
+
29
+ raise "Login failed" unless code.eql? "1000"
30
+
31
+ self.instance
32
+ end
33
+
34
+ def self.host
35
+ @host
36
+ end
37
+
38
+ def self.port
39
+ @port
40
+ end
41
+
42
+ def self.username
43
+ @username
44
+ end
45
+
46
+ def self.password
47
+ @password
48
+ end
49
+
50
+ def self.send(request, expected_response = 'FbiMsgsRs')
51
+ puts 'opening connection...' if Fishbowl.configuration.debug.eql? true
52
+ puts request if Fishbowl.configuration.debug.eql? true
53
+ puts 'waiting for response...' if Fishbowl.configuration.debug.eql? true
54
+ write(request)
55
+ get_response(expected_response)
56
+ end
57
+
58
+ def self.close
59
+ @connection.close
60
+ @connection = nil
61
+ end
62
+
63
+ private
64
+
65
+ def self.login_request
66
+ Nokogiri::XML::Builder.new do |xml|
67
+ xml.request {
68
+ xml.LoginRq {
69
+ xml.IAID Fishbowl.configuration.app_id
70
+ xml.IAName Fishbowl.configuration.app_name
71
+ xml.IADescription Fishbowl.configuration.app_description
72
+ xml.UserName Fishbowl.configuration.username
73
+ xml.UserPassword encoded_password
74
+ }
75
+ }
76
+ end
77
+ end
78
+
79
+ def self.encoded_password
80
+ Digest::MD5.base64digest(@password)
81
+ end
82
+
83
+ def self.write(request)
84
+ body = request.to_xml
85
+ size = [body.size].pack("L>")
86
+ @connection.write(size)
87
+ @connection.write(body)
88
+ end
89
+
90
+ def self.get_response(expectation)
91
+ puts "reading response" if Fishbowl.configuration.debug.eql? true
92
+ length = @connection.read(4).unpack('L>').join('').to_i
93
+ response = Nokogiri::XML.parse(@connection.read(length))
94
+ puts response if Fishbowl.configuration.debug.eql? true
95
+ status_code = response.xpath("/FbiXml/FbiMsgsRs").attr("statusCode").value
96
+ [status_code, response]
97
+ end
98
+
99
+ end
100
+ end
@@ -1,12 +1,22 @@
1
- module Fishbowl::Errors
2
- class ConnectionNotEstablished < RuntimeError; end;
3
- class MissingHost < ArgumentError; end;
4
- class MissingUsername < ArgumentError; end;
5
- class MissingPassword < ArgumentError; end;
1
+ require 'yaml'
6
2
 
7
- class StatusError < RuntimeError; end;
3
+ module Fishbowl
4
+ module Errors
5
+ class ConnectionNotEstablished < RuntimeError; end;
6
+ class MissingHost < ArgumentError; end;
7
+ class MissingUsername < ArgumentError; end;
8
+ class MissingPassword < ArgumentError; end;
9
+ class EmptyResponse < RuntimeError; end;
8
10
 
9
- def self.confirm_success_or_raise(code, message)
10
- code.to_i == 1000 ? true : raise(StatusError, message)
11
+ class StatusError < RuntimeError; end;
12
+
13
+ def self.confirm_success_or_raise(code)
14
+ (code.to_i.eql? 1000) ? true : raise(StatusError, get_status(code))
15
+ end
16
+
17
+ def self.get_status(code)
18
+ status_codes = YAML.load_file('./lib/status_codes.yml')['codes']
19
+ status_codes[code]['message']
20
+ end
11
21
  end
12
22
  end
@@ -0,0 +1,15 @@
1
+ class String
2
+ def underscore
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr("-", "_").
7
+ downcase
8
+ end
9
+ end
10
+
11
+ class Hash
12
+ def symbolize_keys
13
+ self.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
14
+ end
15
+ end
@@ -1,19 +1,15 @@
1
1
  module Fishbowl::Objects
2
2
  class Account < BaseObject
3
- def self.get_list
4
- self.new.send_request("GetAccountListRq")
5
- end
3
+ attr_reader :name, :accounting_id, :account_type, :balance
6
4
 
7
- def self.get_balance(account)
8
- builder = Nokogiri::XML::Builder.new do |xml|
9
- xml.request {
10
- xml.GetAccountBalanceRq {
11
- xml.Account (account.is_a?(Account) ? account.name : account)
12
- }
13
- }
14
- end
5
+ def self.attributes
6
+ %w{Name AccountingID AccountType Balance}
7
+ end
15
8
 
16
- self.new.send_request(builder, true)
9
+ def initialize(account_xml)
10
+ @xml = account_xml
11
+ parse_attributes
12
+ self
17
13
  end
18
14
  end
19
15
  end
@@ -0,0 +1,86 @@
1
+ module Fishbowl::Objects
2
+ class Address < BaseObject
3
+ attr_reader :db_id, :temp_account, :name, :attn, :street, :city, :zip
4
+ attr_reader :location_group_id, :default, :residential, :type, :state
5
+ attr_reader :country, :address_information_list
6
+
7
+ def self.attributes
8
+ %w{ID Name Attn Street City Zip LocationGroupID Default Residential Type}
9
+ end
10
+
11
+ def initialize(address_xml)
12
+ @xml = address_xml
13
+ parse_attributes
14
+
15
+ @temp_account
16
+ @state = get_state(address_xml)
17
+ @country = get_country(address_xml)
18
+ @address_information_list = get_address_information(address_xml)
19
+
20
+ self
21
+ end
22
+
23
+ private
24
+
25
+ def get_state(address_xml)
26
+ State.new(address_xml.xpath("State"))
27
+ end
28
+
29
+ def get_country(address_xml)
30
+ Country.new(address_xml.xpath("Country"))
31
+ end
32
+
33
+ def get_address_information(address_xml)
34
+ results = []
35
+
36
+ address_xml.xpath("AddressInformationList").each do |address_info_xml|
37
+ results << AddressInformation.new(address_info_xml)
38
+ end
39
+
40
+ results
41
+ end
42
+
43
+ end
44
+
45
+ class State < BaseObject
46
+ attr_reader :db_id, :name, :code, :country_id
47
+
48
+ def self.attributes
49
+ %w{ID Name Code CountryID}
50
+ end
51
+
52
+ def initialize(state_xml)
53
+ @xml = state_xml
54
+ parse_attributes
55
+ self
56
+ end
57
+ end
58
+
59
+ class Country < BaseObject
60
+ attr_reader :db_id, :name, :code
61
+
62
+ def self.attributes
63
+ %w{ID Name Code}
64
+ end
65
+
66
+ def initialize(country_xml)
67
+ @xml = country_xml
68
+ parse_attributes
69
+ self
70
+ end
71
+ end
72
+
73
+ class AddressInformation < BaseObject
74
+ attr_reader :db_id, :name, :data, :default, :type
75
+
76
+ def self.attributes
77
+ %w{ID Name Data Default Type}
78
+ end
79
+
80
+ def initialize(address_info_xml)
81
+ @xml = address_info_xml
82
+ parse_attributes
83
+ self
84
+ end
85
+ end
86
+ end
@@ -1,28 +1,61 @@
1
1
  module Fishbowl::Objects
2
2
  class BaseObject
3
- attr_accessor :ticket
3
+ @@ticket = nil
4
+ def send_request(request, expected_response = 'FbiMsgsRs')
5
+ code, response = Fishbowl::Connection.send(build_request(request), expected_response)
6
+ Fishbowl::Errors.confirm_success_or_raise(code)
7
+ puts "Response successful" if Fishbowl.configuration.debug.eql? true
8
+ @@ticket = response.xpath("/FbiXml/Ticket/Key").text
9
+ [code, response]
10
+ end
11
+
12
+ protected
13
+
14
+ def self.attributes
15
+ %w{ID}
16
+ end
4
17
 
5
- def send_request(request, fragment = false)
6
- Fishbowl::Connection.send(build_request(request, fragment))
18
+ def parse_attributes
19
+ self.class.attributes.each do |field|
20
+ field = field.to_s
21
+
22
+ if field == 'ID'
23
+ instance_var = 'db_id'
24
+ elsif field.match(/^[A-Z]{3,}$/)
25
+ instance_var = field.downcase
26
+ else
27
+ instance_var = field.gsub(/ID$/, 'Id').underscore
28
+ end
29
+
30
+ instance_var = '@' + instance_var
31
+ value = @xml.children.nil? ? nil : @xml.children.text
32
+ instance_variable_set(instance_var, value)
33
+ end
7
34
  end
8
35
 
9
36
  private
10
37
 
11
- def build_request(request, fragment = false)
12
- Nokogiri::XML::Builder.new do |xml|
38
+ def build_request(request)
39
+ new_req = Nokogiri::XML::Builder.new do |xml|
13
40
  xml.FbiXml {
14
- if @ticket.nil?
41
+ if @@ticket.nil?
15
42
  xml.Ticket
16
43
  else
17
- xml.Ticket @ticket
44
+ xml.Ticket {
45
+ xml.Key @@ticket
46
+ }
18
47
  end
19
48
 
20
49
  xml.FbiMsgsRq {
21
- xml << request.doc.xpath("request/*").to_xml if fragment
22
- xml.send(request.to_s) unless fragment
50
+ if request.respond_to?(:to_xml)
51
+ xml << request.doc.xpath("request/*").to_xml
52
+ else
53
+ xml.send(request.to_s)
54
+ end
23
55
  }
24
56
  }
25
57
  end
58
+ Nokogiri::XML(new_req.to_xml).root
26
59
  end
27
60
 
28
61
  end
@@ -0,0 +1,15 @@
1
+ module Fishbowl::Objects
2
+ class Carrier < BaseObject
3
+ attr_accessor :name
4
+
5
+ def self.attributes
6
+ %w{Name}
7
+ end
8
+
9
+ def initialize(carrier_xml)
10
+ @xml = carrier_xml
11
+ parse_attributes
12
+ self
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,54 @@
1
+ module Fishbowl::Objects
2
+ class Carton < BaseObject
3
+ attr_reader :db_id, :ship_id, :carton_num, :tracking_num, :freight_weight, :freight_amount, :shipping_items
4
+
5
+ def self.attributes
6
+ %w{ID ShipID CartonNum TrackingNum FreightWeight FreightAmount}
7
+ end
8
+
9
+ def initialize(carton_xml)
10
+ @xml = carton_xml
11
+ parse_attributes
12
+
13
+ @shipping_items = get_shipping_items
14
+
15
+ self
16
+ end
17
+
18
+ private
19
+
20
+ def get_shipping_items
21
+ results = []
22
+
23
+ @xml.xpath('ShippingItems/ShippingItem').each do |xml|
24
+ results << Fishbowl::Objects::ShippingItem.new(xml)
25
+ end
26
+
27
+ results
28
+ end
29
+ end
30
+
31
+ class ShippingItem < BaseObject
32
+ attr_reader :ship_item_id, :product_number, :product_description
33
+ attr_reader :qty_shipped, :cost, :sku, :upc, :order_item_id
34
+ attr_reader :order_line_item, :carton_name, :carton_id, :tag_num, :weight
35
+ attr_reader :display_weight, :tracking, :uom, :weight_uom, :display_weight_uom
36
+
37
+ def self.attributes
38
+ %w{ShipItemID ProductNumber ProductDescription QtyShipped Cost SKU UPC
39
+ OrderItemID OrderLineItem CartonName CartonID TagNum Weight
40
+ DisplayWeight Tracking}
41
+ end
42
+
43
+ def initialize(shipping_item_xml)
44
+ @xml = shipping_item_xml
45
+ parse_attributes
46
+
47
+ @uom = Fishbowl::Objects::UOM.new(@xml.xpath("UOM"))
48
+ @weight_uom = Fishbowl::Objects::UOM.new(@xml.xpath("WeightUOM/UOM"))
49
+ @display_weight_uom = Fishbowl::Objects::UOM.new(@xml.xpath("DisplayWeightUOM/UOM"))
50
+
51
+ self
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,47 @@
1
+ module Fishbowl::Objects
2
+ class UOM < BaseObject
3
+ attr_accessor :uomid, :name, :code, :integral, :active, :type
4
+ attr_accessor :uom_conversions
5
+
6
+ def self.attributes
7
+ %w{UOMID Name Code Integral Active Type}
8
+ end
9
+
10
+ def initialize(uom_xml)
11
+ @xml = uom_xml
12
+ parse_attributes
13
+
14
+ @uom_conversions = get_uom_conversions
15
+
16
+ self
17
+ end
18
+
19
+ private
20
+
21
+ def get_uom_conversions
22
+ results = []
23
+
24
+ @xml.xpath("//UOMConversions/UOMConversion").each do |xml|
25
+ results << Fishbowl::Objects::UOMConversion.new(xml)
26
+ end
27
+
28
+ results
29
+ end
30
+
31
+ end
32
+
33
+ class UOMConversion < BaseObject
34
+ attr_accessor :main_uom_id, :to_uom_id, :to_uom_code, :conversion_multiply
35
+ attr_accessor :conversion_factor, :to_uom_is_integral
36
+
37
+ def self.attributes
38
+ %w{MainUOMID ToUOMID ToUOMCode ConversionMultiply ConversionFactor ToUOMIsIntegral}
39
+ end
40
+
41
+ def initialize(uom_conversion_xml)
42
+ @xml = uom_conversion_xml
43
+ parse_attributes
44
+ self
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,15 @@
1
+ module Fishbowl::Objects
2
+ class User < BaseObject
3
+ attr_accessor :db_id, :user_name, :first_name, :last_name, :initials, :active
4
+
5
+ def self.attributes
6
+ %w{ID UserName FirstName LastName Initials Active}
7
+ end
8
+
9
+ def initialize(user_xml)
10
+ @xml = user_xml
11
+ parse_attributes
12
+ self
13
+ end
14
+ end
15
+ end
@@ -3,4 +3,9 @@ module Fishbowl
3
3
  end
4
4
 
5
5
  require 'fishbowl/objects/base_object'
6
+ require 'fishbowl/objects/uom'
6
7
  require 'fishbowl/objects/account'
8
+ require 'fishbowl/objects/address'
9
+ require 'fishbowl/objects/carton'
10
+ require 'fishbowl/objects/user'
11
+ require 'fishbowl/objects/carrier'
@@ -0,0 +1,34 @@
1
+ module Fishbowl::Requests
2
+ def self.add_inventory(options = {})
3
+ options = options.symbolize_keys
4
+
5
+ %w{part_number quantity uom_id cost location_tag_number tag_number}.each do |required_field|
6
+ raise ArgumentError if options[required_field.to_sym].nil?
7
+ end
8
+
9
+ raise ArgumentError unless options[:tracking].nil? || options[:tracking].is_a?(Fishbowl::Object::Tracking)
10
+
11
+ request = format_add_inventory_request(options)
12
+ Fishbowl::Objects::BaseObject.new.send_request(request, 'AddInventoryRs')
13
+ end
14
+
15
+ private
16
+
17
+ def self.format_add_inventory_request(options)
18
+ Nokogiri::XML::Builder.new do |xml|
19
+ xml.request {
20
+ xml.AddInventoryRq {
21
+ xml.PartNum options[:part_number]
22
+ xml.Quantity options[:quantity]
23
+ xml.UOMID options[:uom_id]
24
+ xml.Cost options[:cost]
25
+ xml.Note options[:note] unless options[:note].nil?
26
+ xml.Tracking options[:tracking] unless options[:tracking].nil?
27
+ xml.LocationTagNum options[:location_tag_number]
28
+ xml.TagNum options[:tag_number]
29
+ }
30
+ }
31
+ end
32
+ end
33
+
34
+ end