fishbowl 0.0.2 → 0.0.3

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 (99) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/Gemfile +1 -8
  4. data/fishbowl.gemspec +4 -4
  5. data/lib/fishbowl.rb +9 -90
  6. data/lib/fishbowl/configuration.rb +9 -0
  7. data/lib/fishbowl/connection.rb +99 -0
  8. data/lib/fishbowl/errors.rb +9 -2
  9. data/lib/fishbowl/objects/account.rb +0 -26
  10. data/lib/fishbowl/objects/base_object.rb +25 -8
  11. data/lib/fishbowl/requests.rb +3 -4
  12. data/lib/fishbowl/requests/get_account_balance.rb +15 -0
  13. data/lib/fishbowl/requests/get_account_list.rb +13 -0
  14. data/lib/fishbowl/requests/get_carrier_list.rb +3 -2
  15. data/lib/fishbowl/requests/get_customer_list.rb +12 -0
  16. data/lib/fishbowl/requests/get_customer_name_list.rb +12 -0
  17. data/lib/fishbowl/requests/get_export_list.rb +12 -0
  18. data/lib/fishbowl/requests/get_import_list.rb +12 -0
  19. data/lib/fishbowl/requests/get_location_group_list.rb +12 -0
  20. data/lib/fishbowl/requests/get_location_list.rb +12 -0
  21. data/lib/fishbowl/requests/get_uom_list.rb +12 -0
  22. data/lib/fishbowl/requests/get_vendor_list.rb +12 -0
  23. data/lib/fishbowl/requests/get_vendor_name_list.rb +12 -0
  24. data/lib/fishbowl/requests/get_work_order_list.rb +12 -0
  25. data/lib/fishbowl/requests/void_sales_order.rb +18 -0
  26. data/lib/fishbowl/version.rb +1 -1
  27. data/lib/status_codes.yml +183 -0
  28. data/spec/objects/account_spec.rb +0 -41
  29. data/spec/requests/calculate_sales_order_spec.rb +48 -0
  30. data/spec/requests/close_short_sales_order_spec.rb +45 -0
  31. data/spec/requests/cycle_count_spec.rb +49 -0
  32. data/spec/requests/delete_sales_order_spec.rb +45 -0
  33. data/spec/requests/export_spec.rb +45 -0
  34. data/spec/requests/get_account_balance_spec.rb +52 -0
  35. data/spec/requests/get_account_list_spec.rb +51 -0
  36. data/spec/requests/get_customer_list_spec.rb +51 -0
  37. data/spec/requests/get_customer_name_list_spec.rb +45 -0
  38. data/spec/requests/get_customer_spec.rb +45 -0
  39. data/spec/requests/get_export_list_spec.rb +45 -0
  40. data/spec/requests/get_import_list_spec.rb +45 -0
  41. data/spec/requests/get_inventory_quantity_spec.rb +65 -0
  42. data/spec/requests/get_light_part_list_spec.rb +51 -0
  43. data/spec/requests/get_location_group_list_spec.rb +45 -0
  44. data/spec/requests/get_location_list_spec.rb +45 -0
  45. data/spec/requests/get_next_number_spec.rb +45 -0
  46. data/spec/requests/get_part_cost_spec.rb +45 -0
  47. data/spec/requests/get_part_information_spec.rb +45 -0
  48. data/spec/requests/get_part_list_spec.rb +65 -0
  49. data/spec/requests/get_pick_spec.rb +45 -0
  50. data/spec/requests/get_product_information_spec.rb +46 -0
  51. data/spec/requests/get_purchase_order_list_spec.rb +45 -0
  52. data/spec/requests/get_receipt_spec.rb +49 -0
  53. data/spec/requests/get_receiving_list_spec.rb +49 -0
  54. data/spec/requests/get_sales_order_list_spec.rb +49 -0
  55. data/spec/requests/get_ship_list_spec.rb +49 -0
  56. data/spec/requests/get_ship_now_list_spec.rb +48 -0
  57. data/spec/requests/get_shipment_spec.rb +45 -0
  58. data/spec/requests/get_system_property_spec.rb +45 -0
  59. data/spec/requests/get_total_inventory_spec.rb +46 -0
  60. data/spec/requests/get_transfer_order_list_spec.rb +45 -0
  61. data/spec/requests/get_uom_list_spec.rb +45 -0
  62. data/spec/requests/get_user_property_spec.rb +45 -0
  63. data/spec/requests/get_vendor_list_spec.rb +45 -0
  64. data/spec/requests/get_vendor_name_list_spec.rb +45 -0
  65. data/spec/requests/get_vendor_spec.rb +48 -0
  66. data/spec/requests/get_work_order_list_spec.rb +45 -0
  67. data/spec/requests/get_work_order_spec.rb +45 -0
  68. data/spec/requests/import_spec.rb +49 -0
  69. data/spec/requests/issues_sales_order_spec.rb +45 -0
  70. data/spec/requests/load_sales_order_spec.rb +45 -0
  71. data/spec/requests/load_transfer_order_spec.rb +45 -0
  72. data/spec/requests/location_query_spec.rb +49 -0
  73. data/spec/requests/make_payment_spec.rb +50 -0
  74. data/spec/requests/move_spec.rb +49 -0
  75. data/spec/requests/part_query_spec.rb +46 -0
  76. data/spec/requests/pick_query_spec.rb +49 -0
  77. data/spec/requests/print_report_spec.rb +48 -0
  78. data/spec/requests/product_query_spec.rb +46 -0
  79. data/spec/requests/quick_ship_spec.rb +45 -0
  80. data/spec/requests/quickbooks_export_spec.rb +43 -0
  81. data/spec/requests/save_customer_spec.rb +48 -0
  82. data/spec/requests/save_discount_spec.rb +48 -0
  83. data/spec/requests/save_pick_spec.rb +48 -0
  84. data/spec/requests/save_purchase_order_spec.rb +48 -0
  85. data/spec/requests/save_receipt_spec.rb +48 -0
  86. data/spec/requests/save_report_spec.rb +49 -0
  87. data/spec/requests/save_sales_order_spec.rb +48 -0
  88. data/spec/requests/save_shipment_spec.rb +48 -0
  89. data/spec/requests/save_tax_rate_spec.rb +48 -0
  90. data/spec/requests/save_transfer_order_spec.rb +48 -0
  91. data/spec/requests/save_upc_spec.rb +48 -0
  92. data/spec/requests/save_vendor_spec.rb +48 -0
  93. data/spec/requests/save_work_order_spec.rb +48 -0
  94. data/spec/requests/set_default_part_location_spec.rb +48 -0
  95. data/spec/requests/set_system_property_spec.rb +48 -0
  96. data/spec/requests/set_user_property_spec.rb +48 -0
  97. data/spec/requests/ship_spec.rb +48 -0
  98. data/spec/requests/void_sales_order_spec.rb +43 -0
  99. metadata +167 -21
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5de36e305db8f0ee23f26a5e54347bf31200326a
4
+ data.tar.gz: 9c43fd84b6929bd7013cbb1f9080247d243370fd
5
+ SHA512:
6
+ metadata.gz: 1e234e842add2ce0df6a7204b792a16033f94f6a728a30768993512defbb76bbcba66b1cb85ec099245e5b2ecec82b72918462e3e6b711d406e1dce2b7b9e992
7
+ data.tar.gz: 3a54c1b6b70b52c8df8654a89d5d143716b77e065496ef3c61b8d42503c5457e0df90adda68744ff3554053472dfd4a91b06ddbeeb3d2760fe6429e60d95024b
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .idea/
data/Gemfile CHANGED
@@ -4,15 +4,8 @@ gemspec
4
4
 
