fishbowl 0.0.1 → 0.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 (77) hide show
  1. data/.travis.yml +9 -4
  2. data/Gemfile +10 -1
  3. data/Guardfile +13 -0
  4. data/lib/fishbowl.rb +13 -15
  5. data/lib/fishbowl/ext.rb +15 -0
  6. data/lib/fishbowl/objects.rb +5 -0
  7. data/lib/fishbowl/objects/account.rb +24 -2
  8. data/lib/fishbowl/objects/address.rb +86 -0
  9. data/lib/fishbowl/objects/base_object.rb +34 -5
  10. data/lib/fishbowl/objects/carrier.rb +15 -0
  11. data/lib/fishbowl/objects/carton.rb +54 -0
  12. data/lib/fishbowl/objects/uom.rb +47 -0
  13. data/lib/fishbowl/objects/user.rb +15 -0
  14. data/lib/fishbowl/requests.rb +6 -0
  15. data/lib/fishbowl/requests/add_inventory.rb +34 -0
  16. data/lib/fishbowl/requests/add_sales_order_item.rb +42 -0
  17. data/lib/fishbowl/requests/adjust_inventory.rb +28 -0
  18. data/lib/fishbowl/requests/get_carrier_list.rb +12 -0
  19. data/lib/fishbowl/version.rb +1 -1
  20. data/spec/examples/account.xml +6 -0
  21. data/spec/examples/address.xml +30 -0
  22. data/spec/examples/carrier.xml +3 -0
  23. data/spec/examples/carton.xml +93 -0
  24. data/spec/examples/contact_information.xml +5 -0
  25. data/spec/examples/contacts.xml +7 -0
  26. data/spec/examples/credit_card.xml +10 -0
  27. data/spec/examples/customer.xml +54 -0
  28. data/spec/examples/location.xml +14 -0
  29. data/spec/examples/location_group.xml +5 -0
  30. data/spec/examples/location_group_string.xml +1 -0
  31. data/spec/examples/order_history.xml +8 -0
  32. data/spec/examples/part.xml +105 -0
  33. data/spec/examples/payment.xml +6 -0
  34. data/spec/examples/pick.xml +265 -0
  35. data/spec/examples/pick_item.xml +236 -0
  36. data/spec/examples/product.xml +159 -0
  37. data/spec/examples/purchase_order.xml +53 -0
  38. data/spec/examples/receipt.xml +146 -0
  39. data/spec/examples/report.xml +10 -0
  40. data/spec/examples/report_tree.xml +7 -0
  41. data/spec/examples/sales_order.xml +47 -0
  42. data/spec/examples/sales_order_item.xml +32 -0
  43. data/spec/examples/shipping.xml +127 -0
  44. data/spec/examples/tag.xml +28 -0
  45. data/spec/examples/tax_rate.xml +10 -0
  46. data/spec/examples/tracking.xml +14 -0
  47. data/spec/examples/tracking_item.xml +12 -0
  48. data/spec/examples/transfer_order.xml +257 -0
  49. data/spec/examples/transfer_order_item.xml +147 -0
  50. data/spec/examples/uom.xml +26 -0
  51. data/spec/examples/uom_conversion.xml +8 -0
  52. data/spec/examples/user.xml +8 -0
  53. data/spec/examples/vendor.xml +19 -0
  54. data/spec/examples/vendor_part_number.xml +3 -0
  55. data/spec/examples/work_order.xml +228 -0
  56. data/spec/examples/work_order_item.xml +172 -0
  57. data/spec/objects/account_spec.rb +53 -6
  58. data/spec/objects/address_information_spec.rb +18 -0
  59. data/spec/objects/address_spec.rb +36 -0
  60. data/spec/objects/base_object_spec.rb +67 -23
  61. data/spec/objects/carrier_spec.rb +15 -0
  62. data/spec/objects/carton_spec.rb +23 -0
  63. data/spec/objects/country_spec.rb +16 -0
  64. data/spec/objects/shipping_item_spec.rb +21 -0
  65. data/spec/objects/state_spec.rb +17 -0
  66. data/spec/objects/uom_conversion_spec.rb +20 -0
  67. data/spec/objects/uom_spec.rb +20 -0
  68. data/spec/objects/user_spec.rb +20 -0
  69. data/spec/requests/add_inventory_spec.rb +79 -0
  70. data/spec/requests/add_sales_order_item_spec.rb +85 -0
  71. data/spec/requests/adjust_inventory_spec.rb +62 -0
  72. data/spec/requests/get_carrier_list_spec.rb +54 -0
  73. data/spec/spec_helper.rb +41 -11
  74. data/spec/support/examples_loader.rb +5 -0
  75. data/spec/support/response_mocks.rb +27 -0
  76. metadata +122 -6
  77. data/spec/support/fake_login.rb +0 -15
@@ -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,15 @@ gemspec
4
4
 
5
5
  gem 'rake'
6
6
  gem 'rspec'
7
- gem 'simplecov'
8
7
 
9
8
  gem 'equivalent-xml'
