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.
- 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
|