5
5
  gem 'rake'
6
6
  gem 'rspec'
7
-
8
7
  gem 'equivalent-xml'
9
8
 
10
9
  group :localtest do
11
- gem 'simplecov'
12
- gem 'guard'
13
- gem 'guard-rspec'
14
- gem 'growl'
15
- gem 'rb-fsevent'
16
- gem 'spork'
17
- gem 'guard-spork'
10
+ gem 'pry'
18
11
  end
@@ -6,11 +6,11 @@ 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/flameofzion/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) }
@@ -10,99 +10,18 @@ require 'fishbowl/version'
10
10
  require 'fishbowl/errors'
11
11
  require 'fishbowl/requests'
12
12
  require 'fishbowl/objects'
13
+ require 'fishbowl/connection'
14
+ require 'fishbowl/configuration'
13
15
 
14
16
  module Fishbowl # :nodoc:
15
- class Connection
16
- include Singleton
17
17
 
18
- def self.connect(options = {})
19
- raise Fishbowl::Errors::MissingHost if options[:host].nil?
20
-
21
- @host = options[:host]
22
- @port = options[:port].nil? ? 28192 : options[:port]
23
-
24
- @connection = TCPSocket.new @host, @port
25
-
26
- self.instance
27
- end
28
-
29
- def self.login(options = {})
30
- raise Fishbowl::Errors::ConnectionNotEstablished if @connection.nil?
31
- raise Fishbowl::Errors::MissingUsername if options[:username].nil?
32
- raise Fishbowl::Errors::MissingPassword if options[:password].nil?
33
-
34
- @username, @password = options[:username], options[:password]
35
-
36
- code, message, _ = Fishbowl::Objects::BaseObject.new.send_request(login_request, 'LoginRs')
37
-
38
- Fishbowl::Errors.confirm_success_or_raise(code, message)
39
-
40
- self.instance
41
- end
42
-
43
- def self.host
44
- @host
45
- end
46
-
47
- def self.port
48
- @port
49
- end
50
-
51
- def self.username
52
- @username
53
- end
54
-
55
- def self.password
56
- @password
57
- end
58
-
59
- def self.send(request, expected_response = 'FbiMsgRs')
60
- write(request)
61
- get_response(expected_response)
62
- end
63
-
64
- def self.close
65
- @connection.close
66
- @connection = nil
67
- end
68
-
69
- private
70
-
71
- def self.login_request
72
- Nokogiri::XML::Builder.new do |xml|
73
- xml.request {
74
- xml.LoginRq {
75
- xml.IAID "fishbowl-ruby"
76
- xml.IAName "Fishbowl Ruby Gem"
77
- xml.IADescription "Fishbowl Ruby Gem"
78
- xml.UserName @username
79
- xml.UserPassword encoded_password
80
- }
81
- }
82
- end
83
- end
84
-
85
- def self.encoded_password
86
- Base64.encode64(@password)
87
- end
88
-
89
- def self.write(request)
90
- body = request.to_xml
91
- size = [body.size].pack("L>")
92
-
93
- @connection.write(size)
94
- @connection.write(body)
95
- end
96
-
97
- def self.get_response(expectation)
98
- length = @connection.recv(3).unpack('L>').join('').to_i
99
- response = Nokogiri::XML.parse(@connection.recv(length))
100
-
101
- status_code = response.xpath("//#{expectation}/@statusCode").first.value
102
- status_message = response.xpath("//#{expectation}/@statusMessage").first.value
103
-
104
- [status_code, status_message, response]
105
- end
18
+ class << self
19
+ attr_accessor :configuration
20
+ end
106
21
 
