fishbowl 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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