9
+
10
+ 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'
18
+ end
@@ -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
@@ -4,8 +4,11 @@ require 'singleton'
4
4
 
5
5
  require 'nokogiri'
6
6
 
7
+ require 'fishbowl/ext'
8
+
7
9
  require 'fishbowl/version'
8
10
  require 'fishbowl/errors'
11
+ require 'fishbowl/requests'
9
12
  require 'fishbowl/objects'
10
13
 
11
14
  module Fishbowl # :nodoc:
@@ -30,9 +33,7 @@ module Fishbowl # :nodoc:
30
33
 
31
34
  @username, @password = options[:username], options[:password]
32
35
 
33
- Fishbowl::Objects::BaseObject.new.send_request(login_request, true)
34
-
35
- code, message, _ = get_response('LoginRs')
36
+ code, message, _ = Fishbowl::Objects::BaseObject.new.send_request(login_request, 'LoginRs')
36
37
 
37
38
  Fishbowl::Errors.confirm_success_or_raise(code, message)
38
39
 
@@ -55,8 +56,9 @@ module Fishbowl # :nodoc:
55
56
  @password
56
57
  end
57
58
 
58
- def self.send(request)
59
+ def self.send(request, expected_response = 'FbiMsgRs')
59
60
  write(request)
61
+ get_response(expected_response)
60
62
  end
61
63
 
62
64
  def self.close
@@ -64,15 +66,6 @@ module Fishbowl # :nodoc:
64
66
  @connection = nil
65
67
  end
66
68
 
67
- def self.get_response(expectation = 'FbiMsgRs')
68
- response = read
69
-
70
- status_code = response.xpath("//#{expectation}/@statusCode").first.value
71
- status_message = response.xpath("//#{expectation}/@statusMessage").first.value
72
-
73
- [status_code, status_message, response]
74
- end
75
-
76
69
  private
77
70
 
78
71
  def self.login_request
@@ -101,9 +94,14 @@ module Fishbowl # :nodoc:
101
94
  @connection.write(body)
102
95
  end
103
96
 
104
- def self.read
97
+ def self.get_response(expectation)
105
98
  length = @connection.recv(3).unpack('L>').join('').to_i
106
- Nokogiri::XML.parse(@connection.recv(length))
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]
107
105
  end
108
106
 
109
107
  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
@@ -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'
@@ -1,7 +1,27 @@
1
1
  module Fishbowl::Objects
2
2
  class Account < BaseObject
3
+ attr_reader :name, :accounting_id, :account_type, :balance
4
+
5
+ def self.attributes
6
+ %w{Name AccountingID AccountType Balance}
7
+ end
8
+
9
+ def initialize(account_xml)
10
+ @xml = account_xml
11
+ parse_attributes
12
+ self
13
+ end
14
+
3
15
  def self.get_list
4
- self.new.send_request("GetAccountListRq")
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
5
25
  end
6
26
 
7
27
  def self.get_balance(account)
@@ -13,7 +33,9 @@ module Fishbowl::Objects
13
33
  }
14
34
  end
15
35
 
16
- self.new.send_request(builder, true)
36
+ _, _, response = BaseObject.new.send_request(builder, "GetAccountBalanceRs")
37
+
38
+ response.xpath("//Account/Balance").first.inner_text
17
39
  end
18
40
  end
19
41
  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
@@ -2,13 +2,39 @@ module Fishbowl::Objects
2
2
  class BaseObject
3
3
  attr_accessor :ticket
4
4
 
5
- def send_request(request, fragment = false)
6
- Fishbowl::Connection.send(build_request(request, fragment))
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]
9
+ end
10
+
11
+ protected
12
+
13
+ def self.attributes
14
+ %w{ID}
15
+ end
16
+
17
+ def parse_attributes
18
+ self.class.attributes.each do |field|
19
+ field = field.to_s
20
+
21
+ if field == 'ID'
22
+ instance_var = 'db_id'
23
+ elsif field.match(/^[A-Z]{3,}$/)
24
+ instance_var = field.downcase
25
+ else
26
+ instance_var = field.gsub(/ID$/, 'Id').underscore
27
+ end
28
+
29
+ instance_var = '@' + instance_var
30
+ value = @xml.xpath(field).first.nil? ? nil : @xml.xpath(field).first.inner_text
31
+ instance_variable_set(instance_var, value)
32
+ end
7
33
  end
8
34
 
9
35
  private
10
36
 
11
- def build_request(request, fragment = false)
37
+ def build_request(request)
12
38
  Nokogiri::XML::Builder.new do |xml|
13
39
  xml.FbiXml {
14
40
  if @ticket.nil?
@@ -18,8 +44,11 @@ module Fishbowl::Objects
18
44
  end
19
45
 
20
46
  xml.FbiMsgsRq {
21
- xml << request.doc.xpath("request/*").to_xml if fragment
22
- xml.send(request.to_s) unless fragment
47
+ if request.respond_to?(:to_xml)
48
+ xml << request.doc.xpath("request/*").to_xml
49
+ else
50
+ xml.send(request.to_s)
51
+ end
23
52
  }
24
53
  }
25
54
  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