22
+ def self.configure
23
+ self.configuration ||= Configuration.new
24
+ yield(configuration)
107
25
  end
26
+
108
27
  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,99 @@
1
+ module Fishbowl
2
+ class Connection
3
+ include Singleton
4
+
5
+ def self.connect()
6
+ raise Fishbowl::Errors::MissingHost if Fishbowl.configuration.host.nil?
7
+
8
+ @host = Fishbowl.configuration.host
9
+ @port = Fishbowl.configuration.port.nil? ? 28192 : Fishbowl.configuration.port
10
+
11
+ @connection = TCPSocket.new @host, @port
12
+
13
+ self.instance
14
+ end
15
+
16
+ def self.login()
17
+ raise Fishbowl::Errors::ConnectionNotEstablished if @connection.nil?
18
+ raise Fishbowl::Errors::MissingUsername if Fishbowl.configuration.host.nil?
19
+ raise Fishbowl::Errors::MissingPassword if Fishbowl.configuration.host.nil?
20
+
21
+ @username = Fishbowl.configuration.username
22
+ @password = Fishbowl.configuration.password
23
+
24
+ code, _ = Fishbowl::Objects::BaseObject.new.send_request(login_request)
25
+ Fishbowl::Errors.confirm_success_or_raise(code)
26
+
27
+ self.instance
28
+ end
29
+
30
+ def self.host
31
+ @host
32
+ end
33
+
34
+ def self.port
35
+ @port
36
+ end
37
+
38
+ def self.username
39
+ @username
40
+ end
41
+
42
+ def self.password
43
+ @password
44
+ end
45
+
46
+ def self.send(request, expected_response = 'FbiMsgsRs')
47
+ puts 'opening connection...' if Fishbowl.configuration.debug.eql? true
48
+ puts request if Fishbowl.configuration.debug.eql? true
49
+ puts 'waiting for response...' if Fishbowl.configuration.debug.eql? true
50
+ write(request)
51
+ get_response(expected_response)
52
+ end
53
+
54
+ def self.close
55
+ @connection.close
56
+ @connection = nil
57
+ end
58
+
59
+ private
60
+
61
+ def self.login_request
62
+ Nokogiri::XML::Builder.new do |xml|
63
+ xml.request {
64
+ xml.LoginRq {
65
+ xml.IAID Fishbowl.configuration.app_id
66
+ xml.IAName Fishbowl.configuration.app_name
67
+ xml.IADescription Fishbowl.configuration.app_description
68
+ xml.UserName Fishbowl.configuration.username
69
+ xml.UserPassword encoded_password
70
+ }
71
+ }
72
+ end
73
+ end
74
+
75
+ def self.encoded_password
76
+ Digest::MD5.base64digest(@password)
77
+ end
78
+
79
+ def self.write(request)
80
+ body = request.to_xml
81
+ size = [body.size].pack("L>")
82
+ @connection.write(size)
83
+ @connection.write(body)
84
+ end
85
+
86
+ def self.get_response(expectation)
87
+ length = @connection.recv(4).unpack('L>').join('').to_i
88
+ response = Nokogiri::XML.parse(@connection.recv(length))
89
+
90
+ puts "Looking for '#{expectation}' node in: " if Fishbowl.configuration.debug.eql? true
91
+ puts response if Fishbowl.configuration.debug.eql? true
92
+
93
+ status_code = response.xpath("/FbiXml/#{expectation}").attr("statusCode").value
94
+
95
+ [status_code, response]
96
+ end
97
+
98
+ end
99
+ end
@@ -1,3 +1,5 @@
1
+ require 'yaml'
2
+
1
3
  module Fishbowl::Errors
