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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +25 -0
  3. data/.env.sample +2 -0
  4. data/.gitignore +15 -0
  5. data/.rspec +2 -0
  6. data/.ruby-version +1 -0
  7. data/.simplecov +4 -0
  8. data/.travis.yml +5 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/Gemfile +6 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +187 -0
  13. data/Rakefile +6 -0
  14. data/bin/console +16 -0
  15. data/bin/setup +8 -0
  16. data/lib/newgistics.rb +68 -0
  17. data/lib/newgistics/api.rb +26 -0
  18. data/lib/newgistics/configuration.rb +23 -0
  19. data/lib/newgistics/customer.rb +20 -0
  20. data/lib/newgistics/default_logger.rb +11 -0
  21. data/lib/newgistics/errors.rb +4 -0
  22. data/lib/newgistics/fee.rb +9 -0
  23. data/lib/newgistics/inbound_return.rb +29 -0
  24. data/lib/newgistics/inventory.rb +22 -0
  25. data/lib/newgistics/item.rb +19 -0
  26. data/lib/newgistics/order.rb +32 -0
  27. data/lib/newgistics/product.rb +30 -0
  28. data/lib/newgistics/query.rb +43 -0
  29. data/lib/newgistics/requests/cancel_shipment.rb +70 -0
  30. data/lib/newgistics/requests/post_inbound_return.rb +76 -0
  31. data/lib/newgistics/requests/post_shipment.rb +121 -0
  32. data/lib/newgistics/requests/search.rb +21 -0
  33. data/lib/newgistics/requests/update_shipment_contents.rb +74 -0
  34. data/lib/newgistics/response_handlers/cancel_shipment.rb +25 -0
  35. data/lib/newgistics/response_handlers/post_errors.rb +40 -0
  36. data/lib/newgistics/response_handlers/post_inbound_return.rb +25 -0
  37. data/lib/newgistics/response_handlers/post_shipment.rb +25 -0
  38. data/lib/newgistics/response_handlers/search.rb +57 -0
  39. data/lib/newgistics/response_handlers/update_shipment_contents.rb +25 -0
  40. data/lib/newgistics/return.rb +40 -0
  41. data/lib/newgistics/shipment.rb +79 -0
  42. data/lib/newgistics/shipment_cancellation.rb +24 -0
  43. data/lib/newgistics/shipment_update.rb +24 -0
  44. data/lib/newgistics/string_helper.rb +13 -0
  45. data/lib/newgistics/time_zone.rb +31 -0
  46. data/lib/newgistics/timestamp.rb +31 -0
  47. data/lib/newgistics/version.rb +3 -0
  48. data/lib/newgistics/warehouse.rb +14 -0
  49. data/lib/newgistics/xml_marshaller.rb +72 -0
  50. data/newgistics.gemspec +37 -0
  51. metadata +263 -0
