newgistics 1.0.0
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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +25 -0
- data/.env.sample +2 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.simplecov +4 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +187 -0
- data/Rakefile +6 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/lib/newgistics.rb +68 -0
- data/lib/newgistics/api.rb +26 -0
- data/lib/newgistics/configuration.rb +23 -0
- data/lib/newgistics/customer.rb +20 -0
- data/lib/newgistics/default_logger.rb +11 -0
- data/lib/newgistics/errors.rb +4 -0
- data/lib/newgistics/fee.rb +9 -0
- data/lib/newgistics/inbound_return.rb +29 -0
- data/lib/newgistics/inventory.rb +22 -0
- data/lib/newgistics/item.rb +19 -0
- data/lib/newgistics/order.rb +32 -0
- data/lib/newgistics/product.rb +30 -0
- data/lib/newgistics/query.rb +43 -0
- data/lib/newgistics/requests/cancel_shipment.rb +70 -0
- data/lib/newgistics/requests/post_inbound_return.rb +76 -0
- data/lib/newgistics/requests/post_shipment.rb +121 -0
- data/lib/newgistics/requests/search.rb +21 -0
- data/lib/newgistics/requests/update_shipment_contents.rb +74 -0
- data/lib/newgistics/response_handlers/cancel_shipment.rb +25 -0
- data/lib/newgistics/response_handlers/post_errors.rb +40 -0
- data/lib/newgistics/response_handlers/post_inbound_return.rb +25 -0
- data/lib/newgistics/response_handlers/post_shipment.rb +25 -0
- data/lib/newgistics/response_handlers/search.rb +57 -0
- data/lib/newgistics/response_handlers/update_shipment_contents.rb +25 -0
- data/lib/newgistics/return.rb +40 -0
- data/lib/newgistics/shipment.rb +79 -0
- data/lib/newgistics/shipment_cancellation.rb +24 -0
- data/lib/newgistics/shipment_update.rb +24 -0
- data/lib/newgistics/string_helper.rb +13 -0
- data/lib/newgistics/time_zone.rb +31 -0
- data/lib/newgistics/timestamp.rb +31 -0
- data/lib/newgistics/version.rb +3 -0
- data/lib/newgistics/warehouse.rb +14 -0
- data/lib/newgistics/xml_marshaller.rb +72 -0
- data/newgistics.gemspec +37 -0
- metadata +263 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module Newgistics
|
2
|
+
class Api
|
3
|
+
def get(request, response_handler)
|
4
|
+
response = connection.get(request.path, request.body)
|
5
|
+
response_handler.handle(response)
|
6
|
+
end
|
7
|
+
|
8
|
+
def post(request, response_handler)
|
9
|
+
response = connection.post(request.path, request.body)
|
10
|
+
response_handler.handle(response)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def connection
|
16
|
+
@connection ||= Faraday.new(url: api_base_url) do |faraday|
|
17
|
+
faraday.response :logger, Newgistics.logger, bodies: true
|
18
|
+
faraday.adapter Faraday.default_adapter
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def api_base_url
|
23
|
+
Newgistics.configuration.api_base_url
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Newgistics
|
2
|
+
class Configuration
|
3
|
+
attr_reader :time_zone, :local_time_zone
|
4
|
+
attr_accessor :api_key, :api_base_url
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
self.time_zone = "America/Denver"
|
8
|
+
self.local_time_zone = "UTC"
|
9
|
+
end
|
10
|
+
|
11
|
+
def api_base_url
|
12
|
+
@api_base_url ||= "https://apistaging.newgisticsfulfillment.com"
|
13
|
+
end
|
14
|
+
|
15
|
+
def time_zone=(name)
|
16
|
+
@time_zone = TimeZone.new(name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def local_time_zone=(name)
|
20
|
+
@local_time_zone = TimeZone.new(name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Newgistics
|
2
|
+
class Customer
|
3
|
+
include Virtus.model
|
4
|
+
|
5
|
+
attribute :company, String
|
6
|
+
attribute :first_name, String
|
7
|
+
attribute :last_name, String
|
8
|
+
attribute :email, String
|
9
|
+
|
10
|
+
attribute :address1, String
|
11
|
+
attribute :address2, String
|
12
|
+
attribute :city, String
|
13
|
+
attribute :state, String
|
14
|
+
attribute :country, String
|
15
|
+
attribute :phone, String
|
16
|
+
attribute :fax, String
|
17
|
+
attribute :zip, String
|
18
|
+
attribute :is_residential, Boolean
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Newgistics
|
2
|
+
class InboundReturn
|
3
|
+
include Virtus.model
|
4
|
+
|
5
|
+
attribute :id, String
|
6
|
+
attribute :shipment_id, String
|
7
|
+
attribute :order_id, String
|
8
|
+
attribute :rma, String
|
9
|
+
attribute :comments, String
|
10
|
+
attribute :items, Array[Item]
|
11
|
+
|
12
|
+
attribute :errors, Array[String], default: []
|
13
|
+
attribute :warnings, Array[String], default: []
|
14
|
+
|
15
|
+
def self.where(conditions)
|
16
|
+
Query.build(
|
17
|
+
endpoint: '/inbound_returns.aspx',
|
18
|
+
element_selector: 'InboundReturns InboundReturn',
|
19
|
+
model_class: self
|
20
|
+
).where(conditions)
|
21
|
+
end
|
22
|
+
|
23
|
+
def save
|
24
|
+
Requests::PostInboundReturn.new(self).perform
|
25
|
+
|
26
|
+
errors.empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Newgistics
|
2
|
+
class Inventory
|
3
|
+
include Virtus.model
|
4
|
+
|
5
|
+
attribute :manifest_id, String
|
6
|
+
attribute :manifest_po, String
|
7
|
+
attribute :shipment_id, String
|
8
|
+
attribute :order_id, String
|
9
|
+
attribute :timestamp, Timestamp
|
10
|
+
attribute :sku, String
|
11
|
+
attribute :quantity, Integer
|
12
|
+
attribute :notes, String
|
13
|
+
|
14
|
+
def self.where(conditions)
|
15
|
+
Query.build(
|
16
|
+
endpoint: '/inventory_details.aspx',
|
17
|
+
element_selector: 'inventories inventory',
|
18
|
+
model_class: self
|
19
|
+
).where(conditions)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Newgistics
|
2
|
+
class Item
|
3
|
+
include Virtus.model
|
4
|
+
|
5
|
+
attribute :id, String
|
6
|
+
|
7
|
+
attribute :sku, String
|
8
|
+
attribute :qty, Integer
|
9
|
+
attribute :is_gift_wrapped, Boolean
|
10
|
+
attribute :custom_fields, Hash
|
11
|
+
|
12
|
+
attribute :qty_returned, Integer
|
13
|
+
attribute :return_reason, String
|
14
|
+
attribute :qty_returned_to_stock, Integer
|
15
|
+
attribute :return_timestamp, Timestamp
|
16
|
+
|
17
|
+
attribute :reason, String
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Newgistics
|
2
|
+
class Order
|
3
|
+
include Virtus.model
|
4
|
+
|
5
|
+
attribute :id, String
|
6
|
+
attribute :warehouse_id, String
|
7
|
+
attribute :customer, Customer
|
8
|
+
attribute :drop_ship_info, Hash
|
9
|
+
attribute :order_date, Date
|
10
|
+
attribute :ship_method, String
|
11
|
+
attribute :info_line, String
|
12
|
+
attribute :requires_signature, Boolean
|
13
|
+
attribute :is_insured, Boolean
|
14
|
+
attribute :insured_value, Float
|
15
|
+
attribute :add_gift_wrap, Boolean
|
16
|
+
attribute :gift_message, String
|
17
|
+
attribute :hold_for_all_inventory, Boolean
|
18
|
+
attribute :custom_fields, Hash
|
19
|
+
attribute :allow_duplicate, Boolean
|
20
|
+
attribute :items, Array[Item]
|
21
|
+
|
22
|
+
attribute :errors, Array[String], default: []
|
23
|
+
attribute :warnings, Array[String], default: []
|
24
|
+
attribute :shipment_id, String
|
25
|
+
|
26
|
+
def save
|
27
|
+
Requests::PostShipment.new(self).perform
|
28
|
+
|
29
|
+
errors.empty?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Newgistics
|
2
|
+
class Product
|
3
|
+
include Virtus.model
|
4
|
+
|
5
|
+
attribute :id, String
|
6
|
+
attribute :sku, String
|
7
|
+
|
8
|
+
attribute :putaway_quantity, Integer
|
9
|
+
attribute :quarantine_quantity, Integer
|
10
|
+
attribute :damaged_quantity, Integer
|
11
|
+
attribute :expired_quantity, Integer
|
12
|
+
attribute :recalled_quantity, Integer
|
13
|
+
attribute :current_quantity, Integer
|
14
|
+
attribute :kitting_quantity, Integer
|
15
|
+
attribute :pending_quantity, Integer
|
16
|
+
attribute :available_quantity, Integer
|
17
|
+
|
18
|
+
def self.all
|
19
|
+
where({}).all
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.where(conditions)
|
23
|
+
Query.build(
|
24
|
+
endpoint: '/inventory.aspx',
|
25
|
+
element_selector: 'products product',
|
26
|
+
model_class: self
|
27
|
+
).where(conditions)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Newgistics
|
2
|
+
class Query
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :request, :response_handler, :conditions
|
6
|
+
|
7
|
+
def initialize(request, response_handler)
|
8
|
+
@request = request
|
9
|
+
@response_handler = response_handler
|
10
|
+
@conditions = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.build(endpoint:, element_selector:, model_class:)
|
14
|
+
request = Requests::Search.new(endpoint)
|
15
|
+
response_handler = ResponseHandlers::Search.new(
|
16
|
+
element_selector: element_selector,
|
17
|
+
model_class: model_class
|
18
|
+
)
|
19
|
+
|
20
|
+
new(request, response_handler)
|
21
|
+
end
|
22
|
+
|
23
|
+
def where(conditions)
|
24
|
+
@conditions.merge!(conditions)
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def all
|
29
|
+
results.to_a
|
30
|
+
end
|
31
|
+
|
32
|
+
def each
|
33
|
+
results.each { |result| yield(result) }
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def results
|
39
|
+
request.params = conditions
|
40
|
+
Newgistics.api.get(request, response_handler)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Newgistics
|
2
|
+
module Requests
|
3
|
+
class CancelShipment
|
4
|
+
attr_reader :shipment_cancellation, :response_handler
|
5
|
+
|
6
|
+
def initialize(shipment_cancellation, response_handler: nil)
|
7
|
+
@shipment_cancellation = shipment_cancellation
|
8
|
+
@response_handler = response_handler || default_response_handler
|
9
|
+
end
|
10
|
+
|
11
|
+
def path
|
12
|
+
"/cancel_shipment.aspx?#{URI.encode_www_form(mandatory_params.merge(optional_params))}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def body
|
16
|
+
xml_builder.to_xml
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform
|
20
|
+
Newgistics.api.post(self, response_handler)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def default_response_handler
|
26
|
+
ResponseHandlers::CancelShipment.new(shipment_cancellation)
|
27
|
+
end
|
28
|
+
|
29
|
+
def xml_builder
|
30
|
+
Nokogiri::XML::Builder.new do |xml|
|
31
|
+
shipment_cancellation_xml(xml)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def shipment_cancellation_xml(xml)
|
36
|
+
xml.cancelShipment(mandatory_params) do
|
37
|
+
cancel_if_in_process(xml)
|
38
|
+
cancel_if_backorder(xml)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def api_key
|
43
|
+
Newgistics.configuration.api_key
|
44
|
+
end
|
45
|
+
|
46
|
+
def mandatory_params
|
47
|
+
{
|
48
|
+
apiKey: api_key,
|
49
|
+
shipmentID: shipment_cancellation.shipment_id,
|
50
|
+
orderID: shipment_cancellation.order_id
|
51
|
+
}.reject { |_k, v| v.nil? || v.empty? }
|
52
|
+
end
|
53
|
+
|
54
|
+
def cancel_if_in_process(xml)
|
55
|
+
xml.cancelIfInProcess shipment_cancellation.cancel_if_in_process
|
56
|
+
end
|
57
|
+
|
58
|
+
def cancel_if_backorder(xml)
|
59
|
+
xml.cancelIfBackorder shipment_cancellation.cancel_if_backorder
|
60
|
+
end
|
61
|
+
|
62
|
+
def optional_params
|
63
|
+
{
|
64
|
+
cancelIfInProcess: shipment_cancellation.cancel_if_in_process,
|
65
|
+
cancelIfBackorder: shipment_cancellation.cancel_if_backorder
|
66
|
+
}.reject { |_k, v| v.nil? }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Newgistics
|
2
|
+
module Requests
|
3
|
+
class PostInboundReturn
|
4
|
+
attr_reader :inbound_return, :response_handler
|
5
|
+
|
6
|
+
def initialize(inbound_return, response_handler: nil)
|
7
|
+
@inbound_return = inbound_return
|
8
|
+
@response_handler = response_handler || default_response_handler
|
9
|
+
end
|
10
|
+
|
11
|
+
def path
|
12
|
+
'/post_inbound_returns.aspx'
|
13
|
+
end
|
14
|
+
|
15
|
+
def body
|
16
|
+
xml_builder.to_xml
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform
|
20
|
+
Newgistics.api.post(self, response_handler)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def default_response_handler
|
26
|
+
ResponseHandlers::PostInboundReturn.new(inbound_return)
|
27
|
+
end
|
28
|
+
|
29
|
+
def xml_builder
|
30
|
+
Nokogiri::XML::Builder.new do |xml|
|
31
|
+
returns_xml(xml)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def returns_xml(xml)
|
36
|
+
xml.Returns(apiKey: api_key) do
|
37
|
+
return_xml(inbound_return, xml)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def api_key
|
42
|
+
Newgistics.configuration.api_key
|
43
|
+
end
|
44
|
+
|
45
|
+
def return_xml(inbound_return, xml)
|
46
|
+
xml.Return(return_attributes(inbound_return)) do
|
47
|
+
xml.RMA inbound_return.rma
|
48
|
+
xml.Comments inbound_return.comments
|
49
|
+
|
50
|
+
items_xml(inbound_return.items, xml)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def return_attributes(inbound_return)
|
55
|
+
{
|
56
|
+
id: inbound_return.shipment_id,
|
57
|
+
orderID: inbound_return.order_id
|
58
|
+
}.reject { |_k, v| v.nil? || v.empty? }
|
59
|
+
end
|
60
|
+
|
61
|
+
def items_xml(items, xml)
|
62
|
+
xml.Items do
|
63
|
+
items.each { |item| item_xml(item, xml) }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def item_xml(item, xml)
|
68
|
+
xml.Item do
|
69
|
+
xml.SKU item.sku
|
70
|
+
xml.Qty item.qty
|
71
|
+
xml.Reason item.reason
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Newgistics
|
2
|
+
module Requests
|
3
|
+
class PostShipment
|
4
|
+
attr_reader :order, :response_handler
|
5
|
+
|
6
|
+
def initialize(order, response_handler: nil)
|
7
|
+
@order = order
|
8
|
+
@response_handler = response_handler || default_response_handler
|
9
|
+
end
|
10
|
+
|
11
|
+
def path
|
12
|
+
'/post_shipments.aspx'
|
13
|
+
end
|
14
|
+
|
15
|
+
def body
|
16
|
+
xml_builder.to_xml
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform
|
20
|
+
Newgistics.api.post(self, response_handler)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def default_response_handler
|
26
|
+
ResponseHandlers::PostShipment.new(order)
|
27
|
+
end
|
28
|
+
|
29
|
+
def xml_builder
|
30
|
+
Nokogiri::XML::Builder.new do |xml|
|
31
|
+
orders_xml(xml)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def orders_xml(xml)
|
36
|
+
xml.Orders(apiKey: api_key) do
|
37
|
+
order_xml(order, xml)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def api_key
|
42
|
+
Newgistics.configuration.api_key
|
43
|
+
end
|
44
|
+
|
45
|
+
def order_xml(order, xml)
|
46
|
+
xml.Order(orderID: order.id) do
|
47
|
+
xml.Warehouse(warehouseid: order.warehouse_id)
|
48
|
+
xml.ShipMethod order.ship_method
|
49
|
+
xml.InfoLine order.info_line
|
50
|
+
xml.RequiresSignature order.requires_signature
|
51
|
+
xml.IsInsured order.is_insured
|
52
|
+
xml.InsuredValue order.insured_value
|
53
|
+
xml.AddGiftWrap order.add_gift_wrap
|
54
|
+
xml.GiftMessage order.gift_message
|
55
|
+
xml.HoldForAllInventory order.hold_for_all_inventory
|
56
|
+
xml.AllowDuplicate order.allow_duplicate
|
57
|
+
|
58
|
+
order_date_xml(order, xml)
|
59
|
+
customer_xml(order.customer, xml)
|
60
|
+
drop_ship_info_xml(order, xml)
|
61
|
+
custom_fields_xml(order, xml)
|
62
|
+
items_xml(order.items, xml)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def order_date_xml(order, xml)
|
67
|
+
unless order.order_date.nil?
|
68
|
+
xml.OrderDate order.order_date.strftime('%m/%d/%Y')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def drop_ship_info_xml(object, xml)
|
73
|
+
xml.DropShipInfo do
|
74
|
+
object.drop_ship_info.each do |key, value|
|
75
|
+
xml.send StringHelper.camelize(key), value
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def custom_fields_xml(object, xml)
|
81
|
+
xml.CustomFields do
|
82
|
+
object.custom_fields.each do |key, value|
|
83
|
+
xml.send StringHelper.camelize(key), value
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def items_xml(items, xml)
|
89
|
+
xml.Items do
|
90
|
+
items.each { |item| item_xml(item, xml) }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def item_xml(item, xml)
|
95
|
+
xml.Item do
|
96
|
+
xml.SKU item.sku
|
97
|
+
xml.Qty item.qty
|
98
|
+
xml.IsGiftWrapped item.is_gift_wrapped
|
99
|
+
custom_fields_xml(item, xml)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def customer_xml(customer, xml)
|
104
|
+
xml.CustomerInfo do
|
105
|
+
xml.Company customer.company
|
106
|
+
xml.FirstName customer.first_name
|
107
|
+
xml.LastName customer.last_name
|
108
|
+
xml.Address1 customer.address1
|
109
|
+
xml.Address2 customer.address2
|
110
|
+
xml.City customer.city
|
111
|
+
xml.State customer.state
|
112
|
+
xml.Zip customer.zip
|
113
|
+
xml.Country customer.country
|
114
|
+
xml.Email customer.email
|
115
|
+
xml.Phone customer.phone
|
116
|
+
xml.IsResidential customer.is_residential
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|