2
4
  class ConnectionNotEstablished < RuntimeError; end;
3
5
  class MissingHost < ArgumentError; end;
@@ -6,7 +8,12 @@ module Fishbowl::Errors
6
8
 
7
9
  class StatusError < RuntimeError; end;
8
10
 
9
- def self.confirm_success_or_raise(code, message)
10
- code.to_i == 1000 ? true : raise(StatusError, message)
11
+ def self.confirm_success_or_raise(code)
12
+ code.to_i == 1000 ? true : raise(StatusError, get_status(code.to_i))
13
+ end
14
+
15
+ def self.get_status(code)
16
+ status_codes = YAML.load_file('./lib/status_codes.yml')['codes']
17
+ status_codes[code]['message']
11
18
  end
12
19
  end
@@ -11,31 +11,5 @@ module Fishbowl::Objects
11
11
  parse_attributes
12
12
  self
13
13
  end
14
-
15
- def self.get_list
16
- _, _, response = BaseObject.new.send_request("GetAccountListRq", "GetAccountListRs")
17
-
18
- results = []
19
-
20
- response.xpath("//Account").each do |account_xml|
21
- results << Account.new(account_xml)
22
- end
23
-
24
- results
25
- end
26
-
27
- def self.get_balance(account)
28
- builder = Nokogiri::XML::Builder.new do |xml|
29
- xml.request {
30
- xml.GetAccountBalanceRq {
31
- xml.Account (account.is_a?(Account) ? account.name : account)
32
- }
33
- }
34
- end
35
-
36
- _, _, response = BaseObject.new.send_request(builder, "GetAccountBalanceRs")
37
-
38
- response.xpath("//Account/Balance").first.inner_text
39
- end
40
14
  end
41
15
  end
@@ -1,11 +1,25 @@
1
1
  module Fishbowl::Objects
2
2
  class BaseObject
3
- attr_accessor :ticket
3
+ @@ticket = nil
4
4
 