@@ -0,0 +1,21 @@
1
+ module Newgistics
2
+ module Requests
3
+ class Search
4
+ attr_reader :path, :params
5
+
6
+ def initialize(path)
7
+ @path = path
8
+ end
9
+
10
+ def params=(params)
11
+ @params = params.merge(key: Newgistics.configuration.api_key)
12
+ end
13
+
14
+ def body
15
+ params.
16
+ map { |k,v| [StringHelper.camelize(k, upcase_first: false), v] }.
17
+ to_h
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,74 @@
1
+ module Newgistics
2
+ module Requests
3
+ class UpdateShipmentContents
4
+ attr_reader :shipment_update, :response_handler
5
+
6
+ def initialize(shipment_update, response_handler: nil)
7
+ @shipment_update = shipment_update
8
+ @response_handler = response_handler || default_response_handler
9
+ end
10
+
11
+ def path
12
+ '/update_shipment_contents.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::UpdateShipmentContents.new(shipment_update)
27
+ end
28
+
29
+ def xml_builder
30
+ Nokogiri::XML::Builder.new do |xml|
31
+ shipment_update_xml(xml)
32
+ end
33
+ end
34
+
35
+ def shipment_update_xml(xml)
36
+ xml.Shipment(shipment_update_attributes) do
37
+ add_items_xml(shipment_update.add_items, xml)
38
+ remove_items_xml(shipment_update.remove_items, xml)
39
+ end
40
+ end
41
+
42
+ def api_key
43
+ Newgistics.configuration.api_key
44
+ end
45
+
46
+ def shipment_update_attributes
47
+ {
48
+ apiKey: api_key,
49
+ id: shipment_update.id,
50
+ orderID: shipment_update.order_id
51
+ }.reject { |_k, v| v.nil? || v.empty? }
52
+ end
53
+
54
+ def add_items_xml(items, xml)
55
+ xml.AddItems do
56
+ items.each { |item| item_xml(item, xml) }
57
+ end
58
+ end
59
+
60
+ def remove_items_xml(items, xml)
61
+ xml.RemoveItems do
62
+ items.each { |item| item_xml(item, xml) }
63
+ end
64
+ end
65
+
66
+ def item_xml(item, xml)
67
+ xml.Item do
68
+ xml.SKU item.sku
69
+ xml.Qty item.qty
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,25 @@
1
+ module Newgistics
2
+ module ResponseHandlers
3
+ class CancelShipment
4
+ attr_reader :shipment
5
+
6
+ def initialize(shipment)
7
+ @shipment = shipment
8
+ end
9
+
10
+ def handle(response)
11
+ PostErrors.new(shipment).handle(response)
12
+ if shipment.errors.empty?
13
+ handle_successful_response(response)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def handle_successful_response(response)
20
+ xml = Nokogiri::XML(response.body)
21
+ shipment.success = xml.at_css('success').text
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,40 @@
1
+ module Newgistics
2
+ module ResponseHandlers
3
+ class PostErrors
4
+ attr_reader :model
5
+
6
+ def initialize(model)
7
+ @model = model
8
+ end
9
+
10
+ def handle(response)
11
+ if response.success?
12
+ handle_successful_response(response)
13
+ else
14
+ handle_failed_response(response)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def handle_successful_response(response)
21
+ xml = Nokogiri::XML(response.body)
22
+ model.errors = error_nodes(xml).map(&:text)
23
+ model.warnings = warning_nodes(xml).map(&:text)
24
+ end
25
+
26
+ def handle_failed_response(response)
27
+ message = "API Error: #{response.status}"
28
+ model.errors << message
29
+ end
30
+
31
+ def error_nodes(xml)
32
+ xml.css('errors error') + xml.css('Errors Error')
33
+ end
34
+
35
+ def warning_nodes(xml)
36
+ xml.css('warnings warning') + xml.css('Warnings warning')
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,25 @@
1
+ module Newgistics
2
+ module ResponseHandlers
3
+ class PostInboundReturn
4
+ attr_reader :inbound_return
5
+
6
+ def initialize(inbound_return)
7
+ @inbound_return = inbound_return
8
+ end
9
+
10
+ def handle(response)
11
+ PostErrors.new(inbound_return).handle(response)
12
+ if inbound_return.errors.empty?
13
+ handle_successful_response(response)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def handle_successful_response(response)
20
+ xml = Nokogiri::XML(response.body)
21
+ inbound_return.id = xml.css('Return').first['ID']
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module Newgistics
2
+ module ResponseHandlers
3
+ class PostShipment
4
+ attr_reader :order
5
+
6
+ def initialize(order)
7
+ @order = order
8
+ end
9
+
10
+ def handle(response)
11
+ PostErrors.new(order).handle(response)
12
+ if order.errors.empty?
13
+ handle_successful_response(response)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def handle_successful_response(response)
20
+ xml = Nokogiri::XML(response.body)
21
+ order.shipment_id = xml.css('shipment').first['id']
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,57 @@
1
+ module Newgistics
2
+ module ResponseHandlers
3
+ class Search
4
+ attr_reader :element_selector, :model_class
5
+
6
+ def initialize(element_selector:, model_class:)
7
+ @element_selector = element_selector
8
+ @model_class = model_class
9
+ end
10
+
11
+ def handle(response)
12
+ if response.success?
13
+ handle_successful_response(response)
14
+ else
15
+ handle_failed_response(response)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def handle_successful_response(response)
22
+ xml = Nokogiri::XML(response.body)
23
+ errors = error_nodes(xml).map(&:text)
24
+
25
+ if errors.empty?
26
+ build_models(xml)
27
+ else
28
+ raise_error(errors.join(', '))
29
+ end
30
+ end
31
+
32
+ def error_nodes(xml)
33
+ xml.css('errors error') + xml.css('Errors Error')
34
+ end
35
+
36
+ def build_models(xml)
37
+ xml.css(element_selector).map do |model_xml|
38
+ build_model(model_xml)
39
+ end
40
+ end
41
+
42
+ def build_model(model_xml)
43
+ model_class.new.tap do |model|
44
+ XmlMarshaller.new.assign_attributes(model, model_xml)
45
+ end
46
+ end
47
+
48
+ def handle_failed_response(response)
49
+ raise_error "API Error: #{response.status}"
50
+ end
51
+
52
+ def raise_error(message)
53
+ raise QueryError.new(message)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,25 @@
1
+ module Newgistics
2
+ module ResponseHandlers
3
+ class UpdateShipmentContents
4
+ attr_reader :shipment
5
+
6
+ def initialize(shipment)
7
+ @shipment = shipment
8
+ end
9
+
10
+ def handle(response)
11
+ PostErrors.new(shipment).handle(response)
12
+ if shipment.errors.empty?
13
+ handle_successful_response(response)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def handle_successful_response(response)
20
+ xml = Nokogiri::XML(response.body)
21
+ shipment.success = xml.at_css('success').text
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,40 @@
1
+ module Newgistics
2
+ class Return
3
+ include Virtus.model
4
+
5
+ attribute :warehouse_id, String
6
+ attribute :shipment_id, String
7
+ attribute :order_id, String
8
+
9
+ attribute :status, String
10
+ attribute :name, String
11
+ attribute :company, String
12
+ attribute :address1, String
13
+ attribute :address2, String
14
+ attribute :city, String
15
+ attribute :state, String
16
+ attribute :postal_code, String
17
+ attribute :country, String
18
+ attribute :email, String
19
+ attribute :phone, String
20
+ attribute :carrier, String
21
+ attribute :tracking_number, String
22
+ attribute :postage_due, Float
23
+ attribute :rma_present, Boolean
24
+ attribute :rma_number, String
25
+ attribute :reason, String
26
+ attribute :condition, String
27
+ attribute :notes, String
28
+ attribute :is_archived, Boolean
29
+ attribute :timestamp, Timestamp
30
+ attribute :items, Array[Item]
31
+
32
+ def self.where(conditions)
33
+ Query.build(
34
+ endpoint: '/returns.aspx',
35
+ element_selector: 'Returns Return',
36
+ model_class: self
37
+ ).where(conditions)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,79 @@
1
+ module Newgistics
2
+ class Shipment
3
+ include Virtus.model
4
+
5
+ attribute :id, String
6
+ attribute :client_name, String
7
+ attribute :order_id, String
8
+ attribute :purchase_order, String
9
+ attribute :name, String
10
+ attribute :last_name, String
11
+ attribute :first_name, String
12
+ attribute :company, String
13
+ attribute :address1, String
14
+ attribute :address2, String
15
+ attribute :city, String
16
+ attribute :state, String
17
+ attribute :postal_code, String
18
+ attribute :country, String
19
+ attribute :email, String
20
+ attribute :phone, String
21
+ attribute :order_timestamp, Timestamp
22
+ attribute :received_timestamp, Timestamp
23
+ attribute :shipment_status, String
24
+ attribute :order_type, String
25
+ attribute :shipped_date, Timestamp
26
+ attribute :expected_delivery_date, Timestamp
27
+ attribute :delivered_timestamp, Timestamp
28
+ attribute :warehouse, Warehouse
29
+ attribute :ship_method, String
30
+ attribute :ship_method_code, String
31
+ attribute :tracking, String
32
+ attribute :tracking_url, String
33
+ attribute :items, Array[Item]
34
+ attribute :custom_fields, Hash
35
+ attribute :weight, Float
36
+ attribute :postage, Float
37
+ attribute :fees, Array[Fee]
38
+
39
+ def backordered?
40
+ shipment_status == 'BACKORDER'
41
+ end
42
+
43
+ def canceled?
44
+ shipment_status == 'CANCELED'
45
+ end
46
+
47
+ def on_hold?
48
+ %w(ONHOLD BADSKUHOLD BADADDRESS CNFHOLD INVHOLD).include? shipment_status
49
+ end
50
+
51
+ def received?
52
+ shipment_status == 'RECEIVED'
53
+ end
54
+
55
+ def printed?
56
+ shipment_status == 'PRINTED'
57
+ end
58
+
59
+ def shipped?
60
+ shipment_status == 'SHIPPED'
61
+ end
62
+
63
+ def returned?
64
+ shipment_status == 'RETURNED'
65
+ end
66
+
67
+ def verified?
68
+ shipment_status == 'VERIFIED'
69
+ end
70
+
71
+ def self.where(conditions)
72
+ Query.build(
73
+ endpoint: '/shipments.aspx',
74
+ element_selector: 'Shipments Shipment',
75
+ model_class: self
76
+ ).where(conditions)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,24 @@
1
+ module Newgistics
2
+ class ShipmentCancellation
3
+ include Virtus.model
4
+
5
+ attribute :shipment_id, String
6
+ attribute :order_id, String
7
+ attribute :cancel_if_in_process, Boolean
8
+ attribute :cancel_if_backorder, Boolean
9
+ attribute :success, Boolean
10
+
11
+ attribute :errors, Array[String], default: []
12
+ attribute :warnings, Array[String], default: []
13
+
14
+ def success?
15
+ !!success
16
+ end
17
+
18
+ def save
19
+ Requests::CancelShipment.new(self).perform
20
+
21
+ errors.empty? && success?
22
+ end
23
+ end
24
+ end