fishbowl 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +9 -4
- data/Gemfile +10 -1
- data/Guardfile +13 -0
- data/lib/fishbowl.rb +13 -15
- data/lib/fishbowl/ext.rb +15 -0
- data/lib/fishbowl/objects.rb +5 -0
- data/lib/fishbowl/objects/account.rb +24 -2
- data/lib/fishbowl/objects/address.rb +86 -0
- data/lib/fishbowl/objects/base_object.rb +34 -5
- data/lib/fishbowl/objects/carrier.rb +15 -0
- data/lib/fishbowl/objects/carton.rb +54 -0
- data/lib/fishbowl/objects/uom.rb +47 -0
- data/lib/fishbowl/objects/user.rb +15 -0
- data/lib/fishbowl/requests.rb +6 -0
- data/lib/fishbowl/requests/add_inventory.rb +34 -0
- data/lib/fishbowl/requests/add_sales_order_item.rb +42 -0
- data/lib/fishbowl/requests/adjust_inventory.rb +28 -0
- data/lib/fishbowl/requests/get_carrier_list.rb +12 -0
- data/lib/fishbowl/version.rb +1 -1
- data/spec/examples/account.xml +6 -0
- data/spec/examples/address.xml +30 -0
- data/spec/examples/carrier.xml +3 -0
- data/spec/examples/carton.xml +93 -0
- data/spec/examples/contact_information.xml +5 -0
- data/spec/examples/contacts.xml +7 -0
- data/spec/examples/credit_card.xml +10 -0
- data/spec/examples/customer.xml +54 -0
- data/spec/examples/location.xml +14 -0
- data/spec/examples/location_group.xml +5 -0
- data/spec/examples/location_group_string.xml +1 -0
- data/spec/examples/order_history.xml +8 -0
- data/spec/examples/part.xml +105 -0
- data/spec/examples/payment.xml +6 -0
- data/spec/examples/pick.xml +265 -0
- data/spec/examples/pick_item.xml +236 -0
- data/spec/examples/product.xml +159 -0
- data/spec/examples/purchase_order.xml +53 -0
- data/spec/examples/receipt.xml +146 -0
- data/spec/examples/report.xml +10 -0
- data/spec/examples/report_tree.xml +7 -0
- data/spec/examples/sales_order.xml +47 -0
- data/spec/examples/sales_order_item.xml +32 -0
- data/spec/examples/shipping.xml +127 -0
- data/spec/examples/tag.xml +28 -0
- data/spec/examples/tax_rate.xml +10 -0
- data/spec/examples/tracking.xml +14 -0
- data/spec/examples/tracking_item.xml +12 -0
- data/spec/examples/transfer_order.xml +257 -0
- data/spec/examples/transfer_order_item.xml +147 -0
- data/spec/examples/uom.xml +26 -0
- data/spec/examples/uom_conversion.xml +8 -0
- data/spec/examples/user.xml +8 -0
- data/spec/examples/vendor.xml +19 -0
- data/spec/examples/vendor_part_number.xml +3 -0
- data/spec/examples/work_order.xml +228 -0
- data/spec/examples/work_order_item.xml +172 -0
- data/spec/objects/account_spec.rb +53 -6
- data/spec/objects/address_information_spec.rb +18 -0
- data/spec/objects/address_spec.rb +36 -0
- data/spec/objects/base_object_spec.rb +67 -23
- data/spec/objects/carrier_spec.rb +15 -0
- data/spec/objects/carton_spec.rb +23 -0
- data/spec/objects/country_spec.rb +16 -0
- data/spec/objects/shipping_item_spec.rb +21 -0
- data/spec/objects/state_spec.rb +17 -0
- data/spec/objects/uom_conversion_spec.rb +20 -0
- data/spec/objects/uom_spec.rb +20 -0
- data/spec/objects/user_spec.rb +20 -0
- data/spec/requests/add_inventory_spec.rb +79 -0
- data/spec/requests/add_sales_order_item_spec.rb +85 -0
- data/spec/requests/adjust_inventory_spec.rb +62 -0
- data/spec/requests/get_carrier_list_spec.rb +54 -0
- data/spec/spec_helper.rb +41 -11
- data/spec/support/examples_loader.rb +5 -0
- data/spec/support/response_mocks.rb +27 -0
- metadata +122 -6
- data/spec/support/fake_login.rb +0 -15
data/.travis.yml
CHANGED
@@ -1,19 +1,24 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 1.9.3
|
4
|
-
- jruby-19mode
|
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
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/lib/fishbowl.rb
CHANGED
@@ -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,
|
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.
|
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
|
data/lib/fishbowl/ext.rb
ADDED
@@ -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
|
data/lib/fishbowl/objects.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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,
|
6
|
-
Fishbowl::Connection.send(build_request(request,
|
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
|
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
|
-
|
22
|
-
|
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,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
|