5
- def send_request(request, expected_response = 'FbiMsgRs')
6
- code, message, response = Fishbowl::Connection.send(build_request(request), expected_response)
7
- Fishbowl::Errors.confirm_success_or_raise(code, message)
8
- [code, message, response]
5
+ def send_request(request, expected_response = 'FbiMsgsRs')
6
+ result = nil
7
+ 5.times do |i|
8
+ puts "REQUEST ATTEMPT: #{i}" if Fishbowl.configuration.debug.eql? true
9
+ begin
10
+ code, response = Fishbowl::Connection.send(build_request(request), expected_response)
11
+ raise "No response" if response.nil?
12
+ Fishbowl::Errors.confirm_success_or_raise(code)
13
+ @@ticket = response.css("FbiXml Ticket Key").text
14
+ puts 'RESPONSE SUCCEEDED' if Fishbowl.configuration.debug.eql? true
15
+ result = [code, nil, response]
16
+ break
17
+ rescue NoMethodError => nme
18
+ puts 'FAILED TO GET RESPONSE' if Fishbowl.configuration.debug.eql? true
19
+ sleep 1
20
+ end
21
+ end
22
+ return result
9
23
  end
10
24
 
11
25
  protected
@@ -35,12 +49,14 @@ module Fishbowl::Objects
35
49
  private
36
50
 
37
51
  def build_request(request)
38
- Nokogiri::XML::Builder.new do |xml|
52
+ new_req = Nokogiri::XML::Builder.new do |xml|
39
53
  xml.FbiXml {
40
- if @ticket.nil?
54
+ if @@ticket.nil?
41
55
  xml.Ticket
42
56
  else
43
- xml.Ticket @ticket
57
+ xml.Ticket {
58
+ xml.Key @@ticket
59
+ }
44
60
  end
45
61
 
46
62
  xml.FbiMsgsRq {
@@ -52,6 +68,7 @@ module Fishbowl::Objects
52
68
  }
53
69
  }
54
70
  end
71
+ Nokogiri::XML(new_req.to_xml).root
55
72
  end
56
73
 
57
74
  end
@@ -1,6 +1,5 @@
1
1
  module Fishbowl; module Requests; end; end
2
2
 
3
- require 'fishbowl/requests/add_inventory'
4
- require 'fishbowl/requests/add_sales_order_item'
5
- require 'fishbowl/requests/adjust_inventory'
6
- require 'fishbowl/requests/get_carrier_list'
3
+ Dir.glob(File.join(File.expand_path("../requests/", __FILE__), "**.rb")).each do |file|
4
+ require file
5
+ end
@@ -0,0 +1,15 @@
1
+ module Fishbowl::Requests
2
+ def self.get_account_balance(account_name)
3
+ builder = Nokogiri::XML::Builder.new do |xml|
4
+ xml.request {
5
+ xml.GetAccountBalanceRq {
6
+ xml.Account (account.is_a?(Account) ? account.name : account)
7
+ }
8
+ }
9
+ end
10
+
11
+ _, _, response = Fishbowl::Objects::BaseObject.new.send_request(builder, "GetAccountBalanceRs")
12
+
13
+ response.xpath("//Account/Balance").first.inner_text
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module Fishbowl::Requests
2
+ def self.get_account_list
3
+ _, _, response = Fishbowl::Objects::BaseObject.new.send_request('GetAccountListRq', 'GetAccountListRs')
4
+
5
+ results = []
6
+
7
+ response.xpath("//Account").each do |account_xml|
8
+ results << Account.new(account_xml)
9
+ end
10
+
11
+ results
12
+ end
13
+ end
@@ -1,9 +1,10 @@
1
1
  module Fishbowl::Requests
2
2
  def self.get_carrier_list
3
- _, _, response = Fishbowl::Objects::BaseObject.new.send_request('CarrierListRq', 'CarrierListRs')
3
+ _, _, response = Fishbowl::Objects::BaseObject.new.send_request('CarrierListRq', 'FbiMsgsRs/CarrierListRs')
4
4
 
5
5
  results = []
6
- response.xpath("//Carrier").each do |carrier_xml|
6
+
7
+ response.xpath("//Carriers/Name").each do |carrier_xml|
7
8
  results << Fishbowl::Objects::Carrier.new(carrier_xml)
8
9
  end
9
10
 
@@ -0,0 +1,12 @@
1
+ module Fishbowl::Requests
2
+ def self.get_customer_list
3
+ _, _, response = Fishbowl::Objects::BaseObject.new.send_request('CustomerListRq', 'CustomerListRs')
4
+
5
+ results = []
6
+ response.xpath("//Customer").each do |customer_xml|
7
+ results << Fishbowl::Objects::Customer.new(customer_xml)
8
+ end
9
+
10
+ results
11
+ end
12
+ end